diff --git a/configuration.nix b/configuration.nix index be8d4b9..3a9e4f7 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,180 +1,5 @@ { config, pkgs, ... }: -let - greetdApodDir = "/var/lib/greetd/apod"; - greetdApodCurrent = "${greetdApodDir}/current"; - swaySession = pkgs.writeTextDir "share/wayland-sessions/sway.desktop" '' - [Desktop Entry] - Name=Sway - Comment=An i3-compatible Wayland compositor - Exec=${config.programs.sway.package}/bin/sway - Type=Application - DesktopNames=sway - ''; - regreetPasswordPrompt = pkgs.regreet.overrideAttrs (oldAttrs: { - postPatch = (oldAttrs.postPatch or "") + '' - substituteInPlace src/gui/model.rs \ - --replace-fail $' } else {\n let username = if let Some(username) = self.get_current_username() {' \ - $' } else if self.sys_util.get_sessions().len() == 1 {\n let (session, sess_info) = self.sys_util.get_sessions().iter().next().expect("one session");\n info!("No session selected; using only available session: {session}");\n (Some(session.to_string()), Some(sess_info.clone()))\n } else {\n let username = if let Some(username) = self.get_current_username() {' - - substituteInPlace src/gui/component.rs \ - --replace-fail $' // Set the default behaviour of pressing the Return key to act like the login button.\n root.set_default_widget(Some(&widgets.ui.login_button));\n\n AsyncComponentParts { model, widgets }' \ - $' // Set the default behaviour of pressing the Return key to act like the login button.\n root.set_default_widget(Some(&widgets.ui.login_button));\n\n // Immediately start authentication so the password entry appears and receives focus.\n sender.input(Self::Input::Login {\n input: String::new(),\n info: UserSessInfo::extract(\n &widgets.ui.usernames_box,\n &widgets.ui.username_entry,\n &widgets.ui.sessions_box,\n &widgets.ui.session_entry,\n ),\n });\n\n AsyncComponentParts { model, widgets }' - ''; - }); - regreetState = pkgs.writeText "regreet-state.toml" '' - last_user = "jet" - - [user_to_last_sess] - jet = "Sway" - ''; - fetchGreetdApod = pkgs.writeShellApplication { - name = "greetd-apod-wallpaper"; - runtimeInputs = [ - pkgs.coreutils - pkgs.curl - pkgs.jq - ]; - text = '' - set -euo pipefail - - state_dir="${greetdApodDir}" - current_link="${greetdApodCurrent}" - user_current="/home/jet/.local/state/nasa-apod/current" - mkdir -p "$state_dir" - chmod 0755 "$state_dir" - - install_current() { - local source="$1" - local target="$2" - - if [ -s "$source" ]; then - cp --dereference --force "$source" "$target" - chmod 0644 "$target" - ln -sfn "$target" "$current_link" - fi - } - - if [ ! -e "$current_link" ] && [ -e "$user_current" ]; then - install_current "$user_current" "$state_dir/bootstrap" - fi - - read_api_key_file() { - local key_file="$1" - - if [ -r "$key_file" ]; then - while IFS= read -r line; do - case "$line" in - NASA_API_KEY=*) - api_key="''${line#NASA_API_KEY=}" - ;; - esac - done < "$key_file" - fi - } - - api_key="''${NASA_API_KEY:-}" - if [ -z "$api_key" ]; then - read_api_key_file "''${NASA_API_KEY_FILE:-/home/jet/.config/nasa-api.env}" - fi - if [ -z "$api_key" ]; then - read_api_key_file /etc/nasa-api.env - fi - if [ -z "$api_key" ]; then - exit 0 - fi - - today="$(date +%F)" - for cached in "$state_dir/apod-$today".*; do - if [ -s "$cached" ]; then - ln -sfn "$cached" "$current_link" - exit 0 - fi - done - - api_curl_args=( - --fail - --silent - --show-error - --location - --connect-timeout 5 - --max-time 20 - ) - - image_curl_args=( - --fail - --silent - --show-error - --location - --retry 2 - --retry-delay 5 - --retry-max-time 120 - --connect-timeout 10 - --max-time 60 - ) - - api_request="$(mktemp)" - trap 'rm -f "$api_request"' EXIT - { - printf '%s\n' 'url = "https://api.nasa.gov/planetary/apod"' - printf '%s\n' 'get' - printf 'data-urlencode = "api_key=%s"\n' "$api_key" - printf '%s\n' 'data-urlencode = "thumbs=True"' - } > "$api_request" - chmod 0600 "$api_request" - - json="$(curl "''${api_curl_args[@]}" --config "$api_request" || true)" - if [ -z "$json" ]; then - exit 0 - fi - - media_type="$(printf '%s' "$json" | jq -r '.media_type // empty')" - case "$media_type" in - image) - image_url="$(printf '%s' "$json" | jq -r '.hdurl // .url // empty')" - ;; - video) - image_url="$(printf '%s' "$json" | jq -r '.thumbnail_url // empty')" - ;; - *) - exit 0 - ;; - esac - if [ -z "$image_url" ]; then - exit 0 - fi - - ext="''${image_url##*.}" - ext="''${ext%%\?*}" - case "$ext" in - jpg|jpeg|png|webp) ;; - *) ext="jpg" ;; - esac - - date_stamp="$(printf '%s' "$json" | jq -r '.date // empty')" - if [ -z "$date_stamp" ]; then - date_stamp="$(date +%F)" - fi - - target="$state_dir/apod-$date_stamp.$ext" - tmp="$target.tmp" - - if [ ! -s "$target" ]; then - if curl "''${image_curl_args[@]}" "$image_url" -o "$tmp" && [ -s "$tmp" ]; then - mv "$tmp" "$target" - chmod 0644 "$target" - else - rm -f "$tmp" - fi - fi - - if [ -e "$target" ]; then - ln -sfn "$target" "$current_link" - fi - ''; - }; -in - { boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.configurationLimit = 3; @@ -195,8 +20,6 @@ in }; }; }; - services.blueman.enable = true; - networking.networkmanager.enable = true; networking.networkmanager.settings = { connection = { @@ -317,7 +140,6 @@ in # Codex currently probes the conventional FHS bubblewrap path. systemd.tmpfiles.rules = [ "L+ /usr/bin/bwrap - - - - ${pkgs.bubblewrap}/bin/bwrap" - "d ${greetdApodDir} 0755 root root -" ]; # Set Ghostty as default terminal @@ -332,40 +154,39 @@ in virtualisation.docker.enable = true; - programs.sway = { - enable = true; - wrapperFeatures.gtk = true; - }; + services.displayManager.gdm.enable = true; + services.desktopManager.gnome.enable = true; + services.gnome.sushi.enable = true; - services.greetd = { - enable = true; - settings.default_session = { - command = "env GTK_USE_PORTAL=0 GDK_DEBUG=no-portals SESSION_DIRS=/run/current-system/sw/share/wayland-sessions XDG_DATA_DIRS=/run/current-system/sw/share ${pkgs.dbus}/bin/dbus-run-session ${pkgs.cage}/bin/cage -s -d -- ${config.programs.regreet.package}/bin/regreet"; - user = "greeter"; - }; - }; - - programs.regreet = { - enable = true; - package = regreetPasswordPrompt; - font = { - package = pkgs.atkinson-hyperlegible-next; - name = "Atkinson Hyperlegible Next"; - size = 16; - }; - settings = { - background = { - path = greetdApodCurrent; - fit = "Cover"; - }; - GTK.application_prefer_dark_theme = true; - appearance.greeting_msg = "Welcome back"; - widget.clock = { - format = "%a %b %d %I:%M %p"; - resolution = "1s"; - }; - }; - }; + # Keep GNOME's shell and file-manager integration while dropping apps replaced elsewhere. + environment.gnome.excludePackages = with pkgs; [ + baobab + decibels + epiphany + evince + geary + gnome-calculator + gnome-calendar + gnome-characters + gnome-clocks + gnome-connections + gnome-console + gnome-contacts + gnome-font-viewer + gnome-logs + gnome-maps + gnome-music + gnome-system-monitor + gnome-text-editor + gnome-tour + gnome-weather + papers + showtime + simple-scan + snapshot + totem + yelp + ]; services.accounts-daemon.enable = true; @@ -379,11 +200,6 @@ in }; }; - system.activationScripts.regreetDefaultSession.text = '' - ${pkgs.coreutils}/bin/install -D -m 0644 ${regreetState} /var/lib/regreet/state.toml - chown greeter:greeter /var/lib/regreet/state.toml - ''; - fonts = { packages = [ pkgs.atkinson-hyperlegible-next @@ -439,44 +255,10 @@ in }; }; - systemd.services.greetd-apod-wallpaper = { - description = "Fetch NASA APOD wallpaper for greetd"; - after = [ "network-online.target" ]; - wants = [ "network-online.target" ]; - restartIfChanged = false; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${fetchGreetdApod}/bin/greetd-apod-wallpaper"; - EnvironmentFile = "-${config.age.secrets.nasa-api-env.path}"; - TimeoutStartSec = "3min"; - }; - }; - - systemd.timers.greetd-apod-wallpaper = { - wantedBy = [ "timers.target" ]; - timerConfig = { - OnActiveSec = "2m"; - OnUnitActiveSec = "1h"; - Persistent = false; - Unit = "greetd-apod-wallpaper.service"; - }; - }; - - xdg.portal = { - enable = true; - wlr.enable = true; - config.common.default = [ - "wlr" - "gtk" - ]; - extraPortals = with pkgs; [ xdg-desktop-portal-gtk ]; - }; - programs.dconf.enable = true; services.gvfs.enable = true; services.udisks2.enable = true; security.polkit.enable = true; - security.pam.services.swaylock = { }; services.printing.enable = true; @@ -584,11 +366,9 @@ in docker docker-compose flatpak - swaySession wget nh ]; - environment.pathsToLink = [ "/share/wayland-sessions" ]; programs.steam.enable = true; programs.nix-index-database.comma.enable = true; diff --git a/home-modules/default.nix b/home-modules/default.nix index bd8bf83..1d3394b 100644 --- a/home-modules/default.nix +++ b/home-modules/default.nix @@ -10,7 +10,6 @@ ./terminal.nix ./browser.nix ./desktop.nix - ./sway.nix ./opencode.nix ]; } diff --git a/home-modules/desktop.nix b/home-modules/desktop.nix index a4ab9e5..cc038bf 100644 --- a/home-modules/desktop.nix +++ b/home-modules/desktop.nix @@ -1,4 +1,73 @@ -{ homeLib, ... }: +{ + config, + homeLib, + hostname, + osConfig ? null, + pkgs, + ... +}: + +let + apodSecretEnvironmentFile = + if + osConfig != null + && osConfig ? age + && osConfig.age ? secrets + && builtins.hasAttr "nasa-api-env" osConfig.age.secrets + then + "-${osConfig.age.secrets."nasa-api-env".path}" + else + "-%h/.config/nasa-api.env"; + chatDesktopId = if hostname == "framework-work" then "slack.desktop" else "vesktop.desktop"; + favoriteApps = [ + "zen-beta.desktop" + "com.mitchellh.ghostty.desktop" + chatDesktopId + "betterbird.desktop" + ] + ++ ( + if hostname == "framework-work" then + [ ] + else + [ + "signal.desktop" + "zulip.desktop" + ] + ); + autoMoveApplications = [ + "zen-beta.desktop:1" + "com.mitchellh.ghostty.desktop:2" + "${chatDesktopId}:3" + "betterbird.desktop:4" + ] + ++ ( + if hostname == "framework-work" then + [ ] + else + [ + "signal.desktop:5" + "zulip.desktop:6" + ] + ); + autostartEntries = [ + "${homeLib.zenStartup}/share/applications/zen-startup.desktop" + "${homeLib.ghosttyZellijStartup}/share/applications/ghostty-zellij-startup.desktop" + ] + ++ ( + if hostname == "framework-work" then + [ + "${pkgs.slack}/share/applications/slack.desktop" + "${homeLib.betterbirdStartup}/share/applications/betterbird-startup.desktop" + ] + else + [ + "${homeLib.vesktopStartup}/share/applications/vesktop-startup.desktop" + "${homeLib.betterbirdStartup}/share/applications/betterbird-startup.desktop" + "${homeLib.signalStartup}/share/applications/signal-startup.desktop" + "${homeLib.zulipStartup}/share/applications/zulip-startup.desktop" + ] + ); +in { dconf.settings = { @@ -10,9 +79,61 @@ cursor-theme = "Adwaita"; document-font-name = "Atkinson Hyperlegible Next 11"; enable-animations = false; + enable-hot-corners = false; font-name = "Atkinson Hyperlegible Next 11"; monospace-font-name = "CommitMono Nerd Font 11"; }; + "org/gnome/system/location" = { + enabled = true; + }; + "org/gnome/settings-daemon/plugins/power" = { + sleep-inactive-ac-type = "nothing"; + }; + "org/gnome/settings-daemon/plugins/media-keys" = { + screensaver = [ "l" ]; + }; + "org/gnome/desktop/peripherals/touchpad" = { + disable-while-typing = false; + natural-scroll = true; + tap-to-click = true; + }; + "org/gnome/mutter" = { + center-new-windows = true; + dynamic-workspaces = false; + edge-tiling = true; + workspaces-only-on-primary = true; + }; + "org/gnome/desktop/wm/preferences" = { + focus-mode = "click"; + num-workspaces = 6; + }; + "org/gnome/shell" = { + disable-user-extensions = false; + enabled-extensions = [ + "hidetopbar@mathieu.bidon.ca" + "wifiqrcode@glerro.pm.me" + "system-monitor-next@paradoxxx.zero.gmail.com" + "clipboard-indicator@tudmotu.com" + "emoji-copy@felipeftn" + "tailscale@joaophi.github.com" + "auto-move-windows@gnome-shell-extensions.gcampax.github.com" + "appindicatorsupport@rgcjonas.gmail.com" + "gnome-shell-extension-maximized-by-default@stiggimy.github.com" + "no-titlebar-when-maximized@alec.ninja" + ]; + favorite-apps = favoriteApps; + }; + "org/gnome/shell/extensions/auto-move-windows" = { + application-list = autoMoveApplications; + }; + "org/gnome/shell/keybindings" = { + switch-to-application-1 = [ "1" ]; + switch-to-application-2 = [ "2" ]; + switch-to-application-3 = [ "3" ]; + switch-to-application-4 = [ "4" ]; + switch-to-application-5 = [ "5" ]; + switch-to-application-6 = [ "6" ]; + }; "org/gtk/gtk4/settings/file-chooser" = { show-hidden = true; }; @@ -66,6 +187,37 @@ }; }; + xdg.autostart = { + enable = true; + entries = autostartEntries; + }; + + systemd.user.services.nasa-apod-wallpaper = { + Unit = { + Description = "Fetch NASA APOD wallpaper"; + After = [ "graphical-session.target" ]; + PartOf = [ "graphical-session.target" ]; + X-RestartIfChanged = false; + }; + Service = { + Type = "oneshot"; + ExecStart = "${homeLib.nasaApodWallpaper}/bin/nasa-apod-wallpaper"; + EnvironmentFile = apodSecretEnvironmentFile; + TimeoutStartSec = "3min"; + }; + }; + + systemd.user.timers.nasa-apod-wallpaper = { + Unit.Description = "Refresh NASA APOD wallpaper regularly"; + Timer = { + OnActiveSec = "2m"; + OnUnitActiveSec = "1h"; + Persistent = false; + Unit = "nasa-apod-wallpaper.service"; + }; + Install.WantedBy = [ "timers.target" ]; + }; + xdg.mimeApps = { enable = true; defaultApplications = { diff --git a/home-modules/lib.nix b/home-modules/lib.nix index a7d5738..a4ef031 100644 --- a/home-modules/lib.nix +++ b/home-modules/lib.nix @@ -145,8 +145,8 @@ let runtimeInputs = [ pkgs.coreutils pkgs.curl + pkgs.glib pkgs.jq - pkgs.sway ]; text = '' set -euo pipefail @@ -201,8 +201,10 @@ let set_wallpaper() { local target="$1" - if [ -n "''${SWAYSOCK:-}" ] && [ -n "''${WAYLAND_DISPLAY:-}" ]; then - swaymsg output "*" bg "$target" fill >/dev/null + if [ -n "''${DBUS_SESSION_BUS_ADDRESS:-}" ]; then + gsettings set org.gnome.desktop.background picture-uri "file://$target" + gsettings set org.gnome.desktop.background picture-uri-dark "file://$target" + gsettings set org.gnome.desktop.background picture-options 'zoom' fi } diff --git a/home-modules/packages.nix b/home-modules/packages.nix index ec813b7..3d62109 100644 --- a/home-modules/packages.nix +++ b/home-modules/packages.nix @@ -61,25 +61,23 @@ linphone lmstudio homeLib.betterbird - blueman brightnessctl - cliphist - fuzzel - grim - mako nautilus - networkmanagerapplet - nwg-displays playerctl - polkit_gnome - slurp - swaybg - swayidle - swaylock - waybar wl-clipboard xdg-utils + gnomeExtensions.appindicator + gnomeExtensions.auto-move-windows + gnomeExtensions.clipboard-indicator + gnomeExtensions.emoji-copy + gnomeExtensions.hide-top-bar + gnomeExtensions.maximized-by-default-actually-reborn + gnomeExtensions.no-titlebar-when-maximized + gnomeExtensions.system-monitor-next + gnomeExtensions.tailscale-qs + gnomeExtensions.wifi-qrcode + nerd-fonts.commit-mono ]; }