|
|
|
@@ -0,0 +1,152 @@
|
|
|
|
|
class GiteaAction {
|
|
|
|
|
constructor($UD, context) {
|
|
|
|
|
this.$UD = $UD;
|
|
|
|
|
this.context = context;
|
|
|
|
|
this.config = {
|
|
|
|
|
url: '',
|
|
|
|
|
owner: '',
|
|
|
|
|
repo: '',
|
|
|
|
|
token: '',
|
|
|
|
|
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() {
|
|
|
|
|
if (this.config.url && this.config.owner && this.config.repo) {
|
|
|
|
|
this.$UD.openUrl(`${this.config.url}/${this.config.owner}/${this.config.repo}/actions`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
start() {
|
|
|
|
|
this.onClear();
|
|
|
|
|
this.fetchRun();
|
|
|
|
|
const duration = this.getRefreshDuration();
|
|
|
|
|
if (duration > 0) {
|
|
|
|
|
this.refreshTimer = setInterval(() => this.fetchRun(), duration * 60 * 1000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fetchRun() {
|
|
|
|
|
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
|
|
|
this.debounceTimer = setTimeout(async () => {
|
|
|
|
|
if (!this.config.url || !this.config.owner || !this.config.repo) {
|
|
|
|
|
this.renderButton(null);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
const headers = this.config.token ? { Authorization: `token ${this.config.token}` } : {};
|
|
|
|
|
const response = await fetch(
|
|
|
|
|
`${this.config.url}/api/v1/repos/${this.config.owner}/${this.config.repo}/actions/runs?limit=1`,
|
|
|
|
|
{ headers }
|
|
|
|
|
);
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
this.renderButton({ error: response.status });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
const run = data.workflow_runs && data.workflow_runs[0];
|
|
|
|
|
this.renderButton(run || null);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
this.renderButton({ error: 'ERR' });
|
|
|
|
|
}
|
|
|
|
|
}, 300);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
renderButton(run) {
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
ctx.textBaseline = 'middle';
|
|
|
|
|
ctx.textAlign = 'center';
|
|
|
|
|
|
|
|
|
|
// Owner — top
|
|
|
|
|
const ownerLabel = this.config.owner || '?';
|
|
|
|
|
ctx.fillStyle = '#888888';
|
|
|
|
|
ctx.font = '18px "Source Han Sans SC"';
|
|
|
|
|
ctx.fillText(ownerLabel.length > 14 ? ownerLabel.slice(0, 13) + '…' : ownerLabel, 98, 22);
|
|
|
|
|
|
|
|
|
|
// Repo name — below owner
|
|
|
|
|
const repoLabel = this.config.repo || '?';
|
|
|
|
|
ctx.fillStyle = '#7ec8e3';
|
|
|
|
|
ctx.font = 'bold 22px "Source Han Sans SC"';
|
|
|
|
|
ctx.fillText(repoLabel.length > 12 ? repoLabel.slice(0, 11) + '…' : repoLabel, 98, 46);
|
|
|
|
|
|
|
|
|
|
// Status symbol — center
|
|
|
|
|
let symbol, color;
|
|
|
|
|
if (!run) {
|
|
|
|
|
symbol = '?';
|
|
|
|
|
color = '#666666';
|
|
|
|
|
} else if (run.error) {
|
|
|
|
|
symbol = '✗';
|
|
|
|
|
color = '#ff6b6b';
|
|
|
|
|
} else if (run.status === 'running' || run.status === 'waiting') {
|
|
|
|
|
symbol = '⟳';
|
|
|
|
|
color = '#f0c040';
|
|
|
|
|
} else if (run.conclusion === 'success') {
|
|
|
|
|
symbol = '✓';
|
|
|
|
|
color = '#6bff6b';
|
|
|
|
|
} else if (run.conclusion === 'failure') {
|
|
|
|
|
symbol = '✗';
|
|
|
|
|
color = '#ff6b6b';
|
|
|
|
|
} else if (run.conclusion === 'cancelled') {
|
|
|
|
|
symbol = '⊘';
|
|
|
|
|
color = '#aaaaaa';
|
|
|
|
|
} else {
|
|
|
|
|
symbol = '?';
|
|
|
|
|
color = '#666666';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx.fillStyle = color;
|
|
|
|
|
ctx.font = 'bold 76px "Source Han Sans SC"';
|
|
|
|
|
ctx.fillText(symbol, 98, 115);
|
|
|
|
|
|
|
|
|
|
// Run info — bottom, single line
|
|
|
|
|
if (run && !run.error) {
|
|
|
|
|
const branch = run.head_branch || '';
|
|
|
|
|
const num = `#${run.run_number}`;
|
|
|
|
|
const info = branch ? `${num} · ${branch}` : num;
|
|
|
|
|
ctx.fillStyle = '#aaaaaa';
|
|
|
|
|
ctx.font = 'bold 20px "Source Han Sans SC"';
|
|
|
|
|
ctx.fillText(info.length > 16 ? info.slice(0, 15) + '…' : info, 98, 172);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|