From a8163c1139e59ce2285c3e2a917648d45ce0d008 Mon Sep 17 00:00:00 2001 From: Peter Siegmund Date: Mon, 20 Apr 2026 20:54:09 +0200 Subject: [PATCH] show blocked counter Signed-off-by: Peter Siegmund --- plugin/actions/GiteaPRAction.js | 67 +++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/plugin/actions/GiteaPRAction.js b/plugin/actions/GiteaPRAction.js index af69ca6..68578fa 100644 --- a/plugin/actions/GiteaPRAction.js +++ b/plugin/actions/GiteaPRAction.js @@ -87,7 +87,21 @@ class GiteaPRAction extends ActionBase { if (raw === null) { this.renderButton(null, true); return; } const prs = raw.filter(pr => pr.pull_request != null); + const prDetails = await Promise.all( + prs.map(pr => { + const [owner, repo] = (pr.repository?.full_name || '').split('/'); + if (!owner || !repo) return Promise.resolve(null); + return fetch(`${this.config.url}/api/v1/repos/${owner}/${repo}/pulls/${pr.number}`, + { headers, signal: AbortSignal.timeout(5000) }) + .then(r => r.ok ? r.json() : null) + .catch(() => null); + }) + ); + const wip = prs.filter(pr => pr.title?.startsWith('WIP: ')).length; + const mergeConflict = prs.filter((pr, i) => + !pr.title?.startsWith('WIP: ') && prDetails[i]?.mergeable === false + ).length; const now = Date.now(); // Update first-seen map: add new, remove gone @@ -106,7 +120,7 @@ class GiteaPRAction extends ActionBase { !pr.title?.startsWith('WIP: ') && (now - (this.firstSeen[String(pr.id)] ?? now)) > 24 * 60 * 60 * 1000 ).length; - this.renderButton(prs.length, false, wip, overdue); + this.renderButton(prs.length, false, wip, mergeConflict, overdue); } catch (e) { // timeout or network error = VPN likely down this.renderButton(null, false); @@ -114,7 +128,7 @@ class GiteaPRAction extends ActionBase { }); } - renderButton(count, isError, wip = 0, overdue = 0) { + renderButton(count, isError, wip = 0, mergeConflict = 0, overdue = 0) { const { canvas, ctx } = this.createCanvas(); // Label — top @@ -156,8 +170,34 @@ class GiteaPRAction extends ActionBase { ctx.textBaseline = 'middle'; }; - if (wip > 0 && overdue > 0) { - // Most compact: 4 items + const extras = (wip > 0 ? 1 : 0) + (mergeConflict > 0 ? 1 : 0) + (overdue > 0 ? 1 : 0); + + if (extras === 3) { + drawCount(68, [38, 50, 60]); + ctx.fillStyle = '#555555'; + ctx.font = '14px "Source Han Sans SC"'; + ctx.fillText(label, 98, 108); + ctx.fillStyle = '#ff8c00'; + ctx.font = 'bold 22px "Source Han Sans SC"'; + ctx.fillText(`WIP: ${wip}`, 98, 133); + ctx.fillStyle = '#e040fb'; + ctx.font = 'bold 22px "Source Han Sans SC"'; + ctx.fillText(`MC: ${mergeConflict}`, 98, 157); + ctx.fillStyle = '#ff3333'; + ctx.font = 'bold 22px "Source Han Sans SC"'; + ctx.fillText(`>24h: ${overdue}`, 98, 181); + } else if (wip > 0 && mergeConflict > 0) { + drawCount(78, [44, 58, 70]); + ctx.fillStyle = '#555555'; + ctx.font = '15px "Source Han Sans SC"'; + ctx.fillText(label, 98, 122); + ctx.fillStyle = '#ff8c00'; + ctx.font = 'bold 26px "Source Han Sans SC"'; + ctx.fillText(`WIP: ${wip}`, 98, 149); + ctx.fillStyle = '#e040fb'; + ctx.font = 'bold 26px "Source Han Sans SC"'; + ctx.fillText(`MC: ${mergeConflict}`, 98, 176); + } else if (wip > 0 && overdue > 0) { drawCount(75, [44, 56, 68]); ctx.fillStyle = '#555555'; ctx.font = '15px "Source Han Sans SC"'; @@ -168,6 +208,17 @@ class GiteaPRAction extends ActionBase { ctx.fillStyle = '#ff3333'; ctx.font = 'bold 24px "Source Han Sans SC"'; ctx.fillText(`>24h: ${overdue}`, 98, 175); + } else if (mergeConflict > 0 && overdue > 0) { + drawCount(75, [44, 56, 68]); + ctx.fillStyle = '#555555'; + ctx.font = '15px "Source Han Sans SC"'; + ctx.fillText(label, 98, 120); + ctx.fillStyle = '#e040fb'; + ctx.font = 'bold 26px "Source Han Sans SC"'; + ctx.fillText(`MC: ${mergeConflict}`, 98, 147); + ctx.fillStyle = '#ff3333'; + ctx.font = 'bold 24px "Source Han Sans SC"'; + ctx.fillText(`>24h: ${overdue}`, 98, 175); } else if (wip > 0) { drawCount(85, [48, 64, 76]); ctx.fillStyle = '#666666'; @@ -176,6 +227,14 @@ class GiteaPRAction extends ActionBase { ctx.fillStyle = '#ff8c00'; ctx.font = 'bold 30px "Source Han Sans SC"'; ctx.fillText(`WIP: ${wip}`, 98, 168); + } else if (mergeConflict > 0) { + drawCount(85, [48, 64, 76]); + ctx.fillStyle = '#666666'; + ctx.font = '16px "Source Han Sans SC"'; + ctx.fillText(label, 98, 140); + ctx.fillStyle = '#e040fb'; + ctx.font = 'bold 30px "Source Han Sans SC"'; + ctx.fillText(`MC: ${mergeConflict}`, 98, 168); } else if (overdue > 0) { drawCount(88, [52, 68, 80]); ctx.fillStyle = '#666666';