aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
AgeCommit message (Collapse)AuthorFilesLines
10 daysfeat(immich): fall back to the past week's memoriesDanilo M.1-2/+3
A day with no memories left the card showing only a notice. When today has none, immich-fetch.sh now merges the memories of each of the past six days, skipping a day whose request fails, and marks the index with a scope week line. The subtitle names where the photos come from, Today or This week, before the i/n counter, and the empty notice reads no memories this week. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 daysfeat(immich): mark the big value with a Y ago unitDanilo M.1-4/+19
The years-ago count read as a bare number unless you read the subtitle. It now carries a small Y at its top-right, where a degree sign sits on a temperature, and ago under it on the baseline. The subtitle drops its now redundant "years ago" and keeps only the i/n counter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 daysfeat: add an Immich memories card with click and scrollDanilo M.1-0/+164
A centred card showing today's "N years ago" photos from Immich, one at a time on a 30-second rotation, with when each was taken and where. bin/immich-fetch.sh runs from conky's execi every 30 minutes: it asks /api/memories for today, converts each preview to PNG (Cairo loads nothing else) and writes an index with the year, local capture time and place. The place needs the key's asset.read permission and reads '--' without it. The key lives in ~/.config/udt/immich.env, like the weather key, because a GPG-backed store would raise a pinentry unattended. The dashboard now registers lua_mouse_hook and hands pointer events to the widget under the pointer. On this card, scrolling steps through the photos and a left click opens the photo in Immich's web UI and hides the dashboard so the browser is not stuck beneath it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-19feat: label the Slackware age and use Italian weekday initialsDanilo M.2-2/+9
The Slackware card's big value gave no hint it was the slackpkg ChangeLog age. Add a small line under the title naming it. The calendar's weekday initials were English. Use the Italian single-letter form, matching the card's already-Italian breaktimer labels.
2026-09-18feat: add a title icon to every labelled cardDanilo M.8-22/+21
Add card.ICON and a card.title helper that draws the glyph in the highlight colour before the label, at the label's own size. The eight labelled cards use it, in both the fit_unit width measurement and the draw, so the icon cannot overrun a narrow cell. Clock (no label) and weather (condition glyph already) are unchanged, and the no-data notice titles stay text-only. Codepoints were chosen against a rendered contact sheet, not fontconfig alone, since a wrong codepoint draws a plausible neighbour.
2026-09-18refactor: unify card no-data face and fluid sizingDanilo M.7-97/+39
Extract card.notice so every cached card's no-data state is one fluid, theme-consistent face instead of a copy per widget, and delete the fixed-size card.label it replaces. Derive weather's arc geometry from its band (pad, curve room, sun dot, time labels) instead of fixed pixels, and cap the arc at a proportion of the card's width rather than 240px. Derive disks' bar-fallback height and its address type from the card's own label scale. Standardise the big-value factor to 1.0 across the fit_unit cards and document the big-value colour rule and the disks headline exception.
2026-09-18feat: add a breaktimer cardDanilo M.1-0/+91
Replaces the Waybar module that used to show breaktimer.sh with a card on the dashboard. The card's big value is the phase countdown, coloured by phase with the same language the Waybar module used, and two rows name the phase and what the countdown leads to. Data comes from bin/breaktimer-sample.sh, run by conky at execi 5, which reads the daemon's runtime files into a cache. The sampler owns the kill -0 liveness check, because conky's Lua cannot run a process and a dead daemon must read as 'fermo' rather than a stale 'running'. Drops outside the work-hours window freeze the countdown while the phase stays 'working'. The sampler detects this from the remain file's age and the card reads it as 'outside working hours', which also covers a hung daemon. The phase words and colour roles live in data.breaktimer_parse so they are unit-tested; the card only draws the result.
2026-09-18feat: date the calendar rows and pin a colour legendDanilo M.1-11/+80
Three changes to the calendar card: The month grid drops further below the header. The weekday initials sat close enough to read as part of the header rather than as the top of the grid. Event rows carry the date before the time, day/month with no year: the window is a week and the grid above already names the month, so a year would spend three characters on the one field that cannot vary. A legend of the calendar colours is pinned along the card's bottom, and the event rows now end above it rather than at the card's inner edge. It lists every calendar khal declared a colour for, in name order so it does not reshuffle between frames, since pairs() walks a hash. The row budget also counted one row more than the drawing loop would draw, which suppressed the '+N more' line exactly when it was needed: the loop cut the row the count had already spent. Both now test the same condition. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18feat: add a calendar card reading khalDanilo M.1-0/+247
The month grid with the week's appointments below it, colour-coded by calendar. Events come from a cache file rather than a live call: khal costs about 200ms of Python startup, which is two orders of magnitude over the 2-second draw budget, so bin/calendar-sample.sh writes the cache on a 5-minute execi and the widget only parses. Calendar colours are read out of khal's own config by the sampler and mapped onto the board's palette roles, so the card follows a scheme change instead of pinning three literal hues. khal will not emit an ISO date: {start-date} uses the user's dateformat, which carries no year here, and a strftime spec inside the field raises. The sampler asks for {start-date-long} and data.calendar_date recovers the numbers by position, resolving day/month by magnitude and reading a genuinely ambiguous pair day-first. A 2-digit year is refused rather than guessed at. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: give the CPU and board rows their own accentsDanilo M.1-1/+8
The two rows name two different pieces of hardware and read as one block in a single colour. heading and highlight are the palette roles that carry no state meaning, so they can stand for an identity; ok/warning/critical could not, since those say how something is doing and these strings never change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: show free and total under each disk ringDanilo M.2-9/+25
Replaces the percentage, which the ring already draws as an angle. A number repeating it costs a row in a column about 75px wide. Free carries the threshold colour because it is the measured quantity; the total is fixed and stays in the plain value colour, so each column has one coloured number. The cache card adopts card.truncate in the same pass: it was slicing names by byte, which halves a multi-byte character. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: name the CPU and motherboard on the system cardDanilo M.1-3/+53
Both read once: neither changes without a reboot, and /proc/cpuinfo repeats its model-name line once per thread. The two rows come out of the equaliser's height budget, since it is the card's designated slack absorber. Its floor drops from 18px to zero: with rows above it the band can genuinely run out of room, and a fixed floor meant it kept height it did not have and the temperatures drew over it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: add the slackware cardDanilo M.1-0/+121
The big value is the time since slackpkg's ChangeLog changed, coloured green under a day, amber to a week, red past it. A cache with no changelog key is a different failure from no cache at all: the sampler ran and the ChangeLog is what was missing, so the rows still draw and only the age reads '--'. Collapsing the two would send the reader to the wrong problem. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: add the network cardDanilo M.1-0/+173
Two lines on one chart against a shared ceiling, one sample per pixel column so nothing is interpolated. The history is module state sized from the card's width, so moving the card reframes the window rather than clearing it. The public address is refused once stale: an address that may no longer be yours, displayed with confidence, is worse than a dash. The fixture uses TEST-NET-1. This repository is public. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: put every card's big number in the same placeDanilo M.2-15/+18
Mirror the weather header so the glyph sits large on the left and the temperature, city and condition run against the right edge, and move the system card's CPU percentage onto its header line, right-aligned. All big values now render at the card's right edge.
2026-09-17feat: make the system card type fluidDanilo M.1-18/+40
The label, headline, RAM and temperature rows now derive from one base size, chosen from the cell height and a measured width fit, and the per-core equaliser absorbs the height left over. Bigger cell, bigger type instead of empty space; the size shrinks only on a width clash.
2026-09-17fix: shorten the cpu equaliser bars to 75%Danilo M.1-1/+1
2026-09-17fix: sit the gpu and cache titles level with the big valueDanilo M.2-3/+3
The 'GPU' and 'CACHE' labels shared the big number's baseline, so they read as sitting under it. Move them to the card's top-left, the same title position the other cards use, level with the top of the value.
2026-09-17feat: fluid type for the gpu and cache cardsDanilo M.2-33/+88
The big value moves to the right of the heading, on the same baseline, so the card's width carries it instead of leaving the right half empty. Type now scales to fill the cell: card.fit_unit measures the rows and returns the largest size that fits the width, and the widget takes the smaller of that and its height budget, shrinking only where a row would collide.
2026-09-17docs: correct the system-widget comments and defer the age markerDanilo M.1-3/+4
Fix the conky.conf.in comment to name all three samplers and the README to say the cache sampler runs every 15 minutes. Rewrite the disks layout comment to match per_row = n (no wrapping), drop the stale "seventeenth bar" note, and record in the spec that the cache age marker is deliberately deferred with the epoch-line upgrade path.
2026-09-17fix: stop the widgets from stalling or raising the drawDanilo M.1-2/+2
Memoize hwmon_dir by chip name so sensor reads no longer popen grep on every frame, cache misses included. Floor fractional byte counts in card.human so it cannot raise. Drop the GPU package-temperature row, which duplicated the headline. Set umask before mkdir in both samplers so a fresh cache directory is not world-readable. Make render.lua exit non-zero on a draw error and tolerate an unset HOME.
2026-09-17fix: adjust the system cards against the screenshotsDanilo M.2-4/+4
2026-09-17feat: add the disks and cache cardsDanilo M.2-0/+198
disks draws a ring per filesystem from the df sample, with the NFS server address read from the device field and a labelled-bar fallback when the rings would be too small to read. cache shows the ~/.cache total and its four largest children from the du sample. card.ring now resets the cairo path first: a preceding card.text() leaves a current point, and cairo_arc() joins to it with a straight line, so the disks rings were drawn with stray chords. The ring primitive had no caller until now, which is why it went unnoticed.
2026-09-17feat: add the GPU cardDanilo M.1-0/+73
2026-09-17feat: add the system card with a per-core equaliserDanilo M.1-0/+111
2026-09-17fix: close the gap between the clock numerals and the dateDanilo M.1-5/+23
The numeral size was capped at a flat 0.46 of the available height, which for two baselines spanning 1.70x the size meant they could only ever fill about four fifths of the band, leaving a void above the date. The divisor is now derived from the baselines themselves. The width cap is measured rather than guessed: two Oswald digits are 1.00x the font size wide (at size 100, '00' measures 100.0px and the widest pair '88' 98.0px), so a width w permits a size of about w, less a margin at the card edges. A narrow cell is still width-bound and cannot fill its height. That slack is now split above and below the numerals instead of collecting under them, so the pair sits centred in the space it cannot fill. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: centre the clock numeralsDanilo M.1-2/+9
Horizontally centred in the card; the weekday and date stay against the left edge at the bottom. Each line is centred on its own ink width via measure(), not advance(): ink is what centring wants, and Oswald is proportional, so 10 and 05 are not the same width and a shared measurement would leave one of them visibly off-centre. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: give the clock its own fontDanilo M.1-1/+1
Installs Oswald (OFL-1.1, from googlefonts/OswaldFont) under ~/.fonts/o/Oswald with its license, and points the clock numerals at it for the squared look the rounded Noto Sans Black did not have. Per-widget fonts needed no new machinery: card.font() already takes any family string, so FONT_* are shared defaults rather than a restriction. FONT_CLOCK joins them, and the weather card keeps FONT_HEAVY, so the two no longer have to agree. Cairo still cannot ask for a weight above bold, so a heavier cut is selected by family name as FONT_HEAVY already did. Worth knowing that fontconfig substitutes a default for a family it does not recognise, which is indistinguishable from the font not applying; fc-match tells you which happened. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: right-align the condition glyphDanilo M.1-6/+6
Temperature and city stay against the left edge; the glyph moves to the right edge, so the header reads as a value on one side and its icon on the other rather than one run of text. text_right takes the right edge as its x and measures ink, which is what aligning to an edge wants, as against advance() for stepping a cursor. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: make the clock fill whatever cell it is givenDanilo M.1-10/+31
The numerals scaled off the cell but the date block sat at a fixed drop below them, so a tall cell left a dead band under the date and a short one would have collided. Now the date pins to the bottom edge, the numerals take everything above it, and both type sizes derive from the width, so the slack of a tall cell falls in the middle of the card where it belongs. Type scales off width for the same reason the weather card does: height is what changes when a row is added to the grid, and a widget that shrinks its text whenever its cell gets shorter reads as broken next to its neighbours. Checked at 1x3, 1x6, 2x2, 2x4 and 3x3 on an 8x6 grid before restarting conky. The 1x6 case stays width-bound and leaves room below the numerals, which is correct for a cell far taller than it is wide. The README now states the convention, since it applies to every widget added later: derive offsets from the rect, scale off width, decide where the slack goes, and drop an element that would otherwise overlap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: move to an 8x6 grid, and let the weather card fit any cell heightDanilo M.1-17/+11
The grid was 4x2, which made every placement decision a coarse one. 8x6 gives 299x157 cells, so a card can be sized in something closer to the increments the layout actually wants. Nothing in rect_for needed changing: it derives cell size from COLS and ROWS, so this is a two-number edit. Note that ROWS has to cover the tallest row in use. A widget placed on row 3 of a two-row grid is computed at y=1068 on a 1080px screen and draws off the bottom, silently. The arc band no longer has a minimum height. It had one, and in a cell 40px shorter than the content wanted, the minimum won and pulled the curve up through the stat rows, drawing the sunrise time across the word WIND. It now takes what is genuinely left and is skipped below the height where it could be read, so the same widget composes in a 2x2 or a 2x3 cell without overlapping anything. Checked by rendering the widget offscreen at 2x1, 2x2 and 2x3 before restarting conky. Layout is now a 1x3 clock with a 2x3 weather card beneath it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: put the weather card under the clock, scale its type to widthDanilo M.1-7/+12
Placement is column 1 row 2, directly beneath the clock, which drops to a single-row cell to make room. The card's type now scales off the cell WIDTH rather than its height. Scaling off height meant the text shrank every time the cell got shorter, and beside the clock's numerals the card read as a whisper. Width is the stable dimension for this layout and is what constrains the text anyway, since the stat rows run edge to edge. Verified against the live dashboard, not only the offscreen render: the two disagreed about type size precisely because the offscreen harness was cropped to the card and never showed it next to the clock. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17fix: size the weather card to its contentDanilo M.1-18/+44
The first draft placed every band at a fixed pixel offset and let the arc absorb whatever height was left. In a 1x2 cell on this monitor that is 794px of arc: a cathedral arch under a fifth of a card of content, nothing like the mockup it was shaped after. Three changes, all visible in an offscreen render of the real widget: - Type sizes and band offsets scale with the rect, within clamps, so the proportions hold on the 1920 monitor as well as this one. - The arc gets a bounded band that follows the stats instead of being pinned to the bottom, so no dead strip opens between them. - The layout gives the widget a 1x1 cell. Its content is about 350px tall and a full-height cell cannot be filled without inventing data. Found before restarting conky by loading conky's own cairo bindings standalone and rendering the widget to a PNG, which is a far tighter loop than install, restart, switch workspace, screenshot. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: add the weather cardDanilo M.1-0/+177
Draws current conditions plus a sunrise-to-sunset arc in widgets/weather.lua, placed at col 2 in dashboard.lua's layout. Schedules the periodic fetch via execi in conky.conf.in, tying refresh to conky's own lifecycle. The no-data env-file probe now closes its handle explicitly: the branch reruns every draw until a fetch succeeds, so an unclosed io.open there would leak one handle per frame. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16fix: step text cursors by advance, not ink widthDanilo M.1-1/+2
The date rendered as "16 /SEP /2026", each slash jammed against the next glyph. measure() returns the ink width, which ignores leading and trailing spaces because a space carries no ink, and clock.lua was using it to advance a cursor. Measured: " / " covers 6px of ink but advances 14px, so every separator lost 8px. Splits the two uses that were conflated in one function. measure() is for centring and right-aligning, where ink width is what you want; advance() returns x_advance and is for laying out runs of text left to right. The clock's date now uses advance() and reads "16 / SEP / 2026" with even gaps, verified by screenshot. Worth the split rather than changing measure() in place: text_right is a correct caller of the ink width, so one function cannot serve both and silently returning the advance would have broken alignment instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16feat: add the clock widgetDanilo M.1-0/+56
Hour stacked over minute in Noto Sans Black, weekday in caps, date slashed, following idea2.png. Colours are the palette's. Numeral size derives from the cell rather than a constant, so the same widget fills its cell on either monitor. The slashes take the dimmer label colour so the numerals read first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>