feat: typography overhaul, custom scrollbars, import/export, settings UI

Includes changes from prior sessions: Epilogue + Space Mono fonts,
OverlayScrollbars integration, markdown editor fixes, settings dialog,
import/export buttons, and various UI refinements.
This commit is contained in:
Your Name
2026-02-16 14:56:36 +02:00
parent 8dedbf6032
commit 414c1f7d68
9 changed files with 343 additions and 205 deletions

View File

@@ -39,30 +39,10 @@ export default function App() {
});
}, [init]);
// Save window state + flush board saves before the app window closes
// Flush board saves before the app window closes
useEffect(() => {
function handleBeforeUnload() {
useBoardStore.getState().closeBoard();
// Save window state synchronously-ish (fire and forget)
const appWindow = getCurrentWindow();
Promise.all([
appWindow.outerSize(),
appWindow.outerPosition(),
appWindow.isMaximized(),
]).then(([size, position, maximized]) => {
const settings = useAppStore.getState().settings;
saveSettings({
...settings,
windowState: {
x: position.x,
y: position.y,
width: size.width,
height: size.height,
maximized,
},
});
});
}
window.addEventListener("beforeunload", handleBeforeUnload);
return () => {
@@ -70,6 +50,45 @@ export default function App() {
};
}, []);
// Save window state on resize/move (debounced) so it persists without blocking close
useEffect(() => {
const appWindow = getCurrentWindow();
let timeout: ReturnType<typeof setTimeout> | null = null;
async function saveWindowState() {
const [size, position, maximized] = await Promise.all([
appWindow.outerSize(),
appWindow.outerPosition(),
appWindow.isMaximized(),
]);
const settings = useAppStore.getState().settings;
await saveSettings({
...settings,
windowState: {
x: position.x,
y: position.y,
width: size.width,
height: size.height,
maximized,
},
});
}
function debouncedSave() {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(saveWindowState, 500);
}
const unlistenResize = appWindow.onResized(debouncedSave);
const unlistenMove = appWindow.onMoved(debouncedSave);
return () => {
if (timeout) clearTimeout(timeout);
unlistenResize.then((fn) => fn());
unlistenMove.then((fn) => fn());
};
}, []);
// Listen for custom event to open settings from TopBar or command palette
useEffect(() => {
function handleOpenSettings() {