Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b014196
feat: normal app mode (dock visible, no auto-hide, draggable)
grimmerk Apr 6, 2026
06efb1b
fix: normal mode show on startup, shortcut only focus, conditional drag
grimmerk Apr 6, 2026
007b867
fix: re-center on menu bar switch, hide toggle in normal mode
grimmerk Apr 6, 2026
b526e3c
feat: mode indicator in title bar, banner on mode change, dock activate
grimmerk Apr 6, 2026
e27d5e4
fix: shortcut on right side of title bar, banner only on mode switch
grimmerk Apr 6, 2026
7afdb2c
fix: sync shortcut display on save/reset
grimmerk Apr 6, 2026
e02a9ea
style: add Dev Hub sub-title + mode indicator below
grimmerk Apr 6, 2026
b225e22
style: reduce title bar padding from 10px to 8px
grimmerk Apr 6, 2026
68c501f
feat: Settings UI with tabs (General / Sessions / Shortcuts)
grimmerk Apr 6, 2026
a771beb
style: reorder settings, add hints, rename Terminal.app
grimmerk Apr 6, 2026
b28fcd6
chore: bump version to 1.0.70
grimmerk Apr 6, 2026
5bd9bb9
fix: remove duplicate Working Dir, fix Launch Mode hint
grimmerk Apr 6, 2026
1a876e1
fix: remove Launch Terminal hint, rename Launch Mode to Open In
grimmerk Apr 6, 2026
f0f9f57
fix: add hint to Launch Terminal, simplify Open In label
grimmerk Apr 6, 2026
1dde984
style: indent Open In as sub-item of Launch Terminal
grimmerk Apr 6, 2026
36a9694
style: use arrow prefix for Open In sub-item
grimmerk Apr 6, 2026
aa5d8a0
docs: add App Mode comparison table to README
grimmerk Apr 6, 2026
25e456b
fix: address review — banner timeout, dock await, startup timing, sho…
grimmerk Apr 6, 2026
50d4bf0
fix: guard shortcut cleanup on tab re-click, show after bootstrap
grimmerk Apr 6, 2026
5a16167
docs: update Settings paths to match tabbed UI
grimmerk Apr 6, 2026
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
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## 1.0.70

- Feat: Normal App mode — window stays visible, shows in Dock, draggable
- Toggle in Settings: Normal App (default for new users) / Menu Bar
- Instant switching, no restart needed
- `Cmd+Ctrl+R` toggles show/hide in both modes
- Title bar shows "Dev Hub" sub-title + mode indicator + shortcut key
- Banner on first launch and mode switch (auto-dismiss)
- Clicking Dock icon shows hidden window
- Feat: Settings UI redesigned with tabs (General / Sessions / Shortcuts)
- All settings visible without scrolling
- No more content changing based on active main tab
- Hints on context-specific settings (projects/sessions/tray)
- Style: Terminal renamed to Terminal.app in Launch Terminal dropdown
- Style: title bar padding reduced for tighter layout

## 1.0.69

