]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/blob
e74bd8456a5484b83af6ad7e95389c71a6605bc6
[pkg/ggml/sources/llama.cpp] /
1 <script lang="ts">
2 import {
3 ChatAttachmentsListItem,
4 DialogChatAttachmentsPreview,
5 DialogMcpResourcePreview,
6 HorizontalScrollCarousel
7 } from '$lib/components/app';
8 import type { DatabaseMessageExtraMcpResource } from '$lib/types';
9 import { getAttachmentDisplayItems, isMcpPrompt, isMcpResource } from '$lib/utils';
10
11 interface Props {
12 class?: string;
13 style?: string;
14 // For ChatMessage - stored attachments
15 attachments?: DatabaseMessageExtra[];
16 readonly?: boolean;
17 // For ChatForm - pending uploads
18 onFileRemove?: (fileId: string) => void;
19 uploadedFiles?: ChatUploadedFile[];
20 // Image size customization
21 imageClass?: string;
22 imageHeight?: string;
23 imageWidth?: string;
24 // Limit display to single row with "+ X more" button
25 limitToSingleRow?: boolean;
26 // For vision modality check
27 activeModelId?: string;
28 }
29
30 let {
31 class: className = '',
32 style = '',
33 attachments = [],
34 readonly = false,
35 onFileRemove,
36 uploadedFiles = $bindable([]),
37 // Default to small size for form previews
38 imageClass = '',
39 imageHeight = 'h-24',
40 imageWidth = 'w-auto',
41 limitToSingleRow = false,
42 activeModelId
43 }: Props = $props();
44
45 let carouselRef: HorizontalScrollCarousel | undefined = $state();
46 let mcpResourcePreviewOpen = $state(false);
47 let mcpResourcePreviewExtra = $state<DatabaseMessageExtraMcpResource | null>(null);
48 let previewFocusIndex = $state(0);
49 let viewAllDialogOpen = $state(false);
50
51 let displayItems = $derived(getAttachmentDisplayItems({ uploadedFiles, attachments }));
52
53 function openPreview(item: ChatAttachmentDisplayItem, event?: MouseEvent) {
54 event?.stopPropagation();
55 event?.preventDefault();
56
57 // Find the index of the clicked item among non-MCP attachments
58 const nonMcpItems = displayItems.filter((i) => !isMcpPrompt(i) && !isMcpResource(i));
59 const index = nonMcpItems.findIndex((i) => i.id === item.id);
60
61 previewFocusIndex = index >= 0 ? index : 0;
62 viewAllDialogOpen = true;
63 }
64
65 function openMcpResourcePreview(extra: DatabaseMessageExtraMcpResource) {
66 mcpResourcePreviewExtra = extra;
67 mcpResourcePreviewOpen = true;
68 }
69
70 $effect(() => {
71 if (carouselRef && displayItems.length) {
72 carouselRef.resetScroll();
73 }
74 });
75 </script>
76
77 {#snippet attachmentitem(item: ChatAttachmentDisplayItem)}
78 <ChatAttachmentsListItem
79 {imageClass}
80 {imageHeight}
81 {imageWidth}
82 {item}
83 {limitToSingleRow}
84 {onFileRemove}
85 onMcpResourcePreview={openMcpResourcePreview}
86 onPreview={(i: ChatAttachmentDisplayItem, event?: MouseEvent) => openPreview(i, event)}
87 {readonly}
88 />
89 {/snippet}
90
91 {#if displayItems.length > 0}
92 <div class={className} {style}>
93 {#if limitToSingleRow}
94 <HorizontalScrollCarousel bind:this={carouselRef}>
95 {#each displayItems as item (item.id)}
96 {@render attachmentitem(item)}
97 {/each}
98 </HorizontalScrollCarousel>
99 {:else}
100 <div class="flex flex-wrap items-start justify-end gap-3">
101 {#each displayItems as item (item.id)}
102 {@render attachmentitem(item)}
103 {/each}
104 </div>
105 {/if}
106 </div>
107 {/if}
108
109 <DialogChatAttachmentsPreview
110 {activeModelId}
111 {attachments}
112 bind:open={viewAllDialogOpen}
113 {previewFocusIndex}
114 {uploadedFiles}
115 />
116
117 {#if mcpResourcePreviewExtra}
118 <DialogMcpResourcePreview extra={mcpResourcePreviewExtra} bind:open={mcpResourcePreviewOpen} />
119 {/if}