mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-20 14:37:43 +01:00
Add pip
This commit is contained in:
parent
fcec845f21
commit
78ae77392c
5 changed files with 43 additions and 0 deletions
14
src/components/player/atoms/Pip.tsx
Normal file
14
src/components/player/atoms/Pip.tsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { Icons } from "@/components/Icon";
|
||||||
|
import { VideoPlayerButton } from "@/components/player/internals/Button";
|
||||||
|
import { usePlayerStore } from "@/stores/player/store";
|
||||||
|
|
||||||
|
export function Pip() {
|
||||||
|
const display = usePlayerStore((s) => s.display);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<VideoPlayerButton
|
||||||
|
onClick={() => display?.togglePictureInPicture()}
|
||||||
|
icon={Icons.PICTURE_IN_PICTURE}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
export * from "./Pause";
|
export * from "./Pause";
|
||||||
export * from "./Fullscreen";
|
export * from "./Fullscreen";
|
||||||
|
export * from "./Pip";
|
||||||
export * from "./ProgressBar";
|
export * from "./ProgressBar";
|
||||||
export * from "./Skips";
|
export * from "./Skips";
|
||||||
export * from "./Time";
|
export * from "./Time";
|
||||||
|
|
|
@ -42,6 +42,14 @@ function hlsLevelsToQualities(levels: Level[]): SourceQuality[] {
|
||||||
.filter((v): v is SourceQuality => !!v);
|
.filter((v): v is SourceQuality => !!v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function canWebkitPictureInPicture(): boolean {
|
||||||
|
return "webkitSupportsPresentationMode" in document.createElement("video");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function canPictureInPicture(): boolean {
|
||||||
|
return "pictureInPictureEnabled" in document;
|
||||||
|
}
|
||||||
|
|
||||||
export function makeVideoElementDisplayInterface(): DisplayInterface {
|
export function makeVideoElementDisplayInterface(): DisplayInterface {
|
||||||
const { emit, on, off } = makeEmitter<DisplayInterfaceEvents>();
|
const { emit, on, off } = makeEmitter<DisplayInterfaceEvents>();
|
||||||
let source: LoadableSource | null = null;
|
let source: LoadableSource | null = null;
|
||||||
|
@ -306,6 +314,24 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
togglePictureInPicture() {
|
||||||
|
if (!videoElement) return;
|
||||||
|
if (canWebkitPictureInPicture()) {
|
||||||
|
const webkitPlayer = videoElement as any;
|
||||||
|
webkitPlayer.webkitSetPresentationMode(
|
||||||
|
webkitPlayer.webkitPresentationMode === "picture-in-picture"
|
||||||
|
? "inline"
|
||||||
|
: "picture-in-picture"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (canPictureInPicture()) {
|
||||||
|
if (videoElement !== document.pictureInPictureElement) {
|
||||||
|
videoElement.requestPictureInPicture();
|
||||||
|
} else {
|
||||||
|
document.exitPictureInPicture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
startAirplay() {
|
startAirplay() {
|
||||||
const videoPlayer = videoElement as any;
|
const videoPlayer = videoElement as any;
|
||||||
if (videoPlayer && videoPlayer.webkitShowPlaybackTargetPicker) {
|
if (videoPlayer && videoPlayer.webkitShowPlaybackTargetPicker) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ export interface DisplayInterface extends Listener<DisplayInterfaceEvents> {
|
||||||
processVideoElement(video: HTMLVideoElement): void;
|
processVideoElement(video: HTMLVideoElement): void;
|
||||||
processContainerElement(container: HTMLElement): void;
|
processContainerElement(container: HTMLElement): void;
|
||||||
toggleFullscreen(): void;
|
toggleFullscreen(): void;
|
||||||
|
togglePictureInPicture(): void;
|
||||||
setSeeking(active: boolean): void;
|
setSeeking(active: boolean): void;
|
||||||
setVolume(vol: number): void;
|
setVolume(vol: number): void;
|
||||||
setTime(t: number): void;
|
setTime(t: number): void;
|
||||||
|
|
|
@ -79,6 +79,7 @@ export function PlayerPart(props: PlayerPartProps) {
|
||||||
</Player.LeftSideControls>
|
</Player.LeftSideControls>
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
<Player.Episodes />
|
<Player.Episodes />
|
||||||
|
<Player.Pip />
|
||||||
<Player.Airplay />
|
<Player.Airplay />
|
||||||
<Player.Chromecast />
|
<Player.Chromecast />
|
||||||
<Player.Settings />
|
<Player.Settings />
|
||||||
|
|
Loading…
Reference in a new issue