mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 06:00:22 +02:00
Dashboard patches: persist frame-controls placements and "Steam hidden" on disk
SteamOS's steamvr.service runs `rm -rf ~/.cache/SteamVR` on every SteamVR start, which deletes vrwebhelper's browser profile and with it the localStorage frame-controls kept its placements in, so they were lost on every SteamVR restart and reboot. steam-ui-patches: per-patch persistent state (`state = true`). The injector keeps ~/.local/state/steam-frame-nix/ui-patches/<name>.json, seeds window.__sfuiStore in a fresh page before the patch runs and writes the file (atomically, on change, name-checked, max 64 KiB) when the page calls the CDP binding __sfuiStoreSave. frame-controls v5: placements saved there (v4 localStorage copy migrated once, then removed). steam-close-button v8: "Steam hidden" saved there; a restored hidden state hides Steam once if SteamVR already shows it when the patch attaches (or first shows it before the patch sees Steam's frame). README: "Changes outside Nix" lists the directory; install.sh uninstall removes it.
This commit is contained in:
1 parent
48d10cc483
commit
7fe68e055c
10 files changed
+215
-34
No files matched your search
@@ -70,7 +70,9 @@ curl -fsSL https://steam-frame-nix.lhns.de | bash -s -- uninstall # --keep-nix
|
||||
|
||||
Uninstall stops the Home Manager user services (reverting the Steam keyboard
|
||||
patch), runs `home-manager uninstall`, then removes Nix and per-user Nix
|
||||
state. Your configuration, `*.hm-backup-*` files, app data and Flatpaks stay.
|
||||
state, and the dashboard patches' saved state (see
|
||||
[Changes outside Nix](#changes-outside-nix)). Your configuration,
|
||||
`*.hm-backup-*` files, app data and Flatpaks stay.
|
||||
|
||||
Manual setup: `nix flake init -t github:lhns/steam-frame-nix`.
|
||||
|
||||
@@ -297,6 +299,7 @@ dashboard features are such patches, and you can add your own:
|
||||
| `target.title` / `target.titleRegex` / `target.urlRegex` | `null` | Pages to patch; all given criteria must match (JS regexes). |
|
||||
| `patch` | | JS file evaluated in every matching page (awaited). |
|
||||
| `unpatch` | `null` | JS file evaluated when the service stops. |
|
||||
| `state` | `false` | Give the patch one persistent JSON value (below). |
|
||||
|
||||
```nix
|
||||
steamFrame.uiPatches.patches = [ {
|
||||
@@ -314,6 +317,22 @@ Patches are evaluated on attach, after new JS contexts (reloads) and every
|
||||
stock UI without a Steam restart. The service exists only while the list is
|
||||
non-empty and is restarted on every switch.
|
||||
|
||||
**Persistent state (`state = true`):** a patch's choices made in the UI
|
||||
can't be kept in the page's own storage: SteamOS's `steamvr.service` runs
|
||||
`rm -rf ~/.cache/SteamVR` (vrwebhelper's browser profile, incl.
|
||||
localStorage) on every SteamVR start. So the service keeps one JSON value
|
||||
per such patch in `~/.local/state/steam-frame-nix/ui-patches/<name>.json`
|
||||
(`$XDG_STATE_HOME`): before each evaluation it defines
|
||||
`window.__sfuiStore.get(name)` / `.set(name, value)` in the page and fills
|
||||
`get` from the file only while the page has no value yet (a fresh page after
|
||||
a SteamVR restart, reboot or reload). `set` goes through the DevTools
|
||||
binding `window.__sfuiStoreSave`; the service writes the file atomically,
|
||||
only on change, only for that page's `state` patches, at most 64 KiB. Used
|
||||
by the [window control bar](#window-control-bar-dashboardframecontrols)
|
||||
and the [Steam close button](#steam-close-button-dashboardsteamclosebuttonenable).
|
||||
The file is user data, not generated by Nix; see
|
||||
[Changes outside Nix](#changes-outside-nix).
|
||||
|
||||
**DevTools on the LAN:** Steam's Developer Mode enables
|
||||
`steam-web-debug-portforward` (`0.0.0.0:8081` → `8080`) and
|
||||
`steamvr-web-debug-portforward` (`0.0.0.0:8088` → `8087`), and firewalld
|
||||
@@ -665,8 +684,14 @@ dashboard window, or **just the dashboard bar** if there is none.
|
||||
Steam stays hidden until you bring it back (Steam tab, a Steam menu pick,
|
||||
SteamVR asking for it): closing the active window, or a theater window,
|
||||
then goes to the previous window or the bar instead of Steam. This
|
||||
survives dashboard reopens and patch-service restarts; a SteamVR restart
|
||||
starts with Steam. Debugging: `window.__sfuiSteamClose.plan()` /
|
||||
survives dashboard reopens, patch-service restarts, SteamVR restarts and
|
||||
reboots ("Steam hidden" is saved in
|
||||
`~/.local/state/steam-frame-nix/ui-patches/steam-close-button.json`, see
|
||||
[persistent state](#ui-patches-uipatchespatches)). After a restart the
|
||||
patch attaches a few seconds after the dashboard appears, possibly after
|
||||
SteamVR has already shown Steam: if Steam is (or first becomes) the active
|
||||
window then, it is hidden once like with X (only the bar at that point);
|
||||
otherwise it just stays hidden. Debugging: `window.__sfuiSteamClose.plan()` /
|
||||
`homePlan()` and `window.__sfuiSteamCloseState` in the `systemui` page.
|
||||
|
||||
**Limitations:** SteamVR's rarer "go home" paths (Now Playing after a game
|
||||
@@ -737,7 +762,10 @@ controller), and theater windows have no "Float".
|
||||
- **long press** a bar icon or menu row (`longPressMs`; a progress ring
|
||||
shows from half the time, at most after 1 s), then **Show in bar** in the
|
||||
popup moves that control between bar and menu **for all windows**.
|
||||
Placements survive SteamVR restarts.
|
||||
Placements survive SteamVR restarts and reboots (saved in
|
||||
`~/.local/state/steam-frame-nix/ui-patches/frame-controls.json`, see
|
||||
[persistent state](#ui-patches-uipatchespatches); version 4 kept them in
|
||||
localStorage, which SteamVR wipes on every start, and is migrated once).
|
||||
- `inBar` / `inMenu` set where controls start; a popup choice wins until
|
||||
that control's entry changes.
|
||||
- `floatInTheater` gives theater windows the "Float" control.
|
||||
@@ -756,7 +784,7 @@ on the curvature control adjusts curvature and cancels the long press, also
|
||||
after the ring shows; once the ring shows, the drag needs 3× the usual travel
|
||||
(`dragThresholdPixels`, counted from where the press started), so laser
|
||||
drift during the hold doesn't cancel it. Debugging: `window.__sfuiFrameControls.dump()`, `.placement()`,
|
||||
`.reset()` (forget choices), `.log`.
|
||||
`.reset()` (forget choices), `.log`, `window.__sfuiFrameControlsState`.
|
||||
|
||||
**Limitations:** laser only (no right-click or thumbstick click reaches the
|
||||
dashboard; gamepad navigation sees stock controls); placements are per
|
||||
@@ -894,6 +922,16 @@ services.flatpak.packages = [ "org.jellyfin.JellyfinDesktop" ];
|
||||
decoder fails; for streams that decode with artifacts, disable the option
|
||||
(or set `hwdec = "auto-copy"`, Jellyfin's own value).
|
||||
|
||||
## Changes outside Nix
|
||||
|
||||
Everything else is generated by Nix and linked from the store, or held in
|
||||
memory; these files are written at runtime and outlive a switch that turns
|
||||
the feature off:
|
||||
|
||||
| Path | What, why | Cleanup |
|
||||
|---|---|---|
|
||||
| `~/.local/state/steam-frame-nix/ui-patches/<name>.json` | Choices made in the dashboard: window control bar placements (`frame-controls.json`), "Steam hidden" (`steam-close-button.json`). Written by `steam-ui-patches` because SteamOS's `steamvr.service` deletes `~/.cache/SteamVR` (the dashboard's own browser storage) on every SteamVR start. Kept when a feature is disabled (your choices come back when you re-enable it). | `rm -rf ~/.local/state/steam-frame-nix/ui-patches` (also done by `install.sh uninstall`) |
|
||||
|
||||
## Rollback
|
||||
|
||||
`home-manager generations` lists previous generations; run
|
||||
|
||||
Reference in new issue
Block a user