2026-01-18 16:28:58 +08:00
|
|
|
{
|
|
|
|
|
config,
|
|
|
|
|
lib,
|
|
|
|
|
inputs,
|
|
|
|
|
pkgs,
|
|
|
|
|
...
|
2026-07-04 23:11:21 +08:00
|
|
|
}:
|
|
|
|
|
let
|
2026-01-18 16:28:58 +08:00
|
|
|
cfg = config.david.programs.noctalia;
|
2026-07-04 23:11:21 +08:00
|
|
|
inherit (inputs.niri-flake.lib.kdl)
|
|
|
|
|
node
|
|
|
|
|
leaf
|
|
|
|
|
flag
|
|
|
|
|
plain
|
|
|
|
|
;
|
2026-01-18 16:28:58 +08:00
|
|
|
spawn = leaf "spawn";
|
2026-07-04 23:11:21 +08:00
|
|
|
noctalia =
|
|
|
|
|
args:
|
|
|
|
|
(spawn (
|
|
|
|
|
[
|
|
|
|
|
"noctalia-shell"
|
|
|
|
|
"ipc"
|
|
|
|
|
"call"
|
|
|
|
|
]
|
|
|
|
|
++ args
|
|
|
|
|
));
|
2026-01-18 16:28:58 +08:00
|
|
|
|
|
|
|
|
layer-rule = plain "layer-rule";
|
|
|
|
|
match = leaf "match";
|
2026-07-04 23:11:21 +08:00
|
|
|
in
|
|
|
|
|
{
|
2026-01-18 16:28:58 +08:00
|
|
|
options = {
|
|
|
|
|
david.programs.noctalia = {
|
|
|
|
|
enable = lib.mkEnableOption "noctalia";
|
|
|
|
|
niriExtraConfig = lib.mkOption {
|
|
|
|
|
type = inputs.niri-flake.lib.kdl.types.kdl-document;
|
|
|
|
|
default = [
|
2026-07-04 23:11:21 +08:00
|
|
|
(leaf "spawn-at-startup" [ (lib.getExe config.programs.noctalia-shell.package) ])
|
2026-01-18 16:28:58 +08:00
|
|
|
(plain "binds" [
|
2026-07-04 23:11:21 +08:00
|
|
|
(plain "Mod+V" [
|
|
|
|
|
(noctalia [
|
|
|
|
|
"launcher"
|
|
|
|
|
"clipboard"
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
(plain "Mod+Shift+P" [
|
|
|
|
|
(noctalia [
|
|
|
|
|
"lockScreen"
|
|
|
|
|
"lock"
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
(plain "Mod+Space" [
|
|
|
|
|
(noctalia [
|
|
|
|
|
"launcher"
|
|
|
|
|
"toggle"
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
(node "XF86AudioRaiseVolume"
|
|
|
|
|
[ { allow-when-locked = true; } ]
|
|
|
|
|
[
|
|
|
|
|
(noctalia [
|
|
|
|
|
"volume"
|
|
|
|
|
"increase"
|
|
|
|
|
])
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
(node "XF86AudioLowerVolume"
|
|
|
|
|
[ { allow-when-locked = true; } ]
|
|
|
|
|
[
|
|
|
|
|
(noctalia [
|
|
|
|
|
"volume"
|
|
|
|
|
"decrease"
|
|
|
|
|
])
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
(node "XF86AudioMute"
|
|
|
|
|
[ { allow-when-locked = true; } ]
|
|
|
|
|
[
|
|
|
|
|
(noctalia [
|
|
|
|
|
"volume"
|
|
|
|
|
"muteOutput"
|
|
|
|
|
])
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
(node "XF86AudioMicMute"
|
|
|
|
|
[ { allow-when-locked = true; } ]
|
|
|
|
|
[
|
|
|
|
|
(noctalia [
|
|
|
|
|
"volume"
|
|
|
|
|
"muteInput"
|
|
|
|
|
])
|
|
|
|
|
]
|
|
|
|
|
)
|
2026-01-18 16:28:58 +08:00
|
|
|
])
|
|
|
|
|
(layer-rule [
|
2026-07-04 23:11:21 +08:00
|
|
|
(match [ { namespace = "^noctalia-wallpaper-.*$"; } ])
|
|
|
|
|
(leaf "place-within-backdrop" [ true ])
|
2026-01-18 16:28:58 +08:00
|
|
|
])
|
|
|
|
|
(layer-rule [
|
2026-07-04 23:11:21 +08:00
|
|
|
(match [ { namespace = "^noctalia-notifications-.*$"; } ])
|
|
|
|
|
(leaf "block-out-from" [ "screen-capture" ])
|
2026-01-18 16:28:58 +08:00
|
|
|
])
|
|
|
|
|
(plain "layout" [
|
|
|
|
|
(plain "focus-ring" [
|
|
|
|
|
(leaf "active-gradient" [
|
|
|
|
|
{
|
|
|
|
|
from = "#8288fcff";
|
|
|
|
|
to = "#8288fc00";
|
|
|
|
|
angle = 45;
|
|
|
|
|
"in" = "oklch";
|
|
|
|
|
}
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
];
|
2026-07-04 23:11:21 +08:00
|
|
|
apply =
|
|
|
|
|
configuration:
|
|
|
|
|
config.david.programs.niri.configHelper.validated-config-for (
|
|
|
|
|
inputs.niri-flake.lib.kdl.serialize.nodes configuration
|
|
|
|
|
);
|
2026-01-18 16:28:58 +08:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
|
|
|
stylix.targets.noctalia-shell.enable = false;
|
2026-07-04 23:11:21 +08:00
|
|
|
home.packages = [
|
|
|
|
|
pkgs.app2unit
|
|
|
|
|
pkgs.gpu-screen-recorder
|
|
|
|
|
];
|
2026-01-18 16:28:58 +08:00
|
|
|
programs.noctalia-shell = {
|
|
|
|
|
enable = true;
|
2026-01-19 19:31:26 +08:00
|
|
|
plugins = builtins.fromJSON (builtins.readFile ./plugins.json);
|
2026-07-04 23:11:21 +08:00
|
|
|
pluginSettings =
|
|
|
|
|
let
|
|
|
|
|
enabledPlugins =
|
|
|
|
|
with lib;
|
|
|
|
|
flip pipe [
|
|
|
|
|
(filterAttrs (_name: settings: settings.enabled or false))
|
|
|
|
|
builtins.attrNames
|
|
|
|
|
] config.programs.noctalia-shell.plugins.states;
|
|
|
|
|
staticSettings = lib.genAttrs enabledPlugins (
|
|
|
|
|
name:
|
|
|
|
|
let
|
|
|
|
|
pluginSettingPath = ./plugin + "/${name}.json";
|
|
|
|
|
in
|
|
|
|
|
if lib.pathIsRegularFile pluginSettingPath then
|
|
|
|
|
builtins.fromJSON (builtins.readFile pluginSettingPath)
|
|
|
|
|
else
|
|
|
|
|
{ }
|
|
|
|
|
);
|
2026-02-19 11:27:27 +08:00
|
|
|
in
|
2026-07-04 23:11:21 +08:00
|
|
|
lib.recursiveUpdate staticSettings {
|
2026-02-19 11:27:27 +08:00
|
|
|
screen-recorder.directory = "${config.xdg.userDirs.videos}/records";
|
|
|
|
|
};
|
2026-07-04 23:11:21 +08:00
|
|
|
settings = lib.recursiveUpdate (builtins.fromJSON (builtins.readFile ./settings.json)) {
|
|
|
|
|
general.avatarImage = "${config.home.homeDirectory}/.face";
|
|
|
|
|
wallpaper.directory = "${config.home.homeDirectory}/${config.david.wallpaper.path}";
|
|
|
|
|
};
|
2026-01-18 16:28:58 +08:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|