···11export * from "./Pause";
22export * from "./Fullscreen";
33+export * from "./Pip";
34export * from "./ProgressBar";
45export * from "./Skips";
56export * from "./Time";
+26
src/components/player/display/base.ts
···4242 .filter((v): v is SourceQuality => !!v);
4343}
44444545+export function canWebkitPictureInPicture(): boolean {
4646+ return "webkitSupportsPresentationMode" in document.createElement("video");
4747+}
4848+4949+export function canPictureInPicture(): boolean {
5050+ return "pictureInPictureEnabled" in document;
5151+}
5252+4553export function makeVideoElementDisplayInterface(): DisplayInterface {
4654 const { emit, on, off } = makeEmitter<DisplayInterfaceEvents>();
4755 let source: LoadableSource | null = null;
···303311 if (videoElement) {
304312 emit("needstrack", true);
305313 (videoElement as any).webkitEnterFullscreen();
314314+ }
315315+ }
316316+ },
317317+ togglePictureInPicture() {
318318+ if (!videoElement) return;
319319+ if (canWebkitPictureInPicture()) {
320320+ const webkitPlayer = videoElement as any;
321321+ webkitPlayer.webkitSetPresentationMode(
322322+ webkitPlayer.webkitPresentationMode === "picture-in-picture"
323323+ ? "inline"
324324+ : "picture-in-picture"
325325+ );
326326+ }
327327+ if (canPictureInPicture()) {
328328+ if (videoElement !== document.pictureInPictureElement) {
329329+ videoElement.requestPictureInPicture();
330330+ } else {
331331+ document.exitPictureInPicture();
306332 }
307333 }
308334 },