diff --git a/vite/src/pipedal/Tone3000Downloader.tsx b/vite/src/pipedal/Tone3000Downloader.tsx index 97a3369..b14bf5a 100644 --- a/vite/src/pipedal/Tone3000Downloader.tsx +++ b/vite/src/pipedal/Tone3000Downloader.tsx @@ -236,6 +236,11 @@ export class Tone3000DownloadHandler { responseUri); if (!tokenResponse.ok) { + if (tokenResponse.canceled === true) + { + this.onTone3000DownloadComplete(""); + return; + } throw new Error(tokenResponse.error); } if (tokenResponse.canceled) { diff --git a/vite/src/pipedal/t3k/tone3000-client.ts b/vite/src/pipedal/t3k/tone3000-client.ts index 36d6d91..c1c8e28 100644 --- a/vite/src/pipedal/t3k/tone3000-client.ts +++ b/vite/src/pipedal/t3k/tone3000-client.ts @@ -69,7 +69,7 @@ export interface T3KTokens { /** Result of handleOAuthCallback(). Always check `ok` before using fields. */ export type OAuthCallbackResult = | { ok: true; tokens: T3KTokens; toneId?: string; modelId?: string; canceled?: boolean } - | { ok: false; error: string }; + | { ok: false; error: string, canceled?: boolean }; // ─── Internal PKCE helpers ──────────────────────────────────────────────────── @@ -216,7 +216,7 @@ export async function handleOAuthCallbackFromPopup( if (returnedState !== storedState) return { ok: false, error: 'state_mismatch' }; // User closed without signing in — no code to exchange - if (canceled && !code) return { ok: false, error: 'canceled' }; + if (canceled && !code) return { ok: false, error: 'canceled', canceled: true }; if (error) return { ok: false, error }; if (!code || !codeVerifier) return { ok: false, error: 'missing_code' }; @@ -496,7 +496,7 @@ export async function handleOAuthCallback( // User closed without signing in — no code to exchange if (canceled && !code) { - return { ok: false, error: 'canceled' }; + return { ok: false, error: 'canceled', canceled: true }; } // Access denied — e.g. model is private and user clicked "Back"