mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 01:00:13 +02:00
- steam-keyboard-patch.nix -> vr-keyboard-extra-keys.nix (option
keyboard.vr.extraKeys), helper.mjs -> xdotool-helper.mjs;
homeManagerModules.steam-keyboard-patch stays as an alias.
- vr-keyboard: panel.js/unpatch-panel.js/relay.mjs ->
suggestions-panel/{patch,unpatch}.js + relay.mjs; decoder.js ->
swipe-decoder.js; build.nix split into dictionary.nix and check.nix.
- modules/lib -> modules/steam-ui-patches/lib (the UI patch library).
- docs/development.md: repository layout (what runs where), runtime names.
Patch names, user services and state files are unchanged.
161 lines
5.6 KiB
Nix
161 lines
5.6 KiB
Nix
# Runtime patches of Steam's and SteamVR's web UIs over local CEF DevTools
|
|
# (Steam 127.0.0.1:8080; SteamVR's vrwebhelper 127.0.0.1:8087, see
|
|
# steamvr-debugger.nix). The steam-ui-patches service (injector.mjs) injects
|
|
# each registered patch into its target pages, re-injects on reload and every
|
|
# 15 s, and runs the unpatches on stop; Steam's files are untouched.
|
|
# 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"), kept when the patch goes and removed by
|
|
# steam-frame-nix-cleanup --all. Patch calling convention (mkPatch) and the
|
|
# finder library: steam-ui-patches/lib/default.nix.
|
|
{ config, pkgs, lib, ... }:
|
|
let
|
|
cfg = config.steamFrame.uiPatches;
|
|
inherit (lib) mkOption types;
|
|
|
|
patchType = types.submodule {
|
|
options = {
|
|
name = mkOption {
|
|
type = types.strMatching "[A-Za-z0-9_.-]+";
|
|
example = "launcher-menu-order";
|
|
description = "Unique name, used in the service's log.";
|
|
};
|
|
endpoint = mkOption {
|
|
type = types.str;
|
|
default = "http://127.0.0.1:8080";
|
|
example = "http://127.0.0.1:8087";
|
|
description = ''
|
|
DevTools base URL (its /json/list is polled): Steam 8080, SteamVR
|
|
8087.
|
|
'';
|
|
};
|
|
target = {
|
|
title = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "SharedJSContext";
|
|
description = "Exact page title of the targets to patch.";
|
|
};
|
|
titleRegex = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = "JavaScript regex the page title must match.";
|
|
};
|
|
urlRegex = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = "JavaScript regex the page URL must match.";
|
|
};
|
|
};
|
|
patch = mkOption {
|
|
type = types.path;
|
|
description = ''
|
|
JavaScript evaluated (awaited) in every matching page after reloads
|
|
and every 15 s, so it must be idempotent. Its result is logged when
|
|
it changes ("unchanged" never is). Build with `lib.mkPatch` to get
|
|
the finder library.
|
|
'';
|
|
};
|
|
unpatch = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
description = ''
|
|
JavaScript that reverts the patch when the service stops; must be
|
|
safe on an unpatched page.
|
|
'';
|
|
};
|
|
state = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Give the patch one persistent JSON value (e.g. choices made in its
|
|
UI): `window.__sfuiStore.get(name)` / `.set(name, value)` in the
|
|
page, kept in $XDG_STATE_HOME/steam-frame-nix/ui-patches/<name>.json
|
|
across SteamVR restarts, reboots and disabling the patch; removed
|
|
by `steam-frame-nix-cleanup --all`.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
entry = p: {
|
|
inherit (p) name endpoint patch unpatch state;
|
|
target = lib.filterAttrs (_: v: v != null) p.target;
|
|
};
|
|
|
|
configFile = pkgs.writeText "steam-ui-patches.json" (builtins.toJSON {
|
|
pollMs = 5000;
|
|
reinjectMs = 15000;
|
|
debounceMs = 3000;
|
|
unpatchTimeoutMs = 2000;
|
|
patches = map entry cfg.patches;
|
|
});
|
|
in {
|
|
imports = [ ./session.nix ./cleanup.nix ];
|
|
|
|
options.steamFrame.uiPatches.lib = mkOption {
|
|
type = types.attrsOf types.raw;
|
|
readOnly = true;
|
|
default = import ./steam-ui-patches/lib { inherit pkgs; };
|
|
defaultText = lib.literalMD "the helpers of `modules/steam-ui-patches/lib`";
|
|
description = ''
|
|
Patch helpers from modules/steam-ui-patches/lib/default.nix:
|
|
`mkPatch { name, src, signatures ? …, opts ? { }, extraArgs ? [ ] }`
|
|
(calls `src` as `(find, sigs, opts, hooks, ...extraArgs) => …`; see
|
|
there), plus
|
|
`finders`, `hooks` (paths) and `signatures` (parsed signatures.json).
|
|
'';
|
|
};
|
|
|
|
options.steamFrame.uiPatches.patches = mkOption {
|
|
type = types.listOf patchType;
|
|
default = [ ];
|
|
example = lib.literalExpression ''
|
|
[ {
|
|
name = "my-patch";
|
|
target.title = "SharedJSContext";
|
|
patch = ./my-patch/patch.js;
|
|
unpatch = ./my-patch/unpatch.js;
|
|
} ]
|
|
'';
|
|
description = ''
|
|
Runtime patches of Steam's web UIs, kept injected by the
|
|
steam-ui-patches service and reverted when it stops. Every page
|
|
matching all given target criteria is patched.
|
|
'';
|
|
};
|
|
|
|
config = lib.mkMerge [
|
|
(lib.mkIf (cfg.patches != [ ]) {
|
|
assertions = [ {
|
|
assertion = lib.allUnique (map (p: p.name) cfg.patches);
|
|
message = "steamFrame.uiPatches.patches: names must be unique.";
|
|
} ];
|
|
|
|
systemd.user.services.steam-ui-patches = {
|
|
Unit.Description = "Runtime patches of Steam's UI (CEF DevTools)";
|
|
Service = {
|
|
ExecStart = lib.escapeShellArgs [
|
|
"${pkgs.nodejs}/bin/node"
|
|
"${./steam-ui-patches/injector.mjs}"
|
|
"${configFile}"
|
|
];
|
|
Restart = "always";
|
|
RestartSec = 5;
|
|
TimeoutStopSec = 5; # the injector unpatches Steam's UI on SIGTERM
|
|
};
|
|
Install.WantedBy = [ "default.target" ];
|
|
};
|
|
|
|
# Restart on switch: re-inject changed patches; the old instance reverts
|
|
# removed ones.
|
|
steamFrame.session.services.restart = [ "steam-ui-patches.service" ];
|
|
})
|
|
# No patches: stopping the injector reverts them right away.
|
|
(lib.mkIf (cfg.patches == [ ]) {
|
|
steamFrame.session.services.stop = [ "steam-ui-patches.service" ];
|
|
})
|
|
];
|
|
}
|