diff --git a/com.pdma.notion-timer.sdPlugin/bin/plugin.js b/com.pdma.notion-timer.sdPlugin/bin/plugin.js index ec3f8d8..e543330 100644 --- a/com.pdma.notion-timer.sdPlugin/bin/plugin.js +++ b/com.pdma.notion-timer.sdPlugin/bin/plugin.js @@ -6438,7 +6438,7 @@ async function stopTimer(token, entryId) { } // src/plugin.ts -var CURRENT_VERSION = "1.0.15"; +var CURRENT_VERSION = "1.0.16"; var GITEA_BASE = "https://gitea.pdmarf.co.uk/pdm/stream_deck_notion_timer/raw/branch/master"; var SIGNING_PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- MCowBQYDK2VwAyEAN7ko8TUpuPzPAJuKAZCRjV0c4ZSlou5d9pUAF6o12b4= @@ -6456,24 +6456,35 @@ function fetchWithTimeout2(url) { const timer = setTimeout(() => controller.abort(), 1e4); return fetch(url, { signal: controller.signal }).finally(() => clearTimeout(timer)); } -async function checkForUpdates() { +async function checkForUpdates(sendStatus) { try { const resp = await fetchWithTimeout2(`${GITEA_BASE}/version.json`); - if (!resp.ok) return; + if (!resp.ok) { + sendStatus?.("Update check failed"); + return; + } const { version } = await resp.json(); if (!/^\d+\.\d+\.\d+$/.test(version)) return; - if (!isNewerVersion(version, CURRENT_VERSION)) return; + if (!isNewerVersion(version, CURRENT_VERSION)) { + sendStatus?.(`Already up to date (v${CURRENT_VERSION})`); + return; + } + sendStatus?.(`Updating to v${version}\u2026`); const [pluginResp, sigResp] = await Promise.all([ fetchWithTimeout2(`${GITEA_BASE}/com.pdma.notion-timer.sdPlugin/bin/plugin.js`), fetchWithTimeout2(`${GITEA_BASE}/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig`) ]); - if (!pluginResp.ok || !sigResp.ok) return; + if (!pluginResp.ok || !sigResp.ok) { + sendStatus?.("Download failed"); + return; + } const newCode = await pluginResp.text(); const sigBytes = Buffer.from(await sigResp.arrayBuffer()); const { verify } = await import("node:crypto"); const valid = verify(null, Buffer.from(newCode), SIGNING_PUBLIC_KEY, sigBytes); if (!valid) { plugin_default.logger.error("Update rejected: signature verification failed"); + sendStatus?.("Update rejected: invalid signature"); return; } const fs3 = await import("fs"); @@ -6481,7 +6492,9 @@ async function checkForUpdates() { plugin_default.logger.info(`Updated to ${version}, restarting\u2026`); process.exit(0); } catch (err) { - plugin_default.logger.error(`Update check failed: ${err instanceof Error ? err.message : String(err)}`); + const msg = err instanceof Error ? err.message : String(err); + plugin_default.logger.error(`Update check failed: ${msg}`); + sendStatus?.(`Error: ${msg}`); } } var HARDCODED = { @@ -6621,6 +6634,11 @@ plugin_default.ui.onSendToPlugin(async (ev) => { const title = buttonTitle(ev.payload.settings.projectName || ""); if (title) await ev.action.setTitle(title); } + if (ev.payload.event === "checkForUpdates") { + const send = (msg) => plugin_default.ui.sendToPropertyInspector({ event: "updateStatus", message: msg }); + send("Checking\u2026"); + await checkForUpdates(send); + } }); plugin_default.connect(); setTimeout(() => checkForUpdates(), 1e4); diff --git a/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig b/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig index 99f1a51..2165063 100644 Binary files a/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig and b/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig differ diff --git a/com.pdma.notion-timer.sdPlugin/ui/property-inspector.html b/com.pdma.notion-timer.sdPlugin/ui/property-inspector.html index 355496b..3d5de35 100644 --- a/com.pdma.notion-timer.sdPlugin/ui/property-inspector.html +++ b/com.pdma.notion-timer.sdPlugin/ui/property-inspector.html @@ -88,6 +88,26 @@ } #credStatus.ok { color: #4caf50; } #credStatus.error { color: #e57373; } + #updateBtn { + display: block; + width: 100%; + margin-top: 10px; + padding: 6px; + background: #2a2a2a; + border: 1px solid #444; + border-radius: 4px; + color: #ccc; + font-size: 12px; + cursor: pointer; + } + #updateBtn:hover { background: #333; } + #updateStatus { + font-size: 11px; + color: #888; + text-align: center; + margin-top: 4px; + min-height: 14px; + } @@ -125,6 +145,8 @@

