fullscreen on iphone/ipad

This commit is contained in:
Jelle van Snik 2023-01-10 01:01:51 +01:00
parent 351b35ef98
commit 2d9b66d9b8
7 changed files with 36 additions and 10 deletions

View File

@ -6,6 +6,7 @@
"dependencies": { "dependencies": {
"@headlessui/react": "^1.5.0", "@headlessui/react": "^1.5.0",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"fscreen": "^1.2.0",
"fuse.js": "^6.4.6", "fuse.js": "^6.4.6",
"hls.js": "^1.0.7", "hls.js": "^1.0.7",
"i18next": "^22.4.5", "i18next": "^22.4.5",
@ -44,6 +45,7 @@
"devDependencies": { "devDependencies": {
"@tailwindcss/line-clamp": "^0.4.2", "@tailwindcss/line-clamp": "^0.4.2",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/fscreen": "^1.0.1",
"@types/node": "^17.0.15", "@types/node": "^17.0.15",
"@types/react": "^17.0.39", "@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",

View File

@ -2,8 +2,7 @@ import { Icons } from "@/components/Icon";
import { useCallback } from "react"; import { useCallback } from "react";
import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton"; import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton";
import { useVideoPlayerState } from "../VideoContext"; import { useVideoPlayerState } from "../VideoContext";
import { canFullscreen } from "../hooks/fullscreen";
const canFullscreen = document.fullscreenEnabled;
interface Props { interface Props {
className?: string; className?: string;

View File

@ -1,3 +1,6 @@
import fscreen from "fscreen";
import { canFullscreen, isSafari } from "./fullscreen";
export interface PlayerControls { export interface PlayerControls {
play(): void; play(): void;
pause(): void; pause(): void;
@ -28,12 +31,18 @@ export function populateControls(
player.pause(); player.pause();
}, },
enterFullscreen() { enterFullscreen() {
if (!document.fullscreenEnabled || document.fullscreenElement) return; if (!canFullscreen || fscreen.fullscreenElement) return;
wrapper.requestFullscreen(); if (fscreen.fullscreenEnabled) {
fscreen.requestFullscreen(wrapper);
return;
}
if (isSafari) {
(player as any).webkitEnterFullscreen();
}
}, },
exitFullscreen() { exitFullscreen() {
if (!document.fullscreenElement) return; if (!fscreen.fullscreenElement) return;
document.exitFullscreen(); fscreen.exitFullscreen();
}, },
setTime(t) { setTime(t) {
// clamp time between 0 and max duration // clamp time between 0 and max duration

View File

@ -0,0 +1,6 @@
import fscreen from "fscreen";
export const isSafari = /^((?!chrome|android).)*safari/i.test(
navigator.userAgent
);
export const canFullscreen = fscreen.fullscreenEnabled || isSafari;

View File

@ -1,3 +1,4 @@
import fscreen from "fscreen";
import React, { MutableRefObject, useEffect, useState } from "react"; import React, { MutableRefObject, useEffect, useState } from "react";
import { import {
initialControls, initialControls,
@ -108,7 +109,7 @@ function registerListeners(player: HTMLVideoElement, update: SetPlayer) {
player.addEventListener("playing", playing); player.addEventListener("playing", playing);
player.addEventListener("seeking", seeking); player.addEventListener("seeking", seeking);
player.addEventListener("seeked", seeked); player.addEventListener("seeked", seeked);
document.addEventListener("fullscreenchange", fullscreenchange); fscreen.addEventListener("fullscreenchange", fullscreenchange);
player.addEventListener("timeupdate", timeupdate); player.addEventListener("timeupdate", timeupdate);
player.addEventListener("loadedmetadata", loadedmetadata); player.addEventListener("loadedmetadata", loadedmetadata);
player.addEventListener("volumechange", volumechange); player.addEventListener("volumechange", volumechange);
@ -120,7 +121,7 @@ function registerListeners(player: HTMLVideoElement, update: SetPlayer) {
player.removeEventListener("playing", playing); player.removeEventListener("playing", playing);
player.removeEventListener("seeking", seeking); player.removeEventListener("seeking", seeking);
player.removeEventListener("seeked", seeked); player.removeEventListener("seeked", seeked);
document.removeEventListener("fullscreenchange", fullscreenchange); fscreen.removeEventListener("fullscreenchange", fullscreenchange);
player.removeEventListener("timeupdate", timeupdate); player.removeEventListener("timeupdate", timeupdate);
player.removeEventListener("loadedmetadata", loadedmetadata); player.removeEventListener("loadedmetadata", loadedmetadata);
player.removeEventListener("volumechange", volumechange); player.removeEventListener("volumechange", volumechange);

View File

@ -17,8 +17,7 @@ import { useCallback, useState } from "react";
// - volume control flashes old value when updating // - volume control flashes old value when updating
// - progress control flashes old value when updating // - progress control flashes old value when updating
// - captions // - captions
// - IOS support: (no volume, fullscreen video element instead of wrapper) // - IOS & IpadOS support: (no volume)
// - IpadOS support: (fullscreen video wrapper should work, see (lookmovie.io) )
// - HLS support: feature detection otherwise use HLS.js // - HLS support: feature detection otherwise use HLS.js
export function TestView() { export function TestView() {
const [show, setShow] = useState(true); const [show, setShow] = useState(true);

View File

@ -267,6 +267,11 @@
"resolved" "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz" "resolved" "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz"
"version" "4.1.1" "version" "4.1.1"
"@types/fscreen@^1.0.1":
"integrity" "sha512-hV2d0BreihMGtrg+EdAFOIl/O2EL5vhAheHJUztGE/lPFZIN8ZCpGFL8hCbtyi1CfhKjDRCf47sHjP+FwJ4q0Q=="
"resolved" "https://registry.npmjs.org/@types/fscreen/-/fscreen-1.0.1.tgz"
"version" "1.0.1"
"@types/history@^4.7.11": "@types/history@^4.7.11":
"integrity" "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" "integrity" "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA=="
"resolved" "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz" "resolved" "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz"
@ -1440,6 +1445,11 @@
"resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
"version" "1.0.0" "version" "1.0.0"
"fscreen@^1.2.0":
"integrity" "sha512-hlq4+BU0hlPmwsFjwGGzZ+OZ9N/wq9Ljg/sq3pX+2CD7hrJsX9tJgWWK/wiNTFM212CLHWhicOoqwXyZGGetJg=="
"resolved" "https://registry.npmjs.org/fscreen/-/fscreen-1.2.0.tgz"
"version" "1.2.0"
"function-bind@^1.1.1": "function-bind@^1.1.1":
"integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
"resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"