diff --git a/src/app.tsx b/src/app.tsx index 23b5c5fe7..d1149ee0f 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -25,6 +25,7 @@ function insertLinkElement(href: string) { l.href = href; l.rel = 'preload'; l.as = 'font'; + l.type = 'font/woff2'; l.crossOrigin = ''; document.head.appendChild(l); diff --git a/src/components/APIConfig.tsx b/src/components/APIConfig.tsx index 6a6388d91..21e9e58c6 100644 --- a/src/components/APIConfig.tsx +++ b/src/components/APIConfig.tsx @@ -5,8 +5,6 @@ import { BackendList } from 'src/components/BackendList'; import { clashAPIConfigsAtom, findClashAPIConfigIndexTmp } from 'src/store/app'; import { ClashAPIConfig } from 'src/types'; -import { saveStateTmp } from '$src/misc/storage'; - import s0 from './APIConfig.module.scss'; import Button from './Button'; import Field from './Field'; @@ -60,7 +58,6 @@ export default function APIConfig() { setApiConfigs((apiConfigs) => { return [...apiConfigs, { ...conf, addedAt: Date.now() }]; }); - saveStateTmp({ clashAPIConfigs: apiConfigs }); } }); }, [baseURL, secret, metaLabel, apiConfigs, setApiConfigs]); diff --git a/src/components/BackendList.tsx b/src/components/BackendList.tsx index 98629b830..f4e55d91e 100644 --- a/src/components/BackendList.tsx +++ b/src/components/BackendList.tsx @@ -4,7 +4,6 @@ import * as React from 'react'; import { Eye, EyeOff, X as Close } from 'react-feather'; import { useToggle } from '$src/hooks/basic'; -import { saveStateTmp } from '$src/misc/storage'; import { clashAPIConfigsAtom, findClashAPIConfigIndexTmp, @@ -35,13 +34,6 @@ export function BackendList() { [apiConfigs, selectedClashAPIConfigIndex, setApiConfigs, setSelectedClashAPIConfigIndex], ); - React.useEffect(() => { - saveStateTmp({ - selectedClashAPIConfigIndex, - clashAPIConfigs: apiConfigs, - }); - }, [apiConfigs, selectedClashAPIConfigIndex]); - const selectClashAPIConfig = React.useCallback( (conf: ClashAPIConfig) => { const idx = findClashAPIConfigIndexTmp(apiConfigs, conf); @@ -49,7 +41,6 @@ export function BackendList() { if (curr !== idx) { setSelectedClashAPIConfigIndex(idx); } - saveStateTmp({ selectedClashAPIConfigIndex }); // manual clean up is too complex // we just reload the app diff --git a/src/components/Config.tsx b/src/components/Config.tsx index 3bf98b165..7b1d9cd4d 100644 --- a/src/components/Config.tsx +++ b/src/components/Config.tsx @@ -6,8 +6,6 @@ import * as logsApi from 'src/api/logs'; import Select from 'src/components/shared/Select'; import { ClashGeneralConfig, DispatchFn, State } from 'src/store/types'; -import { saveStateTmp } from '$src/misc/storage'; - import { darkModePureBlackToggleAtom, latencyTestUrlAtom, @@ -149,7 +147,6 @@ function ConfigImpl({ dispatch, configs }: ConfigImplProps) { ); const selectChartStyleIndex = useCallback((idx: number) => { setSelectedChartStyleIndex(idx); - saveStateTmp({ selectedChartStyleIndex: idx }); }, [setSelectedChartStyleIndex]) const handleInputOnBlur = useCallback>( diff --git a/src/components/Logs.tsx b/src/components/Logs.tsx index 2286f6bf2..bc83937d4 100644 --- a/src/components/Logs.tsx +++ b/src/components/Logs.tsx @@ -7,7 +7,7 @@ import { areEqual, FixedSizeList as List, ListChildComponentProps } from 'react- import { fetchLogs, reconnect as reconnectLogs, stop as stopLogs } from 'src/api/logs'; import ContentHeader from 'src/components/ContentHeader'; import LogSearch from 'src/components/LogSearch'; -import { connect, useStoreActions } from 'src/components/StateProvider'; +import { connect } from 'src/components/StateProvider'; import SvgYacd from 'src/components/SvgYacd'; import useRemainingViewPortHeight from 'src/hooks/useRemainingViewPortHeight'; import { logStreamingPausedAtom, useApiConfig } from 'src/store/app'; diff --git a/src/components/Root.tsx b/src/components/Root.tsx index 871d17fdb..ad4bd4f4d 100644 --- a/src/components/Root.tsx +++ b/src/components/Root.tsx @@ -11,7 +11,8 @@ import Loading from 'src/components/Loading'; import { Head } from 'src/components/shared/Head'; import { queryClient } from 'src/misc/query'; -import { darkModePureBlackToggleAtom } from '$src/store/app'; +import { AppConfigSideEffect } from '$src/components/fn/AppConfigSideEffect'; +import { darkModePureBlackToggleAtom } from '$src/store/app'; import { actions, initialState } from '../store'; import APIConfig from './APIConfig'; @@ -87,6 +88,7 @@ const Root = () => ( + }> diff --git a/src/components/fn/AppConfigSideEffect.tsx b/src/components/fn/AppConfigSideEffect.tsx new file mode 100644 index 000000000..47db90b62 --- /dev/null +++ b/src/components/fn/AppConfigSideEffect.tsx @@ -0,0 +1,66 @@ +import { useAtom } from 'jotai'; +import { useEffect } from 'react'; + +import { saveState } from '$src/misc/storage'; +import { debounce } from '$src/misc/utils'; +import { + autoCloseOldConnsAtom, + clashAPIConfigsAtom, + collapsibleIsOpenAtom, + hideUnavailableProxiesAtom, + latencyTestUrlAtom, + logStreamingPausedAtom, + proxySortByAtom, + selectedChartStyleIndexAtom, + selectedClashAPIConfigIndexAtom, + themeAtom, +} from '$src/store/app'; +import { StateApp } from '$src/store/types'; + +let stateRef: StateApp; + +function save0() { + if (stateRef) saveState(stateRef); +} + +const save = debounce(save0, 500); + +export function AppConfigSideEffect() { + const [selectedClashAPIConfigIndex] = useAtom(selectedClashAPIConfigIndexAtom); + const [clashAPIConfigs] = useAtom(clashAPIConfigsAtom); + const [latencyTestUrl] = useAtom(latencyTestUrlAtom); + const [selectedChartStyleIndex] = useAtom(selectedChartStyleIndexAtom); + const [theme] = useAtom(themeAtom); + const [collapsibleIsOpen] = useAtom(collapsibleIsOpenAtom); + const [proxySortBy] = useAtom(proxySortByAtom); + const [hideUnavailableProxies] = useAtom(hideUnavailableProxiesAtom); + const [autoCloseOldConns] = useAtom(autoCloseOldConnsAtom); + const [logStreamingPaused] = useAtom(logStreamingPausedAtom); + useEffect(() => { + stateRef = { + autoCloseOldConns, + clashAPIConfigs, + collapsibleIsOpen, + hideUnavailableProxies, + latencyTestUrl, + logStreamingPaused, + proxySortBy, + selectedChartStyleIndex, + selectedClashAPIConfigIndex, + theme, + } + save(); + }, [ + autoCloseOldConns, + clashAPIConfigs, + collapsibleIsOpen, + hideUnavailableProxies, + latencyTestUrl, + logStreamingPaused, + proxySortBy, + selectedChartStyleIndex, + selectedClashAPIConfigIndex, + theme, + ]); + return null; +} diff --git a/src/components/shared/ThemeSwitcher.tsx b/src/components/shared/ThemeSwitcher.tsx index 738b06a5b..2dd5eed48 100644 --- a/src/components/shared/ThemeSwitcher.tsx +++ b/src/components/shared/ThemeSwitcher.tsx @@ -7,7 +7,6 @@ import { Check } from 'react-feather'; import { useTranslation } from 'react-i18next'; import { framerMotionResource } from '$src/misc/motion'; -import { saveStateTmp } from '$src/misc/storage'; import { setTheme, themeAtom } from '$src/store/app'; import { ThemeType } from '$src/store/types'; @@ -34,7 +33,6 @@ export function ThemeSwitcher() { const onSelect = React.useCallback((v: ThemeType) => { setThemeAtom(v); setTheme(v); - saveStateTmp({ theme: v }); }, [setThemeAtom]); return ( diff --git a/src/misc/storage.ts b/src/misc/storage.ts index 96ca26657..3d6acedf7 100644 --- a/src/misc/storage.ts +++ b/src/misc/storage.ts @@ -23,20 +23,6 @@ export function saveState(state: StateApp) { } } -export function saveStateTmp(partial: Partial) { - const s = loadState(); - if (!s) return; - try { - const serialized = JSON.stringify({ - ...s, - ...partial - }); - localStorage.setItem(StorageKey, serialized); - } catch (err) { - // ignore - } -} - export function clearState() { try { localStorage.removeItem(StorageKey); diff --git a/src/store/app.ts b/src/store/app.ts index 7cf53fc13..56b410597 100644 --- a/src/store/app.ts +++ b/src/store/app.ts @@ -43,13 +43,13 @@ const CONFIG_QUERY_PARAMS = ['hostname', 'port', 'secret', 'theme']; export const selectedClashAPIConfigIndexAtom = atom(initialState().selectedClashAPIConfigIndex); export const clashAPIConfigsAtom = atom(initialState().clashAPIConfigs); -export const selectedChartStyleIndexAtom = atom(initialState().selectedChartStyleIndex); export const latencyTestUrlAtom = atom(initialState().latencyTestUrl); +export const selectedChartStyleIndexAtom = atom(initialState().selectedChartStyleIndex); +export const themeAtom = atom(initialState().theme); export const collapsibleIsOpenAtom = atom(initialState().collapsibleIsOpen); export const proxySortByAtom = atom(initialState().proxySortBy); export const hideUnavailableProxiesAtom = atom(initialState().hideUnavailableProxies); export const autoCloseOldConnsAtom = atom(initialState().autoCloseOldConns); -export const themeAtom = atom(initialState().theme); export const logStreamingPausedAtom = atom(initialState().logStreamingPaused); // hooks