Compare commits

...

2 Commits

Author SHA1 Message Date
mars3142 3c85fa61b6 register timemaster plugin
Signed-off-by: Peter Siegmund <developer@mars3142.org>
2026-04-20 20:54:25 +02:00
mars3142 a8163c1139 show blocked counter
Signed-off-by: Peter Siegmund <developer@mars3142.org>
2026-04-20 20:54:09 +02:00
5 changed files with 93 additions and 4 deletions
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 233.6 236" style="enable-background:new 0 0 233.6 236;" xml:space="preserve">
<path
style="fill:#ffffff;"
d="M116.8,3.1L116.8,3.1C53.6,3.1,1.9,54.8,1.9,118l0,0c0,63.2,51.7,114.9,114.9,114.9l0,0c63.2,0,114.9-51.7,114.9-114.9l0,0
C231.7,54.8,180,3.1,116.8,3.1L116.8,3.1z M66.7,139.4v12.4H54.3c-6.8,0-12.4-5.5-12.4-12.4V96.6c0-6.8,5.5-12.4,12.4-12.4
s12.4,5.5,12.4,12.4V139.4z M84.2,151.8h-0.9c-6.7,0-12.1-5.5-12.1-12.1s5.4-12.1,12.1-12.1h0.8c6.7,0,12.1,5.4,12.1,12.1
S90.8,151.8,84.2,151.8z M84,122.4h-0.5c-6.8,0-12.3-5.5-12.3-12.3s5.5-12.3,12.3-12.3H84c6.8,0,12.3,5.5,12.3,12.3
S90.8,122.5,84,122.4L84,122.4z M130.3,139.4c0.1,6.9-5.5,12.4-12.4,12.4s-12.4-5.5-12.4-12.4v-29.3c0-6.8,5.5-12.4,12.4-12.4
s12.4,5.5,12.4,12.4V139.4z M161,139.4c0,6.9-5.5,12.4-12.4,12.4s-12.4-5.5-12.4-12.4v-29.3c0-6.8,5.5-12.4,12.4-12.4
s12.4,5.5,12.4,12.4V139.4z M191.7,139.4c0,6.9-5.5,12.4-12.4,12.4s-12.4-5.5-12.4-12.4v-29.3c0-6.8,5.5-12.4,12.4-12.4
s12.4,5.5,12.4,12.4V139.4z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+13
View File
@@ -63,6 +63,19 @@
"Tooltip": "Shows open pull requests assigned to you across all repositories",
"UUID": "dev.mars3142.ulanzideck.collection.giteapr"
},
{
"Name": "Timemaster",
"Icon": "assets/icons/timemaster.svg",
"PropertyInspectorPath": "property-inspector/timemaster/inspector.html",
"States": [
{
"Name": "Default",
"Image": "assets/icons/timemaster.svg"
}
],
"Tooltip": "Shows working hours and time account from Timemaster",
"UUID": "dev.mars3142.ulanzideck.collection.timemaster"
},
{
"Name": "Model Railway",
"Icon": "assets/icons/railway.png",
+63 -4
View File
@@ -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';
+1
View File
@@ -19,6 +19,7 @@
<script src="./actions/GiteaPRAction.js"></script>
<script src="./actions/RailwayAction.js"></script>
<script src="./actions/StreamAction.js"></script>
<script src="./actions/TimemasterAction.js"></script>
<script src="./app.js"></script>
</body>
</html>
+2
View File
@@ -26,6 +26,8 @@ $UD.onAdd(jsn => {
ACTION_CACHES[context] = new RailwayAction($UD, context);
} else if (name === 'stream') {
ACTION_CACHES[context] = new StreamAction($UD, context);
} else if (name === 'timemaster') {
ACTION_CACHES[context] = new TimemasterAction($UD, context);
}
}