From 91d5f83df44bb85f807e36c5199e8b0b428d1967 Mon Sep 17 00:00:00 2001 From: Matvey Melishev Date: Wed, 15 May 2024 22:22:20 +0200 Subject: [PATCH 1/3] fix: main process in desktop --- apps/desktop/forge.config.ts | 2 +- apps/desktop/package.json | 2 +- apps/desktop/src/{main/tray2.ts => main.ts} | 4 ++ apps/desktop/src/main/index.ts | 10 --- apps/desktop/src/main/tray.ts | 67 --------------------- 5 files changed, 6 insertions(+), 79 deletions(-) rename apps/desktop/src/{main/tray2.ts => main.ts} (87%) delete mode 100644 apps/desktop/src/main/index.ts delete mode 100644 apps/desktop/src/main/tray.ts diff --git a/apps/desktop/forge.config.ts b/apps/desktop/forge.config.ts index 8e6825d..1969ec8 100644 --- a/apps/desktop/forge.config.ts +++ b/apps/desktop/forge.config.ts @@ -34,7 +34,7 @@ const config: ForgeConfig = { build: [ { // `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`. - entry: 'src/main/index.ts', + entry: 'src/main.ts', config: 'vite.main.config.ts', }, { diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 713f6e4..98cfe8e 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -2,7 +2,7 @@ "name": "desktop", "private": true, "version": "0.0.0", - "main": ".vite/build/index.js", + "main": ".vite/build/main.js", "scripts": { "dev": "electron-forge start", "package": "electron-forge package", diff --git a/apps/desktop/src/main/tray2.ts b/apps/desktop/src/main.ts similarity index 87% rename from apps/desktop/src/main/tray2.ts rename to apps/desktop/src/main.ts index 70a98ec..5ac2189 100644 --- a/apps/desktop/src/main/tray2.ts +++ b/apps/desktop/src/main.ts @@ -20,3 +20,7 @@ export function initSystemTray() { toggleMenuWindow() }) } + +app.on('window-all-closed', (e) => e.preventDefault()) + +app.on('ready', createTray) diff --git a/apps/desktop/src/main/index.ts b/apps/desktop/src/main/index.ts deleted file mode 100644 index ed88aa4..0000000 --- a/apps/desktop/src/main/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { app, systemPreferences } from 'electron' -// import { initSystemTray } from './tray' -import { initSystemTray } from './tray2' - -systemPreferences.askForMediaAccess('microphone') -systemPreferences.askForMediaAccess('camera') - -app.on('window-all-closed', (e) => e.preventDefault()) - -app.on('ready', initSystemTray) diff --git a/apps/desktop/src/main/tray.ts b/apps/desktop/src/main/tray.ts deleted file mode 100644 index aa5cc55..0000000 --- a/apps/desktop/src/main/tray.ts +++ /dev/null @@ -1,67 +0,0 @@ -import path from 'node:path' -import { Menu, Tray } from 'electron' - -import { createWindow } from '../picture/main' - -export function initSystemTray() { - /** - * To make sure your icon isn't grainy on retina monitors, be sure your @2x image is 144dpi. - * If you are bundling your application (e.g., with webpack for development), be sure that the file names are not being mangled or hashed. The filename needs to end in Template, and the @2x image needs to have the same filename as the standard image, or MacOS will not magically invert your image's colors or use the high density image. - * 16x16 (72dpi) and 32x32@2x (144dpi) work well for most icons. - */ - const tray = new Tray(path.resolve('./src/assets/LogoTemplate@2x.png')) - - const contacts = [ - { - label: 'Raphael', - icon: path.resolve('./src/assets/Raphael.png'), - }, - { - label: 'Leonardo', - icon: path.resolve('./src/assets/UserPlusTemplate@2x.png'), - }, - { - label: 'Donatello', - icon: path.resolve('./src/assets/UserPlusTemplate@2x.png'), - }, - { - label: 'Michelangelo', - icon: path.resolve('./src/assets/UserPlusTemplate@2x.png'), - }, - { - label: 'Splinter', - icon: path.resolve('./src/assets/UserPlusTemplate@2x.png'), - }, - ] - // const contacts1 = [ - // { - // label: 'Contacts', - // type: 'submenu', - // submenu: contacts, - // }, - // ] - - const contacts2 = [{ label: 'Contacts', enabled: false }, ...contacts] - - const menu = Menu.buildFromTemplate([ - ...contacts2, - { type: 'separator' }, - { - label: 'Add New Contact', - icon: path.resolve('./src/assets/UserPlusTemplate@2x.png'), - }, - { type: 'separator' }, - { - label: 'Manual call', - icon: path.resolve('./src/assets/ArrowUpDownTemplate@2x.png'), - }, - { type: 'separator' }, - { label: 'Open Test Window', click: createWindow }, - { type: 'separator' }, - { role: 'about' }, - { type: 'separator' }, - { role: 'quit' }, - ]) - - tray.setContextMenu(menu) -} From 33644c950564bda2690872b18bfd816e19af901d Mon Sep 17 00:00:00 2001 From: Matvey Melishev Date: Sun, 26 May 2024 21:35:02 +0200 Subject: [PATCH 2/3] wip --- apps/desktop/forge.config.ts | 2 + apps/desktop/package.json | 4 +- apps/desktop/src/assets/svg/phone-off.svg | 6 + apps/desktop/src/assets/svg/phone.svg | 5 + apps/desktop/src/components/menuButton.ts | 2 +- apps/desktop/src/features/control.ts | 18 +- apps/desktop/src/main.ts | 25 +- apps/desktop/src/menu/main.ts | 42 ++- apps/desktop/src/menu/renderer.ts | 76 ++++- apps/desktop/src/picture/incomingCall.ts | 93 ++++++ apps/desktop/src/picture/main.ts | 36 +- apps/desktop/src/picture/outgoingCall.ts | 51 +++ apps/desktop/src/picture/renderer.ts | 167 ++++++---- apps/desktop/src/preload.ts | 16 +- apps/desktop/src/vite-env.d.ts | 1 + apps/desktop/src/webSocketManager.ts | 46 +++ package-lock.json | 386 +++++++++++++++++++++- 17 files changed, 893 insertions(+), 83 deletions(-) create mode 100644 apps/desktop/src/assets/svg/phone-off.svg create mode 100644 apps/desktop/src/assets/svg/phone.svg create mode 100644 apps/desktop/src/picture/incomingCall.ts create mode 100644 apps/desktop/src/picture/outgoingCall.ts create mode 100644 apps/desktop/src/vite-env.d.ts create mode 100644 apps/desktop/src/webSocketManager.ts diff --git a/apps/desktop/forge.config.ts b/apps/desktop/forge.config.ts index 1969ec8..48269ec 100644 --- a/apps/desktop/forge.config.ts +++ b/apps/desktop/forge.config.ts @@ -3,6 +3,7 @@ import { MakerSquirrel } from '@electron-forge/maker-squirrel' import { MakerZIP } from '@electron-forge/maker-zip' import { MakerDeb } from '@electron-forge/maker-deb' import { MakerRpm } from '@electron-forge/maker-rpm' +import { MakerDMG } from '@electron-forge/maker-dmg' import { VitePlugin } from '@electron-forge/plugin-vite' import { FusesPlugin } from '@electron-forge/plugin-fuses' import { FuseV1Options, FuseVersion } from '@electron/fuses' @@ -26,6 +27,7 @@ const config: ForgeConfig = { new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({}), + new MakerDMG({}), ], plugins: [ new VitePlugin({ diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 98cfe8e..9d8e2ab 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -14,11 +14,13 @@ }, "dependencies": { "electron-squirrel-startup": "^1.0.0", - "lucide": "^0.378.0" + "lucide": "^0.378.0", + "ws": "^8.17.0" }, "devDependencies": { "@electron-forge/cli": "^7.4.0", "@electron-forge/maker-deb": "^7.4.0", + "@electron-forge/maker-dmg": "^7.4.0", "@electron-forge/maker-rpm": "^7.4.0", "@electron-forge/maker-squirrel": "^7.4.0", "@electron-forge/maker-zip": "^7.4.0", diff --git a/apps/desktop/src/assets/svg/phone-off.svg b/apps/desktop/src/assets/svg/phone-off.svg new file mode 100644 index 0000000..31d89da --- /dev/null +++ b/apps/desktop/src/assets/svg/phone-off.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/apps/desktop/src/assets/svg/phone.svg b/apps/desktop/src/assets/svg/phone.svg new file mode 100644 index 0000000..ed0fea2 --- /dev/null +++ b/apps/desktop/src/assets/svg/phone.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/apps/desktop/src/components/menuButton.ts b/apps/desktop/src/components/menuButton.ts index 7ba4d1f..c543e70 100644 --- a/apps/desktop/src/components/menuButton.ts +++ b/apps/desktop/src/components/menuButton.ts @@ -5,7 +5,7 @@ import { customElement } from 'lit/decorators.js' export class MenuButton extends LitElement { protected render() { return html` - ` diff --git a/apps/desktop/src/features/control.ts b/apps/desktop/src/features/control.ts index 684fdf7..c38ef53 100644 --- a/apps/desktop/src/features/control.ts +++ b/apps/desktop/src/features/control.ts @@ -12,12 +12,29 @@ export class Control extends LitElement { @property({ type: Array }) readonly members?: IMember[] + @property({ type: Object }) + readonly initialConstraints?: MediaStreamConstraints + @state() private _constraints: MediaStreamConstraints = { video: false, audio: false, } + connectedCallback(): void { + super.connectedCallback() + + if (this.initialConstraints) { + if (this.initialConstraints.video) { + this._turnViewerVideo() + } + + if (this.initialConstraints.audio) { + this._turnViewerAudio() + } + } + } + private async _updateStream() { if (!this.viewer) return if (!this.viewer.stream) return @@ -185,7 +202,6 @@ export class Control extends LitElement { static styles = css` :host { - width: 100%; display: flex; align-items: center; justify-content: center; diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index 5ac2189..1b18886 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -1,15 +1,19 @@ import path from 'node:path' -import { app, Tray } from 'electron' -import { createWindow } from '../menu/main' +import { Tray, app, systemPreferences } from 'electron' +import { createWindow as createWindowMenu } from './menu/main' -export function initSystemTray() { +import WebSocket from 'ws' +import { addContact, initializeDataFile } from './localDataManager' +import { initializeWebSocket } from './webSocketManager' + +function createTray(ws: WebSocket) { const iconPath = app.isPackaged ? path.join(process.resourcesPath, 'LogoTemplate@2x.png') : path.resolve('./src/assets/LogoTemplate@2x.png') const tray = new Tray(iconPath) - const trayMenuWindow = createWindow() + const trayMenuWindow = createWindowMenu(ws) function toggleMenuWindow() { trayMenuWindow.isVisible() ? trayMenuWindow.hide() : trayMenuWindow.show() @@ -19,8 +23,19 @@ export function initSystemTray() { trayMenuWindow.setPosition(bounds.x, bounds.y) toggleMenuWindow() }) + + systemPreferences.askForMediaAccess('microphone') + systemPreferences.askForMediaAccess('camera') } app.on('window-all-closed', (e) => e.preventDefault()) -app.on('ready', createTray) +app.on('ready', async () => { + await addContact('4ae45530-39a6-4417-8f58-50edc0a127fd', { name: 'Matvei' }) + await addContact('b45c46f5-1805-4dc9-aecd-d024e259e56a', { name: 'Polina' }) + const localData = await initializeDataFile() + + const ws = initializeWebSocket(localData) + + createTray(ws) +}) diff --git a/apps/desktop/src/menu/main.ts b/apps/desktop/src/menu/main.ts index 6499485..fd2d32f 100644 --- a/apps/desktop/src/menu/main.ts +++ b/apps/desktop/src/menu/main.ts @@ -1,13 +1,16 @@ -import { BrowserWindow, ipcMain } from 'electron' +// TODO: расширять окно, при добавлении контактов +import { BrowserWindow, app, ipcMain } from 'electron' import path from 'node:path' -import { createWindow as createPictureWindow } from '../picture/main' +import { createWindow as createWindowPicture } from '../picture/main' +import type { WebSocket } from 'ws' +import { loadData } from '../localDataManager' -export function createWindow() { +export function createWindow(ws: WebSocket) { const window = new BrowserWindow({ show: false, width: 300, - height: 166, + height: 300, frame: false, resizable: false, transparent: true, @@ -45,8 +48,35 @@ export function createWindow() { ) } - ipcMain.on('open-picture', () => { - createPictureWindow() + window.webContents.on('did-finish-load', async () => { + const localData = await loadData() + console.log(localData) + // window.webContents.openDevTools() + window.webContents.send('local-data', localData) + }) + + // ipcMain.on('call-to-contact', (_, contactID) => { + // // TODO: открывать picture in picture, получать оттуда offer -> передавать его в сокеты + + // const eventData = { + // eventName: 'offer', + // data: { + // to: contactID, + // sdp: '', + // }, + // } + // console.log(contactID) + // ws.send(JSON.stringify(eventData)) + + // // TODO: обработать ответ, что контакт не в сети + // }) + + ipcMain.on('open-picture', (_, id) => { + createWindowPicture(ws, id, 'outgoing') + }) + + ipcMain.on('quit', () => { + app.quit() }) return window diff --git a/apps/desktop/src/menu/renderer.ts b/apps/desktop/src/menu/renderer.ts index e3e540f..35ad396 100644 --- a/apps/desktop/src/menu/renderer.ts +++ b/apps/desktop/src/menu/renderer.ts @@ -1,5 +1,6 @@ import { LitElement, css, html } from 'lit' -import { customElement } from 'lit/decorators.js' +import { customElement, state } from 'lit/decorators.js' +import { repeat } from 'lit/directives/repeat.js' import '../components/menuButton' @@ -20,9 +21,43 @@ registerIconLibrary('lucide', { @customElement('bell-tray-menu') export class TrayMenu extends LitElement { + @state() + myID?: string + + @state() + contacts?: any[] + + connectedCallback(): void { + super.connectedCallback() + + window.electron.onLocalData((value) => { + this.myID = value.id + this.contacts = value.contacts.entries().reduce((acc, [id, value]) => { + acc.push({ id, ...value }) + + return acc + }, []) + }) + } + + private _callToContact(id: string): void { + window.electron.openPicture(id) + } + + private _quit() { + window.electron.quit() + } + protected render() { return html` - window.electronAPI.openPicture()}> + +

ID

+ ${this.myID} +
+ +
+ + this._callToContact(this.myID)}> + ${repeat( + this.contacts, + (contact) => contact.id, + (contact) => html` + this._callToContact(contact.id)} + >${contact.name} + ` + )} + +
+ Settings About
- Quit + Quit ` } @@ -50,6 +97,29 @@ export class TrayMenu extends LitElement { background: #ffffff; } + .bio { + &::part(base) { + display: flex; + align-items: flex-start; + flex-direction: column; + gap: 0; + } + + p { + width: 100%; + text-align: left; + font-size: 11px; + font-weight: 500; + color: #9d9d9d; + margin: 0; + } + + span { + font-size: 13px; + font-weight: 500; + } + } + hr { height: 1px; background: #eeeeee; diff --git a/apps/desktop/src/picture/incomingCall.ts b/apps/desktop/src/picture/incomingCall.ts new file mode 100644 index 0000000..0457c13 --- /dev/null +++ b/apps/desktop/src/picture/incomingCall.ts @@ -0,0 +1,93 @@ +import { LitElement, css, html } from 'lit' +import { customElement, property } from 'lit/decorators.js' +import { unsafeHTML } from 'lit-html/directives/unsafe-html.js' + +// SVG +import PhoneSVG from '../assets/svg/phone.svg?raw' +import PhoneOffSVG from '../assets/svg/phone-off.svg?raw' + +@customElement('bell-incoming-call') +export class IncomingCall extends LitElement { + private _acceptIncomingCall() { + console.log('accept call') + + this.dispatchEvent(new CustomEvent('call:accept')) + } + + private _rejectIncomingCall() { + console.log('reject call') + + this.dispatchEvent(new CustomEvent('call:reject')) + } + + render() { + return html` +
+ +
+ Donatello +

is calling you

+
+ +
+ + ${unsafeHTML(PhoneOffSVG)} + + + ${unsafeHTML(PhoneSVG)} + +
+ ` + } + + static styles = css` + :host { + position: absolute; + top: 0; + left: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + padding: 18px 0 8px 0; + box-sizing: border-box; + width: 100%; + height: 100%; + } + + .overlay { + width: 100%; + height: 100%; + background: #ffffff57; + backdrop-filter: blur(2px); + position: absolute; + top: 0; + left: 0; + } + + .info { + z-index: 1; + text-align: center; + + span { + font-size: 26px; + font-weight: 700; + } + + p { + font-size: 13px; + font-weight: 400; + margin: 0; + } + } + + .actions { + display: flex; + gap: 10px; + + bell-button { + stroke: #00b607 !important; // #EF2727 + } + } + ` +} diff --git a/apps/desktop/src/picture/main.ts b/apps/desktop/src/picture/main.ts index 93e4def..928e042 100644 --- a/apps/desktop/src/picture/main.ts +++ b/apps/desktop/src/picture/main.ts @@ -1,7 +1,14 @@ -import { BrowserWindow, screen } from 'electron' +import { BrowserWindow, screen, ipcMain } from 'electron' import path from 'path' +import type { WebSocket } from 'ws' -export function createWindow() { +// TODO: нельзя что бы это окно было открыто дважды !!! +export function createWindow( + ws: WebSocket, + id: string, + type: 'outgoing' | 'incoming', + remoteSDP?: RTCSessionDescription +) { const windowWidth = 400 const window = new BrowserWindow({ @@ -15,6 +22,9 @@ export function createWindow() { skipTaskbar: true, // vibrancy: 'window', + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + }, }) const display = screen.getPrimaryDisplay() @@ -38,6 +48,28 @@ export function createWindow() { ) } + window.webContents.on('did-finish-load', () => { + if (remoteSDP) { + window.webContents.send('remote-sdp', remoteSDP) + } + window.webContents.send('type', type) + }) + + // TODO: нужно получить оффер и передать его в ws вместе с id + ipcMain.on('local-sdp', (_, sdp) => { + console.log(sdp.type) + const eventData = { + eventName: sdp.type === 'offer' ? 'offer' : 'answer', + data: { + to: id, + sdp: sdp, + }, + } + ws.send(JSON.stringify(eventData)) + + // dialog.showErrorBox('hello', 'sdsds') + }) + // window.setAlwaysOnTop(true, 'pop-up-menu') return window diff --git a/apps/desktop/src/picture/outgoingCall.ts b/apps/desktop/src/picture/outgoingCall.ts new file mode 100644 index 0000000..d751efc --- /dev/null +++ b/apps/desktop/src/picture/outgoingCall.ts @@ -0,0 +1,51 @@ +import { LitElement, css, html } from 'lit' +import { customElement } from 'lit/decorators.js' + +@customElement('bell-outgoing-call') +export class OutgoingCall extends LitElement { + render() { + return html` +
+ +
+

Connecting ...

+
+ ` + } + + static styles = css` + :host { + position: absolute; + top: 0; + left: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + box-sizing: border-box; + width: 100%; + height: 100%; + } + + .overlay { + width: 100%; + height: 100%; + background: #ffffff57; + backdrop-filter: blur(2px); + position: absolute; + top: 0; + left: 0; + } + + .info { + z-index: 1; + text-align: center; + + p { + font-size: 13px; + font-weight: 400; + margin: 0; + } + } + ` +} diff --git a/apps/desktop/src/picture/renderer.ts b/apps/desktop/src/picture/renderer.ts index 34988ad..9e3b3be 100644 --- a/apps/desktop/src/picture/renderer.ts +++ b/apps/desktop/src/picture/renderer.ts @@ -1,4 +1,4 @@ -import { LitElement, html, css } from 'lit' +import { LitElement, html, css, nothing } from 'lit' import { customElement, state } from 'lit/decorators.js' // Shoelace @@ -9,11 +9,17 @@ import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.j // TODO: temporary solution, as I don't want to drag all existing svg into the build setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.0/cdn/') +import './incomingCall' +import './outgoingCall' + +import '../components/button' + import './member' import '../features/control' import '../features/inviteCode' import '../features/responseCode' import { IMember, IViewer } from '../types' +import { PeerController } from '../../../playground/src/components/webrtc/peer.controller' @customElement('bell-main') export class Main extends LitElement { @@ -27,66 +33,107 @@ export class Main extends LitElement { @state() private _members: IMember[] = [] + // FIXME: надо понять, как отправить из main в renderer, до события callback + @state() + private _callType: 'outgoing' | 'incoming' + @state() - private _inviteOrResponse?: 'invite' | 'response' + private _currentCallStatus: 'connection' | 'connected' // TODO: можно брать состояние из webrtc + + // TODO: при открытии окна, важно учитывать на какой стороне его открывают, исходящей или принимающей + async connectedCallback(): Promise { + super.connectedCallback() + + const peerController = new PeerController(this, this._viewer.stream) + + window.electron.onType(async (value) => { + this._callType = value + + if (this._callType === 'outgoing') { + const offer = await peerController.peerConnection.createOffer() + peerController.peerConnection.setLocalDescription(offer) + + window.electron.sendLocalSDP(offer) + } + + this.requestUpdate() + }) + + window.electron.onRemoteSDP(async (value) => { + // TODO: возможно будут проблемы, так как он должен выполняться до создания answer + peerController.peerConnection.setRemoteDescription(value) - private _handleUpdateMembers(e) { - this._members = e.detail + if (this._callType === 'incoming') { + const answer = await peerController.peerConnection.createAnswer() + peerController.peerConnection.setLocalDescription(answer) + + window.electron.sendLocalSDP(answer) + } + + this.requestUpdate() + }) + + const member: IMember = { + id: crypto.randomUUID(), + name: `Someone else #1`, + peerController: peerController, + } + + const updatedMembers = [...this._members] + updatedMembers.push(member) + this._members = updatedMembers } - // TODO: решить, как выводить invite code или response code + private _handleAcceptCall() { + // создать на этой стороне клиента peerconnection + // принять входящий оффер, и положить его в remoteDescription + // ------------ + // сгенерировать ответ и отправить его по ws + } + + private _handleRejectCall() {} + render() { - return this._inviteOrResponse === undefined - ? html` - - - ` - : this._inviteOrResponse === 'invite' - ? html` - - ` - : html` - - ` - // : html` - // - - // - // - // - // - // - // - - // - // ` + const callStatus1 = + this._callType === 'incoming' + ? html`` + : html`` + + const callStatus = this._callType ? callStatus1 : nothing + + return html` + + + ${callStatus} + + window.close()}> + + + + + + + + ` } static styles = css` @@ -114,11 +161,9 @@ export class Main extends LitElement { position: absolute; bottom: 8px; - left: 50%; - transform: translateX(-50%); - - background: none; - transition: background 2s; + /* left: 50%; */ + /* transform: translateX(-50%); */ + left: 8px; } ` } diff --git a/apps/desktop/src/preload.ts b/apps/desktop/src/preload.ts index 89e3ae5..d1a3936 100644 --- a/apps/desktop/src/preload.ts +++ b/apps/desktop/src/preload.ts @@ -1,5 +1,17 @@ import { contextBridge, ipcRenderer } from 'electron' -contextBridge.exposeInMainWorld('electronAPI', { - openPicture: () => ipcRenderer.send('open-picture'), +contextBridge.exposeInMainWorld('electron', { + openPicture: (id) => ipcRenderer.send('open-picture', id), + callToContact: (id) => ipcRenderer.send('call-to-contact', id), + sendLocalSDP: (value: RTCSessionDescription) => + ipcRenderer.send('local-sdp', value), + + quit: () => ipcRenderer.send('quit'), + + onLocalData: (callback) => + ipcRenderer.on('local-data', (_event, value) => callback(value)), + onType: (callback) => + ipcRenderer.on('type', (_event, value) => callback(value)), + onRemoteSDP: (callback: (value: RTCSessionDescription) => void) => + ipcRenderer.on('remote-sdp', (_event, value) => callback(value)), }) diff --git a/apps/desktop/src/vite-env.d.ts b/apps/desktop/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/apps/desktop/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/desktop/src/webSocketManager.ts b/apps/desktop/src/webSocketManager.ts new file mode 100644 index 0000000..81ae81d --- /dev/null +++ b/apps/desktop/src/webSocketManager.ts @@ -0,0 +1,46 @@ +import WebSocket from 'ws' +import { createWindow as createWindowPicture } from './picture/main' // FIXME: + +export function initializeWebSocket(localData) { + let ws: WebSocket + + function connect() { + ws = new WebSocket('ws://192.168.1.101:3000', { + perMessageDeflate: false, + }) + + ws.on('open', () => { + const eventData = { + eventName: 'login', + data: { + id: localData.id, + }, + } + ws.send(JSON.stringify(eventData)) + }) + + ws.on('message', (e) => { + console.log('Received message') + const message = JSON.parse(e) + + // пользователю пришел звонок, необходимо открыть окно, и спросить, принимает он звонок или нет + // положить полученный sdp в remote, сгенерить ответ, отправить на сервер + if ('eventName' in message && message.eventName === 'receiveOffer') { + createWindowPicture(ws, message.data.from, 'incoming', message.data.sdp) + } + }) + + ws.on('close', () => { + console.log('Connection lost, attempting to reconnect...') + setTimeout(connect, 5000) // Пауза перед повторной попыткой переподключения + }) + + ws.on('error', (err) => { + console.error('WebSocket error:', err.message) + ws.close() + }) + } + + connect() + return ws +} diff --git a/package-lock.json b/package-lock.json index f8adb25..dd46dbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,11 +30,13 @@ "version": "0.0.0", "dependencies": { "electron-squirrel-startup": "^1.0.0", - "lucide": "^0.378.0" + "lucide": "^0.378.0", + "ws": "^8.17.0" }, "devDependencies": { "@electron-forge/cli": "^7.4.0", "@electron-forge/maker-deb": "^7.4.0", + "@electron-forge/maker-dmg": "^7.4.0", "@electron-forge/maker-rpm": "^7.4.0", "@electron-forge/maker-squirrel": "^7.4.0", "@electron-forge/maker-zip": "^7.4.0", @@ -46,6 +48,26 @@ "ts-node": "^10.9.2" } }, + "apps/desktop/node_modules/ws": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "apps/playground": { "version": "0.0.0", "devDependencies": { @@ -286,6 +308,37 @@ "electron-installer-debian": "^3.2.0" } }, + "node_modules/@electron-forge/maker-dmg": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-dmg/-/maker-dmg-7.4.0.tgz", + "integrity": "sha512-xRCMNtnpvQNwrDYvwbVFegnErnIMpHGZANrjwushlH9+Fsu60DFvf5s3AVkgsYdQTqlY7wYRG1mziYZmRlPAIw==", + "dev": true, + "dependencies": { + "@electron-forge/maker-base": "7.4.0", + "@electron-forge/shared-types": "7.4.0", + "fs-extra": "^10.0.0" + }, + "engines": { + "node": ">= 16.4.0" + }, + "optionalDependencies": { + "electron-installer-dmg": "^4.0.0" + } + }, + "node_modules/@electron-forge/maker-dmg/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@electron-forge/maker-rpm": { "version": "7.4.0", "dev": true, @@ -1843,6 +1896,35 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/appdmg": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/appdmg/-/appdmg-0.6.6.tgz", + "integrity": "sha512-GRmFKlCG+PWbcYF4LUNonTYmy0GjguDy6Jh9WP8mpd0T6j80XIJyXBiWlD0U+MLNhqV9Nhx49Gl9GpVToulpLg==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "async": "^1.4.2", + "ds-store": "^0.1.5", + "execa": "^1.0.0", + "fs-temp": "^1.0.0", + "fs-xattr": "^0.3.0", + "image-size": "^0.7.4", + "is-my-json-valid": "^2.20.0", + "minimist": "^1.1.3", + "parse-color": "^1.0.0", + "path-exists": "^4.0.0", + "repeat-string": "^1.5.4" + }, + "bin": { + "appdmg": "bin/appdmg.js" + }, + "engines": { + "node": ">=8.5" + } + }, "node_modules/aproba": { "version": "2.0.0", "dev": true, @@ -1906,6 +1988,13 @@ "@types/glob": "^7.1.1" } }, + "node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "dev": true, + "optional": true + }, "node_modules/asynckit": { "version": "0.4.0", "dev": true, @@ -1942,6 +2031,16 @@ "dev": true, "license": "MIT" }, + "node_modules/base32-encode": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/base32-encode/-/base32-encode-1.2.0.tgz", + "integrity": "sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A==", + "dev": true, + "optional": true, + "dependencies": { + "to-data-view": "^1.1.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "dev": true, @@ -2033,6 +2132,16 @@ "license": "MIT", "optional": true }, + "node_modules/bplist-creator": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz", + "integrity": "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==", + "dev": true, + "optional": true, + "dependencies": { + "stream-buffers": "~2.2.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "dev": true, @@ -2774,6 +2883,18 @@ "node": ">=12" } }, + "node_modules/ds-store": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ds-store/-/ds-store-0.1.6.tgz", + "integrity": "sha512-kY21M6Lz+76OS3bnCzjdsJSF7LBpLYGCVfavW8TgQD2XkcqIZ86W0y9qUDZu6fp7SIZzqosMDW2zi7zVFfv4hw==", + "dev": true, + "optional": true, + "dependencies": { + "bplist-creator": "~0.0.3", + "macos-alias": "~0.2.5", + "tn1150": "^0.1.0" + } + }, "node_modules/duplexer": { "version": "0.1.2", "dev": true, @@ -2971,6 +3092,26 @@ "node": ">=10" } }, + "node_modules/electron-installer-dmg": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/electron-installer-dmg/-/electron-installer-dmg-4.0.0.tgz", + "integrity": "sha512-g3W6XnyUa7QGrAF7ViewHdt6bXV2KYU1Pm1CY3pZpp+H6mOjCHHAhf/iZAxtaX1ERCb+SQHz7xSsAHuNH9I8ZQ==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "^4.3.2", + "minimist": "^1.1.1" + }, + "bin": { + "electron-installer-dmg": "bin/electron-installer-dmg.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "optionalDependencies": { + "appdmg": "^0.6.4" + } + }, "node_modules/electron-installer-redhat": { "version": "3.4.0", "dev": true, @@ -3203,6 +3344,13 @@ "dev": true, "license": "MIT" }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", + "dev": true, + "optional": true + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -3970,6 +4118,16 @@ "node": ">=12" } }, + "node_modules/fmix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fmix/-/fmix-0.1.0.tgz", + "integrity": "sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==", + "dev": true, + "optional": true, + "dependencies": { + "imul": "^1.0.0" + } + }, "node_modules/follow-redirects": { "version": "1.15.6", "dev": true, @@ -4049,6 +4207,30 @@ "node": ">= 8" } }, + "node_modules/fs-temp": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/fs-temp/-/fs-temp-1.2.1.tgz", + "integrity": "sha512-okTwLB7/Qsq82G6iN5zZJFsOfZtx2/pqrA7Hk/9fvy+c+eJS9CvgGXT2uNxwnI14BDY9L/jQPkaBgSvlKfSW9w==", + "dev": true, + "optional": true, + "dependencies": { + "random-path": "^0.1.0" + } + }, + "node_modules/fs-xattr": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/fs-xattr/-/fs-xattr-0.3.1.tgz", + "integrity": "sha512-UVqkrEW0GfDabw4C3HOrFlxKfx0eeigfRne69FxSBdHIP8Qt5Sq6Pu3RM9KmMlkygtC4pPKkj5CiPO5USnj2GA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "!win32" + ], + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "dev": true, @@ -4124,6 +4306,26 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "optional": true, + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==", + "dev": true, + "optional": true, + "dependencies": { + "is-property": "^1.0.0" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "dev": true, @@ -4570,6 +4772,19 @@ "node": ">= 4" } }, + "node_modules/image-size": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.5.tgz", + "integrity": "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g==", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "dev": true, @@ -4585,6 +4800,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/imul": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz", + "integrity": "sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "dev": true, @@ -4729,6 +4954,27 @@ "dev": true, "license": "MIT" }, + "node_modules/is-my-ip-valid": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz", + "integrity": "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==", + "dev": true, + "optional": true + }, + "node_modules/is-my-json-valid": { + "version": "2.20.6", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz", + "integrity": "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==", + "dev": true, + "optional": true, + "dependencies": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^5.0.0", + "xtend": "^4.0.0" + } + }, "node_modules/is-number": { "version": "7.0.0", "dev": true, @@ -4750,6 +4996,13 @@ "dev": true, "license": "MIT" }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "dev": true, + "optional": true + }, "node_modules/is-stream": { "version": "1.1.0", "dev": true, @@ -4903,6 +5156,16 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/junk": { "version": "3.1.0", "dev": true, @@ -5256,6 +5519,20 @@ "resolved": "https://registry.npmjs.org/lucide/-/lucide-0.378.0.tgz", "integrity": "sha512-bwWXuZf2jZbCI0Y+MWyv5bedWIxYKtgAEzC2Yl87Nrt/KcG9qTwAQxVFcZ6IwBioML06QUQsG+qRjyQvYHdbBQ==" }, + "node_modules/macos-alias": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/macos-alias/-/macos-alias-0.2.11.tgz", + "integrity": "sha512-zIUs3+qpml+w3wiRuADutd7XIO8UABqksot10Utl/tji4UxZzLG4fWDC+yJZoO8/Ehg5RqsvSRE/6TS5AEOeWw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "nan": "^2.4.0" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -5541,6 +5818,25 @@ "dev": true, "license": "MIT" }, + "node_modules/murmur-32": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/murmur-32/-/murmur-32-0.2.0.tgz", + "integrity": "sha512-ZkcWZudylwF+ir3Ld1n7gL6bI2mQAzXvSobPwVtu8aYi2sbXeipeSkdcanRLzIofLcM5F53lGaKm2dk7orBi7Q==", + "dev": true, + "optional": true, + "dependencies": { + "encode-utf8": "^1.0.3", + "fmix": "^0.1.0", + "imul": "^1.0.0" + } + }, + "node_modules/nan": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", + "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==", + "dev": true, + "optional": true + }, "node_modules/nanoid": { "version": "3.3.7", "dev": true, @@ -6017,6 +6313,23 @@ "node": ">=0.10.0" } }, + "node_modules/parse-color": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", + "integrity": "sha512-fuDHYgFHJGbpGMgw9skY/bj3HL/Jrn4l/5rSspy00DoT4RyLnDcRvPxdZ+r6OFwIsgAuhDh4I09tAId4mI12bw==", + "dev": true, + "optional": true, + "dependencies": { + "color-convert": "~0.5.0" + } + }, + "node_modules/parse-color/node_modules/color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling==", + "dev": true, + "optional": true + }, "node_modules/parse-json": { "version": "2.2.0", "dev": true, @@ -6418,6 +6731,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/random-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/random-path/-/random-path-0.1.2.tgz", + "integrity": "sha512-4jY0yoEaQ5v9StCl5kZbNIQlg1QheIDBrdkDn53EynpPb9FgO6//p3X/tgMnrC45XN6QZCzU1Xz/+pSSsJBpRw==", + "dev": true, + "optional": true, + "dependencies": { + "base32-encode": "^0.1.0 || ^1.0.0", + "murmur-32": "^0.1.0 || ^0.2.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -6583,6 +6907,16 @@ "node": ">= 10.13.0" } }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10" + } + }, "node_modules/require-directory": { "version": "2.1.1", "dev": true, @@ -7176,6 +7510,16 @@ "node": ">= 0.8" } }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "dev": true, @@ -7417,6 +7761,26 @@ "tmp": "^0.2.0" } }, + "node_modules/tn1150": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tn1150/-/tn1150-0.1.0.tgz", + "integrity": "sha512-DbplOfQFkqG5IHcDyyrs/lkvSr3mPUVsFf/RbDppOshs22yTPnSJWEe6FkYd1txAwU/zcnR905ar2fi4kwF29w==", + "dev": true, + "optional": true, + "dependencies": { + "unorm": "^1.4.1" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/to-data-view": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/to-data-view/-/to-data-view-1.1.0.tgz", + "integrity": "sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==", + "dev": true, + "optional": true + }, "node_modules/to-regex-range": { "version": "5.0.1", "dev": true, @@ -7640,6 +8004,16 @@ "node": ">= 10.0.0" } }, + "node_modules/unorm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", + "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -7864,6 +8238,16 @@ "node": ">=8.0" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.4" + } + }, "node_modules/xterm": { "version": "4.19.0", "resolved": "https://registry.npmjs.org/xterm/-/xterm-4.19.0.tgz", From 50802f45aacd120b057833886b10e19264b0fec0 Mon Sep 17 00:00:00 2001 From: Matvey Melishev Date: Sun, 26 May 2024 21:53:45 +0200 Subject: [PATCH 3/3] wip --- apps/desktop/forge.config.ts | 4 ++-- apps/desktop/forge.env.d.ts | 4 ++-- apps/desktop/src/{picture => intercom}/incomingCall.ts | 0 apps/desktop/src/{picture => intercom}/index.css | 0 apps/desktop/src/{picture => intercom}/index.html | 0 apps/desktop/src/{picture => intercom}/main.ts | 9 ++++++--- apps/desktop/src/{picture => intercom}/member.ts | 0 apps/desktop/src/{picture => intercom}/outgoingCall.ts | 0 apps/desktop/src/{picture => intercom}/renderer.ts | 7 +++---- apps/desktop/src/menu/main.ts | 6 +++--- apps/desktop/src/menu/renderer.ts | 2 +- apps/desktop/src/preload.ts | 2 +- apps/desktop/src/webSocketManager.ts | 9 +++++++-- ...icture.config.ts => vite.renderer.intercom.config.ts} | 2 +- 14 files changed, 26 insertions(+), 19 deletions(-) rename apps/desktop/src/{picture => intercom}/incomingCall.ts (100%) rename apps/desktop/src/{picture => intercom}/index.css (100%) rename apps/desktop/src/{picture => intercom}/index.html (100%) rename apps/desktop/src/{picture => intercom}/main.ts (89%) rename apps/desktop/src/{picture => intercom}/member.ts (100%) rename apps/desktop/src/{picture => intercom}/outgoingCall.ts (100%) rename apps/desktop/src/{picture => intercom}/renderer.ts (92%) rename apps/desktop/{vite.renderer.picture.config.ts => vite.renderer.intercom.config.ts} (96%) diff --git a/apps/desktop/forge.config.ts b/apps/desktop/forge.config.ts index 48269ec..c02705c 100644 --- a/apps/desktop/forge.config.ts +++ b/apps/desktop/forge.config.ts @@ -50,8 +50,8 @@ const config: ForgeConfig = { config: 'vite.renderer.menu.config.ts', }, { - name: 'picture_window', - config: 'vite.renderer.picture.config.ts', + name: 'intercom_window', + config: 'vite.renderer.intercom.config.ts', }, ], }), diff --git a/apps/desktop/forge.env.d.ts b/apps/desktop/forge.env.d.ts index 2d607c3..4e81463 100644 --- a/apps/desktop/forge.env.d.ts +++ b/apps/desktop/forge.env.d.ts @@ -7,8 +7,8 @@ declare global { const MENU_WINDOW_VITE_DEV_SERVER_URL: string const MENU_WINDOW_VITE_NAME: string - const PICTURE_WINDOW_VITE_DEV_SERVER_URL: string - const PICTURE_WINDOW_VITE_NAME: string + const INTERCOM_WINDOW_VITE_DEV_SERVER_URL: string + const INTERCOM_WINDOW_VITE_NAME: string namespace NodeJS { interface Process { diff --git a/apps/desktop/src/picture/incomingCall.ts b/apps/desktop/src/intercom/incomingCall.ts similarity index 100% rename from apps/desktop/src/picture/incomingCall.ts rename to apps/desktop/src/intercom/incomingCall.ts diff --git a/apps/desktop/src/picture/index.css b/apps/desktop/src/intercom/index.css similarity index 100% rename from apps/desktop/src/picture/index.css rename to apps/desktop/src/intercom/index.css diff --git a/apps/desktop/src/picture/index.html b/apps/desktop/src/intercom/index.html similarity index 100% rename from apps/desktop/src/picture/index.html rename to apps/desktop/src/intercom/index.html diff --git a/apps/desktop/src/picture/main.ts b/apps/desktop/src/intercom/main.ts similarity index 89% rename from apps/desktop/src/picture/main.ts rename to apps/desktop/src/intercom/main.ts index 928e042..f55f052 100644 --- a/apps/desktop/src/picture/main.ts +++ b/apps/desktop/src/intercom/main.ts @@ -40,11 +40,14 @@ export function createWindow( visibleOnFullScreen: true, }) - if (PICTURE_WINDOW_VITE_DEV_SERVER_URL) { - window.loadURL(PICTURE_WINDOW_VITE_DEV_SERVER_URL) + if (INTERCOM_WINDOW_VITE_DEV_SERVER_URL) { + window.loadURL(INTERCOM_WINDOW_VITE_DEV_SERVER_URL) } else { window.loadFile( - path.join(__dirname, `../renderer/${PICTURE_WINDOW_VITE_NAME}/index.html`) + path.join( + __dirname, + `../renderer/${INTERCOM_WINDOW_VITE_NAME}/index.html` + ) ) } diff --git a/apps/desktop/src/picture/member.ts b/apps/desktop/src/intercom/member.ts similarity index 100% rename from apps/desktop/src/picture/member.ts rename to apps/desktop/src/intercom/member.ts diff --git a/apps/desktop/src/picture/outgoingCall.ts b/apps/desktop/src/intercom/outgoingCall.ts similarity index 100% rename from apps/desktop/src/picture/outgoingCall.ts rename to apps/desktop/src/intercom/outgoingCall.ts diff --git a/apps/desktop/src/picture/renderer.ts b/apps/desktop/src/intercom/renderer.ts similarity index 92% rename from apps/desktop/src/picture/renderer.ts rename to apps/desktop/src/intercom/renderer.ts index 9e3b3be..b1ae91d 100644 --- a/apps/desktop/src/picture/renderer.ts +++ b/apps/desktop/src/intercom/renderer.ts @@ -37,10 +37,9 @@ export class Main extends LitElement { @state() private _callType: 'outgoing' | 'incoming' - @state() - private _currentCallStatus: 'connection' | 'connected' // TODO: можно брать состояние из webrtc + // @state() + // private _currentCallStatus: 'connection' | 'connected' - // TODO: при открытии окна, важно учитывать на какой стороне его открывают, исходящей или принимающей async connectedCallback(): Promise { super.connectedCallback() @@ -138,7 +137,7 @@ export class Main extends LitElement { static styles = css` :host { - /* -webkit-app-region: drag; */ + -webkit-app-region: drag; position: relative; display: block; diff --git a/apps/desktop/src/menu/main.ts b/apps/desktop/src/menu/main.ts index fd2d32f..6eb32da 100644 --- a/apps/desktop/src/menu/main.ts +++ b/apps/desktop/src/menu/main.ts @@ -2,7 +2,7 @@ import { BrowserWindow, app, ipcMain } from 'electron' import path from 'node:path' -import { createWindow as createWindowPicture } from '../picture/main' +import { createWindow as createWindowIntercom } from '../intercom/main' import type { WebSocket } from 'ws' import { loadData } from '../localDataManager' @@ -71,8 +71,8 @@ export function createWindow(ws: WebSocket) { // // TODO: обработать ответ, что контакт не в сети // }) - ipcMain.on('open-picture', (_, id) => { - createWindowPicture(ws, id, 'outgoing') + ipcMain.on('open-intercom', (_, id) => { + createWindowIntercom(ws, id, 'outgoing') }) ipcMain.on('quit', () => { diff --git a/apps/desktop/src/menu/renderer.ts b/apps/desktop/src/menu/renderer.ts index 35ad396..705ee32 100644 --- a/apps/desktop/src/menu/renderer.ts +++ b/apps/desktop/src/menu/renderer.ts @@ -41,7 +41,7 @@ export class TrayMenu extends LitElement { } private _callToContact(id: string): void { - window.electron.openPicture(id) + window.electron.openIntercom(id) } private _quit() { diff --git a/apps/desktop/src/preload.ts b/apps/desktop/src/preload.ts index d1a3936..d56a1ee 100644 --- a/apps/desktop/src/preload.ts +++ b/apps/desktop/src/preload.ts @@ -1,7 +1,7 @@ import { contextBridge, ipcRenderer } from 'electron' contextBridge.exposeInMainWorld('electron', { - openPicture: (id) => ipcRenderer.send('open-picture', id), + openIntercom: (id) => ipcRenderer.send('open-intercom', id), callToContact: (id) => ipcRenderer.send('call-to-contact', id), sendLocalSDP: (value: RTCSessionDescription) => ipcRenderer.send('local-sdp', value), diff --git a/apps/desktop/src/webSocketManager.ts b/apps/desktop/src/webSocketManager.ts index 81ae81d..7fac5d0 100644 --- a/apps/desktop/src/webSocketManager.ts +++ b/apps/desktop/src/webSocketManager.ts @@ -1,5 +1,5 @@ import WebSocket from 'ws' -import { createWindow as createWindowPicture } from './picture/main' // FIXME: +import { createWindow as createWindowIntercom } from './intercom/main' // FIXME: export function initializeWebSocket(localData) { let ws: WebSocket @@ -26,7 +26,12 @@ export function initializeWebSocket(localData) { // пользователю пришел звонок, необходимо открыть окно, и спросить, принимает он звонок или нет // положить полученный sdp в remote, сгенерить ответ, отправить на сервер if ('eventName' in message && message.eventName === 'receiveOffer') { - createWindowPicture(ws, message.data.from, 'incoming', message.data.sdp) + createWindowIntercom( + ws, + message.data.from, + 'incoming', + message.data.sdp + ) } }) diff --git a/apps/desktop/vite.renderer.picture.config.ts b/apps/desktop/vite.renderer.intercom.config.ts similarity index 96% rename from apps/desktop/vite.renderer.picture.config.ts rename to apps/desktop/vite.renderer.intercom.config.ts index 2e0ac56..1748e0b 100644 --- a/apps/desktop/vite.renderer.picture.config.ts +++ b/apps/desktop/vite.renderer.intercom.config.ts @@ -11,7 +11,7 @@ export default defineConfig((env) => { const name = forgeConfigSelf.name ?? '' return { - root: 'src/picture', + root: 'src/intercom', mode, base: './', build: {