diff --git a/com.pdma.notion-timer.sdPlugin/bin/plugin.js b/com.pdma.notion-timer.sdPlugin/bin/plugin.js index 9e8a650..a0451ff 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.32"; +var CURRENT_VERSION = "1.0.33"; var GITEA_BASE = "https://gitea.pdmarf.co.uk/pdm/stream_deck_notion_timer/raw/branch/stable-rebuild"; var SIGNING_PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- MCowBQYDK2VwAyEAN7ko8TUpuPzPAJuKAZCRjV0c4ZSlou5d9pUAF6o12b4= @@ -6593,10 +6593,18 @@ var TimerToggle = class extends SingletonAction { } async onKeyDown(ev) { this.settingsCache.set(ev.action.id, ev.payload.settings); - const global = await getGlobal(); const { projectId, projectName, activeEntryId } = ev.payload.settings; const title = buttonTitle(projectName || ""); + if (projectId) { + if (activeEntryId) { + await Promise.all([ev.action.setState(0), ev.action.setTitle(title)]); + } else { + await Promise.all([ev.action.setState(1), ev.action.setTitle(`\u23F1 ${title}`)]); + } + } + const global = await getGlobal(); if (!isConfigured(global)) { + await Promise.all([ev.action.setState(activeEntryId ? 1 : 0), ev.action.setTitle(activeEntryId ? `\u23F1 ${title}` : title)]); await ev.action.showAlert(); return; } @@ -6610,8 +6618,6 @@ var TimerToggle = class extends SingletonAction { const stopped = { ...ev.payload.settings, activeEntryId: null }; await ev.action.setSettings(stopped); this.settingsCache.set(ev.action.id, stopped); - await ev.action.setState(0); - await ev.action.setTitle(title); await setRunningEntry(null); } else { const prevEntryId = await getRunningEntryId(); @@ -6623,9 +6629,6 @@ var TimerToggle = class extends SingletonAction { await Promise.all([other.setState(0), other.setTitle(buttonTitle(otherSettings.projectName || ""))]); } } - } - await Promise.all([ev.action.setState(1), ev.action.setTitle(`\u23F1 ${title}`)]); - if (prevEntryId) { await stopTimer(global.notionToken, prevEntryId); for (const other of this.actions) { if (other.id === ev.action.id) continue; @@ -6651,6 +6654,7 @@ var TimerToggle = class extends SingletonAction { await Promise.all([ev.action.setState(1), ev.action.setTitle(`\u23F1 ${title}`)]); } } catch (err) { + await Promise.all([ev.action.setState(activeEntryId ? 1 : 0), ev.action.setTitle(activeEntryId ? `\u23F1 ${title}` : title)]); plugin_default.logger.error("Timer toggle failed:", err); await ev.action.showAlert(); } diff --git a/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig b/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig index 94ef762..16c9287 100644 --- a/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig +++ b/com.pdma.notion-timer.sdPlugin/bin/plugin.js.sig @@ -1 +1 @@ -"4-8peOc"uɻS>g-#&ÓqN0vZI \ No newline at end of file +YÈZGæ9⹸ ]WjB=1+nA ;c%:`k \ No newline at end of file diff --git a/com.pdma.notion-timer.sdPlugin/manifest.json b/com.pdma.notion-timer.sdPlugin/manifest.json index 07e5bb8..90dce3e 100644 --- a/com.pdma.notion-timer.sdPlugin/manifest.json +++ b/com.pdma.notion-timer.sdPlugin/manifest.json @@ -2,7 +2,7 @@ "Author": "Pete Marfleet", "Description": "Toggle Notion time tracking for a project with a single button press.", "Name": "Notion Timer", - "Version": "1.0.32", + "Version": "1.0.33", "SDKVersion": 2, "Software": { "MinimumVersion": "5.0" }, "OS": [{ "Platform": "mac", "MinimumVersion": "10.11" }], diff --git a/notion-timer.streamDeckPlugin b/notion-timer.streamDeckPlugin index 0d30ca6..7d03184 100644 Binary files a/notion-timer.streamDeckPlugin and b/notion-timer.streamDeckPlugin differ diff --git a/src/plugin.ts b/src/plugin.ts index 76aaeef..6d19266 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,4 +1,4 @@ -const CURRENT_VERSION = "1.0.32"; +const CURRENT_VERSION = "1.0.33"; const GITEA_BASE = "https://gitea.pdmarf.co.uk/pdm/stream_deck_notion_timer/raw/branch/stable-rebuild"; const SIGNING_PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- MCowBQYDK2VwAyEAN7ko8TUpuPzPAJuKAZCRjV0c4ZSlou5d9pUAF6o12b4= @@ -198,11 +198,22 @@ class TimerToggle extends SingletonAction { async onKeyDown(ev: KeyDownEvent): Promise { this.settingsCache.set(ev.action.id, ev.payload.settings); - const global = await getGlobal(); const { projectId, projectName, activeEntryId } = ev.payload.settings; const title = buttonTitle(projectName || ""); + // Instant visual feedback before any async work + if (projectId) { + if (activeEntryId) { + await Promise.all([ev.action.setState(0), ev.action.setTitle(title)]); + } else { + await Promise.all([ev.action.setState(1), ev.action.setTitle(`⏱ ${title}`)]); + } + } + + const global = await getGlobal(); + if (!isConfigured(global)) { + await Promise.all([ev.action.setState(activeEntryId ? 1 : 0), ev.action.setTitle(activeEntryId ? `⏱ ${title}` : title)]); await ev.action.showAlert(); return; } @@ -218,13 +229,11 @@ class TimerToggle extends SingletonAction { const stopped = { ...ev.payload.settings, activeEntryId: null }; await ev.action.setSettings(stopped); this.settingsCache.set(ev.action.id, stopped); - await ev.action.setState(0); - await ev.action.setTitle(title); await setRunningEntry(null); } else { const prevEntryId = await getRunningEntryId(); - // Optimistically update visuals immediately — no waiting for API + // Turn off the previously running button immediately if (prevEntryId) { for (const other of this.actions) { if (other.id === ev.action.id) continue; @@ -233,11 +242,6 @@ class TimerToggle extends SingletonAction { await Promise.all([other.setState(0), other.setTitle(buttonTitle(otherSettings.projectName || ""))]); } } - } - await Promise.all([ev.action.setState(1), ev.action.setTitle(`⏱ ${title}`)]); - - // Now do the API calls - if (prevEntryId) { await stopTimer(global.notionToken, prevEntryId); for (const other of this.actions) { if (other.id === ev.action.id) continue; @@ -261,10 +265,12 @@ class TimerToggle extends SingletonAction { await ev.action.setSettings(started); this.settingsCache.set(ev.action.id, started); await setRunningEntry(entryId); - // Re-assert state after setSettings, which can reset visual state + // Re-assert after setSettings resets visual state await Promise.all([ev.action.setState(1), ev.action.setTitle(`⏱ ${title}`)]); } } catch (err) { + // Revert optimistic visual on error + await Promise.all([ev.action.setState(activeEntryId ? 1 : 0), ev.action.setTitle(activeEntryId ? `⏱ ${title}` : title)]); streamDeck.logger.error("Timer toggle failed:", err); await ev.action.showAlert(); } diff --git a/version.json b/version.json index 5d8d496..5c1b696 100644 --- a/version.json +++ b/version.json @@ -1 +1 @@ -{ "version": "1.0.32" } +{ "version": "1.0.33" }