mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
lint: resolve lint issues
This commit is contained in:
parent
850ea5a64a
commit
77d9db6043
24 changed files with 101 additions and 84 deletions
|
|
@ -96,6 +96,9 @@
|
|||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
|
|
@ -105,7 +108,10 @@
|
|||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended"
|
||||
]
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/ban-types": "off"
|
||||
}
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "^18.0.9",
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ export function Clippy({ codeSnippetElement }: Props) {
|
|||
React.useEffect(() => {
|
||||
const element = elementRef.current
|
||||
if (element) {
|
||||
function onClippyClick() {
|
||||
const onClippyClick = () =>
|
||||
setState(copyElementContent(codeSnippetElement) ? 'success' : 'fail')
|
||||
}
|
||||
|
||||
element.addEventListener('click', onClippyClick)
|
||||
return () => element.removeEventListener('click', onClippyClick)
|
||||
}
|
||||
}, [])
|
||||
}, [codeSnippetElement])
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import * as React from 'react'
|
|||
import { Icon } from '../Icon'
|
||||
|
||||
export function DiffStatText({
|
||||
diff: { status, changes, additions, deletions },
|
||||
diff: { status, additions, deletions },
|
||||
}: {
|
||||
diff: Required<TreeNode>['diff']
|
||||
}) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export function ListView({
|
|||
const goToCurrentItem = React.useCallback(() => {
|
||||
const targetPath = platform.getCurrentPath(metaData.branchName)
|
||||
if (targetPath) expandTo(targetPath)
|
||||
}, [metaData.branchName])
|
||||
}, [metaData.branchName, expandTo])
|
||||
|
||||
useOnLocationChange(goToCurrentItem)
|
||||
useOnPJAXDone(goToCurrentItem)
|
||||
|
|
@ -52,7 +52,7 @@ export function ListView({
|
|||
const { compactFileTree } = useConfigs().value
|
||||
|
||||
return (
|
||||
<FixedSizeList
|
||||
<FixedSizeList<NodeRendererContext>
|
||||
ref={listRef}
|
||||
itemKey={(index, { visibleNodes }) => visibleNodes?.nodes[index]?.path}
|
||||
itemData={nodeRendererContext}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ export function Node({
|
|||
style={{ ...style, paddingLeft: `${10 + (compact ? 10 : 20) * depth}px` }}
|
||||
title={node.path}
|
||||
target={node.type === 'commit' ? '_blank' : undefined}
|
||||
rel="noopener noreferrer"
|
||||
{...platform.delegatePJAXProps?.({ node })}
|
||||
>
|
||||
<div className={'node-item-label'}>
|
||||
|
|
@ -71,7 +72,7 @@ const NodeItemIcon = React.memo(function NodeItemIcon({
|
|||
|
||||
const src = React.useMemo(
|
||||
() => (node.type === 'tree' ? getFolderIconURL(node, open) : getFileIconURL(node)),
|
||||
[open],
|
||||
[node, open],
|
||||
)
|
||||
|
||||
if (icons === 'native') return <Icon type={getIconType(node)} />
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export function useNodeRenderers(allRenderers: (NodeRenderer | null | undefined)
|
|||
? (node: TreeNode) =>
|
||||
renderers.map((render, i) => <React.Fragment key={i}>{render(node)}</React.Fragment>)
|
||||
: undefined
|
||||
}, allRenderers)
|
||||
}, allRenderers) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}
|
||||
|
||||
export function useRenderFileStatus() {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ export function useVisibleNodesGeneratorMethods(
|
|||
const goTo = useGoTo(visibleNodesGenerator, updateSearchKey, expandTo)
|
||||
const toggleExpansion = useToggleExpansion(visibleNodesGenerator)
|
||||
const focusNode = useFocusNode(visibleNodesGenerator)
|
||||
|
||||
// Only run when visibleNodesGenerator changes
|
||||
useEffect(() => {
|
||||
if (!visibleNodesGenerator) return
|
||||
|
||||
|
|
@ -26,7 +28,7 @@ export function useVisibleNodesGeneratorMethods(
|
|||
const targetPath = getCurrentPath()
|
||||
if (targetPath) goTo(targetPath)
|
||||
}
|
||||
}, [visibleNodesGenerator])
|
||||
}, [visibleNodesGenerator]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return {
|
||||
expandTo,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ export function useVisibleNodesGenerator(metaData: MetaData) {
|
|||
const accessToken = config.accessToken
|
||||
const setStateContext = useLoadedContext(SideBarStateContext).onChange
|
||||
|
||||
// Only run when metadata or accessToken changes
|
||||
useSequentialEffect(
|
||||
useCallback(
|
||||
checker => {
|
||||
|
|
@ -54,7 +55,7 @@ export function useVisibleNodesGenerator(metaData: MetaData) {
|
|||
setStateContext('tree-rendered')
|
||||
})
|
||||
},
|
||||
[metaData, accessToken],
|
||||
[metaData, accessToken], // eslint-disable-line react-hooks/exhaustive-deps
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -116,9 +116,9 @@ export function FileExplorer({ freeze, metaData }: Props) {
|
|||
)}
|
||||
</>
|
||||
)}
|
||||
<SizeObserver className={'files'}>
|
||||
{({ width = 0, height = 0 }) => (
|
||||
<div className={'magic-size-container'}>
|
||||
<SizeObserver<HTMLDivElement>>
|
||||
{({ width = 0, height = 0 }, ref) => (
|
||||
<div className={'files'} ref={ref}>
|
||||
<ListView
|
||||
height={height}
|
||||
width={width}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
import * as React from 'react'
|
||||
|
||||
// I tried to install `react-iifc` but that causes TS build errors for unknown reason
|
||||
// So here the duplicated code is
|
||||
|
||||
export function IIFC({ children }: { children(): React.ReactNode }) {
|
||||
return <>{children()}</>
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ export function SelectInput<T>({
|
|||
onChange={e => {
|
||||
const key = e.target.value
|
||||
const option = options.find(option => option.key === key)
|
||||
onChange(option!?.value)
|
||||
if (option) onChange(option.value)
|
||||
}}
|
||||
value={options.find(option => option.value === value)?.key}
|
||||
{...selectProps}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,8 @@ export function SideBar() {
|
|||
const accessToken = configContext.value.accessToken || ''
|
||||
const [baseSize] = React.useState(() => configContext.value.sideBarWidth)
|
||||
|
||||
const $showSettings = useStateIO(false)
|
||||
const showSettings = $showSettings.value
|
||||
const toggleShowSettings = React.useCallback(() => $showSettings.onChange(show => !show), [])
|
||||
const [showSettings, setShowSettings] = React.useState(false)
|
||||
const toggleShowSettings = React.useCallback(() => setShowSettings(show => !show), [])
|
||||
|
||||
const $logoContainerElement = useStateIO<HTMLElement | null>(null)
|
||||
|
||||
|
|
@ -41,12 +40,12 @@ export function SideBar() {
|
|||
React.useEffect(() => {
|
||||
if (hasMetaData) {
|
||||
DOMHelper.markGitakoReadyState(true)
|
||||
$showSettings.onChange(false)
|
||||
setShowSettings(false)
|
||||
$logoContainerElement.onChange(DOMHelper.insertLogoMountPoint())
|
||||
} else {
|
||||
DOMHelper.markGitakoReadyState(false)
|
||||
}
|
||||
}, [hasMetaData])
|
||||
}, [hasMetaData]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
React.useEffect(() => {
|
||||
if (detectBrowser() === 'Safari') DOMHelper.markGitakoSafariFlag()
|
||||
|
|
@ -79,7 +78,7 @@ export function SideBar() {
|
|||
if (intelligentToggle !== null) {
|
||||
configContext.onChange({ intelligentToggle: shouldShow })
|
||||
}
|
||||
}, [shouldShow, intelligentToggle])
|
||||
}, [shouldShow, intelligentToggle]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const error = useLoadedContext(SideBarErrorContext).value
|
||||
// Lock shouldShow on error
|
||||
|
|
@ -87,25 +86,25 @@ export function SideBar() {
|
|||
if (error && shouldShow) {
|
||||
$shouldShow.onChange(false)
|
||||
}
|
||||
}, [error])
|
||||
}, [error]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const setShowSideBar = React.useCallback(
|
||||
(show: typeof $shouldShow.value) => {
|
||||
(show: boolean) => {
|
||||
if (!error) $shouldShow.onChange(show)
|
||||
},
|
||||
[error],
|
||||
[error], // eslint-disable-line react-hooks/exhaustive-deps
|
||||
)
|
||||
|
||||
const toggleShowSideBar = React.useCallback(() => {
|
||||
if (!error) $shouldShow.onChange(show => !show)
|
||||
}, [error])
|
||||
}, [error]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
useToggleSideBarWithKeyboard(state, configContext, toggleShowSideBar)
|
||||
|
||||
const updateSideBarVisibility = React.useCallback(() => {
|
||||
if (intelligentToggle === null && sidebarToggleMode === 'persistent') {
|
||||
setShowSideBar(platform.shouldShow())
|
||||
}
|
||||
}, [intelligentToggle, sidebarToggleMode])
|
||||
}, [intelligentToggle, sidebarToggleMode, setShowSideBar])
|
||||
|
||||
useOnPJAXDone(updateSideBarVisibility)
|
||||
|
||||
|
|
@ -120,7 +119,7 @@ export function SideBar() {
|
|||
if (hideSidebarOnInvalidToken) {
|
||||
setShowSideBar(false)
|
||||
}
|
||||
}, [hideSidebarOnInvalidToken])
|
||||
}, [hideSidebarOnInvalidToken, setShowSideBar])
|
||||
|
||||
return (
|
||||
<Theme>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export function SideBarBodyWrapper({
|
|||
|
||||
const heightForSafari = useConditionalHook(
|
||||
() => detectBrowser() === 'Safari',
|
||||
() => useWindowSize().height,
|
||||
() => useWindowSize().height, // eslint-disable-line react-hooks/rules-of-hooks
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -55,7 +55,10 @@ export function SideBarBodyWrapper({
|
|||
const bodyWrapperRef = React.useRef<HTMLDivElement | null>(null)
|
||||
useDebounce(() => configContext.onChange({ sideBarWidth: size }), 100, [size])
|
||||
|
||||
function apply(sizeVariableMountPoint: HTMLElement | undefined, size: number) {
|
||||
const applySizeToCSSVariables = React.useCallback(function apply(
|
||||
sizeVariableMountPoint: HTMLElement | undefined,
|
||||
size: number,
|
||||
) {
|
||||
if (sizeVariableMountPoint)
|
||||
setCSSVariable(
|
||||
'--gitako-width',
|
||||
|
|
@ -69,12 +72,13 @@ export function SideBarBodyWrapper({
|
|||
sizeVariableMountPoint ? undefined : `${size}px`,
|
||||
bodyWrapperRef.current,
|
||||
)
|
||||
}
|
||||
},
|
||||
[])
|
||||
|
||||
// Update size using useEffect would cause delay
|
||||
const onResize = React.useMemo(() => {
|
||||
let sizeToApply: number,
|
||||
applied = true
|
||||
let sizeToApply: number
|
||||
let applied = true
|
||||
return ([size]: number[]) => {
|
||||
// do NOT merge this with the above similar effect, side bar will jump otherwise
|
||||
sizeToApply = getSafeSize(size, width)
|
||||
|
|
@ -84,15 +88,15 @@ export function SideBarBodyWrapper({
|
|||
applied = false
|
||||
requestAnimationFrame(() => {
|
||||
applied = true
|
||||
apply(sizeVariableMountPoint, sizeToApply)
|
||||
applySizeToCSSVariables(sizeVariableMountPoint, sizeToApply)
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [width, sizeVariableMountPoint])
|
||||
}, [width, sizeVariableMountPoint, applySizeToCSSVariables])
|
||||
|
||||
React.useEffect(() => {
|
||||
apply(sizeVariableMountPoint, size)
|
||||
}, [sizeVariableMountPoint])
|
||||
applySizeToCSSVariables(sizeVariableMountPoint, size)
|
||||
}, [sizeVariableMountPoint, size, applySizeToCSSVariables])
|
||||
|
||||
const onMouseLeave = React.useCallback(
|
||||
<E extends HTMLElement>(e: React.MouseEvent<E>) => {
|
||||
|
|
@ -116,7 +120,7 @@ export function SideBarBodyWrapper({
|
|||
onResize={onResize}
|
||||
onResetSize={() => {
|
||||
setSize(defaultConfigs.sideBarWidth)
|
||||
apply(sizeVariableMountPoint, defaultConfigs.sideBarWidth)
|
||||
applySizeToCSSVariables(sizeVariableMountPoint, defaultConfigs.sideBarWidth)
|
||||
}}
|
||||
onResizeStateChange={state => {
|
||||
blockLeaveRef.current = state === 'resizing'
|
||||
|
|
|
|||
|
|
@ -33,7 +33,12 @@ export function SimpleToggleField<Key extends keyof Config>({ field, onChange }:
|
|||
<>
|
||||
{field.label}{' '}
|
||||
{field.wikiLink ? (
|
||||
<a href={field.wikiLink} title={field.tooltip} target={'_blank'}>
|
||||
<a
|
||||
href={field.wikiLink}
|
||||
title={field.tooltip}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
(?)
|
||||
</a>
|
||||
) : field.description ? (
|
||||
|
|
|
|||
|
|
@ -6,16 +6,12 @@ type Size = {
|
|||
height: number
|
||||
}
|
||||
|
||||
type Props = Override<
|
||||
React.HTMLAttributes<HTMLElement>,
|
||||
{
|
||||
type?: string | React.ComponentType
|
||||
children(size: Partial<Size>): React.ReactNode
|
||||
}
|
||||
>
|
||||
type Props<R extends Element> = {
|
||||
children(size: Partial<Size>, ref: React.MutableRefObject<R | null>): React.ReactNode
|
||||
}
|
||||
|
||||
export function SizeObserver({ type = 'div', children, ...rest }: Props) {
|
||||
const ref = React.useRef<any>()
|
||||
export function SizeObserver<R extends Element>({ children }: Props<R>) {
|
||||
const ref = React.useRef<R | null>(null)
|
||||
|
||||
const [size, setSize] = React.useState<Partial<Size>>({
|
||||
width: undefined,
|
||||
|
|
@ -42,7 +38,5 @@ export function SizeObserver({ type = 'div', children, ...rest }: Props) {
|
|||
}
|
||||
}, [])
|
||||
|
||||
const props: any = { ...rest, ref } // :)
|
||||
|
||||
return React.createElement(type, props, children(size))
|
||||
return <>{children(size, ref)}</>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export function ToggleShowButton({ error, className, onClick, onHover }: Props)
|
|||
if (ref.current) {
|
||||
ref.current.style.top = distance + 'px'
|
||||
}
|
||||
}, [height])
|
||||
}, [height]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// And this repositions on drag
|
||||
const { onPointerDown } = useResizeHandler(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import { fuzzyMode } from './fuzzyMode'
|
||||
|
||||
type TreeNodeSource = {
|
||||
[key: string]: true | TreeNodeSource
|
||||
}
|
||||
|
||||
function createTreeNode(source: TreeNodeSource, name: string = '', paths: string[] = []): TreeNode {
|
||||
function createTreeNode(source: TreeNodeSource, name = '', paths: string[] = []): TreeNode {
|
||||
const subPaths = paths.concat(name)
|
||||
return {
|
||||
name,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ function fuzzyMatch(input: string, sample: string) {
|
|||
}
|
||||
}
|
||||
|
||||
function fuzzyMatchIndexes(input: string, sample: string, shift: number = 0) {
|
||||
function fuzzyMatchIndexes(input: string, sample: string, shift = 0) {
|
||||
const indexes: number[] = []
|
||||
let i = 0,
|
||||
j = 0
|
||||
|
|
|
|||
|
|
@ -10,31 +10,28 @@ import { SettingsSection } from './SettingsSection'
|
|||
|
||||
const ACCESS_TOKEN_REGEXP = /^([0-9a-fA-F]+|gh[pousr]_[A-Za-z0-9_]+)$/
|
||||
|
||||
type Props = {}
|
||||
|
||||
export function AccessTokenSettings(props: React.PropsWithChildren<Props>) {
|
||||
export function AccessTokenSettings() {
|
||||
const configContext = useConfigs()
|
||||
const hasAccessToken = Boolean(configContext.value.accessToken)
|
||||
const $useAccessToken = useStateIO('')
|
||||
const [accessToken, setAccessToken] = React.useState('')
|
||||
const useAccessTokenHint = useStateIO<React.ReactNode>('')
|
||||
const focusInput = useStateIO(false)
|
||||
|
||||
const { value: accessTokenHint } = useAccessTokenHint
|
||||
const { value: accessToken } = $useAccessToken
|
||||
|
||||
React.useEffect(() => {
|
||||
// clear input when access token updates
|
||||
$useAccessToken.onChange('')
|
||||
setAccessToken('')
|
||||
}, [configContext.value.accessToken])
|
||||
|
||||
const onInputAccessToken = React.useCallback(
|
||||
({ currentTarget: { value } }: React.FormEvent<HTMLInputElement>) => {
|
||||
$useAccessToken.onChange(value)
|
||||
setAccessToken(value)
|
||||
useAccessTokenHint.onChange(
|
||||
ACCESS_TOKEN_REGEXP.test(value) ? '' : 'Gitako does not recognize the token.',
|
||||
)
|
||||
},
|
||||
[],
|
||||
[], // eslint-disable-line react-hooks/exhaustive-deps
|
||||
)
|
||||
|
||||
const saveToken = React.useCallback(
|
||||
|
|
@ -50,11 +47,11 @@ export function AccessTokenSettings(props: React.PropsWithChildren<Props>) {
|
|||
) => {
|
||||
if (accessToken) {
|
||||
configContext.onChange({ accessToken })
|
||||
$useAccessToken.onChange('')
|
||||
setAccessToken('')
|
||||
useAccessTokenHint.onChange(hint)
|
||||
}
|
||||
},
|
||||
[accessToken],
|
||||
[accessToken], // eslint-disable-line react-hooks/exhaustive-deps
|
||||
)
|
||||
|
||||
const onPressAccessToken = React.useCallback(
|
||||
|
|
@ -73,6 +70,7 @@ export function AccessTokenSettings(props: React.PropsWithChildren<Props>) {
|
|||
href={wikiLinks.createAccessToken}
|
||||
title="A token is required to access private repositories or bypass API rate limits"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
(?)
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@ const recursiveToggleFolderOptions: Option<Config['recursiveToggleFolder']>[] =
|
|||
},
|
||||
]
|
||||
|
||||
type Props = {}
|
||||
|
||||
export function FileTreeSettings(props: React.PropsWithChildren<Props>) {
|
||||
export function FileTreeSettings() {
|
||||
const configContext = useConfigs()
|
||||
return (
|
||||
<SettingsSection title={'File Tree'}>
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@ export function Footer(props: Props) {
|
|||
<Link
|
||||
className={'version'}
|
||||
href={wikiLinks.changeLog}
|
||||
target={'_blank'}
|
||||
title={'Check out new features!'}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{VERSION}
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -72,11 +72,19 @@ export function SettingsBarContent({ toggleShow }: { toggleShow: () => void }) {
|
|||
</SettingsSection>
|
||||
)}
|
||||
<SettingsSection title={'Talk to the author'}>
|
||||
<a href="https://github.com/EnixCoda/Gitako/issues" target="_blank">
|
||||
<a
|
||||
href="https://github.com/EnixCoda/Gitako/issues"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Report bug
|
||||
</a>
|
||||
{' / '}
|
||||
<a href="https://github.com/EnixCoda/Gitako/discussions" target="_blank">
|
||||
<a
|
||||
href="https://github.com/EnixCoda/Gitako/discussions"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Discuss feature
|
||||
</a>
|
||||
</SettingsSection>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@ import * as keyHelper from 'utils/keyHelper'
|
|||
import { Field } from './Field'
|
||||
import { SettingsSection } from './SettingsSection'
|
||||
|
||||
type Props = {}
|
||||
|
||||
export function SidebarSettings(props: React.PropsWithChildren<Props>) {
|
||||
export function SidebarSettings() {
|
||||
const configContext = useConfigs()
|
||||
const useToggleShowSideBarShortcut = useStateIO(configContext.value.shortcut)
|
||||
const { value: toggleShowSideBarShortcut } = useToggleShowSideBarShortcut
|
||||
|
|
@ -18,7 +16,7 @@ export function SidebarSettings(props: React.PropsWithChildren<Props>) {
|
|||
|
||||
React.useEffect(() => {
|
||||
useToggleShowSideBarShortcut.onChange(configContext.value.shortcut)
|
||||
}, [configContext.value.shortcut])
|
||||
}, [configContext.value.shortcut]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<SettingsSection title={'Sidebar'}>
|
||||
|
|
@ -38,7 +36,7 @@ export function SidebarSettings(props: React.PropsWithChildren<Props>) {
|
|||
// Clear shortcut with backspace
|
||||
const shortcut = e.key === 'Backspace' ? '' : keyHelper.parseEvent(e)
|
||||
useToggleShowSideBarShortcut.onChange(shortcut)
|
||||
}, [])}
|
||||
}, [])} // eslint-disable-line react-hooks/exhaustive-deps
|
||||
readOnly
|
||||
/>
|
||||
{configContext.value.shortcut === toggleShowSideBarShortcut ? (
|
||||
|
|
|
|||
|
|
@ -24,11 +24,19 @@ export function GiteeAccessDeniedError({ hasToken }: { hasToken: boolean }) {
|
|||
) : (
|
||||
<p>
|
||||
Gitako needs access token to read this project due to{' '}
|
||||
<a href="https://developer.github.com/v3/#rate-limiting" target="_blank">
|
||||
<a
|
||||
href="https://developer.github.com/v3/#rate-limiting"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
GitHub rate limiting
|
||||
</a>{' '}
|
||||
and{' '}
|
||||
<a href="https://developer.github.com/v3/#authentication" target="_blank">
|
||||
<a
|
||||
href="https://developer.github.com/v3/#authentication"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
auth needs
|
||||
</a>
|
||||
. Please setup access token in the settings panel below.
|
||||
|
|
|
|||
Loading…
Reference in a new issue