refactor: deprecate driven sidebar

This commit is contained in:
EnixCoda 2021-05-09 23:16:39 +08:00
parent 11a4399ea0
commit 79644fba82
No known key found for this signature in database
GPG key ID: 0C1A07377913A1DD
5 changed files with 106 additions and 106 deletions

View file

@ -1,6 +1,7 @@
import { useConfigs } from 'containers/ConfigsContext'
import { platform } from 'platforms'
import * as React from 'react'
import { parseURLSearch, run } from 'utils/general'
import { useEffectOnSerializableUpdates } from 'utils/hooks/useEffectOnSerializableUpdates'
import { useLoadedContext } from 'utils/hooks/useLoadedContext'
import { useOnPJAXDone } from 'utils/hooks/usePJAX'
@ -14,8 +15,13 @@ export function RepoContextWrapper({ children }: React.PropsWithChildren<{}>) {
const partialMetaData = usePartialMetaData()
const defaultBranch = useDefaultBranch(partialMetaData)
const metaData = useMetaData(partialMetaData, defaultBranch)
const fetchingAccessToken = useSetAccessToken()
return <RepoContext.Provider value={metaData}>{metaData && children}</RepoContext.Provider>
return (
<RepoContext.Provider value={metaData}>
{metaData && !fetchingAccessToken && children}
</RepoContext.Provider>
)
}
function resolvePartialMetaData() {
@ -97,3 +103,38 @@ function useMetaData(
}, [partialMetaData, branchName, defaultBranchName])
return $metaData.value
}
function useSetAccessToken() {
const $running = useStateIO(() => Boolean(getCodeSearchParam()))
const configContext = useConfigs()
const { accessToken } = configContext.value
React.useEffect(() => {
run(async function () {
const code = getCodeSearchParam()
if (code && !accessToken) {
const accessToken = await getAccessTokenWithCode(code)
if (accessToken) configContext.onChange({ accessToken })
}
$running.onChange(false)
})
}, [])
return $running.value
}
function getCodeSearchParam() {
return parseURLSearch().get('code')
}
async function getAccessTokenWithCode(code: string) {
const accessToken = await platform.setOAuth(code)
if (!accessToken) alert(`Gitako: The OAuth token may have expired, please try again.`)
const search = parseURLSearch()
search.delete('code')
window.history.replaceState(
{},
'removed search param',
window.location.pathname.replace(window.location.search, search.toString()),
)
return accessToken
}

View file

