Add cross-platform process scanning that detects running games and apps, then broadcasts them as Rich Presence activities via the existing Phase 1 pipeline (activityStore -> WS -> other users). - games.json dictionary with 26 entries (games, Spotify, VLC, OBS) - activityDetector module: polls OS process list every 15s via execFile, matches against dictionary, emits IPC on state change only - IPC bridge in main.ts/preload.ts with cleanup on quit - Frontend activityBridge subscribes to IPC and feeds activityStore - Supports Windows (tasklist CSV), macOS (ps -c), Linux (ps)
80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
import { contextBridge, ipcRenderer } from 'electron';
|
|
|
|
contextBridge.exposeInMainWorld('backspace', {
|
|
// Platform info
|
|
platform: process.platform,
|
|
|
|
// Window controls
|
|
minimize: () => {
|
|
ipcRenderer.send('minimize-window');
|
|
},
|
|
maximize: () => {
|
|
ipcRenderer.send('maximize-window');
|
|
},
|
|
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: { message: string; releaseUrl: string }) => void) => {
|
|
ipcRenderer.on('update-error', (_event, error) => callback(error));
|
|
},
|
|
installUpdate: () => {
|
|
ipcRenderer.send('install-update');
|
|
},
|
|
checkForUpdates: () => {
|
|
ipcRenderer.send('check-for-updates');
|
|
},
|
|
getVersion: () => ipcRenderer.invoke('get-app-version'),
|
|
|
|
// 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));
|
|
},
|
|
|
|
// Screen share picker coordination
|
|
onScreenShareSources: (callback: (sources: unknown[]) => void) => {
|
|
ipcRenderer.on('screen-share-sources', (_event, sources) => callback(sources));
|
|
},
|
|
selectScreenSource: (sourceId: string | null, shareAudio?: boolean) => {
|
|
ipcRenderer.send('screen-share-selected', sourceId, shareAudio ?? true);
|
|
},
|
|
|
|
// Instance URL management
|
|
getInstanceUrl: () => ipcRenderer.invoke('get-instance-url'),
|
|
setInstanceUrl: (url: string) => ipcRenderer.invoke('set-instance-url', url),
|
|
clearInstanceUrl: () => ipcRenderer.invoke('clear-instance-url'),
|
|
|
|
// Auto-launch settings
|
|
getAutoLaunchSettings: () => ipcRenderer.invoke('get-auto-launch-settings'),
|
|
setAutoLaunchSettings: (settings: { openAtLogin?: boolean; startMinimized?: boolean }) =>
|
|
ipcRenderer.invoke('set-auto-launch-settings', settings),
|
|
|
|
// Activity detection (game/app process scanning)
|
|
onActivityDetected: (callback: (activity: unknown) => void) => {
|
|
const handler = (_event: Electron.IpcRendererEvent, activity: unknown) => callback(activity);
|
|
ipcRenderer.on('activity-detected', handler);
|
|
return () => { ipcRenderer.removeListener('activity-detected', handler); };
|
|
},
|
|
getCurrentActivity: () => ipcRenderer.invoke('get-current-activity'),
|
|
});
|