fix: Bug - Sending files and attachment issues (gallery load and speed)

Route small images through in-memory receive instead of serialized disk
chunk-acks, and improve gallery hydration for local copies and pending
downloads so thumbnails display without minutes-long progress stalls.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-14 13:19:12 +02:00
co-authored by Cursor
parent fa45052432
commit b13f71d2d3
12 changed files with 206 additions and 34 deletions
@@ -104,7 +104,26 @@ export class ChatMessagesComponent {
readonly replyTo = signal<Message | null>(null);
readonly showKlipyGifPicker = signal(false);
readonly lightboxState = signal<ChatLightboxState | null>(null);
readonly galleryAttachments = signal<Attachment[] | null>(null);
readonly galleryMessageId = signal<string | null>(null);
readonly galleryAttachmentOrder = signal<readonly string[]>([]);
readonly galleryAttachments = computed(() => {
const messageId = this.galleryMessageId();
const attachmentIds = this.galleryAttachmentOrder();
void this.attachmentsSvc.updated;
if (!messageId || attachmentIds.length === 0) {
return null;
}
const attachmentsById = new Map(
this.attachmentsSvc.getForMessage(messageId).map((attachment) => [attachment.id, attachment])
);
return attachmentIds
.map((attachmentId) => attachmentsById.get(attachmentId))
.filter((attachment): attachment is Attachment => !!attachment);
});
readonly imageContextMenu = signal<ChatMessageImageContextMenuEvent | null>(null);
constructor() {
@@ -345,13 +364,20 @@ export class ChatMessagesComponent {
return;
}
const messageId = attachments[0]?.messageId;
if (!messageId) {
return;
}
const displayableImages = attachments.filter((attachment) => attachment.available && attachment.objectUrl);
if (displayableImages.length > 0) {
this.attachmentsSvc.pinDisplayBlobs(displayableImages);
}
this.galleryAttachments.set(attachments);
this.galleryMessageId.set(messageId);
this.galleryAttachmentOrder.set(attachments.map((attachment) => attachment.id));
}
closeImageGallery(): void {
@@ -361,7 +387,8 @@ export class ChatMessagesComponent {
this.attachmentsSvc.unpinDisplayBlobs(gallery);
}
this.galleryAttachments.set(null);
this.galleryMessageId.set(null);
this.galleryAttachmentOrder.set([]);
}
openImageContextMenu(event: ChatMessageImageContextMenuEvent): void {
@@ -378,12 +405,14 @@ export class ChatMessagesComponent {
retryGalleryImage(event: ChatMessageAttachmentEvent): void {
const { messageId, attachment } = event;
const liveAttachment = this.attachmentsSvc.getForMessage(messageId).find((entry) => entry.id === attachment.id)
?? attachment;
if ((attachment.receivedBytes ?? 0) > 0 || this.attachmentsSvc.hasPendingRequest(messageId, attachment.id)) {
this.attachmentsSvc.cancelRequest(messageId, attachment);
if ((liveAttachment.receivedBytes ?? 0) > 0 || this.attachmentsSvc.hasPendingRequest(messageId, liveAttachment.id)) {
this.attachmentsSvc.cancelRequest(messageId, liveAttachment);
}
void this.attachmentsSvc.requestImageFromAnyPeer(messageId, attachment);
void this.attachmentsSvc.requestImageFromAnyPeer(messageId, liveAttachment);
}
cancelGalleryImage(event: ChatMessageAttachmentEvent): void {