Files
thoughtsync/frontend/src/stores/ui.ts
T
bvandeusenandClaude Opus 4.8 d3bb091f73
CI & Build / Python lint (push) Successful in 2s
CI & Build / TypeScript typecheck (push) Successful in 5s
CI & Build / Python tests (push) Successful in 10s
CI & Build / Build & push image (push) Successful in 31s
m4: global API-error surface (no more silent failures)
The api client now catches network failures and non-JSON bodies robustly,
and routes unexpected errors (offline / 5xx) to a global toast — 4xx stay
with the caller so forms keep their inline messages. Toast actions are now
optional (undo toasts keep their button; error toasts are message-only), and
ToastHost moved from AppShell to the app root so toasts show everywhere,
including the login screen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
2026-07-21 00:07:04 -04:00

52 lines
1.3 KiB
TypeScript

import { defineStore } from "pinia";
import { ref } from "vue";
interface ToastAction {
label: string;
run: () => void;
}
interface Toast {
id: number;
message: string;
action?: ToastAction;
}
// Cross-component UI signals that don't belong to any single view (e.g. a
// global shortcut in the app shell asking the board to act).
export const useUiStore = defineStore("ui", () => {
// Bumped to ask the board to open + focus its quick-add composer.
const composeTick = ref(0);
function requestCompose() {
composeTick.value++;
}
// Transient undo toast (e.g. after trash/archive).
const toast = ref<Toast | null>(null);
let toastTimer: ReturnType<typeof setTimeout> | undefined;
let toastSeq = 0;
function showToast(message: string, action?: ToastAction) {
toastSeq += 1;
const id = toastSeq;
toast.value = { id, message, action };
clearTimeout(toastTimer);
toastTimer = setTimeout(() => {
if (toast.value?.id === id) toast.value = null;
}, 5000);
}
function dismissToast() {
clearTimeout(toastTimer);
toast.value = null;
}
function runToastAction() {
const run = toast.value?.action?.run;
dismissToast();
run?.();
}
return { composeTick, requestCompose, toast, showToast, dismissToast, runToastAction };
});