diff --git a/docs/APP_REFACTORING_DESIGN.md b/docs/APP_REFACTORING_DESIGN.md index 5b4dc92..00c4cc3 100644 --- a/docs/APP_REFACTORING_DESIGN.md +++ b/docs/APP_REFACTORING_DESIGN.md @@ -100,7 +100,7 @@ We will gradually eliminate React state variables in `src/app.tsx` and derive th * [x] **Step 3.4:** Extract `config` state. Parse display settings on render using `argsToConfig` helper. Remove state. In `ViewPage`, run `updateChartWithConfig(config, data)` synchronously during the render pass (e.g. in the `useMemo` that derives query parameters/config) to update the in-memory chart data before it is rendered by the `` child component. Run E2E and visual tests to verify no rendering regressions occurred. #### Phase 4: Structural Page Nesting -* [ ] **Step 4.1:** Create `src/hooks/use_google_auth.ts` to manage Google Drive authentication token updates. Remove `hasGoogleToken` state from `src/app.tsx`. +* [x] **Step 4.1:** Create `src/hooks/use_google_auth.ts` to manage Google Drive authentication token updates. Remove `hasGoogleToken` state from `src/app.tsx`. * [ ] **Step 4.2:** Create `src/pages/view_page.tsx` containing layout rendering (`renderMainArea`), asynchronous data loaders, view state management, `revokeObjectUrls` cleanups, and `` error fallback state and rendering. * [ ] **Step 4.3:** Create `src/pages/intro_page.tsx` rendering the landing screen and its own local header. * [ ] **Step 4.4:** Refactor `src/app.tsx` to serve as a pure routing switch routing to `` or ``. In `App`, handle Google Drive redirection synchronously during the render pass by returning a `` element (preventing render flashing), and ensure the redirection parser checks both the router `location.search` and the external `window.location.search` to handle HashRouter query structure robustly. Once external parameters (like `state` or `authcode`) are detected, they must be stripped from `window.location.search` using `window.history.replaceState` to prevent redirection loops on page refresh. Remove all layout state logic from the root file, including moving the `useWebMcpBridge` hook invocation into ``. Run final verification scripts (`npm run check:all`). diff --git a/src/app.tsx b/src/app.tsx index b3f167e..fb60ec0 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -43,6 +43,7 @@ import { WikiTreeSourceSpec, } from './datasource/wikitree'; import {DonatsoChart} from './donatso-chart'; +import {useGoogleAuth} from './hooks/use_google_auth'; import {useWebMcpBridge} from './hooks/use_webmcp_bridge'; import {Intro} from './intro'; import {GoogleAuthModal} from './menu/google_auth_modal'; @@ -90,10 +91,8 @@ export function App() { const [showAuthModal, setShowAuthModal] = useState(false); /** Stores the file ID that failed to load from Google Drive due to authorization errors. */ const [failedFileId, setFailedFileId] = useState(); - /** Tracks whether the user has a valid cached Google Drive OAuth access token. */ - const [hasGoogleToken, setHasGoogleToken] = useState( - () => !!googleDriveService.getAccessToken(), - ); + /** Tracks whether the user has a valid cached Google Drive OAuth access token and provides a state setter. */ + const {hasGoogleToken, setHasGoogleToken} = useGoogleAuth(); const intl = useIntl(); const navigate = useNavigate(); diff --git a/src/hooks/use_google_auth.ts b/src/hooks/use_google_auth.ts new file mode 100644 index 0000000..19674de --- /dev/null +++ b/src/hooks/use_google_auth.ts @@ -0,0 +1,19 @@ +import {useState} from 'react'; +import {googleDriveService} from '../datasource/google_drive_service'; + +/** + * Custom React hook to manage and track the state of Google Drive OAuth2 credentials. + */ +export function useGoogleAuth() { + /** Tracks whether the user has a valid cached Google Drive OAuth access token. */ + const [hasGoogleToken, setHasGoogleToken] = useState( + () => !!googleDriveService.getAccessToken(), + ); + + return { + /** Tracks whether the user has a valid cached Google Drive OAuth access token. */ + hasGoogleToken, + /** Function to update the token presence state in React. */ + setHasGoogleToken, + }; +}