diff --git a/server/api/github.ts b/server/api/github.ts index c29e9c1..559eebf 100644 --- a/server/api/github.ts +++ b/server/api/github.ts @@ -19,7 +19,7 @@ async function oauth(code: string) { }) const body = await res.json() - const { access_token: accessToken, scope, error_description: errorDescription } = body + const { accessToken, scope, error_description: errorDescription } = body if (errorDescription) { throw new Error(errorDescription) } else if (scope !== 'repo' || !accessToken || !(typeof accessToken === 'string')) { diff --git a/src/components/FileExplorer.tsx b/src/components/FileExplorer.tsx index faedc5f..b2311c7 100644 --- a/src/components/FileExplorer.tsx +++ b/src/components/FileExplorer.tsx @@ -37,7 +37,7 @@ const RawFileExplorer: React.FC = function RawFileExplor React.useEffect(() => { const { setUpTree, treeRoot, metaData } = props setUpTree({ treeRoot, metaData, config }) - }, [setUpTree, treeRoot, config.compressSingletonFolder, config.access_token]) + }, [setUpTree, treeRoot, config.compressSingletonFolder, config.accessToken]) React.useEffect(() => { if (visibleNodes?.focusedNode) focusFileExplorer() diff --git a/src/components/SideBar.tsx b/src/components/SideBar.tsx index 87165e3..9aa21ca 100644 --- a/src/components/SideBar.tsx +++ b/src/components/SideBar.tsx @@ -27,7 +27,7 @@ import { Theme } from './Theme' const RawGitako: React.FC = function RawGitako(props) { const configContext = useConfigs() - const accessToken = props.configContext.val.access_token + const accessToken = props.configContext.val.accessToken const [baseSize] = React.useState(() => configContext.val.sideBarWidth) const { shrinkGitHubHeader } = configContext.val @@ -52,8 +52,8 @@ const RawGitako: React.FC = function RawGitako(props) { const { init } = props ;(async function () { if (!accessToken) { - const accessToken = await trySetUpAccessTokenWithCode() - configContext.set({ access_token: accessToken || undefined }) + const accessToken = (await trySetUpAccessTokenWithCode()) || undefined + configContext.set({ accessToken }) } init() })() diff --git a/src/components/settings/AccessTokenSettings.tsx b/src/components/settings/AccessTokenSettings.tsx index 4c56dbb..8bb40dc 100644 --- a/src/components/settings/AccessTokenSettings.tsx +++ b/src/components/settings/AccessTokenSettings.tsx @@ -14,7 +14,7 @@ type Props = {} export function AccessTokenSettings(props: React.PropsWithChildren) { const configContext = useConfigs() - const hasAccessToken = Boolean(configContext.val.access_token) + const hasAccessToken = Boolean(configContext.val.accessToken) const useAccessToken = useStates('') const useAccessTokenHint = useStates('') const focusInput = useStates(false) @@ -25,7 +25,7 @@ export function AccessTokenSettings(props: React.PropsWithChildren) { React.useEffect(() => { // clear input when access token updates useAccessToken.set('') - }, [configContext.val.access_token]) + }, [configContext.val.accessToken]) const onInputAccessToken = React.useCallback( ({ currentTarget: { value } }: React.FormEvent) => { @@ -44,7 +44,7 @@ export function AccessTokenSettings(props: React.PropsWithChildren) { const saveToken = React.useCallback( async (hint?: typeof useAccessTokenHint.val) => { if (accessToken) { - configContext.set({ access_token: accessToken }) + configContext.set({ accessToken }) useAccessToken.set('') useAccessTokenHint.set( hint || ( @@ -79,7 +79,7 @@ export function AccessTokenSettings(props: React.PropsWithChildren) { {hasAccessToken ? (
Your token has been saved. - +
) : (
diff --git a/src/driver/core/FileExplorer.ts b/src/driver/core/FileExplorer.ts index cebb9fa..a28f651 100644 --- a/src/driver/core/FileExplorer.ts +++ b/src/driver/core/FileExplorer.ts @@ -45,9 +45,9 @@ let visibleNodesGenerator: VisibleNodesGenerator type BoundMethodCreator = MethodCreator -export const setUpTree: BoundMethodCreator<[ - Pick & { config: Config }, -]> = dispatch => async ({ treeRoot, metaData, config }) => { +export const setUpTree: BoundMethodCreator< + [Pick & { config: Config }] +> = dispatch => async ({ treeRoot, metaData, config }) => { if (!treeRoot) return dispatch.set({ state: 'rendering' }) @@ -57,7 +57,7 @@ export const setUpTree: BoundMethodCreator<[ root: treeRoot, compress: compressSingletonFolder, async getTreeData(path) { - const { root } = await platform.getTreeData(metaData, path, false, config.access_token) + const { root } = await platform.getTreeData(metaData, path, false, config.accessToken) return root }, }) @@ -205,12 +205,14 @@ export const setExpand: BoundMethodCreator<[TreeNode, boolean]> = dispatch => as dispatch.call(focusNode, node) } -export const toggleNodeExpansion: BoundMethodCreator<[ - TreeNode, - { - recursive?: boolean - }, -]> = dispatch => async (node, { recursive = false }) => { +export const toggleNodeExpansion: BoundMethodCreator< + [ + TreeNode, + { + recursive?: boolean + }, + ] +> = dispatch => async (node, { recursive = false }) => { visibleNodesGenerator.focusNode(node) await visibleNodesGenerator.toggleExpand(node, recursive) } @@ -221,10 +223,9 @@ export const focusNode: BoundMethodCreator<[TreeNode | null]> = dispatch => ( visibleNodesGenerator.focusNode(node) } -export const onNodeClick: BoundMethodCreator<[ - React.MouseEvent, - TreeNode, -]> = dispatch => (event, node) => { +export const onNodeClick: BoundMethodCreator< + [React.MouseEvent, TreeNode] +> = dispatch => (event, node) => { const preventDefault = !(node.type === 'blob' && node.url?.includes('#')) if (preventDefault) event.preventDefault() diff --git a/src/driver/core/SideBar.ts b/src/driver/core/SideBar.ts index bd98e77..aec4513 100644 --- a/src/driver/core/SideBar.ts +++ b/src/driver/core/SideBar.ts @@ -64,7 +64,7 @@ export const init: BoundMethodCreator = dispatch => async () => { const { props: { configContext }, } = dispatch.get() - const { access_token: accessToken } = configContext.val + const { accessToken } = configContext.val if (!metaData.userName || !metaData.repoName) return const guessDefaultBranch = 'master' @@ -152,7 +152,7 @@ export const handleError: BoundMethodCreator<[Error]> = dispatch => async err => dispatch.set({ errorDueToAuth: true }) } else if (err.message === errors.CONNECTION_BLOCKED) { const { props } = dispatch.get() - if (props.configContext.val.access_token) { + if (props.configContext.val.accessToken) { dispatch.call(setError, `Cannot connect to ${platformName}.`) } else { dispatch.set({ errorDueToAuth: true }) @@ -181,9 +181,9 @@ export const toggleShowSideBar: BoundMethodCreator = dispatch => () => { } } -export const setShouldShow: BoundMethodCreator<[ - ConnectorState['shouldShow'], -]> = dispatch => shouldShow => { +export const setShouldShow: BoundMethodCreator< + [ConnectorState['shouldShow']] +> = dispatch => shouldShow => { dispatch.set({ shouldShow }, shouldShow ? DOMHelper.focusFileExplorer : undefined) DOMHelper.setBodyIndent(shouldShow) } diff --git a/src/utils/configHelper.ts b/src/utils/configHelper.ts index e587dae..c6cb4b0 100644 --- a/src/utils/configHelper.ts +++ b/src/utils/configHelper.ts @@ -3,7 +3,7 @@ import * as storageHelper from 'utils/storageHelper' export type Config = { sideBarWidth: number shortcut: string | undefined - access_token: string | undefined + accessToken: string | undefined compressSingletonFolder: boolean copyFileButton: boolean copySnippetButton: boolean @@ -18,7 +18,7 @@ export type Config = { export enum configKeys { sideBarWidth = 'sideBarWidth', shortcut = 'shortcut', - accessToken = 'access_token', + accessToken = 'accessToken', compressSingletonFolder = 'compressSingletonFolder', copyFileButton = 'copyFileButton', copySnippetButton = 'copySnippetButton', @@ -33,7 +33,7 @@ export enum configKeys { const defaultConfigs: Config = { sideBarWidth: 260, shortcut: undefined, - access_token: undefined, + accessToken: undefined, compressSingletonFolder: true, copyFileButton: true, copySnippetButton: true, @@ -55,6 +55,8 @@ function applyDefaultConfigs(configs: Partial) { }, {} as Config) } +type VersionedConfig = Record & { configVersion: string } + type Storage = { // save root level `configVersion` for easier future migrating [key in 'configVersion' | string]: string @@ -73,7 +75,7 @@ async function migrateConfig() { { version: '1.0.1', async migrate(version) { - const config: any | void = await storageHelper.get([ + const config: any | void = await storageHelper.get([ 'configVersion', 'sideBarWidth', 'shortcut', @@ -92,7 +94,7 @@ async function migrateConfig() { { version: '1.3.4', async migrate(version) { - const config: any | void = await storageHelper.get([ + const config: any | void = await storageHelper.get & Storage>([ 'configVersion', 'platform_undefined', // this was a mistake :( 'platform_GitHub', @@ -112,6 +114,42 @@ async function migrateConfig() { } }, }, + { + version: '2.6.0', + async migrate(version) { + type LegacySiteConfig = { + access_token?: string + } + type MigratedSiteConfig = { + accessToken?: string + } + + const config = await storageHelper.get & Storage>() + if (config && config.configVersion < version) { + const { configVersion, ...restConfig } = config + for (const key of Object.keys(restConfig)) { + if ( + typeof restConfig[key] === 'object' && + restConfig[key] && + 'access_token' in restConfig[key] + ) { + const config: LegacySiteConfig = restConfig[key] + const { access_token: accessToken, ...legacy } = config + const migrated: MigratedSiteConfig = { + ...legacy, + accessToken, + } + await storageHelper.set({ + [key]: migrated, + }) + } + } + await storageHelper.set({ + configVersion: version, + }) + } + }, + }, ] for (const { version, migrate } of migrations) { @@ -129,7 +167,7 @@ const prepareConfig = new Promise(async resolve => { export async function get(): Promise { await prepareConfig const config = await storageHelper.get>([platformStorageKey]) - return applyDefaultConfigs((config && config[platformStorageKey]) || {}) + return applyDefaultConfigs(config?.[platformStorageKey] || {}) } export async function set(config: Config) { diff --git a/src/utils/storageHelper.ts b/src/utils/storageHelper.ts index 5357034..455907a 100644 --- a/src/utils/storageHelper.ts +++ b/src/utils/storageHelper.ts @@ -4,7 +4,7 @@ export async function get< T extends { [key: string]: any } ->(mapping: string | string[] | null = null): Promise { +>(mapping: string | string[] | null = null): Promise { try { return (await localStorage.get(mapping || undefined)) as T } catch (err) {}