mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-04 05:12:38 +02:00
Wire General Assist and screen capture through Electron IPC
This commit is contained in:
parent
7097f542fb
commit
b0810b4d47
7 changed files with 40 additions and 49 deletions
|
|
@ -11,12 +11,9 @@ export const IPC_CHANNELS = {
|
|||
REQUEST_ACCESSIBILITY: 'request-accessibility',
|
||||
REQUEST_SCREEN_RECORDING: 'request-screen-recording',
|
||||
RESTART_APP: 'restart-app',
|
||||
// Autocomplete
|
||||
AUTOCOMPLETE_CONTEXT: 'autocomplete-context',
|
||||
ACCEPT_SUGGESTION: 'accept-suggestion',
|
||||
DISMISS_SUGGESTION: 'dismiss-suggestion',
|
||||
SET_AUTOCOMPLETE_ENABLED: 'set-autocomplete-enabled',
|
||||
GET_AUTOCOMPLETE_ENABLED: 'get-autocomplete-enabled',
|
||||
SCREEN_REGION_SUBMIT: 'screen-region:submit',
|
||||
SCREEN_REGION_CANCEL: 'screen-region:cancel',
|
||||
CHAT_SCREEN_CAPTURE: 'chat:screen-capture',
|
||||
// Folder sync channels
|
||||
FOLDER_SYNC_SELECT_FOLDER: 'folder-sync:select-folder',
|
||||
FOLDER_SYNC_ADD_FOLDER: 'folder-sync:add-folder',
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import { getShortcuts, setShortcuts, type ShortcutConfig } from '../modules/shor
|
|||
import { getAutoLaunchState, setAutoLaunch } from '../modules/auto-launch';
|
||||
import { getActiveSearchSpaceId, setActiveSearchSpaceId } from '../modules/active-search-space';
|
||||
import { reregisterQuickAsk } from '../modules/quick-ask';
|
||||
import { reregisterAutocomplete } from '../modules/autocomplete';
|
||||
import { reregisterGeneralAssist } from '../modules/tray';
|
||||
import {
|
||||
getDistinctId,
|
||||
|
|
@ -184,7 +183,6 @@ export function registerIpcHandlers(): void {
|
|||
const updated = await setShortcuts(config);
|
||||
if (config.generalAssist) await reregisterGeneralAssist();
|
||||
if (config.quickAsk) await reregisterQuickAsk();
|
||||
if (config.autocomplete) await reregisterAutocomplete();
|
||||
trackEvent('desktop_shortcut_updated', {
|
||||
keys: Object.keys(config),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { setupDeepLinks, handlePendingDeepLink, hasPendingDeepLink } from './mod
|
|||
import { setupAutoUpdater } from './modules/auto-updater';
|
||||
import { setupMenu } from './modules/menu';
|
||||
import { registerQuickAsk, unregisterQuickAsk } from './modules/quick-ask';
|
||||
import { registerAutocomplete, unregisterAutocomplete } from './modules/autocomplete';
|
||||
import { registerFolderWatcher, unregisterFolderWatcher } from './modules/folder-watcher';
|
||||
import { registerIpcHandlers } from './ipc/handlers';
|
||||
import { createTray, destroyTray } from './modules/tray';
|
||||
|
|
@ -60,7 +59,6 @@ app.whenReady().then(async () => {
|
|||
}
|
||||
|
||||
await registerQuickAsk();
|
||||
await registerAutocomplete();
|
||||
registerFolderWatcher();
|
||||
setupAutoUpdater();
|
||||
|
||||
|
|
@ -94,7 +92,6 @@ app.on('will-quit', async (e) => {
|
|||
didCleanup = true;
|
||||
e.preventDefault();
|
||||
unregisterQuickAsk();
|
||||
unregisterAutocomplete();
|
||||
unregisterFolderWatcher();
|
||||
destroyTray();
|
||||
await shutdownAnalytics();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
export interface ShortcutConfig {
|
||||
generalAssist: string;
|
||||
quickAsk: string;
|
||||
autocomplete: string;
|
||||
}
|
||||
|
||||
const DEFAULTS: ShortcutConfig = {
|
||||
generalAssist: 'CommandOrControl+Shift+S',
|
||||
quickAsk: 'CommandOrControl+Alt+S',
|
||||
autocomplete: 'CommandOrControl+Shift+Space',
|
||||
generalAssist: 'Alt+Shift+G',
|
||||
quickAsk: 'Alt+Shift+Q',
|
||||
};
|
||||
|
||||
const STORE_KEY = 'shortcuts';
|
||||
|
|
@ -27,14 +25,16 @@ async function getStore() {
|
|||
|
||||
export async function getShortcuts(): Promise<ShortcutConfig> {
|
||||
const s = await getStore();
|
||||
const stored = s.get(STORE_KEY) as Partial<ShortcutConfig> | undefined;
|
||||
return { ...DEFAULTS, ...stored };
|
||||
const raw = (s.get(STORE_KEY) as Record<string, string> | undefined) ?? {};
|
||||
const { autocomplete: _drop, ...rest } = raw;
|
||||
return { ...DEFAULTS, ...rest };
|
||||
}
|
||||
|
||||
export async function setShortcuts(config: Partial<ShortcutConfig>): Promise<ShortcutConfig> {
|
||||
const s = await getStore();
|
||||
const current = (s.get(STORE_KEY) as ShortcutConfig) ?? DEFAULTS;
|
||||
const merged = { ...current, ...config };
|
||||
const raw = (s.get(STORE_KEY) as Record<string, string> | undefined) ?? {};
|
||||
const { autocomplete: _drop, ...current } = raw;
|
||||
const merged = { ...DEFAULTS, ...current, ...config };
|
||||
s.set(STORE_KEY, merged);
|
||||
return merged;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import { app, globalShortcut, Menu, nativeImage, Tray } from 'electron';
|
||||
import { app, globalShortcut, Menu, nativeImage, Tray, type NativeImage } from 'electron';
|
||||
import path from 'path';
|
||||
import { getMainWindow, createMainWindow } from './window';
|
||||
import { runGeneralAssistShortcut } from './general-assist';
|
||||
import { showMainWindow } from './window';
|
||||
import { getShortcuts } from './shortcuts';
|
||||
import { trackEvent } from './analytics';
|
||||
|
||||
let tray: Tray | null = null;
|
||||
let currentShortcut: string | null = null;
|
||||
|
||||
function getTrayIcon(): nativeImage {
|
||||
function getTrayIcon(): NativeImage {
|
||||
const iconName = process.platform === 'win32' ? 'icon.ico' : 'icon.png';
|
||||
const iconPath = app.isPackaged
|
||||
? path.join(process.resourcesPath, 'assets', iconName)
|
||||
|
|
@ -16,18 +17,6 @@ function getTrayIcon(): nativeImage {
|
|||
return img.resize({ width: 16, height: 16 });
|
||||
}
|
||||
|
||||
function showMainWindow(source: 'tray_click' | 'tray_menu' | 'shortcut' = 'tray_click'): void {
|
||||
const existing = getMainWindow();
|
||||
const reopened = !existing || existing.isDestroyed();
|
||||
if (reopened) {
|
||||
createMainWindow('/dashboard');
|
||||
} else {
|
||||
existing.show();
|
||||
existing.focus();
|
||||
}
|
||||
trackEvent('desktop_main_window_shown', { source, reopened });
|
||||
}
|
||||
|
||||
function registerShortcut(accelerator: string): void {
|
||||
if (currentShortcut) {
|
||||
globalShortcut.unregister(currentShortcut);
|
||||
|
|
@ -35,11 +24,14 @@ function registerShortcut(accelerator: string): void {
|
|||
}
|
||||
if (!accelerator) return;
|
||||
try {
|
||||
const ok = globalShortcut.register(accelerator, () => showMainWindow('shortcut'));
|
||||
const ok = globalShortcut.register(accelerator, () => {
|
||||
void runGeneralAssistShortcut();
|
||||
});
|
||||
if (ok) {
|
||||
currentShortcut = accelerator;
|
||||
console.log(`[general-assist] Register ${accelerator}: OK`);
|
||||
} else {
|
||||
console.warn(`[tray] Failed to register General Assist shortcut: ${accelerator}`);
|
||||
console.warn(`[general-assist] Register ${accelerator}: FAILED (OS or another app may own this chord)`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[tray] Error registering General Assist shortcut:`, err);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { app, BrowserWindow, shell, session } from 'electron';
|
||||
import path from 'path';
|
||||
import { trackEvent } from './analytics';
|
||||
import { showErrorDialog } from './errors';
|
||||
import { getServerPort } from './server';
|
||||
import { setActiveSearchSpaceId } from './active-search-space';
|
||||
|
|
@ -93,3 +94,15 @@ export function createMainWindow(initialPath = '/dashboard'): BrowserWindow {
|
|||
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
export function showMainWindow(source: 'tray_click' | 'tray_menu' | 'shortcut' = 'tray_click'): void {
|
||||
const existing = getMainWindow();
|
||||
const reopened = !existing || existing.isDestroyed();
|
||||
if (reopened) {
|
||||
createMainWindow('/dashboard');
|
||||
} else {
|
||||
existing.show();
|
||||
existing.focus();
|
||||
}
|
||||
trackEvent('desktop_main_window_shown', { source, reopened });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
|||
ipcRenderer.removeListener(IPC_CHANNELS.DEEP_LINK, listener);
|
||||
};
|
||||
},
|
||||
onChatScreenCapture: (callback: (dataUrl: string) => void) => {
|
||||
const listener = (_event: unknown, dataUrl: string) => callback(dataUrl);
|
||||
ipcRenderer.on(IPC_CHANNELS.CHAT_SCREEN_CAPTURE, listener);
|
||||
return () => {
|
||||
ipcRenderer.removeListener(IPC_CHANNELS.CHAT_SCREEN_CAPTURE, listener);
|
||||
};
|
||||
},
|
||||
getQuickAskText: () => ipcRenderer.invoke(IPC_CHANNELS.QUICK_ASK_TEXT),
|
||||
setQuickAskMode: (mode: string) => ipcRenderer.invoke(IPC_CHANNELS.SET_QUICK_ASK_MODE, mode),
|
||||
getQuickAskMode: () => ipcRenderer.invoke(IPC_CHANNELS.GET_QUICK_ASK_MODE),
|
||||
|
|
@ -26,19 +33,6 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
|||
requestAccessibility: () => ipcRenderer.invoke(IPC_CHANNELS.REQUEST_ACCESSIBILITY),
|
||||
requestScreenRecording: () => ipcRenderer.invoke(IPC_CHANNELS.REQUEST_SCREEN_RECORDING),
|
||||
restartApp: () => ipcRenderer.invoke(IPC_CHANNELS.RESTART_APP),
|
||||
// Autocomplete
|
||||
onAutocompleteContext: (callback: (data: { screenshot: string; searchSpaceId?: string; appName?: string; windowTitle?: string }) => void) => {
|
||||
const listener = (_event: unknown, data: { screenshot: string; searchSpaceId?: string; appName?: string; windowTitle?: string }) => callback(data);
|
||||
ipcRenderer.on(IPC_CHANNELS.AUTOCOMPLETE_CONTEXT, listener);
|
||||
return () => {
|
||||
ipcRenderer.removeListener(IPC_CHANNELS.AUTOCOMPLETE_CONTEXT, listener);
|
||||
};
|
||||
},
|
||||
acceptSuggestion: (text: string) => ipcRenderer.invoke(IPC_CHANNELS.ACCEPT_SUGGESTION, text),
|
||||
dismissSuggestion: () => ipcRenderer.invoke(IPC_CHANNELS.DISMISS_SUGGESTION),
|
||||
setAutocompleteEnabled: (enabled: boolean) => ipcRenderer.invoke(IPC_CHANNELS.SET_AUTOCOMPLETE_ENABLED, enabled),
|
||||
getAutocompleteEnabled: () => ipcRenderer.invoke(IPC_CHANNELS.GET_AUTOCOMPLETE_ENABLED),
|
||||
|
||||
// Folder sync
|
||||
selectFolder: () => ipcRenderer.invoke(IPC_CHANNELS.FOLDER_SYNC_SELECT_FOLDER),
|
||||
addWatchedFolder: (config: any) => ipcRenderer.invoke(IPC_CHANNELS.FOLDER_SYNC_ADD_FOLDER, config),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue