diff --git a/package-lock.json b/package-lock.json index 1d508c3..795a2c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@angular/forms": "^21.2.0", "@angular/platform-browser": "^21.2.0", "@angular/router": "^21.2.0", - "@chatenium/chatenium-sdk": "^1.1.2", + "@chatenium/chatenium-sdk": "^1.1.3", "@ngx-translate/core": "^17.0.0", "@ngx-translate/http-loader": "^17.0.0", "@taiga-ui/addon-charts": "^5.1.0", @@ -988,9 +988,9 @@ } }, "node_modules/@chatenium/chatenium-sdk": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@chatenium/chatenium-sdk/-/chatenium-sdk-1.1.2.tgz", - "integrity": "sha512-MYUdi1zxcsSUlf1JADU7HNU6zxPejNuspbt+9P3iUBI2ecHWzhqSdcQRR+OMEe0UThl7QNIlZrt0yl15/4fjYQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@chatenium/chatenium-sdk/-/chatenium-sdk-1.1.3.tgz", + "integrity": "sha512-y1+ls4MnMu9/t0vWtQEjIw1QPwk0peQbdEx738xu8OgxD/0nEBn6SGhhnesPHcQmdnkhZe/xiRVrIlDmZxGUHg==", "dependencies": { "@faker-js/faker": "^10.4.0", "axios": "^1.14.0", diff --git a/package.json b/package.json index 67da03f..60c1ecf 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "@angular/forms": "^21.2.0", "@angular/platform-browser": "^21.2.0", "@angular/router": "^21.2.0", - "@chatenium/chatenium-sdk": "^1.1.2", + "@chatenium/chatenium-sdk": "^1.1.3", "@ngx-translate/core": "^17.0.0", "@ngx-translate/http-loader": "^17.0.0", "@taiga-ui/addon-charts": "^5.1.0", diff --git a/src/app/chat/dm/dm.ts b/src/app/chat/dm/dm.ts index 013daa8..2c89400 100644 --- a/src/app/chat/dm/dm.ts +++ b/src/app/chat/dm/dm.ts @@ -44,6 +44,9 @@ export class Dm implements OnInit { if (session != null) { let attachments: Attachment[] = [] files?.forEach(file => { + const extraMetaData: Record = {} + extraMetaData["thumbnailMetaData"] = file.videoThumbnail ?? "" + attachments.push({ fileName: file.name, fileId: file.fileId, @@ -52,7 +55,7 @@ export class Dm implements OnInit { path: file.blob, height: file.height, width: file.width, - localVideoThumbnail: file.videoThumbnail + extraMetaData: extraMetaData }) }) diff --git a/src/app/chat/elements/message-box/message-box.ts b/src/app/chat/elements/message-box/message-box.ts index f08211e..0f55039 100644 --- a/src/app/chat/elements/message-box/message-box.ts +++ b/src/app/chat/elements/message-box/message-box.ts @@ -127,7 +127,6 @@ export class MessageBox { width = videoData.width } - console.log("push") this.viewModel().files().push({ fileId: uuidv4(), data: file, @@ -169,30 +168,39 @@ export class MessageBox { const objectUrl = URL.createObjectURL(file); const video = document.createElement('video'); video.src = objectUrl; - video.crossOrigin = 'anonymous'; + video.preload = 'metadata'; // Ensure metadata is loaded video.muted = true; + video.playsInline = true; return new Promise((resolve) => { - video.addEventListener('loadeddata', async () => { - video.currentTime = 0; + video.addEventListener('loadeddata', () => { + // Step 1: Seek to a tiny bit past 0 to ensure a frame is available + video.currentTime = 0.1; + }); + video.addEventListener('seeked', async () => { + // Step 2: Now that the seek is done, the frame is ready const canvas = document.createElement('canvas'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; const ctx = canvas.getContext('2d'); ctx!.drawImage(video, 0, 0, canvas.width, canvas.height); - const thumbnail = canvas.toDataURL('image/jpeg') - const thumbnailResp = await fetch(thumbnail); - const thumbnailBlob = await thumbnailResp.blob(); - const thumbnailBlobUrl = URL.createObjectURL(thumbnailBlob); - resolve({ - thumbnailBlob: thumbnailBlobUrl, - height: video.videoHeight, - width: video.videoWidth, - }); - }); + // Clean up: Convert directly to blob to avoid double-processing + canvas.toBlob((blob) => { + const thumbnailBlobUrl = URL.createObjectURL(blob!); + + // Revoke the original video URL to save memory + URL.revokeObjectURL(objectUrl); + + resolve({ + thumbnailBlob: thumbnailBlobUrl, + height: video.videoHeight, + width: video.videoWidth, + }); + }, 'image/jpeg', 0.8); + }, { once: true }); // Only trigger once }); } } diff --git a/src/app/chat/elements/messages/messages.html b/src/app/chat/elements/messages/messages.html index cf8de81..6b7b97c 100644 --- a/src/app/chat/elements/messages/messages.html +++ b/src/app/chat/elements/messages/messages.html @@ -17,7 +17,11 @@ @if (file.type == "image") { } @else if (file.type == "video") { - + @if (file.extraMetaData && Object.keys(file.extraMetaData).length > 0) { + + } @else { + + } } } diff --git a/src/app/chat/elements/messages/messages.ts b/src/app/chat/elements/messages/messages.ts index eac42fd..9a2eba5 100644 --- a/src/app/chat/elements/messages/messages.ts +++ b/src/app/chat/elements/messages/messages.ts @@ -110,4 +110,6 @@ export class Messages { // last message is always end return i + 1 === this.messages().length; } + + protected readonly Object = Object; } diff --git a/src/app/chat/elements/video-player/video-player.html b/src/app/chat/elements/video-player/video-player.html index dce860a..2fe6e28 100644 --- a/src/app/chat/elements/video-player/video-player.html +++ b/src/app/chat/elements/video-player/video-player.html @@ -2,7 +2,7 @@