Files
bridget/assets/ts/configState.tsx
Sped0n f25b71a858 refactor: split monolithic state into context-based modules
Extract image, desktop, mobile, and config state into separate context
providers to improve modularity and reduce unnecessary re-renders.

Signed-off-by: Sped0n <hi@sped0n.com>
2026-03-22 19:45:05 +08:00

92 lines
2.1 KiB
TypeScript

import {
createContext,
createMemo,
createSignal,
useContext,
type Accessor,
type JSX
} from 'solid-js'
import invariant from 'tiny-invariant'
import { getThresholdSessionIndex } from './utils'
export interface ThresholdRelated {
threshold: number
trailLength: number
}
export interface ConfigState {
thresholdIndex: number
threshold: number
trailLength: number
}
export type ConfigStateContextType = readonly [
Accessor<ConfigState>,
{
readonly incThreshold: () => void
readonly decThreshold: () => void
}
]
const thresholds: ThresholdRelated[] = [
{ threshold: 20, trailLength: 20 },
{ threshold: 40, trailLength: 10 },
{ threshold: 80, trailLength: 5 },
{ threshold: 140, trailLength: 5 },
{ threshold: 200, trailLength: 5 }
]
const ConfigStateContext = createContext<ConfigStateContextType>()
function getSafeThresholdIndex(): number {
const index = getThresholdSessionIndex()
if (index < 0 || index >= thresholds.length) return 2
return index
}
export function ConfigStateProvider(props: { children?: JSX.Element }): JSX.Element {
const [thresholdIndex, setThresholdIndex] = createSignal(getSafeThresholdIndex())
const state = createMemo<ConfigState>(() => {
const current = thresholds[thresholdIndex()]
return {
thresholdIndex: thresholdIndex(),
threshold: current.threshold,
trailLength: current.trailLength
}
})
const updateThreshold = (stride: number): void => {
const nextIndex = thresholdIndex() + stride
if (nextIndex < 0 || nextIndex >= thresholds.length) return
sessionStorage.setItem('thresholdsIndex', nextIndex.toString())
setThresholdIndex(nextIndex)
}
return (
<ConfigStateContext.Provider
value={[
state,
{
incThreshold: () => {
updateThreshold(1)
},
decThreshold: () => {
updateThreshold(-1)
}
}
]}
>
{props.children}
</ConfigStateContext.Provider>
)
}
export function useConfigState(): ConfigStateContextType {
const context = useContext(ConfigStateContext)
invariant(context, 'undefined config context')
return context
}