From 28d0196a259355f405aabe0f4df954edc52b0e0c Mon Sep 17 00:00:00 2001 From: Christoph Urlacher Date: Thu, 13 Nov 2025 15:13:54 +0100 Subject: [PATCH] Modules/Niri: Init niri module --- config/face.jpeg | Bin 0 -> 72203 bytes flake.lock | 171 +++- flake.nix | 35 +- home/christoph/default.nix | 1544 ++++++++++++++++---------------- home/modules/default.nix | 5 + home/modules/niri/default.nix | 509 +++++++++++ home/modules/niri/noctalia.nix | 242 +++++ home/modules/niri/options.nix | 7 + system/default.nix | 4 + 9 files changed, 1752 insertions(+), 765 deletions(-) create mode 100644 config/face.jpeg create mode 100644 home/modules/niri/default.nix create mode 100644 home/modules/niri/noctalia.nix create mode 100644 home/modules/niri/options.nix diff --git a/config/face.jpeg b/config/face.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..7ad35274b16d104aff8342e4c0e274a9b9b9f0ac GIT binary patch literal 72203 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

B0!Xif!xr>l5} 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". - inputs.nix-alien.packages.${system}.nix-alien + docs.enable = !headless; - # Search nixpkgs - inputs.nps.packages.${system}.default + firefox = { + enable = !headless; + wayland = true; + vaapi = true; + textfox = true; + disableTabBar = true; + }; - # Use NixCommunity binary cache - cachix - ] - (lib.mkIf (!headless) [ - ripdrag # drag & drop from terminal - veracrypt + fish.enable = true; - # Proton - protonvpn-gui - protonmail-bridge-gui + git = { + enable = true; - # GUI stuff - nautilus # Just in case - signal-desktop - anki - font-manager # Previews fonts, but doesn't set them - nextcloud-client - keepassxc - thunderbird # TODO: Email module - obsidian - zotero - zeal # docs browser - helvum - vlc - audacity - ferdium - gparted - tidal-hifi - tidal-dl-ng - picard - handbrake - teamspeak6-client + userName = "Christoph Urlacher"; + userEmail = "christoph.urlacher@protonmail.com"; + signCommits = true; + }; - # Office - kdePackages.wacomtablet # For xournalpp/krita - xournalpp # Write with a pen, like old people - hunspell # I cna't type - hunspellDicts.en_US - hunspellDicts.de_DE - ]) + hyprland = import ./hyprland.nix {inherit pkgs config headless;}; + hyprpanel.enable = !headless; + + kitty.enable = !headless; + lazygit.enable = true; + mpd.enable = !headless; + + niri = { + enable = !headless; + }; + + neovim = { + enable = true; + alias = true; + neovide = !headless; + }; + + nnn.enable = false; # Use yazi + qutebrowser.enable = !headless; + rmpc.enable = !headless; + + rofi = { + enable = !headless; + }; + + waybar.enable = false; # Use hyprpanel + yazi.enable = true; + zathura.enable = !headless; + }; + + manual = { + manpages.enable = nixosConfig.documentation.enable; + html.enable = false; + }; + + # Make fonts installed through user packages available to applications. + # Also updates the font-cache. + fonts.fontconfig.enable = !headless; + + # This only works when HM is installed as a system module, + # as nixosConfig won't be available otherwise. + xdg = { + enable = true; # This only does xdg path management + mime.enable = nixosConfig.modules.mime.enable; + + mimeApps = { + enable = nixosConfig.modules.mime.enable; + + associations.added = nixosConfig.xdg.mime.addedAssociations; + associations.removed = nixosConfig.xdg.mime.removedAssociations; + defaultApplications = nixosConfig.xdg.mime.defaultApplications; + }; + + portal = { + inherit (nixosConfig.xdg.portal) enable xdgOpenUsePortal config extraPortals; + }; + }; + + home = { + inherit username; # Inherited from flake.nix + + homeDirectory = "/home/${config.home.username}"; + enableNixpkgsReleaseCheck = true; + + # Environment variables + sessionVariables = lib.mkMerge [ + { + LANG = "en_US.UTF-8"; + MANPAGER = "nvim +Man!"; + } + (lib.mkIf (!headless) { + # TERMINAL = "alacritty -o font.size=12"; + TERMINAL = "kitty"; + BROWSER = "firefox"; + + # Enable wayland + XDG_SESSION_TYPE = "wayland"; + QT_QPA_PLATFORM = "wayland"; + NIXOS_OZONE_WL = "1"; + SDL_VIDEODRIVER = "wayland"; + + # Run SSH_ASKPASS as GUI, not TTY for Obsidian git + SSH_ASKPASS_REQUIRE = "prefer"; + + # GTK_IM_MODULE, QT_IM_MODULE, XMODIFIERS are set by HomeManager fcitx5 module + }) ]; - }; - # home.file.".options-doc".source = "${pkgs.modules-options-doc}"; + # Files to generate in the home directory are specified here. + file = lib.mkMerge [ + { + # Because we can't access the absolute path /run/secrets/... we have to symlink. + # This will create a chain of links leading to /run/secrets/... without /nix/store + # containing the secret contents. + ".ssh/id_ed25519".source = + config.lib.file.mkOutOfStoreSymlink + nixosConfig.sops.secrets.ssh-private-key.path; - # Packages with extra options managed by HomeManager natively - programs = { - # The home-manager management tool. - # Will only be enabled if HM is installed standalone. - home-manager.enable = true; + ".ssh/id_ed25519.pub".text = "${publicKeys.${username}.ssh}"; - bat = { - enable = true; + ".secrets/age/age.pub".text = "${publicKeys.${username}.age}"; - themes = { - catppuccin-latte = { - src = pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "bat"; - rev = "ba4d16880d63e656acced2b7d4e034e4a93f74b1"; - sha256 = "sha256-6WVKQErGdaqb++oaXnY3i6/GuH2FhTgK0v4TN4Y0Wbw="; - }; - file = "Catppuccin-latte.tmTheme"; - }; + # The sops config specifies what happens when we call sops edit + ".sops.yaml".text = '' + keys: + - &${username} ${publicKeys.${username}.age} + creation_rules: + - path_regex: secrets.yaml$ + key_groups: + - age: + - *${username} + ''; + + ".config/nix/nix.conf".source = + config.lib.file.mkOutOfStoreSymlink + nixosConfig.sops.templates."nix.conf".path; + } + (lib.mkIf nixosConfig.modules.desktopportal.termfilechooser.enable { + ".config/xdg-desktop-portal-termfilechooser/config".text = '' + [filechooser] + cmd=${pkgs.xdg-desktop-portal-termfilechooser}/share/xdg-desktop-portal-termfilechooser/yazi-wrapper.sh + default_dir=$HOME + env=TERMCMD=kitty --class=file_chooser + open_mode = suggested + save_mode = last + ''; + }) + (lib.mkIf config.modules.git.enable { + ".ssh/allowed_signers".text = "* ${publicKeys.${username}.ssh}"; + }) + (lib.mkIf config.programs.navi.enable { + ".local/share/navi/cheats/christoph.cheat".source = config.lib.file.mkOutOfStoreSymlink "${config.paths.dotfiles}/navi/christoph.cheat"; + }) + (lib.mkIf (!headless) { + # killswitch: 0, 1, 2 (off, on, advanced - still on after reboot) + # netshield: 0, 1, 2 (off, malware, ads+malware+trackers) + ".config/Proton/VPN/settings.json".text = '' + { + "protocol": "wireguard", + "killswitch": 1, + "custom_dns": { + "enabled": false, + "ip_list": [] + }, + "ipv6": true, + "anonymous_crash_reports": false, + "features": { + "netshield": 1, + "moderate_nat": true, + "vpn_accelerator": true, + "port_forwarding": false + } + } + ''; + ".config/Proton/VPN/app-config.json".text = '' + { + "tray_pinned_servers": [ + "DE", + "CH", + "AU" + ], + "connect_at_app_startup": null, + "start_app_minimized": true + } + ''; + }) + ]; + + # Here, custom scripts can be run when activating a HM generation. + # If those scripts contain side-effects, like creating files, + # they must be placed after the "writeBoundary" node in the execution graph. + activation = { + # Example with side-effects: + # linkObsidianLatexSnippets = + # lib.hm.dag.entryAfter ["writeBoundary"] + # (mylib.modules.mkLink "~/NixFlake/config/obsidian/latex_snippets.json" "~/Notes/Obsidian/Chriphost/latex_snippets.json"); }; - config = { - theme = "catppuccin-latte"; - }; + # Add stuff for your user as you see fit: + # TODO: Make the headless installations smaller + packages = with pkgs; + lib.mkMerge [ + [ + # Shell utils + (ripgrep.override {withPCRE2 = true;}) # fast as fuck + gdu # Alternative to du-dust (I like it better) + duf # Disk usage analyzer (for all disk overview) + sd # Sed alternative + fclones # Duplicate file finder + tealdeer # Very fast tldr (so readable man) + killall + atool # Archive preview + ouch # Unified compression/decompression + ffmpegthumbnailer # Video thumbnails + mediainfo # Media meta information + file # File meta information + unrar # Cooler WinRar + p7zip # Zip stuff + unzip # Unzip stuff + progress # Find coreutils processes and show their progress + tokei # Text file statistics in a project + playerctl # Media player control + pastel # Color tools + nvd # Nix rebuild diff + nix-search-tv # Search nixpkgs, nur, nixos options and homemanager options + nix-tree # Browse the nix store sorted by size (gdu for closures) + nurl # Generate nix fetcher sections based on URLs + python313 # Nicer scripting than bash + binsider # Analyze binaries + lazyjournal # Journalctl viewer + systemctl-tui + restic # Backups + + # Hardware/Software info + pciutils # lspci + mesa-demos # OpenGL info + wayland-utils # wayland-info + clinfo # OpenCL info + vulkan-tools # vulkaninfo + libva-utils # vainfo + vdpauinfo # Video-Decode and Presentation API for Unix info + hwloc # Generate CPU topology diagram + lm_sensors # Readout hardware sensors + acpica-tools # Dump ACPI tables etc. + smartmontools # Disk health + nvme-cli # NVME disk health + + # Video/Image/Audio utils + ffmpeg-full # I love ffmpeg (including ffplay) + ffmpeg-normalize # Normalize audio + imagemagick # Convert image (magic) + mp3val # Validate mp3 files + flac # Validate flac files + spotdl + + # Document utils + poppler-utils # pdfunite + graphviz # generate graphs from code + d2 # generate diagrams from code + plantuml # generate diagrams + gnuplot # generate function plots + pdf2svg # extract vector graphics from pdf + pandoc # document converting madness + + # Networking + dig # Make DNS requests + tcpdump # Listen in on TCP traffic + traceroute # "Follow" a packet + gping # ping with graph + curlie # curl a'la httpie + wget # download that shit + dogdns # dns client + rsync # cp on steroids + rclone # Rsync for cloud + httpie # Cool http client + cifs-utils # Mount samba shares + nfs-utils # Mount NFS shares + sshfs # Mount remote directories via SSH + + # Run unpatched binaries on NixOS + # Sets NIX_LD_LIBRARY_PATH and NIX_LD variables for nix-ld. + # Usage: "nix-alien-ld -- ". + inputs.nix-alien.packages.${system}.nix-alien + + # Search nixpkgs + inputs.nps.packages.${system}.default + + # Use NixCommunity binary cache + cachix + ] + (lib.mkIf (!headless) [ + ripdrag # drag & drop from terminal + veracrypt + + # Proton + protonvpn-gui + protonmail-bridge-gui + + # GUI stuff + nautilus # Just in case + signal-desktop + anki + font-manager # Previews fonts, but doesn't set them + nextcloud-client + keepassxc + thunderbird # TODO: Email module + obsidian + zotero + zeal # docs browser + helvum + vlc + audacity + ferdium + gparted + tidal-hifi + tidal-dl-ng + picard + handbrake + teamspeak6-client + + # Office + kdePackages.wacomtablet # For xournalpp/krita + xournalpp # Write with a pen, like old people + hunspell # I cna't type + hunspellDicts.en_US + hunspellDicts.de_DE + ]) + ]; }; - cava = { - enable = !headless; + # home.file.".options-doc".source = "${pkgs.modules-options-doc}"; - settings = { - general = { - framerate = 60; # default 60 - autosens = 1; # default 1 - sensitivity = 100; # default 100 - lower_cutoff_freq = 50; # not passed to cava if not provided - higher_cutoff_freq = 10000; # not passed to cava if not provided - }; + # Packages with extra options managed by HomeManager natively + programs = { + # The home-manager management tool. + # Will only be enabled if HM is installed standalone. + home-manager.enable = true; - smoothing = { - noise_reduction = 77; # default 77 - monstercat = false; # default false - waves = false; # default false - }; + bat = { + enable = true; - color = let - color = config.modules.color; - in { - # https://github.com/catppuccin/cava/blob/main/themes/latte-transparent.cava - gradient = 1; - - gradient_color_1 = "'${color.hexS.teal}'"; - gradient_color_2 = "'${color.hexS.sky}'"; - gradient_color_3 = "'${color.hexS.sapphire}'"; - gradient_color_4 = "'${color.hexS.blue}'"; - gradient_color_5 = "'${color.hexS.mauve}'"; - gradient_color_6 = "'${color.hexS.pink}'"; - gradient_color_7 = "'${color.hexS.maroon}'"; - gradient_color_8 = "'${color.hexS.red}'"; - }; - }; - }; - - direnv = { - enable = true; - nix-direnv.enable = true; - }; - - eza = { - enable = true; - enableFishIntegration = config.modules.fish.enable; - }; - - # TODO: Module - fastfetch = { - enable = true; - - settings = { - logo = { - padding = { - top = 3; - left = 1; - right = 2; + themes = { + catppuccin-latte = { + src = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "bat"; + rev = "ba4d16880d63e656acced2b7d4e034e4a93f74b1"; + sha256 = "sha256-6WVKQErGdaqb++oaXnY3i6/GuH2FhTgK0v4TN4Y0Wbw="; + }; + file = "Catppuccin-latte.tmTheme"; }; }; - display = { - separator = ""; - key.width = 17; + config = { + theme = "catppuccin-latte"; }; + }; - # Box Drawing: ╭ ─ ╮ ╰ ╯ │ - modules = [ - # Title - { - type = "title"; - format = "{#1}╭─── {#}{user-name-colored}"; - } + cava = { + enable = !headless; - # System Information - { - type = "custom"; - format = "{#1}│ {#}System Information"; - } - { - type = "os"; - key = "{#separator}│ {#keys}󰍹 OS"; - } - { - type = "kernel"; - key = "{#separator}│ {#keys}󰒋 Kernel"; - } - { - type = "bootmgr"; - key = "{#separator}│ {#keys}󰒋 BootMGR"; - } - { - type = "uptime"; - key = "{#separator}│ {#keys}󰅐 Uptime"; - } - { - type = "packages"; - key = "{#separator}│ {#keys}󰏖 Packages"; - # format = "{all}"; - } - { - type = "custom"; - format = "{#1}│"; - } + settings = { + general = { + framerate = 60; # default 60 + autosens = 1; # default 1 + sensitivity = 100; # default 100 + lower_cutoff_freq = 50; # not passed to cava if not provided + higher_cutoff_freq = 10000; # not passed to cava if not provided + }; - # Desktop Environment - { - type = "custom"; - format = "{#1}│ {#}Desktop Environment"; - } - { - type = "de"; - key = "{#separator}│ {#keys}󰧨 DE"; - } - { - type = "wm"; - key = "{#separator}│ {#keys}󱂬 WM"; - } - { - type = "wmtheme"; - key = "{#separator}│ {#keys}󰉼 Theme"; - } - { - type = "display"; - key = "{#separator}│ {#keys}󰹑 Resolution"; - } - { - type = "shell"; - key = "{#separator}│ {#keys}󰞷 Shell"; - } - { - type = "terminalfont"; - key = "{#separator}│ {#keys}󰛖 Font"; - } - { - type = "icons"; - key = "{#separator}│ {#keys} Icons"; - } - { - type = "cursor"; - key = "{#separator}│ {#keys}󰆽 Cursor"; - } - { - type = "custom"; - format = "{#1}│"; - } + smoothing = { + noise_reduction = 77; # default 77 + monstercat = false; # default false + waves = false; # default false + }; - # Hardware Information - { - type = "custom"; - format = "{#1}│ {#}Hardware Information"; - } - { - type = "board"; - key = "{#separator}│ {#keys} Board"; - } - { - type = "cpu"; - key = "{#separator}│ {#keys}󰻠 CPU"; - } - { - type = "gpu"; - key = "{#separator}│ {#keys}󰢮 GPU"; - } - { - type = "memory"; - key = "{#separator}│ {#keys}󰍛 Memory"; - } - # { - # type = "disk"; - # key = "{#separator}│ {#keys}󰋊 Disk (/)"; - # folders = "/"; - # } - # { - # type = "disk"; - # key = "{#separator}│ {#keys}󰋊 Disk (~/Games)"; - # folders = "/home/christoph/Games"; - # } - { - type = "btrfs"; - key = "{#separator}│ {#keys}󰋊 BTRFS"; - } - { - type = "custom"; - format = "{#1}│"; - } + color = { + # https://github.com/catppuccin/cava/blob/main/themes/latte-transparent.cava + gradient = 1; - # Colors Footer + gradient_color_1 = "'${color.hexS.teal}'"; + gradient_color_2 = "'${color.hexS.sky}'"; + gradient_color_3 = "'${color.hexS.sapphire}'"; + gradient_color_4 = "'${color.hexS.blue}'"; + gradient_color_5 = "'${color.hexS.mauve}'"; + gradient_color_6 = "'${color.hexS.pink}'"; + gradient_color_7 = "'${color.hexS.maroon}'"; + gradient_color_8 = "'${color.hexS.red}'"; + }; + }; + }; + + direnv = { + enable = true; + nix-direnv.enable = true; + }; + + eza = { + enable = true; + enableFishIntegration = config.modules.fish.enable; + }; + + # TODO: Module + fastfetch = { + enable = true; + + settings = { + logo = { + padding = { + top = 3; + left = 1; + right = 2; + }; + }; + + display = { + separator = ""; + key.width = 17; + }; + + # Box Drawing: ╭ ─ ╮ ╰ ╯ │ + modules = [ + # Title + { + type = "title"; + format = "{#1}╭─── {#}{user-name-colored}"; + } + + # System Information + { + type = "custom"; + format = "{#1}│ {#}System Information"; + } + { + type = "os"; + key = "{#separator}│ {#keys}󰍹 OS"; + } + { + type = "kernel"; + key = "{#separator}│ {#keys}󰒋 Kernel"; + } + { + type = "bootmgr"; + key = "{#separator}│ {#keys}󰒋 BootMGR"; + } + { + type = "uptime"; + key = "{#separator}│ {#keys}󰅐 Uptime"; + } + { + type = "packages"; + key = "{#separator}│ {#keys}󰏖 Packages"; + # format = "{all}"; + } + { + type = "custom"; + format = "{#1}│"; + } + + # Desktop Environment + { + type = "custom"; + format = "{#1}│ {#}Desktop Environment"; + } + { + type = "de"; + key = "{#separator}│ {#keys}󰧨 DE"; + } + { + type = "wm"; + key = "{#separator}│ {#keys}󱂬 WM"; + } + { + type = "wmtheme"; + key = "{#separator}│ {#keys}󰉼 Theme"; + } + { + type = "display"; + key = "{#separator}│ {#keys}󰹑 Resolution"; + } + { + type = "shell"; + key = "{#separator}│ {#keys}󰞷 Shell"; + } + { + type = "terminalfont"; + key = "{#separator}│ {#keys}󰛖 Font"; + } + { + type = "icons"; + key = "{#separator}│ {#keys} Icons"; + } + { + type = "cursor"; + key = "{#separator}│ {#keys}󰆽 Cursor"; + } + { + type = "custom"; + format = "{#1}│"; + } + + # Hardware Information + { + type = "custom"; + format = "{#1}│ {#}Hardware Information"; + } + { + type = "board"; + key = "{#separator}│ {#keys} Board"; + } + { + type = "cpu"; + key = "{#separator}│ {#keys}󰻠 CPU"; + } + { + type = "gpu"; + key = "{#separator}│ {#keys}󰢮 GPU"; + } + { + type = "memory"; + key = "{#separator}│ {#keys}󰍛 Memory"; + } + # { + # type = "disk"; + # key = "{#separator}│ {#keys}󰋊 Disk (/)"; + # folders = "/"; + # } + # { + # type = "disk"; + # key = "{#separator}│ {#keys}󰋊 Disk (~/Games)"; + # folders = "/home/christoph/Games"; + # } + { + type = "btrfs"; + key = "{#separator}│ {#keys}󰋊 BTRFS"; + } + { + type = "custom"; + format = "{#1}│"; + } + + # Colors Footer + { + type = "colors"; + key = "{#separator}╰─── {#1}"; + keyWidth = 6; + symbol = "circle"; + } + ]; + }; + }; + + fd.enable = true; + + fzf = { + enable = true; + enableFishIntegration = config.modules.fish.enable; + }; + + imv = { + enable = !headless; + settings = { + options = { + background = "${color.hex.base}"; + overlay = true; + overlay_font = "${color.font}:12"; + overlay_background_color = "${color.hex.accent}"; + overlay_text_color = "${color.hex.accentText}"; + }; + }; + }; + + keychain = { + enable = true; + enableFishIntegration = config.modules.fish.enable; + enableXsessionIntegration = !headless; + keys = ["id_ed25519"]; + }; + + mpv = { + enable = false; + config = { + gpu-context = "wayland"; + }; + }; + + navi = { + enable = true; + enableFishIntegration = config.modules.fish.enable; + }; + + nix-index = { + enable = true; + enableFishIntegration = config.modules.fish.enable; + }; + + nushell.enable = false; + + # spicetify = let + # spicePkgs = inputs.spicetify-nix.legacyPackages.${pkgs.system}; + # in { + # enable = true; + # + # # https://github.com/catppuccin/spicetify + # theme = spicePkgs.themes.catppuccin; + # colorScheme = "mocha"; + # + # wayland = true; + # + # enabledExtensions = with spicePkgs.extensions; [ + # adblock + # hidePodcasts + # oneko # cat + # ]; + # # enabledCustomApps = with spicePkgs.apps; []; + # enabledSnippets = with spicePkgs.snippets; [ + # rotatingCoverart + # pointer + # ]; + # }; + + ssh = { + enable = true; + enableDefaultConfig = false; + + matchBlocks = { + "*" = { + forwardAgent = false; + addKeysToAgent = "no"; + compression = true; + serverAliveInterval = 0; + serverAliveCountMax = 3; + hashKnownHosts = false; + userKnownHostsFile = "~/.ssh/known_hosts"; + controlMaster = "no"; + controlPath = "~/.ssh/master-%r@%n:%p"; + controlPersist = "no"; + }; + "nixinator" = { + user = "christoph"; + hostname = "192.168.86.50"; + }; + "servenix" = { + user = "christoph"; + hostname = "local.chriphost.de"; + }; + "thinknix" = { + user = "christoph"; + hostname = "think.chriphost.de"; + }; + "vps" = { + user = "root"; + hostname = "vps.chriphost.de"; + }; + }; + }; + + tmux = { + enable = false; + + clock24 = true; + escapeTime = 0; # Delay after pressing escape + # keyMode = "vi"; + terminal = "xterm-256color"; + + plugins = with pkgs; [ { - type = "colors"; - key = "{#separator}╰─── {#1}"; - keyWidth = 6; - symbol = "circle"; + plugin = tmuxPlugins.catppuccin; + extraConfig = '' + set -g @plugin 'catppuccin/tmux' + set -g @catppuccin_flavour 'latte' # or frappe, macchiato, mocha + ''; } ]; + + extraConfig = '' + set -g default-terminal "xterm-256color" + set-option -ga terminal-overrides ",xterm-256color:Tc" + ''; }; - }; - fd.enable = true; + yt-dlp.enable = true; - fzf = { - enable = true; - enableFishIntegration = config.modules.fish.enable; - }; - - keychain = { - enable = true; - enableFishIntegration = config.modules.fish.enable; - enableXsessionIntegration = !headless; - keys = ["id_ed25519"]; - }; - - mpv = { - enable = false; - config = { - gpu-context = "wayland"; - }; - }; - - navi = { - enable = true; - enableFishIntegration = config.modules.fish.enable; - }; - - nix-index = { - enable = true; - enableFishIntegration = config.modules.fish.enable; - }; - - nushell.enable = false; - - # spicetify = let - # spicePkgs = inputs.spicetify-nix.legacyPackages.${pkgs.system}; - # in { - # enable = true; - # - # # https://github.com/catppuccin/spicetify - # theme = spicePkgs.themes.catppuccin; - # colorScheme = "mocha"; - # - # wayland = true; - # - # enabledExtensions = with spicePkgs.extensions; [ - # adblock - # hidePodcasts - # oneko # cat - # ]; - # # enabledCustomApps = with spicePkgs.apps; []; - # enabledSnippets = with spicePkgs.snippets; [ - # rotatingCoverart - # pointer - # ]; - # }; - - ssh = { - enable = true; - enableDefaultConfig = false; - - matchBlocks = { - "*" = { - forwardAgent = false; - addKeysToAgent = "no"; - compression = true; - serverAliveInterval = 0; - serverAliveCountMax = 3; - hashKnownHosts = false; - userKnownHostsFile = "~/.ssh/known_hosts"; - controlMaster = "no"; - controlPath = "~/.ssh/master-%r@%n:%p"; - controlPersist = "no"; - }; - "nixinator" = { - user = "christoph"; - hostname = "192.168.86.50"; - }; - "servenix" = { - user = "christoph"; - hostname = "local.chriphost.de"; - }; - "thinknix" = { - user = "christoph"; - hostname = "think.chriphost.de"; - }; - "vps" = { - user = "root"; - hostname = "vps.chriphost.de"; - }; - }; - }; - - tmux = { - enable = false; - - clock24 = true; - escapeTime = 0; # Delay after pressing escape - # keyMode = "vi"; - terminal = "xterm-256color"; - - plugins = with pkgs; [ - { - plugin = tmuxPlugins.catppuccin; - extraConfig = '' - set -g @plugin 'catppuccin/tmux' - set -g @catppuccin_flavour 'latte' # or frappe, macchiato, mocha - ''; - } - ]; - - extraConfig = '' - set -g default-terminal "xterm-256color" - set-option -ga terminal-overrides ",xterm-256color:Tc" - ''; - }; - - yt-dlp.enable = true; - - zoxide = { - enable = true; - enableFishIntegration = config.modules.fish.enable; - }; - }; - - services = { - kdeconnect = { - enable = nixosConfig.programs.kdeconnect.enable; # Only the system package sets up the firewall - indicator = nixosConfig.programs.kdeconnect.enable; - }; - - flatpak = lib.mkIf nixosConfig.services.flatpak.enable { - # FlatHub stable is only added by default if no custom remotes are specified - remotes = lib.mkOptionDefault [ - { - name = "flathub"; - location = "https://flathub.org/repo/flathub.flatpakrepo"; - } - { - name = "flathub-beta"; - location = "https://flathub.org/beta-repo/flathub-beta.flatpakrepo"; - } - ]; - - packages = lib.mkMerge [ - [] - (lib.mkIf (!headless) [ - "com.github.tchx84.Flatseal" - - # "com.spotify.Client" # Don't need this when spicetify is enabled - - "com.discordapp.Discord" - # "com.discordapp.DiscordCanary" - - # "com.google.Chrome" - # "md.obsidian.Obsidian" - # "io.anytype.anytype" - ]) - ]; - - uninstallUnmanaged = true; - uninstallUnused = true; - - update.auto = { + zoxide = { enable = true; - onCalendar = "daily"; # Default value: weekly + enableFishIntegration = config.modules.fish.enable; + }; + }; + + services = { + kdeconnect = { + enable = nixosConfig.programs.kdeconnect.enable; # Only the system package sets up the firewall + indicator = nixosConfig.programs.kdeconnect.enable; }; - overrides = { - global = { - # Force Wayland by default - # Context.sockets = ["wayland" "!x11" "!fallback-x11"]; # NOTE: Makes discord + steam crash + flatpak = lib.mkIf nixosConfig.services.flatpak.enable { + # FlatHub stable is only added by default if no custom remotes are specified + remotes = lib.mkOptionDefault [ + { + name = "flathub"; + location = "https://flathub.org/repo/flathub.flatpakrepo"; + } + { + name = "flathub-beta"; + location = "https://flathub.org/beta-repo/flathub-beta.flatpakrepo"; + } + ]; - Context.filesystems = ["/nix/store:ro"]; + packages = lib.mkMerge [ + [] + (lib.mkIf (!headless) [ + "com.github.tchx84.Flatseal" - Environment = { - # Fix un-themed cursor in some Wayland apps - XCURSOR_PATH = "/run/host/user-share/icons:/run/host/share/icons"; + # "com.spotify.Client" # Don't need this when spicetify is enabled - # Force correct theme for some GTK apps - GTK_THEME = "Adwaita:light"; + "com.discordapp.Discord" + # "com.discordapp.DiscordCanary" + + # "com.google.Chrome" + # "md.obsidian.Obsidian" + # "io.anytype.anytype" + ]) + ]; + + uninstallUnmanaged = true; + uninstallUnused = true; + + update.auto = { + enable = true; + onCalendar = "daily"; # Default value: weekly + }; + + overrides = { + global = { + # Force Wayland by default + # Context.sockets = ["wayland" "!x11" "!fallback-x11"]; # NOTE: Makes discord + steam crash + + Context.filesystems = ["/nix/store:ro"]; + + Environment = { + # Fix un-themed cursor in some Wayland apps + XCURSOR_PATH = "/run/host/user-share/icons:/run/host/share/icons"; + + # Force correct theme for some GTK apps + GTK_THEME = "Adwaita:light"; + }; + }; + + "io.anytype.anytype".Context = { + filesystems = [ + "${config.home.homeDirectory}" + ]; + }; + + "com.discordapp.Discord".Context = { + filesystems = [ + "${config.home.homeDirectory}" + ]; }; }; - - "io.anytype.anytype".Context = { - filesystems = [ - "${config.home.homeDirectory}" - ]; - }; - - "com.discordapp.Discord".Context = { - filesystems = [ - "${config.home.homeDirectory}" - ]; - }; }; }; - }; - systemd = { - user = { - # TODO: This has been deprecated and replaced with a bad alternative in a stupid HM update - # tmpfiles.rules = lib.mkMerge [ - # [] - # (lib.mkIf (mylib.modules.contains - # config.services.flatpak.packages - # "com.discordapp.Discord") [ - # # Fix Discord rich presence for Flatpak - # "L %t/discord-ipc-0 - - - - app/com.discordapp.Discord/discord-ipc-0" - # ]) - # (lib.mkIf (mylib.modules.contains - # config.services.flatpak.packages - # "com.discordapp.DiscordCanary") [ - # # Fix Discord rich presence for Flatpak - # "L %t/discord-ipc-0 - - - - app/com.discordapp.DiscordCanary/discord-ipc-0" - # ]) - # ]; + systemd = { + user = { + # TODO: This has been deprecated and replaced with a bad alternative in a stupid HM update + # tmpfiles.rules = lib.mkMerge [ + # [] + # (lib.mkIf (mylib.modules.contains + # config.services.flatpak.packages + # "com.discordapp.Discord") [ + # # Fix Discord rich presence for Flatpak + # "L %t/discord-ipc-0 - - - - app/com.discordapp.Discord/discord-ipc-0" + # ]) + # (lib.mkIf (mylib.modules.contains + # config.services.flatpak.packages + # "com.discordapp.DiscordCanary") [ + # # Fix Discord rich presence for Flatpak + # "L %t/discord-ipc-0 - - - - app/com.discordapp.DiscordCanary/discord-ipc-0" + # ]) + # ]; - # Nicely reload system units when changing configs - startServices = "sd-switch"; + # Nicely reload system units when changing configs + startServices = "sd-switch"; + }; }; - }; -} + } diff --git a/home/modules/default.nix b/home/modules/default.nix index 3a1b6653..21689f38 100644 --- a/home/modules/default.nix +++ b/home/modules/default.nix @@ -18,6 +18,7 @@ ./lazygit ./mpd ./neovim + ./niri ./nnn ./paths ./qutebrowser @@ -31,6 +32,10 @@ inputs.nix-flatpak.homeManagerModules.nix-flatpak inputs.nixvim.homeModules.nixvim inputs.textfox.homeManagerModules.default + # inputs.niri.homeModules.niri # Imported by system module + inputs.noctalia.homeModules.default + # inputs.dankMaterialShell.homeModules.dankMaterialShell.default + # inputs.dankMaterialShell.homeModules.dankMaterialShell.niri # NOTE: Do NOT use this, use the system module (the HM module has to rely on fuse) # inputs.impermanence.homeManagerModules.impermanence diff --git a/home/modules/niri/default.nix b/home/modules/niri/default.nix new file mode 100644 index 00000000..d503c222 --- /dev/null +++ b/home/modules/niri/default.nix @@ -0,0 +1,509 @@ +{ + config, + nixosConfig, + lib, + mylib, + pkgs, + ... +}: let + inherit (config.modules) niri color; +in { + options.modules.niri = import ./options.nix {inherit lib mylib;}; + + config = lib.mkIf niri.enable { + assertions = [ + { + assertion = nixosConfig.programs.niri.enable; + message = "Can't enable Niri module with Niri disabled!"; + } + ]; + + home = { + packages = with pkgs; [ + xwayland-satellite + ncpamixer # Audio control + + nautilus # Fallback file chooser used by xdg-desktop-portal-gnome + + # In case we fallback to the default config + alacritty + fuzzel + ]; + }; + + programs = { + noctalia-shell = import ./noctalia.nix {inherit color;}; + + niri = { + # enable = true; # Enabled in system module + + settings = { + input = { + focus-follows-mouse = { + enable = true; + max-scroll-amount = "0%"; # Skip partial windows that would scroll the viewport on focus + }; + + keyboard = { + xkb = { + layout = "us"; + variant = "altgr-intl"; + options = "nodeadkeys"; + }; + }; + + touchpad = { + click-method = "clickfinger"; + tap = true; + drag = true; + dwt = true; + natural-scroll = true; + scroll-method = "two-finger"; + }; + }; + + hotkey-overlay = { + hide-not-bound = true; + skip-at-startup = true; + }; + + prefer-no-csd = true; # Disable client-side decorations (e.g. window titlebars) + + spawn-at-startup = [ + {argv = ["noctalia-shell"];} + {argv = ["kitty" "--hold" "fastfetch"];} + {argv = ["zeal"];} + {argv = ["nextcloud --background"];} + {argv = ["protonvpn-app"];} + {argv = ["keepassxc"];} + {argv = ["fcitx5"];} + + # TODO: On certain workspaces + # {argv = ["ferdium"];} + # {argv = ["kitty --title=Btop btop"];} + # {argv = ["kitty --title=Rmpc rmpc"];} + ]; + + workspaces = { + "1" = {open-on-output = "DP-1";}; + "2" = {open-on-output = "DP-1";}; + "3" = {open-on-output = "DP-1";}; + "4" = {open-on-output = "DP-1";}; + "5" = {open-on-output = "DP-1";}; + "6" = {open-on-output = "DP-1";}; + "7" = {open-on-output = "DP-1";}; + "8" = {open-on-output = "DP-1";}; + "9" = {open-on-output = "DP-1";}; + "10" = {open-on-output = "DP-2";}; + }; + + outputs = { + "DP-1" = { + focus-at-startup = true; + mode = { + width = 3440; + height = 1440; + refresh = 165.0; + }; + position = { + x = 1920; + y = 0; + }; + }; + "DP-2" = { + focus-at-startup = false; + mode = { + width = 1920; + height = 1080; + refresh = 60.0; + }; + position = { + x = 0; + y = 0; + }; + }; + }; + + cursor = { + hide-when-typing = true; + theme = "Bibata-Modern-Classic"; + size = 24; + }; + + layout = { + # This border is drawn INSIDE the window + border = { + enable = true; + width = 2; + active = {color = color.hex.accent;}; + inactive = {color = color.hex.base;}; + }; + + # This border is drawn OUTSIDE of the focused window + focus-ring = { + enable = false; + }; + + # Hint where a dragged window will be inserted + insert-hint = { + enable = true; + display = {color = color.hex.accentDim;}; + }; + + always-center-single-column = false; + + # Gaps between windows + gaps = 8; + + # Gaps at screen borders + struts = { + # left = 8; + # right = 8; + top = 4; # Somehow the bar eclusivity doesn't work as expected + bottom = 2; + }; + }; + + gestures = { + hot-corners = {enable = false;}; + }; + + window-rules = [ + # Rules for all windows + { + clip-to-geometry = true; + geometry-corner-radius = { + bottom-left = 8.0; + bottom-right = 8.0; + top-left = 8.0; + top-right = 8.0; + }; + } + + # Assign to workspaces + { + matches = [{app-id = "Zotero";}]; + open-on-workspace = "2"; + } + { + matches = [{app-id = "neovide";}]; + open-on-workspace = "2"; + } + { + matches = [{app-id = "code-url-handler";}]; + open-on-workspace = "2"; + } + { + matches = [{app-id = "obsidian";}]; + open-on-workspace = "3"; + } + { + matches = [{app-id = "firefox";}]; + open-on-workspace = "4"; + } + { + matches = [{app-id = "Google-chrome";}]; + open-on-workspace = "4"; + } + { + matches = [{app-id = "chromium-browser";}]; + open-on-workspace = "4"; + } + { + matches = [{app-id = "org.qutebrowser.qutebrowser";}]; + open-on-workspace = "4"; + } + { + matches = [{app-id = "steam";}]; + open-on-workspace = "5"; + } + { + matches = [{app-id = "steam_app_(.+)";}]; + open-on-workspace = "6"; + } + { + matches = [{app-id = "signal";}]; + open-on-workspace = "7"; + } + { + matches = [{app-id = "discord";}]; + open-on-workspace = "9"; + } + ]; + + layer-rules = [ + { + # Set the overview wallpaper on the backdrop. + matches = [{namespace = "^noctalia-overview*";}]; + place-within-backdrop = true; + } + ]; + + debug = { + # Allows notification actions and window activation from Noctalia. + honor-xdg-activation-with-invalid-serial = []; + }; + + # TODO: Only start hypr... stuff with hyprland, not systemd (hypridle, hyprpaper currently) + + # TODO: Move values to config option and set in home/christoph/niri.nix + binds = with config.lib.niri.actions; { + # Applications + "Mod+T" = { + action = spawn "kitty"; + hotkey-overlay = {title = "Spawn Kitty.";}; + }; + "Mod+E" = { + action = spawn "kitty" "--title=Yazi" "yazi"; + hotkey-overlay = {title = "Spawn Yazi.";}; + }; + "Mod+B" = { + action = spawn "kitty" "--title=Btop" "btop"; + hotkey-overlay = {title = "Spawn Btop.";}; + }; + "Mod+R" = { + action = spawn "kitty" "--title=Rmpc" "rmpc"; + hotkey-overlay = {title = "Spawn Rmpc.";}; + }; + "Mod+N" = { + action = spawn "neovide"; + hotkey-overlay = {title = "Spawn Neovide.";}; + }; + "Mod+Ctrl+N" = { + action = spawn "kitty" "--title=Navi" "navi"; + hotkey-overlay = {title = "Call Navi for help.";}; + }; + "Mod+Shift+N" = { + action = spawn "neovide" "${config.paths.dotfiles}/navi/christoph.cheat"; + hotkey-overlay = {title = "Edit the Navi cheats.";}; + }; + "Mod+Shift+F" = { + action = spawn "neovide" "${config.paths.dotfiles}/flake.nix"; + hotkey-overlay = {title = "Edit the NixFlake.";}; + }; + + # Noctalia + "Mod+A" = { + action = spawn "noctalia-shell" "ipc" "call" "launcher" "toggle"; + hotkey-overlay = {title = "Toggle the application launcher.";}; + }; + "Mod+Ctrl+L" = { + action = spawn "noctalia-shell" "ipc" "call" "lockScreen" "lock"; + hotkey-overlay = {title = "Lock the screen.";}; + }; + "Mod+W" = { + action = spawn "noctalia-shell" "ipc" "call" "wallpaper" "toggle"; + hotkey-overlay = {title = "Toggle the wallpaper chooser.";}; + }; + "Mod+Escape" = { + action = spawn "noctalia-shell" "ipc" "call" "sessionMenu" "toggle"; + hotkey-overlay = {title = "Toggle the session menu.";}; + }; + + # Screenshots + "Mod+S" = { + action.screenshot-window = {write-to-disk = true;}; + hotkey-overlay = {title = "Take a screenshot of the current window.";}; + }; + "Mod+Shift+S" = { + action.screenshot = {show-pointer = true;}; + hotkey-overlay = {title = "Take a screenshot of a region.";}; + }; + + # Audio + "XF86AudioRaiseVolume" = { + action = spawn "wpctl" "set-volume" "-l" "1.5" "@DEFAULT_AUDIO_SINK@" "5%+"; + hotkey-overlay = {hidden = true;}; + }; + "XF86AudioLowerVolume" = { + action = spawn "wpctl" "set-volume" "-l" "1.5" "@DEFAULT_AUDIO_SINK@" "5%-"; + hotkey-overlay = {hidden = true;}; + }; + "XF86AudioPlay" = { + action = spawn "playerctl" "play-pause"; + hotkey-overlay = {hidden = true;}; + }; + "XF86AudioPrev" = { + action = spawn "playerctl" "previous"; + hotkey-overlay = {hidden = true;}; + }; + "XF86AudioNext" = { + action = spawn "playerctl" "next"; + hotkey-overlay = {hidden = true;}; + }; + + # Niri + "Mod+Shift+Slash" = { + action = show-hotkey-overlay; + hotkey-overlay = {hidden = true;}; + }; + + # Niri windows + "Mod+Q" = { + action = close-window; + hotkey-overlay = {title = "Close the current window.";}; + }; + "Mod+F" = { + action = fullscreen-window; + hotkey-overlay = {title = "Toggle between fullscreen and tiled window.";}; + }; + "Mod+Equal" = { + action = set-column-width "+10%"; + hotkey-overlay = {title = "Increase column width";}; + }; + "Mod+Minus" = { + action = set-column-width "-10%"; + hotkey-overlay = {title = "Decrease column width";}; + }; + "Mod+Shift+M" = { + action = set-column-width "50%"; + hotkey-overlay = {title = "Set column width to 50%";}; + }; + "Mod+M" = { + action = maximize-column; + hotkey-overlay = {title = "Maximize column.";}; + }; + "Mod+V" = { + action = toggle-window-floating; + hotkey-overlay = {title = "Toggle between floating and tiled window.";}; + }; + "Mod+O" = { + action = toggle-overview; + hotkey-overlay = {title = "Toggle overlay.";}; + }; + "Mod+H" = { + action = focus-column-or-monitor-left; + hotkey-overlay = {title = "Focus column on the left. Equivalent bindings for other directions.";}; + }; + "Mod+J" = { + action = focus-window-or-workspace-down; + hotkey-overlay = {hidden = true;}; + }; + "Mod+K" = { + action = focus-window-or-workspace-up; + hotkey-overlay = {hidden = true;}; + }; + "Mod+L" = { + action = focus-column-or-monitor-right; + hotkey-overlay = {hidden = true;}; + }; + "Mod+WheelScrollUp" = { + action = focus-column-left; + hotkey-overlay = {title = "Focus column on the left. Equivalent binding for other direction.";}; + }; + "Mod+WheelScrollDown" = { + action = focus-column-right; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+WheelScrollUp" = { + action = focus-workspace-up; + hotkey-overlay = {title = "Focus previous workspace. Equivalent binding for other direction.";}; + }; + "Mod+Shift+WheelScrollDown" = { + action = focus-workspace-down; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+H" = { + action = move-column-left; + hotkey-overlay = {title = "Move column to the left. Equivalent bindings for other directions.";}; + }; + "Mod+Shift+J" = { + action = move-window-down; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+K" = { + action = move-window-up; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+L" = { + action = move-column-right; + hotkey-overlay = {hidden = true;}; + }; + + # Niri workspaces + "Mod+1" = { + action = focus-workspace 1; + hotkey-overlay = {title = "Focus workspace 1. Equivalent bindings for other workspaces.";}; + }; + "Mod+2" = { + action = focus-workspace 2; + hotkey-overlay = {hidden = true;}; + }; + "Mod+3" = { + action = focus-workspace 3; + hotkey-overlay = {hidden = true;}; + }; + "Mod+4" = { + action = focus-workspace 4; + hotkey-overlay = {hidden = true;}; + }; + "Mod+5" = { + action = focus-workspace 5; + hotkey-overlay = {hidden = true;}; + }; + "Mod+6" = { + action = focus-workspace 6; + hotkey-overlay = {hidden = true;}; + }; + "Mod+7" = { + action = focus-workspace 7; + hotkey-overlay = {hidden = true;}; + }; + "Mod+8" = { + action = focus-workspace 8; + hotkey-overlay = {hidden = true;}; + }; + "Mod+9" = { + action = focus-workspace 9; + hotkey-overlay = {hidden = true;}; + }; + "Mod+0" = { + action = focus-workspace 10; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+1" = { + action.move-window-to-workspace = 1; + hotkey-overlay = {title = "Move current window to workspace 1. Equivalent bindings for other workspaces.";}; + }; + "Mod+Shift+2" = { + action.move-window-to-workspace = 2; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+3" = { + action.move-window-to-workspace = 3; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+4" = { + action.move-window-to-workspace = 4; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+5" = { + action.move-window-to-workspace = 5; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+6" = { + action.move-window-to-workspace = 6; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+7" = { + action.move-window-to-workspace = 7; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+8" = { + action.move-window-to-workspace = 8; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+9" = { + action.move-window-to-workspace = 9; + hotkey-overlay = {hidden = true;}; + }; + "Mod+Shift+0" = { + action.move-window-to-workspace = 10; + hotkey-overlay = {hidden = true;}; + }; + }; + }; + }; + }; + }; +} diff --git a/home/modules/niri/noctalia.nix b/home/modules/niri/noctalia.nix new file mode 100644 index 00000000..00aa22ff --- /dev/null +++ b/home/modules/niri/noctalia.nix @@ -0,0 +1,242 @@ +{color}: { + enable = true; + settings = { + # configure noctalia here; defaults will + # be deep merged with these attributes. + + colorSchemes.predefinedScheme = "Catppuccin"; + + general = { + avatarImage = ../../../config/face.jpeg; + radiusRatio = 0.2; + showScreenCorners = false; + forceBlackScreenCorners = false; + dimDesktop = true; + scaleRatio = 1; + screenRadiusRatio = 1; + animationSpeed = 1; + animationDisabled = false; + compactLockScreen = false; + lockOnSuspend = true; + enableShadows = true; + shadowDirection = "bottom_right"; + shadowOffsetX = 2; + shadowOffsetY = 3; + language = ""; + }; + + ui = { + fontDefault = color.font; + fontFixed = color.font; + tooltipsEnabled = true; + panelsAttachedToBar = true; + settingsPanelAttachTobar = true; + fontDefaultScale = 1; + fontFixedScale = 1; + settingsPanelAttachToBar = false; + }; + + location = { + name = "Dortmund, Germany"; + monthBeforeDay = true; + weatherEnabled = true; + useFahrenheit = false; + use12hourFormat = false; + showWeekNumberInCalendar = false; + showCalendarEvents = true; + showCalendarWeather = true; + analogClockInCalendar = false; + firstDayOfWeek = -1; + }; + + screenRecorder = { + directory = "~/Videos/Recordings"; + frameRate = 60; + audioCodec = "aac"; + videoCodec = "h265"; + quality = "very_high"; + colorRange = "limited"; + showCursor = true; + audioSource = "default_output"; + videoSource = "portal"; + }; + + wallpaper = { + enabled = true; + overviewEnabled = true; + directory = "~/NixFlake/wallpapers"; + enableMultiMonitorDirectories = false; + recursiveSearch = false; + setWallpaperOnAllMonitors = true; + defaultWallpaper = ../../../wallpapers/Windows.jpg; + fillMode = "crop"; + fillColor = "#000000"; + randomEnabled = false; + randomIntervalSec = 300; + transitionDuration = 1500; + transitionType = "random"; + transitionEdgeSmoothness = 0.05; + monitors = []; + panelPosition = "follow_bar"; + }; + + appLauncher = { + enableClipboardHistory = true; + position = "center"; + backgroundOpacity = 1; + pinnedExecs = []; + useApp2Unit = false; + sortByMostUsed = true; + terminalCommand = "kitty -e"; + customLaunchPrefixEnabled = false; + customLaunchPrefix = ""; + }; + + dock = { + enabled = false; + }; + + network = { + wifiEnabled = true; + bluetoothEnabled = true; + }; + + notifications = { + enabled = true; + monitors = []; + location = "top_right"; + overlayLayer = true; + backgroundOpacity = 1; + respectExpireTimeout = false; + lowUrgencyDuration = 3; + normalUrgencyDuration = 8; + criticalUrgencyDuration = 15; + }; + + osd = { + enabled = true; + location = "top_right"; + monitors = []; + autoHideMs = 2000; + overlayLayer = true; + }; + + audio = { + volumeStep = 5; + volumeOverdrive = true; + cavaFrameRate = 30; + visualizerType = "linear"; + visualizerQuality = "high"; + mprisBlacklist = []; + preferredPlayer = ""; + }; + + nightLight = { + enabled = false; + forced = false; + autoSchedule = true; + nightTemp = "5000"; + dayTemp = "6500"; + manualSunrise = "06:30"; + manualSunset = "21:30"; + }; + + sessionMenu = { + countdownDuration = 10000; + enableCountdown = true; + position = "center"; + powerOptions = [ + { + action = "lock"; + enabled = true; + } + { + action = "suspend"; + enabled = false; + } + { + action = "reboot"; + enabled = true; + } + { + action = "logout"; + enabled = true; + } + { + action = "shutdown"; + enabled = true; + } + ]; + showHeader = true; + }; + + bar = { + density = "default"; + position = "top"; + showCapsule = false; + outerCorners = false; + exclusive = true; + backgroundOpacity = 1; + monitors = []; + floating = false; + marginVertical = 0.25; + marginHorizontal = 0.25; + + widgets = { + left = [ + { + id = "SidePanelToggle"; + useDistroLogo = true; + } + { + hideUnoccupied = false; + id = "Workspace"; + labelMode = "none"; + } + { + id = "ActiveWindow"; + width = 250; # TODO: Doesn't work + } + ]; + center = [ + { + id = "MediaMini"; + width = 250; # TODO: Doesn't work + } + { + id = "AudioVisualizer"; + width = 100; # TODO: Doesn't work + } + ]; + right = [ + { + id = "Volume"; + } + { + id = "Microphone"; + } + { + id = "WiFi"; + } + { + id = "Bluetooth"; + } + { + id = "Tray"; + drawer = false; # TODO: Doesn't work + } + { + formatHorizontal = "yyyy:MM:dd HH:mm"; + formatVertical = "HH mm"; + id = "Clock"; + useMonospacedFont = true; + usePrimaryColor = true; + } + { + id = "NotificationHistory"; + } + ]; + }; + }; + }; +} diff --git a/home/modules/niri/options.nix b/home/modules/niri/options.nix new file mode 100644 index 00000000..852c38c0 --- /dev/null +++ b/home/modules/niri/options.nix @@ -0,0 +1,7 @@ +{ + lib, + mylib, + ... +}: { + enable = lib.mkEnableOption "Niri"; +} diff --git a/system/default.nix b/system/default.nix index f15a9d37..65d2683d 100644 --- a/system/default.nix +++ b/system/default.nix @@ -357,6 +357,10 @@ with mylib.networking; { flake = "/home/${username}/NixFlake"; }; + niri = { + enable = !headless; + }; + ssh.startAgent = true; # Use gnupg starship.enable = true; xwayland.enable = !headless;