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 "./Fullscreen";
|
||||
export * from "./Pip";
|
||||
export * from "./ProgressBar";
|
||||
export * from "./Skips";
|
||||
export * from "./Time";
|
||||
|
|
|
@ -42,6 +42,14 @@ function hlsLevelsToQualities(levels: Level[]): SourceQuality[] {
|
|||
.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 {
|
||||
const { emit, on, off } = makeEmitter<DisplayInterfaceEvents>();
|
||||
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() {
|
||||
const videoPlayer = videoElement as any;
|
||||
if (videoPlayer && videoPlayer.webkitShowPlaybackTargetPicker) {
|
||||
|
|
|
@ -35,6 +35,7 @@ export interface DisplayInterface extends Listener<DisplayInterfaceEvents> {
|
|||
processVideoElement(video: HTMLVideoElement): void;
|
||||
processContainerElement(container: HTMLElement): void;
|
||||
toggleFullscreen(): void;
|
||||
togglePictureInPicture(): void;
|
||||
setSeeking(active: boolean): void;
|
||||
setVolume(vol: number): void;
|
||||
setTime(t: number): void;
|
||||
|
|
|
@ -79,6 +79,7 @@ export function PlayerPart(props: PlayerPartProps) {
|
|||
</Player.LeftSideControls>
|
||||
<div className="flex items-center space-x-3">
|
||||
<Player.Episodes />
|
||||
<Player.Pip />
|
||||
<Player.Airplay />
|
||||
<Player.Chromecast />
|
||||
<Player.Settings />
|
||||
|
|
Loading…
Reference in a new issue