diff --git a/nixos/flake.lock b/nixos/flake.lock index 5e45714f..6564da8b 100644 --- a/nixos/flake.lock +++ b/nixos/flake.lock @@ -278,11 +278,11 @@ "rust-analyzer-src": "rust-analyzer-src_2" }, "locked": { - "lastModified": 1769842381, - "narHash": "sha256-0dPzo1ElvAIZ0RwEwx5FfqAUiFj22K9QJOU9stiMCrw=", + "lastModified": 1777708550, + "narHash": "sha256-Qif3UXT0l5OQq8H9pRWt4/ia4gF48MWK2oHKL8uVx8U=", "owner": "nix-community", "repo": "fenix", - "rev": "b2344f384a82db1410ab09769eb8c4a820de667f", + "rev": "74c1591efaff494756b8d35ebe357c6c2bbdca96", "type": "github" }, "original": { @@ -1217,11 +1217,11 @@ ] }, "locked": { - "lastModified": 1777742447, - "narHash": "sha256-NXU/DH7YmgJ8C3vdcQqxP1TfI9vBeJiN46pAp/OuaCg=", + "lastModified": 1778046887, + "narHash": "sha256-np9C++JA/OgdiPBIkLwRmpEGS8YKDzxs6hy2dn5buPw=", "owner": "colonelpanic8", "repo": "keepbook", - "rev": "f5ae6de3d4145410df90ffb291b297cf12ad1067", + "rev": "8cf913fd43270da40034a90fe81019b39cba76da", "type": "github" }, "original": { @@ -1838,11 +1838,11 @@ "rust-analyzer-src_2": { "flake": false, "locked": { - "lastModified": 1769786006, - "narHash": "sha256-ax6cH54Nc20QuxlHNC8RMt1P8quMECY4gaACFAdd5ec=", + "lastModified": 1777639980, + "narHash": "sha256-6d7Hdurvbjc5uwJuc0YiK7rZBGj6Gs3uzfBFcTs+xCc=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "eb0588812b041ebbf2645555f2a4df3bcd853c6d", + "rev": "64cdaeb06f69b6b769a492edd88b022ae88e8ca2", "type": "github" }, "original": { diff --git a/nixos/flake.nix b/nixos/flake.nix index 4d62586d..9981694c 100644 --- a/nixos/flake.nix +++ b/nixos/flake.nix @@ -245,7 +245,6 @@ url = "github:noctalia-dev/noctalia-shell"; inputs.nixpkgs.follows = "nixpkgs"; }; - }; outputs = inputs @ { @@ -266,10 +265,10 @@ ... }: let # Nixpkgs PR patches - just specify PR number and hash - nixpkgsPRPatches = [ ]; + nixpkgsPRPatches = []; # Custom patches that don't fit the PR template - nixpkgsCustomPatches = [ ]; + nixpkgsCustomPatches = []; # Home-manager PR patches - just specify PR number and hash homeManagerPRPatches = [ @@ -328,7 +327,7 @@ builtins.listToAttrs (map mkConfigurationParams machineFilenames); # Build org-agenda-api container for a given system mkOrgAgendaApiContainerInfo = system: let - pkgs = import nixpkgs { inherit system; }; + pkgs = import nixpkgs {inherit system;}; orgApiRev = builtins.substring 0 7 (org-agenda-api.rev or "unknown"); dotfilesRev = builtins.substring 0 7 (self.rev or self.dirtyRev or "dirty"); dotfilesOrgApi = import ./org-agenda-api.nix { @@ -402,15 +401,21 @@ then home-manager.nixosModules.home-manager else import "${patchedHomeManagerSource}/nixos"; # Create a modified inputs with patched home-manager - patchedInputs = inputs // { - home-manager = inputs.home-manager // { - nixosModules = inputs.home-manager.nixosModules // { - home-manager = patchedHomeManagerModule; - }; - # Also provide the patched source path for any direct imports - outPath = patchedHomeManagerSource.outPath or "${patchedHomeManagerSource}"; + patchedInputs = + inputs + // { + home-manager = + inputs.home-manager + // { + nixosModules = + inputs.home-manager.nixosModules + // { + home-manager = patchedHomeManagerModule; + }; + # Also provide the patched source path for any direct imports + outPath = patchedHomeManagerSource.outPath or "${patchedHomeManagerSource}"; + }; }; - }; in evalConfig { inherit system; @@ -435,262 +440,268 @@ } // specialArgs; }; - in { - nixConfig = { - substituters = [ - "https://cache.nixos.org/" - ]; - trusted-public-keys = [ - "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" - ]; - extra-substituters = [ - "http://192.168.1.26:5050" - "https://ai.cachix.org" - "https://cache.nixos-cuda.org" - "https://nix-community.cachix.org" - "https://cuda-maintainers.cachix.org" - "https://numtide.cachix.org" - "https://cache.flox.dev" - "https://org-agenda-api.cachix.org" - "https://colonelpanic8-dotfiles.cachix.org" - "https://codex-cli.cachix.org" - "https://claude-code.cachix.org" - "https://noctalia.cachix.org" - ]; - extra-trusted-substituters = [ - "https://ai.cachix.org" - "https://cache.nixos.org/" - "https://nix-community.cachix.org" - "https://cache.nixos-cuda.org" - "https://cuda-maintainers.cachix.org" - "https://numtide.cachix.org" - ]; - extra-trusted-public-keys = [ - "1896Folsom.duckdns.org:U2FTjvP95qwAJo0oGpvmUChJCgi5zQoG1YisoI08Qoo=" - "ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc=" - "cache.nixos-cuda.org:74DUi4Ye579gUqzH4ziL9IyiJBlDpMRn9MBN8oNan9M=" - "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" - "cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E=" - "numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE=" - "flox-cache-public-1:7F4OyH7ZCnFhcze3fJdfyXYLQw/aV7GEed86nQ7IsOs=" - "org-agenda-api.cachix.org-1:liKFemKkOLV/rJt2txDNcpDjRsqLuBneBjkSw/UVXKA=" - "colonelpanic8-dotfiles.cachix.org-1:O6GF3nptpeMFapX29okzO92eSWXR36zqW6ZF2C8P0eQ=" - "codex-cli.cachix.org-1:1Br3H1hHoRYG22n//cGKJOk3cQXgYobUel6O8DgSing=" - "claude-code.cachix.org-1:YeXf2aNu7UTX8Vwrze0za1WEDS+4DuI2kVeWEE4fsRk=" - "noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4=" - ]; - }; - nixosConfigurations = - builtins.mapAttrs ( - machineName: params: let - machineParams = - if builtins.hasAttr machineName customParams - then (builtins.getAttr machineName customParams) - else {}; - in - mkConfig (params // machineParams) - ) - defaultConfigurationParams; - } // flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { inherit system; }; - lib = pkgs.lib; - - # Get short revs for tagging - orgApiRev = builtins.substring 0 7 (org-agenda-api.rev or "unknown"); - dotfilesRev = builtins.substring 0 7 (self.rev or self.dirtyRev or "dirty"); - - # Get tangled config files from org-agenda-api.nix - dotfilesOrgApi = import ./org-agenda-api.nix { - inherit pkgs system; - inherit inputs; - }; - tangledConfig = dotfilesOrgApi.org-agenda-custom-config; - - # Import container build logic - containerLib = import ../org-agenda-api/container.nix { - inherit pkgs system tangledConfig org-agenda-api orgApiRev dotfilesRev; - }; - in { - formatter = pkgs.alejandra; - - packages = { - colonelpanic-org-agenda-api = containerLib.containers.colonelpanic; - kat-org-agenda-api = containerLib.containers.kat; - } // lib.optionalAttrs pkgs.stdenv.isLinux { - hyprNStack = inputs.hyprNStack.packages.${system}.hyprNStack; - hyprexpo-lua = inputs.hyprland-plugins-lua.packages.${system}.hyprexpo; - hyprwinview = inputs.hyprwinview.packages.${system}.hyprwinview; - hypr-workspace-history = inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history; - }; - - checks = lib.optionalAttrs pkgs.stdenv.isLinux { - hyprNStack = inputs.hyprNStack.packages.${system}.hyprNStack; - hyprexpo-lua = inputs.hyprland-plugins-lua.packages.${system}.hyprexpo; - hyprwinview = inputs.hyprwinview.packages.${system}.hyprwinview; - hypr-workspace-history = inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history; - hyprland-config-syntax = pkgs.runCommand "hyprland-config-syntax" { - nativeBuildInputs = [ pkgs.lua5_4 ]; - } '' - cp ${../dotfiles/config/hypr/hyprland.lua} hyprland.lua - luac -p hyprland.lua - if grep -n 'hyprctl' hyprland.lua | grep -v 'hyprctl reload' | grep -v 'hyprctl eval' | grep -v 'hyprctl_eval' | grep -v 'hyprctl -j monitors'; then - echo "hyprland.lua should not shell out to hyprctl for window/workspace manipulation" >&2 - exit 1 - fi - lua <<'LUA' - local callbacks = {} - - local function noop() end - - local function dispatcher_proxy() - local proxy = {} - return setmetatable(proxy, { - __index = function() - return dispatcher_proxy() - end, - __call = function() - return noop - end, - }) - end - - local notification = { - is_alive = function() - return true - end, - set_text = noop, - set_timeout = noop, - pause = noop, - resume = noop, - set_paused = noop, - dismiss = noop, - } - - local monitor = { - id = 1, - name = "stub-monitor", - focused = true, - } - - local workspace = { - id = 1, - name = "1", - windows = 0, - special = false, - monitor = monitor, - } - - monitor.active_workspace = workspace - - hl = { - animation = noop, - bind = noop, - config = noop, - curve = noop, - env = noop, - exec_cmd = noop, - define_submap = function(_, reset_or_callback, callback) - local cb = type(reset_or_callback) == "function" and reset_or_callback or callback - if cb then - cb() - end - end, - monitor = noop, - workspace_rule = noop, - window_rule = noop, - dsp = dispatcher_proxy(), - notification = { - create = function() - return notification - end, - }, - plugin = { - load = noop, - }, - get_active_workspace = function() - return workspace - end, - get_active_monitor = function() - return monitor - end, - get_active_window = function() - return nil - end, - get_monitor = function() - return monitor - end, - get_workspace = function(id) - if tostring(id) == "1" then - return workspace - end - return nil - end, - get_windows = function() - return {} - end, - get_workspace_windows = function() - return {} - end, - on = function(_, callback) - callbacks[#callbacks + 1] = callback - end, - timer = function(callback) - callback() - return { - set_enabled = noop, - } - end, - } - - dofile("./hyprland.lua") - - for _, callback in ipairs(callbacks) do - callback() - end - LUA - touch "$out" - ''; - hyprland-verify-config = let - hyprlandPackage = inputs.hyprland.packages.${system}.hyprland; - hyprNStackPackage = inputs.hyprNStack.packages.${system}.hyprNStack; - in pkgs.runCommand "hyprland-lua-verify-config" {} '' - cp ${../dotfiles/config/hypr/hyprland.lua} hyprland.lua - substituteInPlace hyprland.lua \ - --replace-fail /run/current-system/sw/lib/libhyprNStack.so \ - ${hyprNStackPackage}/lib/libhyprNStack.so - export XDG_RUNTIME_DIR="$TMPDIR/runtime" - mkdir -p "$XDG_RUNTIME_DIR" - HYPRLAND_NO_CRASHREPORTER=1 ${pkgs.coreutils}/bin/timeout 20s \ - ${hyprlandPackage}/bin/Hyprland --verify-config --config "$PWD/hyprland.lua" - touch "$out" - ''; - }; - - # Dev shell for org-agenda-api deployment - devShells.org-agenda-api = pkgs.mkShell { - buildInputs = [ - pkgs.flyctl - agenix.packages.${system}.default - pkgs.age - pkgs.ssh-to-age - pkgs.git - pkgs.jq - pkgs.just - pkgs.curl + in + { + nixConfig = { + substituters = [ + "https://cache.nixos.org/" + ]; + trusted-public-keys = [ + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + ]; + extra-substituters = [ + "http://192.168.1.26:5050" + "https://ai.cachix.org" + "https://cache.nixos-cuda.org" + "https://nix-community.cachix.org" + "https://cuda-maintainers.cachix.org" + "https://numtide.cachix.org" + "https://cache.flox.dev" + "https://org-agenda-api.cachix.org" + "https://colonelpanic8-dotfiles.cachix.org" + "https://codex-cli.cachix.org" + "https://claude-code.cachix.org" + "https://noctalia.cachix.org" + ]; + extra-trusted-substituters = [ + "https://ai.cachix.org" + "https://cache.nixos.org/" + "https://nix-community.cachix.org" + "https://cache.nixos-cuda.org" + "https://cuda-maintainers.cachix.org" + "https://numtide.cachix.org" + ]; + extra-trusted-public-keys = [ + "1896Folsom.duckdns.org:U2FTjvP95qwAJo0oGpvmUChJCgi5zQoG1YisoI08Qoo=" + "ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc=" + "cache.nixos-cuda.org:74DUi4Ye579gUqzH4ziL9IyiJBlDpMRn9MBN8oNan9M=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + "cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E=" + "numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE=" + "flox-cache-public-1:7F4OyH7ZCnFhcze3fJdfyXYLQw/aV7GEed86nQ7IsOs=" + "org-agenda-api.cachix.org-1:liKFemKkOLV/rJt2txDNcpDjRsqLuBneBjkSw/UVXKA=" + "colonelpanic8-dotfiles.cachix.org-1:O6GF3nptpeMFapX29okzO92eSWXR36zqW6ZF2C8P0eQ=" + "codex-cli.cachix.org-1:1Br3H1hHoRYG22n//cGKJOk3cQXgYobUel6O8DgSing=" + "claude-code.cachix.org-1:YeXf2aNu7UTX8Vwrze0za1WEDS+4DuI2kVeWEE4fsRk=" + "noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4=" ]; - shellHook = '' - echo "" - echo "org-agenda-api deployment shell" - echo "" - echo "Commands:" - echo " just --list - Show available API commands" - echo " ./deploy.sh - Deploy to Fly.io (colonelpanic or kat)" - echo " flyctl - Fly.io CLI" - echo " agenix -e - Edit encrypted secrets" - echo "" - ''; }; + nixosConfigurations = + builtins.mapAttrs ( + machineName: params: let + machineParams = + if builtins.hasAttr machineName customParams + then (builtins.getAttr machineName customParams) + else {}; + in + mkConfig (params // machineParams) + ) + defaultConfigurationParams; } - ); + // flake-utils.lib.eachDefaultSystem ( + system: let + pkgs = import nixpkgs {inherit system;}; + lib = pkgs.lib; + + # Get short revs for tagging + orgApiRev = builtins.substring 0 7 (org-agenda-api.rev or "unknown"); + dotfilesRev = builtins.substring 0 7 (self.rev or self.dirtyRev or "dirty"); + + # Get tangled config files from org-agenda-api.nix + dotfilesOrgApi = import ./org-agenda-api.nix { + inherit pkgs system; + inherit inputs; + }; + tangledConfig = dotfilesOrgApi.org-agenda-custom-config; + + # Import container build logic + containerLib = import ../org-agenda-api/container.nix { + inherit pkgs system tangledConfig org-agenda-api orgApiRev dotfilesRev; + }; + in { + formatter = pkgs.alejandra; + + packages = + { + colonelpanic-org-agenda-api = containerLib.containers.colonelpanic; + kat-org-agenda-api = containerLib.containers.kat; + } + // lib.optionalAttrs pkgs.stdenv.isLinux { + hyprNStack = inputs.hyprNStack.packages.${system}.hyprNStack; + hyprexpo-lua = inputs.hyprland-plugins-lua.packages.${system}.hyprexpo; + hyprwinview = inputs.hyprwinview.packages.${system}.hyprwinview; + hypr-workspace-history = inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history; + }; + + checks = lib.optionalAttrs pkgs.stdenv.isLinux { + hyprNStack = inputs.hyprNStack.packages.${system}.hyprNStack; + hyprexpo-lua = inputs.hyprland-plugins-lua.packages.${system}.hyprexpo; + hyprwinview = inputs.hyprwinview.packages.${system}.hyprwinview; + hypr-workspace-history = inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history; + hyprland-config-syntax = + pkgs.runCommand "hyprland-config-syntax" { + nativeBuildInputs = [pkgs.lua5_4]; + } '' + cp ${../dotfiles/config/hypr/hyprland.lua} hyprland.lua + luac -p hyprland.lua + if grep -n 'hyprctl' hyprland.lua | grep -v 'hyprctl reload' | grep -v 'hyprctl eval' | grep -v 'hyprctl_eval' | grep -v 'hyprctl -j monitors'; then + echo "hyprland.lua should not shell out to hyprctl for window/workspace manipulation" >&2 + exit 1 + fi + lua <<'LUA' + local callbacks = {} + + local function noop() end + + local function dispatcher_proxy() + local proxy = {} + return setmetatable(proxy, { + __index = function() + return dispatcher_proxy() + end, + __call = function() + return noop + end, + }) + end + + local notification = { + is_alive = function() + return true + end, + set_text = noop, + set_timeout = noop, + pause = noop, + resume = noop, + set_paused = noop, + dismiss = noop, + } + + local monitor = { + id = 1, + name = "stub-monitor", + focused = true, + } + + local workspace = { + id = 1, + name = "1", + windows = 0, + special = false, + monitor = monitor, + } + + monitor.active_workspace = workspace + + hl = { + animation = noop, + bind = noop, + config = noop, + curve = noop, + env = noop, + exec_cmd = noop, + define_submap = function(_, reset_or_callback, callback) + local cb = type(reset_or_callback) == "function" and reset_or_callback or callback + if cb then + cb() + end + end, + monitor = noop, + workspace_rule = noop, + window_rule = noop, + dsp = dispatcher_proxy(), + notification = { + create = function() + return notification + end, + }, + plugin = { + load = noop, + }, + get_active_workspace = function() + return workspace + end, + get_active_monitor = function() + return monitor + end, + get_active_window = function() + return nil + end, + get_monitor = function() + return monitor + end, + get_workspace = function(id) + if tostring(id) == "1" then + return workspace + end + return nil + end, + get_windows = function() + return {} + end, + get_workspace_windows = function() + return {} + end, + on = function(_, callback) + callbacks[#callbacks + 1] = callback + end, + timer = function(callback) + callback() + return { + set_enabled = noop, + } + end, + } + + dofile("./hyprland.lua") + + for _, callback in ipairs(callbacks) do + callback() + end + LUA + touch "$out" + ''; + hyprland-verify-config = let + hyprlandPackage = inputs.hyprland.packages.${system}.hyprland; + hyprNStackPackage = inputs.hyprNStack.packages.${system}.hyprNStack; + in + pkgs.runCommand "hyprland-lua-verify-config" {} '' + cp ${../dotfiles/config/hypr/hyprland.lua} hyprland.lua + substituteInPlace hyprland.lua \ + --replace-fail /run/current-system/sw/lib/libhyprNStack.so \ + ${hyprNStackPackage}/lib/libhyprNStack.so + export XDG_RUNTIME_DIR="$TMPDIR/runtime" + mkdir -p "$XDG_RUNTIME_DIR" + HYPRLAND_NO_CRASHREPORTER=1 ${pkgs.coreutils}/bin/timeout 20s \ + ${hyprlandPackage}/bin/Hyprland --verify-config --config "$PWD/hyprland.lua" + touch "$out" + ''; + }; + + # Dev shell for org-agenda-api deployment + devShells.org-agenda-api = pkgs.mkShell { + buildInputs = [ + pkgs.flyctl + agenix.packages.${system}.default + pkgs.age + pkgs.ssh-to-age + pkgs.git + pkgs.jq + pkgs.just + pkgs.curl + ]; + shellHook = '' + echo "" + echo "org-agenda-api deployment shell" + echo "" + echo "Commands:" + echo " just --list - Show available API commands" + echo " ./deploy.sh - Deploy to Fly.io (colonelpanic or kat)" + echo " flyctl - Fly.io CLI" + echo " agenix -e - Edit encrypted secrets" + echo "" + ''; + }; + } + ); } diff --git a/nixos/keepbook-sync.nix b/nixos/keepbook-sync.nix index 9143e1b9..b2969150 100644 --- a/nixos/keepbook-sync.nix +++ b/nixos/keepbook-sync.nix @@ -1,116 +1,129 @@ -{ config, lib, pkgs, inputs, makeEnable, ... }: -let +{ + config, + lib, + pkgs, + inputs, + makeEnable, + ... +}: let cfg = config.myModules."keepbook-sync"; - keepbookTray = - inputs.keepbook.packages.${pkgs.stdenv.hostPlatform.system}.keepbook-tray.overrideAttrs (_: { - # Upstream currently includes a contract test that expects a built TS CLI - # entrypoint under ts/dist/, but the Nix build does not build the TS - # artifacts first. Skip checks to keep the package usable on NixOS. - doCheck = false; - }); + keepbookPackages = inputs.keepbook.packages.${pkgs.stdenv.hostPlatform.system}; + keepbookTray = keepbookPackages.keepbook-tray.overrideAttrs (_: { + # Upstream currently includes a contract test that expects a built TS CLI + # entrypoint under ts/dist/, but the Nix build does not build the TS + # artifacts first. Skip checks to keep the package usable on NixOS. + doCheck = false; + }); + keepbookDioxusDesktopPackages = + lib.optional (keepbookPackages ? keepbook-dioxus-desktop) + keepbookPackages.keepbook-dioxus-desktop; - daemonArgs = [ - "--config" cfg.configPath - "--interval" cfg.interval - "--jitter" cfg.jitter - ] - ++ lib.optionals (cfg.historyPoints != null) [ "--history-points" (toString cfg.historyPoints) ] - ++ lib.optionals (!cfg.syncOnStart) [ "--no-sync-on-start" ] - ++ lib.optionals (!cfg.syncPrices) [ "--no-sync-prices" ] - ++ lib.optionals (!cfg.syncSymlinks) [ "--no-sync-symlinks" ] - ++ lib.optionals (cfg.balanceStaleness != null) [ "--balance-staleness" cfg.balanceStaleness ] - ++ lib.optionals (cfg.priceStaleness != null) [ "--price-staleness" cfg.priceStaleness ]; + daemonArgs = + [ + "--config" + cfg.configPath + "--interval" + cfg.interval + "--jitter" + cfg.jitter + ] + ++ lib.optionals (cfg.historyPoints != null) ["--history-points" (toString cfg.historyPoints)] + ++ lib.optionals (!cfg.syncOnStart) ["--no-sync-on-start"] + ++ lib.optionals (!cfg.syncPrices) ["--no-sync-prices"] + ++ lib.optionals (!cfg.syncSymlinks) ["--no-sync-symlinks"] + ++ lib.optionals (cfg.balanceStaleness != null) ["--balance-staleness" cfg.balanceStaleness] + ++ lib.optionals (cfg.priceStaleness != null) ["--price-staleness" cfg.priceStaleness]; - daemonExec = lib.escapeShellArgs ([ "${keepbookTray}/bin/keepbook-sync-daemon" ] ++ daemonArgs); + daemonExec = lib.escapeShellArgs (["${keepbookTray}/bin/keepbook-sync-daemon"] ++ daemonArgs); enabledModule = makeEnable config "myModules.keepbook-sync" false { - environment.systemPackages = [ keepbookTray ]; + environment.systemPackages = [keepbookTray] ++ keepbookDioxusDesktopPackages; home-manager.users.${cfg.user} = { systemd.user.services.keepbook-sync-daemon = { Unit = { Description = "keepbook sync daemon"; - After = [ "graphical-session.target" "tray.target" ]; - PartOf = [ "graphical-session.target" ]; - Requires = [ "tray.target" ]; + After = ["graphical-session.target" "tray.target"]; + PartOf = ["graphical-session.target"]; + Requires = ["tray.target"]; }; Service = { ExecStart = daemonExec; Restart = "always"; RestartSec = 5; - Environment = [ "RUST_LOG=info" ]; + Environment = ["RUST_LOG=info"]; }; Install = { - WantedBy = [ "graphical-session.target" ]; + WantedBy = ["graphical-session.target"]; }; }; }; }; in -enabledModule // { - # Merge our extra options with the enable option produced by makeEnable. - options = lib.recursiveUpdate enabledModule.options { - myModules."keepbook-sync" = { - user = lib.mkOption { - type = lib.types.str; - default = "imalison"; - description = "User account to run the keepbook sync daemon."; - }; + enabledModule + // { + # Merge our extra options with the enable option produced by makeEnable. + options = lib.recursiveUpdate enabledModule.options { + myModules."keepbook-sync" = { + user = lib.mkOption { + type = lib.types.str; + default = "imalison"; + description = "User account to run the keepbook sync daemon."; + }; - configPath = lib.mkOption { - type = lib.types.str; - default = "/home/imalison/.local/share/keepbook/keepbook.toml"; - description = "Path to keepbook.toml used by the daemon."; - }; + configPath = lib.mkOption { + type = lib.types.str; + default = "/home/imalison/.local/share/keepbook/keepbook.toml"; + description = "Path to keepbook.toml used by the daemon."; + }; - interval = lib.mkOption { - type = lib.types.str; - default = "30m"; - description = "Base sync interval for keepbook-sync-daemon (e.g. 30m, 1h)."; - }; + interval = lib.mkOption { + type = lib.types.str; + default = "30m"; + description = "Base sync interval for keepbook-sync-daemon (e.g. 30m, 1h)."; + }; - jitter = lib.mkOption { - type = lib.types.str; - default = "5m"; - description = "Random jitter applied around each scheduled interval."; - }; + jitter = lib.mkOption { + type = lib.types.str; + default = "5m"; + description = "Random jitter applied around each scheduled interval."; + }; - balanceStaleness = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - description = "Optional override for balance staleness threshold."; - }; + balanceStaleness = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Optional override for balance staleness threshold."; + }; - priceStaleness = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - description = "Optional override for price staleness threshold."; - }; + priceStaleness = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Optional override for price staleness threshold."; + }; - syncOnStart = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Run a sync cycle immediately when the daemon starts."; - }; + syncOnStart = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Run a sync cycle immediately when the daemon starts."; + }; - syncPrices = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Enable periodic price refresh during sync cycles."; - }; + syncPrices = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Enable periodic price refresh during sync cycles."; + }; - syncSymlinks = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Enable periodic symlink rebuild during sync cycles."; - }; + syncSymlinks = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Enable periodic symlink rebuild during sync cycles."; + }; - historyPoints = lib.mkOption { - type = lib.types.nullOr lib.types.int; - default = null; - description = "Optional override for the maximum recent portfolio history rows shown in the tray menu."; + historyPoints = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + description = "Optional override for the maximum recent portfolio history rows shown in the tray menu."; + }; }; - }; - }; -} + }