diff --git a/.github/workflows/build-nightly-container.yml b/.github/workflows/build-nightly-container.yml index 1153e223..a380bf22 100644 --- a/.github/workflows/build-nightly-container.yml +++ b/.github/workflows/build-nightly-container.yml @@ -75,14 +75,3 @@ jobs: tags: | type=sha,format=short,prefix={{date 'YYYY.MM.DD'}}-,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} type=raw,value=master,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} - - - name: Build and push Docker ARM64 image for Push Event - uses: docker/build-push-action@v5 - with: - context: . - file: docker/Dockerfile.arm64 - platforms: linux/arm64/v8 - push: true - tags: ${{ steps.meta-arm64.outputs.tags }} - build-args: | - "release=1" diff --git a/assets/js/player.js b/assets/js/player.js index 37917147..8ddf17aa 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -407,59 +407,197 @@ if (!video_data.params.listen && video_data.params.annotations) { }); } -function change_volume(delta) { - const curVolume = player.volume(); - let newVolume = curVolume + delta; - newVolume = helpers.clamp(newVolume, 0, 1); - player.volume(newVolume); +var shareOptions = { + socials: ['fbFeed', 'tw', 'reddit', 'email'], + + get url() { + return addCurrentTimeToURL(short_url); + }, + title: player_data.title, + description: player_data.description, + image: player_data.thumbnail, + get embedCode() { + // Single quotes inside here required. HTML inserted as is into value attribute of input + return ""; + } +}; + +if (location.pathname.startsWith('/embed/')) { + console.log('[Invidious Debug] Initializing overlay...'); + try { + var overlay_content = '

' + player_data.title + '

'; + player.overlay({ + overlays: [ + { start: 'loadstart', content: overlay_content, end: 'playing', align: 'top'}, + { start: 'pause', content: overlay_content, end: 'playing', align: 'top'} + ] + }); + console.log('[Invidious Debug] Overlay initialized.'); + } catch (e) { + console.error('[Invidious Debug] Overlay FAILED:', e); + } } -function toggle_muted() { - player.muted(!player.muted()); +// Detect mobile users and initialize mobileUi for better UX +// Detection code taken from https://stackoverflow.com/a/20293441 +function isMobile() { + return typeof window.orientation !== 'undefined' || navigator.userAgent.indexOf('IEMobile') !== -1; } -function skip_seconds(delta) { - const duration = player.duration(); - const curTime = player.currentTime(); - let newTime = curTime + delta; - newTime = helpers.clamp(newTime, 0, duration); - player.currentTime(newTime); +if (isMobile()) { + console.log('[Invidious Debug] Mobile detected, initializing mobile UI...'); + try { + player.mobileUi({ touchControls: { seekSeconds: 5, tapTimeout: 200, disableOnEnd: true } }); + console.log('[Invidious Debug] Mobile UI initialized.'); + } catch (e) { + console.error('[Invidious Debug] Mobile UI FAILED:', e); + } } -function set_seconds_after_start(delta) { - const start = video_data.params.video_start; - player.currentTime(start + delta); +if (player.markers && !video_data.params.listen && video_data.params.chapters) { + console.log('[Invidious Debug] Initializing markers...'); + var markers = []; + for (var i = 0; i < video_data.params.chapters.length; i++) { + var marker = video_data.params.chapters[i]; + markers.push({ + time: marker.start, + text: marker.title, + }); + } + + if (markers.length > 1 && markers[0].time === 0 && markers[0].text === 'Intro') { + markers.shift(); + } + + markers.sort((a,b) => (a.time > b.time) ? 1 : ((b.time > a.time) ? -1 : 0)); + + var unique_markers = []; + var last_time = -1; + for (var i = 0; i < markers.length; i++) { + var marker = markers[i]; + if (marker.time <= last_time) { + continue; + } + unique_markers.push(marker); + last_time = marker.time; + } + markers = unique_markers; + + // Add "end" time information to each marker + for (var i = 0; i < markers.length; i++) { + var marker = markers[i]; + if (i < markers.length - 1) { + marker.end = markers[i+1].time - 0.001; + } else { + marker.end = player.duration(); + } + } + + player.markers.removeAll(); + + // Callback function when a marker is reached + function onMarkerReached(marker) { + //console.log("marker reached: " + marker.text + " at " + marker.time); + } + + try { + player.markers({ + onMarkerReached: onMarkerReached, + markers: markers + }); + console.log('[Invidious Debug] Markers initialized.'); + } catch (e) { + console.error('[Invidious Debug] Markers FAILED:', e); + } + + player.currentTime(video_data.params.video_start); } +player.volume(video_data.params.volume / 100); +player.playbackRate(video_data.params.speed); +console.log('[Invidious Debug] Volume and playback rate set.'); + +if (player.share) { + console.log('[Invidious Debug] Initializing share plugin...'); + try { + player.share(shareOptions); + console.log('[Invidious Debug] Share plugin initialized.'); + } catch(e) { + console.error('[Invidious Debug] Share plugin FAILED:', e); + } +} + +/** + * Method for saving the current video time + * + * @param {number} seconds + */ function save_video_time(seconds) { const all_video_times = get_all_video_times(); all_video_times[video_data.id] = seconds; helpers.storage.set(save_player_pos_key, all_video_times); } +/** + * Method for getting the saved video time + * + * @returns {number} + */ function get_video_time() { return get_all_video_times()[video_data.id] || 0; } +/** + * Method for getting all saved video times + * + * @returns {Object} + */ function get_all_video_times() { return helpers.storage.get(save_player_pos_key) || {}; } +/** + * Method for removing all saved video times + */ function remove_all_video_times() { helpers.storage.remove(save_player_pos_key); } +/** + * Method for setting the video time to a certain percentage + * + * @param {number} percent + */ function set_time_percent(percent) { const duration = player.duration(); const newTime = duration * (percent / 100); player.currentTime(newTime); } +/** + * Method for playing the video + */ function play() { player.play(); } + +/** + * Method for pausing the video + */ function pause() { player.pause(); } + +/** + * Method for stopping the video + */ function stop() { player.pause(); player.currentTime(0); } + +/** + * Method for toggling play/pause + */ function toggle_play() { player.paused() ? play() : pause(); } +/** + * Method for toggling captions + */ const toggle_captions = (function () { let toggledTrack = null; @@ -518,10 +656,18 @@ const toggle_captions = (function () { }; })(); +/** + * Method for toggling fullscreen + */ function toggle_fullscreen() { player.isFullscreen() ? player.exitFullscreen() : player.requestFullscreen(); } +/** + * Method for increasing playback rate + * + * @param {number} steps + */ function increase_playback_rate(steps) { const maxIndex = options.playbackRates.length - 1; const curIndex = options.playbackRates.indexOf(player.playbackRate()); @@ -530,6 +676,7 @@ function increase_playback_rate(steps) { player.playbackRate(options.playbackRates[newIndex]); } +// Add event listener for keydown events addEventListener('keydown', function (e) { if (e.target.tagName.toLowerCase() === 'input') { // Ignore input when focus is on certain elements, e.g. form fields. @@ -664,17 +811,6 @@ addEventListener('keydown', function (e) { player.on('DOMMouseScroll', mouseScroll); }()); -// Since videojs-share can sometimes be blocked, we defer it until last -if (player.share) { - console.log('[Invidious Debug] Initializing share plugin...'); - try { - player.share(shareOptions); - console.log('[Invidious Debug] Share plugin initialized.'); - } catch(e) { - console.error('[Invidious Debug] Share plugin FAILED:', e); - } -} - // show the preferred caption by default if (player_data.preferred_caption_found) { player.ready(function () {