Made file config a context to reduce calls to backend

This commit is contained in:
Connor Yoh 2025-10-15 15:55:46 +01:00
parent 32c0fc0f1c
commit ce9dd57eb0
10 changed files with 50 additions and 19 deletions

View File

@ -7,6 +7,7 @@ import { ToolWorkflowProvider } from "./contexts/ToolWorkflowContext";
import { HotkeyProvider } from "./contexts/HotkeyContext";
import { SidebarProvider } from "./contexts/SidebarContext";
import { PreferencesProvider } from "./contexts/PreferencesContext";
import { AppConfigProvider } from "./contexts/AppConfigContext";
import ErrorBoundary from "./components/shared/ErrorBoundary";
import HomePage from "./pages/HomePage";
import { useScarfTracking } from "./hooks/useScarfTracking";
@ -38,16 +39,21 @@ const LoadingFallback = () => (
</div>
);
export default function App() {
// Initialize scarf tracking (mounts once at app startup)
// Component to initialize scarf tracking (must be inside AppConfigProvider)
function ScarfTrackingInitializer() {
useScarfTracking();
return null;
}
export default function App() {
return (
<Suspense fallback={<LoadingFallback />}>
<RainbowThemeProvider>
<ErrorBoundary>
<PreferencesProvider>
<FileContextProvider enableUrlSync={true} enablePersistence={true}>
<AppConfigProvider>
<ScarfTrackingInitializer />
<PreferencesProvider>
<FileContextProvider enableUrlSync={true} enablePersistence={true}>
<NavigationProvider>
<FilesModalProvider>
<ToolWorkflowProvider>
@ -67,6 +73,7 @@ export default function App() {
</NavigationProvider>
</FileContextProvider>
</PreferencesProvider>
</AppConfigProvider>
</ErrorBoundary>
</RainbowThemeProvider>
</Suspense>

View File

@ -6,7 +6,7 @@ import { useFileHandler } from '../../hooks/useFileHandler';
import { useFileState } from '../../contexts/FileContext';
import { useNavigationState, useNavigationActions } from '../../contexts/NavigationContext';
import { useViewer } from '../../contexts/ViewerContext';
import { useAppConfig } from '../../hooks/useAppConfig';
import { useAppConfig } from '../../contexts/AppConfigContext';
import './Workbench.css';
import TopControls from '../shared/TopControls';

View File

@ -13,7 +13,7 @@ import './quickAccessBar/QuickAccessBar.css';
import AllToolsNavButton from './AllToolsNavButton';
import ActiveToolButton from "./quickAccessBar/ActiveToolButton";
import AppConfigModal from './AppConfigModal';
import { useAppConfig } from '../../hooks/useAppConfig';
import { useAppConfig } from '../../contexts/AppConfigContext';
import {
isNavButtonActive,
getNavButtonStyle,

View File

@ -1,6 +1,6 @@
import React from 'react';
import { Stack, Text, Code, Group, Badge, Alert, Loader } from '@mantine/core';
import { useAppConfig } from '../../../../hooks/useAppConfig';
import { useAppConfig } from '../../../../contexts/AppConfigContext';
const Overview: React.FC = () => {
const { config, loading, error } = useAppConfig();

View File

@ -1,6 +1,6 @@
import { Stack, Button } from "@mantine/core";
import { CertSignParameters } from "../../../hooks/tools/certSign/useCertSignParameters";
import { useAppConfig } from "../../../hooks/useAppConfig";
import { useAppConfig } from "../../../contexts/AppConfigContext";
interface CertificateTypeSettingsProps {
parameters: CertSignParameters;

View File

@ -1,4 +1,4 @@
import { useAppConfig } from '../hooks/useAppConfig';
import { useAppConfig } from '../contexts/AppConfigContext';
// Get base URL from app config with fallback
export const getBaseUrl = (): string => {

View File

@ -1,4 +1,4 @@
import { useState, useEffect } from 'react';
import React, { createContext, useContext, useState, useEffect } from 'react';
export interface AppConfig {
baseUrl?: string;
@ -28,17 +28,21 @@ export interface AppConfig {
error?: string;
}
interface UseAppConfigReturn {
interface AppConfigContextValue {
config: AppConfig | null;
loading: boolean;
error: string | null;
refetch: () => Promise<void>;
}
// Create context
const AppConfigContext = createContext<AppConfigContextValue | undefined>(undefined);
/**
* Custom hook to fetch and manage application configuration
* Provider component that fetches and provides app configuration
* Should be placed at the top level of the app, before any components that need config
*/
export function useAppConfig(): UseAppConfigReturn {
export const AppConfigProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [config, setConfig] = useState<AppConfig | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
@ -56,11 +60,11 @@ export function useAppConfig(): UseAppConfigReturn {
const data: AppConfig = await response.json();
setConfig(data);
console.warn('Fetched app config:', data);
console.warn('[AppConfig] Fetched app config:', data);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
setError(errorMessage);
console.error('Failed to fetch app config:', err);
console.error('[AppConfig] Failed to fetch app config:', err);
} finally {
setLoading(false);
}
@ -70,11 +74,31 @@ export function useAppConfig(): UseAppConfigReturn {
fetchConfig();
}, []);
return {
const value: AppConfigContextValue = {
config,
loading,
error,
refetch: fetchConfig,
};
return (
<AppConfigContext.Provider value={value}>
{children}
</AppConfigContext.Provider>
);
};
/**
* Hook to access application configuration
* Must be used within AppConfigProvider
*/
export function useAppConfig(): AppConfigContextValue {
const context = useContext(AppConfigContext);
if (context === undefined) {
throw new Error('useAppConfig must be used within AppConfigProvider');
}
return context;
}

View File

@ -1,7 +1,7 @@
import { useEffect, useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { BASE_PATH } from '../constants/app';
import { useAppConfig } from './useAppConfig';
import { useAppConfig } from '../contexts/AppConfigContext';
declare global {
interface Window {

View File

@ -1,5 +1,5 @@
import { useEffect } from 'react';
import { useAppConfig } from './useAppConfig';
import { useAppConfig } from '../contexts/AppConfigContext';
import { useCookieConsent } from './useCookieConsent';
import { setScarfConfig, firePixel } from '../utils/scarfTracking';

View File

@ -6,7 +6,7 @@ import { useSidebarContext } from "../contexts/SidebarContext";
import { useDocumentMeta } from "../hooks/useDocumentMeta";
import { BASE_PATH, getBaseUrl } from "../constants/app";
import { useMediaQuery } from "@mantine/hooks";
import { useAppConfig } from "../hooks/useAppConfig";
import { useAppConfig } from "../contexts/AppConfigContext";
import AppsIcon from '@mui/icons-material/AppsRounded';
import ToolPanel from "../components/tools/ToolPanel";