+ +

@@ -229,6 +251,10 @@ document.getElementById("projectSelect").addEventListener("change", save); document.getElementById("notionToken").addEventListener("input", scheduleCredSave); document.getElementById("userId").addEventListener("change", saveCredentials); + document.getElementById("updateBtn").addEventListener("click", function() { + document.getElementById("updateStatus").textContent = ""; + $PI.sendToPlugin({ event: "checkForUpdates" }); + }); }); $PI.onDidReceiveGlobalSettings(function(jsn) { @@ -268,6 +294,9 @@ $PI.onSendToPropertyInspector(ACTION_UUID, function(jsn) { var payload = jsn.payload; + if (payload.event === "updateStatus") { + document.getElementById("updateStatus").textContent = payload.message; + } if (payload.event === "projects") { if (payload.version) { document.getElementById("versionText").textContent = "v" + payload.version; diff --git a/notion-timer.streamDeckPlugin b/notion-timer.streamDeckPlugin index 36aadc8..17e3a2b 100644 Binary files a/notion-timer.streamDeckPlugin and b/notion-timer.streamDeckPlugin differ diff --git a/src/plugin.ts b/src/plugin.ts index 4c0599b..2ea2919 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,4 +1,4 @@ -const CURRENT_VERSION = "1.0.15"; +const CURRENT_VERSION = "1.0.16"; const GITEA_BASE = "https://gitea.pdmarf.co.uk/pdm/stream_deck_notion_timer/raw/branch/master"; const SIGNING_PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- MCowBQYDK2VwAyEAN7ko8TUpuPzPAJuKAZCRjV0c4ZSlou5d9pUAF6o12b4= @@ -19,19 +19,23 @@ function fetchWithTimeout(url: string): Promise { return fetch(url, { signal: controller.signal }).finally(() => clearTimeout(timer)); } -async function checkForUpdates(): Promise { +async function checkForUpdates(sendStatus?: (msg: string) => void): Promise { try { const resp = await fetchWithTimeout(`${GITEA_BASE}/version.json`); - if (!resp.ok) return; + if (!resp.ok) { sendStatus?.("Update check failed"); return; } const { version } = await resp.json() as { version: string }; if (!/^\d+\.\d+\.\d+$/.test(version)) return; - if (!isNewerVersion(version, CURRENT_VERSION)) return; + if (!isNewerVersion(version, CURRENT_VERSION)) { + sendStatus?.(`Already up to date (v${CURRENT_VERSION})`); + return; + } + sendStatus?.(`Updating to v${version}…`); const [pluginResp, sigResp] = await Promise.all([ fetchWithTimeout(`${GITEA_BASE}/com.pdma.notion-timer.sdPlugin/bin/plugin.js`), fetchWithTimeout(`${GITEA_BASE}/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig`), ]); - if (!pluginResp.ok || !sigResp.ok) return; + if (!pluginResp.ok || !sigResp.ok) { sendStatus?.("Download failed"); return; } const newCode = await pluginResp.text(); const sigBytes = Buffer.from(await sigResp.arrayBuffer()); @@ -40,6 +44,7 @@ async function checkForUpdates(): Promise { const valid = verify(null, Buffer.from(newCode), SIGNING_PUBLIC_KEY, sigBytes); if (!valid) { streamDeck.logger.error("Update rejected: signature verification failed"); + sendStatus?.("Update rejected: invalid signature"); return; } @@ -48,7 +53,9 @@ async function checkForUpdates(): Promise { streamDeck.logger.info(`Updated to ${version}, restarting…`); process.exit(0); } catch (err) { - streamDeck.logger.error(`Update check failed: ${err instanceof Error ? err.message : String(err)}`); + const msg = err instanceof Error ? err.message : String(err); + streamDeck.logger.error(`Update check failed: ${msg}`); + sendStatus?.(`Error: ${msg}`); } } @@ -235,6 +242,11 @@ streamDeck.ui.onSendToPlugin<{ event: string; settings?: TimerSettings }>(async const title = buttonTitle(ev.payload.settings.projectName || ""); if (title) await ev.action.setTitle(title); } + if (ev.payload.event === "checkForUpdates") { + const send = (msg: string) => streamDeck.ui.sendToPropertyInspector({ event: "updateStatus", message: msg }); + send("Checking…"); + await checkForUpdates(send); + } }); streamDeck.connect(); diff --git a/version.json b/version.json index b0b51e1..8c7047a 100644 --- a/version.json +++ b/version.json @@ -1 +1 @@ -{ "version": "1.0.15" } +{ "version": "1.0.16" }