pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add pip

Jip Fr 78ae7739 fcec845f

+43
+14
src/components/player/atoms/Pip.tsx
··· 1 + import { Icons } from "@/components/Icon"; 2 + import { VideoPlayerButton } from "@/components/player/internals/Button"; 3 + import { usePlayerStore } from "@/stores/player/store"; 4 + 5 + export function Pip() { 6 + const display = usePlayerStore((s) => s.display); 7 + 8 + return ( 9 + <VideoPlayerButton 10 + onClick={() => display?.togglePictureInPicture()} 11 + icon={Icons.PICTURE_IN_PICTURE} 12 + /> 13 + ); 14 + }
+1
src/components/player/atoms/index.ts
··· 1 1 export * from "./Pause"; 2 2 export * from "./Fullscreen"; 3 + export * from "./Pip"; 3 4 export * from "./ProgressBar"; 4 5 export * from "./Skips"; 5 6 export * from "./Time";
+26
src/components/player/display/base.ts
··· 42 42 .filter((v): v is SourceQuality => !!v); 43 43 } 44 44 45 + export function canWebkitPictureInPicture(): boolean { 46 + return "webkitSupportsPresentationMode" in document.createElement("video"); 47 + } 48 + 49 + export function canPictureInPicture(): boolean { 50 + return "pictureInPictureEnabled" in document; 51 + } 52 + 45 53 export function makeVideoElementDisplayInterface(): DisplayInterface { 46 54 const { emit, on, off } = makeEmitter<DisplayInterfaceEvents>(); 47 55 let source: LoadableSource | null = null; ··· 303 311 if (videoElement) { 304 312 emit("needstrack", true); 305 313 (videoElement as any).webkitEnterFullscreen(); 314 + } 315 + } 316 + }, 317 + togglePictureInPicture() { 318 + if (!videoElement) return; 319 + if (canWebkitPictureInPicture()) { 320 + const webkitPlayer = videoElement as any; 321 + webkitPlayer.webkitSetPresentationMode( 322 + webkitPlayer.webkitPresentationMode === "picture-in-picture" 323 + ? "inline" 324 + : "picture-in-picture" 325 + ); 326 + } 327 + if (canPictureInPicture()) { 328 + if (videoElement !== document.pictureInPictureElement) { 329 + videoElement.requestPictureInPicture(); 330 + } else { 331 + document.exitPictureInPicture(); 306 332 } 307 333 } 308 334 },
+1
src/components/player/display/displayInterface.ts
··· 35 35 processVideoElement(video: HTMLVideoElement): void; 36 36 processContainerElement(container: HTMLElement): void; 37 37 toggleFullscreen(): void; 38 + togglePictureInPicture(): void; 38 39 setSeeking(active: boolean): void; 39 40 setVolume(vol: number): void; 40 41 setTime(t: number): void;
+1
src/pages/parts/player/PlayerPart.tsx
··· 79 79 </Player.LeftSideControls> 80 80 <div className="flex items-center space-x-3"> 81 81 <Player.Episodes /> 82 + <Player.Pip /> 82 83 <Player.Airplay /> 83 84 <Player.Chromecast /> 84 85 <Player.Settings />