Dashboard patch state: kept until cleanup --all; frame-controls v6

The policy for the `state = true` files
(~/.local/state/steam-frame-nix/ui-patches/<name>.json), now stated in the
option, the injector and the README: they are user data, kept when a patch
is disabled or removed (the choices come back when it is enabled again),
and removed only by `steam-frame-nix-cleanup --all` / `install.sh
uninstall`; `--orphans` removes stale *.json.tmp only.

frame-controls v6 drops v5's one-time read of version 4's localStorage copy:
steamvr.service deletes ~/.cache/SteamVR (and with it that localStorage) on
every SteamVR start, so there is nothing left to migrate.
This commit is contained in:
Pierre Kisters committed 2026-09-29 00:08:43 +02:00
1 parent 69909f5b4c
commit 28c285815e
4 files changed
+20 -19

No files matched your search

+4 -11
View File
@@ -30,8 +30,7 @@
// ~/.local/state/steam-frame-nix/ui-patches/frame-controls.json), which
// seeds a fresh page (SteamVR restart, reboot, reload). localStorage can't
// do that: steamvr.service deletes ~/.cache/SteamVR (vrwebhelper's profile)
// on every start. Version 4's localStorage copy is read once as a fallback
// (migration) and removed once the file has the state.
// on every start (which also took version 4's localStorage copy with it).
//
// Long press: the dashboard only gets primary-button laser input (no right
// click; thumbstick click arrives as nothing). Holding changes nothing; the
@@ -69,9 +68,8 @@
// setPlacement(name or "icon:N", 'bar' | 'menu' | null), reset().
((find, sigs, opts) => {
const NAME = 'frame-controls';
const VERSION = 5;
const VERSION = 6;
const T_SPACER = 1, T_ACTION = 2;
const LS_KEY = 'sfui.frameControls.v1'; // version <= 4 (migration only)
// Action icon enums (sigs.controls anchors them): names for the options.
const NAMES = { keyboard: 22, float: 26, dashboard: 27, theater: 28, dockLeft: 29, dockRight: 30, close: 31, curvature: 40 };
const ICON = { more: 38, float: 26, dashboard: 27 };
@@ -118,13 +116,9 @@
const store = window.__sfuiStore; // injector's persistent store (absent: in-page only)
let S = window.__sfuiFrameControlsState, restored = null;
if (S?.schema !== 1) {
let saved = store?.get(NAME), from = 'file';
if (saved?.schema !== 1) {
from = 'localStorage';
try { saved = JSON.parse(localStorage.getItem(LS_KEY) ?? 'null'); } catch { saved = null; }
}
const saved = store?.get(NAME);
const ok = saved?.schema === 1 && saved.placement && typeof saved.placement === 'object';
restored = ok ? from : 'nothing';
restored = ok ? 'file' : 'nothing';
S = window.__sfuiFrameControlsState = { schema: 1, placement: ok ? { ...saved.placement } : {}, nixSeen: ok ? { ...saved.nixSeen } : {}, log: [] };
}
const logBuf = S.log ??= [];
@@ -136,7 +130,6 @@
let unsaved = true; // last save not sent (no injector binding): retried by check()
const save = () => {
unsaved = !store?.set?.(NAME, { schema: 1, placement: { ...S.placement }, nixSeen: { ...S.nixSeen } });
if (!unsaved) { try { localStorage.removeItem(LS_KEY); } catch { /* none */ } }
};
for (const k of new Set([...Object.keys(optMap), ...Object.keys(S.nixSeen)])) {
if (S.nixSeen[k] !== optMap[k] && k in S.placement) {
+7 -2
View File
@@ -6,7 +6,9 @@
# It exists while `patches` is non-empty, restarts on every switch (the old
# instance reverts removed patches) and is stopped once the list is empty.
# Patches with `state = true` get a persistent JSON value (injector.mjs:
# "Persistent state"). Patch calling convention (mkPatch): lib/default.nix.
# "Persistent state"), kept when the patch goes and removed by
# steam-frame-nix-cleanup --all. Patch calling convention (mkPatch):
# lib/default.nix.
{ config, pkgs, lib, ... }:
let
cfg = config.steamFrame.uiPatches;
@@ -73,7 +75,10 @@ let
SteamVR restarts and reboots: the page reads it with
`window.__sfuiStore.get(name)` and writes it with
`window.__sfuiStore.set(name, value)` (see injector.mjs). The file
is user data and stays when the patch is removed.
is kept when the patch is disabled or removed (the choices come
back when it is enabled again) and removed by
`steam-frame-nix-cleanup --all` (also run by `install.sh
uninstall`).
'';
};
};
+3 -1
View File
@@ -34,7 +34,9 @@
// authoritative from then on. set() goes through the CDP binding
// window.__sfuiStoreSave('{"name","value"}'), which this process writes to the
// file (atomically, only on change, only for "state" patches of that target,
// at most 64 KiB). The file is user data: nothing deletes it.
// at most 64 KiB). The file is user data: kept when the patch is disabled or
// removed, deleted only by steam-frame-nix-cleanup --all (install.sh
// uninstall).
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';