From 6b6edc9a0d00ea944ea30352f70099dff8d969ce Mon Sep 17 00:00:00 2001 From: h Date: Thu, 6 Aug 2026 12:29:37 +0200 Subject: [PATCH] fix(frontend): paint video poster frames, clip round videos to circle --- .../lib/components/MediaVersionThumb.svelte | 9 ++++++++- .../src/lib/components/MediaViewer.svelte | 10 +++++++++- .../src/lib/components/MessageMedia.svelte | 9 ++++++++- .../src/lib/components/media/AlbumTile.svelte | 9 ++++++++- .../src/lib/components/media/VideoNote.svelte | 13 +++++++++++- .../lib/components/profile/SharedMedia.svelte | 9 ++++++++- .../stories/AllStoriesArchive.svelte | 3 +++ .../components/stories/StoriesArchive.svelte | 3 +++ frontend/src/lib/media/poster.ts | 20 +++++++++++++++++++ 9 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 frontend/src/lib/media/poster.ts diff --git a/frontend/src/lib/components/MediaVersionThumb.svelte b/frontend/src/lib/components/MediaVersionThumb.svelte index 8110fa7..e0d1e86 100644 --- a/frontend/src/lib/components/MediaVersionThumb.svelte +++ b/frontend/src/lib/components/MediaVersionThumb.svelte @@ -4,6 +4,7 @@ import type { MediaVersion } from "$lib/api/types"; import Icon from "$lib/components/ui/Icon.svelte"; import Spinner from "$lib/components/ui/Spinner.svelte"; + import { poster } from "$lib/media/poster"; interface Props { version: MediaVersion; @@ -37,7 +38,13 @@ {:else if result.state === "ready" && vk === "video"} - + {:else if result.state === "ready"} diff --git a/frontend/src/lib/components/MediaViewer.svelte b/frontend/src/lib/components/MediaViewer.svelte index af315c9..54443ac 100644 --- a/frontend/src/lib/components/MediaViewer.svelte +++ b/frontend/src/lib/components/MediaViewer.svelte @@ -7,6 +7,7 @@ import Button from "$lib/components/ui/Button.svelte"; import Icon from "$lib/components/ui/Icon.svelte"; import Spinner from "$lib/components/ui/Spinner.svelte"; + import { poster } from "$lib/media/poster"; import { toasts } from "$lib/stores/toasts.svelte"; interface Props { @@ -149,7 +150,14 @@ {:else if result?.state === "ready" && isVideo} - + {:else if result?.state === "ready" && isAudio} diff --git a/frontend/src/lib/components/MessageMedia.svelte b/frontend/src/lib/components/MessageMedia.svelte index 0a0fc4b..6657359 100644 --- a/frontend/src/lib/components/MessageMedia.svelte +++ b/frontend/src/lib/components/MessageMedia.svelte @@ -15,6 +15,7 @@ import ContextMenuItem from "$lib/components/ui/ContextMenuItem.svelte"; import Icon from "$lib/components/ui/Icon.svelte"; import Spinner from "$lib/components/ui/Spinner.svelte"; + import { poster } from "$lib/media/poster"; import { toasts } from "$lib/stores/toasts.svelte"; import { ui } from "$lib/stores/ui.svelte"; @@ -143,7 +144,13 @@ {:else if ready && isThumbVideo} {:else if ready} diff --git a/frontend/src/lib/components/media/AlbumTile.svelte b/frontend/src/lib/components/media/AlbumTile.svelte index 728390a..01cfba4 100644 --- a/frontend/src/lib/components/media/AlbumTile.svelte +++ b/frontend/src/lib/components/media/AlbumTile.svelte @@ -5,6 +5,7 @@ import type { MediaRef } from "$lib/api/types"; import Icon from "$lib/components/ui/Icon.svelte"; import Spinner from "$lib/components/ui/Spinner.svelte"; + import { poster } from "$lib/media/poster"; import { toasts } from "$lib/stores/toasts.svelte"; interface Props { @@ -46,7 +47,13 @@
{#if ready && isVideo} {:else if ready} diff --git a/frontend/src/lib/components/media/VideoNote.svelte b/frontend/src/lib/components/media/VideoNote.svelte index 6d439ea..ff200d9 100644 --- a/frontend/src/lib/components/media/VideoNote.svelte +++ b/frontend/src/lib/components/media/VideoNote.svelte @@ -2,6 +2,7 @@ import Icon from "$lib/components/ui/Icon.svelte"; import { formatDuration } from "$lib/format/duration"; import { claimPlayback, releasePlayback } from "$lib/media/playback"; + import { POSTER_TIME, poster } from "$lib/media/poster"; interface Props { transcript?: string | null; @@ -54,6 +55,7 @@ playsinline preload="metadata" src={url} + use:poster > {:else} diff --git a/frontend/src/lib/components/stories/AllStoriesArchive.svelte b/frontend/src/lib/components/stories/AllStoriesArchive.svelte index c8c2bcf..52af996 100644 --- a/frontend/src/lib/components/stories/AllStoriesArchive.svelte +++ b/frontend/src/lib/components/stories/AllStoriesArchive.svelte @@ -9,6 +9,7 @@ import Icon from "$lib/components/ui/Icon.svelte"; import Spinner from "$lib/components/ui/Spinner.svelte"; import { peerName } from "$lib/format/peer"; + import { poster } from "$lib/media/poster"; import { accounts } from "$lib/stores/accounts.svelte"; interface Group { @@ -167,7 +168,9 @@ {:else} diff --git a/frontend/src/lib/components/stories/StoriesArchive.svelte b/frontend/src/lib/components/stories/StoriesArchive.svelte index 1c4c5d5..1291148 100644 --- a/frontend/src/lib/components/stories/StoriesArchive.svelte +++ b/frontend/src/lib/components/stories/StoriesArchive.svelte @@ -8,6 +8,7 @@ import EmptyState from "$lib/components/ui/EmptyState.svelte"; import Icon from "$lib/components/ui/Icon.svelte"; import Spinner from "$lib/components/ui/Spinner.svelte"; + import { poster } from "$lib/media/poster"; import { accounts } from "$lib/stores/accounts.svelte"; const PAGE = 60; @@ -113,7 +114,9 @@ {:else} diff --git a/frontend/src/lib/media/poster.ts b/frontend/src/lib/media/poster.ts new file mode 100644 index 0000000..c1ffdf9 --- /dev/null +++ b/frontend/src/lib/media/poster.ts @@ -0,0 +1,20 @@ +export const POSTER_TIME = 0.001; + +export function poster(node: HTMLVideoElement) { + const seek = () => { + if (node.currentTime === 0) { + node.currentTime = POSTER_TIME; + } + }; + + node.addEventListener("loadedmetadata", seek); + if (node.readyState >= node.HAVE_METADATA) { + seek(); + } + + return { + destroy() { + node.removeEventListener("loadedmetadata", seek); + }, + }; +}