diff options
Diffstat (limited to 'widgets')
| -rw-r--r-- | widgets/updates.lua | 195 |
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 |
