From 1f4b583906dd7c58ae265093e721a92afbee8f7a Mon Sep 17 00:00:00 2001 From: Will Kelly Date: Wed, 18 Sep 2024 09:43:52 -0500 Subject: [PATCH] lock player to video aspect ratio in all circumstances --- src/components/Player.tsx | 340 +++++++++++++++++++------------------- 1 file changed, 170 insertions(+), 170 deletions(-) diff --git a/src/components/Player.tsx b/src/components/Player.tsx index ab0e4bd..7b0ddd7 100644 --- a/src/components/Player.tsx +++ b/src/components/Player.tsx @@ -1,189 +1,189 @@ -import { type Dispatch, type SetStateAction, useEffect, useRef } from "react"; -import type { VideoJsPlayer } from "video.js"; -import type { IVidWithCustom, chapterMarkers } from "../customTypes/types"; -import { handleVideoJsTaps, playerCustomHotKeys } from "../lib/Ui"; -import { getSavedAppPreferences } from "../lib/storage"; +import {type Dispatch, type SetStateAction, useEffect, useRef} from "react"; +import type {VideoJsPlayer} from "video.js"; +import type {IVidWithCustom, chapterMarkers} from "../customTypes/types"; +import {handleVideoJsTaps, playerCustomHotKeys} from "../lib/Ui"; +import {getSavedAppPreferences} from "../lib/storage"; type Iplayer = { - setPlayer: Dispatch>; - existingPlayer: VideoJsPlayer | undefined; - playlistData: Record; - currentVid: IVidWithCustom; - setJumpingForwardAmount: Dispatch>; - setJumpingBackAmount: Dispatch>; - handleChapters( - vid: IVidWithCustom, - vidJsPlayer: VideoJsPlayer | undefined, - ): Promise; + setPlayer: Dispatch>; + existingPlayer: VideoJsPlayer | undefined; + playlistData: Record; + currentVid: IVidWithCustom; + setJumpingForwardAmount: Dispatch>; + setJumpingBackAmount: Dispatch>; + handleChapters( + vid: IVidWithCustom, + vidJsPlayer: VideoJsPlayer | undefined + ): Promise; }; export function VidJsPlayer({ - setPlayer, - existingPlayer, - playlistData, - currentVid, - setJumpingBackAmount, - setJumpingForwardAmount, - handleChapters, + setPlayer, + existingPlayer, + playlistData, + currentVid, + setJumpingBackAmount, + setJumpingForwardAmount, + handleChapters, }: Iplayer) { - const vidPlayerRef = useRef(null); - const vidJsPlayerContainerRef = useRef(null); + const vidPlayerRef = useRef(null); + const vidJsPlayerContainerRef = useRef(null); - async function bootPlayer() { - if (playlistData) { - const curAppState = await getSavedAppPreferences(); - // SPEED - const preferredSpeed = curAppState?.preferredSpeed || 1; - const jumpAmount = 5; //seconds to jump on double taps; - const firstBook = currentVid; - // Resume src, offline or stream - const firstVidSrces = firstBook.savedSources?.video - ? { - src: `${firstBook.savedSources?.video}`, - type: "video/mp4", - } - : firstBook.sources; + async function bootPlayer() { + if (playlistData) { + const curAppState = await getSavedAppPreferences(); + // SPEED + const preferredSpeed = curAppState?.preferredSpeed || 1; + const jumpAmount = 5; //seconds to jump on double taps; + const firstBook = currentVid; + // Resume src, offline or stream + const firstVidSrces = firstBook.savedSources?.video + ? { + src: `${firstBook.savedSources?.video}`, + type: "video/mp4", + } + : firstBook.sources; - const firstPoster = firstBook.savedSources?.poster - ? firstBook.savedSources?.poster - : firstBook.poster; + const firstPoster = firstBook.savedSources?.poster + ? firstBook.savedSources?.poster + : firstBook.poster; - // instantiate player - // window.bc is from /bc/willPlayer. This is a brightcove player that has been manually downloaded and included to avoid the network request for a 200kb + video js player. This allows us to bundle it for offline usage in mobile app more easily too. We could just use video js, but the bundled / minified player includes brightcoves built in analytics. If we are offline, they won't send, but that's a noop at that point. The priority is availability. - // SEe https://videojs.com/guides/options - const player = window.bc(vidPlayerRef.current, { - responsive: true, - fluid: true, - controls: true, - playbackRates: [0.5, 1, 1.5, 2, 2.5], - preload: "auto", - autoplay: false, - fullscreen: { - navigationUI: "show", - }, - enableDocumentPictureInPicture: true, - sources: firstVidSrces, - poster: firstPoster, - nativeControlsForTouch: true, - }); + // instantiate player + // window.bc is from /bc/willPlayer. This is a brightcove player that has been manually downloaded and included to avoid the network request for a 200kb + video js player. This allows us to bundle it for offline usage in mobile app more easily too. We could just use video js, but the bundled / minified player includes brightcoves built in analytics. If we are offline, they won't send, but that's a noop at that point. The priority is availability. + // SEe https://videojs.com/guides/options + const player = window.bc(vidPlayerRef.current, { + responsive: true, + fluid: true, + controls: true, + playbackRates: [0.5, 1, 1.5, 2, 2.5], + preload: "auto", + autoplay: false, + fullscreen: { + navigationUI: "show", + }, + enableDocumentPictureInPicture: true, + sources: firstVidSrces, + poster: firstPoster, + nativeControlsForTouch: true, + }); - player.playbackRate(preferredSpeed); - player.on("loadstart", () => maintainPlayerSpeed(player)); - player.language(navigator.languages[0]); - player.playsinline(true); //ios + player.playbackRate(preferredSpeed); + player.on("loadstart", () => maintainPlayerSpeed(player)); + player.language(navigator.languages[0]); + player.playsinline(true); //ios - // Get initial chapters if present - player.one("loadedmetadata", () => { - handleChapters(currentVid, player); - }); + // Get initial chapters if present + player.one("loadedmetadata", () => { + handleChapters(currentVid, player); + }); - const videoJsDomEl = player.el(); - // Handle mobile taps - handleVideoJsTaps({ - el: videoJsDomEl, - rightDoubleFxn(number) { - const curTime = player?.currentTime(); - if (!curTime) return; - // the extra minus jumpAmount on end of next line is to account for fact that min tap amount is 2 to diff btw double and single taps, so we still want to allow the smallest measure of jump back; - const newTime = number * jumpAmount + curTime - jumpAmount; - player?.currentTime(newTime); - setJumpingForwardAmount(null); - videoJsDomEl.classList.remove("vjs-user-active"); - }, - leftDoubleFxn(number) { - const curTime = player?.currentTime(); - if (!curTime) return; + const videoJsDomEl = player.el(); + // Handle mobile taps + handleVideoJsTaps({ + el: videoJsDomEl, + rightDoubleFxn(number) { + const curTime = player?.currentTime(); + if (!curTime) return; + // the extra minus jumpAmount on end of next line is to account for fact that min tap amount is 2 to diff btw double and single taps, so we still want to allow the smallest measure of jump back; + const newTime = number * jumpAmount + curTime - jumpAmount; + player?.currentTime(newTime); + setJumpingForwardAmount(null); + videoJsDomEl.classList.remove("vjs-user-active"); + }, + leftDoubleFxn(number) { + const curTime = player?.currentTime(); + if (!curTime) return; - const newTime = curTime - number * jumpAmount - jumpAmount; - player?.currentTime(newTime); - setJumpingBackAmount(null); - videoJsDomEl.classList.remove("vjs-user-active"); - }, - singleTapFxn() { - if (!player) return; - if (player.paused()) { - player.play(); - } else { - player.pause(); - } - }, - doubleTapUiClue(dir, tapsCount) { - if (dir === "LEFT") { - setJumpingBackAmount(tapsCount * jumpAmount - 5); - setJumpingForwardAmount(null); - } else if (dir === "RIGHT") { - setJumpingBackAmount(null); - setJumpingForwardAmount(tapsCount * jumpAmount - 5); - } - }, - }); + const newTime = curTime - number * jumpAmount - jumpAmount; + player?.currentTime(newTime); + setJumpingBackAmount(null); + videoJsDomEl.classList.remove("vjs-user-active"); + }, + singleTapFxn() { + if (!player) return; + if (player.paused()) { + player.play(); + } else { + player.pause(); + } + }, + doubleTapUiClue(dir, tapsCount) { + if (dir === "LEFT") { + setJumpingBackAmount(tapsCount * jumpAmount - 5); + setJumpingForwardAmount(null); + } else if (dir === "RIGHT") { + setJumpingBackAmount(null); + setJumpingForwardAmount(tapsCount * jumpAmount - 5); + } + }, + }); - // @MANAGE KEYS TO SKIP - player.on("keydown", (e: KeyboardEvent) => - playerCustomHotKeys({ - e, - vjsPlayer: player, - increment: jumpAmount, - setJumpingBackAmount, - setJumpingForwardAmount, - }), - ); + // @MANAGE KEYS TO SKIP + player.on("keydown", (e: KeyboardEvent) => + playerCustomHotKeys({ + e, + vjsPlayer: player, + increment: jumpAmount, + setJumpingBackAmount, + setJumpingForwardAmount, + }) + ); - // Finally set state - setPlayer(player); - } - } - async function maintainPlayerSpeed(player: VideoJsPlayer) { - if (vidJsPlayerContainerRef.current) { - const curAppState = await getSavedAppPreferences(); - const preferredSpeed = curAppState?.preferredSpeed || 1; - player.playbackRate(preferredSpeed); - } - } - function handleSpeedChangesInApp() { - if (vidJsPlayerContainerRef.current && existingPlayer) { - vidJsPlayerContainerRef.current.addEventListener( - "adjustPlayerSpeed", - (event: Event) => { - const customEvent = event as CustomEvent; + // Finally set state + setPlayer(player); + } + } + async function maintainPlayerSpeed(player: VideoJsPlayer) { + if (vidJsPlayerContainerRef.current) { + const curAppState = await getSavedAppPreferences(); + const preferredSpeed = curAppState?.preferredSpeed || 1; + player.playbackRate(preferredSpeed); + } + } + function handleSpeedChangesInApp() { + if (vidJsPlayerContainerRef.current && existingPlayer) { + vidJsPlayerContainerRef.current.addEventListener( + "adjustPlayerSpeed", + (event: Event) => { + const customEvent = event as CustomEvent; - if ( - customEvent.detail && - typeof customEvent.detail.speed === "number" - ) { - const speed = customEvent.detail.speed; - existingPlayer.playbackRate(speed); - } - }, - ); - } - } + if ( + customEvent.detail && + typeof customEvent.detail.speed === "number" + ) { + const speed = customEvent.detail.speed; + existingPlayer.playbackRate(speed); + } + } + ); + } + } - // biome-ignore lint/correctness/useExhaustiveDependencies: - useEffect(() => { - bootPlayer(); - }, []); + // biome-ignore lint/correctness/useExhaustiveDependencies: + useEffect(() => { + bootPlayer(); + }, []); - // biome-ignore lint/correctness/useExhaustiveDependencies: - useEffect(() => { - // a custom event dispatch listener - handleSpeedChangesInApp(); - }, []); + // biome-ignore lint/correctness/useExhaustiveDependencies: + useEffect(() => { + // a custom event dispatch listener + handleSpeedChangesInApp(); + }, []); - return ( -
- {playlistData && ( - // biome-ignore lint/a11y/useMediaCaption: captions provided through chap segments -
- ); + return ( +
+ {playlistData && ( + // biome-ignore lint/a11y/useMediaCaption: captions provided through chap segments +
+ ); }