added PIP button in order to skip full screen & launch picture-in-picture

This commit is contained in:
Stacktoshi 2024-05-06 09:43:45 -07:00
parent 65c3c4ca4e
commit 86b1f8abad
3 changed files with 42 additions and 6 deletions

View File

@ -33,6 +33,7 @@
"react-intl": "^6.4.4",
"react-router-dom": "^6.13.0",
"react-tag-input-component": "^2.0.2",
"react-use-pip": "^1.5.0",
"recharts": "^2.9.3",
"semantic-sdp": "^3.26.3",
"usehooks-ts": "^2.9.1",

View File

@ -1,12 +1,13 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import Hls from "hls.js";
import { HTMLProps, useEffect, useMemo, useRef, useState } from "react";
import { HTMLProps, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { FormattedMessage } from "react-intl";
import { Icon } from "./icon";
import { ProgressBar } from "./progress-bar";
import { Menu, MenuItem } from "@szhsin/react-menu";
import { StreamState } from "@/const";
import classNames from "classnames";
import usePictureInPicture, { VideoRefType } from "react-use-pip";
export enum VideoStatus {
Online = "online",
@ -133,6 +134,17 @@ export default function LiveVideoPlayer({
}
}, [video, volume, muted]);
const {
isPictureInPictureActive,
isPictureInPictureAvailable,
togglePictureInPicture
} = usePictureInPicture(video as VideoRefType);
const handlePIPClick = useCallback(async () => {
togglePictureInPicture(!isPictureInPictureActive);
}, [
isPictureInPictureActive, togglePictureInPicture]);
function playStateToIcon() {
switch (playState) {
case "playing":
@ -179,15 +191,17 @@ export default function LiveVideoPlayer({
<h2>{title}</h2>
</div>
{/* CENTER PLAY ICON */}
<div className="absolute w-full h-full flex items-center justify-center pointer">
<Icon name={playStateToIcon()} size={80} className={playState === "loading" ? "animate-spin" : ""} />
<div className="absolute w-full h-full flex items-center justify-center cursor-pointer">
{!isPictureInPictureActive && (
<Icon name={playStateToIcon()} size={80} className={playState === "loading" ? "animate-spin" : ""} />
)}
</div>
{/* PLAYER CONTROLS OVERLAY */}
<div
className="absolute flex items-center gap-1 bottom-0 w-full bg-primary h-[40px]"
onClick={e => e.stopPropagation()}>
<div className="flex grow gap-1 items-center">
<div className="px-5 py-2 pointer" onClick={() => togglePlay()}>
<div className="px-5 py-2 cursor-pointer" onClick={() => togglePlay()}>
<Icon name={playStateToIcon()} className={playState === "loading" ? "animate-spin" : ""} />
</div>
<div className="px-3 py-2 uppercase font-bold tracking-wide hover:bg-primary-hover">{pStatus}</div>
@ -214,7 +228,7 @@ export default function LiveVideoPlayer({
<Menu
direction="top"
align="center"
menuButton={<div className="px-3 py-2 tracking-wide pointer">{levelName(level)}</div>}
menuButton={<div className="px-3 py-2 tracking-wide cursor-pointer">{levelName(level)}</div>}
menuClassName="bg-primary w-fit">
{levels?.map(v => (
<MenuItem
@ -227,8 +241,12 @@ export default function LiveVideoPlayer({
))}
</Menu>
</div>
{isPictureInPictureAvailable && (
<div className="pl-3 py-2 cursor-pointer tracking-wide font-bold text-sm"
onClick={handlePIPClick}>PIP</div>
)}
<div
className="px-3 py-2 pointer"
className="px-2 py-2 cursor-pointer"
onClick={() => {
if (video.current) {
video.current.requestFullscreen();
@ -239,6 +257,13 @@ export default function LiveVideoPlayer({
</div>
</div>
)}
{isPictureInPictureActive && (
<div
className="absolute z-20 bg-[#00000055] select-none w-full h-full flex items-center justify-center cursor-pointer">
<h2 onClick={async () => togglePictureInPicture(!isPictureInPictureActive)}>Video is playing in PIP
window</h2>
</div>
)}
{status === VideoStatus.Offline && (
<div className="absolute w-full h-full z-20 bg-[#000000aa] flex items-center justify-center text-3xl font-bold uppercase">
<FormattedMessage defaultMessage="Offline" id="7UOvbT" />

View File

@ -6838,6 +6838,15 @@ __metadata:
languageName: node
linkType: hard
"react-use-pip@npm:^1.5.0":
version: 1.5.0
resolution: "react-use-pip@npm:1.5.0"
peerDependencies:
react: ^16.9.0 || ^17 || ^18
checksum: 10c0/448a6d176eada90cafdcc2465dd9c974ba46e80c033168b3ecef87a064dd5f2976a8758f039e8b5c3f4abf15f844ad4096a2db6b1b0465f8a76988bee28aefdc
languageName: node
linkType: hard
"react@npm:^18.2.0":
version: 18.2.0
resolution: "react@npm:18.2.0"
@ -7516,6 +7525,7 @@ __metadata:
react-intl: "npm:^6.4.4"
react-router-dom: "npm:^6.13.0"
react-tag-input-component: "npm:^2.0.2"
react-use-pip: "npm:^1.5.0"
recharts: "npm:^2.9.3"
rollup-plugin-visualizer: "npm:^5.10.0"
semantic-sdp: "npm:^3.26.3"