Implement membership notifications and deep-link handling for Electron desktop app #246

Merged
talksik merged 11 commits from free-monkey into main 2026-06-09 15:04:19 +00:00
2 changed files with 14 additions and 50 deletions
Showing only changes of commit 45918378a8 - Show all commits
+5
View File
@@ -0,0 +1,5 @@
# Notes
## CORS for desktop app
In dev: each renderer process has it's own localhost port. The renderer process passes this in the `Origin` header for requests, and expects appropriate ACAO headers in the response.
coderabbitai[bot] commented 2026-06-09 00:34:59 +00:00 (Migrated from github.com)
Review

⚠️ Potential issue | 🟡 Minor | Quick win

Fix possessive pronoun.

Change "it's own" to "its own" (possessive, not contraction).

📝 Proposed fix
-In dev: each renderer process has it's own localhost port. The renderer process passes this in the `Origin` header for requests, and expects appropriate ACAO headers in the response.
+In dev: each renderer process has its own localhost port. The renderer process passes this in the `Origin` header for requests, and expects appropriate ACAO headers in the response.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

In dev: each renderer process has its own localhost port. The renderer process passes this in the `Origin` header for requests, and expects appropriate ACAO headers in the response.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@js/desktop/README.md` at line 3, Fix the possessive pronoun in the README
sentence that reads "In dev: each renderer process has it's own localhost port."
— change "it's" to the possessive "its" so the sentence becomes "In dev: each
renderer process has its own localhost port." Update the string in the README
where that exact sentence appears.
_⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Fix possessive pronoun.** Change "it's own" to "its own" (possessive, not contraction). <details> <summary>📝 Proposed fix</summary> ```diff -In dev: each renderer process has it's own localhost port. The renderer process passes this in the `Origin` header for requests, and expects appropriate ACAO headers in the response. +In dev: each renderer process has its own localhost port. The renderer process passes this in the `Origin` header for requests, and expects appropriate ACAO headers in the response. ``` </details> <!-- suggestion_start --> <details> <summary>📝 Committable suggestion</summary> > ‼️ **IMPORTANT** > Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements. ```suggestion In dev: each renderer process has its own localhost port. The renderer process passes this in the `Origin` header for requests, and expects appropriate ACAO headers in the response. ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@js/desktop/README.md` at line 3, Fix the possessive pronoun in the README sentence that reads "In dev: each renderer process has it's own localhost port." — change "it's" to the possessive "its" so the sentence becomes "In dev: each renderer process has its own localhost port." Update the string in the README where that exact sentence appears. ``` </details> <!-- fingerprinting:phantom:poseidon:puma --> <!-- cr-comment:v1:a04e62ddae6a345cfe823d8a --> <!-- This is an auto-generated comment by CodeRabbit -->
In packaged app: the renderer process does not include `Origin` header, so expects no extra ACAO headers from the server, otherwise the client would fail to accept responses.
+9 -50
View File
@@ -26,16 +26,11 @@ if (app.isPackaged) {
});
}
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
// Handle creating/removing shortcuts on Windows when installing/updating/uninstalling.
if (started) {
app.quit();
}
// Set the dock icon for development mode on macOS.
if (process.platform === 'darwin' && !app.isPackaged) {
app.dock?.setIcon(path.join(__dirname, '../../assets/icon.png'));
}
// In dev, `LLINK_PROFILE=foo yarn start` spins up a second instance with an
// isolated userData dir so it can coexist with the default one (separate auth,
// cookies, leveldb locks).
@@ -44,12 +39,10 @@ if (devProfile) {
app.setPath('userData', `${app.getPath('userData')}-${devProfile}`);
}
// Single-instance lock: on Windows/Linux, clicking a llink:// URL launches a new
// process. The lock makes the losing instance quit and fires `second-instance` on
// the primary, so we focus the existing window instead of spawning a duplicate.
// macOS uses `open-url` instead and doesn't need this, but the lock is harmless.
// Skip the lock when running a named dev profile — those instances are meant to
// run alongside the default one.
// NOTE: on Windows/Linux, clicking a llink:// URL launches a new process. On macOS,
// `open-url` focuses existing instance of an application.
// Prevent running multiple instances of app, except when in development
if (!devProfile && !app.requestSingleInstanceLock()) {
app.quit();
}
@@ -88,10 +81,7 @@ function hardenWindow(win: BrowserWindow) {
const isZoom =
cmdOrCtrl && (key === '=' || key === '+' || key === '-' || key === '0');
if (app.isPackaged && (isDevtools || isReload)) {
event.preventDefault();
}
if (isZoom) {
if (app.isPackaged && (isDevtools || isReload || isZoom)) {
event.preventDefault();
}
});
@@ -132,6 +122,9 @@ const createWindow = () => {
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
backgroundThrottling: false,
webSecurity: true,
contextIsolation: true,
nodeIntegration: false,
},
});
hardenWindow(mainWindow);
@@ -433,38 +426,7 @@ ipcMain.on(
},
);
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
// Allow CORS for API requests from the renderer process.
// The server doesn't handle OPTIONS preflight, so we intercept at the
// Electron network layer: inject CORS headers and return 200 for preflight.
session.defaultSession.webRequest.onHeadersReceived(
{ urls: [`${appConfig.orionUrl}/*`, 'https://storage.googleapis.com/*'] },
(details, callback) => {
const headers = { ...details.responseHeaders };
headers['access-control-allow-origin'] = ['*'];
headers['access-control-allow-headers'] = [
'Content-Type',
'Authorization',
];
headers['access-control-allow-methods'] = [
'GET',
'POST',
'PUT',
'DELETE',
'OPTIONS',
];
if (details.method === 'OPTIONS') {
callback({ responseHeaders: headers, statusLine: 'HTTP/1.1 200 OK' });
} else {
callback({ responseHeaders: headers });
}
},
);
createWindow();
createAutoplayWindow();
});
@@ -503,6 +465,3 @@ app.on('open-url', (event) => {
app.on('second-instance', () => {
focusMainWindow();
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.