feat: Electron desktop app — hardening, IPC bridge, and dev launch fixes
- Dev/prod URL auto-detection (Vite 5173 in dev, server 3000 in prod) - Typed IPC bridge via preload (notifications, badge, window controls, updates, deep links) - Native OS notifications via NotificationController with window focus suppression - Auto-update via electron-updater with UpdateToast UI - Deep linking (backspace:// protocol) for macOS and Windows/Linux - Window state persistence (position, size, maximize across restarts) - Tray icon with graceful fallback when icon asset missing - Suppress PWA service worker polling/reloads inside Electron - Platform detection layer (isElectron, getElectronAPI) - Root workspace scripts (dev:desktop, build:desktop) - Document BACKSPACE_URL and BACKSPACE_UPDATE_URL env vars
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
import { contextBridge, ipcRenderer } from 'electron';
|
||||
|
||||
contextBridge.exposeInMainWorld('backspace', {
|
||||
// Platform info
|
||||
platform: process.platform,
|
||||
showNotification: (title: string, body: string) => {
|
||||
ipcRenderer.send('show-notification', { title, body });
|
||||
},
|
||||
setBadgeCount: (count: number) => {
|
||||
ipcRenderer.send('set-badge-count', count);
|
||||
},
|
||||
|
||||
// Window controls
|
||||
minimize: () => {
|
||||
ipcRenderer.send('minimize-window');
|
||||
},
|
||||
@@ -17,4 +14,39 @@ contextBridge.exposeInMainWorld('backspace', {
|
||||
close: () => {
|
||||
ipcRenderer.send('close-window');
|
||||
},
|
||||
|
||||
// Notifications & badge
|
||||
showNotification: (title: string, body: string) => {
|
||||
ipcRenderer.send('show-notification', { title, body });
|
||||
},
|
||||
setBadgeCount: (count: number) => {
|
||||
ipcRenderer.send('set-badge-count', count);
|
||||
},
|
||||
|
||||
// Auto-update
|
||||
onUpdateAvailable: (callback: (info: { version: string }) => void) => {
|
||||
ipcRenderer.on('update-available', (_event, info) => callback(info));
|
||||
},
|
||||
onUpdateDownloaded: (callback: (info: { version: string }) => void) => {
|
||||
ipcRenderer.on('update-downloaded', (_event, info) => callback(info));
|
||||
},
|
||||
onUpdateError: (callback: (error: string) => void) => {
|
||||
ipcRenderer.on('update-error', (_event, error) => callback(error));
|
||||
},
|
||||
installUpdate: () => {
|
||||
ipcRenderer.send('install-update');
|
||||
},
|
||||
checkForUpdates: () => {
|
||||
ipcRenderer.send('check-for-updates');
|
||||
},
|
||||
|
||||
// Window focus
|
||||
onWindowFocusChange: (callback: (focused: boolean) => void) => {
|
||||
ipcRenderer.on('window-focus-changed', (_event, focused) => callback(focused));
|
||||
},
|
||||
|
||||
// Deep linking
|
||||
onDeepLink: (callback: (url: string) => void) => {
|
||||
ipcRenderer.on('deep-link', (_event, url) => callback(url));
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user