Conversation
Persist the frame preference in migration 4 and create main after loading it, so GTK receives the decoration setting before it realizes the window. On Linux and Windows the setting takes effect at the next app launch; frameless windows expose minimize, maximize/restore and close in the existing app header. macOS keeps its overlay titlebar and does not show the setting. The preference round-trip and migration path are covered in Rust tests. The settings UI has English and French strings and the behavior is recorded in the feature spec.
obazin
left a comment
There was a problem hiding this comment.
Thanks for this — the feature itself is solid, and the persistence plus the in-app min/max/close controls are exactly right. My one substantive concern is the apply mechanism in main.rs, which I think can be much simpler.
The whole window reconstruction — create = false, rebuilding via WebviewWindowBuilder::from_config, manually re-injecting the dev URL, the visible=false → show() dance — hangs on this premise:
GTK only applies decorations before a window is realized
I don't think that holds for Tauri v2. Both getCurrentWindow().setDecorations(boolean) (JS) and WebviewWindow::set_decorations(bool) (Rust) toggle decorations on a live window, and neither documents a Linux/GTK "must set before realize" caveat (tao maps it to gtk_window_set_decorated, which takes effect at runtime).
If that's right, we can leave the window declared in tauri.conf.json as-is, delete the entire main.rs block, and apply the preference at runtime instead: in +layout.svelte's existing bootPromise (it already loads preferences), if (!isMac) getCurrentWindow().setDecorations(!prefs.hideTitleBar), and have the settings toggle call setDecorations(...) too. That removes the fragile Rust (no create=false, no from_config rebuild, no dev-URL re-injection, no read_preferences in setup) and, as a bonus, makes the toggle take effect immediately instead of on next launch.
The one thing worth confirming first: could you test setDecorations live on Linux/GTK on your side? The docs say it's unconditional, but you clearly hit something that pushed you toward construction-time. If it genuinely flickers or no-ops on some WM there, the construction-time approach is defensible and I'm happy to take the PR closer to as-is. On macOS it's moot (overlay style, the toggle is hidden) and on Windows runtime toggling is fine.
For completeness: decorations: false is also a static window option in tauri.conf.json, but since we want a per-user toggle rather than always-off, the runtime call is the right tool rather than the JSON one.
Frameless-window toggle persisted with preferences (migration 4 adds hide_title_bar; set_title_bar_hidden). On Windows/Linux it drops the native window frame at runtime via the webview's setDecorations, so it applies instantly rather than on next launch, and the app header then carries its own minimize, maximize/restore and close controls. macOS keeps titleBarStyle: Overlay, so the toggle is hidden there. The apply path lives entirely in the frontend: PreferencesStore.init and setTitleBarHidden call getCurrentWindow().setDecorations (guarded off macOS). main.rs and tauri.conf.json are untouched — no window reconstruction, no reading preferences in setup. This is the simpler alternative to PR #2's approach, which rebuilt the window in Rust after loading preferences to satisfy a GTK "decorations before realize" assumption; the Tauri v2 setDecorations API documents no such runtime limitation. Needs a Linux/GTK smoke test to confirm. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ABuRgJiANb5a87eWFYRJ4B
Hide the title baris now persisted with preferences. On Linux and Windows it takes effect next time Janis opens:mainis constructed after preferences load, so GTK receivesdecorations = falsebefore the window is realized. The app header then exposes minimize, maximize/restore and close. macOS keepstitleBarStyle: Overlay, so the toggle is not shown there.Migration 4 adds
hide_title_bar; the preference is part ofget_preferencesandset_title_bar_hidden. The settings UI has English and French strings, anddocs/specs.mdandCLAUDE.mddescribe the new command and behavior.Verified with
cargo fmt --check,cargo test(6 passed), debug and releasecargo clippy -- -D warnings,pnpm check,pnpm test:unit(8 passed), targeted Prettier (changed code and specs), and apnpm tauri devsmoke launch. The repository-wide Prettier check still reports the existingCLAUDE.mdformatting mismatch. The commit is unsigned because 1Password's agent would not sign from this session.