diff --git a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.css b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.css index d6a35f6b79b4..4637f7b1c3f6 100644 --- a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.css +++ b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.css @@ -65,6 +65,39 @@ /* user-select is intentionally not disabled, so that you can select and copy the stats */ } +.offlineWrapper { + position: absolute; + top: 20px; + right: 20px; + margin-left: 20px; + display: flex; + flex-direction: row; + gap: 10px; + align-items: center; + background-color: #000; + padding: 10px; + border-radius: 10px; +} + +:global(body[dir='rtl'] .offlineWrapper) { + right: initial; + margin-left: initial; + left: 20px; + margin-right: 20px; +} + +.offlineIcon { + font-size: 30px; +} + +.offlineMessage { + margin: 0; +} + +.offlineMessageSubtitle { + font-size: 0.8em; +} + :deep(.shaka-volume-bar-container) { flex-shrink: initial; } diff --git a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js index 6f70fc0dd881..d4039fb082f3 100644 --- a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js +++ b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js @@ -2278,6 +2278,31 @@ export default defineComponent({ // #endregion seek bar markers + // #region offline message + + const isOffline = ref(!navigator.onLine) + const isBuffering = ref(false) + + function onlineHandler() { + isOffline.value = false + } + + function offlineHandler() { + isOffline.value = true + } + + window.addEventListener('online', onlineHandler) + window.addEventListener('offline', offlineHandler) + + // Only display the offline message while buffering/the loading symbol is visible. + // If we briefly lose the connection but it comes back before the buffer is empty, + // the user won't notice anything so we don't need to display the message. + const showOfflineMessage = computed(() => { + return isOffline.value && isBuffering.value + }) + + // #endregion offline message + // #region setup onMounted(async () => { @@ -2320,6 +2345,10 @@ export default defineComponent({ const controls = ui.getControls() player = controls.getPlayer() + player.addEventListener('buffering', event => { + isBuffering.value = event.buffering + }) + player.addEventListener('error', event => handleError(event.detail, 'shaka error handler')) player.configure(getPlayerConfig(props.format, defaultQuality.value === 'auto')) @@ -2701,6 +2730,9 @@ export default defineComponent({ } skippedSponsorBlockSegments.value.forEach(segment => clearTimeout(segment.timeoutId)) + + window.removeEventListener('online', onlineHandler) + window.removeEventListener('offline', offlineHandler) }) // #endregion tear down @@ -2753,6 +2785,8 @@ export default defineComponent({ skippedSponsorBlockSegments, + showOfflineMessage, + handlePlay, handlePause, handleEnded, diff --git a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue index a9aea678c671..f067e092dc94 100644 --- a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue +++ b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue @@ -65,6 +65,28 @@ {{ $t('Video.Player.Stats.Dropped Frames / Total Frames', stats.frames) }} +
+ +

+ + {{ $t('Video.Player.You appear to be offline') }} + +
+ + {{ $t('Video.Player.Playback will resume automatically when your connection comes back') }} + +

+