feat(waybar): open a calendar (calcurse) on the clock click
All checks were successful
Check / eval (push) Successful in 2m54s
All checks were successful
Check / eval (push) Successful in 2m54s
Item 42, de-scoped by Bernardo to app-only — no account sync (the user configures that themselves locally). Clicking the Waybar date/clock now runs nomarchy-calendar → calcurse in a floating, centered ghostty window tagged --class=com.nomarchy.calendar (+ --gtk-single-instance=false for a fresh standalone window), matched by a float+size+center windowrule. The launcher self-gates on calcurse. Dropped the clock's format-alt date toggle (conflicts with on-click) and moved the long date into the tooltip. Parity: on-click added to all four whole-swap jsoncs. Ships calcurse + pwvucontrol uncommented in the downstream template (opt-out). Enforces ghostty always installed (ghostty.nix: enable = true unconditional; nomarchy.ghostty.enable now gates only the theming/config) so the --class launcher can rely on it. Verified: V0 green; four jsoncs valid JSON; V1 HM built — launcher ships, generated clock renders on-click=nomarchy-calendar (format-alt gone, date in tooltip), hyprland has the 3 calendar windowrules, ghostty in the HM profile. Click→float→calcurse month view is V3 (queued). Sync is deliberately the user's own config, not a distro feature. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -252,55 +252,6 @@ Next slice: on hardware, run `hyprctl clients` while each is open, read
|
||||
the real `class`, then append rules. Also revisit whether blueman/s-c-p
|
||||
actually float once seen (regex tolerance for the `.…-wrapped` form).
|
||||
|
||||
### 42. System calendar app synced to the user's accounts `[big]`
|
||||
(Raised by Bernardo, 2026-07-08.) Clicking the Waybar **date/clock**
|
||||
module should open a calendar that shows the user's real events, synced
|
||||
from their calendar accounts (CalDAV / Google / Nextcloud / iCloud). Hard
|
||||
requirement: it must open **instantly** on click — no Thunderbird/Evolution
|
||||
multi-second cold start.
|
||||
|
||||
_Investigation (2026-07-08 — Bernardo suggested calcurse; asked for the
|
||||
best approach):_ the winning shape is **split sync from display** — a sync
|
||||
daemon fills a local store, a fast local viewer reads it instantly.
|
||||
- **Recommended (most Nomarchy-native): `khal` (TUI) in a floating ghostty
|
||||
window + `vdirsyncer` for sync.** khal reads a local vdir instantly →
|
||||
opens immediately; running it in ghostty means it **themes for free** off
|
||||
the palette (pillar 4, zero new theming surface) and slots into the
|
||||
float+center windowrule pattern (item 41). vdirsyncer is the de-facto
|
||||
CalDAV→local-ics sync (Nextcloud/Fastmail/iCloud with an app password are
|
||||
frictionless). Configs are file-based → in-flake friendly.
|
||||
- **calcurse (Bernardo's pick):** viable, instant TUI, single self-contained
|
||||
tool — but it's *local-first*; `calcurse-caldav` multi-account/Google sync
|
||||
is clunkier than vdirsyncer. Fine if a one-tool solution is preferred over
|
||||
sync robustness.
|
||||
- **GNOME Calendar + GNOME Online Accounts:** the GUI path with the *best*
|
||||
Google onboarding (GOA handles OAuth cleanly), themes via GTK — but it's
|
||||
heavier and pulls evolution-data-server + GOA, and first-open is **not
|
||||
instant**, so it fails the core requirement. Fallback only if easy account
|
||||
setup outweighs instant-open. (`gcalcli` = Google-only, not general.)
|
||||
|
||||
_Two real wrinkles to design around:_
|
||||
1. **Credentials are secrets** — account passwords / OAuth tokens can't live
|
||||
in the git-tracked flake, so this is the one legitimate exception to
|
||||
"no state outside the checkout" (see [[in-flake-state-philosophy]]).
|
||||
Decide: a plain runtime path (`~/.config`, documented exception) vs
|
||||
sops/agenix encrypted-in-flake.
|
||||
2. **Google OAuth friction** — vdirsyncer needs a *self-registered*
|
||||
`client_id`/`client_secret` (shipping one violates Google ToS). CalDAV
|
||||
app-password providers are painless; Google is the sharp edge. GOA
|
||||
sidesteps it but only on the heavy GUI path.
|
||||
|
||||
_Slices (split before starting):_ (a) `[human]` pick the tool
|
||||
(recommend khal+vdirsyncer; calcurse acceptable), then ship the viewer
|
||||
bound to the clock `on-click` — launch it in a ghostty window with a
|
||||
distinct `--class` so a float+center windowrule can target it; move the
|
||||
current time↔date `format-alt` toggle to `on-click-right`/scroll; parity
|
||||
across the four whole-swap jsoncs. Local-only first (an .ics on disk).
|
||||
(b) add vdirsyncer + a sync systemd timer (like the update checker) + a
|
||||
menu writer for accounts, resolving the secrets decision above. (c) optional
|
||||
polish: upcoming events in the clock **tooltip** via a khal-backed script
|
||||
(hover = next events, click = full calendar).
|
||||
|
||||
## LATER
|
||||
|
||||
- **Wallpapers artifact split** (ROADMAP § Faster switches — decided,
|
||||
|
||||
@@ -293,6 +293,17 @@ QA machine), the **T14s** (webcam case).
|
||||
night, executive-slate, boreal) behave the same and their shutdown
|
||||
power-button (if present) still opens the lock/logout menu.
|
||||
|
||||
- [ ] **Calendar on the clock click** (iteration #68, item 42) — after
|
||||
`home-update` + relogin: left-click the Waybar date/clock → calcurse
|
||||
opens in a **floating, centered** ghostty window (~60×65% of screen),
|
||||
showing the month calendar; closing calcurse (`q`) closes the window.
|
||||
The `--class=com.nomarchy.calendar` must match the windowrule (if it
|
||||
tiles, run `hyprctl clients` while open and check the real app-id).
|
||||
Hover the clock → tooltip shows the long date + zone + month grid.
|
||||
Same on a whole-swap bar (summer/boreal/executive-slate). If calcurse
|
||||
was removed from home.packages, the click toasts "calcurse isn't
|
||||
installed" instead of doing nothing.
|
||||
|
||||
## AMD dev box only
|
||||
- [ ] **AMD runtime bits** — VA-API (`vainfo` → radeonsi), amd-pstate EPP
|
||||
active and PPD switching governors; opt-ins: ROCm (`rocminfo`, a GPU
|
||||
|
||||
@@ -17,6 +17,35 @@ Template:
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-08 — Calendar on the clock click (iteration #68, item 42)
|
||||
- **Task:** item 42, de-scoped live by Bernardo — DON'T hook up calendar
|
||||
accounts; just ship a lightweight calendar that opens instantly on the
|
||||
Waybar date click, user configures sync themselves. calcurse (his pick;
|
||||
now the right one since it's self-contained for the user's own sync).
|
||||
- **Did:** new `nomarchy-calendar` launcher (waybar.nix) → calcurse in a
|
||||
ghostty window tagged `--class=com.nomarchy.calendar` +
|
||||
`--gtk-single-instance=false` (fresh standalone window); self-gates on
|
||||
calcurse. Clock `on-click = nomarchy-calendar`, dropped the format-alt
|
||||
date-toggle (conflicts with on-click), moved the long date into the
|
||||
tooltip. Parity: on-click in all four whole-swap jsoncs. windowrule
|
||||
float+size(60/65%)+center on the class (hyprland.nix). Shipped calcurse
|
||||
+ pwvucontrol **uncommented** in the downstream template (opt-out).
|
||||
Enforced **ghostty always installed** (ghostty.nix: `enable = true`
|
||||
unconditional, the nomarchy.ghostty.enable option now gates only config)
|
||||
so the launcher can rely on `--class`.
|
||||
- **Verified:** V0 green; all four jsoncs valid JSON; V1 HM built — launcher
|
||||
ships the right command, generated clock renders `on-click:
|
||||
nomarchy-calendar` with format-alt gone + date in the tooltip, hyprland
|
||||
has the 3 calendar windowrules, ghostty present in the HM profile.
|
||||
- **Pending:** V3 — click the clock → calcurse floats centered (the
|
||||
`--class`→windowrule match) and renders its month view; verify on a real
|
||||
session (queued). Sync is deliberately the user's own local config, NOT
|
||||
a distro feature (Bernardo's call) — a future iteration should not
|
||||
re-propose account sync.
|
||||
- **Next suggestion:** Bernardo's big new task — investigate whether THIS
|
||||
machine (NixOS 25.11) can migrate to Nomarchy without a reinstall,
|
||||
keeping all files, and plan it.
|
||||
|
||||
## 2026-07-08 — Combined power menu on the bar icons (iteration #67, item 36b)
|
||||
- **Task:** BACKLOG item 36(b), now unblocked. Bernardo's calls: keep the
|
||||
granular System ▸ Battery limit / Power profile rows; build ONE combined
|
||||
|
||||
@@ -8,11 +8,16 @@ let
|
||||
c = t.colors;
|
||||
in
|
||||
{
|
||||
programs.ghostty = lib.mkIf config.nomarchy.ghostty.enable {
|
||||
# Ghostty is ALWAYS installed — it's Nomarchy's default terminal and is
|
||||
# load-bearing (SUPER+E file manager, the calendar launcher's classed
|
||||
# window, etc.), so the distro enforces it. `nomarchy.ghostty.enable` now
|
||||
# gates only whether Nomarchy's theming/config is applied — a user can
|
||||
# keep ghostty but drop our config, they just can't remove ghostty itself.
|
||||
programs.ghostty = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
|
||||
settings = {
|
||||
settings = lib.mkIf config.nomarchy.ghostty.enable {
|
||||
# ── Typography (from theme-state.json) ────────────────────────
|
||||
font-family = t.fonts.mono;
|
||||
font-size = t.fonts.size;
|
||||
|
||||
@@ -458,6 +458,13 @@ in
|
||||
# Bluetooth manager (blueman) + CUPS printer admin.
|
||||
"float, class:(?i)^(\\.?blueman-(manager|adapters)(-wrapped)?|\\.?system-config-printer(-wrapped)?)$"
|
||||
"center, class:(?i)^(\\.?blueman-(manager|adapters)(-wrapped)?|\\.?system-config-printer(-wrapped)?)$"
|
||||
|
||||
# Calendar popup (item 42): the Waybar clock's on-click runs
|
||||
# nomarchy-calendar → calcurse in a ghostty window tagged with a
|
||||
# distinct --class, so it floats centered instead of tiling.
|
||||
"float, class:^(com\\.nomarchy\\.calendar)$"
|
||||
"size 60% 65%, class:^(com\\.nomarchy\\.calendar)$"
|
||||
"center, class:^(com\\.nomarchy\\.calendar)$"
|
||||
];
|
||||
|
||||
# Rendered from ./keybinds.nix (the cheatsheet reads the same list),
|
||||
|
||||
@@ -82,6 +82,22 @@ let
|
||||
[ -n "$next" ] && powerprofilesctl set "$next"
|
||||
'';
|
||||
|
||||
# Opens calcurse (a lightweight TUI calendar, month view by default) in a
|
||||
# floating, centered ghostty window — bound to the Waybar clock's on-click.
|
||||
# A distinct --class gives the window a matchable app-id for the
|
||||
# float+center+size windowrule (hyprland.nix); --gtk-single-instance=false
|
||||
# forces a fresh standalone window (ghostty defaults single-instance on).
|
||||
# calcurse ships uncommented in the downstream template (opt-out), so
|
||||
# self-gate with a helpful notify if it's been removed. ghostty is always
|
||||
# installed (ghostty.nix), so it can be relied on for the --class window.
|
||||
calendarLauncher = pkgs.writeShellScriptBin "nomarchy-calendar" ''
|
||||
if ! command -v calcurse >/dev/null 2>&1; then
|
||||
notify-send "Calendar" "calcurse isn't installed (removed from home.packages?)." 2>/dev/null
|
||||
exit 0
|
||||
fi
|
||||
exec ghostty --class=com.nomarchy.calendar --gtk-single-instance=false -e calcurse
|
||||
'';
|
||||
|
||||
# VPN indicator — shows a shield when a NetworkManager VPN/WireGuard
|
||||
# connection is active OR Tailscale is up; prints nothing otherwise so the
|
||||
# module self-hides (like nightlight/updates). Click opens the VPN submenu.
|
||||
@@ -154,10 +170,13 @@ let
|
||||
|
||||
clock = {
|
||||
format = "{:%H:%M}";
|
||||
format-alt = "{:%A %d %B %Y}";
|
||||
# Zone line first (LATER nicety): under auto-timezone the tz-watch
|
||||
# SIGUSR2 reload keeps it showing the currently *detected* zone.
|
||||
tooltip-format = "{:%Z (UTC%z)}\n<tt><small>{calendar}</small></tt>";
|
||||
# Left-click → the calendar (nomarchy-calendar → calcurse in a floating
|
||||
# ghostty). Replaces the old format-alt date toggle; the long date now
|
||||
# rides in the tooltip's first line, so nothing is lost on hover.
|
||||
on-click = "nomarchy-calendar";
|
||||
# The zone line stays live under auto-timezone (the tz-watch SIGUSR2
|
||||
# reload keeps it showing the currently *detected* zone).
|
||||
tooltip-format = "{:%A %d %B %Y}\n{:%Z (UTC%z)}\n<tt><small>{calendar}</small></tt>";
|
||||
};
|
||||
|
||||
# Active keyboard layout (per focused device) — only placed in
|
||||
@@ -431,5 +450,5 @@ in
|
||||
# whole-swap themes' static waybar.jsonc can exec them by name — plus
|
||||
# the supervisor hyprland.nix exec-onces.
|
||||
home.packages = lib.optionals config.nomarchy.waybar.enable
|
||||
[ waybarSupervisor powerProfileStatus powerProfileCycle vpnStatus doctorStatus ];
|
||||
[ waybarSupervisor powerProfileStatus powerProfileCycle vpnStatus doctorStatus calendarLauncher ];
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
mpv # media player
|
||||
amberol # music player (local library; streaming → spotify below)
|
||||
pwvucontrol # PipeWire volume mixer (right-click the Waybar volume)
|
||||
calcurse # TUI calendar — click the Waybar clock to open it
|
||||
|
||||
# ── More apps — uncomment to add ─────────────────────────────────
|
||||
# Web browsers
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
},
|
||||
"clock": {
|
||||
"format": "{:%H:%M}",
|
||||
"on-click": "nomarchy-calendar",
|
||||
"tooltip": true,
|
||||
"tooltip-format": "{:%Z (UTC%z)}\n<tt><small>{calendar}</small></tt>"
|
||||
},
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
},
|
||||
"clock": {
|
||||
"format": "{:%H:%M}",
|
||||
"on-click": "nomarchy-calendar",
|
||||
"tooltip": true,
|
||||
"tooltip-format": "{:%Z (UTC%z)}\n<tt><small>{calendar}</small></tt>"
|
||||
},
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
|
||||
"clock": {
|
||||
"format": " {:%H:%M}",
|
||||
"on-click": "nomarchy-calendar",
|
||||
"tooltip": true,
|
||||
"tooltip-format": "{:%Z (UTC%z)}\n<tt><small>{calendar}</small></tt>"
|
||||
},
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
|
||||
"clock": {
|
||||
"format": " {:%H:%M}",
|
||||
"on-click": "nomarchy-calendar",
|
||||
"tooltip": true,
|
||||
"tooltip-format": "{:%Z (UTC%z)}\n<tt><small>{calendar}</small></tt>"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user