feat: custom scrollbars, portable storage, window state persistence

- Custom scrollbar CSS using ::-webkit-scrollbar for Tauri's Chromium WebView
- Portable storage: all data written next to exe in data/ folder instead of AppData
- Rust get_portable_data_dir command with runtime FS scope for exe directory
- Window size/position/maximized saved to settings on close, restored on startup
This commit is contained in:
Your Name
2026-02-15 22:18:50 +02:00
parent bc12b5569a
commit c6fea186ef
8 changed files with 130 additions and 9 deletions

View File

@@ -1,8 +1,10 @@
import { useState, useEffect, useCallback } from "react";
import { getCurrentWindow, LogicalSize, LogicalPosition } from "@tauri-apps/api/window";
import { AnimatePresence, motion } from "framer-motion";
import { springs, fadeSlideLeft, fadeSlideRight } from "@/lib/motion";
import { useAppStore } from "@/stores/app-store";
import { useBoardStore } from "@/stores/board-store";
import { saveSettings } from "@/lib/storage";
import { AppShell } from "@/components/layout/AppShell";
import { BoardList } from "@/components/boards/BoardList";
import { BoardView } from "@/components/board/BoardView";
@@ -21,13 +23,46 @@ export default function App() {
const [shortcutHelpOpen, setShortcutHelpOpen] = useState(false);
useEffect(() => {
init();
init().then(() => {
// Restore window state after settings are loaded
const { settings } = useAppStore.getState();
const ws = settings.windowState;
if (ws) {
const appWindow = getCurrentWindow();
if (ws.maximized) {
appWindow.maximize();
} else {
appWindow.setSize(new LogicalSize(ws.width, ws.height));
appWindow.setPosition(new LogicalPosition(ws.x, ws.y));
}
}
});
}, [init]);
// Flush pending board saves before the app window closes
// Save window state + 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 () => {