mirror of
https://github.com/wahyd4/links.git
synced 2026-08-09 05:06:16 +10:00
Make iptv works on mobile
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user