fix: implemented safari webkit support for fullscreen and PiP
This commit is contained in:
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nodecast-tv",
|
"name": "nodecast-tv",
|
||||||
"version": "2.1.2",
|
"version": "2.1.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nodecast-tv",
|
"name": "nodecast-tv",
|
||||||
"version": "2.1.2",
|
"version": "2.1.3",
|
||||||
"description": "Modern IPTV Player",
|
"description": "Modern IPTV Player",
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"main": "server/index.js",
|
"main": "server/index.js",
|
||||||
|
|||||||
@@ -349,30 +349,47 @@ class VideoPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle fullscreen mode
|
* Toggle fullscreen mode (cross-browser including Safari)
|
||||||
*/
|
*/
|
||||||
toggleFullscreen() {
|
toggleFullscreen() {
|
||||||
if (document.fullscreenElement) {
|
const isFullscreen = document.fullscreenElement || document.webkitFullscreenElement;
|
||||||
|
|
||||||
|
if (isFullscreen) {
|
||||||
|
if (document.exitFullscreen) {
|
||||||
document.exitFullscreen();
|
document.exitFullscreen();
|
||||||
|
} else if (document.webkitExitFullscreen) {
|
||||||
|
document.webkitExitFullscreen();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.container.requestFullscreen().catch(err => {
|
const element = this.container;
|
||||||
console.error('Fullscreen error:', err);
|
if (element.requestFullscreen) {
|
||||||
});
|
element.requestFullscreen().catch(err => console.error('Fullscreen error:', err));
|
||||||
|
} else if (element.webkitRequestFullscreen) {
|
||||||
|
element.webkitRequestFullscreen();
|
||||||
|
} else if (this.video.webkitEnterFullscreen) {
|
||||||
|
// iOS Safari: use native video fullscreen
|
||||||
|
this.video.webkitEnterFullscreen();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle Picture-in-Picture mode
|
* Toggle Picture-in-Picture mode (cross-browser including Safari)
|
||||||
*/
|
*/
|
||||||
async togglePictureInPicture() {
|
async togglePictureInPicture() {
|
||||||
try {
|
try {
|
||||||
|
// Standard PiP API (Chrome, Edge, Firefox)
|
||||||
if (document.pictureInPictureElement) {
|
if (document.pictureInPictureElement) {
|
||||||
await document.exitPictureInPicture();
|
await document.exitPictureInPicture();
|
||||||
} else if (document.pictureInPictureEnabled && this.video.readyState >= 2) {
|
} else if (document.pictureInPictureEnabled && this.video.readyState >= 2) {
|
||||||
await this.video.requestPictureInPicture();
|
await this.video.requestPictureInPicture();
|
||||||
}
|
}
|
||||||
|
// Safari fallback using webkitPresentationMode
|
||||||
|
else if (typeof this.video.webkitSetPresentationMode === 'function') {
|
||||||
|
const mode = this.video.webkitPresentationMode;
|
||||||
|
this.video.webkitSetPresentationMode(mode === 'picture-in-picture' ? 'inline' : 'picture-in-picture');
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Silently fail - Firefox users can use native PiP button
|
|
||||||
if (err.name !== 'NotAllowedError') {
|
if (err.name !== 'NotAllowedError') {
|
||||||
console.error('Picture-in-Picture error:', err);
|
console.error('Picture-in-Picture error:', err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -634,22 +634,40 @@ class WatchPage {
|
|||||||
|
|
||||||
toggleFullscreen() {
|
toggleFullscreen() {
|
||||||
const container = document.querySelector('.watch-video-section');
|
const container = document.querySelector('.watch-video-section');
|
||||||
if (!document.fullscreenElement) {
|
const isFullscreen = document.fullscreenElement || document.webkitFullscreenElement;
|
||||||
container?.requestFullscreen?.() || container?.webkitRequestFullscreen?.();
|
|
||||||
|
if (isFullscreen) {
|
||||||
|
if (document.exitFullscreen) {
|
||||||
|
document.exitFullscreen();
|
||||||
|
} else if (document.webkitExitFullscreen) {
|
||||||
|
document.webkitExitFullscreen();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
document.exitFullscreen?.() || document.webkitExitFullscreen?.();
|
if (container?.requestFullscreen) {
|
||||||
|
container.requestFullscreen();
|
||||||
|
} else if (container?.webkitRequestFullscreen) {
|
||||||
|
container.webkitRequestFullscreen();
|
||||||
|
} else if (this.video?.webkitEnterFullscreen) {
|
||||||
|
// iOS Safari: use native video fullscreen
|
||||||
|
this.video.webkitEnterFullscreen();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async togglePictureInPicture() {
|
async togglePictureInPicture() {
|
||||||
try {
|
try {
|
||||||
|
// Standard PiP API (Chrome, Edge, Firefox)
|
||||||
if (document.pictureInPictureElement) {
|
if (document.pictureInPictureElement) {
|
||||||
await document.exitPictureInPicture();
|
await document.exitPictureInPicture();
|
||||||
} else if (document.pictureInPictureEnabled && this.video.readyState >= 2) {
|
} else if (document.pictureInPictureEnabled && this.video.readyState >= 2) {
|
||||||
await this.video.requestPictureInPicture();
|
await this.video.requestPictureInPicture();
|
||||||
}
|
}
|
||||||
|
// Safari fallback using webkitPresentationMode
|
||||||
|
else if (typeof this.video.webkitSetPresentationMode === 'function') {
|
||||||
|
const mode = this.video.webkitPresentationMode;
|
||||||
|
this.video.webkitSetPresentationMode(mode === 'picture-in-picture' ? 'inline' : 'picture-in-picture');
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Silently fail - Firefox users can use native PiP button
|
|
||||||
if (err.name !== 'NotAllowedError') {
|
if (err.name !== 'NotAllowedError') {
|
||||||
console.error('Picture-in-Picture error:', err);
|
console.error('Picture-in-Picture error:', err);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user