mirror of
https://github.com/PeWu/topola-viewer.git
synced 2026-07-17 17:21:48 +00:00
Move WikiTree and Google Drive code out of app.tsx
This commit is contained in:
60
src/app.tsx
60
src/app.tsx
@@ -1,6 +1,14 @@
|
|||||||
import queryString from 'query-string';
|
import queryString from 'query-string';
|
||||||
import {useMemo} from 'react';
|
import {useMemo} from 'react';
|
||||||
import {Navigate, Route, Routes, useLocation} from 'react-router';
|
import {Navigate, Route, Routes, useLocation} from 'react-router';
|
||||||
|
import {
|
||||||
|
GOOGLE_DRIVE_REDIRECT_KEYS,
|
||||||
|
handleGoogleDriveRedirect,
|
||||||
|
} from './datasource/google_drive';
|
||||||
|
import {
|
||||||
|
handleWikiTreeRedirect,
|
||||||
|
WIKITREE_REDIRECT_KEYS,
|
||||||
|
} from './datasource/wikitree';
|
||||||
import {IntroPage} from './pages/intro_page';
|
import {IntroPage} from './pages/intro_page';
|
||||||
import {ViewPage} from './pages/view_page';
|
import {ViewPage} from './pages/view_page';
|
||||||
import {getStaticUrl} from './util/url_args';
|
import {getStaticUrl} from './util/url_args';
|
||||||
@@ -28,43 +36,31 @@ export function App() {
|
|||||||
let paramsModified = false;
|
let paramsModified = false;
|
||||||
|
|
||||||
// 1. Handle Google Drive "Open with" action
|
// 1. Handle Google Drive "Open with" action
|
||||||
const stateParam = mergedParams.state;
|
const gdResult = handleGoogleDriveRedirect(mergedParams);
|
||||||
if (typeof stateParam === 'string') {
|
if (gdResult) {
|
||||||
try {
|
redirectPath = gdResult.redirectPath;
|
||||||
const parsedState = JSON.parse(stateParam);
|
mergedParams.source = 'google-drive';
|
||||||
if (
|
mergedParams.fileId = gdResult.fileId;
|
||||||
parsedState &&
|
delete mergedParams.state;
|
||||||
parsedState.action === 'open' &&
|
|
||||||
Array.isArray(parsedState.ids) &&
|
|
||||||
parsedState.ids.length > 0
|
|
||||||
) {
|
|
||||||
const fileId = parsedState.ids[0];
|
|
||||||
redirectPath = '/view';
|
|
||||||
mergedParams.source = 'google-drive';
|
|
||||||
mergedParams.fileId = fileId;
|
|
||||||
delete mergedParams.state;
|
|
||||||
paramsModified = true;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// Silently catch JSON parsing errors for state parameters not meant for us
|
|
||||||
console.warn(
|
|
||||||
'Google Drive state query parameter JSON parsing failed or action mismatch:',
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Handle WikiTree authcode presence
|
|
||||||
if (windowSearch.authcode) {
|
|
||||||
redirectPath = redirectPath || location.pathname;
|
|
||||||
paramsModified = true;
|
paramsModified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paramsModified || windowSearch.state || windowSearch.authcode) {
|
// 2. Handle WikiTree authcode presence
|
||||||
|
const wtResult = handleWikiTreeRedirect(windowSearch, location.pathname);
|
||||||
|
if (wtResult) {
|
||||||
|
redirectPath = redirectPath || wtResult.redirectPath;
|
||||||
|
paramsModified = paramsModified || wtResult.paramsModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasRedirectKeys =
|
||||||
|
GOOGLE_DRIVE_REDIRECT_KEYS.some((k) => windowSearch[k] !== undefined) ||
|
||||||
|
WIKITREE_REDIRECT_KEYS.some((k) => windowSearch[k] !== undefined);
|
||||||
|
|
||||||
|
if (paramsModified || hasRedirectKeys) {
|
||||||
// Strip external state / authcode parameters from window.location.search to prevent redirect loops.
|
// Strip external state / authcode parameters from window.location.search to prevent redirect loops.
|
||||||
const cleanWindowSearch = {...windowSearch};
|
const cleanWindowSearch = {...windowSearch};
|
||||||
delete cleanWindowSearch.state;
|
GOOGLE_DRIVE_REDIRECT_KEYS.forEach((k) => delete cleanWindowSearch[k]);
|
||||||
delete cleanWindowSearch.authcode;
|
WIKITREE_REDIRECT_KEYS.forEach((k) => delete cleanWindowSearch[k]);
|
||||||
|
|
||||||
const cleanWindowSearchStr = queryString.stringify(cleanWindowSearch);
|
const cleanWindowSearchStr = queryString.stringify(cleanWindowSearch);
|
||||||
const newUrl =
|
const newUrl =
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type {ParsedQuery} from 'query-string';
|
||||||
import {TopolaData} from '../util/gedcom_util';
|
import {TopolaData} from '../util/gedcom_util';
|
||||||
import {DataSource, DataSourceEnum, SourceSelection} from './data_source';
|
import {DataSource, DataSourceEnum, SourceSelection} from './data_source';
|
||||||
import {
|
import {
|
||||||
@@ -92,3 +93,34 @@ export class GoogleDriveDataSource implements DataSource<GoogleDriveSourceSpec>
|
|||||||
return loadAndPrepareFile(blob, cacheKey, onProgress);
|
return loadAndPrepareFile(blob, cacheKey, onProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GOOGLE_DRIVE_REDIRECT_KEYS = ['state'];
|
||||||
|
|
||||||
|
export function handleGoogleDriveRedirect(
|
||||||
|
mergedParams: ParsedQuery,
|
||||||
|
): {redirectPath: string; fileId: string} | null {
|
||||||
|
const stateParam = mergedParams.state;
|
||||||
|
if (typeof stateParam === 'string') {
|
||||||
|
try {
|
||||||
|
const parsedState = JSON.parse(stateParam);
|
||||||
|
if (
|
||||||
|
parsedState &&
|
||||||
|
parsedState.action === 'open' &&
|
||||||
|
Array.isArray(parsedState.ids) &&
|
||||||
|
parsedState.ids.length > 0
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
redirectPath: '/view',
|
||||||
|
fileId: parsedState.ids[0],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Silently catch JSON parsing errors for state parameters not meant for us
|
||||||
|
console.warn(
|
||||||
|
'Google Drive state query parameter JSON parsing failed or action mismatch:',
|
||||||
|
err,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type {ParsedQuery} from 'query-string';
|
||||||
import {IntlShape} from 'react-intl';
|
import {IntlShape} from 'react-intl';
|
||||||
import {analyticsEvent} from '../util/analytics';
|
import {analyticsEvent} from '../util/analytics';
|
||||||
import {TopolaError} from '../util/error';
|
import {TopolaError} from '../util/error';
|
||||||
@@ -109,3 +110,18 @@ export class WikiTreeDataSource implements DataSource<WikiTreeSourceSpec> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const WIKITREE_REDIRECT_KEYS = ['authcode'];
|
||||||
|
|
||||||
|
export function handleWikiTreeRedirect(
|
||||||
|
windowSearch: ParsedQuery,
|
||||||
|
currentPathname: string,
|
||||||
|
): {redirectPath: string; paramsModified: boolean} | null {
|
||||||
|
if (windowSearch.authcode) {
|
||||||
|
return {
|
||||||
|
redirectPath: currentPathname,
|
||||||
|
paramsModified: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user