diff --git a/eslint.config.ts b/eslint.config.ts
index 1d8babc3..4c1c2e4b 100644
--- a/eslint.config.ts
+++ b/eslint.config.ts
@@ -1,15 +1,23 @@
import js from "@eslint/js";
+import pluginReact from "eslint-plugin-react";
+import pluginReactHooks from "eslint-plugin-react-hooks";
+import { defineConfig } from "eslint/config";
import globals from "globals";
import tseslint from "typescript-eslint";
-import pluginReact from "eslint-plugin-react";
-import { defineConfig } from "eslint/config";
export default defineConfig([
{
files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
- plugins: { js },
+ plugins: {
+ js,
+ "react-hooks": pluginReactHooks,
+ },
extends: ["js/recommended"],
languageOptions: { globals: globals.browser },
+ rules: {
+ "react-hooks/rules-of-hooks": "error",
+ "react-hooks/exhaustive-deps": "error",
+ },
},
tseslint.configs.recommended,
pluginReact.configs.flat["jsx-runtime"],
diff --git a/package.json b/package.json
index 92adbbde..7ec4811e 100644
--- a/package.json
+++ b/package.json
@@ -88,6 +88,7 @@
"cross-env": "^10.0.0",
"eslint": "^9.35.0",
"eslint-plugin-react": "^7.37.5",
+ "eslint-plugin-react-hooks": "^5.2.0",
"glob": "^11.0.3",
"globals": "^16.4.0",
"https-proxy-agent": "^7.0.6",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 54589a32..5534b76d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -180,6 +180,9 @@ importers:
eslint-plugin-react:
specifier: ^7.37.5
version: 7.37.5(eslint@9.35.0(jiti@2.5.1))
+ eslint-plugin-react-hooks:
+ specifier: ^5.2.0
+ version: 5.2.0(eslint@9.35.0(jiti@2.5.1))
glob:
specifier: ^11.0.3
version: 11.0.3
@@ -2205,6 +2208,12 @@ packages:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
+ eslint-plugin-react-hooks@5.2.0:
+ resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+
eslint-plugin-react@7.37.5:
resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
engines: {node: '>=4'}
@@ -5914,6 +5923,10 @@ snapshots:
escape-string-regexp@4.0.0: {}
+ eslint-plugin-react-hooks@5.2.0(eslint@9.35.0(jiti@2.5.1)):
+ dependencies:
+ eslint: 9.35.0(jiti@2.5.1)
+
eslint-plugin-react@7.37.5(eslint@9.35.0(jiti@2.5.1)):
dependencies:
array-includes: 3.1.9
diff --git a/src/components/base/base-search-box.tsx b/src/components/base/base-search-box.tsx
index a8bd2c44..c41aaf2b 100644
--- a/src/components/base/base-search-box.tsx
+++ b/src/components/base/base-search-box.tsx
@@ -81,8 +81,8 @@ export const BaseSearchBox = (props: SearchProps) => {
return (content: string) => {
if (!searchText) return true;
- let item = !matchCase ? content.toLowerCase() : content;
- let searchItem = !matchCase ? searchText.toLowerCase() : searchText;
+ const item = !matchCase ? content.toLowerCase() : content;
+ const searchItem = !matchCase ? searchText.toLowerCase() : searchText;
if (useRegularExpression) {
return new RegExp(searchItem).test(item);
diff --git a/src/components/profile/group-item.tsx b/src/components/profile/group-item.tsx
index b069d187..04f7e338 100644
--- a/src/components/profile/group-item.tsx
+++ b/src/components/profile/group-item.tsx
@@ -19,7 +19,7 @@ interface Props {
}
export const GroupItem = (props: Props) => {
- let { type, group, onDelete } = props;
+ const { type, group, onDelete } = props;
const sortable = type === "prepend" || type === "append";
const {
diff --git a/src/components/profile/groups-editor-viewer.tsx b/src/components/profile/groups-editor-viewer.tsx
index 0c94cc37..b8d3671b 100644
--- a/src/components/profile/groups-editor-viewer.tsx
+++ b/src/components/profile/groups-editor-viewer.tsx
@@ -159,8 +159,8 @@ export const GroupsEditorViewer = (props: Props) => {
}
};
const fetchContent = async () => {
- let data = await readProfileFile(property);
- let obj = yaml.load(data) as ISeqProfileConfig | null;
+ const data = await readProfileFile(property);
+ const obj = yaml.load(data) as ISeqProfileConfig | null;
setPrependSeq(obj?.prepend || []);
setAppendSeq(obj?.append || []);
@@ -174,7 +174,7 @@ export const GroupsEditorViewer = (props: Props) => {
if (currData === "") return;
if (visualization !== true) return;
- let obj = yaml.load(currData) as {
+ const obj = yaml.load(currData) as {
prepend: [];
append: [];
delete: [];
@@ -209,21 +209,21 @@ export const GroupsEditorViewer = (props: Props) => {
}, [prependSeq, appendSeq, deleteSeq]);
const fetchProxyPolicy = async () => {
- let data = await readProfileFile(profileUid);
- let proxiesData = await readProfileFile(proxiesUid);
- let originGroupsObj = yaml.load(data) as {
+ const data = await readProfileFile(profileUid);
+ const proxiesData = await readProfileFile(proxiesUid);
+ const originGroupsObj = yaml.load(data) as {
"proxy-groups": IProxyGroupConfig[];
} | null;
- let originProxiesObj = yaml.load(data) as { proxies: [] } | null;
- let originProxies = originProxiesObj?.proxies || [];
- let moreProxiesObj = yaml.load(proxiesData) as ISeqProfileConfig | null;
- let morePrependProxies = moreProxiesObj?.prepend || [];
- let moreAppendProxies = moreProxiesObj?.append || [];
- let moreDeleteProxies =
+ const originProxiesObj = yaml.load(data) as { proxies: [] } | null;
+ const originProxies = originProxiesObj?.proxies || [];
+ const moreProxiesObj = yaml.load(proxiesData) as ISeqProfileConfig | null;
+ const morePrependProxies = moreProxiesObj?.prepend || [];
+ const moreAppendProxies = moreProxiesObj?.append || [];
+ const moreDeleteProxies =
moreProxiesObj?.delete || ([] as string[] | { name: string }[]);
- let proxies = morePrependProxies.concat(
+ const proxies = morePrependProxies.concat(
originProxies.filter((proxy: any) => {
if (proxy.name) {
return !moreDeleteProxies.includes(proxy.name);
@@ -246,28 +246,30 @@ export const GroupsEditorViewer = (props: Props) => {
);
};
const fetchProfile = async () => {
- let data = await readProfileFile(profileUid);
- let mergeData = await readProfileFile(mergeUid);
- let globalMergeData = await readProfileFile("Merge");
+ const data = await readProfileFile(profileUid);
+ const mergeData = await readProfileFile(mergeUid);
+ const globalMergeData = await readProfileFile("Merge");
- let originGroupsObj = yaml.load(data) as {
+ const originGroupsObj = yaml.load(data) as {
"proxy-groups": IProxyGroupConfig[];
} | null;
- let originProviderObj = yaml.load(data) as { "proxy-providers": {} } | null;
- let originProvider = originProviderObj?.["proxy-providers"] || {};
-
- let moreProviderObj = yaml.load(mergeData) as {
+ const originProviderObj = yaml.load(data) as {
"proxy-providers": {};
} | null;
- let moreProvider = moreProviderObj?.["proxy-providers"] || {};
+ const originProvider = originProviderObj?.["proxy-providers"] || {};
- let globalProviderObj = yaml.load(globalMergeData) as {
+ const moreProviderObj = yaml.load(mergeData) as {
"proxy-providers": {};
} | null;
- let globalProvider = globalProviderObj?.["proxy-providers"] || {};
+ const moreProvider = moreProviderObj?.["proxy-providers"] || {};
- let provider = Object.assign(
+ const globalProviderObj = yaml.load(globalMergeData) as {
+ "proxy-providers": {};
+ } | null;
+ const globalProvider = globalProviderObj?.["proxy-providers"] || {};
+
+ const provider = Object.assign(
{},
originProvider,
moreProvider,
@@ -278,7 +280,7 @@ export const GroupsEditorViewer = (props: Props) => {
setGroupList(originGroupsObj?.["proxy-groups"] || []);
};
const getInterfaceNameList = async () => {
- let list = await getNetworkInterfaces();
+ const list = await getNetworkInterfaces();
setInterfaceNameList(list);
};
useEffect(() => {
@@ -293,7 +295,7 @@ export const GroupsEditorViewer = (props: Props) => {
}, [open]);
const validateGroup = () => {
- let group = formIns.getValues();
+ const group = formIns.getValues();
if (group.name === "") {
throw new Error(t("Group Name Required"));
}
@@ -794,7 +796,7 @@ export const GroupsEditorViewer = (props: Props) => {
}
increaseViewportBy={256}
itemContent={(index) => {
- let shift = filteredPrependSeq.length > 0 ? 1 : 0;
+ const shift = filteredPrependSeq.length > 0 ? 1 : 0;
if (filteredPrependSeq.length > 0 && index === 0) {
return (
{
);
} else if (index < filteredGroupList.length + shift) {
- let newIndex = index - shift;
+ const newIndex = index - shift;
return (
{
};
// 优化:异步分片解析,避免主线程阻塞,解析完成后批量setState
const handleParseAsync = (cb: (proxies: IProxyConfig[]) => void) => {
- let proxies: IProxyConfig[] = [];
- let names: string[] = [];
+ const proxies: IProxyConfig[] = [];
+ const names: string[] = [];
let uris = "";
try {
uris = atob(proxyUri);
@@ -148,7 +148,7 @@ export const ProxiesEditorViewer = (props: Props) => {
for (; idx < end; idx++) {
const uri = lines[idx];
try {
- let proxy = parseUri(uri.trim());
+ const proxy = parseUri(uri.trim());
if (!names.includes(proxy.name)) {
proxies.push(proxy);
names.push(proxy.name);
@@ -171,9 +171,9 @@ export const ProxiesEditorViewer = (props: Props) => {
parseBatch();
};
const fetchProfile = async () => {
- let data = await readProfileFile(profileUid);
+ const data = await readProfileFile(profileUid);
- let originProxiesObj = yaml.load(data) as {
+ const originProxiesObj = yaml.load(data) as {
proxies: IProxyConfig[];
} | null;
@@ -181,8 +181,8 @@ export const ProxiesEditorViewer = (props: Props) => {
};
const fetchContent = async () => {
- let data = await readProfileFile(property);
- let obj = yaml.load(data) as ISeqProfileConfig | null;
+ const data = await readProfileFile(property);
+ const obj = yaml.load(data) as ISeqProfileConfig | null;
setPrependSeq(obj?.prepend || []);
setAppendSeq(obj?.append || []);
@@ -196,7 +196,7 @@ export const ProxiesEditorViewer = (props: Props) => {
if (currData === "") return;
if (visualization !== true) return;
- let obj = yaml.load(currData) as {
+ const obj = yaml.load(currData) as {
prepend: [];
append: [];
delete: [];
@@ -342,7 +342,7 @@ export const ProxiesEditorViewer = (props: Props) => {
}
increaseViewportBy={256}
itemContent={(index) => {
- let shift = filteredPrependSeq.length > 0 ? 1 : 0;
+ const shift = filteredPrependSeq.length > 0 ? 1 : 0;
if (filteredPrependSeq.length > 0 && index === 0) {
return (
{
);
} else if (index < filteredProxyList.length + shift) {
- let newIndex = index - shift;
+ const newIndex = index - shift;
return (
{
- let { type, proxy, onDelete } = props;
+ const { type, proxy, onDelete } = props;
const sortable = type === "prepend" || type === "append";
const {
diff --git a/src/components/profile/rule-item.tsx b/src/components/profile/rule-item.tsx
index 7544a4a8..59bb34a0 100644
--- a/src/components/profile/rule-item.tsx
+++ b/src/components/profile/rule-item.tsx
@@ -16,7 +16,7 @@ interface Props {
}
export const RuleItem = (props: Props) => {
- let { type, ruleRaw, onDelete } = props;
+ const { type, ruleRaw, onDelete } = props;
const sortable = type === "prepend" || type === "append";
const rule = ruleRaw.replace(",no-resolve", "");
diff --git a/src/components/profile/rules-editor-viewer.tsx b/src/components/profile/rules-editor-viewer.tsx
index 5d165d51..0e950b42 100644
--- a/src/components/profile/rules-editor-viewer.tsx
+++ b/src/components/profile/rules-editor-viewer.tsx
@@ -287,8 +287,8 @@ export const RulesEditorViewer = (props: Props) => {
const { active, over } = event;
if (over) {
if (active.id !== over.id) {
- let activeIndex = prependSeq.indexOf(active.id.toString());
- let overIndex = prependSeq.indexOf(over.id.toString());
+ const activeIndex = prependSeq.indexOf(active.id.toString());
+ const overIndex = prependSeq.indexOf(over.id.toString());
setPrependSeq(reorder(prependSeq, activeIndex, overIndex));
}
}
@@ -297,15 +297,15 @@ export const RulesEditorViewer = (props: Props) => {
const { active, over } = event;
if (over) {
if (active.id !== over.id) {
- let activeIndex = appendSeq.indexOf(active.id.toString());
- let overIndex = appendSeq.indexOf(over.id.toString());
+ const activeIndex = appendSeq.indexOf(active.id.toString());
+ const overIndex = appendSeq.indexOf(over.id.toString());
setAppendSeq(reorder(appendSeq, activeIndex, overIndex));
}
}
};
const fetchContent = async () => {
- let data = await readProfileFile(property);
- let obj = yaml.load(data) as ISeqProfileConfig | null;
+ const data = await readProfileFile(property);
+ const obj = yaml.load(data) as ISeqProfileConfig | null;
setPrependSeq(obj?.prepend || []);
setAppendSeq(obj?.append || []);
@@ -319,7 +319,7 @@ export const RulesEditorViewer = (props: Props) => {
if (currData === "") return;
if (visualization !== true) return;
- let obj = yaml.load(currData) as ISeqProfileConfig | null;
+ const obj = yaml.load(currData) as ISeqProfileConfig | null;
setPrependSeq(obj?.prepend || []);
setAppendSeq(obj?.append || []);
setDeleteSeq(obj?.delete || []);
@@ -349,21 +349,21 @@ export const RulesEditorViewer = (props: Props) => {
}, [prependSeq, appendSeq, deleteSeq]);
const fetchProfile = async () => {
- let data = await readProfileFile(profileUid); // 原配置文件
- let groupsData = await readProfileFile(groupsUid); // groups配置文件
- let mergeData = await readProfileFile(mergeUid); // merge配置文件
- let globalMergeData = await readProfileFile("Merge"); // global merge配置文件
+ const data = await readProfileFile(profileUid); // 原配置文件
+ const groupsData = await readProfileFile(groupsUid); // groups配置文件
+ const mergeData = await readProfileFile(mergeUid); // merge配置文件
+ const globalMergeData = await readProfileFile("Merge"); // global merge配置文件
- let rulesObj = yaml.load(data) as { rules: [] } | null;
+ const rulesObj = yaml.load(data) as { rules: [] } | null;
- let originGroupsObj = yaml.load(data) as { "proxy-groups": [] } | null;
- let originGroups = originGroupsObj?.["proxy-groups"] || [];
- let moreGroupsObj = yaml.load(groupsData) as ISeqProfileConfig | null;
- let morePrependGroups = moreGroupsObj?.["prepend"] || [];
- let moreAppendGroups = moreGroupsObj?.["append"] || [];
- let moreDeleteGroups =
+ const originGroupsObj = yaml.load(data) as { "proxy-groups": [] } | null;
+ const originGroups = originGroupsObj?.["proxy-groups"] || [];
+ const moreGroupsObj = yaml.load(groupsData) as ISeqProfileConfig | null;
+ const morePrependGroups = moreGroupsObj?.["prepend"] || [];
+ const moreAppendGroups = moreGroupsObj?.["append"] || [];
+ const moreDeleteGroups =
moreGroupsObj?.["delete"] || ([] as string[] | { name: string }[]);
- let groups = morePrependGroups.concat(
+ const groups = morePrependGroups.concat(
originGroups.filter((group: any) => {
if (group.name) {
return !moreDeleteGroups.includes(group.name);
@@ -374,27 +374,37 @@ export const RulesEditorViewer = (props: Props) => {
moreAppendGroups,
);
- let originRuleSetObj = yaml.load(data) as { "rule-providers": {} } | null;
- let originRuleSet = originRuleSetObj?.["rule-providers"] || {};
- let moreRuleSetObj = yaml.load(mergeData) as {
+ const originRuleSetObj = yaml.load(data) as { "rule-providers": {} } | null;
+ const originRuleSet = originRuleSetObj?.["rule-providers"] || {};
+ const moreRuleSetObj = yaml.load(mergeData) as {
"rule-providers": {};
} | null;
- let moreRuleSet = moreRuleSetObj?.["rule-providers"] || {};
- let globalRuleSetObj = yaml.load(globalMergeData) as {
+ const moreRuleSet = moreRuleSetObj?.["rule-providers"] || {};
+ const globalRuleSetObj = yaml.load(globalMergeData) as {
"rule-providers": {};
} | null;
- let globalRuleSet = globalRuleSetObj?.["rule-providers"] || {};
- let ruleSet = Object.assign({}, originRuleSet, moreRuleSet, globalRuleSet);
+ const globalRuleSet = globalRuleSetObj?.["rule-providers"] || {};
+ const ruleSet = Object.assign(
+ {},
+ originRuleSet,
+ moreRuleSet,
+ globalRuleSet,
+ );
- let originSubRuleObj = yaml.load(data) as { "sub-rules": {} } | null;
- let originSubRule = originSubRuleObj?.["sub-rules"] || {};
- let moreSubRuleObj = yaml.load(mergeData) as { "sub-rules": {} } | null;
- let moreSubRule = moreSubRuleObj?.["sub-rules"] || {};
- let globalSubRuleObj = yaml.load(globalMergeData) as {
+ const originSubRuleObj = yaml.load(data) as { "sub-rules": {} } | null;
+ const originSubRule = originSubRuleObj?.["sub-rules"] || {};
+ const moreSubRuleObj = yaml.load(mergeData) as { "sub-rules": {} } | null;
+ const moreSubRule = moreSubRuleObj?.["sub-rules"] || {};
+ const globalSubRuleObj = yaml.load(globalMergeData) as {
"sub-rules": {};
} | null;
- let globalSubRule = globalSubRuleObj?.["sub-rules"] || {};
- let subRule = Object.assign({}, originSubRule, moreSubRule, globalSubRule);
+ const globalSubRule = globalSubRuleObj?.["sub-rules"] || {};
+ const subRule = Object.assign(
+ {},
+ originSubRule,
+ moreSubRule,
+ globalSubRule,
+ );
setProxyPolicyList(
builtinProxyPolicies.concat(groups.map((group: any) => group.name)),
);
@@ -554,7 +564,7 @@ export const RulesEditorViewer = (props: Props) => {
startIcon={}
onClick={() => {
try {
- let raw = validateRule();
+ const raw = validateRule();
if (prependSeq.includes(raw)) return;
setPrependSeq([raw, ...prependSeq]);
} catch (err: any) {
@@ -572,7 +582,7 @@ export const RulesEditorViewer = (props: Props) => {
startIcon={}
onClick={() => {
try {
- let raw = validateRule();
+ const raw = validateRule();
if (appendSeq.includes(raw)) return;
setAppendSeq([...appendSeq, raw]);
} catch (err: any) {
@@ -601,7 +611,7 @@ export const RulesEditorViewer = (props: Props) => {
}
increaseViewportBy={256}
itemContent={(index) => {
- let shift = filteredPrependSeq.length > 0 ? 1 : 0;
+ const shift = filteredPrependSeq.length > 0 ? 1 : 0;
if (filteredPrependSeq.length > 0 && index === 0) {
return (
{
);
} else if (index < filteredRuleList.length + shift) {
- let newIndex = index - shift;
+ const newIndex = index - shift;
return (
((props, ref) => {
const formatHosts = (hosts: any): string => {
if (!hosts || typeof hosts !== "object") return "";
- let result: string[] = [];
+ const result: string[] = [];
Object.entries(hosts).forEach(([domain, value]) => {
if (Array.isArray(value)) {
diff --git a/src/components/setting/mods/tun-viewer.tsx b/src/components/setting/mods/tun-viewer.tsx
index be0d64a3..3468f34a 100644
--- a/src/components/setting/mods/tun-viewer.tsx
+++ b/src/components/setting/mods/tun-viewer.tsx
@@ -53,7 +53,7 @@ export const TunViewer = forwardRef((props, ref) => {
const onSave = useLockFn(async () => {
try {
- let tun = {
+ const tun = {
stack: values.stack,
device:
values.device === ""
@@ -97,7 +97,7 @@ export const TunViewer = forwardRef((props, ref) => {
variant="outlined"
size="small"
onClick={async () => {
- let tun = {
+ const tun = {
stack: "gvisor",
device: OS === "macos" ? "utun1024" : "Mihomo",
"auto-route": true,
diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx
index 22e34287..b44e3983 100644
--- a/src/pages/_layout.tsx
+++ b/src/pages/_layout.tsx
@@ -34,7 +34,7 @@ import { useLocalStorage } from "foxact/use-local-storage";
import { LogLevel } from "@/hooks/use-log-data";
const appWindow = getCurrentWebviewWindow();
-export let portableFlag = false;
+export const portableFlag = false;
dayjs.extend(relativeTime);
diff --git a/src/pages/profiles.tsx b/src/pages/profiles.tsx
index 1e7540a4..a873a124 100644
--- a/src/pages/profiles.tsx
+++ b/src/pages/profiles.tsx
@@ -166,7 +166,7 @@ const ProfilePage = () => {
async (event: any) => {
const paths = event.payload.paths;
- for (let file of paths) {
+ for (const file of paths) {
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) {
showNotice("error", t("Only YAML Files Supported"));
continue;
@@ -181,7 +181,7 @@ const ProfilePage = () => {
self_proxy: false,
},
} as IProfileItem;
- let data = await readTextFile(file);
+ const data = await readTextFile(file);
await createProfile(item, data);
await mutateProfiles();
}
diff --git a/src/pages/test.tsx b/src/pages/test.tsx
index b77aed37..45797f6b 100644
--- a/src/pages/test.tsx
+++ b/src/pages/test.tsx
@@ -101,12 +101,12 @@ const TestPage = () => {
const { active, over } = event;
if (over) {
if (active.id !== over.id) {
- let old_index = testList.findIndex((x) => x.uid === active.id);
- let new_index = testList.findIndex((x) => x.uid === over.id);
+ const old_index = testList.findIndex((x) => x.uid === active.id);
+ const new_index = testList.findIndex((x) => x.uid === over.id);
if (old_index < 0 || new_index < 0) {
return;
}
- let newList = reorder(testList, old_index, new_index);
+ const newList = reorder(testList, old_index, new_index);
await mutateVerge({ ...verge, test_list: newList }, false);
await patchVerge({ test_list: newList });
}
diff --git a/src/services/cmds.ts b/src/services/cmds.ts
index fc875aff..04e7bd6f 100644
--- a/src/services/cmds.ts
+++ b/src/services/cmds.ts
@@ -217,20 +217,19 @@ export async function getProxies(): Promise<{
}, []);
if (global?.all) {
- let globalGroups: IProxyGroupItem[] = global.all.reduce(
- (acc, name) => {
- if (proxyRecord[name]?.all) {
- acc.push({
- ...proxyRecord[name],
- all: proxyRecord[name].all!.map((item) => generateItem(item)),
- });
- }
- return acc;
- },
- [],
- );
+ const globalGroups: IProxyGroupItem[] = global.all.reduce<
+ IProxyGroupItem[]
+ >((acc, name) => {
+ if (proxyRecord[name]?.all) {
+ acc.push({
+ ...proxyRecord[name],
+ all: proxyRecord[name].all!.map((item) => generateItem(item)),
+ });
+ }
+ return acc;
+ }, []);
- let globalNames = new Set(globalGroups.map((each) => each.name));
+ const globalNames = new Set(globalGroups.map((each) => each.name));
groups = groups
.filter((group) => {
return !globalNames.has(group.name);
@@ -674,7 +673,7 @@ export async function saveWebdavConfig(
}
export async function listWebDavBackup() {
- let list: IWebDavFile[] = await invoke("list_webdav_backup");
+ const list: IWebDavFile[] = await invoke("list_webdav_backup");
list.map((item) => {
item.filename = item.href.split("/").pop() as string;
});
diff --git a/src/utils/uri-parser.ts b/src/utils/uri-parser.ts
index 0dfd3fd8..b25696dc 100644
--- a/src/utils/uri-parser.ts
+++ b/src/utils/uri-parser.ts
@@ -172,7 +172,7 @@ function URI_SS(line: string): IProxyShadowsocksConfig {
if (query) {
if (/(&|\?)v2ray-plugin=/.test(query)) {
const parsed = query.match(/(&|\?)v2ray-plugin=(.*?)(&|$)/);
- let v2rayPlugin = parsed![2];
+ const v2rayPlugin = parsed![2];
if (v2rayPlugin) {
proxy.plugin = "v2ray-plugin";
proxy["plugin-opts"] = JSON.parse(
@@ -251,7 +251,7 @@ function URI_SSR(line: string): IProxyshadowsocksRConfig {
serverAndPort.substring(serverAndPort.lastIndexOf(":") + 1),
);
- let params = line
+ const params = line
.substring(splitIdx + 1)
.split("/?")[0]
.split(":");
@@ -354,7 +354,7 @@ function URI_VMESS(line: string): IProxyVmessConfig {
);
const match = /(^[^?]+?)\/?\?(.*)$/.exec(line);
if (match) {
- let [_, base64Line, qs] = match;
+ const [_, base64Line, qs] = match;
content = decodeBase64OrOriginal(base64Line);
for (const addon of qs.split("&")) {
@@ -370,7 +370,7 @@ function URI_VMESS(line: string): IProxyVmessConfig {
const contentMatch = /(^[^:]+?):([^:]+?)@(.*):(\d+)$/.exec(content);
if (contentMatch) {
- let [__, cipher, uuid, server, port] = contentMatch;
+ const [__, cipher, uuid, server, port] = contentMatch;
params.scy = cipher;
params.id = uuid;
@@ -501,7 +501,7 @@ function URI_VLESS(line: string): IProxyVlessConfig {
let isShadowrocket;
let parsed = /^(.*?)@(.*?):(\d+)\/?(\?(.*?))?(?:#(.*?))?$/.exec(line)!;
if (!parsed) {
- let [_, base64, other] = /^(.*?)(\?.*?$)/.exec(line)!;
+ const [_, base64, other] = /^(.*?)(\?.*?$)/.exec(line)!;
line = `${atob(base64)}${other}`;
parsed = /^(.*?)@(.*?):(\d+)\/?(\?(.*?))?(?:#(.*?))?$/.exec(line)!;
isShadowrocket = true;
@@ -636,7 +636,7 @@ function URI_VLESS(line: string): IProxyVlessConfig {
if (proxy.network === "ws") {
proxy.servername = proxy["ws-opts"]?.headers?.Host;
} else if (proxy.network === "http") {
- let httpHost = proxy["http-opts"]?.headers?.Host;
+ const httpHost = proxy["http-opts"]?.headers?.Host;
proxy.servername = Array.isArray(httpHost) ? httpHost[0] : httpHost;
}
}
@@ -655,7 +655,7 @@ function URI_Trojan(line: string): IProxyTrojanConfig {
password = decodeURIComponent(password);
- let decodedName = trimStr(decodeURIComponent(name));
+ const decodedName = trimStr(decodeURIComponent(name));
name = decodedName ?? `Trojan ${server}:${portNum}`;
const proxy: IProxyTrojanConfig = {
@@ -701,7 +701,7 @@ function URI_Trojan(line: string): IProxyTrojanConfig {
proxy["fingerprint"] = value;
break;
case "encryption":
- let encryption = value.split(";");
+ const encryption = value.split(";");
if (encryption.length === 3) {
proxy["ss-opts"] = {
enabled: true,
@@ -741,7 +741,7 @@ function URI_Hysteria2(line: string): IProxyHysteria2Config {
}
password = decodeURIComponent(password);
- let decodedName = trimStr(decodeURIComponent(name));
+ const decodedName = trimStr(decodeURIComponent(name));
name = decodedName ?? `Hysteria2 ${server}:${port}`;
@@ -786,7 +786,7 @@ function URI_Hysteria(line: string): IProxyHysteriaConfig {
if (isNaN(portNum)) {
portNum = 443;
}
- let decodedName = trimStr(decodeURIComponent(name));
+ const decodedName = trimStr(decodeURIComponent(name));
name = decodedName ?? `Hysteria ${server}:${port}`;
@@ -884,7 +884,7 @@ function URI_TUIC(line: string): IProxyTuicConfig {
portNum = 443;
}
password = decodeURIComponent(password);
- let decodedName = trimStr(decodeURIComponent(name));
+ const decodedName = trimStr(decodeURIComponent(name));
name = decodedName ?? `TUIC ${server}:${port}`;
@@ -963,7 +963,7 @@ function URI_Wireguard(line: string): IProxyWireguardConfig {
portNum = 443;
}
privateKey = decodeURIComponent(privateKey);
- let decodedName = trimStr(decodeURIComponent(name));
+ const decodedName = trimStr(decodeURIComponent(name));
name = decodedName ?? `WireGuard ${server}:${port}`;
const proxy: IProxyWireguardConfig = {
@@ -1047,7 +1047,7 @@ function URI_HTTP(line: string): IProxyHttpConfig {
if (auth) {
auth = decodeURIComponent(auth);
}
- let decodedName = trimStr(decodeURIComponent(name));
+ const decodedName = trimStr(decodeURIComponent(name));
name = decodedName ?? `HTTP ${server}:${portNum}`;
const proxy: IProxyHttpConfig = {
@@ -1111,7 +1111,7 @@ function URI_SOCKS(line: string): IProxySocks5Config {
if (auth) {
auth = decodeURIComponent(auth);
}
- let decodedName = trimStr(decodeURIComponent(name));
+ const decodedName = trimStr(decodeURIComponent(name));
name = decodedName ?? `SOCKS5 ${server}:${portNum}`;
const proxy: IProxySocks5Config = {
type: "socks5",