aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-15 12:34:32 +0200
committerDanilo M. <danix@danix.xyz>2026-10-15 12:34:32 +0200
commit61577be5ebd1818030a0d61dad0abb07b8656f5d (patch)
tree5d302c636e827b55fc6f33199ed3a8189e532969 /widgets
parent3943e08dabe684b409a3ac99c9371fbeb5df5cdb (diff)
downloadconky-theme-udt-61577be5ebd1818030a0d61dad0abb07b8656f5d.tar.gz
conky-theme-udt-61577be5ebd1818030a0d61dad0abb07b8656f5d.zip
feat: the updates card moves to the quickshell drawerHEADmaster
The card was a copy of nvtable's table, where installed-behind and repo-behind share a row and are told apart by colour, and it read "shipped" from the .info rather than the binary repo. The drawer's updates page replaces it: one row per package under the action it needs next, Slackware included. Removed: the card, its sampler and the nvchecker run it started every 30 minutes (the drawer runs nvchecker when its result is older than that), nvtable_parse with its test and fixture, and the package-up icon. The card's slot in the layout is left open; rearranging the board is a separate decision. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'widgets')
-rw-r--r--widgets/updates.lua195
1 files changed, 0 insertions, 195 deletions
diff --git a/widgets/updates.lua b/widgets/updates.lua
deleted file mode 100644
index b50dcf3..0000000
--- a/widgets/updates.lua
+++ /dev/null
@@ -1,195 +0,0 @@
--- Updates: nvtable's table of tracked packages that need action, the one the
--- login shell used to print. Wide and short, so it scrolls: the mouse wheel
--- steps through rows that do not fit.
---
--- Everything comes from the cache bin/updates-sample.sh writes; running
--- nvtable here would cost ~0.7s per draw.
-
-local card = require 'lib.card'
-local data = require 'lib.data'
-
-local CACHE = (os.getenv('XDG_CACHE_HOME') or (os.getenv('HOME') .. '/.cache'))
- .. '/udt/updates.txt'
-
--- Packages behind upstream. One is worth a glance, ten is a backlog.
-local WARN_N, CRIT_N = 1, 10
-
--- First row shown, moved by the wheel. max_offset is remembered from the last
--- draw so the mouse handler can clamp without re-reading the cache.
-local offset, max_offset = 0, 0
-
-local M = {}
-
--- nvtable's status dots, in the board's colours: 🔴 installed behind upstream,
--- 🟡 shipped .info behind, 🟢 current, ⚪ not installed (a ring).
-local function dot(cr, x, y, radius, colour, hollow)
- cairo_new_path(cr)
- cairo_arc(cr, x, y, radius, 0, 2 * math.pi)
- card.rgba(cr, colour)
- if hollow then
- cairo_set_line_width(cr, math.max(1, radius * 0.35))
- cairo_stroke(cr)
- else
- cairo_fill(cr)
- end
-end
-
-function M.draw(cr, rect, colors)
- local inner = card.card(cr, rect, colors)
- local function clamp(v, lo, hi) return math.max(lo, math.min(hi, v)) end
- local LABEL_F, BIG_F, ROW_F, SUB_F = 0.30, 1.0, 0.32, 0.26
-
- local up = data.nvtable_parse(data.slurp(CACHE) or '')
- if not up then
- card.notice(cr, inner, colors, 'UPDATES', 'no update data',
- 'bin/updates-sample.sh')
- return
- end
-
- local big = up.upgrade and tostring(up.upgrade) or '--'
- local sub = {}
- if up.bump then sub[#sub + 1] = up.bump .. (up.bump == 1 and ' repo' or ' repos') .. ' to bump' end
- if up.current then sub[#sub + 1] = up.current .. ' current' end
- if up.missing and up.missing > 0 then sub[#sub + 1] = up.missing .. ' not installed' end
- sub = table.concat(sub, ' · ')
-
- -- Header sized as if the card held ~12 rows: the table scrolls, so letting
- -- the header grow with the cell's height would only squeeze the rows.
- local S = clamp(math.min(inner.h * 0.94 / (1.5 + 12 * 0.66),
- card.fit_unit(cr, inner.w * 0.96, {
- { { card.title_str(card.ICON.updates, 'UPDATES'), card.FONT_MONO, LABEL_F },
- { big, card.FONT_HEAVY, BIG_F } },
- { { sub, card.FONT_UI, SUB_F } },
- }, 100)), 10, 72)
- local label_size = S * LABEL_F
-
- card.font(cr, card.FONT_HEAVY, S * BIG_F, false)
- card.rgba(cr, card.threshold(up.upgrade, WARN_N, CRIT_N, colors))
- card.text_right(cr, inner.x + inner.w, inner.y + S * BIG_F, big)
-
- card.font(cr, card.FONT_MONO, label_size, false)
- card.title(cr, inner.x, inner.y + label_size, card.ICON.updates, 'UPDATES', colors)
-
- card.font(cr, card.FONT_UI, S * SUB_F, false)
- card.rgba(cr, colors.label, 0.65)
- card.text(cr, inner.x, inner.y + label_size + S * SUB_F * 1.5, sub)
-
- local top = inner.y + S * BIG_F + S * ROW_F * 1.2
- local bottom = inner.y + inner.h
-
- if #up == 0 then
- card.font(cr, card.FONT_UI, S * ROW_F, false)
- card.rgba(cr, colors.ok)
- card.text(cr, inner.x, top + S * ROW_F * 1.5, 'everything current')
- return
- end
-
- -- Column widths in characters. The font is monospaced, so padding with
- -- spaces aligns columns exactly and one advance converts chars to pixels.
- local wl, wn, wi, ws, wu = 2, 1, 2, 2, 0
- for _, r in ipairs(up) do
- wl = math.max(wl, #(r.repo or '--'))
- wn = math.max(wn, #r.name)
- wi = math.max(wi, #(r.installed or '--'))
- ws = math.max(ws, #(r.shipped or '--'))
- wu = math.max(wu, #(r.upstream or ''))
- end
- -- repo, gap, name, gap, installed, ' → ', shipped, gap, two dots, gap,
- -- upstream
- local chars = wl + 2 + wn + 2 + wi + 3 + ws + 2 + 3 + 2 + wu
-
- -- Row type: the header's row ratio, shrunk until the widest row fits
- -- beside the scrollbar gutter.
- local gutter = 10
- card.font(cr, card.FONT_MONO, 100, false)
- local per_unit = card.advance(cr, '0') / 100
- local row_size = math.max(8, math.min(S * ROW_F, (inner.w - gutter) / (chars * per_unit)))
- local cw = per_unit * row_size
- local step = row_size * 1.7
- local rad = row_size * 0.28
- local mid = row_size * 0.32 -- baseline to the digits' vertical centre
-
- -- The legend takes the bottom line; the rows scroll above it.
- bottom = bottom - row_size * 2
-
- local visible = math.max(1, math.floor((bottom - top) / step))
- max_offset = math.max(0, #up - visible)
- offset = clamp(offset, 0, max_offset)
-
- local x_name = inner.x + (wl + 2) * cw
- local x_inst = inner.x + inner.w - gutter - (wi + 3 + ws + 2 + 5 + wu) * cw
- local x_ship = x_inst + (wi + 3) * cw
- local x_mark = x_ship + (ws + 2) * cw
- local x_upst = x_mark + 5 * cw
-
- card.font(cr, card.FONT_MONO, row_size, false)
- local y = top + row_size
- for i = offset + 1, math.min(#up, offset + visible) do
- local r = up[i]
- card.rgba(cr, colors.label, 0.65)
- card.text(cr, inner.x, y, r.repo or '--')
- card.rgba(cr, colors.value)
- card.text(cr, x_name, y, r.name)
-
- -- Installed: behind upstream is the critical state, caught up is ok.
- if r.installed then card.rgba(cr, r.behind and colors.critical or colors.ok)
- else card.rgba(cr, colors.label, 0.5) end
- card.text(cr, x_inst, y, string.format('%' .. wi .. 's', r.installed or '--'))
- card.rgba(cr, colors.label, 0.65)
- card.text(cr, x_inst + wi * cw, y, ' → ')
- -- Shipped: a .info behind upstream is packaging work waiting, a warning.
- if r.shipped then card.rgba(cr, r.bump and colors.warning or colors.value)
- else card.rgba(cr, colors.label, 0.5) end
- card.text(cr, x_ship, y, r.shipped or '--')
- -- Installed state, then a second dot when the .info is behind too: the
- -- two are independent, as nvtable shows them.
- if not r.installed then dot(cr, x_mark + cw / 2, y - mid, rad, colors.label, true)
- else dot(cr, x_mark + cw / 2, y - mid, rad, r.behind and colors.critical or colors.ok) end
- if r.bump then dot(cr, x_mark + cw * 2.5, y - mid, rad, colors.warning) end
- card.font(cr, card.FONT_MONO, row_size, false)
- if r.upstream then
- card.rgba(cr, colors.highlight)
- card.text(cr, x_upst, y, r.upstream)
- end
- y = y + step
- end
-
- -- Legend, on the card's bottom line.
- local lx, ly = inner.x, inner.y + inner.h - row_size * 0.2
- card.font(cr, card.FONT_UI, row_size * 0.85, false)
- for _, l in ipairs({
- { colors.critical, 'upstream newer' }, { colors.warning, 'repo behind' },
- { colors.ok, 'current' }, { colors.label, 'not installed', true },
- }) do
- dot(cr, lx + rad, ly - mid, rad, l[1], l[3])
- lx = lx + rad * 2 + cw * 0.7
- card.rgba(cr, colors.label, 0.65)
- card.text(cr, lx, ly, l[2])
- lx = lx + card.advance(cr, l[2]) + cw * 2.5
- end
-
- -- Scrollbar, only when there is something to scroll.
- if max_offset > 0 then
- local track_h = visible * step
- local thumb_h = math.max(row_size, track_h * visible / #up)
- local thumb_y = top + (track_h - thumb_h) * offset / max_offset
- local bx = inner.x + inner.w - 3
- card.rounded_path(cr, bx, top, 3, track_h, 1.5)
- card.rgba(cr, colors.rule, 0.35)
- cairo_fill(cr)
- card.rounded_path(cr, bx, thumb_y, 3, thumb_h, 1.5)
- card.rgba(cr, colors.highlight, 0.8)
- cairo_fill(cr)
- end
-end
-
--- The wheel steps one row. It shows at once because the dashboard draws at
--- 0.1s while visible (see dashboard.lua).
-function M.mouse(event)
- if event.type ~= 'mouse_scroll' then return false end
- offset = math.max(0, math.min(max_offset,
- offset + (event.direction == 'up' and -1 or 1)))
- return true
-end
-
-return M