Skip to content
Merged
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 1.0.71

- Fix: use `setActivationPolicy` instead of `app.dock.hide/show` for proper Dock behavior
- Normal mode: Dock icon with running dot + App Switcher
- Menu bar mode: no Dock icon (clean accessory mode)
- No Dock icon flash on app launch (LSUIElement=true kept)
- Feat: tray right-click menu mode toggle (Switch to Normal/Menu Bar Mode)

## 1.0.70

- Feat: Normal App mode — window stays visible, shows in Dock, draggable
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.70",
"version": "1.0.71",
"description": "Quick switcher for VS Code, Cursor, and Claude Code sessions",
"repository": {
"type": "git",
Expand Down
12 changes: 12 additions & 0 deletions src/TrayGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export class TrayGenerator {
tray: Tray;
attachedWindow: BrowserWindow;
onTrayClickCallback: any;
onToggleAppMode: (() => void) | null = null;
getAppMode: (() => string) | null = null;
title: string;
shortcuts: ShortcutSettings = {
quickSwitcher: 'Command+Control+R',
Expand Down Expand Up @@ -83,7 +85,17 @@ export class TrayGenerator {
},
];

const currentMode = this.getAppMode ? this.getAppMode() : 'normal';
const modeLabel = currentMode === 'normal' ? 'Switch to Menu Bar Mode' : 'Switch to Normal App Mode';

const menu: any = [
{
label: modeLabel,
click: () => {
if (this.onToggleAppMode) this.onToggleAppMode();
},
},
{ type: 'separator' },
{
label: 'Settings',
submenu: settingsItems,
Expand Down
23 changes: 18 additions & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1032,9 +1032,11 @@ const trayToggleEvtHandler = async () => {

// Load app mode setting early (before window creation)
appMode = ((await settings.get('app-mode')) as 'normal' | 'menubar') || 'normal';
if (appMode === 'menubar') {
app.dock.hide();
if (appMode === 'normal') {
app.setActivationPolicy('regular');
}
// LSUIElement=true in Info.plist starts as accessory (no dock icon).
// 'regular' adds dock icon + running dot + App Switcher.

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

tray = new TrayGenerator(switcherWindow, title, trayToggleEvtHandler);
tray.getAppMode = () => appMode;
tray.onToggleAppMode = () => {
const newMode = appMode === 'normal' ? 'menubar' : 'normal';
// Reuse the same logic as the IPC handler
require('electron').ipcMain.emit('set-app-mode', {}, newMode);
};

// https://www.electronjs.org/docs/latest/tutorial/keyboard-shortcuts#global-shortcuts

Expand Down Expand Up @@ -1972,9 +1980,14 @@ ipcMain.on('set-app-mode', async (_event, mode: string) => {
await settings.set('app-mode', newMode);
appMode = newMode;
if (newMode === 'menubar') {
app.dock.hide();
app.setActivationPolicy('accessory');
// accessory mode hides all windows — re-show after short delay
const win = getSwitcherWindow();
if (win) {
setTimeout(() => { win.show(); win.focus(); }, 100);
}
} else {
await app.dock.show();
app.setActivationPolicy('regular');
}
// Notify renderer to update drag region
const window = getSwitcherWindow();
Expand Down Expand Up @@ -2131,4 +2144,4 @@ ipcMain.handle('detect-active-ide-projects', async () => {
return Array.from(folderNames);
});

// app.dock.hide() moved to async init block (after settings loaded)
// Dock visibility managed via app.setActivationPolicy() (see set-app-mode handler)