diff --git a/extension/src/scripts/content.js b/extension/src/scripts/content.js index 73fd2d9..52b74f8 100644 --- a/extension/src/scripts/content.js +++ b/extension/src/scripts/content.js @@ -111,7 +111,7 @@ async function fetchJson(url) { if (bgData !== undefined && bgData !== null) { return bgData; } - } catch (e) {} + } catch (e) { } // 2. Direct fetch fallback from page try { @@ -121,7 +121,7 @@ async function fetchJson(url) { if (res.ok) { return await res.json(); } - } catch (e) {} + } catch (e) { } return null; } @@ -203,6 +203,13 @@ function bindGlobalPlayerListeners() { globalPlayerListenersBound = true; } +function getThumbnailUrl(url, i = 0) { + let splited = url.split("/") + splited = splited.slice(0, -2) + let result = splited.join("/") + `/thumbnails/thumbnail-sheet-${i}.webp`; + return result +} + function extractMetadataFromDOM(channelSlug, videoSlug) { try { const scripts = document.querySelectorAll('script'); @@ -231,11 +238,11 @@ function extractMetadataFromDOM(channelSlug, videoSlug) { }; } } - } catch (e) {} + } catch (e) { } } } } - } catch (e) {} + } catch (e) { } return null; } @@ -671,6 +678,8 @@ async function unlockVideo(triggerElement) { const finalUrl = streamUrl + (streamUrl.includes('?') ? '&' : '?') + 'kick_ts=' + Date.now(); let videoParent = existingChat ? container : container.querySelector('#unlocker-video-area'); + let firstPageThumbnail = getThumbnailUrl(streamUrl) + // Build Custom Player UI const playerHTML = `
@@ -680,7 +689,10 @@ async function unlockVideo(triggerElement) {
-
+
+ +
+
0:00
@@ -726,6 +738,7 @@ async function unlockVideo(triggerElement) { const btnBig = videoParent.querySelector('#k-big-play'); const progressBar = videoParent.querySelector('#k-progress'); const track = videoParent.querySelector('#k-track'); + const thumbnail = videoParent.querySelector("#k-thumbnail") const trackTooltip = videoParent.querySelector('#k-track-tooltip'); const trackTooltipTime = videoParent.querySelector('#k-track-tooltip-time'); const timeDisplay = videoParent.querySelector('#k-time'); @@ -748,6 +761,11 @@ async function unlockVideo(triggerElement) { let loadingStateTimeout = null; let previousVolumeBeforeMute = initialVolume > 0 ? initialVolume : 1; + + thumbnail.src = firstPageThumbnail + console.log(firstPageThumbnail); + + const updateVolumeSliderVisual = (volume) => { const percent = Math.max(0, Math.min(100, Math.round(volume * 100))); volumeSlider.style.setProperty('--k-volume-percent', `${percent}%`); @@ -931,13 +949,13 @@ async function unlockVideo(triggerElement) { }); vid.addEventListener('ended', () => setLoadingState(false)); let lastSave = 0; - + vid.addEventListener('timeupdate', () => { if (Date.now() - lastSave > 4000) { localStorage.setItem(resumeKey, vid.currentTime); lastSave = Date.now(); } - + if (isFinite(vid.duration)) { progressBar.style.width = (vid.currentTime / vid.duration * 100) + '%'; timeDisplay.textContent = `${formatTime(vid.currentTime)} / ${formatTime(vid.duration)}`; @@ -955,6 +973,23 @@ async function unlockVideo(triggerElement) { vid.currentTime = ratio * vid.duration; }; + const getAndUpdateThumbnailPosition = () => { + + const hoverTime = vid.currentTime + + const minutes = Math.floor(hoverTime / 60) + + const row = minutes % 5 + const column = Math.floor(minutes / 5) + + let pageCount = Math.floor(column / 50); + thumbnailUrl = getThumbnailUrl(streamUrl, pageCount) + + thumbnail.src = thumbnailUrl + + return { row, column } + } + track.addEventListener('mousedown', (e) => { isDraggingTrack = true; updateTrackPosition(e); @@ -981,12 +1016,24 @@ async function unlockVideo(triggerElement) { trackTooltipTime.textContent = formatTime(hoverTime); trackTooltip.style.left = `${ratio * rect.width}px`; trackTooltip.classList.add('visible'); + + const { row, column } = getAndUpdateThumbnailPosition(); + if (thumbnail.classList.contains("hidden")) { + thumbnail.classList.remove("hidden") + } + + let position = Math.min(Math.max(ratio * rect.width - 80, 20), rect.width - 180); + thumbnail.style.objectPosition = `${(row) * -180}px ${column % 50 * -101}px`; + thumbnail.style.transform = `translateX(${position}px)`; }); track.addEventListener('mouseenter', () => { if (isFinite(vid.duration)) trackTooltip.classList.add('visible'); }); track.addEventListener('mouseleave', () => { trackTooltip.classList.remove('visible'); + if (!thumbnail.classList.contains("hidden")) { + thumbnail.classList.add("hidden") + } }); let hideControlsTimeout = null; @@ -1080,7 +1127,7 @@ async function unlockVideo(triggerElement) { vid.play().catch(() => btnBig.classList.add('visible')); }); const savedTime = parseFloat(localStorage.getItem(resumeKey)); - + if (Number.isFinite(savedTime) && savedTime > 1) { vid.addEventListener('loadedmetadata', () => { if (Number.isFinite(vid.duration)) {