-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolve DOO-94 "Electron splash and window styles and transparent can…
…vas" (#59) * Updated Websocket * Websocket mocks. * Add logger. * Fix live collab problems * Producer sharing. * Live collab with all edits except opacity * Consumer is working. * Disable sharing in a call. * customizability for rotate, resize, move * fix small linting problem * remove console logs * live collab with redo and undo * live collab with delete * live collab for text * debouncing opacity * live collab for text custimizability * Resized video * Working window alignment * Sharing works with pan and zoom * Documentation * Cleanup. * Workflow * Fix workflow * Add yarn cache dependency path. * Test emulator cache * Update tests and install firetools * Fix node tests * Electron IPC * Cleanup ipc listeners. * Screenshare from electron. * Draw transparent window, screen sources work, windowed kind of. Must be full screen. * Notifications bridged. * Comments. * More comments. * Fix linting. * Fix d.ts type definitions. * Move install firetools after cache. * Remove install fire-tools --------- Co-authored-by: Abdalla Abdelhadi <[email protected]>
- Loading branch information
1 parent
ab4c436
commit 65e5dbc
Showing
49 changed files
with
1,991 additions
and
277 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* Defines the action handles that can be sent to the main process from the renderer process via IPC. | ||
*/ | ||
export const IPC_ACTIONS = { | ||
MAXIMIZE_WINDOW: 'maximize', | ||
UNMAXIMIZE_WINDOW: 'unmaximize', | ||
MINIMIZE_WINDOW: 'minimize', | ||
CLOSE_WINDOW: 'close', | ||
HANDLE_NOTIFICATION: 'notification', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { BrowserWindow, IpcMainEvent, ipcMain } from 'electron'; | ||
import { IPC_ACTIONS } from './ipcActions'; | ||
import { notification } from '../main'; | ||
|
||
const { | ||
MAXIMIZE_WINDOW, | ||
UNMAXIMIZE_WINDOW, | ||
MINIMIZE_WINDOW, | ||
CLOSE_WINDOW, | ||
HANDLE_NOTIFICATION, | ||
} = IPC_ACTIONS; | ||
|
||
/** | ||
* Defines Electron IPC handlers and utility functions for window management. | ||
* @author Yousef Yassin | ||
*/ | ||
|
||
/** | ||
* Shared state object for storing global flags and variables. | ||
* @property global_RecvMaximizedEventFlag Flag to track the reception of maximize events. | ||
*/ | ||
export const shared = { global_RecvMaximizedEventFlag: false }; | ||
|
||
/** | ||
* Retrieves the BrowserWindow associated with the given IPC event. | ||
* @param event The IPC event. | ||
* @returns The associated BrowserWindow or null if not found. | ||
*/ | ||
const getWindow = (event: IpcMainEvent) => { | ||
const webContents = event?.sender; | ||
return BrowserWindow.fromWebContents(webContents); | ||
}; | ||
|
||
/** | ||
* Handles title bar events such as maximizing, unmaximizing, minimizing, and closing the window. | ||
* @param event The IPC event. | ||
* @param type The type of title bar event. | ||
*/ | ||
const handleWindowTitlebarEvent = (event: IpcMainEvent, type: string) => { | ||
if (type === MAXIMIZE_WINDOW) { | ||
shared.global_RecvMaximizedEventFlag = true; | ||
} | ||
const window = getWindow(event); | ||
// The type for title bar events is the same as the method name | ||
window?.[type](); | ||
if (type === CLOSE_WINDOW) { | ||
window?.destroy(); | ||
} | ||
}; | ||
|
||
/** | ||
* Handles notification events by updating notification properties and showing the notification. | ||
* @param _event The IPC event. | ||
* @param params Notification parameters. | ||
* @param params.title The title of the notification. | ||
* @param params.body The body/content of the notification. | ||
*/ | ||
const handleNotification = ( | ||
_event: IpcMainEvent, | ||
{ title, body }: { title: string; body: string }, | ||
) => { | ||
notification.title = title; | ||
notification.body = body; | ||
notification.show(); | ||
}; | ||
|
||
/** | ||
* Mapping of IPC events to their corresponding callback functions. | ||
*/ | ||
const eventToCallback = { | ||
[MAXIMIZE_WINDOW]: handleWindowTitlebarEvent, | ||
[UNMAXIMIZE_WINDOW]: handleWindowTitlebarEvent, | ||
[MINIMIZE_WINDOW]: handleWindowTitlebarEvent, | ||
[CLOSE_WINDOW]: handleWindowTitlebarEvent, | ||
[HANDLE_NOTIFICATION]: handleNotification, | ||
}; | ||
|
||
/** | ||
* Registers IPC event handlers (on the main process) | ||
* based on the defined mappings. | ||
*/ | ||
export const registerIPCHandlers = () => { | ||
Object.entries(eventToCallback).forEach(([event, callback]) => | ||
ipcMain.on(event, callback), | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,22 @@ | ||
import { app, BrowserWindow } from 'electron'; | ||
import { | ||
app, | ||
BrowserWindow, | ||
desktopCapturer, | ||
ipcMain, | ||
Notification, | ||
Tray, | ||
} from 'electron'; | ||
import path from 'node:path'; | ||
import { registerIPCHandlers } from './ipc/ipcHandlers'; | ||
import { registerGlobalShortcuts, setupTray, setupWindow } from './window'; | ||
|
||
/** | ||
* @file Main Electron process handling application initialization and window creation. | ||
* This is the entry point for the main process. | ||
* @author Yousef Yassin | ||
*/ | ||
|
||
// Set environment variables for the build directory structure | ||
// The built directory structure | ||
// | ||
// ├─┬─┬ dist | ||
|
@@ -15,33 +31,94 @@ process.env.PUBLIC = app.isPackaged | |
? process.env.DIST | ||
: path.join(process.env.DIST, '../public'); | ||
|
||
let win: BrowserWindow | null; | ||
// 🚧 Use ['ENV_NAME'] avoid vite:define plugin - [email protected] | ||
const VITE_DEV_SERVER_URL = process.env['VITE_DEV_SERVER_URL']; | ||
const APP_NAME = 'Doodles'; | ||
const iconPath = path.join(process.env.PUBLIC ?? './', 'doodles-icon.png'); | ||
|
||
function createWindow() { | ||
// Global variables for notification, main window, and tray. They | ||
// must be global to prevent garbage collection. | ||
export let notification: Notification; | ||
let win: BrowserWindow | null; | ||
let tray: Tray | null; | ||
|
||
/** | ||
* Creates the main application window. | ||
*/ | ||
const createWindow = () => { | ||
win = new BrowserWindow({ | ||
icon: path.join(process.env.PUBLIC ?? './', 'electron-vite.svg'), | ||
icon: iconPath, | ||
webPreferences: { | ||
preload: path.join(__dirname, 'preload.js'), | ||
nodeIntegration: true, | ||
webSecurity: false, | ||
}, | ||
transparent: true, | ||
frame: false, | ||
title: APP_NAME, | ||
}); | ||
setupWindow(win, VITE_DEV_SERVER_URL ?? ''); | ||
win.on('closed', () => (win = null)); | ||
|
||
// Setup the tray icon | ||
tray = new Tray(iconPath); | ||
setupTray(win, tray, APP_NAME); | ||
|
||
// Test active push message to Renderer-process. | ||
win.webContents.on('did-finish-load', () => { | ||
win?.webContents.send('main-process-message', new Date().toLocaleString()); | ||
// Setup notification with click handling | ||
notification = new Notification({ icon: iconPath }); | ||
notification.on('click', () => { | ||
if (!win?.isVisible() || win?.isMinimized()) { | ||
win?.show(); | ||
} | ||
}); | ||
|
||
if (VITE_DEV_SERVER_URL) { | ||
win.loadURL(VITE_DEV_SERVER_URL); | ||
} else { | ||
// win.loadFile('dist/index.html') | ||
win.loadFile(path.join(process.env.DIST ?? './', 'index.html')); | ||
} | ||
} | ||
// Register global shortcuts for the main window | ||
registerGlobalShortcuts(win); | ||
}; | ||
|
||
// Event handlers for app lifecycle and window focus/blur | ||
app.on('window-all-closed', () => { | ||
win = null; | ||
}); | ||
app.on('browser-window-focus', () => { | ||
win && win.webContents.send('focused'); | ||
}); | ||
app.on('browser-window-blur', () => { | ||
win && win.webContents.send('blurred'); | ||
}); | ||
// Handle 'close-event' IPC event to hide the window instead of closing | ||
ipcMain.handle('close-event', (e) => { | ||
e.preventDefault(); | ||
win && win.hide(); | ||
e.returnValue = false; | ||
}); | ||
|
||
app.whenReady().then(createWindow); | ||
// Application setup when app is ready | ||
app.whenReady().then(() => { | ||
// Register IPC handlers, create the main window. | ||
registerIPCHandlers(); | ||
createWindow(); | ||
// Bridge the get-sources IPC event, fired from the renderer process, | ||
// to the main process. This is necessary because desktopCapturer | ||
// is only available in the main process. | ||
ipcMain.handle('get-sources', () => { | ||
try { | ||
return desktopCapturer | ||
.getSources({ types: ['window', 'screen'] }) | ||
.then((sources) => | ||
sources.map((source) => ({ | ||
...source, | ||
thumbnail: { | ||
// We need to invoke the thumbnail image methods | ||
// in the main process since they can't be | ||
// passed through the context bridge. | ||
dataURL: source.thumbnail.toDataURL(), | ||
aspect: source.thumbnail.getAspectRatio(), | ||
}, | ||
})), | ||
); | ||
} catch (e) { | ||
return []; | ||
} | ||
}); | ||
}); |
Oops, something went wrong.