diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-17 09:22:59 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-17 09:22:59 +0200 |
| commit | b51d1efa913933cb272b7c1906340981f00010c8 (patch) | |
| tree | d3df8647fbb295cb575142fd7125511a795c9646 | |
| parent | a3bb9e2764b415901fb2475c03f6fdb8a736d4fa (diff) | |
| download | conky-theme-udt-b51d1efa913933cb272b7c1906340981f00010c8.tar.gz conky-theme-udt-b51d1efa913933cb272b7c1906340981f00010c8.zip | |
docs: document the weather widget and fix the screenshot recipe
Adds a Weather section covering the API key, where it lives and why, the
401-while-activating behaviour a new key shows, the execi refresh, and
the by-hand fetch check. Adds five gotchas: execi firing under empty
text, the atomic cache write, what OWM actually returns for a bad key
and city, the no-raise invariant in lib/weather.lua, and type scaling
off width.
Also corrects three things that had gone stale: the symlink list omitted
bin/, the layout example still showed a single full-height clock, and
the test line omitted test_weather.lua.
The screenshot recipe was wrong in two ways, both of which bit during
this work. It slept a fixed second and raced the compositor, which is
how a capture came back showing a terminal instead of the dashboard; it
now polls for the workspace switch. And it fed the window's geometry to
grim -g, but a window on a hidden special workspace reports a negative
Y, so that grabs the wrong region; it now captures the output. Every
command in the file was run as written before committing this.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
| -rw-r--r-- | README.md | 101 |
1 files changed, 92 insertions, 9 deletions
@@ -15,8 +15,8 @@ Rendering and linking are automatic: cd ../unified-desktop-theme && ./install.sh That renders `conky.conf` from `conky.conf.in` and symlinks it, along with -`dashboard.lua`, `lib/` and `widgets/`, into `~/.config/conky/`. Re-running it -after a scheme change re-renders the colours. +`dashboard.lua`, `lib/`, `widgets/` and `bin/`, into `~/.config/conky/`. +Re-running it after a scheme change re-renders the colours. The Hyprland side is **not** installed by that script and is still yours to do. Until you do it, the dashboard opens as an ordinary floating window on whatever @@ -27,6 +27,40 @@ are not loaded. Two things are needed, both described in the bare `hl.exec_cmd("conky")` in `sections/autostart.lua` so it loads this config. Both are deliberately left as your choice rather than done for you. +## Weather + +The weather card needs an [OpenWeatherMap](https://openweathermap.org/api) API +key. Copy the example and fill it in: + + cp weather.env.example ~/.config/udt/weather.env + chmod 600 ~/.config/udt/weather.env + +That path is outside the repo because it holds a key, and anything committed is +potentially public. `weather.env` is gitignored here as a second line of +defence. + +**A new key returns `401 Invalid API key` for anywhere from a few minutes to a +few hours after you create it.** That is the API activating it, not a mistake in +the file. Until it works, and whenever the cache is missing, the card draws its +own chrome with `no weather data` and the thing to fix, rather than vanishing. + +Fetching is scheduled by conky itself: `conky.text` carries a single +`${execi 900 ~/.config/conky/bin/weather-fetch.sh}`, so the cache refreshes +every 15 minutes while the dashboard runs and never while it does not. The +widget only ever reads `~/.cache/udt/weather.json`; it makes no network call and +cannot block the draw. + +To check the fetch by hand: + + ./bin/weather-fetch.sh; echo "exit: $?" + +It prints nothing and exits 0 on success. On failure it says why on stderr and +leaves any existing cache alone, so a transient error never replaces good data +with an error body. + +Location and units live in `weather.env` too (`CITY`, `COUNTRY`, `UNITS`), not +in the source, so no real location appears in committed files. + ## Changing the layout Edit the `layout` table at the top of `dashboard.lua`. `col`/`row` are grid @@ -34,7 +68,8 @@ cells and `w`/`h` span them; cell size is derived from the screen, so the same table works on differently shaped monitors. local layout = { - { widget = 'clock', col = 1, row = 1, w = 1, h = 2 }, + { widget = 'clock', col = 1, row = 1, w = 1, h = 1 }, + { widget = 'weather', col = 1, row = 2, w = 1, h = 1 }, } Reordering widgets is an edit to that table and nothing else: a widget is handed @@ -76,21 +111,43 @@ rather than ending up with two. Run the parser and layout checks: - lua test/test_data.lua && lua test/test_layout.lua + lua test/test_data.lua && lua test/test_layout.lua && lua test/test_weather.lua Screenshot it. `grim` captures screen coordinates, not a window, so the dashboard's workspace has to be the active one first, and the toggle needs the Lua dispatch form because this Hyprland config is Lua (the plain -`togglespecialworkspace dash` form fails with `')' expected near 'dash'`): +`togglespecialworkspace dash` form fails with `')' expected near 'dash'`). + +**Poll for the switch, do not sleep through it.** A fixed `sleep` races the +compositor and captures whatever was on screen before; that is how a review +screenshot here once came back showing a terminal. Capture the whole output +instead of the window geometry, too: a window parked on a hidden special +workspace reports a negative Y (`0,-540`), and feeding that to `grim -g` grabs +the wrong region entirely. hyprctl dispatch 'hl.dsp.workspace.toggle_special("dash")' - sleep 1 - grim -g "$(hyprctl clients -j | jq -r '.[]|select(.class=="conky-dash")|"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"')" /tmp/dash.png + for i in $(seq 40); do + [ "$(hyprctl monitors -j | jq -r '.[0].specialWorkspace.name')" = "special:dash" ] && break + sleep 0.15 + done + sleep 2.5 # conky redraws every 2s; make sure a frame has landed + grim -o DP-1 /tmp/dash.png hyprctl dispatch 'hl.dsp.workspace.toggle_special("dash")' +Then **look at the PNG**. `grim` exits 0 whether the card drew correctly, drew +nothing, or drew an error, so the exit status says nothing about the thing you +are checking. + +Faster, for iterating on a widget's layout: conky's Cairo bindings load in +plain Lua, so a widget can be rendered to a PNG without conky at all. Point +`package.cpath` at `/usr/lib64/conky/lib?.so`, `require 'cairo'`, build an +image surface, and call the widget's `draw` with a hand-made rect and palette. +That turns install-restart-toggle-screenshot into one command. Be aware it +crops away the neighbouring cards, so check the real dashboard before believing +anything about relative type size. + Before the Hyprland section is installed there is no `special:dash` to toggle, -so the window is simply wherever it opened and the `grim` line alone captures -it. +so the window is simply wherever it opened and a bare `grim` captures it. ## Gotchas worth knowing @@ -119,6 +176,32 @@ the heavy clock numerals ask for the family `Noto Sans Black` at normal weight. **Sensors are globbed by hwmon `name`, never by index.** Indices drift across kernel and hardware reorders, and a stale one silently reports a different chip. +**`${execi}` fires even though `conky.text` renders nothing.** Cairo output +covers the text stream, so the `execi` that refreshes the weather cache is +invisible, but it still runs on schedule. This was checked with a probe config +rather than assumed, because the whole refresh mechanism rests on it. + +**The weather cache is written to a temp file and renamed.** The widget reads it +on the 2-second draw cadence, entirely unrelated to the 15-minute fetch, so a +fetch killed mid-write would otherwise hand the parser half a response. Rename +is only atomic within a filesystem, so the temp file sits in the same directory. + +**A bad OWM key returns 401 and an unknown city returns 404**, so `curl -f` +catches both. The fetch script also checks `.cod` is 200 before replacing the +cache, which covers the remaining case of a 200 whose body is not usable +weather. The polybar script this was ported from needed that check as its only +defence, because it ran curl without `-f`. + +**Nothing in `lib/weather.lua` raises.** Every function returns nil, or a +sentinel, on input it cannot use, and that is verified against every function +for nil, string, table, boolean, NaN and negative arguments. It matters because +the parser's input is a file written by a network fetch, and a raise here is a +blank dashboard rather than a message. + +**Card type scales off the cell WIDTH, not its height.** Height changes with the +grid, and scaling off it made the weather text shrink to a whisper beside the +clock's numerals when its cell got shorter. + ## License GPLv2 only. See `LICENSE`. |
