Skip to content

Commit

Permalink
lock player to video aspect ratio in all circumstances
Browse files Browse the repository at this point in the history
  • Loading branch information
wkelly17 committed Sep 18, 2024
1 parent ba4965b commit 1f4b583
Showing 1 changed file with 170 additions and 170 deletions.
340 changes: 170 additions & 170 deletions src/components/Player.tsx
Original file line number Diff line number Diff line change
@@ -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<SetStateAction<VideoJsPlayer | undefined>>;
existingPlayer: VideoJsPlayer | undefined;
playlistData: Record<string, IVidWithCustom[]>;
currentVid: IVidWithCustom;
setJumpingForwardAmount: Dispatch<SetStateAction<string | number | null>>;
setJumpingBackAmount: Dispatch<SetStateAction<string | number | null>>;
handleChapters(
vid: IVidWithCustom,
vidJsPlayer: VideoJsPlayer | undefined,
): Promise<chapterMarkers | undefined>;
setPlayer: Dispatch<SetStateAction<VideoJsPlayer | undefined>>;
existingPlayer: VideoJsPlayer | undefined;
playlistData: Record<string, IVidWithCustom[]>;
currentVid: IVidWithCustom;
setJumpingForwardAmount: Dispatch<SetStateAction<string | number | null>>;
setJumpingBackAmount: Dispatch<SetStateAction<string | number | null>>;
handleChapters(
vid: IVidWithCustom,
vidJsPlayer: VideoJsPlayer | undefined
): Promise<chapterMarkers | undefined>;
};

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<HTMLDivElement>(null);
const vidPlayerRef = useRef(null);
const vidJsPlayerContainerRef = useRef<HTMLDivElement>(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: <custom event listener>
useEffect(() => {
bootPlayer();
}, []);
// biome-ignore lint/correctness/useExhaustiveDependencies: <custom event listener>
useEffect(() => {
bootPlayer();
}, []);

// biome-ignore lint/correctness/useExhaustiveDependencies: <custom event listener>
useEffect(() => {
// a custom event dispatch listener
handleSpeedChangesInApp();
}, []);
// biome-ignore lint/correctness/useExhaustiveDependencies: <custom event listener>
useEffect(() => {
// a custom event dispatch listener
handleSpeedChangesInApp();
}, []);

return (
<div
className="mx-auto absolute inset-0 "
ref={vidJsPlayerContainerRef}
id="vidJsPlayerContainer"
>
{playlistData && (
// biome-ignore lint/a11y/useMediaCaption: captions provided through chap segments
<video
ref={vidPlayerRef}
className="video-js object-cover absolute inset-0"
controls
src=""
/>
)}
</div>
);
return (
<div
className="mx-auto absolute inset-0 aspect-video"
ref={vidJsPlayerContainerRef}
id="vidJsPlayerContainer"
>
{playlistData && (
// biome-ignore lint/a11y/useMediaCaption: captions provided through chap segments
<video
ref={vidPlayerRef}
className="video-js object-cover absolute inset-0"
controls
src=""
/>
)}
</div>
);
}

0 comments on commit 1f4b583

Please sign in to comment.