From d297f239329a1494b6822b717527f0dffdc5a918 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Fri, 28 Oct 2022 01:09:59 -0400 Subject: [PATCH 1/7] Add api and user contexts --- src/App.tsx | 64 +++++++++++++++++++++ src/apiclient.d.ts | 1 + src/components/search/SearchSuggestions.tsx | 40 +++++++------ src/hooks/useApi.ts | 5 ++ src/hooks/useUser.ts | 5 ++ src/index.jsx | 7 +-- src/routes/search.tsx | 1 - src/utils/sdk.ts | 23 ++++++++ 8 files changed, 124 insertions(+), 22 deletions(-) create mode 100644 src/App.tsx create mode 100644 src/hooks/useApi.ts create mode 100644 src/hooks/useUser.ts create mode 100644 src/utils/sdk.ts diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000000..50661303db --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,64 @@ +import { Api } from '@jellyfin/sdk'; +import { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto'; +import { History } from '@remix-run/router'; +import { ApiClient, ConnectionManager } from 'jellyfin-apiclient'; +import React, { useEffect, useState } from 'react'; + +import { HistoryRouter } from './components/HistoryRouter'; +import ServerConnections from './components/ServerConnections'; +import { ApiContext } from './hooks/useApi'; +import { UserContext } from './hooks/useUser'; +import AppRoutes from './routes/index'; +import events from './utils/events'; +import { toApi } from './utils/sdk'; + +interface ServerConnections extends ConnectionManager { + currentApiClient: () => ApiClient +} + +const App = ({ history, connections }: { history: History, connections: ServerConnections }) => { + const [ api, setApi ] = useState(toApi(connections.currentApiClient())); + const [ user, setUser ] = useState(); + + useEffect(() => { + connections.currentApiClient() + .getCurrentUser() + .then(newUser => setUser(newUser)) + .catch(err => { + console.warn('[App] Could not get current user', err); + }); + + const udpateApiUser = (_e: any, newUser: UserDto) => { + setUser(newUser); + + if (newUser.ServerId) { + setApi(toApi(connections.getApiClient(newUser.ServerId))); + } + }; + + const resetApiUser = () => { + setApi(undefined); + setUser(undefined); + }; + + events.on(connections, 'localusersignedin', udpateApiUser); + events.on(connections, 'localusersignedout', resetApiUser); + + return () => { + events.off(connections, 'localusersignedin', udpateApiUser); + events.off(connections, 'localusersignedout', resetApiUser); + }; + }, [ connections ]); + + return ( + + + + + + + + ); +}; + +export default App; diff --git a/src/apiclient.d.ts b/src/apiclient.d.ts index 9ad794dd65..33f3752ca7 100644 --- a/src/apiclient.d.ts +++ b/src/apiclient.d.ts @@ -117,6 +117,7 @@ declare module 'jellyfin-apiclient' { getCountries(): Promise; getCriticReviews(itemId: string, options?: any): Promise; getCultures(): Promise; + getCurrentUser(cache?: boolean): Promise; getCurrentUserId(): string; getDateParamValue(date: Date): string; getDefaultImageQuality(imageType: ImageType): number; diff --git a/src/components/search/SearchSuggestions.tsx b/src/components/search/SearchSuggestions.tsx index 2442861893..887fa2481e 100644 --- a/src/components/search/SearchSuggestions.tsx +++ b/src/components/search/SearchSuggestions.tsx @@ -1,10 +1,14 @@ import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client'; +import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind'; +import { getItemsApi } from '@jellyfin/sdk/lib/utils/api/items-api'; +import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by'; import escapeHtml from 'escape-html'; import React, { FunctionComponent, useEffect, useState } from 'react'; import { appRouter } from '../appRouter'; +import { useApi } from '../../hooks/useApi'; +import { useUser } from '../../hooks/useUser'; import globalize from '../../scripts/globalize'; -import ServerConnections from '../ServerConnections'; import '../../elements/emby-button/emby-button'; @@ -21,27 +25,31 @@ const createSuggestionLink = ({ name, href }: { name: string, href: string }) => }); type SearchSuggestionsProps = { - serverId?: string; parentId?: string | null; } -const SearchSuggestions: FunctionComponent = ({ serverId = window.ApiClient.serverId(), parentId }: SearchSuggestionsProps) => { +const SearchSuggestions: FunctionComponent = ({ parentId }: SearchSuggestionsProps) => { const [ suggestions, setSuggestions ] = useState([]); + const api = useApi(); + const user = useUser(); useEffect(() => { - const apiClient = ServerConnections.getApiClient(serverId); - - apiClient.getItems(apiClient.getCurrentUserId(), { - SortBy: 'IsFavoriteOrLiked,Random', - IncludeItemTypes: 'Movie,Series,MusicArtist', - Limit: 20, - Recursive: true, - ImageTypeLimit: 0, - EnableImages: false, - ParentId: parentId, - EnableTotalRecordCount: false - }).then(result => setSuggestions(result.Items || [])); - }, [parentId, serverId]); + if (api && user?.Id) { + getItemsApi(api) + .getItemsByUserId({ + userId: user.Id, + sortBy: [ItemSortBy.IsFavoriteOrLiked, ItemSortBy.Random], + includeItemTypes: [BaseItemKind.Movie, BaseItemKind.Series, BaseItemKind.MusicArtist], + limit: 20, + recursive: true, + imageTypeLimit: 0, + enableImages: false, + parentId: parentId || undefined, + enableTotalRecordCount: false + }) + .then(result => setSuggestions(result.data.Items || [])); + } + }, [api, parentId, user?.Id]); return (
(undefined); +export const useApi = () => useContext(ApiContext); diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts new file mode 100644 index 0000000000..ad681f71d2 --- /dev/null +++ b/src/hooks/useUser.ts @@ -0,0 +1,5 @@ +import { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto'; +import { createContext, useContext } from 'react'; + +export const UserContext = createContext(undefined); +export const useUser = () => useContext(UserContext); diff --git a/src/index.jsx b/src/index.jsx index 2c786b736e..15d6b48d11 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -37,8 +37,7 @@ import './legacy/htmlMediaElement'; import './legacy/vendorStyles'; import { currentSettings } from './scripts/settings/userSettings'; import taskButton from './scripts/taskbutton'; -import { HistoryRouter } from './components/HistoryRouter.tsx'; -import AppRoutes from './routes/index.tsx'; +import App from './App.tsx'; function loadCoreDictionary() { const languages = ['af', 'ar', 'be-by', 'bg-bg', 'bn_bd', 'ca', 'cs', 'cy', 'da', 'de', 'el', 'en-gb', 'en-us', 'eo', 'es', 'es-419', 'es-ar', 'es_do', 'es-mx', 'et', 'eu', 'fa', 'fi', 'fil', 'fr', 'fr-ca', 'gl', 'gsw', 'he', 'hi-in', 'hr', 'hu', 'id', 'it', 'ja', 'kk', 'ko', 'lt-lt', 'lv', 'mr', 'ms', 'nb', 'nl', 'nn', 'pl', 'pr', 'pt', 'pt-br', 'pt-pt', 'ro', 'ru', 'sk', 'sl-si', 'sq', 'sv', 'ta', 'th', 'tr', 'uk', 'ur_pk', 'vi', 'zh-cn', 'zh-hk', 'zh-tw']; @@ -146,9 +145,7 @@ async function onAppReady() { ReactDOM.render( - - - + , document.getElementById('reactRoot') ); diff --git a/src/routes/search.tsx b/src/routes/search.tsx index 059a81783f..d154018b4e 100644 --- a/src/routes/search.tsx +++ b/src/routes/search.tsx @@ -21,7 +21,6 @@ const Search: FunctionComponent = () => { {!query && } diff --git a/src/utils/sdk.ts b/src/utils/sdk.ts new file mode 100644 index 0000000000..444dbee45f --- /dev/null +++ b/src/utils/sdk.ts @@ -0,0 +1,23 @@ +import { Api, Jellyfin } from '@jellyfin/sdk'; +import { ApiClient } from 'jellyfin-apiclient'; + +/** + * Returns an SDK Api instance using the same parameters as the provided ApiClient. + * @param {ApiClient} apiClient The (legacy) ApiClient. + * @returns {Api} An equivalent SDK Api instance. + */ +export const toApi = (apiClient: ApiClient): Api => { + return (new Jellyfin({ + clientInfo: { + name: apiClient.appName(), + version: apiClient.appVersion() + }, + deviceInfo: { + name: apiClient.deviceName(), + id: apiClient.deviceId() + } + })).createApi( + apiClient.serverAddress(), + apiClient.accessToken() + ); +}; From 72dab5381dd761de890ed25697854429b37f190d Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Fri, 28 Oct 2022 12:53:31 -0400 Subject: [PATCH 2/7] Update typing for currentApiClient --- src/App.tsx | 7 +------ src/components/ConnectionRequired.tsx | 2 +- src/components/ServerConnections.js | 4 ++++ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 50661303db..d88e709c6e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,6 @@ import { Api } from '@jellyfin/sdk'; import { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto'; import { History } from '@remix-run/router'; -import { ApiClient, ConnectionManager } from 'jellyfin-apiclient'; import React, { useEffect, useState } from 'react'; import { HistoryRouter } from './components/HistoryRouter'; @@ -12,11 +11,7 @@ import AppRoutes from './routes/index'; import events from './utils/events'; import { toApi } from './utils/sdk'; -interface ServerConnections extends ConnectionManager { - currentApiClient: () => ApiClient -} - -const App = ({ history, connections }: { history: History, connections: ServerConnections }) => { +const App = ({ history, connections }: { history: History, connections: typeof ServerConnections }) => { const [ api, setApi ] = useState(toApi(connections.currentApiClient())); const [ user, setUser ] = useState(); diff --git a/src/components/ConnectionRequired.tsx b/src/components/ConnectionRequired.tsx index 9de9db0eca..1bc211c43a 100644 --- a/src/components/ConnectionRequired.tsx +++ b/src/components/ConnectionRequired.tsx @@ -129,7 +129,7 @@ const ConnectionRequired: FunctionComponent = ({ if (isAdminRequired) { try { const user = await client.getCurrentUser(); - if (!user.Policy.IsAdministrator) { + if (!user.Policy?.IsAdministrator) { console.warn('[ConnectionRequired] normal user attempted to access admin route'); bounce(await ServerConnections.connect()); return; diff --git a/src/components/ServerConnections.js b/src/components/ServerConnections.js index 5f7a7ef673..2ae12aad36 100644 --- a/src/components/ServerConnections.js +++ b/src/components/ServerConnections.js @@ -86,6 +86,10 @@ class ServerConnections extends ConnectionManager { return this.localApiClient; } + /** + * Gets the ApiClient that is currently connected. + * @returns {ApiClient} apiClient + */ currentApiClient() { let apiClient = this.getLocalApiClient(); From 331f05b77df77a1b25c4657e83bdbb2dd55e34b0 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Tue, 1 Nov 2022 17:43:44 -0400 Subject: [PATCH 3/7] Babelify compare-versions dependency --- webpack.common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webpack.common.js b/webpack.common.js index 4c15134b52..2548961b89 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -146,7 +146,7 @@ const config = { }, { test: /\.(js|jsx)$/, - exclude: /node_modules[\\/](?!@uupaa[\\/]dynamic-import-polyfill|@remix-run[\\/]router|blurhash|date-fns|dom7|epubjs|flv.js|libarchive.js|marked|react-router|screenfull|ssr-window|swiper)/, + exclude: /node_modules[\\/](?!@uupaa[\\/]dynamic-import-polyfill|@remix-run[\\/]router|blurhash|compare-versions|date-fns|dom7|epubjs|flv.js|libarchive.js|marked|react-router|screenfull|ssr-window|swiper)/, use: [{ loader: 'babel-loader', options: { From c8ea7322fd819584114585091f5555698ea89b9d Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Fri, 18 Nov 2022 12:55:46 -0500 Subject: [PATCH 4/7] Refactor api hooks --- src/App.tsx | 54 ++------------ src/components/search/SearchSuggestions.tsx | 6 +- src/hooks/useApi.ts | 5 -- src/hooks/useApi.tsx | 71 +++++++++++++++++++ src/hooks/useUser.ts | 5 -- .../{sdk.ts => jellyfin-apiclient/compat.ts} | 0 6 files changed, 80 insertions(+), 61 deletions(-) delete mode 100644 src/hooks/useApi.ts create mode 100644 src/hooks/useApi.tsx delete mode 100644 src/hooks/useUser.ts rename src/utils/{sdk.ts => jellyfin-apiclient/compat.ts} (100%) diff --git a/src/App.tsx b/src/App.tsx index d88e709c6e..9f5552554e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,58 +1,18 @@ -import { Api } from '@jellyfin/sdk'; -import { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto'; import { History } from '@remix-run/router'; -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { HistoryRouter } from './components/HistoryRouter'; import ServerConnections from './components/ServerConnections'; -import { ApiContext } from './hooks/useApi'; -import { UserContext } from './hooks/useUser'; +import { ApiProvider } from './hooks/useApi'; import AppRoutes from './routes/index'; -import events from './utils/events'; -import { toApi } from './utils/sdk'; const App = ({ history, connections }: { history: History, connections: typeof ServerConnections }) => { - const [ api, setApi ] = useState(toApi(connections.currentApiClient())); - const [ user, setUser ] = useState(); - - useEffect(() => { - connections.currentApiClient() - .getCurrentUser() - .then(newUser => setUser(newUser)) - .catch(err => { - console.warn('[App] Could not get current user', err); - }); - - const udpateApiUser = (_e: any, newUser: UserDto) => { - setUser(newUser); - - if (newUser.ServerId) { - setApi(toApi(connections.getApiClient(newUser.ServerId))); - } - }; - - const resetApiUser = () => { - setApi(undefined); - setUser(undefined); - }; - - events.on(connections, 'localusersignedin', udpateApiUser); - events.on(connections, 'localusersignedout', resetApiUser); - - return () => { - events.off(connections, 'localusersignedin', udpateApiUser); - events.off(connections, 'localusersignedout', resetApiUser); - }; - }, [ connections ]); - return ( - - - - - - - + + + + + ); }; diff --git a/src/components/search/SearchSuggestions.tsx b/src/components/search/SearchSuggestions.tsx index 887fa2481e..d16cdca8e6 100644 --- a/src/components/search/SearchSuggestions.tsx +++ b/src/components/search/SearchSuggestions.tsx @@ -7,7 +7,6 @@ import React, { FunctionComponent, useEffect, useState } from 'react'; import { appRouter } from '../appRouter'; import { useApi } from '../../hooks/useApi'; -import { useUser } from '../../hooks/useUser'; import globalize from '../../scripts/globalize'; import '../../elements/emby-button/emby-button'; @@ -30,8 +29,7 @@ type SearchSuggestionsProps = { const SearchSuggestions: FunctionComponent = ({ parentId }: SearchSuggestionsProps) => { const [ suggestions, setSuggestions ] = useState([]); - const api = useApi(); - const user = useUser(); + const { api, user } = useApi(); useEffect(() => { if (api && user?.Id) { @@ -49,7 +47,7 @@ const SearchSuggestions: FunctionComponent = ({ parentId }) .then(result => setSuggestions(result.data.Items || [])); } - }, [api, parentId, user?.Id]); + }, [ api, parentId, user ]); return (
(undefined); -export const useApi = () => useContext(ApiContext); diff --git a/src/hooks/useApi.tsx b/src/hooks/useApi.tsx new file mode 100644 index 0000000000..7952a9030d --- /dev/null +++ b/src/hooks/useApi.tsx @@ -0,0 +1,71 @@ +import type { Api } from '@jellyfin/sdk'; +import type { UserDto } from '@jellyfin/sdk/lib/generated-client'; +import { ApiClient } from 'jellyfin-apiclient'; +import React, { createContext, FC, useContext, useEffect, useState } from 'react'; + +import type ServerConnections from '../components/ServerConnections'; +import events from '../utils/events'; +import { toApi } from '../utils/jellyfin-apiclient/compat'; + +interface ApiProviderProps { + connections: typeof ServerConnections +} + +interface JellyfinApiContext { + __legacyApiClient__?: ApiClient + api?: Api + user?: UserDto +} + +export const ApiContext = createContext({}); +export const useApi = () => useContext(ApiContext); + +export const ApiProvider: FC = ({ connections, children }) => { + const [ legacyApiClient, setLegacyApiClient ] = useState(); + const [ api, setApi ] = useState(); + const [ user, setUser ] = useState(); + + useEffect(() => { + connections.currentApiClient() + .getCurrentUser() + .then(newUser => udpateApiUser(null, newUser)) + .catch(err => { + console.warn('[ApiProvider] Could not get current user', err); + }); + + const udpateApiUser = (_e: any, newUser: UserDto) => { + setUser(newUser); + + if (newUser.ServerId) { + setLegacyApiClient(connections.getApiClient(newUser.ServerId)); + } + }; + + const resetApiUser = () => { + setLegacyApiClient(undefined); + setUser(undefined); + }; + + events.on(connections, 'localusersignedin', udpateApiUser); + events.on(connections, 'localusersignedout', resetApiUser); + + return () => { + events.off(connections, 'localusersignedin', udpateApiUser); + events.off(connections, 'localusersignedout', resetApiUser); + }; + }, [ connections, setLegacyApiClient, setUser ]); + + useEffect(() => { + setApi(legacyApiClient ? toApi(legacyApiClient) : undefined); + }, [ legacyApiClient, setApi ]); + + return ( + + {children} + + ); +}; diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts deleted file mode 100644 index ad681f71d2..0000000000 --- a/src/hooks/useUser.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto'; -import { createContext, useContext } from 'react'; - -export const UserContext = createContext(undefined); -export const useUser = () => useContext(UserContext); diff --git a/src/utils/sdk.ts b/src/utils/jellyfin-apiclient/compat.ts similarity index 100% rename from src/utils/sdk.ts rename to src/utils/jellyfin-apiclient/compat.ts From 9bf0a6bf4d91345cbfcb4e0c5ce68f2ec71f9259 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Mon, 28 Nov 2022 16:51:57 -0500 Subject: [PATCH 5/7] Cleanup useApi hook --- src/hooks/useApi.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hooks/useApi.tsx b/src/hooks/useApi.tsx index 7952a9030d..1e17efcc14 100644 --- a/src/hooks/useApi.tsx +++ b/src/hooks/useApi.tsx @@ -1,6 +1,6 @@ import type { Api } from '@jellyfin/sdk'; import type { UserDto } from '@jellyfin/sdk/lib/generated-client'; -import { ApiClient } from 'jellyfin-apiclient'; +import type { ApiClient, Event } from 'jellyfin-apiclient'; import React, { createContext, FC, useContext, useEffect, useState } from 'react'; import type ServerConnections from '../components/ServerConnections'; @@ -28,12 +28,12 @@ export const ApiProvider: FC = ({ connections, children }) => useEffect(() => { connections.currentApiClient() .getCurrentUser() - .then(newUser => udpateApiUser(null, newUser)) + .then(newUser => updateApiUser(undefined, newUser)) .catch(err => { - console.warn('[ApiProvider] Could not get current user', err); + console.info('[ApiProvider] Could not get current user', err); }); - const udpateApiUser = (_e: any, newUser: UserDto) => { + const updateApiUser = (_e: Event | undefined, newUser: UserDto) => { setUser(newUser); if (newUser.ServerId) { @@ -46,11 +46,11 @@ export const ApiProvider: FC = ({ connections, children }) => setUser(undefined); }; - events.on(connections, 'localusersignedin', udpateApiUser); + events.on(connections, 'localusersignedin', updateApiUser); events.on(connections, 'localusersignedout', resetApiUser); return () => { - events.off(connections, 'localusersignedin', udpateApiUser); + events.off(connections, 'localusersignedin', updateApiUser); events.off(connections, 'localusersignedout', resetApiUser); }; }, [ connections, setLegacyApiClient, setUser ]); From 516bd2aab83f5dcf9f48c4d798e476eff91bcaa2 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 30 Nov 2022 14:18:49 -0500 Subject: [PATCH 6/7] Remove connections prop --- src/App.tsx | 5 ++--- src/hooks/useApi.tsx | 22 +++++++++------------- src/index.jsx | 2 +- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 9f5552554e..79828b6bd0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,13 +2,12 @@ import { History } from '@remix-run/router'; import React from 'react'; import { HistoryRouter } from './components/HistoryRouter'; -import ServerConnections from './components/ServerConnections'; import { ApiProvider } from './hooks/useApi'; import AppRoutes from './routes/index'; -const App = ({ history, connections }: { history: History, connections: typeof ServerConnections }) => { +const App = ({ history }: { history: History }) => { return ( - + diff --git a/src/hooks/useApi.tsx b/src/hooks/useApi.tsx index 1e17efcc14..409b40875f 100644 --- a/src/hooks/useApi.tsx +++ b/src/hooks/useApi.tsx @@ -3,14 +3,10 @@ import type { UserDto } from '@jellyfin/sdk/lib/generated-client'; import type { ApiClient, Event } from 'jellyfin-apiclient'; import React, { createContext, FC, useContext, useEffect, useState } from 'react'; -import type ServerConnections from '../components/ServerConnections'; +import ServerConnections from '../components/ServerConnections'; import events from '../utils/events'; import { toApi } from '../utils/jellyfin-apiclient/compat'; -interface ApiProviderProps { - connections: typeof ServerConnections -} - interface JellyfinApiContext { __legacyApiClient__?: ApiClient api?: Api @@ -20,13 +16,13 @@ interface JellyfinApiContext { export const ApiContext = createContext({}); export const useApi = () => useContext(ApiContext); -export const ApiProvider: FC = ({ connections, children }) => { +export const ApiProvider: FC = ({ children }) => { const [ legacyApiClient, setLegacyApiClient ] = useState(); const [ api, setApi ] = useState(); const [ user, setUser ] = useState(); useEffect(() => { - connections.currentApiClient() + ServerConnections.currentApiClient() .getCurrentUser() .then(newUser => updateApiUser(undefined, newUser)) .catch(err => { @@ -37,7 +33,7 @@ export const ApiProvider: FC = ({ connections, children }) => setUser(newUser); if (newUser.ServerId) { - setLegacyApiClient(connections.getApiClient(newUser.ServerId)); + setLegacyApiClient(ServerConnections.getApiClient(newUser.ServerId)); } }; @@ -46,14 +42,14 @@ export const ApiProvider: FC = ({ connections, children }) => setUser(undefined); }; - events.on(connections, 'localusersignedin', updateApiUser); - events.on(connections, 'localusersignedout', resetApiUser); + events.on(ServerConnections, 'localusersignedin', updateApiUser); + events.on(ServerConnections, 'localusersignedout', resetApiUser); return () => { - events.off(connections, 'localusersignedin', updateApiUser); - events.off(connections, 'localusersignedout', resetApiUser); + events.off(ServerConnections, 'localusersignedin', updateApiUser); + events.off(ServerConnections, 'localusersignedout', resetApiUser); }; - }, [ connections, setLegacyApiClient, setUser ]); + }, [ setLegacyApiClient, setUser ]); useEffect(() => { setApi(legacyApiClient ? toApi(legacyApiClient) : undefined); diff --git a/src/index.jsx b/src/index.jsx index 15d6b48d11..b0de802d59 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -145,7 +145,7 @@ async function onAppReady() { ReactDOM.render( - + , document.getElementById('reactRoot') ); From 5db9384c9ce95543fd70968fa89b8b2aaf29bcc6 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Thu, 8 Dec 2022 14:32:50 -0500 Subject: [PATCH 7/7] Fix currentApiClient return type to include undefined --- src/components/ConnectionRequired.tsx | 4 ++-- src/components/ServerConnections.js | 2 +- src/components/ServerContentPage.tsx | 2 +- src/hooks/useApi.tsx | 2 +- src/plugins/syncPlay/core/Manager.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/ConnectionRequired.tsx b/src/components/ConnectionRequired.tsx index 1bc211c43a..aa67a257e1 100644 --- a/src/components/ConnectionRequired.tsx +++ b/src/components/ConnectionRequired.tsx @@ -128,8 +128,8 @@ const ConnectionRequired: FunctionComponent = ({ // If this is an admin route, ensure the user has access if (isAdminRequired) { try { - const user = await client.getCurrentUser(); - if (!user.Policy?.IsAdministrator) { + const user = await client?.getCurrentUser(); + if (!user?.Policy?.IsAdministrator) { console.warn('[ConnectionRequired] normal user attempted to access admin route'); bounce(await ServerConnections.connect()); return; diff --git a/src/components/ServerConnections.js b/src/components/ServerConnections.js index 2ae12aad36..9bdb82fc60 100644 --- a/src/components/ServerConnections.js +++ b/src/components/ServerConnections.js @@ -88,7 +88,7 @@ class ServerConnections extends ConnectionManager { /** * Gets the ApiClient that is currently connected. - * @returns {ApiClient} apiClient + * @returns {ApiClient|undefined} apiClient */ currentApiClient() { let apiClient = this.getLocalApiClient(); diff --git a/src/components/ServerContentPage.tsx b/src/components/ServerContentPage.tsx index f5c705cf6f..7473c856e8 100644 --- a/src/components/ServerContentPage.tsx +++ b/src/components/ServerContentPage.tsx @@ -34,7 +34,7 @@ const ServerContentPage: FunctionComponent = ({ view }) const apiClient = ServerConnections.currentApiClient(); // Fetch the view html from the server and translate it - const viewHtml = await apiClient.get(apiClient.getUrl(view + location.search)) + const viewHtml = await apiClient?.get(apiClient.getUrl(view + location.search)) .then((html: string) => globalize.translateHtml(html)); viewManager.loadView({ diff --git a/src/hooks/useApi.tsx b/src/hooks/useApi.tsx index 409b40875f..7828db6cd8 100644 --- a/src/hooks/useApi.tsx +++ b/src/hooks/useApi.tsx @@ -23,7 +23,7 @@ export const ApiProvider: FC = ({ children }) => { useEffect(() => { ServerConnections.currentApiClient() - .getCurrentUser() + ?.getCurrentUser() .then(newUser => updateApiUser(undefined, newUser)) .catch(err => { console.info('[ApiProvider] Could not get current user', err); diff --git a/src/plugins/syncPlay/core/Manager.js b/src/plugins/syncPlay/core/Manager.js index af39d422d4..740e0709d9 100644 --- a/src/plugins/syncPlay/core/Manager.js +++ b/src/plugins/syncPlay/core/Manager.js @@ -71,7 +71,7 @@ class Manager { /** * Update active ApiClient. - * @param {Object} apiClient The ApiClient. + * @param {ApiClient|undefined} apiClient The ApiClient. */ updateApiClient(apiClient) { if (!apiClient) {