Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 49 additions & 7 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@ let mainWindow: BrowserWindow | null = null;
let spotlightWindow: BrowserWindow | null = null;
let settingsWindow: BrowserWindow | null = null;

// Default keyboard shortcuts
const DEFAULT_KEYBOARD_SHORTCUTS = {
spotlight: 'CommandOrControl+Shift+C',
newConversation: 'CommandOrControl+N',
toggleSidebar: 'CommandOrControl+B',
};

// Default settings
const DEFAULT_SETTINGS: SettingsSchema = {
spotlightKeybind: 'CommandOrControl+Shift+C',
spotlightPersistHistory: true,
keyboardShortcuts: DEFAULT_KEYBOARD_SHORTCUTS,
};

// Get settings with defaults
Expand All @@ -27,23 +35,57 @@ function saveSettings(settings: Partial<SettingsSchema>) {
store.set('settings', { ...current, ...settings });
}

// Register spotlight shortcut
function registerSpotlightShortcut() {
// Register all keyboard shortcuts
function registerKeyboardShortcuts() {
globalShortcut.unregisterAll();
const settings = getSettings();
const keybind = settings.spotlightKeybind || DEFAULT_SETTINGS.spotlightKeybind;
const shortcuts = settings.keyboardShortcuts || DEFAULT_KEYBOARD_SHORTCUTS;

// Register spotlight shortcut
const spotlightKey = shortcuts.spotlight || settings.spotlightKeybind || DEFAULT_KEYBOARD_SHORTCUTS.spotlight;
try {
globalShortcut.register(keybind, () => {
globalShortcut.register(spotlightKey, () => {
createSpotlightWindow();
});
} catch (e) {
// Fallback to default if custom keybind fails
console.error('Failed to register keybind:', keybind, e);
globalShortcut.register(DEFAULT_SETTINGS.spotlightKeybind, () => {
console.error('Failed to register spotlight keybind:', spotlightKey, e);
globalShortcut.register(DEFAULT_KEYBOARD_SHORTCUTS.spotlight, () => {
createSpotlightWindow();
});
Comment on lines +52 to 54
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the default spotlight shortcut registration also fails (which could happen if another application is using it), the application will throw an unhandled error. Consider wrapping this fallback in a try-catch as well:

try {
  globalShortcut.register(spotlightKey, () => {
    createSpotlightWindow();
  });
} catch (e) {
  console.error('Failed to register spotlight keybind:', spotlightKey, e);
  try {
    globalShortcut.register(DEFAULT_KEYBOARD_SHORTCUTS.spotlight, () => {
      createSpotlightWindow();
    });
  } catch (fallbackError) {
    console.error('Failed to register default spotlight keybind:', fallbackError);
  }
}
Suggested change
globalShortcut.register(DEFAULT_KEYBOARD_SHORTCUTS.spotlight, () => {
createSpotlightWindow();
});
try {
globalShortcut.register(DEFAULT_KEYBOARD_SHORTCUTS.spotlight, () => {
createSpotlightWindow();
});
} catch (fallbackError) {
console.error('Failed to register default spotlight keybind:', fallbackError);
}

Copilot uses AI. Check for mistakes.
}

// Register new conversation shortcut
const newConvKey = shortcuts.newConversation || DEFAULT_KEYBOARD_SHORTCUTS.newConversation;
try {
globalShortcut.register(newConvKey, () => {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('new-conversation');
mainWindow.show();
mainWindow.focus();
}
});
} catch (e) {
console.error('Failed to register new conversation keybind:', newConvKey, e);
}

// Register toggle sidebar shortcut
const sidebarKey = shortcuts.toggleSidebar || DEFAULT_KEYBOARD_SHORTCUTS.toggleSidebar;
try {
globalShortcut.register(sidebarKey, () => {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('toggle-sidebar');
mainWindow.show();
mainWindow.focus();
}
});
} catch (e) {
console.error('Failed to register toggle sidebar keybind:', sidebarKey, e);
}
}

// Legacy function for compatibility
function registerSpotlightShortcut() {
registerKeyboardShortcuts();
}

// Create spotlight search window
Expand Down
10 changes: 9 additions & 1 deletion src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,17 @@ contextBridge.exposeInMainWorld('claude', {
ipcRenderer.on('toggle-search-modal', () => callback());
},

// Global keyboard shortcuts
onNewConversation: (callback: () => void) => {
ipcRenderer.on('new-conversation', () => callback());
},
onToggleSidebar: (callback: () => void) => {
ipcRenderer.on('toggle-sidebar', () => callback());
},

// Settings functions
openSettings: () => ipcRenderer.invoke('open-settings'),
getSettings: () => ipcRenderer.invoke('get-settings'),
saveSettings: (settings: { spotlightKeybind?: string; spotlightPersistHistory?: boolean }) =>
saveSettings: (settings: { spotlightKeybind?: string; spotlightPersistHistory?: boolean; keyboardShortcuts?: { spotlight?: string; newConversation?: string; toggleSidebar?: string } }) =>
ipcRenderer.invoke('save-settings', settings),
Comment on lines +125 to 126
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inline type definition for keyboardShortcuts in the saveSettings parameter makes all nested properties optional, which differs from the KeyboardShortcuts interface in src/types/index.ts where all properties are required. This inconsistency could lead to confusion.

Consider using a proper Partial type or importing the actual type:

saveSettings: (settings: { 
  spotlightKeybind?: string; 
  spotlightPersistHistory?: boolean; 
  keyboardShortcuts?: Partial<KeyboardShortcuts>
}) => ipcRenderer.invoke('save-settings', settings),

Or better yet, import and use Partial<SettingsSchema> to match what the main process expects.

Copilot uses AI. Check for mistakes.
});
11 changes: 11 additions & 0 deletions src/renderer/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ declare global {
onMessageToolResult: (callback: (data: ToolResultData) => void) => void;
onMessageStream: (callback: (data: StreamData) => void) => void;
onMessageComplete: (callback: (data: CompleteData) => void) => void;
onNewConversation: (callback: () => void) => void;
onToggleSidebar: (callback: () => void) => void;
};
}
}
Expand Down Expand Up @@ -1576,6 +1578,15 @@ async function init() {
if (inputEl) inputEl.focus();
}
});

// Global keyboard shortcut handlers
window.claude.onNewConversation(() => {
newChat();
});

window.claude.onToggleSidebar(() => {
toggleSidebar();
});
}

// Set up event listeners
Expand Down
Loading