@@ -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
diff --git a/src/components/FileExplorer/hooks/useNodeRenderers.tsx b/src/components/FileExplorer/hooks/useNodeRenderers.tsx
index 7b5c9df..08bf1e9 100644
--- a/src/components/FileExplorer/hooks/useNodeRenderers.tsx
+++ b/src/components/FileExplorer/hooks/useNodeRenderers.tsx
@@ -14,7 +14,7 @@ export function useNodeRenderers(allRenderers: (NodeRenderer | null | undefined)
? (node: TreeNode) =>
renderers.map((render, i) =>
{render(node)})
: undefined
- }, allRenderers)
+ }, allRenderers) // eslint-disable-line react-hooks/exhaustive-deps
}
export function useRenderFileStatus() {
diff --git a/src/components/FileExplorer/hooks/useOnVisibleNodesGeneratorReady.tsx b/src/components/FileExplorer/hooks/useOnVisibleNodesGeneratorReady.tsx
index 16cc3e5..81e858c 100644
--- a/src/components/FileExplorer/hooks/useOnVisibleNodesGeneratorReady.tsx
+++ b/src/components/FileExplorer/hooks/useOnVisibleNodesGeneratorReady.tsx
@@ -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,
diff --git a/src/components/FileExplorer/hooks/useSetupTree.tsx b/src/components/FileExplorer/hooks/useSetupTree.tsx
index f830885..521b429 100644
--- a/src/components/FileExplorer/hooks/useSetupTree.tsx
+++ b/src/components/FileExplorer/hooks/useSetupTree.tsx
@@ -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
),
)
diff --git a/src/components/FileExplorer/index.tsx b/src/components/FileExplorer/index.tsx
index bc85622..e4fe6d0 100644
--- a/src/components/FileExplorer/index.tsx
+++ b/src/components/FileExplorer/index.tsx
@@ -116,9 +116,9 @@ export function FileExplorer({ freeze, metaData }: Props) {
)}
>
)}
-
- {({ width = 0, height = 0 }) => (
-
+
>
+ {({ width = 0, height = 0 }, ref) => (
+
{children()}>
-}
diff --git a/src/components/SelectInput.tsx b/src/components/SelectInput.tsx
index 48479a4..ff3a130 100644
--- a/src/components/SelectInput.tsx
+++ b/src/components/SelectInput.tsx
@@ -16,7 +16,7 @@ export function SelectInput({
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}
diff --git a/src/components/SideBar.tsx b/src/components/SideBar.tsx
index 185d580..00c193c 100644
--- a/src/components/SideBar.tsx
+++ b/src/components/SideBar.tsx
@@ -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(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 (
diff --git a/src/components/SideBarBodyWrapper.tsx b/src/components/SideBarBodyWrapper.tsx
index fff4d2a..78e502b 100644
--- a/src/components/SideBarBodyWrapper.tsx
+++ b/src/components/SideBarBodyWrapper.tsx
@@ -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(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: React.MouseEvent) => {
@@ -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'
diff --git a/src/components/SimpleToggleField.tsx b/src/components/SimpleToggleField.tsx
index 7e0ec27..529a584 100644
--- a/src/components/SimpleToggleField.tsx
+++ b/src/components/SimpleToggleField.tsx
@@ -33,7 +33,12 @@ export function SimpleToggleField({ field, onChange }:
<>
{field.label}{' '}
{field.wikiLink ? (
-
+
(?)
) : field.description ? (
diff --git a/src/components/SizeObserver.tsx b/src/components/SizeObserver.tsx
index 0b24933..26347e6 100644
--- a/src/components/SizeObserver.tsx
+++ b/src/components/SizeObserver.tsx
@@ -6,16 +6,12 @@ type Size = {
height: number
}
-type Props = Override<
- React.HTMLAttributes,
- {
- type?: string | React.ComponentType
- children(size: Partial): React.ReactNode
- }
->
+type Props = {
+ children(size: Partial, ref: React.MutableRefObject): React.ReactNode
+}
-export function SizeObserver({ type = 'div', children, ...rest }: Props) {
- const ref = React.useRef()
+export function SizeObserver({ children }: Props) {
+ const ref = React.useRef(null)
const [size, setSize] = React.useState>({
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)}>
}
diff --git a/src/components/ToggleShowButton.tsx b/src/components/ToggleShowButton.tsx
index baf0fe8..5e51750 100644
--- a/src/components/ToggleShowButton.tsx
+++ b/src/components/ToggleShowButton.tsx
@@ -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(
diff --git a/src/components/searchModes/fuzzyMode.test.ts b/src/components/searchModes/fuzzyMode.test.ts
index 5a82b6c..57469af 100644
--- a/src/components/searchModes/fuzzyMode.test.ts
+++ b/src/components/searchModes/fuzzyMode.test.ts
@@ -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,
diff --git a/src/components/searchModes/fuzzyMode.tsx b/src/components/searchModes/fuzzyMode.tsx
index ad71595..291a529 100644
--- a/src/components/searchModes/fuzzyMode.tsx
+++ b/src/components/searchModes/fuzzyMode.tsx
@@ -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
diff --git a/src/components/settings/AccessTokenSettings.tsx b/src/components/settings/AccessTokenSettings.tsx
index e26980c..b53414a 100644
--- a/src/components/settings/AccessTokenSettings.tsx
+++ b/src/components/settings/AccessTokenSettings.tsx
@@ -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) {
+export function AccessTokenSettings() {
const configContext = useConfigs()
const hasAccessToken = Boolean(configContext.value.accessToken)
- const $useAccessToken = useStateIO('')
+ const [accessToken, setAccessToken] = React.useState('')
const useAccessTokenHint = useStateIO('')
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) => {
- $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) {
) => {
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) {
href={wikiLinks.createAccessToken}
title="A token is required to access private repositories or bypass API rate limits"
target="_blank"
+ rel="noopener noreferrer"
>
(?)
diff --git a/src/components/settings/FileTreeSettings.tsx b/src/components/settings/FileTreeSettings.tsx
index 3b79af5..96ab893 100644
--- a/src/components/settings/FileTreeSettings.tsx
+++ b/src/components/settings/FileTreeSettings.tsx
@@ -38,9 +38,7 @@ const recursiveToggleFolderOptions: Option[] =
},
]
-type Props = {}
-
-export function FileTreeSettings(props: React.PropsWithChildren) {
+export function FileTreeSettings() {
const configContext = useConfigs()
return (
diff --git a/src/components/settings/Footer.tsx b/src/components/settings/Footer.tsx
index 23ed12b..7542476 100644
--- a/src/components/settings/Footer.tsx
+++ b/src/components/settings/Footer.tsx
@@ -15,8 +15,9 @@ export function Footer(props: Props) {
{VERSION}
diff --git a/src/components/settings/SettingsBar.tsx b/src/components/settings/SettingsBar.tsx
index 254215a..669993e 100644
--- a/src/components/settings/SettingsBar.tsx
+++ b/src/components/settings/SettingsBar.tsx
@@ -72,11 +72,19 @@ export function SettingsBarContent({ toggleShow }: { toggleShow: () => void }) {
)}
-
+
Report bug
{' / '}
-
+
Discuss feature
diff --git a/src/components/settings/SidebarSettings.tsx b/src/components/settings/SidebarSettings.tsx
index 8d2f403..20c8335 100644
--- a/src/components/settings/SidebarSettings.tsx
+++ b/src/components/settings/SidebarSettings.tsx
@@ -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) {
+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) {
React.useEffect(() => {
useToggleShowSideBarShortcut.onChange(configContext.value.shortcut)
- }, [configContext.value.shortcut])
+ }, [configContext.value.shortcut]) // eslint-disable-line react-hooks/exhaustive-deps
return (
@@ -38,7 +36,7 @@ export function SidebarSettings(props: React.PropsWithChildren) {
// 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 ? (
diff --git a/src/platforms/Gitee/components.tsx b/src/platforms/Gitee/components.tsx
index 945f11d..bd4472a 100644
--- a/src/platforms/Gitee/components.tsx
+++ b/src/platforms/Gitee/components.tsx
@@ -24,11 +24,19 @@ export function GiteeAccessDeniedError({ hasToken }: { hasToken: boolean }) {
) : (
Gitako needs access token to read this project due to{' '}
-
+
GitHub rate limiting
{' '}
and{' '}
-
+
auth needs
. Please setup access token in the settings panel below.