diff --git a/scripts/capture-quietware-screenshots.mjs b/scripts/capture-quietware-screenshots.mjs index 535ef72..2ebbc0d 100644 --- a/scripts/capture-quietware-screenshots.mjs +++ b/scripts/capture-quietware-screenshots.mjs @@ -103,5 +103,25 @@ try { console.error(`files page skipped: ${e.message}`); } +// History page — SPA navigation via the sidebar item. +try { + console.log("\n=== history page (best effort) ==="); + await page.evaluate(() => { + const items = Array.from(document.querySelectorAll('button, a, [role="button"], li')); + const target = items.find(el => (el.textContent || "").trim().toLowerCase() === "history"); + if (target) target.click(); + }); + await page.waitForTimeout(1500); + for (const mode of MODES.slice(1, 3)) { + await setMode(mode); + await page.waitForTimeout(400); + const file = `${OUT}/history__${mode.id}.png`; + await page.screenshot({ path: file, fullPage: false }); + console.log(` history ${mode.id}`); + } +} catch (e) { + console.error(`history page skipped: ${e.message}`); +} + await browser.close(); console.log(`\nWrote screenshots to ${OUT}/`); diff --git a/src/lib/pages/HistoryPage.svelte b/src/lib/pages/HistoryPage.svelte index f6eb36f..1d65f58 100644 --- a/src/lib/pages/HistoryPage.svelte +++ b/src/lib/pages/HistoryPage.svelte @@ -25,7 +25,11 @@ import LumotiaCard from "$lib/ui/LumotiaCard.svelte"; import LumotiaEmptyState from "$lib/ui/LumotiaEmptyState.svelte"; import LumotiaButton from "$lib/ui/LumotiaButton.svelte"; - import { formatTime, formatDuration } from "$lib/utils/time.js"; + import LumotiaNotice from "$lib/ui/LumotiaNotice.svelte"; + // v0.3 Phase 5f — quietware History layout. + import LumotiaPageSkeleton from "$lib/ui/LumotiaPageSkeleton.svelte"; + import { onMount } from "svelte"; + import { formatTime, formatDuration, formatTimestamp } from "$lib/utils/time.js"; import { PLAYBACK_SPEEDS } from "$lib/utils/constants.js"; import { Search, Clock, Play, Pause, FileText, Mic, ChevronDown, ExternalLink, Star, Tag } from 'lucide-svelte'; @@ -203,7 +207,27 @@ : "" ); + // v0.3 Phase 5f — quietware layout switch. Same observer pattern + // as Dictation / Files. v0.2 surface unchanged without quietware. + let isQuietware = $state(false); + let quietwareObserver: MutationObserver | null = null; + + onMount(() => { + if (typeof document === "undefined") return; + const sync = () => { + isQuietware = document.documentElement.dataset.design === "quietware"; + }; + sync(); + quietwareObserver = new MutationObserver(sync); + quietwareObserver.observe(document.documentElement, { + attributes: true, + attributeFilter: ["data-design"], + }); + }); + onDestroy(() => { + quietwareObserver?.disconnect(); + quietwareObserver = null; stopPlayback(); if (bulkDeleteArmTimer) clearTimeout(bulkDeleteArmTimer); }); @@ -683,7 +707,7 @@ }); -
+
@@ -693,6 +717,168 @@ aria-atomic="true" >{confirmAnnouncement}
+ {#if isQuietware} + + + {#snippet header()} +
+
+

History

+

+ {viewMode === "trash" ? "Recover transcripts within 30 days." : "Search and reopen saved transcripts."} +

+
+
+ + +
+
+ {/snippet} + + {#snippet primary()} +
+ {#if trashError && viewMode === "trash"} +
+ trashError = ""}> + {trashError} + +
+ {/if} + + +
+
+
+
+ + +
+ {#if viewMode === "live"} + {#if filtered.length === 0} +
+
+ {:else} +
    + {#each filtered as item (item.id)} +
  • +
    + {#if item.source === "file"} +
    +
    +

    + {item.title || item.preview?.slice(0, 80) || "Untitled"} +

    +

    {compactPreviewText(item)}

    +

    {formatTimestamp(item.savedAt || item.timestamp)}

    +
    +
    + openViewer(item)}>Open + copyItem(item)}>Copy + removeItem(item)}>Delete +
    +
  • + {/each} +
+ {/if} + {:else} + + {#if trashLoading && trashItems.length === 0} +
Loading trash…
+ {:else if trashItems.length === 0} +
+
+ {:else} +
    + {#each trashItems as item (item.id)} +
  • +
    +
    +
    +

    + {item.title || item.preview?.slice(0, 80) || "Untitled"} +

    +

    {item.preview || ""}

    +

    Deleted {formatTrashTimestamp(item.deleted_at)}

    +
    +
    + restoreFromTrash(item.id)} + >{restoringId === item.id ? "Restoring…" : "Restore"} +
    +
  • + {/each} +
+ {/if} + {/if} +
+
+ {/snippet} + + {#snippet metadata()} +
+ {history.length} saved · {trashItems.length} in trash · Local only +
+ {/snippet} +
+ {:else}

History

@@ -1223,4 +1409,5 @@
{/if} + {/if}