From 614c9e4481f5a0e436802060204f80c0e80942fa Mon Sep 17 00:00:00 2001 From: Doxterpepper Date: Tue, 13 Aug 2024 11:53:19 -0400 Subject: [PATCH 1/5] Backport pull request #5730 from jellyfin-web/release-10.9.z Add no-cache attribute for fetch requests to /system/info/public to prevent stale server info Original-merge: a0e6da790c3f40185eb970836d38569cab2fd047 Merged-by: thornbill Backported-by: thornbill --- src/components/ConnectionRequired.tsx | 2 +- src/components/router/appRouter.js | 2 +- src/hooks/useSystemInfo.ts | 2 +- src/utils/dashboard.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/ConnectionRequired.tsx b/src/components/ConnectionRequired.tsx index 8dde8ec1e7..ad2577c5d1 100644 --- a/src/components/ConnectionRequired.tsx +++ b/src/components/ConnectionRequired.tsx @@ -83,7 +83,7 @@ const ConnectionRequired: FunctionComponent = ({ if (firstConnection.State === ConnectionState.ServerSignIn) { // Verify the wizard is complete try { - const infoResponse = await fetch(`${firstConnection.ApiClient.serverAddress()}/System/Info/Public`); + const infoResponse = await fetch(`${firstConnection.ApiClient.serverAddress()}/System/Info/Public`, { cache: 'no-cache' }); if (!infoResponse.ok) { throw new Error('Public system info request failed'); } diff --git a/src/components/router/appRouter.js b/src/components/router/appRouter.js index 20571c840f..31e949035d 100644 --- a/src/components/router/appRouter.js +++ b/src/components/router/appRouter.js @@ -387,7 +387,7 @@ class AppRouter { if (firstResult) { if (firstResult.State === ConnectionState.ServerSignIn) { const url = firstResult.ApiClient.serverAddress() + '/System/Info/Public'; - fetch(url).then(response => { + fetch(url, { cache: 'no-cache' }).then(response => { if (!response.ok) return Promise.reject(new Error('fetch failed')); return response.json(); }).then(data => { diff --git a/src/hooks/useSystemInfo.ts b/src/hooks/useSystemInfo.ts index 9fed3dd3f6..0fa4604a59 100644 --- a/src/hooks/useSystemInfo.ts +++ b/src/hooks/useSystemInfo.ts @@ -23,7 +23,7 @@ export const getSystemInfoQuery = ( api?: Api ) => queryOptions({ queryKey: [ 'SystemInfo' ], - queryFn: ({ signal }) => fetchSystemInfo(api, { signal }), + queryFn: ({ signal }) => fetchSystemInfo(api, { signal, headers: { 'Cache-Control': 'no-cache' } }), // Allow for query reuse in legacy javascript. staleTime: 1000, // 1 second enabled: !!api diff --git a/src/utils/dashboard.js b/src/utils/dashboard.js index 393125c6fd..89c4c406d6 100644 --- a/src/utils/dashboard.js +++ b/src/utils/dashboard.js @@ -52,7 +52,7 @@ export async function serverAddress() { console.debug('URL candidates:', urls); const promises = urls.map(url => { - return fetch(`${url}/System/Info/Public`) + return fetch(`${url}/System/Info/Public`, { cache: 'no-cache' }) .then(async resp => { if (!resp.ok) { return; From 371994642d3d9b906057f8b9b797bc1b3ce526f0 Mon Sep 17 00:00:00 2001 From: ilteoood Date: Tue, 13 Aug 2024 11:53:20 -0400 Subject: [PATCH 2/5] Backport pull request #5823 from jellyfin-web/release-10.9.z Use navigate instead of resolver Original-merge: 2e4e4050cd4f8b0c8decb6092e5b06ceb3efd839 Merged-by: thornbill Backported-by: thornbill --- src/apps/experimental/routes/routes.tsx | 4 ++-- src/apps/stable/routes/routes.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apps/experimental/routes/routes.tsx b/src/apps/experimental/routes/routes.tsx index 02efc1e7ef..8f9ed6587f 100644 --- a/src/apps/experimental/routes/routes.tsx +++ b/src/apps/experimental/routes/routes.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { RouteObject, redirect } from 'react-router-dom'; +import { Navigate, RouteObject } from 'react-router-dom'; import { REDIRECTS } from 'apps/dashboard/routes/_redirects'; import ConnectionRequired from 'components/ConnectionRequired'; @@ -35,7 +35,7 @@ export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [ }, /* Public routes */ - { index: true, loader: () => redirect('/home.html') }, + { index: true, element: }, ...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute) ] }, diff --git a/src/apps/stable/routes/routes.tsx b/src/apps/stable/routes/routes.tsx index bf66a48459..61feac2ad0 100644 --- a/src/apps/stable/routes/routes.tsx +++ b/src/apps/stable/routes/routes.tsx @@ -1,4 +1,4 @@ -import { RouteObject, redirect } from 'react-router-dom'; +import { Navigate, RouteObject } from 'react-router-dom'; import React from 'react'; import ConnectionRequired from 'components/ConnectionRequired'; @@ -30,7 +30,7 @@ export const STABLE_APP_ROUTES: RouteObject[] = [ }, /* Public routes */ - { index: true, loader: () => redirect('/home.html') }, + { index: true, element: }, ...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute) ] }, From 75d78a96b8553c60947d866a8bb72ae5f068d141 Mon Sep 17 00:00:00 2001 From: viown <48097677+viown@users.noreply.github.com> Date: Tue, 13 Aug 2024 11:53:21 -0400 Subject: [PATCH 3/5] Backport pull request #5843 from jellyfin-web/release-10.9.z Fix swipe gestures on android for book reader Original-merge: 44afbc2357df70613b56a2d397a6fa41457250ef Merged-by: thornbill Backported-by: thornbill --- src/plugins/bookPlayer/plugin.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/plugins/bookPlayer/plugin.js b/src/plugins/bookPlayer/plugin.js index ef8fef28b5..17fec59285 100644 --- a/src/plugins/bookPlayer/plugin.js +++ b/src/plugins/bookPlayer/plugin.js @@ -7,6 +7,7 @@ import ServerConnections from '../../components/ServerConnections'; import Screenfull from 'screenfull'; import TableOfContents from './tableOfContents'; import { translateHtml } from '../../scripts/globalize'; +import browser from 'scripts/browser'; import * as userSettings from '../../scripts/settings/userSettings'; import TouchHelper from 'scripts/touchHelper'; import { PluginType } from '../../types/plugin.ts'; @@ -45,6 +46,7 @@ export class BookPlayer { this.previous = this.previous.bind(this); this.next = this.next.bind(this); this.onWindowKeyUp = this.onWindowKeyUp.bind(this); + this.addSwipeGestures = this.addSwipeGestures.bind(this); } play(options) { @@ -155,6 +157,12 @@ export class BookPlayer { } } + addSwipeGestures(element) { + this.touchHelper = new TouchHelper(element); + Events.on(this.touchHelper, 'swipeleft', () => this.next()); + Events.on(this.touchHelper, 'swiperight', () => this.previous()); + } + onDialogClosed() { this.stop(); } @@ -179,10 +187,12 @@ export class BookPlayer { document.addEventListener('keyup', this.onWindowKeyUp); this.rendition?.on('keyup', this.onWindowKeyUp); - const player = document.getElementById('bookPlayerContainer'); - this.touchHelper = new TouchHelper(player); - Events.on(this.touchHelper, 'swipeleft', () => this.next()); - Events.on(this.touchHelper, 'swiperight', () => this.previous()); + if (browser.safari) { + const player = document.getElementById('bookPlayerContainer'); + this.addSwipeGestures(player); + } else { + this.rendition?.on('rendered', (e, i) => this.addSwipeGestures(i.document.documentElement)); + } } unbindMediaElementEvents() { @@ -207,6 +217,10 @@ export class BookPlayer { document.removeEventListener('keyup', this.onWindowKeyUp); this.rendition?.off('keyup', this.onWindowKeyUp); + if (!browser.safari) { + this.rendition?.off('rendered', (e, i) => this.addSwipeGestures(i.document.documentElement)); + } + this.touchHelper?.destroy(); } From 37fbfb37722a083e0e8a072b37dbf52a80a59f4c Mon Sep 17 00:00:00 2001 From: thornbill Date: Tue, 13 Aug 2024 11:53:23 -0400 Subject: [PATCH 4/5] Backport pull request #5898 from jellyfin-web/release-10.9.z Fix autoCast race condition Original-merge: 7f575d724ed04d3409c104cee59de9c1be86feda Merged-by: thornbill Backported-by: thornbill --- .../AppToolbar/menus/RemotePlayActiveMenu.tsx | 29 +++++++++---------- .../playback/playerSelectionMenu.js | 14 ++++----- src/index.jsx | 3 ++ src/scripts/autocast.js | 19 +++--------- 4 files changed, 26 insertions(+), 39 deletions(-) diff --git a/src/apps/experimental/components/AppToolbar/menus/RemotePlayActiveMenu.tsx b/src/apps/experimental/components/AppToolbar/menus/RemotePlayActiveMenu.tsx index 0ea518c6c9..e184a3a25d 100644 --- a/src/apps/experimental/components/AppToolbar/menus/RemotePlayActiveMenu.tsx +++ b/src/apps/experimental/components/AppToolbar/menus/RemotePlayActiveMenu.tsx @@ -12,7 +12,7 @@ import { playbackManager } from 'components/playback/playbackmanager'; import React, { FC, useCallback, useState } from 'react'; import { Link } from 'react-router-dom'; -import { enable, isEnabled, supported } from 'scripts/autocast'; +import { enable, isEnabled } from 'scripts/autocast'; import globalize from 'scripts/globalize'; interface RemotePlayActiveMenuProps extends MenuProps { @@ -43,11 +43,10 @@ const RemotePlayActiveMenu: FC = ({ }, [ isDisplayMirrorEnabled, setIsDisplayMirrorEnabled ]); const [ isAutoCastEnabled, setIsAutoCastEnabled ] = useState(isEnabled()); - const isAutoCastSupported = supported(); const toggleAutoCast = useCallback(() => { enable(!isAutoCastEnabled); setIsAutoCastEnabled(!isAutoCastEnabled); - }, [ isAutoCastEnabled, setIsAutoCastEnabled ]); + }, [ isAutoCastEnabled ]); const remotePlayerName = playerInfo?.deviceName || playerInfo?.name; @@ -117,20 +116,18 @@ const RemotePlayActiveMenu: FC = ({ )} - {isAutoCastSupported && ( - - {isAutoCastEnabled && ( - - - - )} - - {globalize.translate('EnableAutoCast')} - - - )} + + {isAutoCastEnabled && ( + + + + )} + + {globalize.translate('EnableAutoCast')} + + - {(isDisplayMirrorSupported || isAutoCastSupported) && } + '; - html += '' + globalize.translate('EnableAutoCast') + ''; - html += ''; - } + html += '
'; html += '
'; diff --git a/src/index.jsx b/src/index.jsx index a74802cbb2..e8a3b5a3ad 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -24,6 +24,7 @@ import packageManager from './components/packageManager'; import './components/playback/displayMirrorManager.ts'; import { appRouter } from './components/router/appRouter'; import './elements/emby-button/emby-button'; +import { initialize as initializeAutoCast } from 'scripts/autocast'; import './scripts/autoThemes'; import './components/themeMediaPlayer'; import { pageClassOn, serverAddress } from './utils/dashboard'; @@ -79,6 +80,8 @@ build: ${__JF_BUILD_VERSION__}`); }).then(() => { console.debug('initAfterDependencies promises resolved'); + initializeAutoCast(ServerConnections.currentApiClient()); + loadCoreDictionary().then(function () { onGlobalizeInit(); }); diff --git a/src/scripts/autocast.js b/src/scripts/autocast.js index 2633587ba5..ead25e06eb 100644 --- a/src/scripts/autocast.js +++ b/src/scripts/autocast.js @@ -1,14 +1,7 @@ import { playbackManager } from '../components/playback/playbackmanager'; -import ServerConnections from '../components/ServerConnections'; import Events from '../utils/events.ts'; -export function supported() { - return typeof(Storage) !== 'undefined'; -} - export function enable(enabled) { - if (!supported()) return; - if (enabled) { const currentPlayerInfo = playbackManager.getPlayerInfo(); @@ -21,8 +14,6 @@ export function enable(enabled) { } export function isEnabled() { - if (!supported()) return false; - const playerId = localStorage.getItem('autocastPlayerId'); const currentPlayerInfo = playbackManager.getPlayerInfo(); @@ -42,12 +33,10 @@ function onOpen() { }); } -try { - const apiClient = ServerConnections.currentApiClient(); - - if (apiClient && supported()) { +export function initialize(apiClient) { + if (apiClient) { Events.on(apiClient, 'websocketopen', onOpen); + } else { + console.warn('[autoCast] cannot initialize missing apiClient'); } -} catch (ex) { - console.warn('Could not get current apiClient', ex); } From 6d350b8aa4db122751e377215bd14ab3d4fd5b4e Mon Sep 17 00:00:00 2001 From: jchuong Date: Tue, 13 Aug 2024 11:53:24 -0400 Subject: [PATCH 5/5] Backport pull request #5910 from jellyfin-web/release-10.9.z Fix "Download All" for Safari Original-merge: 4071c4443757aa01f46398b981f1ccc25615c379 Merged-by: thornbill Backported-by: thornbill --- src/scripts/multiDownload.js | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/scripts/multiDownload.js b/src/scripts/multiDownload.js index ec3db52015..c9f40f56a4 100644 --- a/src/scripts/multiDownload.js +++ b/src/scripts/multiDownload.js @@ -27,19 +27,11 @@ function fallback(urls) { })(); } -function sameDomain(url) { - const a = document.createElement('a'); - a.href = url; - - return window.location.hostname === a.hostname && window.location.protocol === a.protocol; -} - function download(url) { const a = document.createElement('a'); a.download = ''; a.href = url; - // firefox doesn't support `a.click()`... - a.dispatchEvent(new MouseEvent('click')); + a.click(); } export default function (urls) { @@ -47,19 +39,13 @@ export default function (urls) { throw new Error('`urls` required'); } - if (typeof document.createElement('a').download === 'undefined') { + if (typeof document.createElement('a').download === 'undefined' || browser.iOS) { return fallback(urls); } let delay = 0; urls.forEach(function (url) { - // the download init has to be sequential for firefox if the urls are not on the same domain - if (browser.firefox && !sameDomain(url)) { - setTimeout(download.bind(null, url), 100 * ++delay); - return; - } - - download(url); + setTimeout(download.bind(null, url), 100 * ++delay); }); }