diff --git a/common/flake.nix b/common/flake.nix index 1b299be..05bf7ab 100644 --- a/common/flake.nix +++ b/common/flake.nix @@ -3,7 +3,6 @@ # NOTE if you add/change any inputs here also add them in the TOP level repo's flake.nix home-manager.url = "github:rycee/home-manager/release-25.05"; ragenix.url = "github:yaxitech/ragenix"; - nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=latest"; hyprland.url = "github:hyprwm/Hyprland"; }; @@ -28,7 +27,6 @@ imports = [ home-manager.nixosModules.default ragenix.nixosModules.age - nix-flatpak.nixosModules.nix-flatpak hyprland.nixosModules.default ./_home_manager ./options.nix diff --git a/common/programs/default.nix b/common/programs/default.nix index c56a1ab..82c2679 100644 --- a/common/programs/default.nix +++ b/common/programs/default.nix @@ -13,7 +13,6 @@ in ./docker.nix ./podman.nix ./incus.nix - ./flatpaks.nix ./virt-manager.nix ]; config = { diff --git a/common/programs/flatpaks.nix b/common/programs/flatpaks.nix deleted file mode 100644 index 307fff2..0000000 --- a/common/programs/flatpaks.nix +++ /dev/null @@ -1,66 +0,0 @@ -{ - config, - lib, - ... -}: -let - ccfg = import ../config.nix; - cfg_path = [ - ccfg.custom_config_key - "programs" - "flatpaks" - ]; - cfg = lib.attrsets.getAttrFromPath cfg_path config; -in -{ - options = - { } - // lib.attrsets.setAttrByPath cfg_path { - enable = lib.mkEnableOption "flatpaks"; - packages = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - description = "List of Flatpak package names to install."; - }; - }; - - config = lib.mkIf cfg.enable { - services.flatpak = { - enable = true; - packages = cfg.packages; - overrides = { - global = { - Context.sockets = [ - "wayland" - "x11" - ]; - Context.devices = [ "dri" ]; # allow GPU access if desired - Environment = { - XCURSOR_PATH = "/run/host/user-share/icons:/run/host/share/icons"; - GTK_THEME = "Adwaita:dark"; - # Force wayland as much as possible. - ELECTRON_OZONE_PLATFORM_HINT = "auto"; # or 'auto' - GTK_USE_PORTAL = "1"; - OZONE_PLATFORM = "wayland"; - QT_QPA_PLATFORM = "xcb"; # force XCB for Flatpaks (XWayland) - }; - }; - "org.signal.Signal" = { - Environment = { - SIGNAL_PASSWORD_STORE = "gnome-libsecret"; - }; - Context = { - sockets = [ - "xfg-settings" - ]; - }; - }; - "com.google.Chrome" = { - Environment = { - CHROME_EXTRA_ARGS = "--enable-features=WaylandWindowDecorations --ozone-platform-hint=auto"; - }; - }; - }; - }; - }; -} diff --git a/flakes/common/flake.nix b/flakes/common/flake.nix new file mode 100644 index 0000000..bed3399 --- /dev/null +++ b/flakes/common/flake.nix @@ -0,0 +1,16 @@ +let + utils = import ./utils.nix; +in +with utils; +{ + description = "Common NixOS configuration modules and Home Manager modules that require not other inputs beyond nixpkgs or home-manager itself. This is made by me for me and not designed to be general purpose for anyone else, but could be useful nontheless."; + inputs = { }; + outputs = + { + ... + }: + { + nixosModules = importAll ./nix_modules; + homeManagerModules = importAll ./hm_modules; + }; +} diff --git a/flakes/common/hm_modules/alacritty.nix b/flakes/common/hm_modules/alacritty.nix new file mode 100644 index 0000000..0794c15 --- /dev/null +++ b/flakes/common/hm_modules/alacritty.nix @@ -0,0 +1,34 @@ +{ ... }: +{ + programs.alacritty = { + enable = true; + settings = { + window = { + decorations = "None"; + dynamic_title = false; + }; + colors = { + primary = { + foreground = "#e0e0e0"; + background = "#262626"; + }; + normal = { + # Catppuccin Coal + black = "#1f1f1f"; + red = "#f38ba8"; + green = "#a6e3a1"; + yellow = "#f9e2af"; + blue = "#89b4fa"; + magenta = "#cba6f7"; + cyan = "#89dceb"; + white = "#e0e0e0"; + }; + }; + font = { + normal = { family = "JetBrainsMonoNL Nerd Font"; style = "Regular"; }; + size = 12.0; + }; + }; + }; +} + diff --git a/flakes/common/hm_modules/atuin.nix b/flakes/common/hm_modules/atuin.nix new file mode 100644 index 0000000..021745f --- /dev/null +++ b/flakes/common/hm_modules/atuin.nix @@ -0,0 +1,18 @@ +{ ... }: +# TODO setup auto secret/login for sync +{ + programs.atuin = { + enable = true; + enableZshIntegration = true; # TODO make dynamic? + flags = [ "--disable-up-arrow" ]; + settings = { + workspaces = true; + exit-mode = "return-query"; + enter_accept = true; + sync_address = "https://atuin.joshuabell.xyz"; + sync = { + records = true; + }; + }; + }; +} diff --git a/flakes/common/hm_modules/de_sway/default.nix b/flakes/common/hm_modules/de_sway/default.nix new file mode 100644 index 0000000..09539e5 --- /dev/null +++ b/flakes/common/hm_modules/de_sway/default.nix @@ -0,0 +1,12 @@ +{ ... }: +{ + imports = [ + ./theme.nix + ./sway.nix + ./waybar.nix + ./wofi.nix + ./swaync.nix + ./swaylock.nix + ./polkit.nix + ]; +} diff --git a/flakes/common/hm_modules/de_sway/polkit.nix b/flakes/common/hm_modules/de_sway/polkit.nix new file mode 100644 index 0000000..785abb2 --- /dev/null +++ b/flakes/common/hm_modules/de_sway/polkit.nix @@ -0,0 +1,4 @@ +{ ... }: +{ + services.polkit-gnome.enable = true; +} diff --git a/flakes/common/hm_modules/de_sway/sway.nix b/flakes/common/hm_modules/de_sway/sway.nix new file mode 100644 index 0000000..9854d05 --- /dev/null +++ b/flakes/common/hm_modules/de_sway/sway.nix @@ -0,0 +1,180 @@ +{ + config, + ... +}: + +{ + wayland.windowManager.sway = { + enable = true; + xwayland = true; + + systemd.enable = true; + + config = rec { + modifier = "Mod4"; # SUPER + terminal = "foot"; + menu = "wofi --show drun"; + + # Per-output workspace mapping (user can extend via extraOptions) + # Example (left as defaults): users can add `output HDMI-A-1 workspace 1,3,5` in extraOptions + + input = { + "type:keyboard" = { + xkb_layout = "us"; + xkb_options = "caps:escape"; + }; + "type:touchpad" = { + natural_scroll = "enabled"; + tap = "enabled"; + dwt = "enabled"; + }; + # Disable focus follows mouse to avoid accidental focus changes + # In Sway this behavior is controlled by focus_follows_mouse + }; + + focus = { + followMouse = "no"; + # onWindowActivation = "urgent"; # don't steal focus; mark urgent instead + }; + + gaps = { + inner = 2; + outer = 5; + smartGaps = false; + smartBorders = "on"; + }; + + colors = { + focused = { + background = "#444444"; + border = "#555555"; + childBorder = "#444444"; + indicator = "#595959"; + text = "#f1f1f1"; + }; + unfocused = { + background = "#222222"; + border = "#333333"; + childBorder = "#222222"; + indicator = "#292d2e"; + text = "#888888"; + }; + }; + + window = { + border = 1; + titlebar = false; + commands = [ + # Bitwarden chrome popup as floating example from Hyprland rules + { + criteria = { + app_id = "chrome-nngceckbapebfimnlniiiahkandclblb-Default"; + }; + command = "floating enable"; + } + { + criteria = { + app_id = "pavucontrol"; + }; + command = "floating enable, move position center, resize set 620 1200"; + } + { + criteria = { + class = "Google-chrome"; + window_role = "pop-up"; + }; + command = "floating enable, move position center, resize set 720 480"; + } + { + criteria = { + window_role = "pop-up"; + }; + command = "floating enable, move position center, resize set 640 420"; + } + { + criteria = { + window_role = "About"; + }; + command = "floating enable, move position center, resize set 640 420"; + } + ]; + }; + + # Keybindings mirroring Hyprland + keybindings = { + # Apps + "${modifier}+return" = "exec ${config.wayland.winfowManager.sway.config.terminal}"; + "${modifier}+space" = "exec pkill wofi || wofi --show drun"; + "${modifier}+q" = "kill"; + "${modifier}+shift+Escape" = "exit"; + "${modifier}+shift+q" = "exec swaylock"; + "${modifier}+f" = "floating toggle"; + + # Focus + "${modifier}+h" = "focus left"; + "${modifier}+l" = "focus right"; + "${modifier}+k" = "focus up"; + "${modifier}+j" = "focus down"; + + # Workspaces (numbers and vim-like mirror) + "${modifier}+1" = "workspace number 1"; + "${modifier}+n" = "workspace number 1"; + "${modifier}+2" = "workspace number 2"; + "${modifier}+m" = "workspace number 2"; + "${modifier}+3" = "workspace number 3"; + "${modifier}+comma" = "workspace number 3"; + "${modifier}+4" = "workspace number 4"; + "${modifier}+period" = "workspace number 4"; + "${modifier}+5" = "workspace number 5"; + "${modifier}+slash" = "workspace number 5"; + "${modifier}+6" = "workspace number 6"; + "${modifier}+7" = "workspace number 7"; + "${modifier}+8" = "workspace number 8"; + "${modifier}+9" = "workspace number 9"; + "${modifier}+0" = "workspace number 10"; + + # Move windows + "${modifier}+shift+h" = "move left"; + "${modifier}+shift+l" = "move right"; + "${modifier}+shift+k" = "move up"; + "${modifier}+shift+j" = "move down"; + "${modifier}+shift+1" = "move container to workspace number 1"; + "${modifier}+shift+n" = "move container to workspace number 1"; + "${modifier}+shift+2" = "move container to workspace number 2"; + "${modifier}+shift+m" = "move container to workspace number 2"; + "${modifier}+shift+3" = "move container to workspace number 3"; + "${modifier}+shift+comma" = "move container to workspace number 3"; + "${modifier}+shift+4" = "move container to workspace number 4"; + "${modifier}+shift+period" = "move container to workspace number 4"; + "${modifier}+shift+5" = "move container to workspace number 5"; + "${modifier}+shift+slash" = "move container to workspace number 5"; + "${modifier}+shift+6" = "move container to workspace number 6"; + "${modifier}+shift+7" = "move container to workspace number 7"; + "${modifier}+shift+8" = "move container to workspace number 8"; + "${modifier}+shift+9" = "move container to workspace number 9"; + "${modifier}+shift+0" = "move container to workspace number 10"; + + "${modifier}+left" = "resize shrink width 10 px or 10 ppt"; + "${modifier}+down" = "resize shrink height 10 px or 10 ppt"; + "${modifier}+up" = "resize grow height 10 px or 10 ppt"; + "${modifier}+right" = "resize grow width 10 px or 10 ppt"; + + # Mouse bindings (Mod + drag) + "${modifier}+button1" = "move"; + "${modifier}+button3" = "resize"; + + # Screenshot + "Print" = "exec grim -g \"$(slurp)\" - | wl-copy"; + }; + + bars = [ ]; # Use Waybar via Home Manager + startup = [ + { + command = "exec sh -c 'sleep 0.01; swaymsg workspace number 7 ; sleep 0.01; swaymsg workspace number 1'"; + } + # Waybar is managed by Home Manager systemd unit + # { command = "pgrep waybar >/dev/null || waybar"; } + ]; + }; + }; +} diff --git a/flakes/common/hm_modules/de_sway/swaylock.nix b/flakes/common/hm_modules/de_sway/swaylock.nix new file mode 100644 index 0000000..86243aa --- /dev/null +++ b/flakes/common/hm_modules/de_sway/swaylock.nix @@ -0,0 +1,15 @@ +{ ... }: +{ + programs.swaylock = { + enable = true; + settings = { + color = "#000000"; + indicator-caps-lock = true; + indicator-idle-visible = true; + indicator-radius = 100; + indicator-thickness = 10; + font = "JetBrainsMono Nerd Font Regular"; + font-size = 20; + }; + }; +} diff --git a/flakes/common/hm_modules/de_sway/swaync.nix b/flakes/common/hm_modules/de_sway/swaync.nix new file mode 100644 index 0000000..a60df5d --- /dev/null +++ b/flakes/common/hm_modules/de_sway/swaync.nix @@ -0,0 +1,100 @@ +{ ... }: +{ + services.swaync = { + enable = true; + settings = { + ignore = [ "com.spotify.Client" ]; + positionX = "right"; + positionY = "top"; + layer = "overlay"; + control-center-layer = "top"; + layer-shell = true; + cssPriority = "application"; + control-center-margin-top = 0; + control-center-margin-bottom = 0; + control-center-margin-right = 0; + control-center-margin-left = 0; + notification-2fa-action = true; + notification-inline-replies = false; + notification-icon-size = 64; + notification-body-image-height = 100; + notification-body-image-width = 200; + timeout = 10; + timeout-low = 5; + timeout-critical = 0; + control-center-width = 500; + control-center-height = 600; + notification-window-width = 500; + keyboard-shortcuts = true; + image-visibility = "when-available"; + transition-time = 200; + hide-on-clear = false; + hide-on-action = true; + script-fail-notify = true; + widgets = [ + "inhibitors" + "title" + "dnd" + "volume" + "backlight" + "mpris" + "buttons-grid#quick" + "notifications" + ]; + widget-config = { + inhibitors = { + text = "Inhibitors"; + button-text = "Clear All"; + clear-all-button = true; + }; + title = { + text = "Notifications"; + clear-all-button = true; + button-text = "Clear All"; + }; + dnd.text = "Do Not Disturb"; + mpris = { + image-size = 96; + image-radius = 12; + }; + volume = { + label = "󰕾"; + show-per-app = true; + }; + backlight = { + label = "󰃟"; + device = "intel_backlight"; + }; + # "buttons-grid#quick" = { + # columns = 4; + # icon-size = 20; + # actions = [ + # { label = "󰐥"; tooltip = "Shutdown"; command = "confirm-action 'systemctl poweroff' 'Shutdown?'"; } + # { label = "󰜉"; tooltip = "Reboot"; command = "confirm-action 'systemctl reboot' 'Reboot?'"; } + # { label = "󰍃"; tooltip = "Logout"; command = "confirm-action 'swaymsg exit' 'Logout?'"; } + # ]; + # }; + }; + }; + style = '' + .control-center { background: #1a1b26; border: 2px solid #7dcae4; border-radius: 12px; } + .control-center-list { background: transparent; } + .control-center .notification-row:focus, .control-center .notification-row:hover { opacity: 1; background: #24283b; } + .notification { border-radius: 8px; margin: 6px 12px; box-shadow: 0 0 0 1px rgba(125,196,228,.3), 0 1px 3px 1px rgba(0,0,0,.7), 0 2px 6px 2px rgba(0,0,0,.3); padding: 0; } + .widget-title { margin: 8px; font-size: 1.5rem; color: #c0caf5; } + .widget-dnd { margin: 8px; font-size: 1.1rem; color: #c0caf5; } + .widget-dnd > switch { font-size: initial; border-radius: 8px; background: #414868; border: 1px solid #7dcae4; } + .widget-dnd > switch:checked { background: #7dcae4; } + .widget-mpris { color: #c0caf5; background: #24283b; padding: 8px; margin: 8px; border-radius: 8px; } + .widget-mpris-player { padding: 8px; margin: 8px; } + .widget-mpris-title { font-weight: bold; font-size: 1.25rem; } + .widget-mpris-subtitle { font-size: 1.1rem; color: #9ece6a; } + .widget-volume, .widget-backlight, .widget-menubar { background: #24283b; padding: 8px; margin: 8px; border-radius: 8px; color: #c0caf5; } + .widget-menubar .menu-item button { background: #1f2335; color: #c0caf5; border-radius: 8px; padding: 6px 10px; margin: 4px; border: 1px solid #2e3440; font-family: "JetBrainsMonoNL Nerd Font"; } + .widget-menubar .menu-item button:hover { background: #414868; border-color: #7dcae4; } + .topbar-buttons button { border: none; background: transparent; color: #c0caf5; font-size: 1.1rem; border-radius: 8px; margin: 0 4px; padding: 8px; } + .topbar-buttons button:hover { background: #414868; } + .topbar-buttons button:active { background: #7dcae4; color: #1a1b26; } + ''; + }; +} diff --git a/flakes/common/hm_modules/de_sway/theme.nix b/flakes/common/hm_modules/de_sway/theme.nix new file mode 100644 index 0000000..5a3fbf7 --- /dev/null +++ b/flakes/common/hm_modules/de_sway/theme.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: +{ + home.pointerCursor = { + gtk.enable = true; + package = pkgs.bibata-cursors; + name = "Bibata-Modern-Classic"; + size = 16; + }; + gtk = { + enable = true; + theme = { package = pkgs.flat-remix-gtk; name = "Flat-Remix-GTK-Grey-Darkest"; }; + iconTheme = { package = pkgs.adwaita-icon-theme; name = "Adwaita"; }; + font = { name = "Sans"; size = 11; }; + }; +} diff --git a/flakes/common/hm_modules/de_sway/waybar.nix b/flakes/common/hm_modules/de_sway/waybar.nix new file mode 100644 index 0000000..cf2afff --- /dev/null +++ b/flakes/common/hm_modules/de_sway/waybar.nix @@ -0,0 +1,246 @@ +{ ... }: +{ + programs.waybar = { + enable = true; + systemd.enable = true; + settings = { + mainBar = { + layer = "top"; + position = "top"; + height = 28; + spacing = 6; + margin-top = 0; + margin-bottom = 0; + margin-left = 10; + margin-right = 10; + + modules-left = [ + "sway/workspaces" + ]; + modules-center = [ + "clock" + "temperature" + "cpu" + "memory" + "disk" + ]; + modules-right = [ + "battery" + "battery#bat2" + "pulseaudio" + "network" + "bluetooth" + "power-profiles-daemon" + "backlight" + "custom/notifications" + "sway/language" + "tray" + "custom/power" + ]; + + "sway/workspaces" = { + format = "{icon}"; + format-icons = { + "1" = "一"; + "2" = "二"; + "3" = "三"; + "4" = "四"; + "5" = "五"; + "6" = "六"; + "7" = "七"; + "8" = "八"; + "9" = "九"; + "10" = "十"; + "11" = "十一"; + "12" = "十二"; + "13" = "十三"; + "14" = "十四"; + "15" = "十五"; + "16" = "十六"; + "17" = "十七"; + "18" = "十八"; + "19" = "十九"; + "20" = "二十"; + }; + disable-scroll = false; + }; + + # CENTER + clock = { + format = "{:%b %d, %H:%M}"; + tooltip-format = "{:%Y %B}\n{calendar}"; + }; + + temperature = { + thermal-zone = 2; + hwmon-path = "/sys/class/hwmon/hwmon2/temp1_input"; + critical-threshold = 80; + format-critical = "󰔏 {temperatureC}°C"; + format = "󰔏 {temperatureC}°C"; + }; + + cpu = { + format = "󰻠 {usage}%"; + tooltip = true; + on-click = "btop"; + }; + + memory = { + format = "󰍛 {}%"; + on-click = "btop"; + }; + + disk = { + interval = 30; + format = "󰋊 {percentage_used}%"; + path = "/"; + on-click = "btop"; + }; + + # RIGHT + "battery" = { + "states" = { + # "good"= 95; + "warning" = 30; + "critical" = 15; + }; + "format" = "{capacity}% {icon}"; + "format-full" = "{capacity}% {icon}"; + "format-charging" = "{capacity}% "; + "format-plugged" = "{capacity}% "; + "format-alt" = "{time} {icon}"; + # "format-good"= ""; // An empty format will hide the module + # "format-full"= ""; + "format-icons" = [ + "" + "" + "" + "" + "" + ]; + }; + "battery#bat2" = { + "bat" = "BAT2"; + }; + + pulseaudio = { + format = "{icon} {volume}%"; + format-bluetooth = "󰂰 {volume}%"; + format-bluetooth-muted = "󰂲 "; + format-muted = "󰖁 "; + format-source = "󰍬 {volume}%"; + format-source-muted = "󰍭 "; + format-icons = { + headphone = "󰋋"; + hands-free = "󰂑"; + headset = "󰂑"; + phone = "󰏲"; + portable = "󰦧"; + car = "󰄋"; + default = [ + "󰕿" + "󰖀" + "󰕾" + ]; + }; + scroll-step = 5; + on-click = "pavucontrol"; + on-click-right = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; + }; + + network = { + format-wifi = "󰤨 {essid} ({signalStrength}%)"; + format-ethernet = "󰈀 {ipaddr}/{cidr}"; + tooltip-format = "{ifname} via {gwaddr} "; + format-linked = "󰈀 {ifname} (No IP)"; + format-disconnected = "󰖪 Disconnected"; + # on-click = "wofi-wifi-menu"; + # on-click-right = "nmcli radio wifi toggle"; + }; + + bluetooth = { + format = "󰂯 {status}"; + format-connected = "󰂱 {device_alias}"; + format-connected-battery = "󰂱 {device_alias} {device_battery_percentage}%"; + tooltip-format = "{controller_alias}\t{controller_address}\n\n{num_connections} connected"; + tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}"; + tooltip-format-enumerate-connected = "{device_alias}\t{device_address}"; + tooltip-format-enumerate-connected-battery = "{device_alias}\t{device_address}\t{device_battery_percentage}%"; + # on-click = "wofi-bluetooth-menu"; + # on-click-right = "bluetoothctl power toggle"; + }; + + "power-profiles-daemon" = { + format = "{icon}"; + "tooltip-format" = "Power profile: {profile}\nDriver: {driver}"; + tooltip = true; + "format-icons" = { + default = ""; + performance = ""; + balanced = ""; + "power-saver" = ""; + }; + }; + + backlight = { + format = "{percent}% {icon}"; + "format-icons" = [ + "" + "" + "" + "" + "" + "" + "" + "" + "" + ]; + }; + + "custom/notifications" = { + format = "{icon} {}"; + format-icons = { + notification = ""; + none = ""; + dnd-notification = "󰂛"; + dnd-none = "󰂛"; + inhibited-notification = ""; + inhibited-none = ""; + dnd-inhibited-notification = "󰂛"; + dnd-inhibited-none = "󰂛"; + }; + return-type = "json"; + exec-if = "which swaync-client"; + exec = "swaync-client -swb"; + on-click = "swaync-client -t -sw"; + on-click-right = "swaync-client -d -sw"; + escape = true; + tooltip = false; + }; + + "sway/language" = { + format = "{}"; + }; + + "tray" = { + "spacing" = 10; + }; + + "custom/power" = { + format = "⏻ "; + tooltip = false; + menu = "on-click"; + "menu-file" = ./waybar/power_menu.xml; + "menu-actions" = { + shutdown = "shutdown 0"; + reboot = "reboot"; + logout = "loginctl terminate-session $(loginctl list-sessions | grep seat0 | awk '{print $1}')"; + }; + }; + + }; + }; + + style = builtins.readFile ./waybar/waybar.css; + }; +} diff --git a/flakes/common/hm_modules/de_sway/waybar/power_menu.xml b/flakes/common/hm_modules/de_sway/waybar/power_menu.xml new file mode 100644 index 0000000..a061b18 --- /dev/null +++ b/flakes/common/hm_modules/de_sway/waybar/power_menu.xml @@ -0,0 +1,26 @@ + + + + + + Logout + + + + + + + + Reboot + + + + + + + + Shutdown + + + + diff --git a/flakes/common/hm_modules/de_sway/waybar/waybar.css b/flakes/common/hm_modules/de_sway/waybar/waybar.css new file mode 100644 index 0000000..efeba06 --- /dev/null +++ b/flakes/common/hm_modules/de_sway/waybar/waybar.css @@ -0,0 +1,101 @@ +* { + /* `otf-font-awesome` is required to be installed for icons */ + font-family: "JetBrainsMonoNL Nerd Font", FontAwesome, Roboto, Helvetica, Arial, sans-serif; + font-size: 14px; + border: none; + border-radius: 0; + min-height: 0; + color: #f1f1f1; +} + +window#waybar { + background: transparent; +} + +#workspaces button.focused { + background-color: rgba(220, 220, 220, 0.2); +} + +#workspaces button.urgent { + background-color: rgba(214, 82, 82, 0.3); +} + +button, +#clock, +#battery, +#cpu, +#memory, +#disk, +#temperature, +#backlight, +#network, +#pulseaudio, +#wireplumber, +#custom-media, +#custom-notifications, +#custom-power, +#tray, +#mode, +#idle_inhibitor, +#scratchpad, +#power-profiles-daemon, +#bluetooth, +#language, +#mpd { + padding: 0 5px; + color: #f1f1f1; + background-color: rgba(220, 220, 220, 0.1); + border-radius: 6px; +} + + +button:hover, +#clock:hover, +#battery:hover, +#cpu:hover, +#memory:hover, +#disk:hover, +#temperature:hover, +#backlight:hover, +#network:hover, +#pulseaudio:hover, +#wireplumber:hover, +#custom-media:hover, +#custom-notifications:hover, +#tray:hover, +#mode:hover, +#idle_inhibitor:hover, +#scratchpad:hover, +#power-profiles-daemon:hover, +#bluetooth:hover, +#language:hover, +#mpd:hover { + color: #f1f1f1; + background-color: rgba(220, 220, 220, 0.2); + border-radius: 6px; +} + +#power-profiles-daemon { + padding-right: 15px; +} + +#power-profiles-daemon.performance { + color: #fff7d6; +} + +#power-profiles-daemon.balanced { + color: #d6efff; +} + +#power-profiles-daemon.power-saver { + color:#dcffd6; +} + +#tray>.passive { + -gtk-icon-effect: dim; +} + +#tray>.needs-attention { + -gtk-icon-effect: highlight; + background-color: #eb4d4b; +} diff --git a/flakes/common/hm_modules/de_sway/wofi.nix b/flakes/common/hm_modules/de_sway/wofi.nix new file mode 100644 index 0000000..8c0ba40 --- /dev/null +++ b/flakes/common/hm_modules/de_sway/wofi.nix @@ -0,0 +1,23 @@ +{ ... }: +{ + programs.wofi = { + enable = true; + settings = { + width = 500; + height = 600; + location = "bottom"; + show = "drun"; + prompt = "..."; + filter_rate = 100; + allow_markup = true; + no_actions = true; + halign = "fill"; + orientation = "vertical"; + content_halign = "fill"; + insensitive = true; + allow_images = true; + image_size = 40; + gtk_dark = true; + }; + }; +} diff --git a/flakes/common/hm_modules/direnv.nix b/flakes/common/hm_modules/direnv.nix new file mode 100644 index 0000000..b36ce49 --- /dev/null +++ b/flakes/common/hm_modules/direnv.nix @@ -0,0 +1,23 @@ +{ ... }: +{ + programs.direnv = { + enable = true; + enableZshIntegration = true; + nix-direnv.enable = true; + config = { + nix-direnv = true; + global = { + strict_env = true; + load_dotenv = true; + hide_env_diff = true; + }; + whitelist = { + prefix = [ + "~/projects" + "~/.config" + "~/.local/share/git_worktrees/" + ]; + }; + }; + }; +} diff --git a/flakes/common/hm_modules/foot.nix b/flakes/common/hm_modules/foot.nix new file mode 100644 index 0000000..d52af61 --- /dev/null +++ b/flakes/common/hm_modules/foot.nix @@ -0,0 +1,47 @@ +{ ... }: +{ + programs.foot = { + enable = true; + + # This renders to ~/.config/foot/foot.ini + settings = { + main = { + # Use the same font and size as your Kitty config + font = "JetBrainsMonoNL Nerd Font:size=12"; + + # Initial window size in character cells (Kitty used 160c x 55c) + "initial-window-size-chars" = "160x55"; + }; + + colors = { + # Background opacity (1.0 = opaque) + alpha = "0.94"; + + # Foreground/background + foreground = "e0e0e0"; + background = "262626"; + + # 16-color palette + # normal (0–7) + regular0 = "1f1f1f"; # black + regular1 = "f38ba8"; # red + regular2 = "a6e3a1"; # green + regular3 = "f9e2af"; # yellow + regular4 = "89b4fa"; # blue + regular5 = "cba6f7"; # magenta + regular6 = "89dceb"; # cyan + regular7 = "e0e0e0"; # white + + # bright (8–15) + bright0 = "565656"; # bright black + bright1 = "f38ba8"; # bright red + bright2 = "a6e3a1"; # bright green + bright3 = "f9e2af"; # bright yellow + bright4 = "89b4fa"; # bright blue + bright5 = "cba6f7"; # bright magenta + bright6 = "89dceb"; # bright cyan + bright7 = "ffffff"; # bright white + }; + }; + }; +} diff --git a/flakes/common/hm_modules/git.nix b/flakes/common/hm_modules/git.nix new file mode 100644 index 0000000..34e6d18 --- /dev/null +++ b/flakes/common/hm_modules/git.nix @@ -0,0 +1,67 @@ +{ ... }: +{ + programs.git = { + enable = true; + # TODO make configurable + userEmail = "ringofstorms@gmail.com"; + userName = "RingOfStorms (Joshua Bell)"; + + extraConfig = { + core.pager = "bat"; + core.editor = "nano"; + + pull.rebase = false; + + init.defaultBranch = "main"; + + rerere.enabled = true; + }; + + difftastic = { + enable = true; + background = "dark"; + }; + + ignores = [ + # -------------- + # Intellij + # -------------- + "*.iml" + # -------------- + # MAC OS + # -------------- + ".DS_Store" + ".AppleDouble" + ".LSOverride" + # Icon must end with two \r + "Icon" + # Thumbnails + "._*" + # Files that might appear in the root of a volume + ".DocumentRevisions-V100" + ".fseventsd" + ".Spotlight-V100" + ".TemporaryItems" + ".Trashes" + ".VolumeIcon.icns" + ".com.apple.timemachine.donotpresent" + + # Directories potentially created on remote AFP share + ".AppleDB" + ".AppleDesktop" + "Network Trash Folder" + "Temporary Items" + ".apdisk" + + # direnv things + ".direnv" + + # local only files + "*.local" + + # AI tooling + ".aider*" + "aider" + ]; + }; +} diff --git a/flakes/common/hm_modules/kitty.nix b/flakes/common/hm_modules/kitty.nix new file mode 100644 index 0000000..236c6ef --- /dev/null +++ b/flakes/common/hm_modules/kitty.nix @@ -0,0 +1,56 @@ +{ ... }: +{ + # Enable Kitty terminal + programs.kitty = { + enable = true; + + settings = { + # Window settings + background_opacity = 1.0; + os_window_class = "kitty"; + remember_window_size = false; + placement_strategy = "center"; + initial_window_width = "160c"; + initial_window_height = "55c"; + + # Remove window borders + hide_window_decorations = "titlebar-only"; + tab_title_template = "none"; + active_tab_title_template = "none"; + draw_minimal_borders = "yes"; + window_border_width = "0.1pt"; + + # Colors (Catppuccin Coal) + foreground = "#e0e0e0"; + background = "#262626"; + color0 = "#1f1f1f"; + color1 = "#f38ba8"; + color2 = "#a6e3a1"; + color3 = "#f9e2af"; + color4 = "#89b4fa"; + color5 = "#cba6f7"; + color6 = "#89dceb"; + color7 = "#e0e0e0"; + color8 = "#565656"; + color9 = "#f38ba8"; + color10 = "#a6e3a1"; + color11 = "#f9e2af"; + color12 = "#89b4fa"; + color13 = "#cba6f7"; + color14 = "#89dceb"; + color15 = "#ffffff"; + + # Font settings + font_family = "JetBrainsMonoNL Nerd Font"; + font_size = 12.0; + bold_font = "auto"; + italic_font = "auto"; + italic_bold_font = "auto"; + }; + + # If you want to include extra configuration this way instead of through the main `settings` attribute + extraConfig = '' + # You can add additional config here if needed + ''; + }; +} diff --git a/flakes/common/hm_modules/launcher_rofi.nix b/flakes/common/hm_modules/launcher_rofi.nix new file mode 100644 index 0000000..353b29e --- /dev/null +++ b/flakes/common/hm_modules/launcher_rofi.nix @@ -0,0 +1,18 @@ +{ + pkgs, + ... +}: +{ + programs.rofi = { + enable = true; + plugins = with pkgs; [ rofi-calc ]; + extraConfig = { + modi = "drun,run,ssh,window,calc"; + terminal = "alacritty"; + }; + theme = "glue_pro_blue"; + }; + programs.wofi = { + enable = true; + }; +} diff --git a/flakes/common/hm_modules/postgres_cli_options.nix b/flakes/common/hm_modules/postgres_cli_options.nix new file mode 100644 index 0000000..053099b --- /dev/null +++ b/flakes/common/hm_modules/postgres_cli_options.nix @@ -0,0 +1,7 @@ +{ ... }: +{ + home.file.".psqlrc".text = '' + \pset pager off + ''; +} + diff --git a/flakes/common/hm_modules/slicer.nix b/flakes/common/hm_modules/slicer.nix new file mode 100644 index 0000000..4361d5a --- /dev/null +++ b/flakes/common/hm_modules/slicer.nix @@ -0,0 +1,33 @@ +{ pkgs, ... }: +let + orca-slicer-fix = pkgs.stdenv.mkDerivation { + name = "orca-slicer"; + buildInputs = [ pkgs.makeWrapper ]; + unpackPhase = "true"; + buildPhase = '' + mkdir -p $out/bin + makeWrapper ${pkgs.orca-slicer}/bin/orca-slicer $out/bin/orca-slicer \ + --set WEBKIT_DISABLE_DMABUF_RENDERER 1 + ''; + + installPhase = '' + mkdir -p $out/share/applications + cat > $out/share/applications/orca-slicer.desktop </dev/null || waybar" ]; + + # Default monitor configuration + monitor = "monitor = , preferred, auto, 1"; + + windowrulev2 = [ + # Bitwarden password manager popup for chrome, always float it + "float, class:^(?i)chrome-nngceckbapebfimnlniiiahkandclblb-Default$, initialtitle:^_crx_nngceckbapebfimnlniiiahkandclblb$" + "center, class:^(?i)chrome-nngceckbapebfimnlniiiahkandclblb-Default$, initialtitle:^_crx_nngceckbapebfimnlniiiahkandclblb$" + "size 720 600, class:^(?i)chrome-nngceckbapebfimnlniiiahkandclblb-Default$, initialtitle:^_crx_nngceckbapebfimnlniiiahkandclblb$" + ]; + + # Input configuration + input = { + kb_layout = "us"; + kb_options = "caps:escape"; + + follow_mouse = 2; + touchpad = { + natural_scroll = true; + disable_while_typing = true; + }; + }; + + # General settings + general = { + gaps_in = 2; + gaps_out = 4; + border_size = 1; + "col.active_border" = "rgba(797979aa)"; + "col.inactive_border" = "rgba(393939aa)"; + layout = "dwindle"; + }; + + # Decoration + decoration = { + rounding = 4; + blur.enabled = false; + }; + + # Animations + animations = { + enabled = false; + }; + + # Layout + dwindle = { + pseudotile = true; + preserve_split = true; + }; + + # Misc + misc = { + force_default_wallpaper = 0; + disable_hyprland_logo = true; + disable_splash_rendering = true; + }; + + # Key bindings + "$mainMod" = "SUPER"; + + bind = [ + # Applications + "$mainMod, Return, exec, ${cfg.terminalCommand}" + "$mainMod, Space, exec, pkill wofi || wofi --show drun" + "$mainMod, q, killactive" + "$mainMod SHIFT, escape, exit" + "$mainMod SHIFT, q, exec, swaylock" + "$mainMod, f, togglefloating" + "$mainMod SHIFT, F, fullscreen" + "$mainMod, g, pseudo" + "$mainMod, t, togglesplit" + + # Move focus with mainMod + hjkl + "$mainMod, h, movefocus, l" + "$mainMod, l, movefocus, r" + "$mainMod, k, movefocus, u" + "$mainMod, j, movefocus, d" + + # Switch workspaces with mainMod + [0-9] + "$mainMod, 1, workspace, 1" + "$mainMod, n, workspace, 1" + "$mainMod, 2, workspace, 2" + "$mainMod, m, workspace, 2" + "$mainMod, 3, workspace, 3" + "$mainMod, comma, workspace, 3" + "$mainMod, 4, workspace, 4" + "$mainMod, period, workspace, 4" + "$mainMod, 5, workspace, 5" + "$mainMod, slash, workspace, 5" + "$mainMod, 6, workspace, 6" + "$mainMod, 7, workspace, 7" + "$mainMod, 8, workspace, 8" + "$mainMod, 9, workspace, 9" + "$mainMod, 0, workspace, 10" + + # Window management (similar to your GNOME setup) + "$mainMod SHIFT, h, movewindow, l" + "$mainMod SHIFT, l, movewindow, r" + "$mainMod SHIFT, k, movewindow, u" + "$mainMod SHIFT, j, movewindow, d" + "$mainMod SHIFT, 1, movetoworkspacesilent, 1" + "$mainMod SHIFT, n, movetoworkspacesilent, 1" + "$mainMod SHIFT, 2, movetoworkspacesilent, 2" + "$mainMod SHIFT, m, movetoworkspacesilent, 2" + "$mainMod SHIFT, 3, movetoworkspacesilent, 3" + "$mainMod SHIFT, comma, movetoworkspacesilent, 3" + "$mainMod SHIFT, 4, movetoworkspacesilent, 4" + "$mainMod SHIFT, period, movetoworkspacesilent, 4" + "$mainMod SHIFT, 5, movetoworkspacesilent, 5" + "$mainMod SHIFT, slash, movetoworkspacesilent, 5" + "$mainMod SHIFT, 6, movetoworkspacesilent, 6" + "$mainMod SHIFT, 7, movetoworkspacesilent, 7" + "$mainMod SHIFT, 8, movetoworkspacesilent, 8" + "$mainMod SHIFT, 9, movetoworkspacesilent, 9" + "$mainMod SHIFT, 0, movetoworkspacesilent, 10" + + # Screenshots + ", Print, exec, grimblast copy area" + ]; + + bindr = [ + # overview + # "$mainMod, SUPER_L, overview:toggle" $ hyprspace plugin + "$mainMod SHIFT, R, exec, systemctl --user restart hyprpanel.service" + ]; + + binde = [ + # Move between workspaces + # "$mainMod, n, workspace, r+1" + # "$mainMod, p, workspace, r-1" + + # Resize windows + "$mainMod CTRL, h, resizeactive, -40 0" + "$mainMod CTRL, l, resizeactive, 40 0" + "$mainMod CTRL, k, resizeactive, 0 -20" + "$mainMod CTRL, j, resizeactive, 0 20" + ]; + + # Mouse bindings + bindm = [ + "$mainMod, mouse:272, movewindow" + "$mainMod, mouse:273, resizewindow" + ]; + + } cfg.extraOptions; + }; +} diff --git a/flakes/hyprland/home_manager/hyprpaper.nix b/flakes/hyprland/home_manager/hyprpaper.nix new file mode 100644 index 0000000..06d6820 --- /dev/null +++ b/flakes/hyprland/home_manager/hyprpaper.nix @@ -0,0 +1,22 @@ +{ + osConfig, + lib, + ... +}: +let + ccfg = import ../../../config.nix; + cfg_path = [ + ccfg.custom_config_key + "desktopEnvironment" + "hyprland" + ]; + cfg = lib.attrsets.getAttrFromPath cfg_path osConfig; +in +{ + config = { + services.hyprpaper = { + enable = true; + settings = cfg.hyprpaperSettings; + }; + }; +} diff --git a/flakes/hyprland/home_manager/hyprpolkitagent.nix b/flakes/hyprland/home_manager/hyprpolkitagent.nix new file mode 100644 index 0000000..dc68933 --- /dev/null +++ b/flakes/hyprland/home_manager/hyprpolkitagent.nix @@ -0,0 +1,8 @@ +{ + ... +}: +{ + services.hyprpolkitagent = { + enable = true; + }; +} diff --git a/flakes/hyprland/home_manager/quickshell.nix b/flakes/hyprland/home_manager/quickshell.nix new file mode 100644 index 0000000..2f5032c --- /dev/null +++ b/flakes/hyprland/home_manager/quickshell.nix @@ -0,0 +1,93 @@ +{ + osConfig, + lib, + pkgs, + upkgs, + ... +}: +let + ccfg = import ../../../config.nix; + cfg_path = [ + ccfg.custom_config_key + "desktopEnvironment" + "hyprland" + ]; + cfg = lib.attrsets.getAttrFromPath cfg_path osConfig; +in +{ + home.packages = with pkgs; [ + upkgs.quickshell + pulseaudio + brightnessctl + networkmanager + bluez + bluez-tools + power-profiles-daemon + upower + systemd + hyprlock + ]; + + # Ensure CLI quickshell can resolve modules when not using --config-path + home.sessionVariables = { + QML_IMPORT_PATH = "$HOME/.config/quickshell"; + QML2_IMPORT_PATH = "$HOME/.config/quickshell"; + }; + + # install config files + home.file = { + ".config/quickshell/shell.qml".source = ./quickshell/shell.qml; + ".config/quickshell/panels/TopBar.qml".source = ./quickshell/panels/TopBar.qml; + ".config/quickshell/notifications/NotificationServer.qml".source = + ./quickshell/notifications/NotificationServer.qml; + ".config/quickshell/notifications/NotificationPopup.qml".source = + ./quickshell/notifications/NotificationPopup.qml; + ".config/quickshell/notifications/NotificationCenter.qml".source = + ./quickshell/notifications/NotificationCenter.qml; + ".config/quickshell/widgets/status/Workspaces.qml".source = + ./quickshell/widgets/status/Workspaces.qml; + ".config/quickshell/widgets/status/Clock.qml".source = ./quickshell/widgets/status/Clock.qml; + ".config/quickshell/widgets/status/SystemTrayWidget.qml".source = + ./quickshell/widgets/status/SystemTrayWidget.qml; + ".config/quickshell/widgets/status/Battery.qml".source = ./quickshell/widgets/status/Battery.qml; + ".config/quickshell/widgets/controls/QuickSettings.qml".source = + ./quickshell/widgets/controls/QuickSettings.qml; + ".config/quickshell/widgets/controls/Audio.qml".source = ./quickshell/widgets/controls/Audio.qml; + ".config/quickshell/widgets/controls/Network.qml".source = + ./quickshell/widgets/controls/Network.qml; + ".config/quickshell/widgets/controls/Bluetooth.qml".source = + ./quickshell/widgets/controls/Bluetooth.qml; + ".config/quickshell/widgets/controls/Brightness.qml".source = + ./quickshell/widgets/controls/Brightness.qml; + ".config/quickshell/widgets/controls/PowerProfilesWidget.qml".source = + ./quickshell/widgets/controls/PowerProfilesWidget.qml; + ".config/quickshell/panels/qmldir".source = ./quickshell/panels/qmldir; + ".config/quickshell/notifications/qmldir".source = ./quickshell/notifications/qmldir; + ".config/quickshell/widgets/status/qmldir".source = ./quickshell/widgets/status/qmldir; + ".config/quickshell/widgets/controls/qmldir".source = ./quickshell/widgets/controls/qmldir; + # optional: .qmlls.ini should be gitignored; create empty to enable LSP + ".config/quickshell/.qmlls.ini".text = ""; + }; + + systemd.user.services.quickshell = { + Unit = { + Description = "Quickshell Desktop Shell"; + PartOf = [ "graphical-session.target" ]; + After = [ "graphical-session.target" ]; + }; + Service = { + ExecStart = "${upkgs.quickshell}/bin/quickshell --config-path %h/.config/quickshell"; + Restart = "on-failure"; + RestartSec = 2; + Environment = [ + "QML_IMPORT_PATH=%h/.config/quickshell" + "QT_QPA_PLATFORM=wayland" + # Ensure we find icons + "XDG_CURRENT_DESKTOP=quickshell" + ]; + }; + Install = { + WantedBy = [ "graphical-session.target" ]; + }; + }; +} diff --git a/flakes/hyprland/home_manager/scripts.nix b/flakes/hyprland/home_manager/scripts.nix new file mode 100644 index 0000000..6c3d1c5 --- /dev/null +++ b/flakes/hyprland/home_manager/scripts.nix @@ -0,0 +1,10 @@ +{ pkgs, ... }: +{ + home.packages = with pkgs; [ + (writeShellScriptBin "toggle-airplane-mode" (builtins.readFile ./scripts/toggle-airplane-mode.sh)) + (writeShellScriptBin "toggle-power-profile" (builtins.readFile ./scripts/toggle-power-profile.sh)) + (writeShellScriptBin "wofi-wifi-menu" (builtins.readFile ./scripts/wofi-wifi-menu.sh)) + (writeShellScriptBin "wofi-bluetooth-menu" (builtins.readFile ./scripts/wofi-bluetooth-menu.sh)) + (writeShellScriptBin "confirm-action" (builtins.readFile ./scripts/confirm-action.sh)) + ]; +} diff --git a/flakes/hyprland/home_manager/scripts/confirm-action.sh b/flakes/hyprland/home_manager/scripts/confirm-action.sh new file mode 100755 index 0000000..5c30d11 --- /dev/null +++ b/flakes/hyprland/home_manager/scripts/confirm-action.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +COMMAND_TO_RUN="$1" +PROMPT_MESSAGE="$2" + +if [ -z "$PROMPT_MESSAGE" ]; then + PROMPT_MESSAGE="Are you sure?" +fi + +choice=$(echo -e "No\nYes" | wofi --dmenu --location center -p "$PROMPT_MESSAGE") + +if [ "$choice" == "Yes" ]; then + eval "$COMMAND_TO_RUN" +fi diff --git a/flakes/hyprland/home_manager/scripts/toggle-airplane-mode.sh b/flakes/hyprland/home_manager/scripts/toggle-airplane-mode.sh new file mode 100755 index 0000000..7a6636a --- /dev/null +++ b/flakes/hyprland/home_manager/scripts/toggle-airplane-mode.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +if [ "$(nmcli radio all)" = "enabled" ]; then + nmcli radio all off +else + nmcli radio all on +fi diff --git a/flakes/hyprland/home_manager/scripts/toggle-power-profile.sh b/flakes/hyprland/home_manager/scripts/toggle-power-profile.sh new file mode 100755 index 0000000..1d14395 --- /dev/null +++ b/flakes/hyprland/home_manager/scripts/toggle-power-profile.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +if [ "$(powerprofilesctl get)" = "performance" ]; then + powerprofilesctl set balanced +else + powerprofilesctl set performance +fi diff --git a/flakes/hyprland/home_manager/scripts/wofi-bluetooth-menu.sh b/flakes/hyprland/home_manager/scripts/wofi-bluetooth-menu.sh new file mode 100755 index 0000000..b7a05dc --- /dev/null +++ b/flakes/hyprland/home_manager/scripts/wofi-bluetooth-menu.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +devices=$(bluetoothctl devices | awk '{print $2, $3}') + +if [ -z "$devices" ]; then + options="󰂲 Power On\n󰂬 Scan for devices" +else + options="$devices\n󰂲 Power Off\n󰂬 Scan for devices" +fi + +chosen=$(echo -e "$options" | wofi --dmenu --location 3 --yoffset 40 --xoffset -20 -p "Bluetooth") + +case "$chosen" in + "󰂲 Power On") bluetoothctl power on;; + "󰂲 Power Off") bluetoothctl power off;; + "󰂬 Scan for devices") bluetoothctl scan on;; + *) + mac=$(echo "$chosen" | awk '{print $1}') + bluetoothctl connect "$mac" + ;; +esac diff --git a/flakes/hyprland/home_manager/scripts/wofi-wifi-menu.sh b/flakes/hyprland/home_manager/scripts/wofi-wifi-menu.sh new file mode 100755 index 0000000..6e4dbbe --- /dev/null +++ b/flakes/hyprland/home_manager/scripts/wofi-wifi-menu.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Get a list of available Wi-Fi networks +nets=$(nmcli --terse --fields SSID,SECURITY,BARS device wifi list | sed '/^--/d' | sed 's/\\:/__/g') + +# Get the current connection status +connected_ssid=$(nmcli -t -f active,ssid dev wifi | egrep '^yes' | cut -d: -f2) + +if [[ ! -z "$connected_ssid" ]]; then + toggle="󰖪 Toggle Wi-Fi Off" +else + toggle="󰖩 Toggle Wi-Fi On" +fi + +# Present the menu to the user +chosen_network=$(echo -e "$toggle\n$nets" | wofi --dmenu --location 3 --yoffset 40 --xoffset -20 -p "Wi-Fi Networks") + +# Perform an action based on the user's choice +if [ "$chosen_network" = "$toggle" ]; then + nmcli radio wifi $([ "$connected_ssid" = "" ] && echo "on" || echo "off") +elif [ ! -z "$chosen_network" ]; then + ssid=$(echo "$chosen_network" | sed 's/__/\\:/g' | awk -F' ' '{print $1}') + nmcli device wifi connect "$ssid" +fi diff --git a/flakes/hyprland/home_manager/swaylock.nix b/flakes/hyprland/home_manager/swaylock.nix new file mode 100644 index 0000000..06ebf13 --- /dev/null +++ b/flakes/hyprland/home_manager/swaylock.nix @@ -0,0 +1,17 @@ +{ + ... +}: +{ + programs.swaylock = { + enable = true; + settings = { + color = "#000000"; + indicator-caps-lock = true; + indicator-idle-visible = true; + indicator-radius = 100; + indicator-thickness = 10; + font = "JetBrainsMono Nerd Font Regular"; + font-size = 20; + }; + }; +} diff --git a/flakes/hyprland/home_manager/swaync.nix b/flakes/hyprland/home_manager/swaync.nix new file mode 100644 index 0000000..b26fa58 --- /dev/null +++ b/flakes/hyprland/home_manager/swaync.nix @@ -0,0 +1,251 @@ +{ + lib, + osConfig, + ... +}: +let + ccfg = import ../../../config.nix; + cfg_path = [ + ccfg.custom_config_key + "desktopEnvironment" + "hyprland" + "swaync" + ]; + cfg = lib.attrsets.getAttrFromPath cfg_path osConfig; +in +{ + config = lib.mkIf cfg.enable { + services.swaync = { + enable = true; + settings = { + ignore = [ + "com.spotify.Client" + ]; + + positionX = "right"; + positionY = "top"; + layer = "overlay"; + control-center-layer = "top"; + layer-shell = true; + cssPriority = "application"; + + control-center-margin-top = 0; + control-center-margin-bottom = 0; + control-center-margin-right = 0; + control-center-margin-left = 0; + + notification-2fa-action = true; + notification-inline-replies = false; + notification-icon-size = 64; + notification-body-image-height = 100; + notification-body-image-width = 200; + + timeout = 10; + timeout-low = 5; + timeout-critical = 0; + + control-center-width = 500; + control-center-height = 600; + notification-window-width = 500; + + keyboard-shortcuts = true; + image-visibility = "when-available"; + transition-time = 200; + hide-on-clear = false; + hide-on-action = true; + script-fail-notify = true; + + widgets = [ + "inhibitors" + "title" + "dnd" + "volume" + "backlight" + "mpris" + "buttons-grid#quick" + "notifications" + ]; + + # Widget configurations + widget-config = { + inhibitors = { + text = "Inhibitors"; + button-text = "Clear All"; + clear-all-button = true; + }; + title = { + text = "Notifications"; + clear-all-button = true; + button-text = "Clear All"; + }; + dnd.text = "Do Not Disturb"; + mpris = { + image-size = 96; + image-radius = 12; + }; + volume = { + label = "󰕾"; + show-per-app = true; + }; + backlight = { + label = "󰃟"; + device = "intel_backlight"; + }; + "buttons-grid#quick" = { + columns = 4; # adjust: 3/4/5 + icon-size = 20; # tweak to taste + actions = [ + # Power + { + label = "󰐥"; + tooltip = "Shutdown"; + command = "confirm-action 'systemctl poweroff' 'Shutdown?'"; + } + { + label = "󰜉"; + tooltip = "Reboot"; + command = "confirm-action 'systemctl reboot' 'Reboot?'"; + } + { + label = "󰍃"; + tooltip = "Logout"; + command = "confirm-action 'hyprctl dispatch exit' 'Logout?'"; + } + ]; + }; + }; + }; + + # Custom CSS for the control center + style = '' + .control-center { + background: #1a1b26; + border: 2px solid #7dcae4; + border-radius: 12px; + } + + .control-center-list { + background: transparent; + } + + .control-center .notification-row:focus, + .control-center .notification-row:hover { + opacity: 1; + background: #24283b; + } + + .notification { + border-radius: 8px; + margin: 6px 12px; + box-shadow: 0 0 0 1px rgba(125, 196, 228, 0.3), 0 1px 3px 1px rgba(0, 0, 0, 0.7), 0 2px 6px 2px rgba(0, 0, 0, 0.3); + padding: 0; + } + + /* Widget styling */ + .widget-title { + margin: 8px; + font-size: 1.5rem; + color: #c0caf5; + } + + .widget-dnd { + margin: 8px; + font-size: 1.1rem; + color: #c0caf5; + } + + .widget-dnd > switch { + font-size: initial; + border-radius: 8px; + background: #414868; + border: 1px solid #7dcae4; + } + + .widget-dnd > switch:checked { + background: #7dcae4; + } + + .widget-mpris { + color: #c0caf5; + background: #24283b; + padding: 8px; + margin: 8px; + border-radius: 8px; + } + + .widget-mpris-player { + padding: 8px; + margin: 8px; + } + + .widget-mpris-title { + font-weight: bold; + font-size: 1.25rem; + } + + .widget-mpris-subtitle { + font-size: 1.1rem; + color: #9ece6a; + } + + .widget-volume { + background: #24283b; + padding: 8px; + margin: 8px; + border-radius: 8px; + color: #c0caf5; + } + + .widget-backlight { + background: #24283b; + padding: 8px; + margin: 8px; + border-radius: 8px; + color: #c0caf5; + } + + .widget-menubar { + background: #24283b; + padding: 8px; + margin: 8px; + border-radius: 8px; + color: #c0caf5; + } + + .widget-menubar .menu-item button { + background: #1f2335; + color: #c0caf5; + border-radius: 8px; + padding: 6px 10px; + margin: 4px; + border: 1px solid #2e3440; + font-family: "JetBrainsMonoNL Nerd Font"; + } + + .widget-menubar .menu-item button:hover { + background: #414868; + border-color: #7dcae4; + } + + .topbar-buttons button { + border: none; + background: transparent; + color: #c0caf5; + font-size: 1.1rem; + border-radius: 8px; + margin: 0 4px; + padding: 8px; + } + + .topbar-buttons button:hover { + background: #414868; + } + + .topbar-buttons button:active { + background: #7dcae4; + color: #1a1b26; + } + ''; + }; + }; +} diff --git a/flakes/hyprland/home_manager/template.nix b/flakes/hyprland/home_manager/template.nix new file mode 100644 index 0000000..905d5e4 --- /dev/null +++ b/flakes/hyprland/home_manager/template.nix @@ -0,0 +1,18 @@ +{ + osConfig, + lib, + pkgs, + ... +}: +let + ccfg = import ../../../config.nix; + cfg_path = [ + ccfg.custom_config_key + "desktopEnvironment" + "hyprland" + ]; + cfg = lib.attrsets.getAttrFromPath cfg_path osConfig; +in +{ + +} diff --git a/flakes/hyprland/home_manager/theme.nix b/flakes/hyprland/home_manager/theme.nix new file mode 100644 index 0000000..c6045d0 --- /dev/null +++ b/flakes/hyprland/home_manager/theme.nix @@ -0,0 +1,32 @@ +{ + pkgs, + ... +}: +{ + home.pointerCursor = { + gtk.enable = true; + # x11.enable = true; + package = pkgs.bibata-cursors; + name = "Bibata-Modern-Classic"; + size = 16; + }; + # GTK theming + gtk = { + enable = true; + + theme = { + package = pkgs.flat-remix-gtk; + name = "Flat-Remix-GTK-Grey-Darkest"; + }; + + iconTheme = { + package = pkgs.adwaita-icon-theme; + name = "Adwaita"; + }; + + font = { + name = "Sans"; + size = 11; + }; + }; +} diff --git a/flakes/hyprland/home_manager/waybar.nix b/flakes/hyprland/home_manager/waybar.nix new file mode 100644 index 0000000..66f3349 --- /dev/null +++ b/flakes/hyprland/home_manager/waybar.nix @@ -0,0 +1,258 @@ +{ lib, osConfig, ... }: +let + ccfg = import ../../../config.nix; + cfg_path = [ + ccfg.custom_config_key + "desktopEnvironment" + "hyprland" + "waybar" + ]; + cfg = lib.attrsets.getAttrFromPath cfg_path osConfig; +in +{ + config = lib.mkIf cfg.enable { + + programs.waybar = { + enable = true; + systemd.enable = true; + settings = { + mainBar = { + layer = "top"; + position = "top"; + height = 28; + spacing = 6; + margin-top = 0; + margin-bottom = 0; + margin-left = 10; + margin-right = 10; + + modules-left = [ + "hyprland/workspaces" + ]; + modules-center = [ + "clock" + "temperature" + "cpu" + "memory" + "disk" + ]; + modules-right = [ + "battery" + "battery#bat2" + "pulseaudio" + "network" + "bluetooth" + "power-profiles-daemon" + "backlight" + "custom/notifications" + "tray" + "custom/power" + ]; + + "hyprland/workspaces" = { + format = "{icon}"; + format-icons = { + "1" = "一"; + "2" = "二"; + "3" = "三"; + "4" = "四"; + "5" = "五"; + "6" = "六"; + "7" = "七"; + "8" = "八"; + "9" = "九"; + "10" = "十"; + "11" = "十一"; + "12" = "十二"; + "13" = "十三"; + "14" = "十四"; + "15" = "十五"; + "16" = "十六"; + "17" = "十七"; + "18" = "十八"; + "19" = "十九"; + "20" = "二十"; + }; + disable-scroll = false; + }; + + # CENTER + clock = { + format = "{:%b %d, %H:%M}"; + tooltip-format = "{:%Y %B}\n{calendar}"; + }; + + temperature = { + thermal-zone = 2; + hwmon-path = "/sys/class/hwmon/hwmon2/temp1_input"; + critical-threshold = 80; + format-critical = "󰔏 {temperatureC}°C"; + format = "󰔏 {temperatureC}°C"; + }; + + cpu = { + format = "󰻠 {usage}%"; + tooltip = true; + on-click = "btop"; + }; + + memory = { + format = "󰍛 {}%"; + on-click = "btop"; + }; + + disk = { + interval = 30; + format = "󰋊 {percentage_used}%"; + path = "/"; + on-click = "btop"; + }; + + # RIGHT + "battery" = { + "states" = { + # "good"= 95; + "warning" = 30; + "critical" = 15; + }; + "format" = "{capacity}% {icon}"; + "format-full" = "{capacity}% {icon}"; + "format-charging" = "{capacity}% "; + "format-plugged" = "{capacity}% "; + "format-alt" = "{time} {icon}"; + # "format-good"= ""; // An empty format will hide the module + # "format-full"= ""; + "format-icons" = [ + "" + "" + "" + "" + "" + ]; + }; + "battery#bat2" = { + "bat" = "BAT2"; + }; + + pulseaudio = { + format = "{icon} {volume}%"; + format-bluetooth = "󰂰 {volume}%"; + format-bluetooth-muted = "󰂲 "; + format-muted = "󰖁 "; + format-source = "󰍬 {volume}%"; + format-source-muted = "󰍭 "; + format-icons = { + headphone = "󰋋"; + hands-free = "󰂑"; + headset = "󰂑"; + phone = "󰏲"; + portable = "󰦧"; + car = "󰄋"; + default = [ + "󰕿" + "󰖀" + "󰕾" + ]; + }; + scroll-step = 5; + on-click = "pavucontrol"; + on-click-right = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; + }; + + network = { + format-wifi = "󰤨 {essid} ({signalStrength}%)"; + format-ethernet = "󰈀 {ipaddr}/{cidr}"; + tooltip-format = "{ifname} via {gwaddr} "; + format-linked = "󰈀 {ifname} (No IP)"; + format-disconnected = "󰖪 Disconnected"; + # on-click = "wofi-wifi-menu"; + # on-click-right = "nmcli radio wifi toggle"; + }; + + bluetooth = { + format = "󰂯 {status}"; + format-connected = "󰂱 {device_alias}"; + format-connected-battery = "󰂱 {device_alias} {device_battery_percentage}%"; + tooltip-format = "{controller_alias}\t{controller_address}\n\n{num_connections} connected"; + tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}"; + tooltip-format-enumerate-connected = "{device_alias}\t{device_address}"; + tooltip-format-enumerate-connected-battery = "{device_alias}\t{device_address}\t{device_battery_percentage}%"; + # on-click = "wofi-bluetooth-menu"; + # on-click-right = "bluetoothctl power toggle"; + }; + + "power-profiles-daemon" = { + format = "{icon}"; + "tooltip-format" = "Power profile: {profile}\nDriver: {driver}"; + tooltip = true; + "format-icons" = { + default = ""; + performance = ""; + balanced = ""; + "power-saver" = ""; + }; + }; + + backlight = { + format = "{percent}% {icon}"; + "format-icons" = [ + "" + "" + "" + "" + "" + "" + "" + "" + "" + ]; + }; + + "custom/notifications" = { + format = "{icon} {}"; + format-icons = { + notification = ""; + none = ""; + dnd-notification = "󰂛"; + dnd-none = "󰂛"; + inhibited-notification = ""; + inhibited-none = ""; + dnd-inhibited-notification = "󰂛"; + dnd-inhibited-none = "󰂛"; + }; + return-type = "json"; + exec-if = "which swaync-client"; + exec = "swaync-client -swb"; + on-click = "swaync-client -t -sw"; + on-click-right = "swaync-client -d -sw"; + escape = true; + tooltip = false; + }; + + "sway/language" = { + format = "{}"; + }; + + "tray" = { + "spacing" = 10; + }; + + "custom/power" = { + format = "⏻ "; + tooltip = false; + menu = "on-click"; + "menu-file" = ./waybar/power_menu.xml; + "menu-actions" = { + shutdown = "shutdown 0"; + reboot = "reboot"; + logout = "loginctl terminate-session $(loginctl list-sessions | grep seat0 | awk '{print $1}')"; + }; + }; + + }; + }; + + style = builtins.readFile ./waybar/waybar.css; + }; + }; +} diff --git a/flakes/hyprland/home_manager/waybar/power_menu.xml b/flakes/hyprland/home_manager/waybar/power_menu.xml new file mode 100644 index 0000000..a061b18 --- /dev/null +++ b/flakes/hyprland/home_manager/waybar/power_menu.xml @@ -0,0 +1,26 @@ + + + + + + Logout + + + + + + + + Reboot + + + + + + + + Shutdown + + + + diff --git a/flakes/hyprland/home_manager/waybar/waybar.css b/flakes/hyprland/home_manager/waybar/waybar.css new file mode 100644 index 0000000..6ed5a8c --- /dev/null +++ b/flakes/hyprland/home_manager/waybar/waybar.css @@ -0,0 +1,102 @@ +* { + /* `otf-font-awesome` is required to be installed for icons */ + font-family: "JetBrainsMonoNL Nerd Font", FontAwesome, Roboto, Helvetica, Arial, sans-serif; + font-size: 14px; + border: none; + border-radius: 0; + min-height: 0; + color: #f1f1f1; +} + +window#waybar { + background: transparent; +} + +#workspaces button.focused, +#workspaces button.active { + background-color: rgba(220, 220, 220, 0.2); +} + +#workspaces button.urgent { + background-color: rgba(214, 82, 82, 0.3); +} + +button, +#clock, +#battery, +#cpu, +#memory, +#disk, +#temperature, +#backlight, +#network, +#pulseaudio, +#wireplumber, +#custom-media, +#custom-notifications, +#custom-power, +#tray, +#mode, +#idle_inhibitor, +#scratchpad, +#power-profiles-daemon, +#bluetooth, +#language, +#mpd { + padding: 0 5px; + color: #f1f1f1; + background-color: rgba(220, 220, 220, 0.1); + border-radius: 6px; +} + + +button:hover, +#clock:hover, +#battery:hover, +#cpu:hover, +#memory:hover, +#disk:hover, +#temperature:hover, +#backlight:hover, +#network:hover, +#pulseaudio:hover, +#wireplumber:hover, +#custom-media:hover, +#custom-notifications:hover, +#tray:hover, +#mode:hover, +#idle_inhibitor:hover, +#scratchpad:hover, +#power-profiles-daemon:hover, +#bluetooth:hover, +#language:hover, +#mpd:hover { + color: #f1f1f1; + background-color: rgba(220, 220, 220, 0.2); + border-radius: 6px; +} + +#power-profiles-daemon { + padding-right: 15px; +} + +#power-profiles-daemon.performance { + color: #fff7d6; +} + +#power-profiles-daemon.balanced { + color: #d6efff; +} + +#power-profiles-daemon.power-saver { + color:#dcffd6; +} + +#tray>.passive { + -gtk-icon-effect: dim; +} + +#tray>.needs-attention { + -gtk-icon-effect: highlight; + background-color: #eb4d4b; +} diff --git a/flakes/hyprland/home_manager/wofi.nix b/flakes/hyprland/home_manager/wofi.nix new file mode 100644 index 0000000..f2df05b --- /dev/null +++ b/flakes/hyprland/home_manager/wofi.nix @@ -0,0 +1,26 @@ +{ + ... +}: +{ + programs.wofi = { + enable = true; + settings = { + width = 500; + height = 600; + location = "bottom"; + show = "drun"; + prompt = "..."; + filter_rate = 100; + allow_markup = true; + no_actions = true; + halign = "fill"; + orientation = "vertical"; + content_halign = "fill"; + insensitive = true; + allow_images = true; + image_size = 40; + gtk_dark = true; + }; + }; + +} diff --git a/flakes/secrets/flake.nix b/flakes/secrets/flake.nix new file mode 100644 index 0000000..a282f79 --- /dev/null +++ b/flakes/secrets/flake.nix @@ -0,0 +1,33 @@ +{ + inputs = { + ragenix.url = "github:yaxitech/ragenix"; + }; + + outputs = + { + ragenix, + ... + }: + { + nixosModules = { + default = + { + config, + lib, + pkgs, + ... + }: + { + imports = [ + ragenix.nixosModules.age + ./secrets + ]; + config = { + _module.args = { + inherit ragenix; + }; + }; + }; + }; + }; +} diff --git a/flakes/test b/flakes/test new file mode 100644 index 0000000..e69de29 diff --git a/hosts/lio/home_manager.nix b/hosts/lio/home_manager.nix new file mode 100644 index 0000000..f42762b --- /dev/null +++ b/hosts/lio/home_manager.nix @@ -0,0 +1,10 @@ +{ + config, + lib, + pkgs, + modulesPath, + ... +}: +{ + +}