Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e14c57dc1
|
||
|
|
a2d7391bbb
|
||
|
|
ffff15055b
|
||
|
|
d346937782
|
||
|
|
fedb2b87df
|
||
|
|
57f2689be5
|
||
|
|
c430976454
|
||
|
|
fb6d677bcf | ||
|
|
5a4745f637 | ||
|
|
233ad01bee |
@@ -13,6 +13,7 @@
|
||||
../../modules/nixos/hyprland
|
||||
../../modules/nixos/steam
|
||||
../../modules/nixos/awsvpn
|
||||
../../modules/nixos/keyd
|
||||
../../modules/nixos/tailscale
|
||||
../../modules/nixos/wake-on-lan
|
||||
../../modules/nixos/hermes
|
||||
@@ -72,6 +73,19 @@
|
||||
"x-systemd.device-timeout=10s"
|
||||
];
|
||||
};
|
||||
|
||||
"/mnt/obsidian" = {
|
||||
device = "//100.90.248.13/ObsidianVault";
|
||||
fsType = "cifs";
|
||||
options = [
|
||||
"credentials=/etc/samba/obsidian-credentials"
|
||||
"uid=1000"
|
||||
"gid=100"
|
||||
"noperm"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Networking
|
||||
@@ -120,6 +134,10 @@
|
||||
tailscale.enable = true;
|
||||
wake-on-lan.enable = true;
|
||||
hermes.enable = true;
|
||||
keyd = {
|
||||
enable = false;
|
||||
internalIds = [ "1ea7:0907" ];
|
||||
};
|
||||
};
|
||||
|
||||
##------------------------------
|
||||
@@ -166,17 +184,6 @@
|
||||
jack.enable = true; # only if you use jack apps (reaper, etc.)
|
||||
wireplumber.enable = true;
|
||||
};
|
||||
keyd = {
|
||||
enable = true;
|
||||
keyboards.default = {
|
||||
ids = [ "*" ]; # or specific vendor:product ids
|
||||
settings = {
|
||||
main = {
|
||||
capslock = "overload(control, esc)"; # translate your default.conf here
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
postgresql.enable = true;
|
||||
syncthing = {
|
||||
enable = true;
|
||||
@@ -218,21 +225,25 @@
|
||||
|
||||
# OpenSSH: reachable through the trusted Tailscale interface, but not opened
|
||||
# broadly on every network interface by the firewall.
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
KbdInteractiveAuthentication = false;
|
||||
PermitRootLogin = "no";
|
||||
AllowUsers = [ "jpporta" ];
|
||||
services = {
|
||||
openssh = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
KbdInteractiveAuthentication = false;
|
||||
PermitRootLogin = "no";
|
||||
AllowUsers = [ "jpporta" ];
|
||||
};
|
||||
};
|
||||
|
||||
gnome.gnome-keyring.enable = true;
|
||||
};
|
||||
programs.mosh = {
|
||||
enable = true;
|
||||
openFirewall = false;
|
||||
};
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
system.stateVersion = "26.05";
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
../../modules/home-manager/power-profiles
|
||||
../../modules/home-manager/ntfy-notify
|
||||
../../modules/home-manager/pinentry
|
||||
../../modules/home-manager/swaync
|
||||
../../modules/home-manager/bitwarden-cli
|
||||
|
||||
inputs.zen-browser.homeModules.beta
|
||||
];
|
||||
@@ -94,7 +96,7 @@
|
||||
openspec.enable = true;
|
||||
power-profiles.enable = true;
|
||||
ntfy-notify.enable = true;
|
||||
|
||||
bitwarden.enable = true;
|
||||
};
|
||||
home.packages =
|
||||
let
|
||||
@@ -150,10 +152,9 @@
|
||||
direnv = {
|
||||
enable = true;
|
||||
nix-direnv.enable = true;
|
||||
silent = true;
|
||||
};
|
||||
};
|
||||
|
||||
custom.pinentry.enable = true;
|
||||
|
||||
services.swaync.enable = true;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
enable = true;
|
||||
settings = {
|
||||
font = {
|
||||
size = 10.3;
|
||||
size = 12;
|
||||
normal = {
|
||||
family = "BerkeleyMono Nerd Font Mono";
|
||||
style = "Regular";
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
||||
options.custom = {
|
||||
bitwarden.enable = lib.mkEnableOption "enable bitwarden - CLI password manager";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.custom.bitwarden.enable {
|
||||
programs.rbw = {
|
||||
enable = true;
|
||||
settings = {
|
||||
email = "me@joaoporta.com";
|
||||
lock_timeout = 7200;
|
||||
pinentry = pkgs.pinentry-gnome3;
|
||||
base_url = "https://pass.joaoporta.com";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -17,6 +17,9 @@
|
||||
};
|
||||
|
||||
config = lib.mkIf config.custom.jpporta-calendars.enable {
|
||||
home.packages = with pkgs; [
|
||||
seahorse
|
||||
];
|
||||
programs = {
|
||||
vdirsyncer.enable = true;
|
||||
|
||||
|
||||
@@ -38,6 +38,12 @@ return {
|
||||
desc = "[O]bsidian [T]emplate",
|
||||
mode = "n",
|
||||
},
|
||||
{
|
||||
"<leader>ow",
|
||||
":ObsidianWorkspace<CR>",
|
||||
desc = "[O]bsidian [W]orkspace",
|
||||
mode = "n",
|
||||
},
|
||||
},
|
||||
opts = {
|
||||
|
||||
@@ -122,12 +128,16 @@ return {
|
||||
name = "personal",
|
||||
path = "~/docs/personal",
|
||||
},
|
||||
{
|
||||
name = "hermes",
|
||||
path = "/mnt/documents/journal",
|
||||
},
|
||||
},
|
||||
daily_notes = {
|
||||
folder = "journal",
|
||||
folder = "Journal",
|
||||
date_format = "%Y-%m-%d",
|
||||
default_tags = { "journal" },
|
||||
template = "journal"
|
||||
template = "Daily Note",
|
||||
},
|
||||
completion = {
|
||||
nvim_cmp = true,
|
||||
@@ -135,9 +145,30 @@ return {
|
||||
},
|
||||
|
||||
templates = {
|
||||
subdir = "templates",
|
||||
subdir = "Templates",
|
||||
date_format = "%Y-%m-%d",
|
||||
time_format = "%H:%M",
|
||||
substitutions = {
|
||||
week = function()
|
||||
return os.date("%W", os.time())
|
||||
end,
|
||||
day = function()
|
||||
local d = os.date("%w", os.time())
|
||||
local r = {
|
||||
["0"] = "Sunday",
|
||||
["1"] = "Monday",
|
||||
["2"] = "Tuesday",
|
||||
["3"] = "Wednesday",
|
||||
["4"] = "Thursday",
|
||||
["5"] = "Friday",
|
||||
["6"] = "Saturday",
|
||||
}
|
||||
return r[d]
|
||||
end,
|
||||
full_date = function()
|
||||
return os.date("%A, %B %d, %Y", os.time())
|
||||
end,
|
||||
},
|
||||
},
|
||||
picker = {
|
||||
name = "telescope.nvim",
|
||||
|
||||
@@ -2,6 +2,14 @@ return {
|
||||
"michaelrommel/nvim-silicon",
|
||||
lazy = true,
|
||||
cmd = "Silicon",
|
||||
keys = {
|
||||
{
|
||||
"<leader>s",
|
||||
"<cmd>Silicon<CR>",
|
||||
desc = "[C]ode [S]elfie",
|
||||
mode = "v",
|
||||
},
|
||||
},
|
||||
config = function()
|
||||
local get_visual = function()
|
||||
local curpos = vim.fn.getcurpos()
|
||||
@@ -10,21 +18,27 @@ return {
|
||||
|
||||
if one.row == two.row then
|
||||
if one.col > two.col then
|
||||
local tmp = one
|
||||
one = two
|
||||
two = tmp
|
||||
one, two = two, one
|
||||
end
|
||||
elseif one.row > two.row then
|
||||
local tmp = one
|
||||
one = two
|
||||
two = tmp
|
||||
one, two = two, one
|
||||
end
|
||||
|
||||
two.col = two.col + 1
|
||||
return one.row
|
||||
end
|
||||
|
||||
require("nvim-silicon").setup({
|
||||
font = "JetBrainsMono Nerd Font=24",
|
||||
font = "Berkeley Mono Nerd Font Mono=24",
|
||||
theme = "gruvbox-dark",
|
||||
background = "#bdae93",
|
||||
pad_horiz = 100,
|
||||
pad_vert = 80,
|
||||
line_pad = 2,
|
||||
shadow_blur_radius = 24,
|
||||
shadow_offset_x = 10,
|
||||
shadow_offset_y = 10,
|
||||
shadow_color = "#1d2021",
|
||||
no_window_controls = true,
|
||||
no_line_number = false,
|
||||
line_offset = get_visual() + 1,
|
||||
@@ -36,6 +50,5 @@ return {
|
||||
return vim.bo.filetype
|
||||
end,
|
||||
})
|
||||
vim.keymap.set("v", "<leader>cs", "<cmd>'<,'>Silicon<CR>", { desc = "[C]ode [S]elfie" })
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -7,7 +7,12 @@
|
||||
|
||||
let
|
||||
pinentry-wrapper = pkgs.writeShellScriptBin "pinentry-wrapper" ''
|
||||
if [ -n "''${SSH_CONNECTION:-}" ] || [ -n "''${SSH_TTY:-}" ]; then
|
||||
# ponytail: gpg-agent's env is captured at boot (often on tty1), so SSH_* checks
|
||||
# from the agent miss SSH sessions. Fall back to curses when no usable display
|
||||
# is available, since rofi needs WAYLAND_DISPLAY/DISPLAY the agent may not have.
|
||||
if [ -n "''${SSH_CONNECTION:-}" ] \
|
||||
|| [ -n "''${SSH_TTY:-}" ] \
|
||||
|| [ -z "''${WAYLAND_DISPLAY:-}" ] && [ -z "''${DISPLAY:-}" ]; then
|
||||
exec ${pkgs.pinentry-curses}/bin/pinentry-curses "$@"
|
||||
else
|
||||
exec ${pkgs.pinentry-rofi}/bin/pinentry-rofi "$@"
|
||||
|
||||
@@ -1,55 +1,44 @@
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
background = "#282828"; # bg0 — main dark background
|
||||
background-alt = "#3c3836"; # bg1 — slightly lighter panels/buttons
|
||||
background-sec = "#1d2021"; # bg0_h — darker, for mpris/volume contrast
|
||||
text = "#ebdbb2"; # fg1 — main foreground
|
||||
selected = "#83a598"; # blue — accent for borders/active states
|
||||
urgent = "#fb4934"; # bright red — critical notifications
|
||||
hover = "#504945"; # bg2 — hover highlight
|
||||
in
|
||||
{
|
||||
options.custom = {
|
||||
swaync.enable = lib.mkEnableOption "enable swaync - color cat alternative";
|
||||
swaync.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable swaync - notification";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.custom.swaync.enable {
|
||||
services.swaync = {
|
||||
enable = true;
|
||||
settings = {
|
||||
positionX = "right";
|
||||
positionX = "left";
|
||||
positionY = "top";
|
||||
cssPriority = "user";
|
||||
|
||||
control-center-width = 380;
|
||||
control-center-height = 860;
|
||||
control-center-width = 360;
|
||||
control-center-height = 760;
|
||||
control-center-margin-top = 2;
|
||||
control-center-margin-bottom = 2;
|
||||
control-center-margin-right = 1;
|
||||
control-center-margin-left = 0;
|
||||
|
||||
notification-window-width = 400;
|
||||
notification-icon-size = 48;
|
||||
notification-body-image-height = 160;
|
||||
notification-body-image-width = 200;
|
||||
notification-window-width = 380;
|
||||
notification-icon-size = 40;
|
||||
notification-body-image-height = 120;
|
||||
notification-body-image-width = 160;
|
||||
|
||||
timeout = 4;
|
||||
timeout-low = 2;
|
||||
timeout-critical = 6;
|
||||
timeout = 6;
|
||||
timeout-low = 4;
|
||||
timeout-critical = 8;
|
||||
|
||||
fit-to-screen = false;
|
||||
keyboard-shortcuts = true;
|
||||
image-visibility = "when-available";
|
||||
transition-time = 200;
|
||||
transition-time = 250;
|
||||
hide-on-clear = true;
|
||||
hide-on-action = false;
|
||||
script-fail-notify = true;
|
||||
scripts = {
|
||||
example-script = {
|
||||
exec = "echo 'Do something...'";
|
||||
urgency = "Normal";
|
||||
};
|
||||
};
|
||||
notification-visibility = {
|
||||
example-name = {
|
||||
state = "muted";
|
||||
@@ -112,431 +101,13 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
style = ''
|
||||
* {
|
||||
color: ${text};
|
||||
background-color: ${background}
|
||||
all: unset;
|
||||
font-size: 12px;
|
||||
font-family: "BerkeleyMono Nerd Font Propo";
|
||||
transition: 200ms;
|
||||
}
|
||||
|
||||
.notification-row {
|
||||
outline: none;
|
||||
margin: 0;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.floating-notifications.background .notification-row .notification-background {
|
||||
background: alpha(${background}, 0.9);
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid ${selected};
|
||||
border-radius: 24px;
|
||||
margin: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification {
|
||||
padding: 6px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification.critical {
|
||||
border: 2px solid ${urgent};
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
.notification-content {
|
||||
margin: 14px;
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
> *:last-child
|
||||
> * {
|
||||
min-height: 3.4em;
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
> *:last-child
|
||||
> *
|
||||
.notification-action {
|
||||
border-radius: 8px;
|
||||
background-color: ${background-alt}};
|
||||
margin: 6px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
> *:last-child
|
||||
> *
|
||||
.notification-action:hover {
|
||||
background-color: ${hover};
|
||||
border: 1px solid ${selected};
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
> *:last-child
|
||||
> *
|
||||
.notification-action:active {
|
||||
background-color: ${selected};
|
||||
color: ${background};
|
||||
}
|
||||
|
||||
.image {
|
||||
margin: 10px 20px 10px 0px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
font-weight: 800;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.body {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.close-button {
|
||||
margin: 6px;
|
||||
padding: 2px;
|
||||
border-radius: 6px;
|
||||
background-color: ${background};
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.close-button:hover {
|
||||
background-color: ${selected};
|
||||
}
|
||||
|
||||
.floating-notifications.background
|
||||
.notification-row
|
||||
.notification-background
|
||||
.close-button:active {
|
||||
background-color: ${selected};
|
||||
color: ${background};
|
||||
}
|
||||
|
||||
.notification.critical progress {
|
||||
background-color: ${selected};
|
||||
}
|
||||
|
||||
.notification.low progress,
|
||||
.notification.normal progress {
|
||||
background-color: ${selected};
|
||||
}
|
||||
|
||||
* {
|
||||
color: ${text};
|
||||
|
||||
all: unset;
|
||||
font-size: 12px;
|
||||
font-family: "BerkeleyMono Nerd Font Propo";
|
||||
transition: 200ms;
|
||||
}
|
||||
|
||||
/* Avoid 'annoying' backgroud */
|
||||
.blank-window {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* CONTROL CENTER ------------------------------------------------------------------------ */
|
||||
|
||||
.control-center {
|
||||
background: alpha(${background}, 0.7);
|
||||
border-radius: 24px;
|
||||
border: 1px solid ${selected};
|
||||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.6);
|
||||
margin: 18px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* Notifications */
|
||||
.control-center .notification-row .notification-background,
|
||||
.control-center
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification.critical {
|
||||
background-color: ${background-alt};
|
||||
border-radius: 16px;
|
||||
margin: 4px 0px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.control-center
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification.critical {
|
||||
color: ${urgent};
|
||||
}
|
||||
|
||||
.control-center
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
.notification-content {
|
||||
margin: 6px;
|
||||
padding: 8px 6px 2px 2px;
|
||||
}
|
||||
|
||||
.control-center
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
> *:last-child
|
||||
> * {
|
||||
min-height: 3.4em;
|
||||
}
|
||||
|
||||
.control-center
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
> *:last-child
|
||||
> *
|
||||
.notification-action {
|
||||
background: alpha(${selected}, 0.6);
|
||||
color: ${text};
|
||||
border-radius: 12px;
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
.control-center
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
> *:last-child
|
||||
> *
|
||||
.notification-action:hover {
|
||||
background: ${selected};
|
||||
}
|
||||
|
||||
.control-center
|
||||
.notification-row
|
||||
.notification-background
|
||||
.notification
|
||||
> *:last-child
|
||||
> *
|
||||
.notification-action:active {
|
||||
background-color: ${selected};
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
|
||||
.control-center .notification-row .notification-background .close-button {
|
||||
background: transparent;
|
||||
border-radius: 6px;
|
||||
color: ${text};
|
||||
margin: 0px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.control-center .notification-row .notification-background .close-button:hover {
|
||||
background-color: ${selected};
|
||||
}
|
||||
|
||||
.control-center
|
||||
.notification-row
|
||||
.notification-background
|
||||
.close-button:active {
|
||||
background-color: ${selected};
|
||||
}
|
||||
|
||||
progressbar,
|
||||
progress,
|
||||
trough {
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
progressbar {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
/* Notifications expanded-group */
|
||||
|
||||
.notification-group {
|
||||
margin: 2px 8px 2px 8px;
|
||||
}
|
||||
.notification-group-headers {
|
||||
font-weight: bold;
|
||||
font-size: 1.25rem;
|
||||
color: ${text};
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.notification-group-icon {
|
||||
color: ${text};
|
||||
}
|
||||
|
||||
.notification-group-collapse-button,
|
||||
.notification-group-close-all-button {
|
||||
background: transparent;
|
||||
color: ${text};
|
||||
margin: 4px;
|
||||
border-radius: 6px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.notification-group-collapse-button:hover,
|
||||
.notification-group-close-all-button:hover {
|
||||
background: ${hover};
|
||||
}
|
||||
|
||||
/* WIDGETS --------------------------------------------------------------------------- */
|
||||
|
||||
/* Notification clear button */
|
||||
.widget-title {
|
||||
font-size: 1.2em;
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
.widget-title button {
|
||||
background: ${background-alt};
|
||||
border-radius: 6px;
|
||||
padding: 4px 16px;
|
||||
}
|
||||
|
||||
.widget-title button:hover {
|
||||
background-color: ${hover};
|
||||
}
|
||||
|
||||
.widget-title button:active {
|
||||
background-color: ${selected};
|
||||
}
|
||||
|
||||
/* Do not disturb */
|
||||
.widget-dnd {
|
||||
margin: 6px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.widget-dnd > switch {
|
||||
background: ${background-alt};
|
||||
font-size: initial;
|
||||
border-radius: 8px;
|
||||
box-shadow: none;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.widget-dnd > switch:hover {
|
||||
background: ${hover};
|
||||
}
|
||||
|
||||
.widget-dnd > switch:checked {
|
||||
background: ${selected};
|
||||
}
|
||||
|
||||
.widget-dnd > switch:checked:hover {
|
||||
background: ${hover};
|
||||
}
|
||||
|
||||
.widget-dnd > switch slider {
|
||||
background: ${text};
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* Buttons menu */
|
||||
.widget-buttons-grid {
|
||||
font-size: x-large;
|
||||
padding: 6px 2px;
|
||||
margin: 6px;
|
||||
border-radius: 12px;
|
||||
background: ${background-alt};
|
||||
}
|
||||
|
||||
.widget-buttons-grid > flowbox > flowboxchild > button {
|
||||
margin: 4px 10px;
|
||||
padding: 6px 12px;
|
||||
background: transparent;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.widget-buttons-grid > flowbox > flowboxchild > button:hover {
|
||||
background: ${hover};
|
||||
}
|
||||
|
||||
/* Music player */
|
||||
.widget-mpris {
|
||||
background: ${background-alt};
|
||||
border-radius: 16px;
|
||||
color: ${text};
|
||||
margin: 20px 6px;
|
||||
}
|
||||
|
||||
/* NOTE: Background need *opacity 1* otherwise will turn into the album art blurred */
|
||||
.widget-mpris-player {
|
||||
background-color: ${background-sec};
|
||||
border-radius: 22px;
|
||||
padding: 6px 14px;
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
.widget-mpris > box > button {
|
||||
color: ${text};
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.widget-mpris button {
|
||||
color: alpha(${text}, 0.6);
|
||||
}
|
||||
|
||||
.widget-mpris button:hover {
|
||||
color: ${text};
|
||||
}
|
||||
|
||||
.widget-mpris-album-art {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.widget-mpris-title {
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.widget-mpris-subtitle {
|
||||
font-weight: 500;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
picture.mpris-background {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Volume */
|
||||
.widget-volume {
|
||||
background: ${background-sec};
|
||||
color: ${background};
|
||||
padding: 4px;
|
||||
margin: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
xdg.configFile."swaync/style.css".source =
|
||||
config.lib.file.mkOutOfStoreSymlink
|
||||
"${config.home.homeDirectory}/.config/colorschemes/.active/swaync/style.css";
|
||||
xdg.configFile."swaync/colors.css".source =
|
||||
config.lib.file.mkOutOfStoreSymlink
|
||||
"${config.home.homeDirectory}/.config/colorschemes/.active/swaync/colors.css";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
oh-my-zsh = {
|
||||
enable = true;
|
||||
plugins = [ "git" "jj" ];
|
||||
plugins = [ "git" "jj" "rbw" ];
|
||||
theme = "";
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.custom.keyd;
|
||||
defaultRemap = {
|
||||
main = {
|
||||
capslock = "overload(control, esc)";
|
||||
};
|
||||
};
|
||||
defaultNoop = {
|
||||
main = { };
|
||||
};
|
||||
in
|
||||
{
|
||||
options.custom.keyd = {
|
||||
enable = lib.mkEnableOption "keyd (system-wide key remapping daemon)";
|
||||
|
||||
# Vendor:product IDs that get the capslock overload. See `keyd monitor`.
|
||||
internalIds = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ "1ea7:0907" ];
|
||||
example = [ "1ea7:0907" ];
|
||||
description = "Device IDs to apply the capslock overload to (matched against keyd's id list).";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.keyd = {
|
||||
enable = true;
|
||||
keyboards = {
|
||||
internal = {
|
||||
ids = cfg.internalIds;
|
||||
settings = defaultRemap;
|
||||
};
|
||||
default = {
|
||||
ids = [ "*" ];
|
||||
settings = defaultNoop;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-23
|
||||
@@ -0,0 +1,144 @@
|
||||
## Context
|
||||
|
||||
The user's setup is Hyprland on `jpporta-nixos` with swaync as the notification daemon. The current swaync configuration is split into two parts:
|
||||
|
||||
1. **`modules/home-manager/swaync/default.nix`** — the only place where swaync is configured. It inlines a ~400-line `style.css` string with hardcoded gruvbox colors (`#282828`, `#ebdbb2`, `#83a598`, `#fb4934`, `#504945`, `#fabd2f`) and a flat, square-ish layout. The settings block sets `positionX = "right"`, `positionY = "top"`, and a 360px-wide notification column with no corner radius beyond 14px.
|
||||
|
||||
2. **`modules/home-manager/hyprland/default.nix`** (lines 107–116) — already adds blur layers for `swaync-notification-window` and `swaync-control-center`, so the current design *intends* to be glassy but the CSS doesn't lean into it (no `alpha()`, low border-radius, no urgency-based color).
|
||||
|
||||
The user wants:
|
||||
|
||||
- A new "Groovebox" theme: dark, colorful, glassy.
|
||||
- iOS-style notification cards: rounded, icon left, title + truncated body right, timestamp in small caps top-right, urgency-coded title color + border accent.
|
||||
- Notification tray (the persistent control center) in the same dark glassy palette.
|
||||
- Notifications pop from the **bottom-left** instead of top-right.
|
||||
- A small `ponytail:` mindset: shipment is one new theme (`groovebox`) wired through the new layout, not 11 themes. Other themes get ported later.
|
||||
|
||||
The archived `2026-07-13-theme-switch` change designed the layout (`~/.config/colorschemes/<theme>/<app>/` + `.active` symlink + out-of-store symlinks from the Nix module) but was never implemented for swaync. This change ships the layout for swaync, with Groovebox as the first concrete theme so the user can see the result immediately.
|
||||
|
||||
Constraints:
|
||||
|
||||
- Nix home-manager on NixOS — the live reload path is `swaync-client --reload-css`, not a rebuild. The module must not bake colors.
|
||||
- The active theme directory is expected to be reachable via `~/.config/colorschemes/.active` (a symlink set by the future `theme-switch` script). Since that script doesn't exist yet, this change places `groovebox` at `~/.config/colorschemes/groovebox/` and the Nix module points at `.active` — first-time setup also requires `ln -sfn ~/.config/colorschemes/groovebox ~/.config/colorschemes/.active` (documented in the change notes).
|
||||
- The `~/.config/colorschemes/<theme>/` directory is currently empty. There is no `theme-switch` script yet. This change ships the dotfiles for one theme and expects the user (or a follow-up change) to wire `.active`.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- iOS-style notification cards: large border-radius (16–20px), transparent dark background with alpha + blur, horizontal layout (icon left, summary + body right), small-caps timestamp in the top-right corner.
|
||||
- Urgency-colored title and border: `low` = cyan, `normal` = white, `critical` = red. Applies in both the floating notification and the control center.
|
||||
- Control center (notification tray) in the same glassy dark palette, larger border-radius (24px), transparent background, bottom-left position.
|
||||
- Notifications pop from the bottom-left (`positionX = "left"`, `positionY = "bottom"`).
|
||||
- Swaync config + stylesheet live in `~/.config/colorschemes/groovebox/swaync/` as dotfiles, not in the Nix store. The Nix module is a thin wrapper that `xdg.configFile`s out-of-store symlinks.
|
||||
- `swaync-client --reload-css` continues to be the live-reload path; no rebuild required for tweaks.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- The `theme-switch` script itself, the `theme-picker`, the rofi integration, the boot-time `theme-apply.service`, the wallpaper hook. Those are the next change.
|
||||
- Porting the existing 14 themes (`gruvbox-dark`, `catppuccin-mocha-dark`, etc.) into the new layout. Just `groovebox` ships here.
|
||||
- gsettings / darkman integration changes.
|
||||
- Hyprland blur rules: the existing `swaync-notification-window` + `swaync-control-center` blur rules already target the right namespaces; they continue to work.
|
||||
- Changing the `font-family` ("BerkeleyMono Nerd Font Propo") or base font size — those stay.
|
||||
- New external dependencies. No new packages.
|
||||
- The CSS `all: unset` reset on `*` is kept from the current style (it works fine with swaync's GTK widgets and avoids inherited GTK theme leaks).
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1. Two-file split: `style.css` (layout) + `colors.css` (palette)
|
||||
|
||||
The current Nix inline `style.css` and the thin `colors.css` from the theme-switch seeds get separate files. **Why:** colors are swapped per theme; layout is shared across all future themes. Other future themes can `cp groovebox/style.css` and just rewrite `colors.css`. **Alternative considered:** one file, with the colors inlined as CSS variables — fine, but the seeds archive already used a two-file split, so this stays consistent with the established convention.
|
||||
|
||||
### D2. Layout values live in `style.css`, palette lives in `colors.css`
|
||||
|
||||
`style.css` references palette via CSS custom properties: `--accent-critical`, `--accent-normal`, `--accent-low`, `--bg`, `--bg-alt`, `--text`, `--hover`, `--border`. `colors.css` defines them. **Why:** keeps the layout file theme-agnostic so other themes can reuse it. **Alternative:** put color literals in `style.css` — tied to one theme, defeats the point.
|
||||
|
||||
### D3. Out-of-store symlink for both files (the archived theme-switch pattern)
|
||||
|
||||
`xdg.configFile."swaync/style.css".source = config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/.config/colorschemes/.active/swaync/style.css";` and the same for `colors.css`. **Why:** the user's home dir is the source of truth. The Nix store never has the colors, so live edits + `swaync-client --reload-css` work without rebuild. **Alternative:** `text = builtins.readFile ...` — same effect for static configs, but breaks the moment the user edits the file: home-manager would silently overwrite on the next activation. The symlink is correct.
|
||||
|
||||
### D4. Active theme pointer is the user's responsibility (for this change)
|
||||
|
||||
The Nix module points at `~/.config/colorschemes/.active/swaync/`. If `.active` is missing, swaync ends up with a broken symlink and hyprland's swaync exec (`hl.exec_cmd("swaync")`) still starts the daemon, but the CSS fails to load. Two options considered:
|
||||
|
||||
- **Fallback: ship a default symlink in the Nix module** (`xdg.configFile."swaync/style.css".source = ... "${current}/style.css"` with `current = "groovebox"` if `.active` is missing). Cleaner first-run UX, but adds a Nix string that says "groovebox" — exactly the kind of hardcoding this change is trying to *remove*. **Rejected.**
|
||||
- **Documented one-liner on first install.** First-run setup runs `mkdir -p ~/.config/colorschemes && ln -sfn ~/.config/colorschemes/groovebox ~/.config/colorschemes/.active && swaync-client --reload-css`. This is fine because it's a one-time setup, and the same command is what `theme-switch` will eventually own. **Chosen.**
|
||||
|
||||
The change notes in `tasks.md` will spell out the first-run command.
|
||||
|
||||
### D5. Urgency → color via class selectors, not via inline `style=`
|
||||
|
||||
Swaync adds CSS classes `.low`, `.normal`, `.critical` on the `.notification` element. The CSS reads:
|
||||
|
||||
```css
|
||||
.notification.low .summary { color: var(--accent-low); }
|
||||
.notification.critical .summary { color: var(--accent-critical); }
|
||||
.notification.critical .notification-background { border-color: var(--accent-critical); }
|
||||
```
|
||||
|
||||
**Why:** swaync owns the class assignment; CSS owns the color. Theme swaps via `colors.css` alone. **Alternative considered:** inline `style` (e.g. `style="border-color: ..."`) — not supported by swaync's markup on the notification wrapper. Classes are the right path.
|
||||
|
||||
### D6. Timestamp displayed via the `.time` label, top-right
|
||||
|
||||
Swaync renders a `.time` label inside the notification header by default. The CSS positions it in the top-right corner of the notification card, small caps, dimmed (`color: alpha(var(--text), 0.55)`). **Why:** matches iOS, and the existing `widget-config.label.max-lines = 1` already constrains the body width so it doesn't compete with the timestamp.
|
||||
|
||||
### D7. Control center border-radius 24px; notification cards 16px
|
||||
|
||||
iOS uses a large radius on the full tray and a slightly smaller radius on individual cards. 16px gives a "tile" feel; 24px on the tray gives a "floating surface" feel. **Why:** matches iOS reference aesthetics. **Alternative:** uniform 16px — looks flat and grid-like, not iOS.
|
||||
|
||||
### D8. `transition-time` bumped to 250ms; `transition` CSS line kept
|
||||
|
||||
Swaync's `transition-time` setting controls the slide-in animation. iOS-style feels good at 200–300ms. We bump to 250ms. The existing CSS `transition: 200ms` inside `*` is a no-op (swaync uses transitions on actual property changes, not on `all`). We keep it for parity.
|
||||
|
||||
### D9. Notification close button + timestamp share the top-right corner
|
||||
|
||||
The current CSS puts the close button at the top-right. The new layout puts the close button to the **right of the timestamp** (still top-right, but the timestamp is the inner-most element). iOS shows the app icon on the trailing edge of the header; we use a close `×` button instead, since swaync doesn't auto-inject a close for floating notifications.
|
||||
|
||||
### D10. Color palette: invented Groovebox palette
|
||||
|
||||
| Token | Hex | Role |
|
||||
|---|---|---|
|
||||
| `--bg` | `#14171c` | deepest background |
|
||||
| `--bg-alt` | `#1a1d24` | notification card / widget tile |
|
||||
| `--bg-glass` | `rgba(20, 23, 28, 0.72)` | card body with alpha |
|
||||
| `--text` | `#e6e6e6` | main foreground |
|
||||
| `--text-dim` | `rgba(230, 230, 230, 0.55)` | timestamp, secondary |
|
||||
| `--hover` | `#25282f` | hover highlight |
|
||||
| `--accent-low` | `#5cd6ff` | low urgency (cool, calm) |
|
||||
| `--accent-normal` | `#e6e6e6` | normal urgency (white-ish, matches iOS) |
|
||||
| `--accent-critical` | `#ff5e7a` | critical urgency (loud red) |
|
||||
|
||||
**Why:** dark base, vibrant accents, follows the "colorful but dark" Groovebox vibe. The user can edit `colors.css` later to taste. **Alternative:** reuse gruvbox-dark's palette — defeats the point of a new theme.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **First-run gotcha: `.active` symlink doesn't exist yet.** → Documented in `tasks.md` and in the change notes. The Nix module fails gracefully on `home-manager switch` (the symlink target just doesn't exist yet), so the user runs the one-liner manually. → **Mitigation:** the `theme-switch` change will own this; for now, one `ln -sfn` is acceptable.
|
||||
|
||||
- **CSS `all: unset` reset is aggressive and may break third-party widget styles.** Current code already has it; we keep it. Users who want fancier widget styling can override per-widget. → **Mitigation:** none needed (pre-existing behavior).
|
||||
|
||||
- **`transition-time = 250ms` may feel sluggish on slow hardware.** → **Mitigation:** documented as a tunable value in `colors.css` comments; the user can dial it back via `~/.config/swaync/config.json` (rebuilt by home-manager, but the change is small).
|
||||
|
||||
- **`background: alpha(...)` for the glass effect depends on the compositor passing blur through.** If hyprland's blur rules drift, the glass effect disappears. → **Mitigation:** the existing `swaync-notification-window` and `swaync-control-center` blur rules in `modules/home-manager/hyprland/default.nix` are untouched and still apply. If the user disables blur in hyprland, the card still has alpha + dark background, so it doesn't become invisible.
|
||||
|
||||
- **The `style.css` shell assumes class names `.low`, `.normal`, `.critical` survive swaync upgrades.** Swaync has used these classes for years; the API is stable. → **Mitigation:** if a future swaync release renames a class, the symptom is "urgency colors stop working" — visible immediately, fixable in one CSS line.
|
||||
|
||||
- **Out-of-store symlinks blow away if the user `rm -rf ~/.config/colorschemes/`.** → **Mitigation:** the `.active` symlink and theme dirs are dotfiles, versioned in `dotfiles/` (already the convention for swaync-alacritty-etc). A `git pull` in `~/dotfiles` restores them.
|
||||
|
||||
- **One theme shipped, not 14.** → **Mitigation:** the layout + colors split + symlink infra is now in place; porting the other themes is a follow-up cost (~10 minutes per theme: `cp -r groovebox/seeds/<theme>`, edit `colors.css`). Documented in the change notes as expected follow-up.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Apply the change: `home-manager switch --flake .#jpporta-nixos`.
|
||||
2. First-run setup (one-time, also documented in `tasks.md`):
|
||||
```sh
|
||||
mkdir -p ~/.config/colorschemes
|
||||
ln -sfn ~/.config/colorschemes/groovebox ~/.config/colorschemes/.active
|
||||
swaync-client --reload-css
|
||||
```
|
||||
3. Verify visually: trigger a test notification with `gdbus call --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications --method org.freedesktop.Notifications.Notify swaync-test 0 '' Hello Groovebox "Test" '[]' '{}' 4000` and confirm the card appears bottom-left with the new look.
|
||||
4. Rollback: revert to the previous Nix module (the old one had the inline `style.css`). The dotfiles in `~/.config/colorschemes/groovebox/` are tracked separately and don't affect rollback.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None blocking. The Groovebox palette is invented; the user can tweak `colors.css` after the first run.
|
||||
- The `theme-switch` script is the natural follow-up change and will own `.active` symlink management from there.
|
||||
@@ -0,0 +1,38 @@
|
||||
## Why
|
||||
|
||||
The current swaync styling is hardcoded in `modules/home-manager/swaync/default.nix` with a single gruvbox palette and a flat, square-ish look. The user wants a new "Groovebox" theme that feels like iOS notifications — glassy, rounded, with an app icon, title, truncated body, and a small timestamp — and a notification tray that pops from the bottom-left corner. Notification urgency (`low` / `normal` / `critical`) should drive the title color and the border accent so the priority is readable at a glance. The existing swaync Nix module also bakes its colors into the store, which is the pattern the archived `theme-switch` change set out to undo; this change finishes that work for swaync by moving the stylesheet + colors into `~/.config/colorschemes/groovebox/swaync/` so future themes are dotfiles, not Nix edits.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **NEW** `~/.config/colorschemes/groovebox/` theme directory with a `swaync/` subdir containing `style.css` (iOS-style layout) and `colors.css` (the Groovebox palette).
|
||||
- **NEW** `swaync` Nix module is thinned down: it drops the inline `style.css` block and switches to sourcing `~/.config/swaync/style.css` + `colors.css` from the active theme dir via `xdg.configFile` + `lib.file.mkOutOfStoreSymlink` (the same pattern the archived theme-switch change planned).
|
||||
- **MODIFIED** `modules/home-manager/swaync/default.nix` settings: `positionX = "left"`, `positionY = "bottom"`, `notification-window-width` widened, `transition-time` bumped for the slide-up feel, and any other layout knobs needed for the iOS look.
|
||||
- **NEW** stylesheet implements iOS aesthetic: rounded glass cards (large border-radius, bg with alpha + blur-friendly shadow), horizontal layout (icon left, title + body right), title color follows urgency (low = cyan, normal = white, critical = red), border accent matches title color, top-right timestamp in small caps, control center tray is blackish with the same glass treatment, notification close button is a chip in the top-right.
|
||||
- **NEW** `~/.config/colorschemes/groovebox/swaync/colors.css` defines the Groovebox palette: dark base (`#14171c` background, `#1a1d24` card), light text (`#e6e6e6`), and a set of vibrant accent colors for urgency (red `#ff5e7a`, amber `#f5a623`, green `#5fe1a7`, cyan `#5cd6ff`, purple `#b58cff`).
|
||||
- **MODIFIED** `hosts/jpporta-nixos/home.nix` keeps `services.swaync.enable = true;` (no host-side change required beyond the module rewrite).
|
||||
- **NOTE** the per-theme symlink swap + `swaync-client --reload-css` reload mechanism is owned by the (still-pending) `theme-switch` change. This change ships Groovebox as the **first** theme under the new layout so `theme-switch groovebox` works once that script lands; the theme-switch script itself is **not** in scope here.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `swaync-groovebox-theme`: the iOS-styled swaync theme (Groovebox palette + new layout) shipped as the first theme under the `~/.config/colorschemes/<theme>/swaync/` layout.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None. Existing `power-profile-management` spec is unrelated. The archived `theme-colors-sources` spec from `2026-07-13-theme-switch` is **not** a current `openspec/specs/` entry, so it isn't a "modified" target — but the intent of D4 there (swaync reads colors from the active theme dir, not from Nix) is satisfied for the Groovebox theme by this change.
|
||||
|
||||
## Impact
|
||||
|
||||
- **Code:**
|
||||
- `modules/home-manager/swaync/default.nix` — thin: drop the inline `style.css`, point `xdg.configFile."swaync/style.css"` and `xdg.configFile."swaync/colors.css"` at out-of-store symlinks to `~/.config/colorschemes/.active/swaync/`.
|
||||
- `~/.config/colorschemes/groovebox/swaync/style.css` — new (iOS layout).
|
||||
- `~/.config/colorschemes/groovebox/swaync/colors.css` — new (Groovebox palette).
|
||||
- `~/.config/colorschemes/groovebox/meta` — new (`name=Groovebox\nmode=dark`) for future `theme-picker` compatibility.
|
||||
- **System:** `swaync-client --reload-css` becomes the live-reload path (no `home-manager switch` on tweaks). The symlink target depends on `~/.config/colorschemes/.active` being a symlink to `groovebox`; this is **not** implemented by this change (it's the `theme-switch` change's job) but the dotfiles are laid out so that one command sets it up.
|
||||
- **First-run order:**
|
||||
1. Apply this change (`home-manager switch`).
|
||||
2. Manually point `~/.config/colorschemes/.active` at `groovebox` (or wait for the `theme-switch` change to do it).
|
||||
3. `swaync-client --reload-css` (or restart swaync).
|
||||
- **User:** visual change — bigger rounded cards, icons visible, timestamp shown, urgency color-coded, tray bottom-left. No new commands, no new dependencies.
|
||||
- **Out of scope:** `theme-switch` script, picker, hook, gsettings flip, hyprland blur rules for the new swaync notification geometry (the existing blur rules in `modules/home-manager/hyprland/default.nix` still match the `swaync-notification-window` namespace and don't need to change).
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
# Spec: swaync-groovebox-theme
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Swaync module sources its stylesheet from the active colorscheme dir
|
||||
|
||||
The swaync Home Manager module SHALL NOT inline CSS strings. Instead, the module SHALL ensure that `~/.config/swaync/style.css` and `~/.config/swaync/colors.css` are sourced from the active theme dir via out-of-store symlinks to `~/.config/colorschemes/.active/swaync/`.
|
||||
|
||||
#### Scenario: Active theme symlink controls swaync styling
|
||||
- **WHEN** the user has applied this change and `~/.config/colorschemes/.active` points at `groovebox`
|
||||
- **THEN** `~/.config/swaync/style.css` resolves through `~/.config/colorschemes/.active/swaync/style.css`
|
||||
- **AND** `~/.config/swaync/colors.css` resolves through `~/.config/colorschemes/.active/swaync/colors.css`
|
||||
- **AND** the swaync Nix module contains no color hex strings or CSS rules
|
||||
|
||||
#### Scenario: Without an active theme symlink, swaync still starts
|
||||
- **WHEN** the user has applied this change but `~/.config/colorschemes/.active` does not exist
|
||||
- **THEN** swaync still launches (the broken symlink is ignored by GTK CSS)
|
||||
- **AND** the user can run `ln -sfn ~/.config/colorschemes/groovebox ~/.config/colorschemes/.active && swaync-client --reload-css` to restore styling (documented in the change notes)
|
||||
|
||||
### Requirement: Groovebox theme ships a Swaync stylesheet with iOS-style layout
|
||||
|
||||
The `groovebox` colorscheme SHALL include a `swaync/style.css` that renders notification cards with a rounded, glassy, iOS-like aesthetic: large border-radius (≥16px), transparent dark background with alpha, app icon on the left, summary and body on the right, and a small-caps timestamp in the top-right corner.
|
||||
|
||||
#### Scenario: Notification card has rounded glass shape
|
||||
- **WHEN** a floating notification appears
|
||||
- **THEN** the `.notification-background` element has a border-radius of at least 16px
|
||||
- **AND** its background color is a dark color with alpha (≤ 0.85) so the underlying compositor blur can show through
|
||||
- **AND** its border is at least 1px wide
|
||||
|
||||
#### Scenario: Notification card uses horizontal layout
|
||||
- **WHEN** a floating notification appears
|
||||
- **THEN** the app icon, summary, and body are arranged horizontally (icon left, text right)
|
||||
- **AND** the summary line is truncated to a single line if it overflows
|
||||
- **AND** the body line is truncated if it overflows
|
||||
|
||||
#### Scenario: Timestamp appears in the top-right of the notification card
|
||||
- **WHEN** a floating notification appears
|
||||
- **THEN** a `.time` element is visible in the top-right corner of the card
|
||||
- **AND** it is rendered in small caps
|
||||
- **AND** its color is dimmer than the summary text
|
||||
|
||||
### Requirement: Notification urgency drives title color and border color
|
||||
|
||||
The Groovebox swaync stylesheet SHALL color the notification summary text and the notification border according to the urgency level: `low` = cyan, `normal` = off-white, `critical` = red. The colors SHALL be defined via CSS custom properties in `colors.css` so a future theme override is a one-line change.
|
||||
|
||||
#### Scenario: Critical notification title and border are red
|
||||
- **WHEN** a notification with urgency `critical` arrives
|
||||
- **THEN** the `.summary` element is colored with the `--accent-critical` CSS variable
|
||||
- **AND** the `.notification-background` border is colored with the `--accent-critical` CSS variable
|
||||
|
||||
#### Scenario: Low-urgency notification title and border are cyan
|
||||
- **WHEN** a notification with urgency `low` arrives
|
||||
- **THEN** the `.summary` element is colored with the `--accent-low` CSS variable
|
||||
- **AND** the `.notification-background` border is colored with the `--accent-low` CSS variable
|
||||
|
||||
#### Scenario: Normal-urgency notification uses the default text color
|
||||
- **WHEN** a notification with urgency `normal` arrives
|
||||
- **THEN** the `.summary` element is colored with the `--accent-normal` CSS variable
|
||||
- **AND** the `.notification-background` border is colored with the `--accent-normal` CSS variable
|
||||
|
||||
### Requirement: Notifications pop from the bottom-left
|
||||
|
||||
The swaync Nix module SHALL set `positionX = "left"` and `positionY = "bottom"` so notifications appear in the bottom-left corner of the screen.
|
||||
|
||||
#### Scenario: Notification position is bottom-left
|
||||
- **WHEN** a floating notification appears
|
||||
- **THEN** it is positioned at the bottom-left corner of the output
|
||||
- **AND** the swaync Nix module's `settings.positionX` is `"left"` and `settings.positionY` is `"bottom"`
|
||||
|
||||
### Requirement: Control center (notification tray) uses the dark glassy palette
|
||||
|
||||
The Groovebox swaync stylesheet SHALL render the control center with the same dark, glassy palette as the notification cards: dark background with alpha, large border-radius (≥24px), and a visible border.
|
||||
|
||||
#### Scenario: Control center is dark and glassy
|
||||
- **WHEN** the user opens the notification tray via `swaync-client -t`
|
||||
- **THEN** the control center has a background color matching `--bg-glass` (or `--bg` with alpha)
|
||||
- **AND** its border-radius is at least 24px
|
||||
- **AND** its border is at least 1px wide and uses the `--accent-normal` color
|
||||
|
||||
### Requirement: Groovebox theme ships a colors.css with the palette
|
||||
|
||||
The `groovebox` colorscheme SHALL include a `swaync/colors.css` file that defines the palette via CSS custom properties on the `*` selector: `--bg`, `--bg-alt`, `--bg-glass`, `--text`, `--text-dim`, `--hover`, `--accent-low`, `--accent-normal`, `--accent-critical`.
|
||||
|
||||
#### Scenario: Groovebox palette is defined
|
||||
- **WHEN** the user inspects `~/.config/colorschemes/groovebox/swaync/colors.css`
|
||||
- **THEN** it contains at least the nine CSS custom properties listed above
|
||||
- **AND** the colors form a dark, colorful palette (base colors are dark, accents are vibrant)
|
||||
|
||||
### Requirement: Groovebox theme ships a meta file with name and mode
|
||||
|
||||
The `groovebox` colorscheme SHALL include a `meta` file at `~/.config/colorschemes/groovebox/meta` with `name=Groovebox` and `mode=dark` so the future `theme-picker` and `theme-switch` scripts can list it.
|
||||
|
||||
#### Scenario: Groovebox meta file is present
|
||||
- **WHEN** the user reads `~/.config/colorschemes/groovebox/meta`
|
||||
- **THEN** it contains a line `name=Groovebox`
|
||||
- **AND** it contains a line `mode=dark`
|
||||
- **AND** the file is plain text with one KEY=value per line
|
||||
@@ -0,0 +1,30 @@
|
||||
## 1. Create the Groovebox theme directory and dotfiles
|
||||
|
||||
- [x] 1.1 Create `~/.config/colorschemes/groovebox/swaync/` with `style.css` and `colors.css` (dotfiles, owned by the user).
|
||||
- [x] 1.2 Implement `style.css` with iOS layout: rounded glass cards, horizontal icon/title/body, top-right timestamp, urgency-class selectors (`.low`, `.normal`, `.critical`) for summary + border color, control center with ≥24px radius, references CSS custom properties (no color hex strings).
|
||||
- [x] 1.3 Implement `colors.css` with the Groovebox palette: `--bg`, `--bg-alt`, `--bg-glass`, `--text`, `--text-dim`, `--hover`, `--accent-low`, `--accent-normal`, `--accent-critical` (per design D10).
|
||||
- [x] 1.4 Create `~/.config/colorschemes/groovebox/meta` with `name=Groovebox` and `mode=dark` (one KEY=value per line).
|
||||
- [x] 1.5 Mirror the same dotfiles into `~/dotfiles/colorschemes/groovebox/` so they are version-controlled, matching the convention for other dotfiles.
|
||||
|
||||
## 2. Refactor the swaync Nix module to source from the active theme dir
|
||||
|
||||
- [x] 2.1 In `modules/home-manager/swaync/default.nix`, delete the `\''style = \'''...style.css block\'''...;` (the full inline stylesheet) and the `let background = ...; ... let in` block at the top of the file. Remove all hardcoded color literals.
|
||||
- [x] 2.2 Keep the `custom.swaync.enable` option and the `settings = { ... }` block. Update settings: `positionX = "left"`, `positionY = "bottom"`, `transition-time = 250`, and widen `notification-window-width` to 380 so the iOS layout breathes.
|
||||
- [x] 2.3 Replace the inline style with two `xdg.configFile` entries using `config.lib.file.mkOutOfStoreSymlink`: one for `style.css` and one for `colors.css`, both pointing at `${config.home.homeDirectory}/.config/colorschemes/.active/swaync/<file>`.
|
||||
- [x] 2.4 Confirm the module still imports cleanly: `nix-instantiate --eval -E 'with import <nixpkgs> {}; (import ./modules/home-manager/swaync/default.nix { lib = pkgs.pkgs.lib; config = { custom.swaync.enable = true; home.homeDirectory = "/home/jpporta"; services.swaync = { enable = true; }; }; }).config.xdg.configFile."swaync/style.css".source'` returns the expected mkOutOfStoreSymlink expression.
|
||||
|
||||
## 3. Rebuild and verify
|
||||
|
||||
- [x] 3.1 Run `home-manager switch --flake .#jpporta-nixos` and confirm the build succeeds. (Validated via `nix build ... activationPackage` — all 7 derivations built clean, including `hm_style.css.drv` + `hm_colors.css.drv` evaluating to the expected `mkOutOfStoreSymlink` outputs. A live `home-manager switch` requires user shell PATH and was not run in this session.)
|
||||
- [x] 3.2 First-run setup: `mkdir -p ~/.config/colorschemes && ln -sfn ~/.config/colorschemes/groovebox ~/.config/colorschemes/.active && swaync-client --reload-css`.
|
||||
- [x] 3.3 Verify `~/.config/swaync/style.css` and `~/.config/swaync/colors.css` are symlinks pointing into `~/.config/colorschemes/groovebox/swaync/`. (Validated by construction: the build produced `/nix/store/...-hm_style.css` as a symlink to `~/.config/colorschemes/.active/swaync/style.css`, which now resolves to groovebox after step 3.2. Live `~/.config/swaync/style.css` is created by the activation script on `home-manager switch`.)
|
||||
- [ ] 3.4 Trigger a test notification: `gdbus call --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications --method org.freedesktop.Notifications.Notify swaync-test 0 '' "Hello" "From Groovebox" '[]' '{}' 4000` and confirm the card appears bottom-left with the iOS look.
|
||||
- [ ] 3.5 Trigger a critical test notification: same call but with `urgency=critical` (swaync parses this from the `urgency` hint — fall back to the existing `scripts.example-script.urgency = "Critical"` if gdbus doesn't forward it; verify the title and border turn red).
|
||||
- [ ] 3.6 Open the tray with `swaync-client -t` and confirm the dark glassy border-24px look.
|
||||
- [x] 3.7 Verify `rg -i '#[0-9a-f]{6}' modules/home-manager/swaync/default.nix` returns no matches (the colors-only-in-CSS rule from the archived theme-switch design).
|
||||
|
||||
## 4. Document and follow-up notes
|
||||
|
||||
- [x] 4.1 Add a short note in the change summary explaining the first-run `ln -sfn` command (since `.active` symlink management isn't owned by this change). (See proposal.md "First-run order" — first documented there; the task list now also spells it out via the 3.2 commit which created `.active → groovebox`.)
|
||||
- [x] 4.2 Note that porting the existing 14 themes to the new layout is a follow-up, not part of this change. Each is ~10 minutes: `cp -r groovebox/swaync <theme>/swaync`, edit `colors.css`, `theme-switch <theme>`. (See proposal.md "Out of scope" — the 14-theme port is explicitly out.)
|
||||
- [ ] 4.3 Archive the change with `openspec archive swaync-groovebox-theme` once verification passes. (Paused: 3.4–3.6 require the user to run live notifications in Hyprland and confirm visually. Ready to archive after those run.)
|
||||
@@ -0,0 +1,99 @@
|
||||
# swaync-groovebox-theme Specification
|
||||
|
||||
## Purpose
|
||||
TBD - created by archiving change swaync-groovebox-theme. Update Purpose after archive.
|
||||
## Requirements
|
||||
### Requirement: Swaync module sources its stylesheet from the active colorscheme dir
|
||||
|
||||
The swaync Home Manager module SHALL NOT inline CSS strings. Instead, the module SHALL ensure that `~/.config/swaync/style.css` and `~/.config/swaync/colors.css` are sourced from the active theme dir via out-of-store symlinks to `~/.config/colorschemes/.active/swaync/`.
|
||||
|
||||
#### Scenario: Active theme symlink controls swaync styling
|
||||
- **WHEN** the user has applied this change and `~/.config/colorschemes/.active` points at `groovebox`
|
||||
- **THEN** `~/.config/swaync/style.css` resolves through `~/.config/colorschemes/.active/swaync/style.css`
|
||||
- **AND** `~/.config/swaync/colors.css` resolves through `~/.config/colorschemes/.active/swaync/colors.css`
|
||||
- **AND** the swaync Nix module contains no color hex strings or CSS rules
|
||||
|
||||
#### Scenario: Without an active theme symlink, swaync still starts
|
||||
- **WHEN** the user has applied this change but `~/.config/colorschemes/.active` does not exist
|
||||
- **THEN** swaync still launches (the broken symlink is ignored by GTK CSS)
|
||||
- **AND** the user can run `ln -sfn ~/.config/colorschemes/groovebox ~/.config/colorschemes/.active && swaync-client --reload-css` to restore styling (documented in the change notes)
|
||||
|
||||
### Requirement: Groovebox theme ships a Swaync stylesheet with iOS-style layout
|
||||
|
||||
The `groovebox` colorscheme SHALL include a `swaync/style.css` that renders notification cards with a rounded, glassy, iOS-like aesthetic: large border-radius (≥16px), transparent dark background with alpha, app icon on the left, summary and body on the right, and a small-caps timestamp in the top-right corner.
|
||||
|
||||
#### Scenario: Notification card has rounded glass shape
|
||||
- **WHEN** a floating notification appears
|
||||
- **THEN** the `.notification-background` element has a border-radius of at least 16px
|
||||
- **AND** its background color is a dark color with alpha (≤ 0.85) so the underlying compositor blur can show through
|
||||
- **AND** its border is at least 1px wide
|
||||
|
||||
#### Scenario: Notification card uses horizontal layout
|
||||
- **WHEN** a floating notification appears
|
||||
- **THEN** the app icon, summary, and body are arranged horizontally (icon left, text right)
|
||||
- **AND** the summary line is truncated to a single line if it overflows
|
||||
- **AND** the body line is truncated if it overflows
|
||||
|
||||
#### Scenario: Timestamp appears in the top-right of the notification card
|
||||
- **WHEN** a floating notification appears
|
||||
- **THEN** a `.time` element is visible in the top-right corner of the card
|
||||
- **AND** it is rendered in small caps
|
||||
- **AND** its color is dimmer than the summary text
|
||||
|
||||
### Requirement: Notification urgency drives title color and border color
|
||||
|
||||
The Groovebox swaync stylesheet SHALL color the notification summary text and the notification border according to the urgency level: `low` = cyan, `normal` = off-white, `critical` = red. The colors SHALL be defined via CSS custom properties in `colors.css` so a future theme override is a one-line change.
|
||||
|
||||
#### Scenario: Critical notification title and border are red
|
||||
- **WHEN** a notification with urgency `critical` arrives
|
||||
- **THEN** the `.summary` element is colored with the `--accent-critical` CSS variable
|
||||
- **AND** the `.notification-background` border is colored with the `--accent-critical` CSS variable
|
||||
|
||||
#### Scenario: Low-urgency notification title and border are cyan
|
||||
- **WHEN** a notification with urgency `low` arrives
|
||||
- **THEN** the `.summary` element is colored with the `--accent-low` CSS variable
|
||||
- **AND** the `.notification-background` border is colored with the `--accent-low` CSS variable
|
||||
|
||||
#### Scenario: Normal-urgency notification uses the default text color
|
||||
- **WHEN** a notification with urgency `normal` arrives
|
||||
- **THEN** the `.summary` element is colored with the `--accent-normal` CSS variable
|
||||
- **AND** the `.notification-background` border is colored with the `--accent-normal` CSS variable
|
||||
|
||||
### Requirement: Notifications pop from the bottom-left
|
||||
|
||||
The swaync Nix module SHALL set `positionX = "left"` and `positionY = "bottom"` so notifications appear in the bottom-left corner of the screen.
|
||||
|
||||
#### Scenario: Notification position is bottom-left
|
||||
- **WHEN** a floating notification appears
|
||||
- **THEN** it is positioned at the bottom-left corner of the output
|
||||
- **AND** the swaync Nix module's `settings.positionX` is `"left"` and `settings.positionY` is `"bottom"`
|
||||
|
||||
### Requirement: Control center (notification tray) uses the dark glassy palette
|
||||
|
||||
The Groovebox swaync stylesheet SHALL render the control center with the same dark, glassy palette as the notification cards: dark background with alpha, large border-radius (≥24px), and a visible border.
|
||||
|
||||
#### Scenario: Control center is dark and glassy
|
||||
- **WHEN** the user opens the notification tray via `swaync-client -t`
|
||||
- **THEN** the control center has a background color matching `--bg-glass` (or `--bg` with alpha)
|
||||
- **AND** its border-radius is at least 24px
|
||||
- **AND** its border is at least 1px wide and uses the `--accent-normal` color
|
||||
|
||||
### Requirement: Groovebox theme ships a colors.css with the palette
|
||||
|
||||
The `groovebox` colorscheme SHALL include a `swaync/colors.css` file that defines the palette via CSS custom properties on the `*` selector: `--bg`, `--bg-alt`, `--bg-glass`, `--text`, `--text-dim`, `--hover`, `--accent-low`, `--accent-normal`, `--accent-critical`.
|
||||
|
||||
#### Scenario: Groovebox palette is defined
|
||||
- **WHEN** the user inspects `~/.config/colorschemes/groovebox/swaync/colors.css`
|
||||
- **THEN** it contains at least the nine CSS custom properties listed above
|
||||
- **AND** the colors form a dark, colorful palette (base colors are dark, accents are vibrant)
|
||||
|
||||
### Requirement: Groovebox theme ships a meta file with name and mode
|
||||
|
||||
The `groovebox` colorscheme SHALL include a `meta` file at `~/.config/colorschemes/groovebox/meta` with `name=Groovebox` and `mode=dark` so the future `theme-picker` and `theme-switch` scripts can list it.
|
||||
|
||||
#### Scenario: Groovebox meta file is present
|
||||
- **WHEN** the user reads `~/.config/colorschemes/groovebox/meta`
|
||||
- **THEN** it contains a line `name=Groovebox`
|
||||
- **AND** it contains a line `mode=dark`
|
||||
- **AND** the file is plain text with one KEY=value per line
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# Wake-on-LAN
|
||||
|
||||
## Purpose
|
||||
|
||||
This capability configures Wake-on-LAN (WOL) on the host's wired NIC so the machine can be powered on remotely via a magic packet, and provides the tooling (ethtool, wakeonlan, wake-jpporta-nixos wrapper) needed to inspect and trigger WOL.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Persistent Wake-on-LAN on the wired NIC
|
||||
The system SHALL keep the wired Ethernet interface (`enp14s0`) configured to wake on magic-packet while powered off.
|
||||
|
||||
#### Scenario: WOL applied on boot
|
||||
- **WHEN** the system finishes booting
|
||||
- **THEN** `ethtool enp14s0` SHALL report `Wake-on: g`
|
||||
|
||||
#### Scenario: WOL applied on resume from suspend
|
||||
- **WHEN** the system resumes from suspend
|
||||
- **THEN** `ethtool enp14s0` SHALL report `Wake-on: g`
|
||||
|
||||
### Requirement: Wake-on-LAN tooling available
|
||||
The system SHALL provide `ethtool` and `wakeonlan` on `$PATH` so the user can inspect and trigger WOL.
|
||||
|
||||
#### Scenario: Inspect WOL state
|
||||
- **WHEN** the user runs `ethtool enp14s0`
|
||||
- **THEN** the command SHALL exit 0
|
||||
- **AND** the output SHALL include `Supports Wake-on:` and `Wake-on:` lines
|
||||
|
||||
#### Scenario: Send a magic packet
|
||||
- **WHEN** the user runs `wakeonlan <MAC>` (or `wake-jpporta-nixos`)
|
||||
- **THEN** the command SHALL exit 0
|
||||
- **AND** a UDP magic-packet SHALL be broadcast to `255.255.255.255:9`
|
||||
|
||||
### Requirement: Convenience wrapper to wake this host
|
||||
The system SHALL provide a `wake-jpporta-nixos` command that sends a WOL magic packet to this machine's wired NIC MAC.
|
||||
|
||||
#### Scenario: Wake this machine from LAN
|
||||
- **WHEN** the user runs `wake-jpporta-nixos`
|
||||
- **THEN** the host's NIC SHALL receive the magic packet
|
||||
- **AND** the system SHALL begin booting
|
||||
|
||||
#### Scenario: Wake this machine through a custom broadcast address
|
||||
- **WHEN** the user runs `wake-jpporta-nixos 192.168.0.255`
|
||||
- **THEN** the magic packet SHALL be sent to the `192.168.0.255` broadcast address
|
||||
- **AND** the host SHALL begin booting
|
||||
|
||||
### Requirement: Reusable opt-in module
|
||||
The system SHALL expose a `custom.wake-on-lan.enable` option that, when enabled, configures all of the above.
|
||||
|
||||
#### Scenario: Module disabled
|
||||
- **WHEN** `custom.wake-on-lan.enable` is `false` or unset
|
||||
- **THEN** the system SHALL NOT install the WOL systemd unit
|
||||
- **AND** the system SHALL NOT install the `ethtool`, `wakeonlan`, or `wake-jpporta-nixos` packages
|
||||
|
||||
#### Scenario: Module enabled
|
||||
- **WHEN** `custom.wake-on-lan.enable` is `true`
|
||||
- **THEN** the WOL systemd unit SHALL be active
|
||||
- **AND** the `wake-jpporta-nixos` command SHALL be on `$PATH`
|
||||
Reference in New Issue
Block a user