From 878a1e6be052ba98a67a6974bbdf5bef08905511 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 18:03:03 +0530 Subject: [PATCH 1/2] chore: auto update in linux electron base tested --- src-electron/main.js | 39 +++++++++++++++++++++++++++++++++++++++ src-electron/preload.js | 8 +++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src-electron/main.js b/src-electron/main.js index 386314bf..086ddc91 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -225,6 +225,45 @@ ipcMain.on('send-health-metric', (event, payload) => { } }); +/** + * App updater IPC handlers + * These provide low-level APIs for the update-electron.js extension in Phoenix + */ + +// Get app version from config +ipcMain.handle('get-app-version', (event) => { + assertTrusted(event); + return version; +}); + +// Check if app is packaged (production build) +ipcMain.handle('is-packaged', (event) => { + assertTrusted(event); + return app.isPackaged; +}); + +// Get executable path (path to the AppImage on Linux) +ipcMain.handle('get-executable-path', (event) => { + assertTrusted(event); + return process.execPath; +}); + +// Run a shell command for update script execution +ipcMain.handle('run-shell-command', async (event, command) => { + assertTrusted(event); + const { exec } = require('child_process'); + return new Promise((resolve) => { + exec(command, { shell: '/bin/bash' }, (error, stdout, stderr) => { + if (error) { + console.error('Shell command error:', error); + resolve({ code: error.code || 1, stdout, stderr }); + } else { + resolve({ code: 0, stdout, stderr }); + } + }); + }); +}); + // Handle quit request from renderer app.on('quit-requested', (exitCode) => { gracefulShutdown(exitCode); diff --git a/src-electron/preload.js b/src-electron/preload.js index 6ef2ef49..d73aeb5e 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -160,5 +160,11 @@ contextBridge.exposeInMainWorld('electronAPI', { // Health metrics for Google Analytics (sends to hidden metrics window) sendHealthMetric: (payload) => ipcRenderer.send('send-health-metric', payload), - onHealthMetric: (callback) => ipcRenderer.on('health-metric', (_event, payload) => callback(payload)) + onHealthMetric: (callback) => ipcRenderer.on('health-metric', (_event, payload) => callback(payload)), + + // App updater APIs - just expose primitives, logic is in update-electron.js + getAppVersion: () => ipcRenderer.invoke('get-app-version'), + isPackaged: () => ipcRenderer.invoke('is-packaged'), + getExecutablePath: () => ipcRenderer.invoke('get-executable-path'), + runShellCommand: (command) => ipcRenderer.invoke('run-shell-command', command) }); From 99a1fa6e913617478d97600c213d82d01839fa35 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 18:55:03 +0530 Subject: [PATCH 2/2] feat: electron supporting apis for auto update in linux --- src-electron/main.js | 26 ++++++++++++-------------- src-electron/package.json | 2 +- src-electron/preload.js | 8 ++++++-- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src-electron/main.js b/src-electron/main.js index 086ddc91..b548c491 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -78,9 +78,12 @@ function getSrcNodePath() { } // In-memory key-value store shared across all windows (mirrors Tauri's put_item/get_all_items) -// Used for multi-window storage synchronization +// Used for multi-window storage synchronization - ONLY for use by storage.js const sharedStorageMap = new Map(); +// Update scheduled flag - shared across all windows for app updater +let updateScheduled = false; + // Hidden metrics window for Google Analytics let metricsWindow = null; @@ -248,20 +251,15 @@ ipcMain.handle('get-executable-path', (event) => { return process.execPath; }); -// Run a shell command for update script execution -ipcMain.handle('run-shell-command', async (event, command) => { +// Update scheduled state - shared across windows for multi-window update persistence +ipcMain.handle('set-update-scheduled', (event, scheduled) => { assertTrusted(event); - const { exec } = require('child_process'); - return new Promise((resolve) => { - exec(command, { shell: '/bin/bash' }, (error, stdout, stderr) => { - if (error) { - console.error('Shell command error:', error); - resolve({ code: error.code || 1, stdout, stderr }); - } else { - resolve({ code: 0, stdout, stderr }); - } - }); - }); + updateScheduled = scheduled; +}); + +ipcMain.handle('get-update-scheduled', (event) => { + assertTrusted(event); + return updateScheduled; }); // Handle quit request from renderer diff --git a/src-electron/package.json b/src-electron/package.json index 9b312c13..6d3a0c57 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -22,4 +22,4 @@ "electron": "^40.0.0", "electron-builder": "^24.13.3" } -} \ No newline at end of file +} diff --git a/src-electron/preload.js b/src-electron/preload.js index d73aeb5e..0a2a9a64 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -79,7 +79,10 @@ contextBridge.exposeInMainWorld('electronAPI', { // Set zoom factor on the webview (mirrors Tauri's zoom_window) zoomWindow: (scaleFactor) => ipcRenderer.invoke('zoom-window', scaleFactor), - // In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) + /** + * In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) + * WARNING: These APIs are ONLY for use by storage.js - do not use elsewhere + */ putItem: (key, value) => ipcRenderer.invoke('put-item', key, value), getAllItems: () => ipcRenderer.invoke('get-all-items'), @@ -166,5 +169,6 @@ contextBridge.exposeInMainWorld('electronAPI', { getAppVersion: () => ipcRenderer.invoke('get-app-version'), isPackaged: () => ipcRenderer.invoke('is-packaged'), getExecutablePath: () => ipcRenderer.invoke('get-executable-path'), - runShellCommand: (command) => ipcRenderer.invoke('run-shell-command', command) + setUpdateScheduled: (scheduled) => ipcRenderer.invoke('set-update-scheduled', scheduled), + getUpdateScheduled: () => ipcRenderer.invoke('get-update-scheduled') });