- Feat: adaptive VS Code resume via IDE lock file polling
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "CodeV",
"productName": "CodeV",
"version": "1.0.69",
"version": "1.0.70",
"description": "Quick switcher for VS Code, Cursor, and Claude Code sessions",
"repository": {
"type": "git",
Expand Down
6 changes: 6 additions & 0 deletions src/electron-api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ interface IElectronAPI {
getUpdateStatus: () => Promise<{ status: string; releaseName?: string; error?: string } | null>;
onUpdateStatus: (callback: IpcCallback) => void;

// App mode
getAppMode: () => Promise<string>;
setAppMode: (mode: string) => void;
onAppModeChanged: (callback: IpcCallback) => void;
onShortcutsUpdated: (callback: IpcCallback) => void;

// Session terminal settings
getSessionTerminalApp: () => Promise<string>;
setSessionTerminalApp: (app: string) => void;
Expand Down
69 changes: 61 additions & 8 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ let serverProcess: any;
const WIN_WIDTH = 800;
const WIN_HEIGHT = 600;

// App mode: 'normal' (dock visible, no auto-hide) or 'menubar' (hidden dock, auto-hide on blur)
let appMode: 'normal' | 'menubar' = 'normal'; // default to normal for new users

const getWindowPosition = () => {
const primaryDisplay = screen.getPrimaryDisplay();
const { width, height } = primaryDisplay.workAreaSize;
Expand All @@ -95,19 +98,23 @@ const getWindowPosition = () => {
// NOTE: setVisibleOnAllWorkspaces is needed ?
const showSwitcherWindow = () => {
let window = getSwitcherWindow();

if (!window) {
// Recreate window if it has been destroyed
switcherWindow = createSwitcherWindow();
window = switcherWindow;
}

const position = getWindowPosition();
window.setPosition(position.x, position.y, false);

if (appMode === 'menubar') {
// Menu bar mode: always center on screen
const position = getWindowPosition();
window.setPosition(position.x, position.y, false);
}
if (window.isMinimized()) {
window.restore();
}
window.show();
// mainWindow.setVisibleOnAllWorkspaces(true);
window.focus();
// mainWindow.setVisibleOnAllWorkspaces(false);
};

const showAIAssistantWindow = () => {
Expand Down Expand Up @@ -258,6 +265,8 @@ const hideSwitcherWindow = () => {
};

const onBlur = (event: any) => {
// Normal mode: don't auto-hide on blur
if (appMode === 'normal') return;
hideSwitcherWindow();
};

Expand Down Expand Up @@ -506,6 +515,11 @@ app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
switcherWindow = createSwitcherWindow();
}
// Normal mode: clicking Dock icon shows hidden window
const window = getSwitcherWindow();
if (window && !window.isVisible()) {
showSwitcherWindow();
}
});

/** https://www.electronjs.org/docs/latest/tutorial/ipc */
Expand Down Expand Up @@ -1016,6 +1030,12 @@ const trayToggleEvtHandler = async () => {
(async () => {
await app.whenReady();

// Load app mode setting early (before window creation)
appMode = ((await settings.get('app-mode')) as 'normal' | 'menubar') || 'normal';
if (appMode === 'menubar') {
app.dock.hide();
}

// Auto-update: check for updates via update.electronjs.org (non-MAS only)
if (!isMAS()) {
try {
Expand Down Expand Up @@ -1061,6 +1081,10 @@ const trayToggleEvtHandler = async () => {
}

switcherWindow = createSwitcherWindow();
// Normal mode: show window immediately on startup
if (appMode === 'normal') {
showSwitcherWindow();
}
Comment thread
grimmerk marked this conversation as resolved.
Outdated
if (isDebug) {
console.log('when ready');
}
Expand Down Expand Up @@ -1293,7 +1317,7 @@ const trayToggleEvtHandler = async () => {
} else {
const window = getSwitcherWindow();

if (window && window.isVisible()) {
if (window && window.isVisible() && !window.isMinimized()) {
if (isDebug) {
console.log('Switcher window visible, hiding it');
}
Expand Down Expand Up @@ -1679,6 +1703,8 @@ const trayToggleEvtHandler = async () => {
if (registered) {
await settings.set(`shortcut-${key}`, accelerator);
await syncTrayShortcuts();
// Notify switcher window to update shortcut display
switcherWindow?.webContents.send('shortcuts-updated', await getCurrentShortcuts());
return { success: true };
} else {
// Re-register the old shortcut since the new one failed
Expand All @@ -1694,6 +1720,8 @@ const trayToggleEvtHandler = async () => {
}
await registerAllShortcuts();
await syncTrayShortcuts();
// Notify switcher window to update shortcut display
switcherWindow?.webContents.send('shortcuts-updated', DEFAULT_SHORTCUTS);
return DEFAULT_SHORTCUTS;
});
})();
Expand Down Expand Up @@ -1934,6 +1962,31 @@ ipcMain.handle('get-session-statuses', async () => {
return obj;
});

ipcMain.handle('get-app-mode', async () => {
return appMode;
});

ipcMain.on('set-app-mode', async (_event, mode: string) => {
const newMode = mode === 'menubar' ? 'menubar' : 'normal';
await settings.set('app-mode', newMode);
appMode = newMode;
if (newMode === 'menubar') {
app.dock.hide();
} else {
app.dock.show();
Comment thread
grimmerk marked this conversation as resolved.
Outdated
}
// Notify renderer to update drag region
const window = getSwitcherWindow();
if (window) {
window.webContents.send('app-mode-changed', newMode);
// Re-center when switching to menu bar mode
if (newMode === 'menubar') {
const position = getWindowPosition();
window.setPosition(position.x, position.y, false);
}
}
});

ipcMain.handle('get-session-terminal-app', async () => {
return (await settings.get('session-terminal-app')) || 'iterm2';
});
Expand Down Expand Up @@ -2077,4 +2130,4 @@ ipcMain.handle('detect-active-ide-projects', async () => {
return Array.from(folderNames);
});

app.dock.hide();
// app.dock.hide() moved to async init block (after settings loaded)
Loading