Stage 5: wire the skin switch — both UIs now reachable
The reunion is complete: one build contains both UIs and picks between them at bootstrap. - src/shared/types.ts regains `skin: "modern" | "win7"` on AppSettings. - SettingsService regains the skin signal, setSkin() and applySkin(), which toggles the `.win7` class on <html>. - buildPreload emits __APP_SKIN and adds `.win7` conditionally again, instead of unconditionally as it had sincefe028a9. - chromeOptions() regains its parameter: win7 gets frameless + transparent, modern gets the macOS hiddenInset fusion or the plain native frame. - core/platform.ts regains APP_SKIN / IS_WIN7_CHROME (added in stage 4). - main.ts now selects on both axes — skin picks the tree, APP_MODE picks the root within it. - Both tab-bars get a skin row, with the reopen caveat as its tooltip. DEFAULT_SETTINGS.skin is "modern", matching the original design and `main`. Worth flagging: this branch has booted win7 unconditionally sincefe028a9, so after this commit it starts in the modern UI unless the setting says otherwise. One word in types.ts flips that if the win7 look should be the default. i18n: en.ts is the source of truth and everything else falls back to it, so only en was strictly required — but es/eu/fr/de/zh/ja got real translations too, each matching the terminology that locale already uses for the Theme row. Verified both skins on live single-instance captures. Modern boots and renders fully styled, which also proves Tailwind scans skins/shadlike/** — a purge would have produced an unstyled page rather than this one. Win7, selected by setting skin in the persisted settings, is still pixel-identical to the pre-refactor baseline across all five stages. The persisted settings file was backed up and restored, so it still carries no skin key and resolves to the default through the backend's merge. Not verified: clicking the new skin row itself, which needs an interaction pass — no window automation is available here. Its bindings compile and the built bundle contains options.skin, setSkin and the translated labels. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+31
-19
@@ -20,13 +20,16 @@ export function buildPreload(
|
||||
): string {
|
||||
let script =
|
||||
`window.__APP_PLATFORM=${JSON.stringify(process.platform)};` +
|
||||
`window.__APP_MODE=${JSON.stringify(mode)};`;
|
||||
`window.__APP_MODE=${JSON.stringify(mode)};` +
|
||||
`window.__APP_SKIN=${JSON.stringify(settings.skin)};`;
|
||||
if (ctx !== undefined) script += `window.__APP_CTX=${JSON.stringify(ctx)};`;
|
||||
|
||||
// A class, not a data-* attribute: 7.scoped.css is precompiled to require a
|
||||
// literal `.win7` ancestor. Unconditional on this branch — the skin is not a
|
||||
// setting any more, this build IS the Windows 7 build.
|
||||
script += `document.documentElement.classList.add("win7");`;
|
||||
// literal `.win7` ancestor, so the name is not ours to choose. Mirrors
|
||||
// SettingsService.applySkin, which owns it once the page is live.
|
||||
if (settings.skin === "win7") {
|
||||
script += `document.documentElement.classList.add("win7");`;
|
||||
}
|
||||
|
||||
const dataset: Record<string, string> = {};
|
||||
if (settings.theme !== "system") dataset["theme"] = settings.theme;
|
||||
@@ -43,22 +46,31 @@ export function buildPreload(
|
||||
* Native chrome options for a window. The ONE place the frame decision is made —
|
||||
* both the main window (src/bun/index.ts) and openSecondaryWindow spread this.
|
||||
*
|
||||
* The webview draws its own Aero title bar (drag region + our own
|
||||
* minimize/maximize/close), so the window is frameless on EVERY platform.
|
||||
* `titleBarStyle: "hidden"` clears `Titled` from the Cocoa style mask, which is
|
||||
* also what removes the macOS traffic lights — there is no separate
|
||||
* hide-traffic-lights API. Linux honours it too: the GTK wrapper calls
|
||||
* gtk_window_set_decorated(false).
|
||||
* Both values are BrowserWindow CONSTRUCTOR options, which is exactly why a
|
||||
* skin change only reaches the frame on the next window open: there is no API
|
||||
* to re-decorate a live window. SettingsService.applySkin flips the CSS half
|
||||
* immediately, and the options row tells the user about the gap.
|
||||
*/
|
||||
export function chromeOptions() {
|
||||
export function chromeOptions(skin: AppSettings["skin"]) {
|
||||
// win7 draws its own Aero title bar (drag region + our minimize/maximize/
|
||||
// close), so the window is frameless on EVERY platform. `titleBarStyle:
|
||||
// "hidden"` clears `Titled` from the Cocoa style mask, which is also what
|
||||
// removes the macOS traffic lights — there is no separate
|
||||
// hide-traffic-lights API. Linux honours it too: the GTK wrapper calls
|
||||
// gtk_window_set_decorated(false).
|
||||
//
|
||||
// `transparent` is what lets the Aero frame be a real frame: .window's 6px
|
||||
// radius and its outer drop shadow are drawn by the webview OUTSIDE the
|
||||
// window's own rectangle, so on an opaque surface they are simply clipped —
|
||||
// square corners and no shadow. The UI reserves the shadow's gutter (see
|
||||
// the .window margin in styles.css).
|
||||
// PORTABILITY: on Linux this needs a compositor granting an RGBA visual;
|
||||
// without one the frame still draws, just without the shadow falloff.
|
||||
return { titleBarStyle: "hidden" as const, transparent: true };
|
||||
// radius is drawn by the webview OUTSIDE the window's own rectangle, so on
|
||||
// an opaque surface the corners are simply clipped square.
|
||||
// PORTABILITY: on Linux this needs a compositor granting an RGBA visual.
|
||||
if (skin === "win7") return { titleBarStyle: "hidden" as const, transparent: true };
|
||||
|
||||
// modern: the native frame stays. On macOS it fuses with the app's own
|
||||
// header row (hiddenInset), and the traffic lights overlay it — which is
|
||||
// what IS_MAC_CHROME reserves pl-24 for in the shadlike tree.
|
||||
return process.platform === "darwin"
|
||||
? { titleBarStyle: "hiddenInset" as const, trafficLightOffset: { x: 12, y: 13 } }
|
||||
: {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,7 +141,7 @@ export function openSecondaryWindow(opts: SecondaryWindowOptions): BrowserWindow
|
||||
title: opts.title,
|
||||
url: opts.url,
|
||||
frame: opts.frame,
|
||||
...chromeOptions(),
|
||||
...chromeOptions(opts.settings.skin),
|
||||
preload: buildPreload(opts.mode, opts.settings, opts.ctx),
|
||||
rpc: opts.rpc,
|
||||
hidden: true,
|
||||
|
||||
Reference in New Issue
Block a user