chore: reorganize utility files

This commit is contained in:
EnixCoda 2020-03-08 14:27:08 +08:00
parent 78a4668a08
commit 05f670bb90
No known key found for this signature in database
GPG key ID: 0C1A07377913A1DD
16 changed files with 105 additions and 96 deletions

View file

@ -9,7 +9,8 @@ import * as React from 'react'
import useEvent from 'react-use/esm/useEvent'
import { FixedSizeList as List, ListChildComponentProps, ListProps } from 'react-window'
import { cx } from 'utils/cx'
import { useOnLocationChange, usePrevious } from 'utils/hooks'
import { useOnLocationChange } from 'utils/hooks/useOnLocationChange'
import { usePrevious } from 'utils/hooks/usePrevious'
import { getCurrentPath } from 'utils/URLHelper'
import { TreeNode, VisibleNodes } from 'utils/VisibleNodesGenerator'
import { Icon } from './Icon'

View file

@ -4,7 +4,8 @@ import * as React from 'react'
import { cx } from 'utils/cx'
import { bodySpacingClassName } from 'utils/DOMHelper'
import * as features from 'utils/features'
import { useMediaStyleSheet, useWindowSize } from 'utils/hooks'
import { useMediaStyleSheet } from 'utils/hooks/useMediaStyleSheet'
import { useWindowSize } from 'utils/hooks/useWindowSize'
export type Size = number
type Props = {

View file

@ -2,7 +2,7 @@ import { Icon } from 'components/Icon'
import { VERSION } from 'env'
import * as React from 'react'
import { Config } from 'utils/configHelper'
import { useStates } from 'utils/hooks'
import { useStates } from 'utils/hooks/useStates'
import { AccessTokenSettings } from './settings/AccessTokenSettings'
import { FileTreeIconSettings } from './settings/FileTreeIconSettings'
import { ShortcutSettings } from './settings/ShortcutSettings'

View file

@ -15,7 +15,7 @@ import useEvent from 'react-use/esm/useEvent'
import { cx } from 'utils/cx'
import * as DOMHelper from 'utils/DOMHelper'
import { JSONRequest, parseURLSearch } from 'utils/general'
import { useDidUpdate } from 'utils/hooks'
import { useDidUpdate } from 'utils/hooks/useDidUpdate'
import * as keyHelper from 'utils/keyHelper'
import * as URLHelper from 'utils/URLHelper'

View file

@ -2,7 +2,7 @@ import { wikiLinks } from 'components/SettingsBar'
import { useConfigs } from 'containers/ConfigsContext'
import { oauth } from 'env'
import * as React from 'react'
import { useStates } from 'utils/hooks'
import { useStates } from 'utils/hooks/useStates'
const ACCESS_TOKEN_REGEXP = /^[0-9a-f]{40}$/

View file

@ -1,7 +1,7 @@
import { useConfigs } from 'containers/ConfigsContext'
import * as React from 'react'
import { friendlyFormatShortcut } from 'utils/general'
import { useStates } from 'utils/hooks'
import { useStates } from 'utils/hooks/useStates'
import * as keyHelper from 'utils/keyHelper'
type Props = {}

View file

@ -1,90 +0,0 @@
import * as React from 'react'
import useLocation from 'react-use/esm/useLocation'
import { createStyleSheet, setStyleSheetMedia } from './general'
export function useWindowSize(
callback: (width: number) => void,
deps?: ReadonlyArray<any> | undefined,
) {
React.useEffect(() => {
const resizeListener: (this: Window, ev: UIEvent) => void = () => callback(window.innerWidth)
window.addEventListener('resize', resizeListener)
return () => window.removeEventListener('resize', resizeListener)
}, deps)
}
export function useMediaStyleSheet(
content: string,
getMediaQuery: (width: number) => string[],
size: number,
) {
const style = React.useRef<HTMLStyleElement>()
// this order may prevent first effect actually occur at first time
React.useEffect(() => {
setSheetMedia()
}, [size])
React.useEffect(() => {
style.current = createStyleSheet(content)
setSheetMedia()
}, [])
function setSheetMedia() {
if (style.current)
setStyleSheetMedia(
style.current,
getMediaQuery(size)
.map(query => `(${query})`)
.join(' and '),
)
}
}
export function usePrevious<T>(newValue: T) {
const previousRef = React.useRef(newValue)
React.useEffect(() => {
previousRef.current = newValue
})
return previousRef.current
}
export function useStates<S>(
initialState: S | (() => S),
): { val: S; set: React.Dispatch<React.SetStateAction<S>> } {
const [val, set] = React.useState(initialState)
return { val, set }
}
export function useAsyncMemo<T, D extends any[] | readonly any[]>(
factory: (dependencies: D) => T | Promise<T>,
deps: D,
initialValue: T,
): T {
const firstTime = React.useRef(true)
const state = useStates<T>(() => initialValue)
React.useEffect(() => {
if (firstTime.current) firstTime.current = false
Promise.resolve(factory(deps)).then(consumed => state.set(() => consumed))
}, deps)
return state.val
}
export function useDidUpdate(effect: React.EffectCallback, deps?: React.DependencyList) {
const firstTime = React.useRef(true)
React.useEffect(() => {
if (firstTime.current) {
firstTime.current = false
return
}
return effect()
}, deps)
}
export function useOnLocationChange(
callback: React.EffectCallback,
extraDeps: React.DependencyList = [],
) {
const { href, pathname, search } = useLocation()
React.useEffect(callback, [href, pathname, search, ...extraDeps])
}

View file

@ -0,0 +1,16 @@
import * as React from 'react'
import { useStates } from './useStates'
export function useAsyncMemo<T, D extends any[] | readonly any[]>(
factory: (dependencies: D) => T | Promise<T>,
deps: D,
initialValue: T,
): T {
const firstTime = React.useRef(true)
const state = useStates<T>(() => initialValue)
React.useEffect(() => {
if (firstTime.current) firstTime.current = false
Promise.resolve(factory(deps)).then(consumed => state.set(() => consumed))
}, deps)
return state.val
}

View file

@ -0,0 +1,12 @@
import * as React from 'react'
export function useDidUpdate(effect: React.EffectCallback, deps?: React.DependencyList) {
const firstTime = React.useRef(true)
React.useEffect(() => {
if (firstTime.current) {
firstTime.current = false
return
}
return effect()
}, deps)
}

View file

@ -0,0 +1,27 @@
import * as React from 'react'
import { createStyleSheet, setStyleSheetMedia } from '../general'
export function useMediaStyleSheet(
content: string,
getMediaQuery: (width: number) => string[],
size: number,
) {
const style = React.useRef<HTMLStyleElement>()
// this order may prevent first effect actually occur at first time
React.useEffect(() => {
setSheetMedia()
}, [size])
React.useEffect(() => {
style.current = createStyleSheet(content)
setSheetMedia()
}, [])
function setSheetMedia() {
if (style.current)
setStyleSheetMedia(
style.current,
getMediaQuery(size)
.map(query => `(${query})`)
.join(' and '),
)
}
}

View file

@ -0,0 +1,10 @@
import * as React from 'react'
import useLocation from 'react-use/esm/useLocation'
export function useOnLocationChange(
callback: React.EffectCallback,
extraDeps: React.DependencyList = [],
) {
const { href, pathname, search } = useLocation()
React.useEffect(callback, [href, pathname, search, ...extraDeps])
}

View file

@ -0,0 +1,9 @@
import * as React from 'react'
export function usePrevious<T>(newValue: T) {
const previousRef = React.useRef(newValue)
React.useEffect(() => {
previousRef.current = newValue
})
return previousRef.current
}

View file

@ -0,0 +1,11 @@
import * as React from 'react'
export function useStates<S>(
initialState: S | (() => S),
): {
val: S
set: React.Dispatch<React.SetStateAction<S>>
} {
const [val, set] = React.useState(initialState)
return { val, set }
}

View file

@ -0,0 +1,12 @@
import * as React from 'react'
export function useWindowSize(
callback: (width: number) => void,
deps?: ReadonlyArray<any> | undefined,
) {
React.useEffect(() => {
const resizeListener: (this: Window, ev: UIEvent) => void = () => callback(window.innerWidth)
window.addEventListener('resize', resizeListener)
return () => window.removeEventListener('resize', resizeListener)
}, deps)
}