super-productivity/electron/various-shared.ts
Symon Baikov e0be3a1a16
Feat/task widget global shortcut (#7099)
* feat(electron): add global shortcut for task widget toggle

Adds a configurable global shortcut (`globalToggleTaskWidget`) that
shows/hides the task widget without changing the persisted
enabled/disabled preference. The shortcut is a no-op while the task
widget feature is disabled.

When the user reveals the widget via the shortcut while the main window
is visible, a sticky "user-forced visible" flag keeps it up (like
always-show) instead of letting the next focus/show event immediately
hide it. The flag clears when the user toggles the widget off, opens the
app from the widget, or the feature is disabled.

Rebased onto master to drop the now-superseded tray-indicator refactor;
the only main-window.ts change is the additive user-forced-visible gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(electron): handle task widget shortcut races

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 16:11:16 +02:00

58 lines
1.9 KiB
TypeScript

import { app, BrowserWindow } from 'electron';
import { info } from 'electron-log/main';
import { getWin, getWasMaximizedBeforeHide } from './main-window';
import {
getIsTaskWidgetAlwaysShow,
getIsTaskWidgetUserForcedVisible,
hideTaskWidget,
} from './task-widget/task-widget';
import { setIsQuiting } from './shared-state';
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
export function quitApp(): void {
setIsQuiting(true);
app.quit();
}
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
export function showOrFocus(passedWin: BrowserWindow): void {
// default to main winpc
const win = passedWin || getWin();
// sometimes when starting a second instance we get here although we don't want to
if (!win) {
info(
'special case occurred when showOrFocus is called even though, this is a second instance of the app',
);
return;
}
if (win.isVisible()) {
win.focus();
} else {
// restore explicitly - always call restore() before show()
// On Linux, event.preventDefault() on the minimize event has no effect, so the
// window may be minimized. On some desktop environments (e.g. GNOME/Wayland),
// isMinimized() returns false for a hidden+minimized window, so calling restore()
// only when isMinimized() is true would skip it and leave show() to fail alone.
win.restore();
win.show();
if (getWasMaximizedBeforeHide()) win.maximize();
}
// Hide task widget when main window is shown, unless the user explicitly
// pinned it visible via the global shortcut.
if (!getIsTaskWidgetAlwaysShow() && !getIsTaskWidgetUserForcedVisible()) {
hideTaskWidget();
}
// focus window afterwards always
setTimeout(() => {
if (win.isDestroyed()) return;
win.focus();
// Ensure Chromium renderer also gets keyboard focus (electron#20464)
if (!win.webContents.isDestroyed()) {
win.webContents.focus();
}
}, 60);
}