Files
mars3142_collection/plugin/actions/CopilotAction.js
T
mars3142 fbf40f75b2 first plugins for Ulanzi D200H
- petrol watch
- copilot usage

Signed-off-by: Peter Siegmund <developer@mars3142.org>
2026-04-09 20:42:31 +02:00

176 lines
4.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
class CopilotAction {
constructor($UD, context) {
this.$UD = $UD;
this.context = context;
this.config = {
url: '',
refreshRate: '4',
};
this.refreshTimer = null;
this.debounceTimer = 0;
}
setActive() {}
onClear() {
if (this.refreshTimer) {
clearInterval(this.refreshTimer);
this.refreshTimer = null;
}
if (this.debounceTimer) {
clearTimeout(this.debounceTimer);
this.debounceTimer = 0;
}
}
setParams(jsn) {
this.config = Object.assign(this.config, (jsn && jsn.param) || {});
this.start();
}
onRun() {
this.fetchData();
}
start() {
this.onClear();
this.fetchData();
const duration = this.getRefreshDuration();
if (duration > 0) {
this.refreshTimer = setInterval(() => this.fetchData(), duration * 60 * 1000);
}
}
async fetchData() {
if (this.debounceTimer) clearTimeout(this.debounceTimer);
this.debounceTimer = setTimeout(async () => {
if (!this.config.url) {
this.renderGauge(null);
return;
}
try {
const response = await fetch(this.config.url);
const text = await response.text();
const value = this.parsePrometheus(text);
this.renderGauge(value !== null ? parseFloat(value) : null);
} catch (e) {
this.renderGauge(null);
}
}, 300);
}
parsePrometheus(text) {
for (const line of text.split('\n')) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
if (trimmed.startsWith('github_copilot_usage_percentage')) {
const closingBrace = trimmed.indexOf('}');
if (closingBrace !== -1) return trimmed.slice(closingBrace + 1).trim();
// no labels
const parts = trimmed.split(/\s+/);
if (parts.length >= 2) return parts[1];
}
}
return null;
}
renderGauge(value) {
const canvas = document.createElement('canvas');
canvas.width = 196;
canvas.height = 196;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, 196, 196);
const cx = 98, cy = 100;
const r = 68;
const lineWidth = 14;
// Gauge runs from 225° to 315° clockwise (270° sweep)
const startAngle = 135 * Math.PI / 180;
const totalSweep = 270 * Math.PI / 180;
const greenEnd = startAngle + 0.50 * totalSweep; // 50%
const yellowEnd = startAngle + 0.80 * totalSweep; // 80%
const endAngle = startAngle + totalSweep; // 100%
// Background track
ctx.beginPath();
ctx.arc(cx, cy, r, startAngle, endAngle, false);
ctx.strokeStyle = '#333333';
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round';
ctx.stroke();
if (value !== null) {
const pct = Math.max(0, Math.min(100, value)) / 100;
const valueAngle = startAngle + pct * totalSweep;
// Green segment (050%)
if (pct > 0) {
ctx.beginPath();
ctx.arc(cx, cy, r, startAngle, Math.min(valueAngle, greenEnd), false);
ctx.strokeStyle = '#4caf50';
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round';
ctx.stroke();
}
// Yellow segment (5080%)
if (pct > 0.5) {
ctx.beginPath();
ctx.arc(cx, cy, r, greenEnd, Math.min(valueAngle, yellowEnd), false);
ctx.strokeStyle = '#ffeb3b';
ctx.lineWidth = lineWidth;
ctx.lineCap = 'butt';
ctx.stroke();
}
// Red segment (80100%)
if (pct > 0.8) {
ctx.beginPath();
ctx.arc(cx, cy, r, yellowEnd, valueAngle, false);
ctx.strokeStyle = '#f44336';
ctx.lineWidth = lineWidth;
ctx.lineCap = 'butt';
ctx.stroke();
}
// Value text — centered, colored
const color = pct <= 0.5 ? '#4caf50' : pct <= 0.8 ? '#ffeb3b' : '#f44336';
const displayText = value.toFixed(1) + '%';
const fSize = displayText.length > 6 ? 28 : 34;
ctx.fillStyle = color;
ctx.font = `bold ${fSize}px "Source Han Sans SC"`;
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.fillText(displayText, cx, cy + 8);
} else {
ctx.fillStyle = '#666666';
ctx.font = 'bold 28px "Source Han Sans SC"';
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.fillText('N/A', cx, cy + 8);
}
// Label — bottom
ctx.fillStyle = '#7ec8e3';
ctx.font = 'bold 20px "Source Han Sans SC"';
ctx.fillText('Copilot', cx, 165);
this.$UD.setBaseDataIcon(this.context, canvas.toDataURL('image/png'));
}
getRefreshDuration() {
switch (this.config.refreshRate) {
case '1': return 1;
case '2': return 2;
case '3': return 5;
case '4': return 10;
case '5': return 30;
case '6': return 60;
default: return 0;
}
}
}