diff --git a/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentThumbnailFile.svelte b/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentThumbnailFile.svelte
index cecdc784c9..73ef7852e1 100644
--- a/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentThumbnailFile.svelte
+++ b/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentThumbnailFile.svelte
@@ -145,7 +145,9 @@
{name}
diff --git a/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentsList.svelte b/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentsList.svelte
index 46fc2d4313..7e29df60b0 100644
--- a/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentsList.svelte
+++ b/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentsList.svelte
@@ -2,10 +2,8 @@
import { ChatAttachmentThumbnailImage, ChatAttachmentThumbnailFile } from '$lib/components/app';
import { Button } from '$lib/components/ui/button';
import { ChevronLeft, ChevronRight } from '@lucide/svelte';
- import { getFileTypeCategory } from '$lib/utils/file-type';
- import { FileTypeCategory } from '$lib/enums';
- import { isImageFile } from '$lib/utils/attachment-type';
import { DialogChatAttachmentPreview, DialogChatAttachmentsViewAll } from '$lib/components/app';
+ import { getAttachmentDisplayItems } from '$lib/utils/attachment-display';
import type { ChatAttachmentDisplayItem, ChatAttachmentPreviewItem } from '$lib/types/chat';
import type { DatabaseMessageExtra } from '$lib/types/database';
@@ -40,7 +38,7 @@
limitToSingleRow = false
}: Props = $props();
- let displayItems = $derived(getDisplayItems());
+ let displayItems = $derived(getAttachmentDisplayItems({ uploadedFiles, attachments }));
let canScrollLeft = $state(false);
let canScrollRight = $state(false);
@@ -51,40 +49,6 @@
let showViewAll = $derived(limitToSingleRow && displayItems.length > 0 && isScrollable);
let viewAllDialogOpen = $state(false);
- function getDisplayItems(): ChatAttachmentDisplayItem[] {
- const items: ChatAttachmentDisplayItem[] = [];
-
- // Add uploaded files (ChatForm)
- for (const file of uploadedFiles) {
- items.push({
- id: file.id,
- name: file.name,
- size: file.size,
- preview: file.preview,
- isImage: getFileTypeCategory(file.type) === FileTypeCategory.IMAGE,
- uploadedFile: file,
- textContent: file.textContent
- });
- }
-
- // Add stored attachments (ChatMessage)
- for (const [index, attachment] of attachments.entries()) {
- const isImage = isImageFile(attachment);
-
- items.push({
- id: `attachment-${index}`,
- name: attachment.name,
- preview: isImage && 'base64Url' in attachment ? attachment.base64Url : undefined,
- isImage,
- attachment,
- attachmentIndex: index,
- textContent: 'content' in attachment ? attachment.content : undefined
- });
- }
-
- return items.reverse();
- }
-
function openPreview(item: ChatAttachmentDisplayItem, event?: MouseEvent) {
event?.stopPropagation();
event?.preventDefault();
@@ -218,7 +182,7 @@
{/if}
{:else}
-
+
{#each displayItems as item (item.id)}
{#if item.isImage && item.preview}
(null);
- let displayItems = $derived(getDisplayItems());
+ let displayItems = $derived(getAttachmentDisplayItems({ uploadedFiles, attachments }));
let imageItems = $derived(displayItems.filter((item) => item.isImage));
let fileItems = $derived(displayItems.filter((item) => !item.isImage));
- function getDisplayItems(): ChatAttachmentDisplayItem[] {
- const items: ChatAttachmentDisplayItem[] = [];
-
- for (const file of uploadedFiles) {
- items.push({
- id: file.id,
- name: file.name,
- size: file.size,
- preview: file.preview,
- isImage: getFileTypeCategory(file.type) === FileTypeCategory.IMAGE,
- uploadedFile: file,
- textContent: file.textContent
- });
- }
-
- for (const [index, attachment] of attachments.entries()) {
- const isImage = isImageFile(attachment);
-
- items.push({
- id: `attachment-${index}`,
- name: attachment.name,
- preview: isImage && 'base64Url' in attachment ? attachment.base64Url : undefined,
- isImage,
- attachment,
- attachmentIndex: index,
- textContent: 'content' in attachment ? attachment.content : undefined
- });
- }
-
- return items.reverse();
- }
-
function openPreview(item: (typeof displayItems)[0], event?: Event) {
if (event) {
event.preventDefault();
diff --git a/tools/server/webui/src/lib/utils/attachment-display.ts b/tools/server/webui/src/lib/utils/attachment-display.ts
new file mode 100644
index 0000000000..1fc166a881
--- /dev/null
+++ b/tools/server/webui/src/lib/utils/attachment-display.ts
@@ -0,0 +1,51 @@
+import { FileTypeCategory } from '$lib/enums';
+import type { ChatAttachmentDisplayItem } from '$lib/types/chat';
+import type { DatabaseMessageExtra } from '$lib/types/database';
+import { isImageFile } from '$lib/utils/attachment-type';
+import { getFileTypeCategory } from '$lib/utils/file-type';
+
+export interface AttachmentDisplayItemsOptions {
+ uploadedFiles?: ChatUploadedFile[];
+ attachments?: DatabaseMessageExtra[];
+}
+
+/**
+ * Creates a unified list of display items from uploaded files and stored attachments.
+ * Items are returned in reverse order (newest first).
+ */
+export function getAttachmentDisplayItems(
+ options: AttachmentDisplayItemsOptions
+): ChatAttachmentDisplayItem[] {
+ const { uploadedFiles = [], attachments = [] } = options;
+ const items: ChatAttachmentDisplayItem[] = [];
+
+ // Add uploaded files (ChatForm)
+ for (const file of uploadedFiles) {
+ items.push({
+ id: file.id,
+ name: file.name,
+ size: file.size,
+ preview: file.preview,
+ isImage: getFileTypeCategory(file.type) === FileTypeCategory.IMAGE,
+ uploadedFile: file,
+ textContent: file.textContent
+ });
+ }
+
+ // Add stored attachments (ChatMessage)
+ for (const [index, attachment] of attachments.entries()) {
+ const isImage = isImageFile(attachment);
+
+ items.push({
+ id: `attachment-${index}`,
+ name: attachment.name,
+ preview: isImage && 'base64Url' in attachment ? attachment.base64Url : undefined,
+ isImage,
+ attachment,
+ attachmentIndex: index,
+ textContent: 'content' in attachment ? attachment.content : undefined
+ });
+ }
+
+ return items.reverse();
+}