@franzzemen/brokenstock-shell 0.4.6 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2224,38 +2224,92 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
2224
2224
  args: [{ providedIn: 'root' }]
2225
2225
  }] });
2226
2226
 
2227
- const STORAGE_KEY = 'shell.commandTerminalVisible';
2227
+ /**
2228
+ * The choice a NEW window starts with. Shared by the whole browser.
2229
+ * Written on every toggle, read only at construction.
2230
+ */
2231
+ const DEFAULT_KEY = 'shell.commandTerminalVisible';
2232
+ /**
2233
+ * THIS window's current choice. Per-window by definition, so two windows cannot
2234
+ * fight over it.
2235
+ */
2236
+ const WINDOW_KEY = 'shell.commandTerminalVisible.window';
2228
2237
  /**
2229
2238
  * Controls visibility of the command terminal at the bottom of the shell.
2230
2239
  *
2231
- * State is a single signal, persisted to localStorage so the user's choice
2232
- * survives reloads. The side-menu toggles it; the shell layout reads it to
2233
- * collapse the terminal (and its resize handle) rows.
2240
+ * ⚠ TWO KEYS, AND THE SPLIT IS THE POINT (multiple-windows F6).
2241
+ *
2242
+ * This used to be one `localStorage` value, read once at construction and
2243
+ * written on every change, with nothing listening for another window. That was
2244
+ * correct while the app could only be open once. It is not now: two windows
2245
+ * would each write the shared value on every toggle, so whichever you touched
2246
+ * last decided what BOTH windows got on their next start — a setting that
2247
+ * quietly refuses to stay put, which reads as a bug in the shell rather than in
2248
+ * storage.
2249
+ *
2250
+ * The resolution is not "make them agree". You genuinely may want the terminal
2251
+ * up on the scanner window and out of the way on the other, so forcing them into
2252
+ * step would be the wrong fix as well as a harder one. Instead:
2253
+ *
2254
+ * - the LIVE state is per-window (`sessionStorage`), so the two never collide
2255
+ * and a reload still restores what this window had;
2256
+ * - the DEFAULT for a brand-new window is shared (`localStorage`), so your
2257
+ * last choice anywhere still carries into the next window and across a
2258
+ * browser restart, which is the behaviour the single key was providing.
2259
+ *
2260
+ * Both writes are best-effort: losing a remembered layout must never break the
2261
+ * screen trying to remember it.
2262
+ *
2263
+ * ⚠ `visible` is READ-ONLY to the outside and `toggle()` is the only mutator.
2264
+ * It used to be a writable signal persisted by an `effect`, which meant any
2265
+ * caller could `set()` it — and whether that got remembered depended on an
2266
+ * effect firing somewhere else. Persisting inside the one mutator makes it
2267
+ * impossible to change this without persisting it.
2234
2268
  */
2235
2269
  class TerminalVisibilityService {
2236
2270
  constructor() {
2237
- this.visible = signal(this.#readInitial(), /* @ts-ignore */
2238
- ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
2239
- effect(() => {
2240
- const isVisible = this.visible();
2241
- try {
2242
- localStorage.setItem(STORAGE_KEY, isVisible ? '1' : '0');
2243
- }
2244
- catch {
2245
- // localStorage unavailable (private mode / SSR) — non-fatal.
2246
- }
2247
- });
2271
+ this.#visible = signal(this.#readInitial(), /* @ts-ignore */
2272
+ ...(ngDevMode ? [{ debugName: "#visible" }] : /* istanbul ignore next */ []));
2273
+ /** Read-only on purpose — see the header. */
2274
+ this.visible = this.#visible.asReadonly();
2248
2275
  }
2276
+ #visible;
2249
2277
  toggle() {
2250
- this.visible.update(v => !v);
2278
+ const next = !this.#visible();
2279
+ this.#visible.set(next);
2280
+ this.#write(sessionStorage, WINDOW_KEY, next);
2281
+ this.#write(localStorage, DEFAULT_KEY, next);
2251
2282
  }
2283
+ /**
2284
+ * This window's own choice wins; otherwise the last choice made anywhere;
2285
+ * otherwise visible.
2286
+ *
2287
+ * The order matters on a reload: a window that had hidden the terminal must
2288
+ * not have it reappear because another window showed one since.
2289
+ */
2252
2290
  #readInitial() {
2291
+ const own = this.#read(sessionStorage, WINDOW_KEY);
2292
+ if (own !== undefined)
2293
+ return own;
2294
+ const shared = this.#read(localStorage, DEFAULT_KEY);
2295
+ return shared ?? true;
2296
+ }
2297
+ #read(store, key) {
2253
2298
  try {
2254
- const raw = localStorage.getItem(STORAGE_KEY);
2255
- return raw === null ? true : raw === '1';
2299
+ const raw = store.getItem(key);
2300
+ return raw === null ? undefined : raw === '1';
2256
2301
  }
2257
2302
  catch {
2258
- return true;
2303
+ // Storage unavailable (private mode / prerender) — fall through.
2304
+ return undefined;
2305
+ }
2306
+ }
2307
+ #write(store, key, value) {
2308
+ try {
2309
+ store.setItem(key, value ? '1' : '0');
2310
+ }
2311
+ catch {
2312
+ // Non-fatal by policy: a lost layout preference must not break the screen.
2259
2313
  }
2260
2314
  }
2261
2315
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: TerminalVisibilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -2264,7 +2318,7 @@ class TerminalVisibilityService {
2264
2318
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: TerminalVisibilityService, decorators: [{
2265
2319
  type: Injectable,
2266
2320
  args: [{ providedIn: 'root' }]
2267
- }], ctorParameters: () => [] });
2321
+ }] });
2268
2322
 
2269
2323
  /**
2270
2324
  * Elements that mean "the user is typing", where an unmodified shortcut must not fire.