Hydrate playable media after disk receive, relay file-announce to sibling devices via account_sync, bind DM attachments to pre-allocated message ids, and improve gallery retry/cancel UX with bounded parallel auto-downloads. Co-authored-by: Cursor <cursoragent@cursor.com>
125 lines
4.1 KiB
TypeScript
125 lines
4.1 KiB
TypeScript
import {
|
|
getWatchedAttachmentRoomIdFromUrl,
|
|
isAttachmentPendingMediaHydration,
|
|
isDirectMessageAttachmentRoomId,
|
|
isPlayableAttachmentMedia,
|
|
shouldCopyUploaderMediaToAppData,
|
|
shouldCopyLargeUploaderFileToAppData,
|
|
shouldStreamAttachmentReceiveToDisk,
|
|
canReceiveAttachment
|
|
} from './attachment.logic';
|
|
|
|
describe('attachment logic', () => {
|
|
it('extracts watched server room ids from room URLs', () => {
|
|
expect(getWatchedAttachmentRoomIdFromUrl('/room/general')).toBe('general');
|
|
expect(getWatchedAttachmentRoomIdFromUrl('/room/general/chat')).toBe('general');
|
|
});
|
|
|
|
it('extracts watched direct-message storage ids from DM URLs', () => {
|
|
expect(getWatchedAttachmentRoomIdFromUrl('/dm/alice%3Abob')).toBe('direct-message:alice:bob');
|
|
expect(getWatchedAttachmentRoomIdFromUrl('/pm/dm-group-1?tab=chat')).toBe('direct-message:dm-group-1');
|
|
});
|
|
|
|
it('ignores non-message URLs', () => {
|
|
expect(getWatchedAttachmentRoomIdFromUrl('/settings')).toBeNull();
|
|
expect(getWatchedAttachmentRoomIdFromUrl('/dm')).toBeNull();
|
|
});
|
|
|
|
it('identifies direct-message attachment storage ids', () => {
|
|
expect(isDirectMessageAttachmentRoomId('direct-message:alice:bob')).toBe(true);
|
|
expect(isDirectMessageAttachmentRoomId('room-1')).toBe(false);
|
|
expect(isDirectMessageAttachmentRoomId(null)).toBe(false);
|
|
});
|
|
|
|
it('copies large uploader media into app data when a source path exists', () => {
|
|
expect(shouldCopyUploaderMediaToAppData({
|
|
size: 64 * 1024 * 1024,
|
|
mime: 'video/mp4'
|
|
}, '/home/ludde/video.mp4', true)).toBe(true);
|
|
});
|
|
|
|
it('copies any oversized upload with a source path into app data', () => {
|
|
expect(shouldCopyLargeUploaderFileToAppData({
|
|
size: 628 * 1024 * 1024
|
|
}, '/home/ludde/setup.exe', true)).toBe(true);
|
|
|
|
expect(shouldCopyLargeUploaderFileToAppData({
|
|
size: 1024
|
|
}, '/home/ludde/setup.exe', true)).toBe(false);
|
|
});
|
|
|
|
it('skips app-data copy for small uploads and missing source paths', () => {
|
|
expect(shouldCopyUploaderMediaToAppData({
|
|
size: 1024,
|
|
mime: 'video/mp4'
|
|
}, '/home/ludde/video.mp4', true)).toBe(false);
|
|
|
|
expect(shouldCopyUploaderMediaToAppData({
|
|
size: 64 * 1024 * 1024,
|
|
mime: 'video/mp4'
|
|
}, undefined, true)).toBe(false);
|
|
});
|
|
|
|
it('streams any persistable download to disk when the store supports streaming', () => {
|
|
const capabilities = {
|
|
canStreamToDisk: true,
|
|
canPersistSize: (bytes: number) => bytes <= 256 * 1024 * 1024
|
|
};
|
|
|
|
expect(shouldStreamAttachmentReceiveToDisk({
|
|
size: 200 * 1024 * 1024,
|
|
mime: 'application/zip',
|
|
filePath: undefined
|
|
}, capabilities)).toBe(true);
|
|
|
|
expect(shouldStreamAttachmentReceiveToDisk({
|
|
size: 3,
|
|
mime: 'application/zip',
|
|
filePath: undefined
|
|
}, capabilities)).toBe(true);
|
|
|
|
expect(shouldStreamAttachmentReceiveToDisk({
|
|
size: 200 * 1024 * 1024,
|
|
mime: 'application/zip',
|
|
filePath: '/home/ludde/archive.zip'
|
|
}, capabilities)).toBe(true);
|
|
});
|
|
|
|
it('identifies playable media pending hydration from disk paths', () => {
|
|
expect(isPlayableAttachmentMedia({ mime: 'video/mp4' })).toBe(true);
|
|
expect(isPlayableAttachmentMedia({ mime: 'image/png' })).toBe(false);
|
|
|
|
expect(isAttachmentPendingMediaHydration({
|
|
mime: 'audio/mpeg',
|
|
available: true,
|
|
savedPath: '/data/song.mp3'
|
|
})).toBe(true);
|
|
|
|
expect(isAttachmentPendingMediaHydration({
|
|
mime: 'audio/mpeg',
|
|
available: true,
|
|
objectUrl: 'file:///data/song.mp3',
|
|
savedPath: '/data/song.mp3'
|
|
})).toBe(false);
|
|
});
|
|
|
|
it('receives browser-sized files in memory when disk streaming is unavailable', () => {
|
|
const browserCapabilities = {
|
|
canStreamToDisk: false,
|
|
canPersistSize: (bytes: number) => bytes <= 50 * 1024 * 1024
|
|
};
|
|
|
|
expect(canReceiveAttachment({
|
|
size: 20 * 1024 * 1024,
|
|
mime: 'application/zip',
|
|
filePath: undefined
|
|
}, browserCapabilities)).toBe(true);
|
|
|
|
expect(canReceiveAttachment({
|
|
size: 200 * 1024 * 1024,
|
|
mime: 'application/zip',
|
|
filePath: undefined
|
|
}, browserCapabilities)).toBe(false);
|
|
});
|
|
});
|