mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 00:00:16 +02:00
Launchers: a neutral example app in docs and tests
The Nix-package launcher example in docs and option examples is now Signal (pkgs.signal-desktop, desktop ID "signal", sgnl:// and signalcaptcha:// handlers). The check uses a made-up org.example.App from a fake package (fake store path), covering the same Exec, action, MimeType, source and missing-entry cases. Screenshots: placeholder Steam account IDs in the docs, option example and check.
This commit is contained in:
1 parent
a01a49da45
commit
92e9d17e09
11 files changed
+83
-83
No files matched your search
+5
-5
@@ -27,7 +27,7 @@ the Frame's [two sessions](../README.md#two-sessions):
|
||||
reads through the Secret Service `org.freedesktop.secrets` (KRDC: "Password
|
||||
not found").
|
||||
- **Login callbacks:** SSO logins come back through a URL scheme
|
||||
(`io.element.desktop://`, `claude://`) opened by the portal. Unless the app
|
||||
(`io.element.desktop://`, `signalcaptcha://`) opened by the portal. Unless the app
|
||||
is the default and a recommended handler, the portal opens an app chooser,
|
||||
which isn't shown in VR.
|
||||
|
||||
@@ -80,11 +80,11 @@ A program from a Nix package, from the package's own entry
|
||||
|
||||
```nix
|
||||
{ pkgs, ... }: {
|
||||
home.packages = [ pkgs.claude-desktop ];
|
||||
steamFrame.launchers."com.anthropic.Claude" = {
|
||||
source.package = pkgs.claude-desktop;
|
||||
home.packages = [ pkgs.signal-desktop ];
|
||||
steamFrame.launchers.signal = {
|
||||
source.package = pkgs.signal-desktop;
|
||||
keyring = { enable = true; electron = true; };
|
||||
defaultFor = [ "x-scheme-handler/claude" ]; # login callback
|
||||
defaultFor = [ "x-scheme-handler/sgnl" "x-scheme-handler/signalcaptcha" ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ in `…/760/screenshots.vdf`). The JPG is the only copy that stays.
|
||||
|
||||
```nix
|
||||
steamFrame.screenshots.enable = true;
|
||||
# steamFrame.screenshots.steamUserId = "80511808"; # optional
|
||||
# steamFrame.screenshots.steamUserId = "12345678"; # optional
|
||||
```
|
||||
|
||||
The account ID is found at runtime: the account last logged in to Steam
|
||||
|
||||
@@ -41,10 +41,10 @@ let
|
||||
keyring = { enable = true; electron = true; };
|
||||
defaultFor = [ "x-scheme-handler/element" "x-scheme-handler/io.element.desktop" ];
|
||||
};
|
||||
steamFrame.launchers."com.anthropic.Claude" = {
|
||||
source.package = pkgs.claude-desktop;
|
||||
steamFrame.launchers.signal = {
|
||||
source.package = pkgs.signal-desktop;
|
||||
keyring = { enable = true; electron = true; };
|
||||
defaultFor = [ "x-scheme-handler/claude" ];
|
||||
defaultFor = [ "x-scheme-handler/sgnl" ];
|
||||
};
|
||||
(schemeHandlers = [ "x" ] -> defaultFor = [ "x-scheme-handler/x" ];
|
||||
flatpakArgs, args, mimeTypes, settings keep their meaning; name, icon,
|
||||
@@ -63,10 +63,10 @@ in {
|
||||
defaultFor = [ "x-scheme-handler/element" "x-scheme-handler/io.element.desktop" ];
|
||||
};
|
||||
"org.kde.krdc".keyring.enable = true;
|
||||
"com.anthropic.Claude" = {
|
||||
source.package = pkgs.claude-desktop;
|
||||
signal = {
|
||||
source.package = pkgs.signal-desktop;
|
||||
keyring = { enable = true; electron = true; };
|
||||
defaultFor = [ "x-scheme-handler/claude" ];
|
||||
defaultFor = [ "x-scheme-handler/sgnl" ];
|
||||
};
|
||||
}
|
||||
'';
|
||||
|
||||
+14
-14
@@ -1,8 +1,8 @@
|
||||
# Checks of steamFrame.launchers (lib.nix, rewrite.awk, generate.sh) on
|
||||
# copies of real entries (fixtures/sources: Element, KRDC, Firefox, gedit
|
||||
# (DBusActivatable) from /var/lib/flatpak, Jellyfin from the user
|
||||
# installation, Claude from the claude-desktop package) and two made-up ones
|
||||
# (quoting, an Exec without anchor):
|
||||
# installation) and three made-up ones (quoting, an Exec without anchor, an
|
||||
# Electron app from a fake package):
|
||||
# - the rewritten entries equal fixtures/expected (X-SteamFrameNix-Source
|
||||
# compared separately) and pass desktop-file-validate;
|
||||
# - the generator: unchanged sources change nothing (mtimes kept, no touch of
|
||||
@@ -19,9 +19,9 @@ let
|
||||
src = ./fixtures/sources;
|
||||
shim = "/nix/store/00000000000000000000000000000000-mpv-hwdec-shim";
|
||||
|
||||
fakeClaude = pkgs.runCommand "claude-desktop-fixture" { } ''
|
||||
fakeApp = pkgs.runCommand "example-app-fixture" { } ''
|
||||
mkdir -p $out/share/applications
|
||||
cp ${src}/com.anthropic.Claude.desktop $out/share/applications/
|
||||
cp ${src}/org.example.App.desktop $out/share/applications/
|
||||
'';
|
||||
noEntry = pkgs.runCommand "no-entry-fixture" { } "mkdir -p $out/share/applications";
|
||||
|
||||
@@ -58,10 +58,10 @@ let
|
||||
args = [ "a b" "50%" "q\"uote" "$HOME" "back\\slash" "back`tick" "" ];
|
||||
settings.Keywords = "x;";
|
||||
};
|
||||
"com.anthropic.Claude" = {
|
||||
source.package = fakeClaude;
|
||||
"org.example.App" = {
|
||||
source.package = fakeApp;
|
||||
keyring = { enable = true; electron = true; };
|
||||
defaultFor = [ "x-scheme-handler/claude" ];
|
||||
defaultFor = [ "x-scheme-handler/example" ];
|
||||
};
|
||||
};
|
||||
} ];
|
||||
@@ -81,14 +81,14 @@ let
|
||||
applicationsDir = "/nonexistent";
|
||||
exportDirs = [ "/nonexistent" ];
|
||||
};
|
||||
claude = L.packageEntry all."com.anthropic.Claude";
|
||||
missing = pkgs.testers.testBuildFailure (L.packageEntry (all."com.anthropic.Claude" // {
|
||||
source = all."com.anthropic.Claude".source // { package = noEntry; };
|
||||
app = L.packageEntry all."org.example.App";
|
||||
missing = pkgs.testers.testBuildFailure (L.packageEntry (all."org.example.App" // {
|
||||
source = all."org.example.App".source // { package = noEntry; };
|
||||
}));
|
||||
in
|
||||
pkgs.runCommand "launchers-check" {
|
||||
nativeBuildInputs = [ generator pkgs.desktop-file-utils pkgs.diffutils ];
|
||||
passthru = { inherit generator claude; };
|
||||
passthru = { inherit generator app; };
|
||||
} ''
|
||||
set -euo pipefail
|
||||
fail() { echo "FAIL: $*" >&2; exit 1; }
|
||||
@@ -127,12 +127,12 @@ pkgs.runCommand "launchers-check" {
|
||||
[ $id = org.example.NoAnchor ] && continue
|
||||
cp $out_dir/$id.desktop $out/actual/
|
||||
done
|
||||
cp ${claude} $out/actual/com.anthropic.Claude.desktop
|
||||
cp ${app} $out/actual/org.example.App.desktop
|
||||
grep -qx "X-SteamFrameNix-Source=$root/user/org.jellyfin.JellyfinDesktop.desktop" $out/actual/org.jellyfin.JellyfinDesktop.desktop \
|
||||
|| fail "Jellyfin not from the user installation"
|
||||
grep -qx "X-SteamFrameNix-Source=$root/system/org.kde.krdc.desktop" $out/actual/org.kde.krdc.desktop || fail "KRDC source"
|
||||
grep -qx "X-SteamFrameNix-Source=${src}/org.example.Quoting.desktop" $out/actual/org.example.Quoting.desktop || fail "file source"
|
||||
grep -qx "X-SteamFrameNix-Source=${fakeClaude}/share/applications/com.anthropic.Claude.desktop" $out/actual/com.anthropic.Claude.desktop || fail "package source"
|
||||
grep -qx "X-SteamFrameNix-Source=${fakeApp}/share/applications/org.example.App.desktop" $out/actual/org.example.App.desktop || fail "package source"
|
||||
sed -i 's|^X-SteamFrameNix-Source=.*|X-SteamFrameNix-Source=@SOURCE@|' $out/actual/*.desktop
|
||||
desktop-file-validate --no-hints $out/actual/*.desktop || fail "desktop-file-validate"
|
||||
for f in ${./fixtures/expected}/*.desktop; do
|
||||
@@ -185,7 +185,7 @@ pkgs.runCommand "launchers-check" {
|
||||
[ "$(mt $root/apps)" != 1000000000 ] || fail "removal didn't touch the applications dir"
|
||||
|
||||
# a package without the entry: the build fails
|
||||
[ -e ${missing}/testBuildFailure.log ] && grep -q "has no share/applications/com.anthropic.Claude.desktop" ${missing}/testBuildFailure.log \
|
||||
[ -e ${missing}/testBuildFailure.log ] && grep -q "has no share/applications/org.example.App.desktop" ${missing}/testBuildFailure.log \
|
||||
|| fail "package without the entry built"
|
||||
echo ok
|
||||
''
|
||||
@@ -1,26 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Claude
|
||||
Comment=Desktop application for Claude.ai
|
||||
GenericName=AI Assistant
|
||||
Keywords=AI;Chat;Assistant;Claude;Code;LLM;
|
||||
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop --password-store=kwallet6 %U
|
||||
Icon=claude-desktop
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
# Matches the Wayland app_id / X11 WM_CLASS Chromium derives from
|
||||
# package.json desktopName, so docks group windows under this entry.
|
||||
StartupWMClass=com.anthropic.Claude
|
||||
# second-instance just focuses mainWindow; suppress GNOME's default "New Window" item
|
||||
SingleMainWindow=true
|
||||
Categories=Utility;Development;
|
||||
MimeType=x-scheme-handler/claude;
|
||||
Actions=NewChat;NewCode;
|
||||
X-SteamFrameNix-Source=@SOURCE@
|
||||
|
||||
[Desktop Action NewChat]
|
||||
Name=New Chat
|
||||
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop --password-store=kwallet6 "claude://claude.ai/new?surface=chat&source=desktop_action"
|
||||
|
||||
[Desktop Action NewCode]
|
||||
Name=New Claude Code Session
|
||||
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop --password-store=kwallet6 "claude://code/new?source=desktop_action"
|
||||
@@ -0,0 +1,26 @@
|
||||
[Desktop Entry]
|
||||
Name=Example App
|
||||
Comment=A made-up Electron app from a Nix package
|
||||
GenericName=Example
|
||||
Keywords=Example;Test;
|
||||
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /nix/store/00000000000000000000000000000000-example-app-1.0/bin/example-app --password-store=kwallet6 %U
|
||||
Icon=example-app
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
# Matches the Wayland app_id / X11 WM_CLASS Electron derives from
|
||||
# package.json desktopName, so docks group windows under this entry.
|
||||
StartupWMClass=org.example.App
|
||||
# second-instance just focuses the main window
|
||||
SingleMainWindow=true
|
||||
Categories=Utility;Development;
|
||||
MimeType=x-scheme-handler/example;
|
||||
Actions=NewWindow;NewSession;
|
||||
X-SteamFrameNix-Source=@SOURCE@
|
||||
|
||||
[Desktop Action NewWindow]
|
||||
Name=New Window
|
||||
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /nix/store/00000000000000000000000000000000-example-app-1.0/bin/example-app --password-store=kwallet6 "example://app/new?surface=window&source=desktop_action"
|
||||
|
||||
[Desktop Action NewSession]
|
||||
Name=New Example Session
|
||||
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /nix/store/00000000000000000000000000000000-example-app-1.0/bin/example-app --password-store=kwallet6 "example://session/new?source=desktop_action"
|
||||
@@ -1,25 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Claude
|
||||
Comment=Desktop application for Claude.ai
|
||||
GenericName=AI Assistant
|
||||
Keywords=AI;Chat;Assistant;Claude;Code;LLM;
|
||||
Exec=/nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop %U
|
||||
Icon=claude-desktop
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
# Matches the Wayland app_id / X11 WM_CLASS Chromium derives from
|
||||
# package.json desktopName, so docks group windows under this entry.
|
||||
StartupWMClass=com.anthropic.Claude
|
||||
# second-instance just focuses mainWindow; suppress GNOME's default "New Window" item
|
||||
SingleMainWindow=true
|
||||
Categories=Utility;Development;
|
||||
MimeType=x-scheme-handler/claude;
|
||||
Actions=NewChat;NewCode;
|
||||
|
||||
[Desktop Action NewChat]
|
||||
Name=New Chat
|
||||
Exec=/nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop "claude://claude.ai/new?surface=chat&source=desktop_action"
|
||||
|
||||
[Desktop Action NewCode]
|
||||
Name=New Claude Code Session
|
||||
Exec=/nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop "claude://code/new?source=desktop_action"
|
||||
@@ -0,0 +1,25 @@
|
||||
[Desktop Entry]
|
||||
Name=Example App
|
||||
Comment=A made-up Electron app from a Nix package
|
||||
GenericName=Example
|
||||
Keywords=Example;Test;
|
||||
Exec=/nix/store/00000000000000000000000000000000-example-app-1.0/bin/example-app %U
|
||||
Icon=example-app
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
# Matches the Wayland app_id / X11 WM_CLASS Electron derives from
|
||||
# package.json desktopName, so docks group windows under this entry.
|
||||
StartupWMClass=org.example.App
|
||||
# second-instance just focuses the main window
|
||||
SingleMainWindow=true
|
||||
Categories=Utility;Development;
|
||||
MimeType=x-scheme-handler/example;
|
||||
Actions=NewWindow;NewSession;
|
||||
|
||||
[Desktop Action NewWindow]
|
||||
Name=New Window
|
||||
Exec=/nix/store/00000000000000000000000000000000-example-app-1.0/bin/example-app "example://app/new?surface=window&source=desktop_action"
|
||||
|
||||
[Desktop Action NewSession]
|
||||
Name=New Example Session
|
||||
Exec=/nix/store/00000000000000000000000000000000-example-app-1.0/bin/example-app "example://session/new?source=desktop_action"
|
||||
@@ -45,7 +45,7 @@ in rec {
|
||||
package = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.package;
|
||||
default = null;
|
||||
example = lib.literalExpression "pkgs.claude-desktop";
|
||||
example = lib.literalExpression "pkgs.signal-desktop";
|
||||
description = ''
|
||||
Nix package whose `share/applications/<desktop ID>.desktop` is
|
||||
rewritten at build time (the build fails if it has none).
|
||||
|
||||
@@ -25,7 +25,7 @@ in {
|
||||
steamUserId = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.strMatching "[1-9][0-9]*");
|
||||
default = null;
|
||||
example = "80511808";
|
||||
example = "12345678";
|
||||
description = ''
|
||||
Steam account ID: the folder name in ~/.local/share/Steam/userdata.
|
||||
`null`: the account last logged in, found at runtime.
|
||||
|
||||
@@ -19,16 +19,16 @@ pkgs.runCommand "screenshots-check" { nativeBuildInputs = [ script ]; } ''
|
||||
|
||||
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
|
||||
mkdir -p run $S/config $S/userdata/0 $S/userdata/12345678
|
||||
|
||||
# the only account folder ("0" is not an account)
|
||||
steam-frame-nix-screenshots; expect 80511808 "userdata"
|
||||
steam-frame-nix-screenshots; expect 12345678 "userdata"
|
||||
|
||||
# MostRecent wins over a later timestamp
|
||||
cat > $S/config/loginusers.vdf <<'VDF'
|
||||
"users"
|
||||
{
|
||||
"76561198040777536"
|
||||
"76561197972611406"
|
||||
{
|
||||
"AccountName" "a"
|
||||
"MostRecent" "1"
|
||||
@@ -42,7 +42,7 @@ pkgs.runCommand "screenshots-check" { nativeBuildInputs = [ script ]; } ''
|
||||
}
|
||||
}
|
||||
VDF
|
||||
steam-frame-nix-screenshots; expect 80511808 "MostRecent"
|
||||
steam-frame-nix-screenshots; expect 12345678 "MostRecent"
|
||||
# unchanged: not rewritten
|
||||
res=$(steam-frame-nix-screenshots 2>&1); [ -z "$res" ] || fail "rewrote: $res"
|
||||
|
||||
|
||||
Reference in new issue
Block a user