@ -5,30 +5,32 @@ import { Portal } from 'components/Portal'
import { Resizable } from 'components/Resizable'
import { SettingsBar } from 'components/settings/SettingsBar'
import { ToggleShowButton } from 'components/ToggleShowButton'
import { useConfigs } from 'containers/ConfigsContext'
import { connect } from 'driver/connect'
import { SideBarCore } from 'driver/core'
import { ConnectorState, Props } from 'driver/core/SideBar'
import { ConfigsContextShape, useConfigs } from 'containers/ConfigsContext'
import { platform } from 'platforms'
import { useGitHubAttachCopyFileButton, useGitHubAttachCopySnippetButton } from 'platforms/GitHub'
import * as React from 'react'
import { cx } from 'utils/cx'
import * as DOMHelper from 'utils/DOMHelper'
import { parseURLSearch, run } from 'utils/general'
import { run } from 'utils/general'
import { useCatchNetworkError } from 'utils/hooks/useCatchNetworkError'
import { useLoadedContext } from 'utils/hooks/useLoadedContext'
import { loadWithPJAX, useOnPJAXDone, usePJAX } from 'utils/hooks/usePJAX'
import { useProgressBar } from 'utils/hooks/useProgressBar'
import { useStateIO } from 'utils/hooks/useStateIO'
import * as keyHelper from 'utils/keyHelper'
import { SideBarErrorContext } from './ErrorContext'
import { Icon } from './Icon'
import { IIFC } from './IIFC'
import { LoadingIndicator } from './LoadingIndicator'
import { SideBarStateContext } from './SideBarState'
import { SideBarState, SideBarStateContext, SideBarStateContextShape } from './SideBarState'
import { Theme } from './Theme'
const RawSideBar: React.FC<Props & ConnectorState> = function RawGitako(props) {
const { metaData, error, shouldShow, toggleShowSideBar } = props
export function SideBar(props: {
metaData: MetaData | null
configContext: ConfigsContextShape
stateContext: SideBarStateContextShape
}) {
const { metaData } = props
const state = useLoadedContext(SideBarStateContext).value
const configContext = useConfigs()
@ -55,30 +57,31 @@ const RawSideBar: React.FC<Props & ConnectorState> = function RawGitako(props) {
}
}, [hasMetaData])
React.useEffect(() => {
run(async function () {
if (!accessToken) {
const accessToken = await trySetUpAccessTokenWithCode()
if (accessToken) configContext.onChange({ accessToken })
}
})
const $shouldShow = useStateIO(false)
const shouldShow = $shouldShow.value
const setShouldShow = React.useCallback((shouldShow: boolean) => {
$shouldShow.onChange(shouldShow)
DOMHelper.setBodyIndent(shouldShow)
}, [])
React.useEffect(() => {
if (shouldShow) {
DOMHelper.focusFileExplorer() // TODO: verify if it works
}
}, [shouldShow])
const toggleShowSideBar = React.useCallback(() => {
$shouldShow.onChange(shouldShow => {
DOMHelper.setBodyIndent(!shouldShow)
return !shouldShow
})
React.useEffect(
function attachKeyDown() {
if (state === 'disabled' || !configContext.value.shortcut) return
function onKeyDown(e: KeyboardEvent) {
const keys = keyHelper.parseEvent(e)
if (keys === configContext.value.shortcut) {
toggleShowSideBar()
}
}
window.addEventListener('keydown', onKeyDown)
return () => window.removeEventListener('keydown', onKeyDown)
},
[toggleShowSideBar, state === 'disabled', configContext.value.shortcut],
)
const {
value: { intelligentToggle },
} = configContext
if (intelligentToggle !== null) {
configContext.onChange({ intelligentToggle: !shouldShow })
}
}, [])
useToggleSideBarWithKeyboard(state, configContext, toggleShowSideBar)
const intelligentToggle = configContext.value.intelligentToggle
// Hide sidebar when error due to auth but token is set #128
@ -86,19 +89,26 @@ const RawSideBar: React.FC<Props & ConnectorState> = function RawGitako(props) {
intelligentToggle === null && Boolean(state === 'error-due-to-auth' && accessToken)
React.useEffect(() => {
if (hideSidebarOnInvalidToken) {
props.setShouldShow(false)
setShouldShow(false)
} else {
const shouldShow = intelligentToggle === null ? platform.shouldShow() : intelligentToggle
props.setShouldShow(shouldShow)
setShouldShow(shouldShow)
}
}, [intelligentToggle, hideSidebarOnInvalidToken, metaData])
const error = useLoadedContext(SideBarErrorContext).value
React.useEffect(() => {
if (error) {
$shouldShow.onChange(false)
}
}, [error])
const updateSideBarVisibility = React.useCallback(
function updateSideBarVisibility() {
if (hideSidebarOnInvalidToken) {
props.setShouldShow(false)
setShouldShow(false)
} else if (intelligentToggle === null) {
props.setShouldShow(platform.shouldShow())
setShouldShow(platform.shouldShow())
}
},
[metaData?.branchName, intelligentToggle, hideSidebarOnInvalidToken],
@ -169,22 +179,24 @@ const RawSideBar: React.FC<Props & ConnectorState> = function RawGitako(props) {
)
}
RawSideBar.defaultProps = {
shouldShow: false,
}
function useToggleSideBarWithKeyboard(
state: SideBarState,
configContext: ConfigsContextShape,
toggleShowSideBar: () => void,
) {
React.useEffect(
function attachKeyDown() {
if (state === 'disabled' || !configContext.value.shortcut) return
export const SideBar = connect(SideBarCore)(RawSideBar)
async function trySetUpAccessTokenWithCode() {
const search = parseURLSearch()
if ('code' in search) {
const accessToken = await platform.setOAuth(search.code)
if (!accessToken) alert(`Gitako: The OAuth token has expired, please try again.`)
window.history.replaceState(
{},
'removed search param',
window.location.pathname.replace(window.location.search, ''),
)
return accessToken
}
function onKeyDown(e: KeyboardEvent) {
const keys = keyHelper.parseEvent(e)
if (keys === configContext.value.shortcut) {
toggleShowSideBar()
}
}
window.addEventListener('keydown', onKeyDown)
return () => window.removeEventListener('keydown', onKeyDown)
},
[toggleShowSideBar, state === 'disabled', configContext.value.shortcut],
)
}

View file

@ -5,7 +5,7 @@ import { useDebounce, useWindowSize } from 'react-use'
import { Icon } from './Icon'
type Props = {
error?: string
error?: string | null
} & Pick<React.HTMLAttributes<HTMLButtonElement>, 'onClick'>
export function ToggleShowButton({ error, onClick }: Props) {

View file

@ -1,50 +0,0 @@
import { SideBarStateContextShape } from 'components/SideBarState'
import { ConfigsContextShape } from 'containers/ConfigsContext'
import { GetCreatedMethod, MethodCreator } from 'driver/connect'
import * as DOMHelper from 'utils/DOMHelper'
export type Props = {
// meta data for the repository
metaData: MetaData | null
configContext: ConfigsContextShape
stateContext: SideBarStateContextShape
}
export type ConnectorState = {
// error message
error?: string
// whether Gitako side bar should be shown
shouldShow: boolean
} & {
setShouldShow: GetCreatedMethod<typeof setShouldShow>
toggleShowSideBar: GetCreatedMethod<typeof toggleShowSideBar>
}
type BoundMethodCreator<Args extends any[] = []> = MethodCreator<Props, ConnectorState, Args>
export const toggleShowSideBar: BoundMethodCreator = dispatch => () => {
const {
state: { shouldShow },
props: { configContext },
} = dispatch.get()
dispatch.call(setShouldShow, !shouldShow)
const {
value: { intelligentToggle },
} = configContext
if (intelligentToggle !== null) {
configContext.onChange({ intelligentToggle: !shouldShow })
}
}
export const setShouldShow: BoundMethodCreator<
[ConnectorState['shouldShow']]
> = dispatch => shouldShow => {
dispatch.set({ shouldShow }, shouldShow ? DOMHelper.focusFileExplorer : undefined)
DOMHelper.setBodyIndent(shouldShow)
}
export const setError: BoundMethodCreator<[ConnectorState['error']]> = dispatch => error => {
dispatch.set({ error })
dispatch.call(setShouldShow, false)
}

View file

@ -4,8 +4,5 @@ import {
ConnectorState as FileExplorerConnectorState,
Props as FileExplorerProps,
} from './FileExplorer'
import * as SideBar from './SideBar'
import { ConnectorState as SideBarConnectorState, Props as SideBarProps } from './SideBar'
export const FileExplorerCore: Sources<FileExplorerProps, FileExplorerConnectorState> = FileExplorer
export const SideBarCore: Sources<SideBarProps, SideBarConnectorState> = SideBar