mirror of
https://github.com/immich-app/immich.git
synced 2026-05-22 23:52:32 -04:00
refactor commit on release
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
import 'media-chrome/media-play-button';
|
||||
import 'media-chrome/media-playback-rate-button';
|
||||
import 'media-chrome/media-time-display';
|
||||
import 'media-chrome/media-time-range';
|
||||
import './immich-time-range';
|
||||
import 'media-chrome/media-volume-range';
|
||||
import 'media-chrome/menu/media-playback-rate-menu';
|
||||
import 'media-chrome/menu/media-rendition-menu';
|
||||
@@ -279,43 +279,9 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Suppress mediaseekrequest events while the user is dragging the time range and
|
||||
// replay only the last one on pointerup.
|
||||
const commitOnRelease = (node: HTMLElement) => {
|
||||
let dragging = false;
|
||||
let pending: number | undefined;
|
||||
const onPointerDown = () => (dragging = true);
|
||||
const onPointerUp = () => {
|
||||
if (!dragging) {
|
||||
return;
|
||||
}
|
||||
dragging = false;
|
||||
if (pending !== undefined) {
|
||||
node.dispatchEvent(new CustomEvent('mediaseekrequest', { composed: true, bubbles: true, detail: pending }));
|
||||
// Update time display immediately without waiting for the new fragment to load
|
||||
videoPlayer?.dispatchEvent(new Event('timeupdate'));
|
||||
pending = undefined;
|
||||
}
|
||||
};
|
||||
const onSeekRequest = (event: Event) => {
|
||||
if (dragging) {
|
||||
pending = (event as CustomEvent<number>).detail;
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
};
|
||||
node.addEventListener('pointerdown', onPointerDown);
|
||||
node.addEventListener('pointerup', onPointerUp);
|
||||
node.addEventListener('pointercancel', onPointerUp);
|
||||
node.addEventListener('mediaseekrequest', onSeekRequest, { capture: true });
|
||||
return {
|
||||
destroy() {
|
||||
node.removeEventListener('pointerdown', onPointerDown);
|
||||
node.removeEventListener('pointerup', onPointerUp);
|
||||
node.removeEventListener('pointercancel', onPointerUp);
|
||||
node.removeEventListener('mediaseekrequest', onSeekRequest, { capture: true });
|
||||
},
|
||||
};
|
||||
};
|
||||
// The time is only refreshed on HLS fragment decode by default,
|
||||
// so manually emit events on seek to update it immediately.
|
||||
const onSeeking = (event: Event) => event.currentTarget?.dispatchEvent(new Event('timeupdate'));
|
||||
</script>
|
||||
|
||||
{#if showVideo}
|
||||
@@ -356,6 +322,7 @@
|
||||
class="h-full object-contain"
|
||||
oncanplay={(e: Event) => handleCanPlay(e.currentTarget as HTMLVideoElement)}
|
||||
onended={onVideoEnded}
|
||||
onseeking={onSeeking}
|
||||
onplaying={(e: Event) => {
|
||||
if (!hasFocused) {
|
||||
(e.currentTarget as HTMLElement).focus();
|
||||
@@ -377,6 +344,7 @@
|
||||
class="h-full object-contain"
|
||||
oncanplay={(e) => handleCanPlay(e.currentTarget)}
|
||||
onended={onVideoEnded}
|
||||
onseeking={onSeeking}
|
||||
onplaying={(e) => {
|
||||
if (!hasFocused) {
|
||||
e.currentTarget.focus();
|
||||
@@ -442,7 +410,7 @@
|
||||
<media-settings-menu-button class="shrink-0 rounded-full p-2 outline-none"></media-settings-menu-button>
|
||||
{/if}
|
||||
</media-control-bar>
|
||||
<media-time-range use:commitOnRelease class="h-8 w-full rounded-lg px-2 pb-3 outline-none"></media-time-range>
|
||||
<immich-time-range class="h-8 w-full rounded-lg px-2 pb-3 outline-none"></immich-time-range>
|
||||
</div>
|
||||
</media-controller>
|
||||
|
||||
@@ -495,12 +463,12 @@
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
media-time-range,
|
||||
immich-time-range,
|
||||
media-volume-range {
|
||||
--media-control-hover-background: none;
|
||||
}
|
||||
|
||||
media-time-range:hover,
|
||||
immich-time-range:hover,
|
||||
media-volume-range:hover {
|
||||
--media-range-thumb-opacity: 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import MediaTimeRange from 'media-chrome/media-time-range';
|
||||
|
||||
const COMMIT_DELAY_MS = 750;
|
||||
|
||||
/** Custom MediaTimeRange that only seeks after pointer release to avoid hammering the server.
|
||||
* Keyboard input uses timed debouncing instead since there's no release event. */
|
||||
class ImmichTimeRange extends MediaTimeRange {
|
||||
private pointerSeek = false;
|
||||
private pendingSeek = false;
|
||||
private commitTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.addEventListener('pointercancel', this); // The base only wires pointerdown/up
|
||||
}
|
||||
|
||||
override handleEvent(event: Event) {
|
||||
switch (event.type) {
|
||||
case 'pointerdown': {
|
||||
this.pointerSeek = true;
|
||||
break;
|
||||
}
|
||||
case 'input': {
|
||||
this.pendingSeek = true;
|
||||
this.updateBar();
|
||||
if (this.pointerSeek) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(this.commitTimer);
|
||||
this.commitTimer = setTimeout(() => this.commit(), COMMIT_DELAY_MS);
|
||||
return;
|
||||
}
|
||||
case 'pointerup':
|
||||
case 'pointercancel': {
|
||||
super.handleEvent(event);
|
||||
if (this.pointerSeek) {
|
||||
this.pointerSeek = false;
|
||||
this.commit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.handleEvent(event);
|
||||
}
|
||||
|
||||
private commit() {
|
||||
clearTimeout(this.commitTimer);
|
||||
if (this.pendingSeek) {
|
||||
this.pendingSeek = false;
|
||||
super.handleEvent(new Event('input'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!globalThis.customElements.get('immich-time-range')) {
|
||||
globalThis.customElements.define('immich-time-range', ImmichTimeRange);
|
||||
}
|
||||
Reference in New Issue
Block a user