feat(briefwechsel): add ConversationThumbnail with aspect + page badge
Reads thumbnailAspect from the backend and swaps between a 120×168 portrait tile and a 168×120 landscape tile so postcards and photos don't get cropped into a portrait frame. Shows a page-count badge top-right for multi-page PDFs, and a pulsing skeleton while the async thumbnail job hasn't run yet. URL assembly goes through the existing thumbnailUrl helper so cache-busting stays consistent with DocumentThumbnail. Refs #305 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
48
frontend/src/lib/components/ConversationThumbnail.svelte
Normal file
48
frontend/src/lib/components/ConversationThumbnail.svelte
Normal file
@@ -0,0 +1,48 @@
|
||||
<script lang="ts">
|
||||
import { thumbnailUrl } from '$lib/thumbnails';
|
||||
|
||||
type Doc = {
|
||||
id: string;
|
||||
thumbnailKey?: string;
|
||||
thumbnailGeneratedAt?: string;
|
||||
thumbnailAspect?: 'PORTRAIT' | 'LANDSCAPE';
|
||||
pageCount?: number;
|
||||
};
|
||||
|
||||
let { doc }: { doc: Doc } = $props();
|
||||
|
||||
const url = $derived(thumbnailUrl(doc));
|
||||
const aspect = $derived(doc.thumbnailAspect ?? 'PORTRAIT');
|
||||
const pageCount = $derived(doc.pageCount ?? 1);
|
||||
const tileClass = $derived(aspect === 'LANDSCAPE' ? 'h-[120px] w-[168px]' : 'h-[168px] w-[120px]');
|
||||
</script>
|
||||
|
||||
<div
|
||||
data-testid="conv-thumb-tile"
|
||||
data-aspect={aspect}
|
||||
class="relative {tileClass} flex-shrink-0 overflow-hidden rounded-sm border border-line bg-white"
|
||||
>
|
||||
{#if url}
|
||||
<img
|
||||
src={url}
|
||||
alt=""
|
||||
class="h-full w-full object-cover object-top dark:mix-blend-multiply"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
{:else}
|
||||
<div
|
||||
data-testid="conv-thumb-skeleton"
|
||||
class="h-full w-full bg-line/60 motion-safe:animate-pulse"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
{/if}
|
||||
|
||||
{#if pageCount > 1}
|
||||
<span
|
||||
data-testid="conv-thumb-page-badge"
|
||||
class="absolute top-1 right-1 rounded-full bg-primary/90 px-1.5 py-0.5 text-xs leading-none font-bold text-surface"
|
||||
>{pageCount}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
Reference in New Issue
Block a user