diff --git a/README.md b/README.md index f904a72..61063b4 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ configuration, limitations and how it works. - [Jellyfin](docs/jellyfin.md) (`jellyfin.hardwareDecoding`): hardware video decoding in the Jellyfin Desktop Flatpak. - [Launchers](docs/launchers.md) (`launchers.`): an app's own desktop entry (Flatpak, Nix package) with extra options, environment, wrappers and MIME defaults; `keyring` keeps its KDE wallet logins in both sessions (Electron too). - [Docker](docs/docker.md) (`docker`): rootless Docker as a user service, CLI working in both sessions. +- [SteamVR screenshots](docs/screenshots.md) (`screenshots`): `~/Pictures/SteamVR Screenshots`, a link to Steam's folder of the current account. **Your own patches** of Steam's UI, and fixing patches after a Steam update: [UI patches](docs/ui-patches.md). @@ -215,7 +216,7 @@ home-manager switch --flake .#steamos # manual setup, from the flake's director In your own flake, add the input as above and `steam-frame-nix.homeManagerModules.default` to the modules. `default` imports all modules; single ones: -`homeManagerModules.{session,portal,applications-menu,keyboard-layout,vr-keyboard-extra-keys,vr-keyboard,hidden-apps,steam-ui-patches,launcher-menu,steamvr-debugger,cleanup,dashboard-windows,steam-close-button,window-curvature,frame-controls,clipboard-sync,firefox,jellyfin,launchers,docker}` +`homeManagerModules.{session,portal,applications-menu,keyboard-layout,vr-keyboard-extra-keys,vr-keyboard,hidden-apps,steam-ui-patches,launcher-menu,steamvr-debugger,cleanup,dashboard-windows,steam-close-button,window-curvature,frame-controls,clipboard-sync,firefox,jellyfin,launchers,docker,screenshots}` (`steam-keyboard-patch` and `keyring` still work as the former names of `vr-keyboard-extra-keys` and `launchers`). Every module imports `cleanup` (see [Changes outside Nix](#changes-outside-nix-exceptions)); which file is @@ -326,6 +327,9 @@ which: [Repository layout](docs/development.md). | `steamFrame.docker.enable` | bool | `false` | Rootless Docker as a user service, CLI for both sessions, see [Docker](docs/docker.md). | | `steamFrame.docker.package` | package | `pkgs.docker` | Docker package (daemon and CLI). | | `steamFrame.docker.host` | str, read-only | `"unix://${runtimeDir}/docker.sock"` | The daemon's `DOCKER_HOST` (the CLI's default). | +| `steamFrame.screenshots.enable` | bool | `false` | Link `~/Pictures/` to the SteamVR screenshots, see [SteamVR screenshots](docs/screenshots.md). | +| `steamFrame.screenshots.name` | str | `"SteamVR Screenshots"` | Name of the link in `~/Pictures`. | +| `steamFrame.screenshots.steamUserId` | null or str (digits) | `null` | Steam account ID (folder in `~/.local/share/Steam/userdata`); `null`: the account last logged in, found at runtime. | | `steamFrame.cleanup.package` | package, read-only | | `steam-frame-nix-cleanup` (on `PATH` too), see [Changes outside Nix](#changes-outside-nix-exceptions). | Renamed options still work under their old names, with a warning: @@ -363,6 +367,7 @@ lives in memory (the UI patches). These are written at runtime: | `/run/user/1000/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf`, `/run/user/1000/steam-frame-nix/steamvr-debugger-restore` | SteamVR debugger: puts the key back when SteamVR stops, without Nix | until reboot (tmpfs) | reboot; `steam-frame-nix-cleanup` while SteamVR is stopped and the debugger is off | | `~/.local/state/steam-frame-nix/ui-patches/.json` | Saved choices of dashboard patches ([persistent state](docs/ui-patches.md#persistent-state)): window control bar placements (`frame-controls`), "Steam hidden" (`steam-close-button`). SteamOS's `steamvr.service` deletes `~/.cache/SteamVR` (the dashboard's own browser storage) on every SteamVR start. | until removed: kept when a patch is disabled (the choices come back when you enable it again) | `steam-frame-nix-cleanup --all`, `install.sh uninstall` | | `/run/user/1000/steam-frame-nix/applications/.desktop` (with `..desktop.sum`, `.lock`) | [Launchers](docs/launchers.md) of Flatpaks and host files; `~/.local/share/applications/.desktop` is a Home Manager link to it | until reboot (tmpfs), written again at login | reboot; the next switch or rewrite when the launcher or its app is gone; `steam-frame-nix-cleanup --all` | +| `/run/user/1000/steam-frame-nix/screenshots` | [SteamVR screenshots](docs/screenshots.md#how-it-works) without `steamUserId`: link to the current account's folder; `~/Pictures/` is a Home Manager link to it | until reboot (tmpfs), written again at login | reboot; `steam-frame-nix-cleanup` once unused | | mtime of `~/.local/share/applications` | [Launchers](docs/launchers.md#how-it-works): a running Steam rescans the "+" menu | only the directory's timestamp | nothing to remove | | mtime of `~/.local/share/icons/hicolor` | [icon fallbacks](docs/launcher-menu.md#icon-fallbacks): a running Steam rescans icons | only the directory's timestamp | nothing to remove | diff --git a/docs/cleanup.md b/docs/cleanup.md index 93cc61a..b9e9fae 100644 --- a/docs/cleanup.md +++ b/docs/cleanup.md @@ -26,6 +26,7 @@ is reported as "left alone" and never touched: | `jellyfin` | the hwdec shim entries in the Jellyfin Flatpak's user override `~/.local/share/flatpak/overrides/org.jellyfin.JellyfinDesktop` (nix-flatpak), an empty override file, and the shim copy of earlier versions in `~/.var/app/org.jellyfin.JellyfinDesktop` (marker `~/.local/state/steam-frame-nix/jellyfin-hwdec-shim`) | | `ui-state`: `~/.local/state/steam-frame-nix/ui-patches/.json` | the dashboard patches' saved choices; `--all` only, never `--orphans`; stray `*.json.tmp` files | | `launchers`: `/run/user/1000/steam-frame-nix/applications` | the entries of [launchers](launchers.md) (tmpfs); `--all` only (switches remove those of removed launchers themselves) | +| `screenshots`: `/run/user/1000/steam-frame-nix/screenshots` | a link to `*/userdata/*/760/remote/250820/screenshots` ([SteamVR screenshots](screenshots.md)); kept by `--orphans --keep screenshots` (while `steamUserId` is unset) | | `dirs` | `~/.local/state/steam-frame-nix` and `/run/user/1000/steam-frame-nix` when empty | ### Left by older versions diff --git a/docs/development.md b/docs/development.md index 2768b01..8e01254 100644 --- a/docs/development.md +++ b/docs/development.md @@ -64,6 +64,11 @@ modules/ of Flatpaks/host files in /steam-frame-nix/applications check.nix, fixtures/ test: real entries rewritten (fixtures/expected), generator runs docker.nix service: rootless dockerd (docker) + screenshots.nix ~/Pictures link to the SteamVR screenshots (screenshots) + screenshots/ + link.sh, package.nix service steam-frame-nix-screenshots (+ .path), switch: + /steam-frame-nix/screenshots -> account folder + check.nix test: account detection on fake Steam dirs firefox.nix Flatpak prefs extension and launcher (firefox) firefox/wrapper.nix app: launcher wrapper (desktop profile, fullscreen fix) firefox/check.nix test: wrapper against a fake flatpak @@ -128,6 +133,7 @@ they are kept even where a file name says more: | `frame-controls` | `dashboard.frameControls` | `frame-controls` (SteamVR, state) | `steam-ui-patches` | | `steamvr-debugger` | `steamvrDebugger` | | `steamvr-webhelper-debugger` | | `launchers` | `launchers` | | `steam-frame-nix-launchers` (`.service`, `.path`) | +| `screenshots` | `screenshots` | | `steam-frame-nix-screenshots` (`.service`, `.path`) | Log of all patches: `journalctl --user -u steam-ui-patches -u steam-keyboard-patch -u vr-keyboard-relay`. diff --git a/docs/screenshots.md b/docs/screenshots.md new file mode 100644 index 0000000..00f70cf --- /dev/null +++ b/docs/screenshots.md @@ -0,0 +1,54 @@ +# SteamVR screenshots + +`screenshots.*`, module `screenshots`. Options: +[README, Options](../README.md#options). + +## Problem + +Steam keeps VR screenshots deep in its data directory, under the Steam +account ID, where Dolphin, Gwenview and the file pickers don't look. + +## What you get + +`~/Pictures/SteamVR Screenshots` (`screenshots.name`), a link to Steam's +folder of SteamVR screenshots (app 250820): +`~/.local/share/Steam/userdata//760/remote/250820/screenshots`. +Nothing is copied; the link goes away when you turn the option off. + +**Taking a screenshot:** hold the Steam button and click a trigger +(SteamVR's `TakeScreenshot` chord). Steam writes the capture as a PNG to +`/run/user/1000/Screenshot_*.png` (tmpfs, temporary), then imports it as a +1920x1080 JPG into the folder above (small copies in `thumbnails/`, listed +in `…/760/screenshots.vdf`). The JPG is the only copy that stays. + +## Configuration + +```nix +steamFrame.screenshots.enable = true; +# steamFrame.screenshots.steamUserId = "80511808"; # optional +``` + +The account ID is found at runtime: the account last logged in to Steam +(`MostRecent`, else the latest `timestamp` in +`~/.local/share/Steam/config/loginusers.vdf`), else the only folder in +`~/.local/share/Steam/userdata`; it follows when you switch accounts. +`steamUserId` (the folder name, `ls ~/.local/share/Steam/userdata`) fixes +it instead: a plain Home Manager link, no service. + +## Caveats + +- Steam creates the folder with the first screenshot: until then the link + points nowhere. +- Only SteamVR's folder is linked; screenshots Steam files under another app + are in `…/760/remote//screenshots`. +- Without `steamUserId`, when no account is found there is no link (the + service warns in `journalctl --user -u steam-frame-nix-screenshots`). + +## How it works + +Without `steamUserId`, `~/Pictures/` is a Home Manager link to +`/run/user/1000/steam-frame-nix/screenshots`, a link that the oneshot user +service `steam-frame-nix-screenshots` points to the account's folder: on +switch, at login and when `loginusers.vdf` or `userdata` changes (path +unit). Its lifetime and cleanup: +[Changes outside Nix](../README.md#changes-outside-nix-exceptions). diff --git a/flake.nix b/flake.nix index 54126f8..495760e 100644 --- a/flake.nix +++ b/flake.nix @@ -37,6 +37,7 @@ jellyfin = ./modules/jellyfin.nix; launchers = ./modules/launchers.nix; docker = ./modules/docker.nix; + screenshots = ./modules/screenshots.nix; }; # Former attribute names, kept so existing imports keep working (not in # `default`, which imports each module once under its current name). @@ -67,8 +68,8 @@ # Tests of the VR keyboard (text model, corrector, swipe decoder on the # default German + English dictionary), the extra keys' xdotool # allowlist, the Jellyfin mpv shim, the Firefox wrapper, the launchers, - # install.sh cleanup, the applications.menu link and the portal config: - # nix flake check + # install.sh cleanup, the applications.menu link, the portal config and + # the screenshots account detection: nix flake check checks = forSystems (pkgs: { applications-menu = import ./modules/applications-menu/check.nix { inherit pkgs; }; cleanup = import ./modules/cleanup/check.nix { inherit pkgs; }; @@ -76,6 +77,7 @@ jellyfin = import ./modules/jellyfin/check.nix { inherit pkgs; }; launchers = import ./modules/launchers/check.nix { inherit pkgs; }; portal = import ./modules/portal/check.nix { inherit pkgs; }; + screenshots = import ./modules/screenshots/check.nix { inherit pkgs; }; vr-keyboard = import ./modules/vr-keyboard/check.nix { inherit pkgs; }; vr-keyboard-extra-keys = import ./modules/vr-keyboard-extra-keys/check.nix { inherit pkgs; }; }); diff --git a/install.sh b/install.sh index de24632..6c5b614 100755 --- a/install.sh +++ b/install.sh @@ -74,7 +74,7 @@ Commands: or before removing it. --orphans what the configuration no longer uses (run by the Home Manager module on every switch); keeps saved choices. - --keep still in use (with --orphans): debugger + --keep still in use (with --orphans): debugger, screenshots --dry-run only print what would be done --quiet print only actions, deferrals and warnings SteamVR's VRWebHelper.DebuggerEnabled can't be changed while SteamVR @@ -410,6 +410,9 @@ EOF # launchers entries of steamFrame.launchers in # $OUTER_RUNTIME_DIR/steam-frame-nix/applications (tmpfs; --all # only: the switch's own run removes those of removed launchers). +# screenshots the link $OUTER_RUNTIME_DIR/steam-frame-nix/screenshots +# (tmpfs) to a SteamVR screenshot folder +# (*/userdata//760/remote/250820/screenshots). # dirs $SFN_STATE and $OUTER_RUNTIME_DIR/steam-frame-nix when empty. # # --orphans keeps what the current configuration still uses (--keep ...); @@ -839,6 +842,19 @@ clean_launchers() { c_rmdir "$d" } +# --- screenshots link (tmpfs) --- + +clean_screenshots() { # keep + local l=$SFN_RUNTIME/screenshots + (( $1 )) && return 0 + [[ -L $l ]] || return 0 + if [[ $(readlink "$l") == */userdata/*/760/remote/250820/screenshots ]]; then + c_rm "$l" "link to the SteamVR screenshots" + else + c_left "$l (not a link to SteamVR screenshots)" + fi +} + # --- dashboard patch state --- clean_ui_state() { # all @@ -859,7 +875,7 @@ clean_ui_state() { # all } cmd_cleanup() { - local mode='' keep_debugger=0 keeps=0 k + local mode='' keep_debugger=0 keep_screenshots=0 keeps=0 k while (( $# )); do case $1 in --all) mode=all; shift ;; @@ -871,7 +887,8 @@ cmd_cleanup() { k=$2; shift 2; keeps=$((keeps + 1)) case $k in debugger) keep_debugger=1 ;; - *) die "cleanup: unknown artifact '$k' for --keep (debugger)" ;; + screenshots) keep_screenshots=1 ;; + *) die "cleanup: unknown artifact '$k' for --keep (debugger, screenshots)" ;; esac ;; -h|--help) usage; exit 0 ;; *) die "cleanup: unknown option '$1' (see --help)" ;; @@ -891,6 +908,7 @@ cmd_cleanup() { clean_jellyfin clean_ui_state "$([[ $mode == all ]] && echo 1 || echo 0)" c_rmdir "$SFN_STATE" + clean_screenshots "$keep_screenshots" if [[ $mode == all ]]; then clean_launchers; c_rmdir "$SFN_RUNTIME"; fi (( CLEAN_ACTIONS || ${#CLEAN_DEFERRED[@]} || CLEAN_QUIET )) || info "nothing to clean up" return 0 diff --git a/modules/cleanup/check.nix b/modules/cleanup/check.nix index 7696a05..44ec857 100644 --- a/modules/cleanup/check.nix +++ b/modules/cleanup/check.nix @@ -57,6 +57,8 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } '' echo '[Desktop Entry]' > $root/run/steam-frame-nix/applications/im.riot.Riot.desktop echo x > $root/run/steam-frame-nix/applications/.im.riot.Riot.desktop.sum : > $root/run/steam-frame-nix/applications/.lock + ln -s $HOME/.local/share/Steam/userdata/1/760/remote/250820/screenshots \ + $root/run/steam-frame-nix/screenshots # steamFrame.screenshots echo old > $root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf echo keep > $root/run/systemd/user/steamvr.service.d/other.conf ln -s /nix/store/00000000000000000000000000000000-breeze-icons-6.30.0/share/icons/breeze/apps/64/utilities-terminal.svg $I/utilities-terminal.svg @@ -191,6 +193,17 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } '' exec 8<&- # Firefox closed res=$(steam-frame-nix-cleanup --orphans) gone $F/desktop/user.js + # screenshots link: kept while used, a foreign link left alone + mkdir -p $root/run/steam-frame-nix + ln -s /x/userdata/1/760/remote/250820/screenshots $root/run/steam-frame-nix/screenshots + res=$(steam-frame-nix-cleanup --orphans --keep screenshots) + there $root/run/steam-frame-nix/screenshots + res=$(steam-frame-nix-cleanup --orphans) + gone $root/run/steam-frame-nix/screenshots + ln -s /elsewhere $root/run/steam-frame-nix/screenshots + res=$(steam-frame-nix-cleanup --orphans) + has "$res" "left alone: $root/run/steam-frame-nix/screenshots" + rm -r $root/run/steam-frame-nix ! steam-frame-nix-cleanup --all --keep debugger 2>/dev/null || fail "--all --keep accepted" ! steam-frame-nix-cleanup --orphans --keep bogus 2>/dev/null || fail "unknown --keep accepted" echo "C ok" diff --git a/modules/screenshots.nix b/modules/screenshots.nix new file mode 100644 index 0000000..ecff34c --- /dev/null +++ b/modules/screenshots.nix @@ -0,0 +1,73 @@ +# ~/Pictures/: a link to Steam's folder of SteamVR screenshots +# (docs/screenshots.md). With steamUserId a plain Home Manager link; without, +# it points to /steam-frame-nix/screenshots (tmpfs), +# which steam-frame-nix-screenshots (screenshots/link.sh) points to the +# current account's folder: on switch, at login and when loginusers.vdf or +# userdata changes (path unit). +{ config, lib, pkgs, ... }: +let + cfg = config.steamFrame.screenshots; + session = config.steamFrame.session; + steam = "${config.home.homeDirectory}/.local/share/Steam"; + detect = cfg.enable && cfg.steamUserId == null; + script = import ./screenshots/package.nix { inherit lib pkgs steam; inherit (session) runtimeDir; }; + exe = lib.getExe script; +in { + imports = [ ./cleanup.nix ]; + + options.steamFrame.screenshots = { + enable = lib.mkEnableOption "a link to the SteamVR screenshots in ~/Pictures"; + name = lib.mkOption { + type = lib.types.str; + default = "SteamVR Screenshots"; + description = "Name of the link in ~/Pictures."; + }; + steamUserId = lib.mkOption { + type = lib.types.nullOr (lib.types.strMatching "[1-9][0-9]*"); + default = null; + example = "80511808"; + description = '' + Steam account ID: the folder name in ~/.local/share/Steam/userdata. + `null`: the account last logged in, found at runtime. + ''; + }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + home.file."Pictures/${cfg.name}".source = config.lib.file.mkOutOfStoreSymlink + (if detect then "${session.runtimeDir}/steam-frame-nix/screenshots" + else "${steam}/userdata/${cfg.steamUserId}/760/remote/250820/screenshots"); + } + (lib.mkIf detect { + steamFrame.cleanup.keep = [ "screenshots" ]; + home.packages = [ script ]; + + systemd.user.services.steam-frame-nix-screenshots = { + Unit.Description = "steam-frame-nix: link to the SteamVR screenshots of the current Steam account"; + Service = { + Type = "oneshot"; + ExecStart = exe; + }; + Install.WantedBy = [ "default.target" ]; + }; + systemd.user.paths.steam-frame-nix-screenshots = { + Unit.Description = "steam-frame-nix: update the screenshots link when the Steam account changes"; + Path = { + PathChanged = [ "${steam}/config/loginusers.vdf" "${steam}/userdata" ]; + Unit = "steam-frame-nix-screenshots.service"; + }; + Install.WantedBy = [ "default.target" ]; + }; + steamFrame.session.services.start = [ "steam-frame-nix-screenshots.path" ]; + + home.activation.steamFrameScreenshots = lib.hm.dag.entryAfter [ "linkGeneration" "steamFrameNixCleanup" ] '' + if [[ -v DRY_RUN ]]; then + echo "would run: ${exe}" + else + ${exe} + fi + ''; + }) + ]); +} diff --git a/modules/screenshots/check.nix b/modules/screenshots/check.nix new file mode 100644 index 0000000..e24a550 --- /dev/null +++ b/modules/screenshots/check.nix @@ -0,0 +1,58 @@ +# Checks of steam-frame-nix-screenshots (link.sh) on fake Steam and runtime +# dirs: account from loginusers.vdf (MostRecent, else latest timestamp), +# else the only userdata folder, else no link (an old one removed); an +# unchanged target isn't rewritten; no outer runtime dir is a no-op. +{ pkgs }: +let + script = import ./package.nix { + inherit (pkgs) lib; inherit pkgs; + runtimeDir = "/nonexistent"; steam = "/nonexistent"; + }; +in +pkgs.runCommand "screenshots-check" { nativeBuildInputs = [ script ]; } '' + set -euo pipefail + fail() { echo "FAIL: $*" >&2; exit 1; } + export STEAM_FRAME_NIX_RUNTIME_DIR=$PWD/run STEAM_FRAME_NIX_STEAM_DIR=$PWD/steam + S=$STEAM_FRAME_NIX_STEAM_DIR L=$STEAM_FRAME_NIX_RUNTIME_DIR/steam-frame-nix/screenshots + target() { echo "$S/userdata/$1/760/remote/250820/screenshots"; } + expect() { [ "$(readlink $L)" = "$(target $1)" ] || fail "$2: $(readlink $L || echo no link)"; } + + steam-frame-nix-screenshots 2>&1 | grep -q "doesn't exist" || fail "no runtime dir" + [ ! -e run ] || fail "runtime dir created" + mkdir -p run $S/config $S/userdata/0 $S/userdata/80511808 + + # the only account folder ("0" is not an account) + steam-frame-nix-screenshots; expect 80511808 "userdata" + + # MostRecent wins over a later timestamp + cat > $S/config/loginusers.vdf <<'VDF' +"users" +{ + "76561198040777536" + { + "AccountName" "a" + "MostRecent" "1" + "timestamp" "100" + } + "76561197960265729" + { + "AccountName" "b" + "MostRecent" "0" + "timestamp" "200" + } +} +VDF + steam-frame-nix-screenshots; expect 80511808 "MostRecent" + # unchanged: not rewritten + res=$(steam-frame-nix-screenshots 2>&1); [ -z "$res" ] || fail "rewrote: $res" + + # no MostRecent (current Steam): latest timestamp + sed -i '/MostRecent/d' $S/config/loginusers.vdf + steam-frame-nix-screenshots; expect 1 "timestamp" + + # nothing to go by: link removed + rm $S/config/loginusers.vdf; mkdir $S/userdata/42 + steam-frame-nix-screenshots 2>&1 | grep -q "no Steam account" || fail "no warning" + [ ! -L $L ] || fail "link kept" + touch $out +'' diff --git a/modules/screenshots/link.sh b/modules/screenshots/link.sh new file mode 100644 index 0000000..c31f349 --- /dev/null +++ b/modules/screenshots/link.sh @@ -0,0 +1,54 @@ +# steam-frame-nix-screenshots (the module prepends runtime, steam): points +# /steam-frame-nix/screenshots (tmpfs), where ~/Pictures/ +# links, to the SteamVR screenshot folder of the Steam account last logged +# in: +# 1. the user marked MostRecent "1" in config/loginusers.vdf, else the one +# with the latest "timestamp" (SteamID64 - 76561197960265728 = account +# ID, the folder in userdata); +# 2. else the only account folder in userdata; +# 3. else no link (warning). +# The link is replaced atomically and only when its target changes. +link=$runtime/steam-frame-nix/screenshots +log() { echo "steam-frame-nix-screenshots: $*" >&2; } + +if [[ ! -d $runtime ]]; then + log "$runtime doesn't exist (outer session not running?); skipped" + exit 0 +fi + +id='' +if [[ -f $steam/config/loginusers.vdf ]]; then + id64=$(awk ' + { gsub(/"/, " ") } + $1 == "{" { depth++; next } + $1 == "}" { depth--; next } + depth == 1 && $1 ~ /^[0-9]+$/ && NF == 1 { user = $1; next } + depth == 2 && tolower($1) == "mostrecent" && $2 == "1" { recent = user } + depth == 2 && tolower($1) == "timestamp" && $2 + 0 > best { best = $2 + 0; latest = user } + END { print recent != "" ? recent : latest } + ' "$steam/config/loginusers.vdf") + if [[ $id64 =~ ^[0-9]{17}$ ]] && (( id64 > 76561197960265728 )); then + id=$(( id64 - 76561197960265728 )) + fi +fi +if [[ -z $id ]]; then + dirs=() + for d in "$steam"/userdata/*/; do + d=${d%/}; d=${d##*/} + [[ $d =~ ^[1-9][0-9]*$ ]] && dirs+=("$d") + done + (( ${#dirs[@]} == 1 )) && id=${dirs[0]} +fi + +if [[ -z $id ]]; then + log "no Steam account found in $steam (log in to Steam, or set steamFrame.screenshots.steamUserId); no link" + [[ -L $link ]] && rm -f "$link" + exit 0 +fi + +target=$steam/userdata/$id/760/remote/250820/screenshots +[[ -L $link && $(readlink "$link") == "$target" ]] && exit 0 +mkdir -p "${link%/*}" +ln -sfn "$target" "$link.tmp.$$" +mv -fT "$link.tmp.$$" "$link" +log "$link -> $target" diff --git a/modules/screenshots/package.nix b/modules/screenshots/package.nix new file mode 100644 index 0000000..2f11e04 --- /dev/null +++ b/modules/screenshots/package.nix @@ -0,0 +1,11 @@ +# steam-frame-nix-screenshots: link.sh with the outer runtime dir and the +# Steam directory (both overridable by environment, for the check). +{ lib, pkgs, runtimeDir, steam }: +pkgs.writeShellApplication { + name = "steam-frame-nix-screenshots"; + runtimeInputs = [ pkgs.coreutils pkgs.gawk ]; + text = '' + runtime=''${STEAM_FRAME_NIX_RUNTIME_DIR:-${lib.escapeShellArg runtimeDir}} + steam=''${STEAM_FRAME_NIX_STEAM_DIR:-${lib.escapeShellArg steam}} + '' + builtins.readFile ./link.sh; +}