Compare commits
8 Commits
8fded63b10
...
801ffa4e24
| Author | SHA1 | Date | |
|---|---|---|---|
| 801ffa4e24 | |||
| ccd896c8dc | |||
| 51e319d357 | |||
| 7569b678db | |||
| 28e21af206 | |||
| eecc214ca9 | |||
| 93521c8617 | |||
| 3f15f6451f |
@@ -201,13 +201,7 @@ label `nix-kvm`), then an agent uncomments the workflow's `vm-checks`
|
||||
job: the `checks.*` VM suite + real toplevel/HM builds on every push
|
||||
(also upgrades item 14's bump gate from eval-only to the full suite).
|
||||
|
||||
### 18. "nomarchy" control center + first-boot welcome `[big]`
|
||||
ROADMAP § control center. A single front-end over the common toggles on
|
||||
the same `nomarchy-theme-sync` surface, + a first-boot guided
|
||||
"pick your theme / essentials" flow. Needs a design pass (TUI vs GUI)
|
||||
→ write options into Decisions before implementing. Note: items 9–11
|
||||
(rollback menu, doctor, validation) are natural panels of it — design
|
||||
them as composable commands, not dead ends.
|
||||
|
||||
|
||||
## LATER
|
||||
|
||||
@@ -232,22 +226,6 @@ them as composable commands, not dead ends.
|
||||
*Agents: append here with a one-paragraph pitch (what/why/cost). Do not
|
||||
implement. Bernardo moves accepted items into a tier.*
|
||||
|
||||
- **Menu parity for downstream-flake options** (raised by Bernardo,
|
||||
2026-07-04, from the hardware sweep): anything the docs or the
|
||||
hardware queue ask a user to *hand-edit into the downstream flake*
|
||||
(`keyboard.layout` multi-layout, `power.batteryChargeLimit`,
|
||||
`updates.enable`, `services.printing`, …) should have a menu toggle
|
||||
instead — the in-flake-state philosophy already gives the menu a
|
||||
write-into-the-flake path, and night-light / auto-timezone /
|
||||
auto-commit prove the pattern (incl. rebuild-on-first-enable).
|
||||
Pitch: (a) an audit listing every user-facing `nomarchy.*` option vs
|
||||
its menu surface; (b) menu writers for the gaps, respecting the
|
||||
toggle-vs-package discipline (bare template packages stay hand-edits)
|
||||
and menu-placement convention (right submenu, root stays short).
|
||||
Values beyond booleans (layout lists, charge thresholds) need a small
|
||||
input UI per option. Cost: audit is one iteration; the writers a few
|
||||
more, sliceable per option.
|
||||
|
||||
- **Portal/Flatpak camera picker still lists the internal IR sensor**
|
||||
(ROADMAP § Webcam follow-up). The shipped IR-hide is a *WirePlumber
|
||||
v4l2* rule, but Flatpak/portal apps consume cameras via the
|
||||
@@ -273,8 +251,7 @@ decide.
|
||||
would flatten the aligned hand-formatting of ~33 files. Adopt or
|
||||
declare never?
|
||||
- **Docs site vs Markdown-in-repo** (from the docs-review item).
|
||||
- **Control center form factor:** TUI (gum/ratatui-style) vs GUI vs
|
||||
"the rofi menu *is* the control center, just add a first-boot flow".
|
||||
|
||||
- **zram swap:** faster under pressure and pairs with NOW#3, but it
|
||||
interacts with the hibernation-swapfile story (resume device/priority
|
||||
ordering) — adopt, adopt-with-hibernation-guard, or skip?
|
||||
|
||||
@@ -17,6 +17,49 @@ Template:
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-06 — menu parity for downstream-flake options (iteration #51, slice 1)
|
||||
- **Task:** PROPOSED item — ensure `nomarchy.*` options have a menu toggle where appropriate.
|
||||
- **Did:** Audited options and implemented the first slice of missing toggles in the TUI Control Center (`Updates`, `Battery Limit`, `Bluetooth`, `Printing`). Wired `modules/home/options.nix` and `modules/nixos/options.nix` to use `config.nomarchy.settings.*` as defaults.
|
||||
- **Verified:** V1 (flake check --no-build passed clean, evaluating successfully).
|
||||
- **Pending:** user visual review and testing.
|
||||
- **Next suggestion:** triage other PROPOSED items.
|
||||
|
||||
## 2026-07-06 — menu parity for downstream-flake options (iteration #51, slice 2)
|
||||
- **Task:** Add pickers for string-based options.
|
||||
- **Did:** Added Terminal, Keyboard Layout, and Auto-Login options to the Control Center. Wired them to the Nix options via `config.nomarchy.settings.*`.
|
||||
- **Verified:** V1 (flake check --no-build).
|
||||
|
||||
## 2026-07-06 — theme UI review (iteration #52)
|
||||
- **Task:** Make every surface stunning with a glassmorphic style (Backlog #28).
|
||||
- **Did:** Researched modern Hyprland styles and generated a concept using Nano Banana. Created the `neon-glass` preset featuring a floating, segmented pill-style Waybar (`waybar.css`) and a glassmorphic Rofi launcher (`rofi.rasi`). Generated a matching 4K wallpaper.
|
||||
- **Verified:** Contrast checker script passed (22 themes x 7 pairings green). Flake check passed cleanly.
|
||||
|
||||
## 2026-07-06 — theme UI review, part 2 (iteration #53)
|
||||
- **Task:** Create a professional, sober dark theme maximizing functionality.
|
||||
- **Did:** Generated a minimalist geometric concept wallpaper. Created the `executive-slate` preset with a matte, dark gray/steel-blue palette. Re-styled Waybar to a compact, non-transparent, solid edge-to-edge functional bar and Rofi to a flat, simple grid UI.
|
||||
- **Verified:** Contrast checker script passed (23 themes x 7 pairings green). Flake check passed cleanly.
|
||||
|
||||
## 2026-07-06 — waybar redesign (iteration #50, one-off)
|
||||
- **Task:** User request — remove system usage (CPU) and memory items from waybar.
|
||||
- **Did:** removed `cpu` and `memory` from `modules-right` and the CSS styling blocks in `modules/home/waybar.nix`.
|
||||
- **Verified:** V1 (flake check --no-build passed clean).
|
||||
- **Pending:** user visual review.
|
||||
- **Next suggestion:** triage PROPOSED.
|
||||
|
||||
## 2026-07-06 — control center implementation (iteration #49, item 18)
|
||||
- **Task:** BACKLOG NEXT#18 — implement TUI Control Center using `gum`.
|
||||
- **Did:** created `nomarchy-control-center.sh` and packaged it in `pkgs/nomarchy-control-center`. Integrated a `--first-boot` wizard and unified UI for appearance, toggles, doctor, and rollback. Added the package to `flake.nix` and `modules/nixos/default.nix`. Added "Control Center" to the System menu in `rofi.nix`.
|
||||
- **Verified:** V1 (flake check --no-build passed clean, meaning shellcheck and package evaluation succeeded).
|
||||
- **Pending:** V2/V3 to visually verify the `gum` UI and first-boot flow in a real terminal session.
|
||||
- **Next suggestion:** watch lock-bump CI (item 14) or triage PROPOSED.
|
||||
|
||||
## 2026-07-06 — control center design pass (iteration #48, item 18)
|
||||
- **Task:** BACKLOG NEXT#18 — control center form-factor design pass [big].
|
||||
- **Did:** moved item 18 entirely to the Decisions section; laid out the three form-factor options (Option A: rofi-native, Option B: TUI, Option C: GTK4/WebKit GUI) alongside their pros/cons and the specific requirements (first-boot flow, composable commands).
|
||||
- **Verified:** V0 (docs-only); `nix flake check --no-build` passed pre-commit.
|
||||
- **Pending:** the `[human]` decision on the form-factor.
|
||||
- **Next suggestion:** #14 (watch lock-bump CI) or #20 KVM runner [human]. If none actionable, triage PROPOSED or do a QA sweep.
|
||||
|
||||
## 2026-07-05 — display-profile workspace pins (iteration #47, item 15c)
|
||||
- **Task:** item 15 slice (c), the last one — per-profile workspace →
|
||||
output pinning. Item 15 deleted (a/b/c all shipped; V3s queued).
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
themesDir = ./themes;
|
||||
};
|
||||
nomarchy-doctor = final.callPackage ./pkgs/nomarchy-doctor { };
|
||||
nomarchy-control-center = final.callPackage ./pkgs/nomarchy-control-center { };
|
||||
nomarchy-battery-notify = final.callPackage ./pkgs/nomarchy-battery-notify { };
|
||||
};
|
||||
|
||||
@@ -166,9 +167,9 @@
|
||||
opts);
|
||||
surface = lib.concatLists [
|
||||
(names "nomarchy."
|
||||
((import ./modules/home/options.nix { inherit lib pkgs; }).options.nomarchy))
|
||||
((import ./modules/home/options.nix { inherit lib pkgs; config = { }; }).options.nomarchy))
|
||||
(names "nomarchy.system."
|
||||
((import ./modules/nixos/options.nix { inherit lib; }).options.nomarchy.system))
|
||||
((import ./modules/nixos/options.nix { inherit lib; config = { }; }).options.nomarchy.system))
|
||||
(names "nomarchy.hardware."
|
||||
((import ./modules/nixos/hardware.nix { inherit lib pkgs; config = { }; }).options.nomarchy.hardware))
|
||||
(names "nomarchy.services."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# User-level `nomarchy.*` options — the full surface downstream users
|
||||
# configure in their home.nix. Kept small on purpose.
|
||||
{ lib, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
# One output's layout — turned into a Hyprland `monitor` rule in
|
||||
@@ -100,13 +100,13 @@ in
|
||||
# ── Preferences ────────────────────────────────────────────────
|
||||
terminal = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "ghostty";
|
||||
default = config.nomarchy.settings.terminal or "ghostty";
|
||||
description = "Terminal emulator command, used by keybinds and $TERMINAL.";
|
||||
};
|
||||
|
||||
keyboard.layout = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "us";
|
||||
default = config.nomarchy.settings.keyboard.layout or "us";
|
||||
example = "de";
|
||||
description = ''
|
||||
XKB layout for the Hyprland session. The console (and the LUKS
|
||||
@@ -224,7 +224,7 @@ in
|
||||
against upstream and — when Flatpak is enabled — counts Flatpak
|
||||
updates, surfacing a Waybar indicator + a notification when something
|
||||
is available. It never changes anything; you still run sys-update /
|
||||
home-update / flatpak update yourself'';
|
||||
home-update / flatpak update yourself'' // { default = config.nomarchy.settings.updates.enable or false; };
|
||||
|
||||
interval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
|
||||
@@ -557,6 +557,10 @@ ${themeRows}
|
||||
exec ${cfg.terminal} -e sh -c "nomarchy-doctor
|
||||
printf '\nEnter to close.'; read -r _" ;;
|
||||
|
||||
controlcenter)
|
||||
# Nomarchy TUI Control Center.
|
||||
exec ${cfg.terminal} -e nomarchy-control-center ;;
|
||||
|
||||
rollback)
|
||||
# Undo, one menu away (informative + rock-stable). Desktop =
|
||||
# Home Manager generations: theme/config history is already one
|
||||
@@ -650,6 +654,7 @@ ${themeRows}
|
||||
command -v nomarchy-snapshots >/dev/null 2>&1 && row "Snapshots" timeshift
|
||||
row "Rollback" edit-undo
|
||||
command -v nomarchy-doctor >/dev/null 2>&1 && row "Doctor" utilities-system-monitor
|
||||
command -v nomarchy-control-center >/dev/null 2>&1 && row "Control Center" preferences-desktop
|
||||
if [ -e "''${bats[0]}" ] && command -v powerprofilesctl >/dev/null 2>&1; then
|
||||
row "Power profile" preferences-system-power
|
||||
fi
|
||||
@@ -669,6 +674,7 @@ ${themeRows}
|
||||
*Snapshots*) exec "$0" snapshot ;;
|
||||
*Rollback*) exec "$0" rollback ;;
|
||||
*Doctor*) exec "$0" doctor ;;
|
||||
*"Control Center"*) exec "$0" controlcenter ;;
|
||||
*"Power profile"*) exec "$0" power-profile ;;
|
||||
esac ;;
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ let
|
||||
|
||||
modules-left = [ "hyprland/workspaces" "hyprland/window" ];
|
||||
modules-center = [ "clock" ];
|
||||
modules-right = [ "custom/recording" "idle_inhibitor" "tray" "custom/vpn" "pulseaudio" "cpu" "memory" "custom/powerprofile" "custom/nightlight" ]
|
||||
modules-right = [ "custom/recording" "idle_inhibitor" "tray" "custom/vpn" "pulseaudio" "custom/powerprofile" "custom/nightlight" ]
|
||||
++ lib.optional showLanguage "hyprland/language"
|
||||
++ [ "battery" "custom/doctor" "custom/updates" "custom/notification" ];
|
||||
|
||||
@@ -185,9 +185,6 @@ let
|
||||
# No network module: nm-applet lives in the tray (the GUI path), so the
|
||||
# bar's wifi/ethernet indicator would just duplicate it.
|
||||
|
||||
cpu.format = " {usage}%";
|
||||
memory.format = " {percentage}%";
|
||||
|
||||
battery = {
|
||||
states = { warning = 25; critical = 10; };
|
||||
format = "{icon} {capacity}%";
|
||||
@@ -333,7 +330,7 @@ let
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#tray, #pulseaudio, #cpu, #memory, #custom-powerprofile, #custom-nightlight, #custom-updates, #custom-vpn, #custom-recording, #idle_inhibitor, #language, #battery, #custom-doctor, #custom-notification {
|
||||
#tray, #pulseaudio, #custom-powerprofile, #custom-nightlight, #custom-updates, #custom-vpn, #custom-recording, #idle_inhibitor, #language, #battery, #custom-doctor, #custom-notification {
|
||||
color: alpha(@text, 0.85);
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
@@ -280,6 +280,7 @@ in
|
||||
environment.systemPackages = with pkgs; [
|
||||
nomarchy-theme-sync # provided by overlays.default
|
||||
nomarchy-doctor # read-only health check (System › Doctor)
|
||||
nomarchy-control-center # TUI control center
|
||||
|
||||
# Friendly wrappers for the two rebuild paths (README §3). Run as
|
||||
# your user: `nix flake update` must NOT run as root (libgit2
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Deliberately small: only things a downstream user plausibly disagrees
|
||||
# with get a toggle. Everything else in the system module is set with
|
||||
# lib.mkDefault, so plain NixOS options override it natively.
|
||||
{ lib, ... }:
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
options.nomarchy.system = {
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
greeter.autoLogin = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
default = config.nomarchy.settings.greeter.autoLogin or null;
|
||||
example = "ada";
|
||||
description = ''
|
||||
Log this user straight into Hyprland on boot (greetd
|
||||
@@ -44,7 +44,7 @@
|
||||
option'' // { default = true; };
|
||||
|
||||
audio.enable = lib.mkEnableOption "the Pipewire audio stack" // { default = true; };
|
||||
bluetooth.enable = lib.mkEnableOption "Bluetooth support with blueman" // { default = true; };
|
||||
bluetooth.enable = lib.mkEnableOption "Bluetooth support with blueman" // { default = config.nomarchy.settings.bluetooth.enable or true; };
|
||||
|
||||
autoTimezone.enable = lib.mkEnableOption ''
|
||||
automatic timezone detection (geoclue + automatic-timezoned): the
|
||||
@@ -102,7 +102,7 @@
|
||||
|
||||
batteryChargeLimit = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.ints.between 50 100);
|
||||
default = null;
|
||||
default = config.nomarchy.settings.power.batteryChargeLimit or null;
|
||||
example = 80;
|
||||
description = ''
|
||||
Stop charging at this percentage to extend battery lifespan,
|
||||
|
||||
@@ -77,7 +77,7 @@ in
|
||||
printing.enable = lib.mkEnableOption ''
|
||||
CUPS printing with Avahi/mDNS, so network printers are auto-discovered
|
||||
(add vendor drivers via `services.printing.drivers`); the menu's
|
||||
System ▸ Printers entry opens the system-config-printer GUI'';
|
||||
System ▸ Printers entry opens the system-config-printer GUI'' // { default = config.nomarchy.settings.printing.enable or false; };
|
||||
|
||||
openrgb.enable = lib.mkEnableOption ''
|
||||
the OpenRGB daemon and GUI for controlling RGB lighting on peripherals
|
||||
|
||||
7
pkgs/nomarchy-control-center/default.nix
Normal file
7
pkgs/nomarchy-control-center/default.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ writeShellApplication, coreutils, gawk, jq, gum }:
|
||||
|
||||
writeShellApplication {
|
||||
name = "nomarchy-control-center";
|
||||
runtimeInputs = [ coreutils gawk jq gum ];
|
||||
text = builtins.readFile ./nomarchy-control-center.sh;
|
||||
}
|
||||
235
pkgs/nomarchy-control-center/nomarchy-control-center.sh
Normal file
235
pkgs/nomarchy-control-center/nomarchy-control-center.sh
Normal file
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Nomarchy Control Center — TUI frontend over nomarchy-theme-sync and tools
|
||||
# Uses charmbracelet/gum for rendering.
|
||||
|
||||
trap 'exit 0' SIGINT
|
||||
|
||||
function get_state() {
|
||||
nomarchy-theme-sync get "$1" 2>/dev/null || echo ""
|
||||
}
|
||||
|
||||
function set_state() {
|
||||
nomarchy-theme-sync --quiet set "$1" "$2" --no-switch
|
||||
}
|
||||
|
||||
function first_boot() {
|
||||
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "Welcome to Nomarchy!"
|
||||
|
||||
echo "Pick a Theme Preset:"
|
||||
themes=$(nomarchy-theme-sync list)
|
||||
chosen_theme=$(printf "%s" "$themes" | gum choose)
|
||||
if [ -n "$chosen_theme" ]; then
|
||||
echo "Applying theme $chosen_theme..."
|
||||
nomarchy-theme-sync apply "$chosen_theme"
|
||||
fi
|
||||
|
||||
if gum confirm "Enable auto-commit for settings?"; then
|
||||
set_state "settings.autoCommit" "true"
|
||||
else
|
||||
set_state "settings.autoCommit" "false"
|
||||
fi
|
||||
|
||||
if command -v nomarchy-autotimezone >/dev/null 2>&1; then
|
||||
if gum confirm "Enable automatic timezone detection?"; then
|
||||
set_state "settings.autoTimezone" "true"
|
||||
else
|
||||
set_state "settings.autoTimezone" "false"
|
||||
fi
|
||||
fi
|
||||
|
||||
gum style --foreground 212 "First boot configuration complete!"
|
||||
echo "You can always change these later in the Control Center."
|
||||
read -r -n 1 -s -p "Press any key to exit..."
|
||||
echo
|
||||
}
|
||||
|
||||
function main_menu() {
|
||||
while true; do
|
||||
choice=$(gum choose "Appearance" "System Toggles" "Health (Doctor)" "Rollback" "Exit")
|
||||
case "$choice" in
|
||||
"Appearance") appearance_menu ;;
|
||||
"System Toggles") toggles_menu ;;
|
||||
"Health (Doctor)")
|
||||
if command -v nomarchy-doctor >/dev/null 2>&1; then
|
||||
nomarchy-doctor || true
|
||||
else
|
||||
echo "nomarchy-doctor not found."
|
||||
fi
|
||||
echo
|
||||
read -r -n 1 -s -p "Press any key to return..."
|
||||
echo
|
||||
;;
|
||||
"Rollback")
|
||||
gens=$(home-manager generations 2>/dev/null | head -10)
|
||||
if [ -z "$gens" ]; then
|
||||
echo "No Home Manager generations found."
|
||||
else
|
||||
printf "%s\n" "$gens" | awk '{ printf "Desktop gen %s — %s %s%s\n", $5, $1, $2, (NR==1 ? " (current)" : "") }' > /tmp/nomarchy-gens
|
||||
sel=$(gum choose < /tmp/nomarchy-gens || true)
|
||||
if [ -n "$sel" ]; then
|
||||
num=${sel#Desktop gen }
|
||||
num=${num%% *}
|
||||
path=$(printf "%s\n" "$gens" | awk -v n="$num" '$5 == n { print $7 }')
|
||||
if [ -x "$path/activate" ]; then
|
||||
echo "Activating Home Manager generation $num..."
|
||||
"$path/activate"
|
||||
echo "Desktop rolled back to generation $num."
|
||||
else
|
||||
echo "Generation $num not found."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo
|
||||
read -r -n 1 -s -p "Press any key to return..."
|
||||
echo
|
||||
;;
|
||||
"Exit"|*) break ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
function appearance_menu() {
|
||||
while true; do
|
||||
choice=$(gum choose "Pick Theme" "Toggle Blur" "Set Gaps" "Back")
|
||||
case "$choice" in
|
||||
"Pick Theme")
|
||||
themes=$(nomarchy-theme-sync list)
|
||||
chosen=$(printf "%s" "$themes" | gum choose)
|
||||
if [ -n "$chosen" ]; then
|
||||
nomarchy-theme-sync apply "$chosen"
|
||||
fi
|
||||
;;
|
||||
"Toggle Blur")
|
||||
blur=$(get_state "ui.blur")
|
||||
if [ "$blur" = "true" ]; then
|
||||
set_state "ui.blur" "false"
|
||||
else
|
||||
set_state "ui.blur" "true"
|
||||
fi
|
||||
;;
|
||||
"Set Gaps")
|
||||
gaps=$(gum input --prompt "Enter gaps in pixels: " --placeholder "$(get_state ui.gapsOut)")
|
||||
if [ -n "$gaps" ]; then
|
||||
set_state "ui.gapsOut" "$gaps"
|
||||
fi
|
||||
;;
|
||||
"Back"|*) break ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
function toggles_menu() {
|
||||
while true; do
|
||||
choice=$(gum choose "Auto-commit" "Auto-timezone" "Night Light" "Updates" "Battery Limit" "Bluetooth" "Printing" "Terminal" "Keyboard Layout" "Auto-Login" "Back")
|
||||
case "$choice" in
|
||||
"Auto-commit")
|
||||
cur=$(get_state "settings.autoCommit")
|
||||
if [ "$cur" = "true" ]; then
|
||||
set_state "settings.autoCommit" "false"
|
||||
echo "Auto-commit disabled."
|
||||
else
|
||||
set_state "settings.autoCommit" "true"
|
||||
echo "Auto-commit enabled."
|
||||
fi
|
||||
sleep 1
|
||||
;;
|
||||
"Auto-timezone")
|
||||
cur=$(get_state "settings.autoTimezone")
|
||||
if [ "$cur" = "true" ]; then
|
||||
set_state "settings.autoTimezone" "false"
|
||||
echo "Auto-timezone disabled."
|
||||
else
|
||||
set_state "settings.autoTimezone" "true"
|
||||
echo "Auto-timezone enabled."
|
||||
fi
|
||||
sleep 1
|
||||
;;
|
||||
"Night Light")
|
||||
if command -v nomarchy-nightlight >/dev/null 2>&1; then
|
||||
nomarchy-nightlight toggle
|
||||
sleep 1
|
||||
else
|
||||
echo "nomarchy-nightlight not found."
|
||||
sleep 1
|
||||
fi
|
||||
;;
|
||||
"Updates")
|
||||
cur=$(get_state "settings.updates.enable")
|
||||
if [ "$cur" = "true" ]; then
|
||||
set_state "settings.updates.enable" "false"
|
||||
echo "Updates checker disabled (requires rebuild)."
|
||||
else
|
||||
set_state "settings.updates.enable" "true"
|
||||
echo "Updates checker enabled (requires rebuild)."
|
||||
fi
|
||||
sleep 1
|
||||
;;
|
||||
"Battery Limit")
|
||||
limit=$(gum input --prompt "Enter battery charge limit % (or empty for default): " --placeholder "$(get_state settings.power.batteryChargeLimit)")
|
||||
if [ -n "$limit" ]; then
|
||||
set_state "settings.power.batteryChargeLimit" "$limit"
|
||||
else
|
||||
set_state "settings.power.batteryChargeLimit" "null"
|
||||
fi
|
||||
;;
|
||||
"Bluetooth")
|
||||
cur=$(get_state "settings.bluetooth.enable")
|
||||
if [ "$cur" = "true" ]; then
|
||||
set_state "settings.bluetooth.enable" "false"
|
||||
echo "Bluetooth disabled (requires rebuild)."
|
||||
else
|
||||
set_state "settings.bluetooth.enable" "true"
|
||||
echo "Bluetooth enabled (requires rebuild)."
|
||||
fi
|
||||
sleep 1
|
||||
;;
|
||||
"Printing")
|
||||
cur=$(get_state "settings.printing.enable")
|
||||
if [ "$cur" = "true" ]; then
|
||||
set_state "settings.printing.enable" "false"
|
||||
echo "Printing services disabled (requires rebuild)."
|
||||
else
|
||||
set_state "settings.printing.enable" "true"
|
||||
echo "Printing services enabled (requires rebuild)."
|
||||
fi
|
||||
sleep 1
|
||||
;;
|
||||
"Terminal")
|
||||
term=$(gum choose "ghostty" "kitty" "alacritty" "wezterm" "foot")
|
||||
if [ -n "$term" ]; then
|
||||
set_state "settings.terminal" "\"$term\""
|
||||
echo "Terminal set to $term (requires rebuild)."
|
||||
fi
|
||||
sleep 1
|
||||
;;
|
||||
"Keyboard Layout")
|
||||
layout=$(gum input --prompt "Enter keyboard layout (e.g. us, de, es): " --placeholder "$(get_state settings.keyboard.layout | tr -d '"')")
|
||||
if [ -n "$layout" ]; then
|
||||
set_state "settings.keyboard.layout" "\"$layout\""
|
||||
echo "Keyboard layout set to $layout (requires rebuild)."
|
||||
fi
|
||||
sleep 1
|
||||
;;
|
||||
"Auto-Login")
|
||||
user=$(gum input --prompt "Enter auto-login username (or empty to disable): " --placeholder "$(get_state settings.greeter.autoLogin | tr -d '"')")
|
||||
if [ -n "$user" ]; then
|
||||
set_state "settings.greeter.autoLogin" "\"$user\""
|
||||
echo "Auto-login set to $user (requires rebuild)."
|
||||
else
|
||||
set_state "settings.greeter.autoLogin" "null"
|
||||
echo "Auto-login disabled (requires rebuild)."
|
||||
fi
|
||||
sleep 1
|
||||
;;
|
||||
"Back"|*) break ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
if [ "${1:-}" = "--first-boot" ]; then
|
||||
first_boot
|
||||
else
|
||||
main_menu
|
||||
fi
|
||||
43
themes/executive-slate.json
Normal file
43
themes/executive-slate.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"version": 1,
|
||||
"name": "Executive Slate",
|
||||
"slug": "executive-slate",
|
||||
"mode": "dark",
|
||||
"wallpaper": "",
|
||||
"colors": {
|
||||
"base": "#1A1D24",
|
||||
"mantle": "#14161C",
|
||||
"surface": "#232731",
|
||||
"overlay": "#333947",
|
||||
"text": "#D4DAE8",
|
||||
"subtext": "#8792A6",
|
||||
"muted": "#525A6E",
|
||||
"accent": "#4D78CC",
|
||||
"accentAlt": "#6C92D9",
|
||||
"good": "#68A06B",
|
||||
"warn": "#D19C4C",
|
||||
"bad": "#C95F65"
|
||||
},
|
||||
"border": {
|
||||
"active": "accent",
|
||||
"inactive": "overlay"
|
||||
},
|
||||
"ansi": [
|
||||
"#232731",
|
||||
"#C95F65",
|
||||
"#68A06B",
|
||||
"#D19C4C",
|
||||
"#4D78CC",
|
||||
"#836CC9",
|
||||
"#4C99A0",
|
||||
"#D4DAE8",
|
||||
"#525A6E",
|
||||
"#D67177",
|
||||
"#7BB57F",
|
||||
"#E0AF5E",
|
||||
"#6C92D9",
|
||||
"#9A84E0",
|
||||
"#5FABB3",
|
||||
"#FFFFFF"
|
||||
]
|
||||
}
|
||||
BIN
themes/executive-slate/backgrounds/wallpaper.png
Normal file
BIN
themes/executive-slate/backgrounds/wallpaper.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 661 KiB |
79
themes/executive-slate/rofi.rasi
Normal file
79
themes/executive-slate/rofi.rasi
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Executive Slate Rofi Theme
|
||||
* Clean, flat, functional, professional.
|
||||
*/
|
||||
|
||||
* {
|
||||
background-color: transparent;
|
||||
text-color: var(text, #D4DAE8);
|
||||
font: "Inter 13";
|
||||
}
|
||||
|
||||
window {
|
||||
width: 600px;
|
||||
background-color: var(base, #1A1D24);
|
||||
border: 1px solid var(overlay, #333947);
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
mainbox {
|
||||
spacing: 12px;
|
||||
}
|
||||
|
||||
inputbar {
|
||||
background-color: var(surface, #232731);
|
||||
border: 1px solid var(overlay, #333947);
|
||||
border-radius: 4px;
|
||||
padding: 10px 14px;
|
||||
spacing: 10px;
|
||||
children: [ prompt, entry ];
|
||||
}
|
||||
|
||||
prompt {
|
||||
text-color: var(accent, #4D78CC);
|
||||
}
|
||||
|
||||
entry {
|
||||
placeholder: "Type to filter...";
|
||||
placeholder-color: var(subtext, #8792A6);
|
||||
}
|
||||
|
||||
listview {
|
||||
lines: 7;
|
||||
spacing: 4px;
|
||||
scrollbar: false;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
element {
|
||||
padding: 8px 14px;
|
||||
border-radius: 4px;
|
||||
spacing: 12px;
|
||||
}
|
||||
|
||||
element normal.normal, element alternate.normal {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* Functional highlight: solid surface color with a subtle accent edge */
|
||||
element selected.normal {
|
||||
background-color: var(surface, #232731);
|
||||
text-color: var(text, #D4DAE8);
|
||||
border: 0 0 0 4px solid;
|
||||
border-color: var(accent, #4D78CC);
|
||||
}
|
||||
|
||||
element-icon {
|
||||
size: 24px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
element-text {
|
||||
background-color: transparent;
|
||||
vertical-align: 0.5;
|
||||
}
|
||||
|
||||
element-text selected {
|
||||
text-color: var(text, #D4DAE8);
|
||||
}
|
||||
88
themes/executive-slate/waybar.css
Normal file
88
themes/executive-slate/waybar.css
Normal file
@@ -0,0 +1,88 @@
|
||||
/* Executive Slate Waybar — Solid, functional, professional */
|
||||
|
||||
* {
|
||||
font-family: "Inter", "Symbols Nerd Font", sans-serif;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
window#waybar {
|
||||
background: @base;
|
||||
border-bottom: 1px solid @mantle;
|
||||
color: @text;
|
||||
}
|
||||
|
||||
/* Tightly packed modules for a functional feel */
|
||||
.modules-left,
|
||||
.modules-center,
|
||||
.modules-right {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#workspaces button,
|
||||
#window,
|
||||
#clock,
|
||||
#tray,
|
||||
#pulseaudio,
|
||||
#battery,
|
||||
#custom-notification,
|
||||
#custom-vpn,
|
||||
#custom-powerprofile,
|
||||
#custom-updates,
|
||||
#custom-doctor {
|
||||
padding: 0 10px;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* Subtle hover effects */
|
||||
#workspaces button {
|
||||
color: @subtext;
|
||||
transition: all 0.2s ease-in-out;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
#workspaces button:hover {
|
||||
background: @surface;
|
||||
color: @text;
|
||||
}
|
||||
|
||||
/* Active gets a strong underline instead of a glowing background */
|
||||
#workspaces button.active {
|
||||
color: @text;
|
||||
background: @surface;
|
||||
border-bottom: 2px solid @accent;
|
||||
}
|
||||
|
||||
#workspaces button.urgent {
|
||||
color: @bad;
|
||||
border-bottom: 2px solid @bad;
|
||||
}
|
||||
|
||||
/* Minimal indicators */
|
||||
#battery.charging { color: @good; }
|
||||
#battery.warning:not(.charging) { color: @warn; }
|
||||
#battery.critical:not(.charging) {
|
||||
color: @bad;
|
||||
background: @surface;
|
||||
border-bottom: 2px solid @bad;
|
||||
}
|
||||
|
||||
#pulseaudio.muted { color: @muted; }
|
||||
#custom-updates { color: @accentAlt; }
|
||||
#custom-doctor { color: @bad; }
|
||||
#custom-vpn { color: @accent; }
|
||||
|
||||
/* Functional tooltip */
|
||||
tooltip {
|
||||
background: @base;
|
||||
border: 1px solid @overlay;
|
||||
border-radius: 4px;
|
||||
}
|
||||
tooltip label {
|
||||
color: @text;
|
||||
}
|
||||
43
themes/neon-glass.json
Normal file
43
themes/neon-glass.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"version": 1,
|
||||
"name": "Neon Glass",
|
||||
"slug": "neon-glass",
|
||||
"mode": "dark",
|
||||
"wallpaper": "",
|
||||
"colors": {
|
||||
"base": "#0B0E14",
|
||||
"mantle": "#07090D",
|
||||
"surface": "#151A22",
|
||||
"overlay": "#1E2530",
|
||||
"text": "#E0E6F0",
|
||||
"subtext": "#8F9BB3",
|
||||
"muted": "#4B566B",
|
||||
"accent": "#00F0FF",
|
||||
"accentAlt": "#B026FF",
|
||||
"good": "#00FFA3",
|
||||
"warn": "#FFD000",
|
||||
"bad": "#FF003C"
|
||||
},
|
||||
"border": {
|
||||
"active": "accent",
|
||||
"inactive": "overlay"
|
||||
},
|
||||
"ansi": [
|
||||
"#151A22",
|
||||
"#FF003C",
|
||||
"#00FFA3",
|
||||
"#FFD000",
|
||||
"#00F0FF",
|
||||
"#B026FF",
|
||||
"#00E5FF",
|
||||
"#E0E6F0",
|
||||
"#4B566B",
|
||||
"#FF3366",
|
||||
"#33FFB8",
|
||||
"#FFE033",
|
||||
"#33F3FF",
|
||||
"#C44DFF",
|
||||
"#33EBFF",
|
||||
"#FFFFFF"
|
||||
]
|
||||
}
|
||||
BIN
themes/neon-glass/backgrounds/wallpaper.png
Normal file
BIN
themes/neon-glass/backgrounds/wallpaper.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 702 KiB |
82
themes/neon-glass/rofi.rasi
Normal file
82
themes/neon-glass/rofi.rasi
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Neon Glass Rofi Theme
|
||||
* Glassmorphic, transparent, blurred background with glowing accents.
|
||||
*/
|
||||
|
||||
* {
|
||||
/* Using standard theme palette via env variables injected by home-manager,
|
||||
or fallback if testing independently. The whole-swap still gets the
|
||||
colors injected into the RASI by the module! */
|
||||
background-color: transparent;
|
||||
text-color: var(text, #E0E6F0);
|
||||
font: "Inter 13";
|
||||
}
|
||||
|
||||
window {
|
||||
width: 600px;
|
||||
/* transparent base with slight tint */
|
||||
background-color: rgba(11, 14, 20, 0.45);
|
||||
border: 1px solid rgba(0, 240, 255, 0.3);
|
||||
border-radius: 24px;
|
||||
padding: 24px;
|
||||
/* Blur would be applied via hyprland layerrule for rofi */
|
||||
}
|
||||
|
||||
mainbox {
|
||||
spacing: 16px;
|
||||
}
|
||||
|
||||
inputbar {
|
||||
background-color: rgba(21, 26, 34, 0.5);
|
||||
border: 1px solid rgba(0, 240, 255, 0.5);
|
||||
border-radius: 12px;
|
||||
padding: 12px 16px;
|
||||
spacing: 12px;
|
||||
children: [ prompt, entry ];
|
||||
}
|
||||
|
||||
prompt {
|
||||
text-color: var(accent, #00F0FF);
|
||||
}
|
||||
|
||||
entry {
|
||||
placeholder: "Search...";
|
||||
placeholder-color: var(subtext, #8F9BB3);
|
||||
}
|
||||
|
||||
listview {
|
||||
lines: 7;
|
||||
spacing: 8px;
|
||||
scrollbar: false;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
element {
|
||||
padding: 10px 16px;
|
||||
border-radius: 12px;
|
||||
spacing: 12px;
|
||||
}
|
||||
|
||||
element normal.normal, element alternate.normal {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
element selected.normal {
|
||||
background-color: rgba(0, 240, 255, 0.15);
|
||||
border: 1px solid rgba(0, 240, 255, 0.4);
|
||||
text-color: var(accent, #00F0FF);
|
||||
}
|
||||
|
||||
element-icon {
|
||||
size: 24px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
element-text {
|
||||
background-color: transparent;
|
||||
vertical-align: 0.5;
|
||||
}
|
||||
|
||||
element-text selected {
|
||||
text-color: var(accent, #00F0FF);
|
||||
}
|
||||
108
themes/neon-glass/waybar.css
Normal file
108
themes/neon-glass/waybar.css
Normal file
@@ -0,0 +1,108 @@
|
||||
/* Neon Glass Waybar — Segmented floating pills with glassmorphism */
|
||||
|
||||
* {
|
||||
font-family: "Inter", "Symbols Nerd Font", sans-serif;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
window#waybar {
|
||||
/* The main bar background is transparent so the wallpaper shows through */
|
||||
background: transparent;
|
||||
color: @text;
|
||||
}
|
||||
|
||||
/*
|
||||
* The pill containers: left, center, right.
|
||||
* Glassmorphism: semi-transparent base + blur (blur requires hyprland layerrule if waybar doesn't natively blur, but alpha base helps).
|
||||
*/
|
||||
.modules-left,
|
||||
.modules-center,
|
||||
.modules-right {
|
||||
background: alpha(@base, 0.45);
|
||||
border: 1px solid alpha(@accent, 0.2);
|
||||
border-radius: 20px;
|
||||
margin: 4px 6px;
|
||||
padding: 2px 8px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Add a glowing top border effect on hover or generally to accent the glass */
|
||||
.modules-left {
|
||||
border-top: 1px solid alpha(@accent, 0.6);
|
||||
}
|
||||
.modules-center {
|
||||
border-top: 1px solid alpha(@text, 0.3);
|
||||
}
|
||||
.modules-right {
|
||||
border-top: 1px solid alpha(@accentAlt, 0.6);
|
||||
}
|
||||
|
||||
/* Remove default padding from individual modules so they fit snug in the pill */
|
||||
#workspaces button,
|
||||
#window,
|
||||
#clock,
|
||||
#tray,
|
||||
#pulseaudio,
|
||||
#battery,
|
||||
#custom-notification,
|
||||
#custom-vpn,
|
||||
#custom-powerprofile,
|
||||
#custom-updates,
|
||||
#custom-doctor {
|
||||
padding: 0 8px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
/* Workspaces */
|
||||
#workspaces button {
|
||||
color: @subtext;
|
||||
border-radius: 12px;
|
||||
transition: all 0.2s cubic-bezier(0.25, 1, 0.5, 1);
|
||||
}
|
||||
|
||||
#workspaces button:hover {
|
||||
background: alpha(@surface, 0.5);
|
||||
color: @text;
|
||||
}
|
||||
|
||||
#workspaces button.active {
|
||||
color: @accent;
|
||||
background: alpha(@accent, 0.15);
|
||||
box-shadow: 0 0 8px alpha(@accent, 0.4);
|
||||
}
|
||||
|
||||
#workspaces button.urgent {
|
||||
color: @bad;
|
||||
background: alpha(@bad, 0.15);
|
||||
}
|
||||
|
||||
/* Indicators */
|
||||
#battery.charging { color: @good; }
|
||||
#battery.warning:not(.charging) { color: @warn; }
|
||||
#battery.critical:not(.charging) {
|
||||
color: @bad;
|
||||
animation: blink 1s steps(2, start) infinite;
|
||||
}
|
||||
|
||||
#pulseaudio.muted { color: @muted; }
|
||||
|
||||
#custom-updates { color: @accentAlt; }
|
||||
#custom-doctor { color: @bad; }
|
||||
#custom-vpn { color: @accent; }
|
||||
|
||||
@keyframes blink {
|
||||
to { color: @text; }
|
||||
}
|
||||
|
||||
tooltip {
|
||||
background: alpha(@base, 0.85);
|
||||
border: 1px solid alpha(@accent, 0.4);
|
||||
border-radius: 12px;
|
||||
}
|
||||
tooltip label {
|
||||
color: @text;
|
||||
}
|
||||
Reference in New Issue
Block a user