feat(customWindowTitleBar): add sexy custom window title bar <3

This commit is contained in:
Johannes Millan 2025-12-01 15:21:15 +01:00
parent b070233f29
commit c5625de6f1
17 changed files with 99 additions and 14 deletions

View file

@ -11,6 +11,8 @@ import {
import { lockscreen } from '../lockscreen';
import { errorHandlerWithFrontendInform } from '../error-handler-with-frontend-inform';
import { GlobalConfigState } from '../../src/app/features/config/global-config.model';
import { saveSimpleStore } from '../simple-store';
import { SimpleStoreKey } from '../shared-with-frontend/simple-store.const';
export const initAppControlIpc = (): void => {
ipcMain.on(IPC.SHUTDOWN_NOW, quitApp);
@ -19,10 +21,17 @@ export const initAppControlIpc = (): void => {
ipcMain.on(IPC.OPEN_DEV_TOOLS, () => getWin().webContents.openDevTools());
ipcMain.on(IPC.RELOAD_MAIN_WIN, () => getWin().reload());
ipcMain.on(IPC.TRANSFER_SETTINGS_TO_ELECTRON, (ev, cfg: GlobalConfigState) => {
ipcMain.on(IPC.TRANSFER_SETTINGS_TO_ELECTRON, async (ev, cfg: GlobalConfigState) => {
setIsMinimizeToTray(cfg.misc.isMinimizeToTray);
setIsTrayShowCurrentTask(cfg.misc.isTrayShowCurrentTask);
setIsTrayShowCurrentCountdown(cfg.misc.isTrayShowCurrentCountdown);
if (cfg.misc.isUseCustomWindowTitleBar !== undefined) {
await saveSimpleStore(
SimpleStoreKey.IS_USE_CUSTOM_WINDOW_TITLE_BAR,
cfg.misc.isUseCustomWindowTitleBar,
);
}
});
ipcMain.on(IPC.SHOW_OR_FOCUS, () => {

View file

@ -5,8 +5,9 @@ import { log } from 'electron-log/main';
import { loadSimpleStoreAll, saveSimpleStore } from '../simple-store';
import { getWin } from '../main-window';
import { errorHandlerWithFrontendInform } from '../error-handler-with-frontend-inform';
import { SimpleStoreKey } from '../shared-with-frontend/simple-store.const';
const COMMAND_MAP_PROP = 'allowedCommands';
const COMMAND_MAP_PROP = SimpleStoreKey.ALLOWED_COMMANDS;
export const initExecIpc = (): void => {
ipcMain.on(IPC.EXEC, execWithFrontendErrorHandlerInform);

View file

@ -2,6 +2,7 @@ import windowStateKeeper from 'electron-window-state';
import {
App,
BrowserWindow,
BrowserWindowConstructorOptions,
ipcMain,
Menu,
MenuItem,
@ -22,6 +23,8 @@ import {
showOverlayWindow,
} from './overlay-indicator/overlay-indicator';
import { getIsMinimizeToTray, getIsQuiting, setIsQuiting } from './shared-state';
import { loadSimpleStoreAll } from './simple-store';
import { SimpleStoreKey } from './shared-with-frontend/simple-store.const';
let mainWin: BrowserWindow;
@ -44,7 +47,7 @@ export const getIsAppReady = (): boolean => {
return mainWinModule.isAppReady;
};
export const createWindow = ({
export const createWindow = async ({
IS_DEV,
ICONS_FOLDER,
quitApp,
@ -56,7 +59,7 @@ export const createWindow = ({
quitApp: () => void;
app: App;
customUrl?: string;
}): BrowserWindow => {
}): Promise<BrowserWindow> => {
// make sure the main window isn't already created
if (mainWin) {
errorHandlerWithFrontendInform('Main window already exists');
@ -73,6 +76,24 @@ export const createWindow = ({
defaultHeight: 800,
});
const simpleStore = await loadSimpleStoreAll();
const persistedIsUseCustomWindowTitleBar =
simpleStore[SimpleStoreKey.IS_USE_CUSTOM_WINDOW_TITLE_BAR];
const legacyIsUseObsidianStyleHeader =
simpleStore[SimpleStoreKey.LEGACY_IS_USE_OBSIDIAN_STYLE_HEADER];
const isUseCustomWindowTitleBar =
persistedIsUseCustomWindowTitleBar ?? legacyIsUseObsidianStyleHeader ?? true;
const titleBarStyle: BrowserWindowConstructorOptions['titleBarStyle'] =
isUseCustomWindowTitleBar || IS_MAC ? 'hidden' : 'default';
const titleBarOverlay: BrowserWindowConstructorOptions['titleBarOverlay'] =
isUseCustomWindowTitleBar && !IS_MAC
? {
color: '#00000000',
symbolColor: '#fff',
height: 44,
}
: undefined;
mainWin = new BrowserWindow({
x: mainWindowState.x,
y: mainWindowState.y,
@ -81,7 +102,8 @@ export const createWindow = ({
minHeight: 240,
minWidth: 300,
title: IS_DEV ? 'Super Productivity D' : 'Super Productivity',
titleBarStyle: IS_MAC ? 'hidden' : 'default',
titleBarStyle,
titleBarOverlay,
show: false,
webPreferences: {
scrollBounce: true,
@ -99,7 +121,7 @@ export const createWindow = ({
},
icon: ICONS_FOLDER + '/icon_256x256.png',
// Wayland compatibility: disable transparent/frameless features that can cause issues
// transparent: false,
transparent: false,
// frame: true,
});

View file

@ -0,0 +1,6 @@
export enum SimpleStoreKey {
IS_USE_CUSTOM_WINDOW_TITLE_BAR = 'isUseCustomWindowTitleBar',
ALLOWED_COMMANDS = 'allowedCommands',
// Legacy key kept for backwards compatibility when reading persisted settings
LEGACY_IS_USE_OBSIDIAN_STYLE_HEADER = 'isUseObsidianStyleHeader',
}

View file

@ -149,7 +149,7 @@ export const startApp = (): void => {
// APP EVENT LISTENERS
// -------------------
appIN.on('ready', createMainWin);
appIN.on('ready', () => createMainWin());
appIN.on('ready', () => initBackupAdapter());
appIN.on('ready', () => initLocalFileSyncAdapter());
appIN.on('ready', () => initFullScreenBlocker(IS_DEV));
@ -353,8 +353,8 @@ export const startApp = (): void => {
}
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
function createMainWin(): void {
mainWin = createWindow({
async function createMainWin(): Promise<void> {
mainWin = await createWindow({
app,
IS_DEV,
ICONS_FOLDER,