Make iptv works on mobile

This commit is contained in:
2025-03-02 10:49:38 +11:00
parent e68d92e7d7
commit 7434e0b017
+83 -61
View File
@@ -122,8 +122,8 @@
<div class="absolute right-0 top-0 hidden pr-4 pt-4 sm:block">
<button type="button" onclick="hideChannelModal()" class="rounded-md bg-white text-gray-400 hover:text-gray-500">
<span class="sr-only">Close</span>
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
@@ -171,8 +171,8 @@
<div class="relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<svg class="h-6 w-6 text-red-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
<svg class="h-6 w-6 text-red-600" fill="none" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
</svg>
</div>
<div class="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
@@ -351,65 +351,86 @@ const channelTitle = document.getElementById('channel-title');
let hls = null;
let activeChannelElement = null;
function initHls() {
if (!Hls.isSupported()) {
alert('Your browser does not support HLS streaming');
return null;
}
return new Hls({
debug: false,
enableWorker: true,
lowLatencyMode: true,
backBufferLength: 90
});
}
function loadStream(url) {
// Clean up any existing HLS instance
if (hls) {
hls.destroy();
hls = null;
}
hls = initHls();
if (!hls) return false;
try {
hls.loadSource(url);
hls.attachMedia(videoPlayer);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
console.log('HLS manifest loaded');
if (document.documentElement.hasAttribute('data-user-interacted')) {
playVideo();
} else {
playOverlay.classList.remove('hidden');
}
});
hls.on(Hls.Events.ERROR, (event, data) => {
if (data.fatal) {
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
console.error('Network error:', data);
hls.startLoad();
break;
case Hls.ErrorTypes.MEDIA_ERROR:
console.error('Media error:', data);
hls.recoverMediaError();
break;
default:
console.error('Fatal error:', data);
hls.destroy();
alert('Error loading stream. Please try another channel.');
break;
}
}
});
// Show the video player and hide empty state
videoPlayer.classList.remove('hidden');
emptyState.classList.add('hidden');
// First check if the browser natively supports HLS
if (videoPlayer.canPlayType('application/vnd.apple.mpegurl')) {
// Safari on iOS has native HLS support
console.log('Using native HLS support');
videoPlayer.src = url;
// Show play overlay if user hasn't interacted yet
if (document.documentElement.hasAttribute('data-user-interacted')) {
playVideo();
} else {
playOverlay.classList.remove('hidden');
}
return true;
} catch (error) {
console.error('Error initializing stream:', error);
alert('Error loading stream. Please try another channel.');
}
// Otherwise use hls.js if it's supported
else if (Hls.isSupported()) {
console.log('Using HLS.js');
hls = new Hls({
debug: false,
enableWorker: true,
lowLatencyMode: true,
backBufferLength: 90
});
try {
hls.loadSource(url);
hls.attachMedia(videoPlayer);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
console.log('HLS manifest loaded');
if (document.documentElement.hasAttribute('data-user-interacted')) {
playVideo();
} else {
playOverlay.classList.remove('hidden');
}
});
hls.on(Hls.Events.ERROR, (event, data) => {
if (data.fatal) {
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
console.error('Network error:', data);
hls.startLoad();
break;
case Hls.ErrorTypes.MEDIA_ERROR:
console.error('Media error:', data);
hls.recoverMediaError();
break;
default:
console.error('Fatal error:', data);
hls.destroy();
alert('Error loading stream. Please try another channel.');
break;
}
}
});
return true;
} catch (error) {
console.error('Error initializing stream:', error);
alert('Error loading stream. Please try another channel.');
return false;
}
} else {
// Neither native support nor hls.js support
console.error('HLS is not supported in this browser');
alert('Your browser does not support HLS streaming');
cleanupPlayer();
return false;
}
}
@@ -431,8 +452,6 @@ function selectChannel(url, title, element = null) {
}
if (loadStream(url)) {
videoPlayer.classList.remove('hidden');
emptyState.classList.add('hidden');
channelTitle.textContent = title;
} else {
cleanupPlayer();
@@ -448,8 +467,6 @@ function updatePlayOverlay() {
}
function playVideo() {
if (!hls || !videoPlayer) return;
videoPlayer.play()
.then(() => {
document.documentElement.setAttribute('data-user-interacted', 'true');
@@ -512,6 +529,11 @@ function cleanupPlayer() {
hls.destroy();
hls = null;
}
// Reset video source
videoPlayer.src = '';
videoPlayer.load();
if (activeChannelElement) {
activeChannelElement.classList.remove('bg-indigo-50', 'border-l-4', 'border-indigo-500');
activeChannelElement = null;