From 654cbe255bfed9bb63398a5b907d0fe197baeb05 Mon Sep 17 00:00:00 2001 From: August Cayzer Date: Tue, 12 May 2026 23:06:50 +0100 Subject: [PATCH] fix: suppress Recharts dimension warnings; add DevTools toggle --- src/main/config.ts | 6 ++++-- src/main/index.ts | 2 ++ src/main/ipc.ts | 14 +++++++++++++- src/preload/api.ts | 6 ++++++ .../src/components/charts/ActivityArea.tsx | 2 +- .../src/components/charts/DistBar.tsx | 2 +- .../src/components/charts/LineTrend.tsx | 2 +- .../src/components/charts/PaceTrend.tsx | 2 +- src/renderer/src/screens/Settings.tsx | 19 +++++++++++++++++++ src/renderer/src/state/configStore.ts | 12 ++++++++++++ 10 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/main/config.ts b/src/main/config.ts index c7bd8d1..4b1c9d3 100644 --- a/src/main/config.ts +++ b/src/main/config.ts @@ -28,7 +28,8 @@ function defaultConfig(): Config { watchFolder: false, transcriptsOnly: false, demoMode: false, - autoHideSidebar: true + autoHideSidebar: true, + devTools: false } } @@ -71,7 +72,8 @@ export function getConfig(): Config { demoMode: parsed.demoMode === true, // Default ON when absent — first-launch behaviour is auto-hide on // narrow windows, which matches the plan's UX intent. - autoHideSidebar: parsed.autoHideSidebar !== false + autoHideSidebar: parsed.autoHideSidebar !== false, + devTools: parsed.devTools === true } } catch (err) { console.warn('[config] failed to read config.json, falling back to defaults:', err) diff --git a/src/main/index.ts b/src/main/index.ts index fbbf655..78319de 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -6,6 +6,7 @@ import { registerIpcHandlers } from './ipc' import { registerSwProtocolHandler, registerSwSchemeAsPrivileged } from './protocol' import { initAutoUpdater } from './updater' import { disableWatch } from './watcher' +import { getConfig } from './config' // Privileged scheme registration must happen BEFORE app.whenReady — the // renderer's session inherits these privileges at startup. Doing this at @@ -32,6 +33,7 @@ function createWindow(): void { mainWindow.on('ready-to-show', () => { mainWindow.show() + if (getConfig().devTools) mainWindow.webContents.openDevTools() }) mainWindow.webContents.setWindowOpenHandler((details) => { diff --git a/src/main/ipc.ts b/src/main/ipc.ts index c7c8f9c..ea6793d 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -33,7 +33,8 @@ function buildStatus(): ConfigStatus { watchFolder: config.watchFolder, transcriptsOnly: config.transcriptsOnly, demoMode: config.demoMode, - autoHideSidebar: config.autoHideSidebar + autoHideSidebar: config.autoHideSidebar, + devTools: config.devTools } } @@ -95,6 +96,17 @@ export function registerIpcHandlers(): void { return buildStatus() }) + ipcMain.handle('config:setDevTools', (event, enabled: unknown): ConfigStatus => { + if (!validBool(enabled)) return buildStatus() + setConfig({ devTools: enabled }) + const win = BrowserWindow.fromWebContents(event.sender) + if (win) { + if (enabled) win.webContents.openDevTools() + else win.webContents.closeDevTools() + } + return buildStatus() + }) + // Reset everything — wipes config.json back to defaults so the // welcome flow shows again on next hydrate. Used by the "Reset app" // affordance in Settings → About. diff --git a/src/preload/api.ts b/src/preload/api.ts index 9b197a7..74d555b 100644 --- a/src/preload/api.ts +++ b/src/preload/api.ts @@ -40,6 +40,8 @@ export interface Config { * navbar PanelLeft icon; widening the window again does NOT auto- * expand, so user intent always wins. Default true. */ autoHideSidebar: boolean + /** When true, DevTools open on launch. Equivalent to Cmd+Option+I. */ + devTools: boolean } /** @@ -65,6 +67,7 @@ export interface ConfigStatus { transcriptsOnly: boolean demoMode: boolean autoHideSidebar: boolean + devTools: boolean } /** Wire callback type for main → renderer push when the indexed dataset @@ -104,6 +107,9 @@ export const api = { * it entirely via Cmd-B / the navbar icon. */ setAutoHideSidebar: (enabled: boolean): Promise => ipcRenderer.invoke('config:setAutoHideSidebar', enabled), + /** Toggle DevTools open/close. Persists across restarts. */ + setDevTools: (enabled: boolean): Promise => + ipcRenderer.invoke('config:setDevTools', enabled), /** Wipe the persisted config back to defaults — clears the saved * folder, demo flag, custom filler dictionary, etc. The renderer * follows up by triggering a fresh hydrate so the dataStore picks diff --git a/src/renderer/src/components/charts/ActivityArea.tsx b/src/renderer/src/components/charts/ActivityArea.tsx index 7701880..651b66a 100644 --- a/src/renderer/src/components/charts/ActivityArea.tsx +++ b/src/renderer/src/components/charts/ActivityArea.tsx @@ -104,7 +104,7 @@ function ActivityAreaInner({ const effectiveTickFormatter = monthTicks ? monthLabel : formatTick return ( - + >} margin={{ top: 8, right: 8, left: -4, bottom: 0 }} diff --git a/src/renderer/src/components/charts/DistBar.tsx b/src/renderer/src/components/charts/DistBar.tsx index 9f9aa46..47378ca 100644 --- a/src/renderer/src/components/charts/DistBar.tsx +++ b/src/renderer/src/components/charts/DistBar.tsx @@ -24,7 +24,7 @@ interface DistBarProps { */ function DistBarInner({ data, xKey, yKey }: DistBarProps): React.JSX.Element { return ( - + >} margin={{ top: 8, right: 8, left: 0, bottom: 0 }} diff --git a/src/renderer/src/components/charts/LineTrend.tsx b/src/renderer/src/components/charts/LineTrend.tsx index d37ec60..73eb6a5 100644 --- a/src/renderer/src/components/charts/LineTrend.tsx +++ b/src/renderer/src/components/charts/LineTrend.tsx @@ -39,7 +39,7 @@ function LineTrendInner({ }: LineTrendProps): React.JSX.Element { const yTick = formatYTick ?? ((v: number) => formatCompact(v)) return ( - + >} margin={{ top: 8, right: 8, left: -4, bottom: 0 }} diff --git a/src/renderer/src/components/charts/PaceTrend.tsx b/src/renderer/src/components/charts/PaceTrend.tsx index 0ff9032..72df683 100644 --- a/src/renderer/src/components/charts/PaceTrend.tsx +++ b/src/renderer/src/components/charts/PaceTrend.tsx @@ -58,7 +58,7 @@ function PaceTrendInner({ const dotRows = dots.map((d) => ({ [xKey]: d.period, dotValue: d.value })) return ( - + + )} @@ -629,6 +631,23 @@ function ResetAppCard(): React.JSX.Element { ) } +// ---------- Developer ---------------------------------------------------- + +function DeveloperCard(): React.JSX.Element { + const devTools = useConfigStore((s) => s.devTools) + const setDevTools = useConfigStore((s) => s.setDevTools) + return ( + + void setDevTools(next)} + /> + + ) +} + /** Plain-language summary of the updater state, shown next to the * "Check now" button. */ function describeStatus(s: UpdaterStatus): string { diff --git a/src/renderer/src/state/configStore.ts b/src/renderer/src/state/configStore.ts index 4c99f08..77061f0 100644 --- a/src/renderer/src/state/configStore.ts +++ b/src/renderer/src/state/configStore.ts @@ -35,6 +35,8 @@ interface ConfigState { demoMode: boolean /** When true, sidebar auto-collapses on narrow windows. */ autoHideSidebar: boolean + /** When true, DevTools are open. Persisted across restarts. */ + devTools: boolean /** Has the initial round-trip completed? Gates the first-run modal. */ hydrated: boolean /** Transient flag — when true, force the welcome modal regardless @@ -60,6 +62,8 @@ interface ConfigState { setDemoMode: (enabled: boolean) => Promise /** Toggle the auto-hide sidebar behaviour. */ setAutoHideSidebar: (enabled: boolean) => Promise + /** Toggle DevTools open/close. Persists across restarts. */ + setDevTools: (enabled: boolean) => Promise /** Wipe the persisted config back to defaults and force the welcome * modal to re-appear. Used by Settings → About → Reset app. */ resetApp: () => Promise @@ -79,6 +83,7 @@ function applyStatus(status: ConfigStatus): Partial { transcriptsOnly: status.transcriptsOnly, demoMode: status.demoMode, autoHideSidebar: status.autoHideSidebar, + devTools: status.devTools, hydrated: true } } @@ -93,6 +98,7 @@ export const useConfigStore = create((set, get) => ({ transcriptsOnly: false, demoMode: false, autoHideSidebar: true, + devTools: false, hydrated: false, welcomeForceShow: false, @@ -160,6 +166,12 @@ export const useConfigStore = create((set, get) => ({ set(applyStatus(updated)) }, + setDevTools: async (enabled) => { + set({ devTools: enabled }) + const updated = await window.api.config.setDevTools(enabled) + set(applyStatus(updated)) + }, + resetApp: async () => { const status = await window.api.config.reset() // Apply the cleared status AND flip the force-show flag so the