feat: save proxy page state
This commit is contained in:
parent
3b5993652f
commit
7fa3c1e12a
@ -5,7 +5,8 @@ import { Virtuoso } from "react-virtuoso";
|
|||||||
import { ApiType } from "../../services/types";
|
import { ApiType } from "../../services/types";
|
||||||
import { updateProxy } from "../../services/api";
|
import { updateProxy } from "../../services/api";
|
||||||
import { getProfiles, patchProfile } from "../../services/cmds";
|
import { getProfiles, patchProfile } from "../../services/cmds";
|
||||||
import useSortProxy, { ProxySortType } from "./use-sort-proxy";
|
import useSortProxy from "./use-sort-proxy";
|
||||||
|
import useHeadState from "./use-head-state";
|
||||||
import useFilterProxy from "./use-filter-proxy";
|
import useFilterProxy from "./use-filter-proxy";
|
||||||
import delayManager from "../../services/delay";
|
import delayManager from "../../services/delay";
|
||||||
import ProxyHead from "./proxy-head";
|
import ProxyHead from "./proxy-head";
|
||||||
@ -24,13 +25,19 @@ const ProxyGlobal = (props: Props) => {
|
|||||||
const { mutate } = useSWRConfig();
|
const { mutate } = useSWRConfig();
|
||||||
const [now, setNow] = useState(curProxy || "DIRECT");
|
const [now, setNow] = useState(curProxy || "DIRECT");
|
||||||
|
|
||||||
const [showType, setShowType] = useState(true);
|
const [headState, setHeadState] = useHeadState(groupName);
|
||||||
const [sortType, setSortType] = useState<ProxySortType>(0);
|
|
||||||
const [filterText, setFilterText] = useState("");
|
|
||||||
|
|
||||||
const virtuosoRef = useRef<any>();
|
const virtuosoRef = useRef<any>();
|
||||||
const filterProxies = useFilterProxy(proxies, groupName, filterText);
|
const filterProxies = useFilterProxy(
|
||||||
const sortedProxies = useSortProxy(filterProxies, groupName, sortType);
|
proxies,
|
||||||
|
groupName,
|
||||||
|
headState.filterText
|
||||||
|
);
|
||||||
|
const sortedProxies = useSortProxy(
|
||||||
|
filterProxies,
|
||||||
|
groupName,
|
||||||
|
headState.sortType
|
||||||
|
);
|
||||||
|
|
||||||
const { data: profiles } = useSWR("getProfiles", getProfiles);
|
const { data: profiles } = useSWR("getProfiles", getProfiles);
|
||||||
|
|
||||||
@ -102,15 +109,11 @@ const ProxyGlobal = (props: Props) => {
|
|||||||
<>
|
<>
|
||||||
<ProxyHead
|
<ProxyHead
|
||||||
sx={{ px: 3, my: 0.5, button: { mr: 0.5 } }}
|
sx={{ px: 3, my: 0.5, button: { mr: 0.5 } }}
|
||||||
showType={showType}
|
|
||||||
sortType={sortType}
|
|
||||||
groupName={groupName}
|
groupName={groupName}
|
||||||
filterText={filterText}
|
headState={headState}
|
||||||
onLocation={onLocation}
|
onLocation={onLocation}
|
||||||
onCheckDelay={onCheckAll}
|
onCheckDelay={onCheckAll}
|
||||||
onShowType={setShowType}
|
onHeadState={setHeadState}
|
||||||
onSortType={setSortType}
|
|
||||||
onFilterText={setFilterText}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
@ -122,7 +125,7 @@ const ProxyGlobal = (props: Props) => {
|
|||||||
groupName={groupName}
|
groupName={groupName}
|
||||||
proxy={sortedProxies[index]}
|
proxy={sortedProxies[index]}
|
||||||
selected={sortedProxies[index].name === now}
|
selected={sortedProxies[index].name === now}
|
||||||
showType={showType}
|
showType={headState.showType}
|
||||||
onClick={onChangeProxy}
|
onClick={onChangeProxy}
|
||||||
sx={{ py: 0, px: 2 }}
|
sx={{ py: 0, px: 2 }}
|
||||||
/>
|
/>
|
||||||
|
@ -18,7 +18,8 @@ import {
|
|||||||
import { ApiType } from "../../services/types";
|
import { ApiType } from "../../services/types";
|
||||||
import { updateProxy } from "../../services/api";
|
import { updateProxy } from "../../services/api";
|
||||||
import { getProfiles, patchProfile } from "../../services/cmds";
|
import { getProfiles, patchProfile } from "../../services/cmds";
|
||||||
import useSortProxy, { ProxySortType } from "./use-sort-proxy";
|
import useSortProxy from "./use-sort-proxy";
|
||||||
|
import useHeadState from "./use-head-state";
|
||||||
import useFilterProxy from "./use-filter-proxy";
|
import useFilterProxy from "./use-filter-proxy";
|
||||||
import delayManager from "../../services/delay";
|
import delayManager from "../../services/delay";
|
||||||
import ProxyHead from "./proxy-head";
|
import ProxyHead from "./proxy-head";
|
||||||
@ -30,16 +31,21 @@ interface Props {
|
|||||||
|
|
||||||
const ProxyGroup = ({ group }: Props) => {
|
const ProxyGroup = ({ group }: Props) => {
|
||||||
const { mutate } = useSWRConfig();
|
const { mutate } = useSWRConfig();
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const [now, setNow] = useState(group.now);
|
const [now, setNow] = useState(group.now);
|
||||||
|
|
||||||
const [showType, setShowType] = useState(false);
|
const [headState, setHeadState] = useHeadState(group.name);
|
||||||
const [sortType, setSortType] = useState<ProxySortType>(0);
|
|
||||||
const [filterText, setFilterText] = useState("");
|
|
||||||
|
|
||||||
const virtuosoRef = useRef<any>();
|
const virtuosoRef = useRef<any>();
|
||||||
const filterProxies = useFilterProxy(group.all, group.name, filterText);
|
const filterProxies = useFilterProxy(
|
||||||
const sortedProxies = useSortProxy(filterProxies, group.name, sortType);
|
group.all,
|
||||||
|
group.name,
|
||||||
|
headState.filterText
|
||||||
|
);
|
||||||
|
const sortedProxies = useSortProxy(
|
||||||
|
filterProxies,
|
||||||
|
group.name,
|
||||||
|
headState.sortType
|
||||||
|
);
|
||||||
|
|
||||||
const { data: profiles } = useSWR("getProfiles", getProfiles);
|
const { data: profiles } = useSWR("getProfiles", getProfiles);
|
||||||
|
|
||||||
@ -99,14 +105,18 @@ const ProxyGroup = ({ group }: Props) => {
|
|||||||
|
|
||||||
// auto scroll to current index
|
// auto scroll to current index
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (headState.open) {
|
||||||
setTimeout(() => onLocation(false), 5);
|
setTimeout(() => onLocation(false), 5);
|
||||||
}
|
}
|
||||||
}, [open]);
|
}, [headState.open]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ListItem button onClick={() => setOpen(!open)} dense>
|
<ListItem
|
||||||
|
button
|
||||||
|
dense
|
||||||
|
onClick={() => setHeadState({ open: !headState.open })}
|
||||||
|
>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={group.name}
|
primary={group.name}
|
||||||
secondary={
|
secondary={
|
||||||
@ -120,21 +130,17 @@ const ProxyGroup = ({ group }: Props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{open ? <ExpandLessRounded /> : <ExpandMoreRounded />}
|
{headState.open ? <ExpandLessRounded /> : <ExpandMoreRounded />}
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
<Collapse in={headState.open} timeout="auto" unmountOnExit>
|
||||||
<ProxyHead
|
<ProxyHead
|
||||||
sx={{ pl: 4, pr: 3, my: 0.5, button: { mr: 0.5 } }}
|
sx={{ pl: 4, pr: 3, my: 0.5, button: { mr: 0.5 } }}
|
||||||
showType={showType}
|
|
||||||
sortType={sortType}
|
|
||||||
groupName={group.name}
|
groupName={group.name}
|
||||||
filterText={filterText}
|
headState={headState}
|
||||||
onLocation={onLocation}
|
onLocation={onLocation}
|
||||||
onCheckDelay={onCheckAll}
|
onCheckDelay={onCheckAll}
|
||||||
onShowType={setShowType}
|
onHeadState={setHeadState}
|
||||||
onSortType={setSortType}
|
|
||||||
onFilterText={setFilterText}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{!sortedProxies.length && (
|
{!sortedProxies.length && (
|
||||||
@ -160,7 +166,7 @@ const ProxyGroup = ({ group }: Props) => {
|
|||||||
groupName={group.name}
|
groupName={group.name}
|
||||||
proxy={sortedProxies[index]}
|
proxy={sortedProxies[index]}
|
||||||
selected={sortedProxies[index].name === now}
|
selected={sortedProxies[index].name === now}
|
||||||
showType={showType}
|
showType={headState.showType}
|
||||||
sx={{ py: 0, pl: 4 }}
|
sx={{ py: 0, pl: 4 }}
|
||||||
onClick={onChangeProxy}
|
onClick={onChangeProxy}
|
||||||
/>
|
/>
|
||||||
@ -178,7 +184,7 @@ const ProxyGroup = ({ group }: Props) => {
|
|||||||
groupName={group.name}
|
groupName={group.name}
|
||||||
proxy={proxy}
|
proxy={proxy}
|
||||||
selected={proxy.name === now}
|
selected={proxy.name === now}
|
||||||
showType={showType}
|
showType={headState.showType}
|
||||||
sx={{ py: 0, pl: 4 }}
|
sx={{ py: 0, pl: 4 }}
|
||||||
onClick={onChangeProxy}
|
onClick={onChangeProxy}
|
||||||
/>
|
/>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Box, IconButton, TextField, SxProps } from "@mui/material";
|
import { Box, IconButton, TextField, SxProps } from "@mui/material";
|
||||||
import {
|
import {
|
||||||
AccessTimeRounded,
|
AccessTimeRounded,
|
||||||
@ -14,27 +14,33 @@ import {
|
|||||||
SortRounded,
|
SortRounded,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import delayManager from "../../services/delay";
|
import delayManager from "../../services/delay";
|
||||||
|
import type { HeadState } from "./use-head-state";
|
||||||
import type { ProxySortType } from "./use-sort-proxy";
|
import type { ProxySortType } from "./use-sort-proxy";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
sx?: SxProps;
|
sx?: SxProps;
|
||||||
groupName: string;
|
groupName: string;
|
||||||
showType: boolean;
|
headState: HeadState;
|
||||||
sortType: ProxySortType;
|
|
||||||
filterText: string;
|
|
||||||
onLocation: () => void;
|
onLocation: () => void;
|
||||||
onCheckDelay: () => void;
|
onCheckDelay: () => void;
|
||||||
onShowType: (val: boolean) => void;
|
onHeadState: (val: Partial<HeadState>) => void;
|
||||||
onSortType: (val: ProxySortType) => void;
|
|
||||||
onFilterText: (val: string) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProxyHead = (props: Props) => {
|
const ProxyHead = (props: Props) => {
|
||||||
const { sx = {}, groupName, showType, sortType, filterText } = props;
|
const { sx = {}, groupName, headState, onHeadState } = props;
|
||||||
|
|
||||||
const [textState, setTextState] = useState<"url" | "filter" | null>(null);
|
const { showType, sortType, filterText, textState, testUrl } = headState;
|
||||||
|
|
||||||
const [testUrl, setTestUrl] = useState(delayManager.getUrl(groupName) || "");
|
const [autoFocus, setAutoFocus] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// fix the focus conflict
|
||||||
|
setTimeout(() => setAutoFocus(true), 100);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
delayManager.setUrl(groupName, testUrl);
|
||||||
|
}, [groupName, headState.testUrl]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex", alignItems: "center", ...sx }}>
|
<Box sx={{ display: "flex", alignItems: "center", ...sx }}>
|
||||||
@ -54,7 +60,7 @@ const ProxyHead = (props: Props) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
// Remind the user that it is custom test url
|
// Remind the user that it is custom test url
|
||||||
if (testUrl?.trim() && textState !== "filter") {
|
if (testUrl?.trim() && textState !== "filter") {
|
||||||
setTextState("url");
|
onHeadState({ textState: "url" });
|
||||||
}
|
}
|
||||||
props.onCheckDelay();
|
props.onCheckDelay();
|
||||||
}}
|
}}
|
||||||
@ -66,7 +72,9 @@ const ProxyHead = (props: Props) => {
|
|||||||
size="small"
|
size="small"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
title={["sort by default", "sort by delay", "sort by name"][sortType]}
|
title={["sort by default", "sort by delay", "sort by name"][sortType]}
|
||||||
onClick={() => props.onSortType(((sortType + 1) % 3) as ProxySortType)}
|
onClick={() =>
|
||||||
|
onHeadState({ sortType: ((sortType + 1) % 3) as ProxySortType })
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{sortType === 0 && <SortRounded />}
|
{sortType === 0 && <SortRounded />}
|
||||||
{sortType === 1 && <AccessTimeRounded />}
|
{sortType === 1 && <AccessTimeRounded />}
|
||||||
@ -77,7 +85,9 @@ const ProxyHead = (props: Props) => {
|
|||||||
size="small"
|
size="small"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
title="edit test url"
|
title="edit test url"
|
||||||
onClick={() => setTextState((ts) => (ts === "url" ? null : "url"))}
|
onClick={() =>
|
||||||
|
onHeadState({ textState: textState === "url" ? null : "url" })
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{textState === "url" ? (
|
{textState === "url" ? (
|
||||||
<WifiTetheringRounded />
|
<WifiTetheringRounded />
|
||||||
@ -90,7 +100,7 @@ const ProxyHead = (props: Props) => {
|
|||||||
size="small"
|
size="small"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
title="proxy detail"
|
title="proxy detail"
|
||||||
onClick={() => props.onShowType(!showType)}
|
onClick={() => onHeadState({ showType: !showType })}
|
||||||
>
|
>
|
||||||
{showType ? <VisibilityRounded /> : <VisibilityOffRounded />}
|
{showType ? <VisibilityRounded /> : <VisibilityOffRounded />}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@ -100,7 +110,7 @@ const ProxyHead = (props: Props) => {
|
|||||||
color="inherit"
|
color="inherit"
|
||||||
title="filter"
|
title="filter"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setTextState((ts) => (ts === "filter" ? null : "filter"))
|
onHeadState({ textState: textState === "filter" ? null : "filter" })
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{textState === "filter" ? (
|
{textState === "filter" ? (
|
||||||
@ -112,20 +122,20 @@ const ProxyHead = (props: Props) => {
|
|||||||
|
|
||||||
{textState === "filter" && (
|
{textState === "filter" && (
|
||||||
<TextField
|
<TextField
|
||||||
autoFocus
|
autoFocus={autoFocus}
|
||||||
hiddenLabel
|
hiddenLabel
|
||||||
value={filterText}
|
value={filterText}
|
||||||
size="small"
|
size="small"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
placeholder="Filter conditions"
|
placeholder="Filter conditions"
|
||||||
onChange={(e) => props.onFilterText(e.target.value)}
|
onChange={(e) => onHeadState({ filterText: e.target.value })}
|
||||||
sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }}
|
sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{textState === "url" && (
|
{textState === "url" && (
|
||||||
<TextField
|
<TextField
|
||||||
autoFocus
|
autoFocus={autoFocus}
|
||||||
hiddenLabel
|
hiddenLabel
|
||||||
autoSave="off"
|
autoSave="off"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
@ -133,10 +143,7 @@ const ProxyHead = (props: Props) => {
|
|||||||
size="small"
|
size="small"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
placeholder="Test url"
|
placeholder="Test url"
|
||||||
onChange={(e) => {
|
onChange={(e) => onHeadState({ testUrl: e.target.value })}
|
||||||
setTestUrl(e.target.value);
|
|
||||||
delayManager.setUrl(groupName, e.target.value);
|
|
||||||
}}
|
|
||||||
sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }}
|
sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
80
src/components/proxy/use-head-state.ts
Normal file
80
src/components/proxy/use-head-state.ts
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { useRecoilValue } from "recoil";
|
||||||
|
import { atomCurrentProfile } from "../../services/states";
|
||||||
|
import { ProxySortType } from "./use-sort-proxy";
|
||||||
|
|
||||||
|
export interface HeadState {
|
||||||
|
open?: boolean;
|
||||||
|
showType: boolean;
|
||||||
|
sortType: ProxySortType;
|
||||||
|
filterText: string;
|
||||||
|
textState: "url" | "filter" | null;
|
||||||
|
testUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type HeadStateStorage = Record<string, Record<string, HeadState>>;
|
||||||
|
|
||||||
|
const HEAD_STATE_KEY = "proxy-head-state";
|
||||||
|
const DEFAULT_STATE: HeadState = {
|
||||||
|
open: false,
|
||||||
|
showType: false,
|
||||||
|
sortType: 0,
|
||||||
|
filterText: "",
|
||||||
|
textState: null,
|
||||||
|
testUrl: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function useHeadState(groupName: string) {
|
||||||
|
const current = useRecoilValue(atomCurrentProfile);
|
||||||
|
|
||||||
|
const [state, setState] = useState<HeadState>(DEFAULT_STATE);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!current) {
|
||||||
|
setState(DEFAULT_STATE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(
|
||||||
|
localStorage.getItem(HEAD_STATE_KEY)!
|
||||||
|
) as HeadStateStorage;
|
||||||
|
|
||||||
|
const value = data[current][groupName] || DEFAULT_STATE;
|
||||||
|
|
||||||
|
if (value && typeof value === "object") {
|
||||||
|
setState({ ...DEFAULT_STATE, ...value });
|
||||||
|
} else {
|
||||||
|
setState(DEFAULT_STATE);
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}, [current, groupName]);
|
||||||
|
|
||||||
|
const setHeadState = useCallback(
|
||||||
|
(obj: Partial<HeadState>) => {
|
||||||
|
setState((old) => {
|
||||||
|
const ret = { ...old, ...obj };
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
try {
|
||||||
|
const item = localStorage.getItem(HEAD_STATE_KEY);
|
||||||
|
|
||||||
|
let data = (item ? JSON.parse(item) : {}) as HeadStateStorage;
|
||||||
|
|
||||||
|
if (!data || typeof data !== "object") data = {};
|
||||||
|
if (!data[current]) data[current] = {};
|
||||||
|
|
||||||
|
data[current][groupName] = ret;
|
||||||
|
|
||||||
|
localStorage.setItem(HEAD_STATE_KEY, JSON.stringify(data));
|
||||||
|
} catch {}
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[current, groupName]
|
||||||
|
);
|
||||||
|
|
||||||
|
return [state, setHeadState] as const;
|
||||||
|
}
|
@ -3,6 +3,7 @@ import i18next from "i18next";
|
|||||||
import relativeTime from "dayjs/plugin/relativeTime";
|
import relativeTime from "dayjs/plugin/relativeTime";
|
||||||
import useSWR, { SWRConfig, useSWRConfig } from "swr";
|
import useSWR, { SWRConfig, useSWRConfig } from "swr";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { useSetRecoilState } from "recoil";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Route, Routes } from "react-router-dom";
|
import { Route, Routes } from "react-router-dom";
|
||||||
import { alpha, List, Paper, ThemeProvider } from "@mui/material";
|
import { alpha, List, Paper, ThemeProvider } from "@mui/material";
|
||||||
@ -10,7 +11,8 @@ import { listen } from "@tauri-apps/api/event";
|
|||||||
import { appWindow } from "@tauri-apps/api/window";
|
import { appWindow } from "@tauri-apps/api/window";
|
||||||
import { routers } from "./_routers";
|
import { routers } from "./_routers";
|
||||||
import { getAxios } from "../services/api";
|
import { getAxios } from "../services/api";
|
||||||
import { getVergeConfig } from "../services/cmds";
|
import { atomCurrentProfile } from "../services/states";
|
||||||
|
import { getVergeConfig, getProfiles } from "../services/cmds";
|
||||||
import { ReactComponent as LogoSvg } from "../assets/image/logo.svg";
|
import { ReactComponent as LogoSvg } from "../assets/image/logo.svg";
|
||||||
import LayoutItem from "../components/layout/layout-item";
|
import LayoutItem from "../components/layout/layout-item";
|
||||||
import LayoutControl from "../components/layout/layout-control";
|
import LayoutControl from "../components/layout/layout-control";
|
||||||
@ -33,6 +35,8 @@ const Layout = () => {
|
|||||||
const { data: vergeConfig } = useSWR("getVergeConfig", getVergeConfig);
|
const { data: vergeConfig } = useSWR("getVergeConfig", getVergeConfig);
|
||||||
const { theme_blur, language } = vergeConfig || {};
|
const { theme_blur, language } = vergeConfig || {};
|
||||||
|
|
||||||
|
const setCurrentProfile = useSetRecoilState(atomCurrentProfile);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener("keydown", (e) => {
|
window.addEventListener("keydown", (e) => {
|
||||||
if (e.key === "Escape") appWindow.close();
|
if (e.key === "Escape") appWindow.close();
|
||||||
@ -47,6 +51,9 @@ const Layout = () => {
|
|||||||
|
|
||||||
// update the verge config
|
// update the verge config
|
||||||
listen("verge://refresh-verge-config", () => mutate("getVergeConfig"));
|
listen("verge://refresh-verge-config", () => mutate("getVergeConfig"));
|
||||||
|
|
||||||
|
// set current profile uid
|
||||||
|
getProfiles().then((data) => setCurrentProfile(data.current ?? ""));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import useSWR, { useSWRConfig } from "swr";
|
import useSWR, { useSWRConfig } from "swr";
|
||||||
import { useLockFn } from "ahooks";
|
import { useLockFn } from "ahooks";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
import { useSetRecoilState } from "recoil";
|
||||||
import { Box, Button, Grid, TextField } from "@mui/material";
|
import { Box, Button, Grid, TextField } from "@mui/material";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
@ -10,6 +11,7 @@ import {
|
|||||||
importProfile,
|
importProfile,
|
||||||
} from "../services/cmds";
|
} from "../services/cmds";
|
||||||
import { getProxies, updateProxy } from "../services/api";
|
import { getProxies, updateProxy } from "../services/api";
|
||||||
|
import { atomCurrentProfile } from "../services/states";
|
||||||
import Notice from "../components/base/base-notice";
|
import Notice from "../components/base/base-notice";
|
||||||
import BasePage from "../components/base/base-page";
|
import BasePage from "../components/base/base-page";
|
||||||
import ProfileNew from "../components/profile/profile-new";
|
import ProfileNew from "../components/profile/profile-new";
|
||||||
@ -24,6 +26,8 @@ const ProfilePage = () => {
|
|||||||
const [disabled, setDisabled] = useState(false);
|
const [disabled, setDisabled] = useState(false);
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
|
|
||||||
|
const setCurrentProfile = useSetRecoilState(atomCurrentProfile);
|
||||||
|
|
||||||
const { data: profiles = {} } = useSWR("getProfiles", getProfiles);
|
const { data: profiles = {} } = useSWR("getProfiles", getProfiles);
|
||||||
|
|
||||||
// distinguish type
|
// distinguish type
|
||||||
@ -52,6 +56,9 @@ const ProfilePage = () => {
|
|||||||
|
|
||||||
const current = profiles.current;
|
const current = profiles.current;
|
||||||
const profile = regularItems.find((p) => p.uid === current);
|
const profile = regularItems.find((p) => p.uid === current);
|
||||||
|
|
||||||
|
setCurrentProfile(current);
|
||||||
|
|
||||||
if (!profile) return;
|
if (!profile) return;
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
@ -121,6 +128,7 @@ const ProfilePage = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await selectProfile(uid);
|
await selectProfile(uid);
|
||||||
|
setCurrentProfile(uid);
|
||||||
mutate("getProfiles", { ...profiles, current: uid }, true);
|
mutate("getProfiles", { ...profiles, current: uid }, true);
|
||||||
if (force) Notice.success("Refresh clash config", 1000);
|
if (force) Notice.success("Refresh clash config", 1000);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
@ -22,3 +22,9 @@ export const atomUpdateState = atom<boolean>({
|
|||||||
key: "atomUpdateState",
|
key: "atomUpdateState",
|
||||||
default: false,
|
default: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// current profile uid
|
||||||
|
export const atomCurrentProfile = atom<string>({
|
||||||
|
key: "atomCurrentProfile",
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user