1
0
Fork 0
mirror of https://github.com/sussy-code/smov.git synced 2024-12-26 15:37:41 +01:00
smov/src/components/player/display/base.ts

137 lines
3.8 KiB
TypeScript
Raw Normal View History

import fscreen from "fscreen";
2023-09-30 20:57:00 +02:00
import {
DisplayInterface,
DisplayInterfaceEvents,
} from "@/components/player/display/displayInterface";
import { Source } from "@/components/player/hooks/usePlayer";
import { handleBuffered } from "@/components/player/utils/handleBuffered";
import {
canChangeVolume,
canFullscreen,
canFullscreenAnyElement,
canWebkitFullscreen,
} from "@/utils/detectFeatures";
2023-09-30 20:57:00 +02:00
import { makeEmitter } from "@/utils/events";
export function makeVideoElementDisplayInterface(): DisplayInterface {
const { emit, on, off } = makeEmitter<DisplayInterfaceEvents>();
let source: Source | null = null;
let videoElement: HTMLVideoElement | null = null;
let containerElement: HTMLElement | null = null;
let isFullscreen = false;
let isPausedBeforeSeeking = false;
let isSeeking = false;
2023-09-30 20:57:00 +02:00
function setSource() {
if (!videoElement || !source) return;
videoElement.src = source.url;
videoElement.addEventListener("play", () => emit("play", undefined));
videoElement.addEventListener("pause", () => emit("pause", undefined));
videoElement.addEventListener("volumechange", () =>
emit("volumechange", videoElement?.volume ?? 0)
);
videoElement.addEventListener("timeupdate", () =>
emit("time", videoElement?.currentTime ?? 0)
);
videoElement.addEventListener("loadedmetadata", () => {
emit("duration", videoElement?.duration ?? 0);
});
videoElement.addEventListener("progress", () => {
if (videoElement)
emit(
"buffered",
handleBuffered(videoElement.currentTime, videoElement.buffered)
);
});
2023-09-30 20:57:00 +02:00
}
function fullscreenChange() {
isFullscreen =
!!document.fullscreenElement || // other browsers
!!(document as any).webkitFullscreenElement; // safari
}
fscreen.addEventListener("fullscreenchange", fullscreenChange);
2023-09-30 20:57:00 +02:00
return {
on,
off,
destroy: () => {
fscreen.removeEventListener("fullscreenchange", fullscreenChange);
},
2023-09-30 20:57:00 +02:00
load(newSource) {
source = newSource;
setSource();
},
processVideoElement(video) {
videoElement = video;
setSource();
},
processContainerElement(container) {
containerElement = container;
},
2023-09-30 20:57:00 +02:00
pause() {
videoElement?.pause();
},
play() {
videoElement?.play();
},
setSeeking(active) {
if (active === isSeeking) return;
isSeeking = active;
// if it was playing when starting to seek, play again
if (!active) {
if (!isPausedBeforeSeeking) this.play();
return;
}
isPausedBeforeSeeking = videoElement?.paused ?? true;
this.pause();
},
setTime(t) {
if (!videoElement) return;
// clamp time between 0 and max duration
let time = Math.min(t, videoElement.duration);
time = Math.max(0, time);
if (Number.isNaN(time)) return;
emit("time", time);
videoElement.currentTime = time;
},
async setVolume(v) {
if (!videoElement) return;
// clamp time between 0 and 1
let volume = Math.min(v, 1);
volume = Math.max(0, volume);
// update state
if (await canChangeVolume()) videoElement.volume = volume;
},
toggleFullscreen() {
if (isFullscreen) {
isFullscreen = false;
emit("fullscreen", isFullscreen);
if (!fscreen.fullscreenElement) return;
fscreen.exitFullscreen();
return;
}
// enter fullscreen
isFullscreen = true;
emit("fullscreen", isFullscreen);
if (!canFullscreen() || fscreen.fullscreenElement) return;
if (canFullscreenAnyElement()) {
if (containerElement) fscreen.requestFullscreen(containerElement);
return;
}
if (canWebkitFullscreen()) {
if (videoElement) (videoElement as any).webkitEnterFullscreen();
}
},
2023-09-30 20:57:00 +02:00
};
}