Remove the Windows 7 (7.css) skin
The win7 skin is dropped. Everything else the branch built stays: Linux support and the HTML context menus, the workspace-tab menu, the continuous interface scale (rem everywhere, stepper, Ctrl/Cmd +/-/0) and the core/ service layer. The modern tree already carried all of them, and nothing outside skins/7like/ imported the win7 tree except main.ts and styles.css. Removed: the skins/7like/ tree (5.1k lines, fonts), the 7.css dependency, the skin setting and its options row + strings in all 7 locales, the frameless-window plumbing (window-control RPCs, windowState push, trackMaximizeState, the synthesized resize grip and its postinstall watchdog), the session-skin pinning in buildPreload/chromeOptions, the skin/skinfix cascade layers, and the win7-only probes and screenshot harness (the harness cannot render the modern tree: plain Firefox has no RPC bridge). chromeOptions() stays as the one shared frame decision. Fixed on the way out: - index.html's per-theme pre-paint background is restored. The branch had replaced it with a win7-only transparent rule, so modern dark windows had silently lost one of the three flash guards. - editor-windows.ts wrote its window-key separator as a literal NUL byte, which made git and grep treat the file as binary; it is `\0` now (same string at runtime). No settings migration: a stale "skin" key is carried harmlessly by the store's spread-merge and dropped on the next save. UI bundle: 616.7 kB -> 405.4 kB, back under the 500 kB budget. Docs: architecture, gotchas and platform-notes lose the win7 material but keep what stays true (construction-time preloads/frames, drag regions ignoring preventDefault, electrobun's missing resize/maximize primitives); flash-prevention, dev-URL and Bun-panic notes move back under Electrobun; stale context-menu/tab-bar links fixed; README documents the scale keys. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -16,8 +16,8 @@ export interface MenuItem {
|
||||
tooltip?: string;
|
||||
/** Shortcut hint, rendered right-aligned. */
|
||||
accelerator?: string;
|
||||
/** Greyed and unclickable. Win7 menus disable rather than hide, so the set
|
||||
* of commands stays in the same place from one right-click to the next. */
|
||||
/** Greyed and unclickable. Menus disable rather than hide, so the set of
|
||||
* commands stays in the same place from one right-click to the next. */
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ export class ContextMenuService {
|
||||
* assume `activeWorkspace`.
|
||||
*
|
||||
* Everything illegal is DISABLED, not omitted: a menu whose items move
|
||||
* between right-clicks is a Win7 sin, and "Close Tab" greyed out explains
|
||||
* between right-clicks is worse than a dead row, and "Close Tab" greyed out explains
|
||||
* why the last tab cannot be closed better than its absence does.
|
||||
*
|
||||
* Duplicate/Rename/Save-session are deliberately absent until tabs have an
|
||||
|
||||
@@ -8,9 +8,6 @@ declare global {
|
||||
__APP_PLATFORM?: string;
|
||||
/** Which root component this window boots. */
|
||||
__APP_MODE?: 'main' | 'editor' | 'manager';
|
||||
/** Which skin tree this window boots. Baked into the preload because
|
||||
* settings resolve too late to decide layout without a flash. */
|
||||
__APP_SKIN?: 'modern' | 'win7';
|
||||
/** Window-kind specific context (EditorOpenContext for editor windows). */
|
||||
__APP_CTX?: unknown;
|
||||
}
|
||||
@@ -24,8 +21,7 @@ export const IS_WINDOWS = PLATFORM === 'win32';
|
||||
|
||||
export const IS_LINUX = PLATFORM === 'linux';
|
||||
|
||||
/** Shortcut-hint labels: "⌘W" on macOS, "Ctrl+W" elsewhere. Keyed on the real
|
||||
* platform — the keyboard does not change with the window chrome. */
|
||||
/** Shortcut-hint labels: "⌘W" on macOS, "Ctrl+W" elsewhere. */
|
||||
export const MOD_LABEL = IS_MAC ? '⌘' : 'Ctrl+';
|
||||
export const ALT_LABEL = IS_MAC ? '⌥' : 'Alt+';
|
||||
|
||||
@@ -35,25 +31,9 @@ export const APP_MODE: 'main' | 'editor' | 'manager' =
|
||||
export const EDITOR_CONTEXT =
|
||||
typeof window !== 'undefined' ? (window.__APP_CTX as EditorOpenContext | undefined) : undefined;
|
||||
|
||||
/**
|
||||
* Which skin tree this window booted. Read from the preload rather than from
|
||||
* SettingsService because both are needed before first paint — main.ts picks a
|
||||
* root component from it, and it must not change under a running window (the
|
||||
* native frame is fixed at BrowserWindow construction).
|
||||
*/
|
||||
export const APP_SKIN: 'modern' | 'win7' =
|
||||
typeof window !== 'undefined' ? (window.__APP_SKIN ?? 'modern') : 'modern';
|
||||
|
||||
export const IS_WIN7_CHROME = APP_SKIN === 'win7';
|
||||
|
||||
/**
|
||||
* True when macOS traffic lights overlay the app's own header row — the fused
|
||||
* `hiddenInset` layout, which reserves `pl-24` for them. False under the win7
|
||||
* skin even on macOS: `titleBarStyle: 'hidden'` removes the traffic lights
|
||||
* altogether, so reserving space would leave a gap. Only the shadlike tree
|
||||
* reads this; 7like draws its own title bar and never defers to native chrome.
|
||||
*/
|
||||
export const IS_MAC_CHROME = IS_MAC && !IS_WIN7_CHROME;
|
||||
/** True when macOS traffic lights overlay the app's own header row (the fused
|
||||
* hiddenInset layout, see chromeOptions), which reserves `pl-24` for them. */
|
||||
export const IS_MAC_CHROME = IS_MAC;
|
||||
|
||||
/**
|
||||
* Kill the webview's default right-click menu (Reload, Inspect Element…)
|
||||
|
||||
@@ -32,7 +32,6 @@ export class RpcService {
|
||||
private managerStateListeners = new Set<(open: boolean) => void>();
|
||||
private connectionsListeners = new Set<() => void>();
|
||||
private updateStatusListeners = new Set<(status: UpdateStatus) => void>();
|
||||
private windowStateListeners = new Set<(maximized: boolean) => void>();
|
||||
|
||||
private rpc: ReturnType<typeof Electroview.defineRPC<AppRPC>> | undefined;
|
||||
private ready: Promise<void> = Promise.resolve();
|
||||
@@ -72,9 +71,6 @@ export class RpcService {
|
||||
updateStatus: (status) => {
|
||||
for (const listener of this.updateStatusListeners) listener(status);
|
||||
},
|
||||
windowState: ({ maximized }) => {
|
||||
for (const listener of this.windowStateListeners) listener(maximized);
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -136,12 +132,6 @@ export class RpcService {
|
||||
this.updateStatusListeners.add(listener);
|
||||
}
|
||||
|
||||
/** win7 skin: the frameless window's maximize state changed (derived from
|
||||
* the native resize event, so Aero Snap and Win+Up land here too). */
|
||||
onWindowState(listener: (maximized: boolean) => void): void {
|
||||
this.windowStateListeners.add(listener);
|
||||
}
|
||||
|
||||
/** Typed request proxy: `await rpc.request.listDir({...})`. Waits for the bridge. */
|
||||
get request() {
|
||||
const rpc = this.rpc;
|
||||
|
||||
@@ -7,7 +7,6 @@ import { RpcService } from './rpc.service';
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class SettingsService {
|
||||
readonly locale = signal<AppSettings['locale']>(DEFAULT_SETTINGS.locale);
|
||||
readonly skin = signal<AppSettings['skin']>(DEFAULT_SETTINGS.skin);
|
||||
readonly theme = signal<AppSettings['theme']>(DEFAULT_SETTINGS.theme);
|
||||
readonly darkTone = signal<AppSettings['darkTone']>(DEFAULT_SETTINGS.darkTone);
|
||||
readonly accent = signal<AppSettings['accent']>(DEFAULT_SETTINGS.accent);
|
||||
@@ -51,7 +50,6 @@ export class SettingsService {
|
||||
|
||||
private applyAll(settings: AppSettings): void {
|
||||
this.locale.set(settings.locale);
|
||||
this.skin.set(settings.skin);
|
||||
this.theme.set(settings.theme);
|
||||
this.darkTone.set(settings.darkTone);
|
||||
this.accent.set(settings.accent);
|
||||
@@ -64,9 +62,6 @@ export class SettingsService {
|
||||
this.autoClearCompleted.set(settings.autoClearCompleted);
|
||||
this.editor.set(settings.editor);
|
||||
this.editorApp.set(settings.editorApp);
|
||||
// NO applySkin here, deliberately — see setSkin. applyAll also runs on the
|
||||
// settingsChanged push, so flipping the class here would break every OPEN
|
||||
// editor and manager window too, not just the one that changed the setting.
|
||||
this.applyTheme();
|
||||
this.applyDarkTone();
|
||||
this.applyAccent();
|
||||
@@ -80,30 +75,6 @@ export class SettingsService {
|
||||
void this.persist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the preference and NOTHING else — the skin is a launch-time choice.
|
||||
*
|
||||
* It deliberately does not touch the `.win7` class, which is the whole bug
|
||||
* this replaced: each skin's CSS is written against its OWN component tree's
|
||||
* markup, and the tree is fixed at bootstrap from the preload-baked
|
||||
* __APP_SKIN. Flipping the class live therefore painted 7.css onto shadlike
|
||||
* markup that has no .window.glass, no .title-bar, no menu[role=tablist] and
|
||||
* no <table> ListView — a broken window, not a reskinned one.
|
||||
*
|
||||
* A reload would not have helped either: the preload string is frozen at
|
||||
* webview construction (a persistent WebKitUserScript), and titleBarStyle /
|
||||
* transparent have no setters, so the native frame cannot change on a live
|
||||
* window. win7 -> modern without a reframe is the dangerous direction — the
|
||||
* modern tree draws no title bar, so it would land in a frameless window
|
||||
* with no way to move, minimize or close it.
|
||||
*
|
||||
* The options row shows the saved value as pending until the next start.
|
||||
*/
|
||||
setSkin(skin: AppSettings['skin']): void {
|
||||
this.skin.set(skin);
|
||||
void this.persist();
|
||||
}
|
||||
|
||||
setTheme(theme: AppSettings['theme']): void {
|
||||
this.theme.set(theme);
|
||||
this.applyTheme();
|
||||
@@ -171,12 +142,6 @@ export class SettingsService {
|
||||
void this.persist();
|
||||
}
|
||||
|
||||
// There is deliberately no applySkin(). The `.win7` class is written once by
|
||||
// buildPreload at DOCUMENT_START for the skin this window actually booted,
|
||||
// and must never change afterwards — see setSkin for why. Every other apply*
|
||||
// below is safe to run live because it only re-points tokens, and both skins
|
||||
// consume the same token system.
|
||||
|
||||
private applyTheme(): void {
|
||||
const theme = this.theme();
|
||||
if (theme === 'system') {
|
||||
@@ -205,7 +170,7 @@ export class SettingsService {
|
||||
}
|
||||
|
||||
/** The whole interface scale is ONE declaration: every size in the app is
|
||||
* rem, so moving the root font-size moves both skins in lockstep. 1 = the
|
||||
* rem, so moving the root font-size moves the whole UI. 1 = the
|
||||
* browser-default 16px root; delete-when-default keeps the pristine state
|
||||
* attribute-free like the other axes. buildPreload mirrors this for a
|
||||
* flash-free first paint. */
|
||||
@@ -225,7 +190,6 @@ export class SettingsService {
|
||||
protected settings(): AppSettings {
|
||||
return {
|
||||
locale: this.locale(),
|
||||
skin: this.skin(),
|
||||
theme: this.theme(),
|
||||
darkTone: this.darkTone(),
|
||||
accent: this.accent(),
|
||||
|
||||
Reference in New Issue
Block a user