Require server settings and global metadata to be loaded

This commit is contained in:
schroda
2026-04-27 15:38:49 +02:00
parent a7dcdd5651
commit 9440326b72
2 changed files with 75 additions and 15 deletions

View File

@@ -7,7 +7,8 @@
*/ */
import CssBaseline from '@mui/material/CssBaseline'; import CssBaseline from '@mui/material/CssBaseline';
import React, { useEffect, useLayoutEffect } from 'react'; import type { PropsWithChildren } from 'react';
import React, { useEffect, useLayoutEffect, useState } from 'react';
import { Navigate, Outlet, Route, Routes, useLocation, useNavigate } from 'react-router-dom'; import { Navigate, Outlet, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
import { loadErrorMessages, loadDevMessages } from '@apollo/client/dev'; import { loadErrorMessages, loadDevMessages } from '@apollo/client/dev';
import { loadable } from 'react-lazily/loadable'; import { loadable } from 'react-lazily/loadable';
@@ -34,6 +35,8 @@ import { AuthManager } from '@/features/authentication/AuthManager.ts';
import { ImageProcessingType } from '@/features/settings/Settings.types.ts'; import { ImageProcessingType } from '@/features/settings/Settings.types.ts';
import { MigrationFABIndicator } from '@/features/migration/components/MigrationFABIndicator.tsx'; import { MigrationFABIndicator } from '@/features/migration/components/MigrationFABIndicator.tsx';
import { MigrationManager } from '@/features/migration/MigrationManager.ts'; import { MigrationManager } from '@/features/migration/MigrationManager.ts';
import { SplashScreen } from '@/features/authentication/components/SplashScreen.tsx';
import { d } from 'koration';
const { Browse } = loadable(() => import('@/features/browse/screens/Browse.tsx'), lazyLoadFallback); const { Browse } = loadable(() => import('@/features/browse/screens/Browse.tsx'), lazyLoadFallback);
const { DownloadQueue } = loadable(() => import('@/features/downloads/screens/DownloadQueue.tsx'), lazyLoadFallback); const { DownloadQueue } = loadable(() => import('@/features/downloads/screens/DownloadQueue.tsx'), lazyLoadFallback);
@@ -114,6 +117,55 @@ const ScrollToTop = () => {
return null; return null;
}; };
const InitializeGuard = ({ children }: PropsWithChildren) => {
const [isInitialized, setIsInitialized] = useState(false);
useEffect(() => {
type RequestConfig = [string, () => Promise<unknown>][];
type InFlightRequest = [string, Promise<unknown>];
const initialRequests: RequestConfig = [
['globalMeta', () => requestManager.getGlobalMeta().response],
['serverSettings', () => requestManager.getServerSettings().response],
];
const executeRequests = async (requests: RequestConfig, timeout: number = d(5).seconds.inWholeMilliseconds) => {
const runningRequests = requests.map(([key, fn]) => [key, fn()] satisfies InFlightRequest);
const failedRequests = runningRequests.filter(async ([_, request]) => {
try {
await request;
return false;
} catch (e) {
return true;
}
});
if (failedRequests.length) {
await new Promise((resolve) => {
setTimeout(resolve, timeout);
});
return executeRequests(
requests.filter(([key]) => !failedRequests.some(([k]) => k === key)),
(timeout * 1.5) % d(2).minutes.inWholeMilliseconds,
);
}
};
executeRequests(initialRequests).catch(defaultPromiseErrorHandler('InitializeGuard'));
setIsInitialized(true);
}, []);
if (isInitialized) {
return children;
}
return <SplashScreen />;
};
const InitialBackgroundRequests = () => { const InitialBackgroundRequests = () => {
// Load the full download status once on startup to fill the cache // Load the full download status once on startup to fill the cache
requestManager.useGetDownloadStatus({ nextFetchPolicy: 'standby' }); requestManager.useGetDownloadStatus({ nextFetchPolicy: 'standby' });
@@ -349,6 +401,7 @@ export const App: React.FC = () => (
<CssBaseline enableColorScheme /> <CssBaseline enableColorScheme />
<AuthGuard> <AuthGuard>
<InitializeGuard>
<ServerUpdateChecker /> <ServerUpdateChecker />
<WebUIUpdateChecker /> <WebUIUpdateChecker />
<InitialBackgroundRequests /> <InitialBackgroundRequests />
@@ -365,6 +418,7 @@ export const App: React.FC = () => (
</Routes> </Routes>
</Box> </Box>
<MigrationFABIndicator /> <MigrationFABIndicator />
</InitializeGuard>
</AuthGuard> </AuthGuard>
</AppContext> </AppContext>
); );

View File

@@ -3562,6 +3562,12 @@ export class RequestManager {
) as useSubscription.Result<UpdaterSubscription>; ) as useSubscription.Result<UpdaterSubscription>;
} }
public getServerSettings(
options?: QueryOptions<GetServerSettingsQueryVariables>,
): AbortabaleApolloQueryResponse<GetServerSettingsQuery> {
return this.doRequest(GQLMethod.QUERY, GET_SERVER_SETTINGS, undefined, options);
}
public useGetServerSettings( public useGetServerSettings(
options?: QueryHookOptions<GetServerSettingsQuery, GetServerSettingsQueryVariables>, options?: QueryHookOptions<GetServerSettingsQuery, GetServerSettingsQueryVariables>,
): AbortableApolloUseQueryResponse<GetServerSettingsQuery, GetServerSettingsQueryVariables> { ): AbortableApolloUseQueryResponse<GetServerSettingsQuery, GetServerSettingsQueryVariables> {