From de837c034acf7e6ab55023f948d9ebe8c749c2c4 Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Mon, 16 Jun 2025 20:38:15 +0200 Subject: [PATCH] Update On Mon Jun 16 20:38:15 CEST 2025 --- .github/update.log | 1 + .../frontend/interface/package.json | 2 +- clash-nyanpasu/frontend/nyanpasu/package.json | 10 +- clash-nyanpasu/frontend/ui/package.json | 4 +- clash-nyanpasu/manifest/version.json | 4 +- clash-nyanpasu/pnpm-lock.yaml | 443 ++++++++++----- clash-verge-rev/UPDATELOG.md | 33 +- .../src-tauri/src/cmd/save_profile.rs | 79 ++- clash-verge-rev/src-tauri/src/cmd/validate.rs | 48 +- clash-verge-rev/src-tauri/src/config/verge.rs | 95 +++- clash-verge-rev/src-tauri/src/core/core.rs | 13 +- clash-verge-rev/src-tauri/src/core/service.rs | 3 +- clash-verge-rev/src-tauri/src/enhance/mod.rs | 2 +- .../src-tauri/src/enhance/script.rs | 102 +--- clash-verge-rev/src-tauri/src/feat/clash.rs | 2 +- clash-verge-rev/src-tauri/src/feat/profile.rs | 30 +- clash-verge-rev/src-tauri/src/feat/window.rs | 49 +- clash-verge-rev/src-tauri/src/lib.rs | 2 +- clash-verge-rev/src-tauri/src/utils/init.rs | 3 + .../setting/mods/controller-viewer.tsx | 11 +- filebrowser/CHANGELOG.md | 25 + .../src/components/settings/Languages.vue | 1 + filebrowser/frontend/src/i18n/index.ts | 4 + filebrowser/frontend/src/i18n/ko.json | 248 +++++---- filebrowser/frontend/src/i18n/pt-br.json | 33 +- filebrowser/frontend/src/i18n/vi.json | 265 +++++++++ .../arch/arm64/boot/dts/qcom/ipq5018-ess.dtsi | 2 + .../arm64/boot/dts/qcom/ipq5018-gl-b3000.dts | 516 +++++++++--------- .../arm64/boot/dts/qcom/ipq5018-mr5500.dts | 379 +++++++++++++ .../arm64/boot/dts/qcom/ipq5018-mx-base.dtsi | 6 - .../arm64/boot/dts/qcom/ipq5018-mx2000.dts | 16 +- .../arm64/boot/dts/qcom/ipq5018-mx5500.dts | 21 +- .../arm64/boot/dts/qcom/ipq5018-spnmx56.dts | 235 ++++++++ lede/target/linux/qualcommax/image/ipq50xx.mk | 57 +- .../ipq50xx/base-files/etc/board.d/02_network | 12 +- .../etc/hotplug.d/firmware/11-ath11k-caldata | 28 +- .../ipq50xx/base-files/etc/init.d/bootcount | 4 +- .../base-files/lib/upgrade/platform.sh | 80 ++- .../.github/workflows/compile_meta_core.yml | 449 ++++++++++++--- .../.github/workflows/master_release_sync.yml | 5 +- .../luasrc/controller/openclash.lua | 22 +- .../luasrc/view/openclash/select_git_cdn.htm | 40 +- .../luasrc/view/openclash/update.htm | 72 ++- .../po/zh-cn/openclash.zh-cn.po | 16 +- .../root/etc/config/openclash | 1 + .../usr/share/openclash/openclash_core.sh | 36 +- .../crates/shadowsocks/src/net/udp.rs | 14 + .../luasrc/controller/openclash.lua | 22 +- .../luasrc/view/openclash/select_git_cdn.htm | 40 +- .../luasrc/view/openclash/update.htm | 72 ++- .../po/zh-cn/openclash.zh-cn.po | 16 +- .../root/etc/config/openclash | 1 + .../usr/share/openclash/openclash_core.sh | 36 +- small/v2ray-geodata/Makefile | 4 +- .../ViewModels/StatusBarViewModel.cs | 12 +- .../Views/ProfilesView.axaml.cs | 20 +- v2rayu/Build/build.sh | 10 +- 57 files changed, 2762 insertions(+), 994 deletions(-) create mode 100644 filebrowser/frontend/src/i18n/vi.json create mode 100644 lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mr5500.dts create mode 100644 lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-spnmx56.dts diff --git a/.github/update.log b/.github/update.log index c5ff32f50f..769adc2fa3 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1029,3 +1029,4 @@ Update On Wed Jun 11 20:39:57 CEST 2025 Update On Fri Jun 13 20:38:23 CEST 2025 Update On Sat Jun 14 20:35:08 CEST 2025 Update On Sun Jun 15 20:35:35 CEST 2025 +Update On Mon Jun 16 20:38:07 CEST 2025 diff --git a/clash-nyanpasu/frontend/interface/package.json b/clash-nyanpasu/frontend/interface/package.json index fa06996d49..ae818f5612 100644 --- a/clash-nyanpasu/frontend/interface/package.json +++ b/clash-nyanpasu/frontend/interface/package.json @@ -11,7 +11,7 @@ "build": "tsc" }, "dependencies": { - "@tanstack/react-query": "5.80.6", + "@tanstack/react-query": "5.80.7", "@tauri-apps/api": "2.5.0", "ahooks": "3.8.5", "dayjs": "1.11.13", diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 3de2a05a98..9b04b4acf2 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -18,7 +18,7 @@ "@material/material-color-utilities": "0.3.0", "@mui/icons-material": "7.1.1", "@mui/lab": "7.0.0-beta.13", - "@mui/x-date-pickers": "8.5.1", + "@mui/x-date-pickers": "8.5.2", "@mui/material": "7.1.1", "@nyanpasu/interface": "workspace:^", "@nyanpasu/ui": "workspace:^", @@ -27,7 +27,7 @@ "@tauri-apps/api": "2.5.0", "@types/json-schema": "7.0.15", "ahooks": "3.8.5", - "allotment": "1.20.3", + "allotment": "1.20.4", "country-code-emoji": "2.3.0", "country-emoji": "1.5.6", "dayjs": "1.11.13", @@ -57,7 +57,7 @@ "@emotion/react": "11.14.0", "@iconify/json": "2.2.349", "@monaco-editor/react": "4.7.0", - "@tanstack/react-query": "5.80.6", + "@tanstack/react-query": "5.80.7", "@tanstack/react-router": "1.120.20", "@tanstack/react-router-devtools": "1.120.20", "@tanstack/router-plugin": "1.120.20", @@ -73,8 +73,8 @@ "@types/react-dom": "19.1.6", "@types/validator": "13.15.1", "@vitejs/plugin-legacy": "6.1.1", - "@vitejs/plugin-react": "4.5.1", - "@vitejs/plugin-react-swc": "3.10.1", + "@vitejs/plugin-react": "4.5.2", + "@vitejs/plugin-react-swc": "3.10.2", "change-case": "5.4.4", "clsx": "2.1.1", "core-js": "3.42.0", diff --git a/clash-nyanpasu/frontend/ui/package.json b/clash-nyanpasu/frontend/ui/package.json index 5c64080081..e9d9cf03eb 100644 --- a/clash-nyanpasu/frontend/ui/package.json +++ b/clash-nyanpasu/frontend/ui/package.json @@ -20,7 +20,7 @@ "@tauri-apps/api": "2.5.0", "@types/d3": "7.4.3", "@types/react": "19.1.6", - "@vitejs/plugin-react": "4.5.1", + "@vitejs/plugin-react": "4.5.2", "ahooks": "3.8.5", "d3": "7.9.0", "framer-motion": "12.16.0", @@ -39,7 +39,7 @@ "clsx": "2.1.1", "d3-interpolate-path": "2.3.0", "sass-embedded": "1.88.0", - "tailwind-merge": "3.3.0", + "tailwind-merge": "3.3.1", "typescript-plugin-css-modules": "5.1.0", "vite-plugin-dts": "4.5.4" } diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 4bcd1f95a0..cbbc76c65d 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -5,7 +5,7 @@ "mihomo_alpha": "alpha-c60750d", "clash_rs": "v0.8.0", "clash_premium": "2023-09-05-gdcc8d87", - "clash_rs_alpha": "0.8.0-alpha+sha.22dc4d9" + "clash_rs_alpha": "0.8.0-alpha+sha.74dba39" }, "arch_template": { "mihomo": { @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-06-14T22:21:02.626Z" + "updated_at": "2025-06-15T22:21:05.509Z" } diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index a0dce6744a..506014829b 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -173,8 +173,8 @@ importers: frontend/interface: dependencies: '@tanstack/react-query': - specifier: 5.80.6 - version: 5.80.6(react@19.1.0) + specifier: 5.80.7 + version: 5.80.7(react@19.1.0) '@tauri-apps/api': specifier: 2.5.0 version: 2.5.0 @@ -234,8 +234,8 @@ importers: specifier: 7.1.1 version: 7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@mui/x-date-pickers': - specifier: 8.5.1 - version: 8.5.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 8.5.2 + version: 8.5.2(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@nyanpasu/interface': specifier: workspace:^ version: link:../interface @@ -258,8 +258,8 @@ importers: specifier: 3.8.5 version: 3.8.5(react@19.1.0) allotment: - specifier: 1.20.3 - version: 1.20.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 1.20.4 + version: 1.20.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) country-code-emoji: specifier: 2.3.0 version: 2.3.0 @@ -283,7 +283,7 @@ importers: version: 0.4.0 material-react-table: specifier: npm:@greenhat616/material-react-table@4.0.0 - version: '@greenhat616/material-react-table@4.0.0(f792f3152d47990021a35f343160b990)' + version: '@greenhat616/material-react-table@4.0.0(1200cdc8a1e411f19b648bfe23908224)' monaco-editor: specifier: 0.52.2 version: 0.52.2 @@ -304,7 +304,7 @@ importers: version: 1.6.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-hook-form-mui: specifier: 7.6.1 - version: 7.6.1(d57264b30a79ce6f9a19367b42c73611) + version: 7.6.1(a709df8d501e7bdf4d7009cd73340429) react-i18next: specifier: 15.5.2 version: 15.5.2(i18next@25.2.1(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3) @@ -343,8 +343,8 @@ importers: specifier: 4.7.0 version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@tanstack/react-query': - specifier: 5.80.6 - version: 5.80.6(react@19.1.0) + specifier: 5.80.7 + version: 5.80.7(react@19.1.0) '@tanstack/react-router': specifier: 1.120.20 version: 1.120.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -391,11 +391,11 @@ importers: specifier: 6.1.1 version: 6.1.1(terser@5.36.0)(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0)) '@vitejs/plugin-react': - specifier: 4.5.1 - version: 4.5.1(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0)) + specifier: 4.5.2 + version: 4.5.2(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0)) '@vitejs/plugin-react-swc': - specifier: 3.10.1 - version: 3.10.1(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0)) + specifier: 3.10.2 + version: 3.10.2(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0)) change-case: specifier: 5.4.4 version: 5.4.4 @@ -481,8 +481,8 @@ importers: specifier: 19.1.6 version: 19.1.6 '@vitejs/plugin-react': - specifier: 4.5.1 - version: 4.5.1(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0)) + specifier: 4.5.2 + version: 4.5.2(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0)) ahooks: specifier: 3.8.5 version: 3.8.5(react@19.1.0) @@ -533,8 +533,8 @@ importers: specifier: 1.88.0 version: 1.88.0 tailwind-merge: - specifier: 3.3.0 - version: 3.3.0 + specifier: 3.3.1 + version: 3.3.1 typescript-plugin-css-modules: specifier: 5.1.0 version: 5.1.0(typescript@5.8.3) @@ -648,14 +648,26 @@ packages: resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.26.8': resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.27.5': + resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==} + engines: {node: '>=6.9.0'} + '@babel/core@7.26.10': resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} engines: {node: '>=6.9.0'} + '@babel/core@7.27.4': + resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.17.7': resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} engines: {node: '>=6.9.0'} @@ -664,6 +676,10 @@ packages: resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==} engines: {node: '>=6.9.0'} + '@babel/generator@7.27.5': + resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} + engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.25.9': resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} @@ -672,6 +688,10 @@ packages: resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-create-class-features-plugin@7.25.9': resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==} engines: {node: '>=6.9.0'} @@ -709,12 +729,22 @@ packages: resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-transforms@7.26.0': resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-optimise-call-expression@7.25.9': resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} engines: {node: '>=6.9.0'} @@ -723,6 +753,10 @@ packages: resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} engines: {node: '>=6.9.0'} + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + '@babel/helper-remap-async-to-generator@7.25.9': resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} engines: {node: '>=6.9.0'} @@ -747,14 +781,26 @@ packages: resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.25.9': resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.9': resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + '@babel/helper-wrap-function@7.25.9': resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} engines: {node: '>=6.9.0'} @@ -763,11 +809,20 @@ packages: resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} engines: {node: '>=6.9.0'} + '@babel/helpers@7.27.6': + resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.27.0': resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.27.5': + resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} engines: {node: '>=6.9.0'} @@ -1069,14 +1124,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-self@7.25.9': - resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-source@7.25.9': - resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1180,6 +1235,10 @@ packages: resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.23.2': resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} engines: {node: '>=6.9.0'} @@ -1192,6 +1251,10 @@ packages: resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.27.4': + resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==} + engines: {node: '>=6.9.0'} + '@babel/types@7.17.0': resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==} engines: {node: '>=6.9.0'} @@ -1204,6 +1267,10 @@ packages: resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} engines: {node: '>=6.9.0'} + '@babel/types@7.27.6': + resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} + engines: {node: '>=6.9.0'} + '@bufbuild/protobuf@2.2.3': resolution: {integrity: sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==} @@ -1834,8 +1901,8 @@ packages: '@types/react': optional: true - '@mui/x-date-pickers@8.5.1': - resolution: {integrity: sha512-sZXL7FhOcWvlSZTjffEwUs6aOJlGu7gAGUpaaQHWlOK6eTQyTKlQEVRy7CJdk1SBO9K6T5tmSMAI6hKBDforDQ==} + '@mui/x-date-pickers@8.5.2': + resolution: {integrity: sha512-KN0GK5aVetGFB3n4W7XsUI79uTSxftTEhHtDCdQjOOeri2lZSY55MVn/CeYZdpuWlBOD1eTLPtCFzueeUp3m6g==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.9.0 @@ -1871,8 +1938,8 @@ packages: moment-jalaali: optional: true - '@mui/x-internals@8.5.1': - resolution: {integrity: sha512-7rAWK7SB6FxEIXKgsHsJjIzeeKOLxFJ16gePgZVWlvyew+xDb4P0fgjwW3ThcJjgvkUm0UhGGfLh/JP8l514IA==} + '@mui/x-internals@8.5.2': + resolution: {integrity: sha512-5YhB2AekK7G8d0YrAjg3WNf0uy3V73JD98WNxJhbIlCraQgl8QOQzr2zNO7MAf/X7mZQtjpjuAsiG3+gI2NVyg==} engines: {node: '>=14.0.0'} peerDependencies: '@mui/system': ^5.15.14 || ^6.0.0 || ^7.0.0 @@ -2316,8 +2383,8 @@ packages: '@types/react': optional: true - '@rolldown/pluginutils@1.0.0-beta.9': - resolution: {integrity: sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==} + '@rolldown/pluginutils@1.0.0-beta.11': + resolution: {integrity: sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==} '@rollup/pluginutils@4.2.1': resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} @@ -2565,68 +2632,68 @@ packages: peerDependencies: '@svgr/core': '*' - '@swc/core-darwin-arm64@1.11.29': - resolution: {integrity: sha512-whsCX7URzbuS5aET58c75Dloby3Gtj/ITk2vc4WW6pSDQKSPDuONsIcZ7B2ng8oz0K6ttbi4p3H/PNPQLJ4maQ==} + '@swc/core-darwin-arm64@1.12.1': + resolution: {integrity: sha512-nUjWVcJ3YS2N40ZbKwYO2RJ4+o2tWYRzNOcIQp05FqW0+aoUCVMdAUUzQinPDynfgwVshDAXCKemY8X7nN5MaA==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.11.29': - resolution: {integrity: sha512-S3eTo/KYFk+76cWJRgX30hylN5XkSmjYtCBnM4jPLYn7L6zWYEPajsFLmruQEiTEDUg0gBEWLMNyUeghtswouw==} + '@swc/core-darwin-x64@1.12.1': + resolution: {integrity: sha512-OGm4a4d3OeJn+tRt8H/eiHgTFrJbS6r8mi/Ob65tAEXZGHN900T2kR7c5ALr0V2hBOQ8BfhexwPoQlGQP/B95w==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.11.29': - resolution: {integrity: sha512-o9gdshbzkUMG6azldHdmKklcfrcMx+a23d/2qHQHPDLUPAN+Trd+sDQUYArK5Fcm7TlpG4sczz95ghN0DMkM7g==} + '@swc/core-linux-arm-gnueabihf@1.12.1': + resolution: {integrity: sha512-76YeeQKyK0EtNkQiNBZ0nbVGooPf9IucY0WqVXVpaU4wuG7ZyLEE2ZAIgXafIuzODGQoLfetue7I8boMxh1/MA==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.11.29': - resolution: {integrity: sha512-sLoaciOgUKQF1KX9T6hPGzvhOQaJn+3DHy4LOHeXhQqvBgr+7QcZ+hl4uixPKTzxk6hy6Hb0QOvQEdBAAR1gXw==} + '@swc/core-linux-arm64-gnu@1.12.1': + resolution: {integrity: sha512-BxJDIJPq1+aCh9UsaSAN6wo3tuln8UhNXruOrzTI8/ElIig/3sAueDM6Eq7GvZSGGSA7ljhNATMJ0elD7lFatQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.11.29': - resolution: {integrity: sha512-PwjB10BC0N+Ce7RU/L23eYch6lXFHz7r3NFavIcwDNa/AAqywfxyxh13OeRy+P0cg7NDpWEETWspXeI4Ek8otw==} + '@swc/core-linux-arm64-musl@1.12.1': + resolution: {integrity: sha512-NhLdbffSXvY0/FwUSAl4hKBlpe5GHQGXK8DxTo3HHjLsD9sCPYieo3vG0NQoUYAy4ZUY1WeGjyxeq4qZddJzEQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.11.29': - resolution: {integrity: sha512-i62vBVoPaVe9A3mc6gJG07n0/e7FVeAvdD9uzZTtGLiuIfVfIBta8EMquzvf+POLycSk79Z6lRhGPZPJPYiQaA==} + '@swc/core-linux-x64-gnu@1.12.1': + resolution: {integrity: sha512-CrYnV8SZIgArQ9LKH0xEF95PKXzX9WkRSc5j55arOSBeDCeDUQk1Bg/iKdnDiuj5HC1hZpvzwMzSBJjv+Z70jA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.11.29': - resolution: {integrity: sha512-YER0XU1xqFdK0hKkfSVX1YIyCvMDI7K07GIpefPvcfyNGs38AXKhb2byySDjbVxkdl4dycaxxhRyhQ2gKSlsFQ==} + '@swc/core-linux-x64-musl@1.12.1': + resolution: {integrity: sha512-BQMl3d0HaGB0/h2xcKlGtjk/cGRn2tnbsaChAKcjFdCepblKBCz1pgO/mL7w5iXq3s57wMDUn++71/a5RAkZOA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.11.29': - resolution: {integrity: sha512-po+WHw+k9g6FAg5IJ+sMwtA/fIUL3zPQ4m/uJgONBATCVnDDkyW6dBA49uHNVtSEvjvhuD8DVWdFP847YTcITw==} + '@swc/core-win32-arm64-msvc@1.12.1': + resolution: {integrity: sha512-b7NeGnpqTfmIGtUqXBl0KqoSmOnH64nRZoT5l4BAGdvwY7nxitWR94CqZuwyLPty/bLywmyDA9uO12Kvgb3+gg==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.11.29': - resolution: {integrity: sha512-h+NjOrbqdRBYr5ItmStmQt6x3tnhqgwbj9YxdGPepbTDamFv7vFnhZR0YfB3jz3UKJ8H3uGJ65Zw1VsC+xpFkg==} + '@swc/core-win32-ia32-msvc@1.12.1': + resolution: {integrity: sha512-iU/29X2D7cHBp1to62cUg/5Xk8K+lyOJiKIGGW5rdzTW/c2zz3d/ehgpzVP/rqC4NVr88MXspqHU4il5gmDajw==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.11.29': - resolution: {integrity: sha512-Q8cs2BDV9wqDvqobkXOYdC+pLUSEpX/KvI0Dgfun1F+LzuLotRFuDhrvkU9ETJA6OnD2+Fn/ieHgloiKA/Mn/g==} + '@swc/core-win32-x64-msvc@1.12.1': + resolution: {integrity: sha512-+Zh+JKDwiFqV5N9yAd2DhYVGPORGh9cfenu1ptr9yge+eHAf7vZJcC3rnj6QMR1QJh0Y5VC9+YBjRFjZVA7XDw==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.11.29': - resolution: {integrity: sha512-g4mThMIpWbNhV8G2rWp5a5/Igv8/2UFRJx2yImrLGMgrDDYZIopqZ/z0jZxDgqNA1QDx93rpwNF7jGsxVWcMlA==} + '@swc/core@1.12.1': + resolution: {integrity: sha512-aKXdDTqxTVFl/bKQZ3EQUjEMBEoF6JBv29moMZq0kbVO43na6u/u+3Vcbhbrh+A2N0X5OL4RaveuWfAjEgOmeA==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -2637,8 +2704,8 @@ packages: '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - '@swc/types@0.1.21': - resolution: {integrity: sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==} + '@swc/types@0.1.23': + resolution: {integrity: sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==} '@szmarczak/http-timer@4.0.6': resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} @@ -2740,11 +2807,11 @@ packages: resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} engines: {node: '>=12'} - '@tanstack/query-core@5.80.6': - resolution: {integrity: sha512-nl7YxT/TAU+VTf+e2zTkObGTyY8YZBMnbgeA1ee66lIVqzKlYursAII6z5t0e6rXgwUMJSV4dshBTNacNpZHbQ==} + '@tanstack/query-core@5.80.7': + resolution: {integrity: sha512-s09l5zeUKC8q7DCCCIkVSns8zZrK4ZDT6ryEjxNBFi68G4z2EBobBS7rdOY3r6W1WbUDpc1fe5oY+YO/+2UVUg==} - '@tanstack/react-query@5.80.6': - resolution: {integrity: sha512-izX+5CnkpON3NQGcEm3/d7LfFQNo9ZpFtX2QsINgCYK9LT2VCIdi8D3bMaMSNhrAJCznRoAkFic76uvLroALBw==} + '@tanstack/react-query@5.80.7': + resolution: {integrity: sha512-u2F0VK6+anItoEvB3+rfvTO9GEh2vb00Je05OwlUe/A0lkJBgW1HckiY3f9YZa+jx6IOe4dHPh10dyp9aY3iRQ==} peerDependencies: react: ^18 || ^19 @@ -3320,16 +3387,16 @@ packages: terser: ^5.16.0 vite: ^6.0.0 - '@vitejs/plugin-react-swc@3.10.1': - resolution: {integrity: sha512-FmQvN3yZGyD9XW6IyxE86Kaa/DnxSsrDQX1xCR1qojNpBLaUop+nLYFvhCkJsq8zOupNjCRA9jyhPGOJsSkutA==} + '@vitejs/plugin-react-swc@3.10.2': + resolution: {integrity: sha512-xD3Rdvrt5LgANug7WekBn1KhcvLn1H3jNBfJRL3reeOIua/WnZOEV5qi5qIBq5T8R0jUDmRtxuvk4bPhzGHDWw==} peerDependencies: - vite: ^4 || ^5 || ^6 + vite: ^4 || ^5 || ^6 || ^7.0.0-beta.0 - '@vitejs/plugin-react@4.5.1': - resolution: {integrity: sha512-uPZBqSI0YD4lpkIru6M35sIfylLGTyhGHvDZbNLuMA73lMlwJKz5xweH7FajfcCAc2HnINciejA9qTz0dr0M7A==} + '@vitejs/plugin-react@4.5.2': + resolution: {integrity: sha512-QNVT3/Lxx99nMQWJWF7K4N6apUEuT0KlZA3mx/mVaoGj3smm/8rc8ezz15J1pcbcjDK0V15rpHetVfya08r76Q==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 '@volar/language-core@2.4.11': resolution: {integrity: sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==} @@ -3427,8 +3494,8 @@ packages: alien-signals@0.4.14: resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} - allotment@1.20.3: - resolution: {integrity: sha512-JCnklt7j0OsyDjD7A9AdT6wqJ3FSoo1ASV6w02Am02lo6NwO25yhG1DcWW8ueBV38ppXQmvrXBXuzX7iVkq6Tw==} + allotment@1.20.4: + resolution: {integrity: sha512-LMM5Xe5nLePFOLAlW/5k3ARqznYGUyNekV4xJrfDKn1jimW3nlZE6hT/Tu0T8s0VgAkr9s2P7+uM0WvJKn5DAw==} peerDependencies: react: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -6849,6 +6916,9 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + reselect@5.1.1: + resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} + reserved-words@0.1.2: resolution: {integrity: sha512-0S5SrIUJ9LfpbVl4Yzij6VipUdafHrOTzvmfazSw/jeZrZtQK303OPZW+obtkaw7jQlTQppy0UvZWm9872PbRw==} @@ -7499,8 +7569,8 @@ packages: resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} engines: {node: '>=10.0.0'} - tailwind-merge@3.3.0: - resolution: {integrity: sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ==} + tailwind-merge@3.3.1: + resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} tailwindcss@4.1.8: resolution: {integrity: sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==} @@ -8225,8 +8295,16 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.26.8': {} + '@babel/compat-data@7.27.5': {} + '@babel/core@7.26.10': dependencies: '@ampproject/remapping': 2.3.0 @@ -8247,9 +8325,29 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/core@7.27.4': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4) + '@babel/helpers': 7.27.6 + '@babel/parser': 7.27.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.27.4 + '@babel/types': 7.27.6 + convert-source-map: 2.0.0 + debug: 4.4.1 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/generator@7.17.7': dependencies: - '@babel/types': 7.27.0 + '@babel/types': 7.27.6 jsesc: 2.5.2 source-map: 0.5.7 optional: true @@ -8262,6 +8360,14 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 + '@babel/generator@7.27.5': + dependencies: + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.25.9': dependencies: '@babel/types': 7.27.0 @@ -8274,6 +8380,14 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.27.5 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -8307,18 +8421,18 @@ snapshots: '@babel/helper-environment-visitor@7.24.7': dependencies: - '@babel/types': 7.27.0 + '@babel/types': 7.27.6 optional: true '@babel/helper-function-name@7.24.7': dependencies: - '@babel/template': 7.27.0 - '@babel/types': 7.27.0 + '@babel/template': 7.27.2 + '@babel/types': 7.27.6 optional: true '@babel/helper-hoist-variables@7.24.7': dependencies: - '@babel/types': 7.27.0 + '@babel/types': 7.27.6 optional: true '@babel/helper-member-expression-to-functions@7.25.9': @@ -8335,6 +8449,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.27.4 + '@babel/types': 7.27.6 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -8344,12 +8465,23 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4)': + dependencies: + '@babel/core': 7.27.4 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.27.4 + transitivePeerDependencies: + - supports-color + '@babel/helper-optimise-call-expression@7.25.9': dependencies: '@babel/types': 7.27.0 '@babel/helper-plugin-utils@7.26.5': {} + '@babel/helper-plugin-utils@7.27.1': {} + '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -8377,15 +8509,21 @@ snapshots: '@babel/helper-split-export-declaration@7.24.7': dependencies: - '@babel/types': 7.27.0 + '@babel/types': 7.27.6 optional: true '@babel/helper-string-parser@7.25.9': {} + '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-option@7.25.9': {} + '@babel/helper-validator-option@7.27.1': {} + '@babel/helper-wrap-function@7.25.9': dependencies: '@babel/template': 7.27.0 @@ -8399,10 +8537,19 @@ snapshots: '@babel/template': 7.27.0 '@babel/types': 7.27.0 + '@babel/helpers@7.27.6': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.27.6 + '@babel/parser@7.27.0': dependencies: '@babel/types': 7.27.0 + '@babel/parser@7.27.5': + dependencies: + '@babel/types': 7.27.6 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -8727,15 +8874,15 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.10)': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.4)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 + '@babel/core': 7.27.4 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.10)': + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.27.4)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 + '@babel/core': 7.27.4 + '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.10)': dependencies: @@ -8901,16 +9048,22 @@ snapshots: '@babel/parser': 7.27.0 '@babel/types': 7.27.0 + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 + '@babel/traverse@7.23.2': dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.27.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.5 '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-function-name': 7.24.7 '@babel/helper-hoist-variables': 7.24.7 '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.27.0 - '@babel/types': 7.27.0 + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 debug: 4.4.1 globals: 11.12.0 transitivePeerDependencies: @@ -8941,9 +9094,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.27.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.5 + '@babel/parser': 7.27.5 + '@babel/template': 7.27.2 + '@babel/types': 7.27.6 + debug: 4.4.1 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + '@babel/types@7.17.0': dependencies: - '@babel/helper-validator-identifier': 7.25.9 + '@babel/helper-validator-identifier': 7.27.1 to-fast-properties: 2.0.0 optional: true @@ -8957,6 +9122,11 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 + '@babel/types@7.27.6': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@bufbuild/protobuf@2.2.3': {} '@commitlint/cli@19.8.1(@types/node@22.15.30)(typescript@5.8.3)': @@ -9360,13 +9530,13 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@greenhat616/material-react-table@4.0.0(f792f3152d47990021a35f343160b990)': + '@greenhat616/material-react-table@4.0.0(1200cdc8a1e411f19b648bfe23908224)': dependencies: '@emotion/react': 11.14.0(@types/react@19.1.6)(react@19.1.0) '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0) '@mui/icons-material': 7.1.1(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.6)(react@19.1.0) '@mui/material': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@mui/x-date-pickers': 8.5.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@mui/x-date-pickers': 8.5.2(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@tanstack/match-sorter-utils': 8.19.4 '@tanstack/react-table': 8.21.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@tanstack/react-virtual': 3.13.9(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -9558,7 +9728,7 @@ snapshots: '@mui/private-theming@7.1.1(@types/react@19.1.6)(react@19.1.0)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.6 '@mui/utils': 7.1.1(@types/react@19.1.6)(react@19.1.0) prop-types: 15.8.1 react: 19.1.0 @@ -9567,7 +9737,7 @@ snapshots: '@mui/styled-engine@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(react@19.1.0)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.6 '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 '@emotion/sheet': 1.4.0 @@ -9580,7 +9750,7 @@ snapshots: '@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.6 '@mui/private-theming': 7.1.1(@types/react@19.1.6)(react@19.1.0) '@mui/styled-engine': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(react@19.1.0) '@mui/types': 7.4.3(@types/react@19.1.6) @@ -9596,13 +9766,13 @@ snapshots: '@mui/types@7.4.3(@types/react@19.1.6)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.6 optionalDependencies: '@types/react': 19.1.6 '@mui/utils@7.1.1(@types/react@19.1.6)(react@19.1.0)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.6 '@mui/types': 7.4.3(@types/react@19.1.6) '@types/prop-types': 15.7.14 clsx: 2.1.1 @@ -9612,13 +9782,13 @@ snapshots: optionalDependencies: '@types/react': 19.1.6 - '@mui/x-date-pickers@8.5.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@mui/x-date-pickers@8.5.2(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@babel/runtime': 7.27.6 '@mui/material': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0) '@mui/utils': 7.1.1(@types/react@19.1.6)(react@19.1.0) - '@mui/x-internals': 8.5.1(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0) + '@mui/x-internals': 8.5.2(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0) '@types/react-transition-group': 4.4.12(@types/react@19.1.6) clsx: 2.1.1 prop-types: 15.8.1 @@ -9632,12 +9802,13 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@mui/x-internals@8.5.1(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0)': + '@mui/x-internals@8.5.2(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0)': dependencies: '@babel/runtime': 7.27.6 '@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0) '@mui/utils': 7.1.1(@types/react@19.1.6)(react@19.1.0) react: 19.1.0 + reselect: 5.1.1 transitivePeerDependencies: - '@types/react' @@ -10059,7 +10230,7 @@ snapshots: optionalDependencies: '@types/react': 19.1.6 - '@rolldown/pluginutils@1.0.0-beta.9': {} + '@rolldown/pluginutils@1.0.0-beta.11': {} '@rollup/pluginutils@4.2.1': dependencies: @@ -10297,55 +10468,55 @@ snapshots: transitivePeerDependencies: - supports-color - '@swc/core-darwin-arm64@1.11.29': + '@swc/core-darwin-arm64@1.12.1': optional: true - '@swc/core-darwin-x64@1.11.29': + '@swc/core-darwin-x64@1.12.1': optional: true - '@swc/core-linux-arm-gnueabihf@1.11.29': + '@swc/core-linux-arm-gnueabihf@1.12.1': optional: true - '@swc/core-linux-arm64-gnu@1.11.29': + '@swc/core-linux-arm64-gnu@1.12.1': optional: true - '@swc/core-linux-arm64-musl@1.11.29': + '@swc/core-linux-arm64-musl@1.12.1': optional: true - '@swc/core-linux-x64-gnu@1.11.29': + '@swc/core-linux-x64-gnu@1.12.1': optional: true - '@swc/core-linux-x64-musl@1.11.29': + '@swc/core-linux-x64-musl@1.12.1': optional: true - '@swc/core-win32-arm64-msvc@1.11.29': + '@swc/core-win32-arm64-msvc@1.12.1': optional: true - '@swc/core-win32-ia32-msvc@1.11.29': + '@swc/core-win32-ia32-msvc@1.12.1': optional: true - '@swc/core-win32-x64-msvc@1.11.29': + '@swc/core-win32-x64-msvc@1.12.1': optional: true - '@swc/core@1.11.29': + '@swc/core@1.12.1': dependencies: '@swc/counter': 0.1.3 - '@swc/types': 0.1.21 + '@swc/types': 0.1.23 optionalDependencies: - '@swc/core-darwin-arm64': 1.11.29 - '@swc/core-darwin-x64': 1.11.29 - '@swc/core-linux-arm-gnueabihf': 1.11.29 - '@swc/core-linux-arm64-gnu': 1.11.29 - '@swc/core-linux-arm64-musl': 1.11.29 - '@swc/core-linux-x64-gnu': 1.11.29 - '@swc/core-linux-x64-musl': 1.11.29 - '@swc/core-win32-arm64-msvc': 1.11.29 - '@swc/core-win32-ia32-msvc': 1.11.29 - '@swc/core-win32-x64-msvc': 1.11.29 + '@swc/core-darwin-arm64': 1.12.1 + '@swc/core-darwin-x64': 1.12.1 + '@swc/core-linux-arm-gnueabihf': 1.12.1 + '@swc/core-linux-arm64-gnu': 1.12.1 + '@swc/core-linux-arm64-musl': 1.12.1 + '@swc/core-linux-x64-gnu': 1.12.1 + '@swc/core-linux-x64-musl': 1.12.1 + '@swc/core-win32-arm64-msvc': 1.12.1 + '@swc/core-win32-ia32-msvc': 1.12.1 + '@swc/core-win32-x64-msvc': 1.12.1 '@swc/counter@0.1.3': {} - '@swc/types@0.1.21': + '@swc/types@0.1.23': dependencies: '@swc/counter': 0.1.3 @@ -10431,11 +10602,11 @@ snapshots: dependencies: remove-accents: 0.5.0 - '@tanstack/query-core@5.80.6': {} + '@tanstack/query-core@5.80.7': {} - '@tanstack/react-query@5.80.6(react@19.1.0)': + '@tanstack/react-query@5.80.7(react@19.1.0)': dependencies: - '@tanstack/query-core': 5.80.6 + '@tanstack/query-core': 5.80.7 react: 19.1.0 '@tanstack/react-router-devtools@1.120.20(@tanstack/react-router@1.120.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@tanstack/router-core@1.120.19)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tiny-invariant@1.3.3)': @@ -10640,7 +10811,7 @@ snapshots: '@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.5.3)': dependencies: '@babel/generator': 7.17.7 - '@babel/parser': 7.27.0 + '@babel/parser': 7.27.5 '@babel/traverse': 7.23.2 '@babel/types': 7.17.0 javascript-natural-sort: 0.7.1 @@ -11095,20 +11266,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitejs/plugin-react-swc@3.10.1(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0))': + '@vitejs/plugin-react-swc@3.10.2(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0))': dependencies: - '@rolldown/pluginutils': 1.0.0-beta.9 - '@swc/core': 1.11.29 + '@rolldown/pluginutils': 1.0.0-beta.11 + '@swc/core': 1.12.1 vite: 6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@4.5.1(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0))': + '@vitejs/plugin-react@4.5.2(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0))': dependencies: - '@babel/core': 7.26.10 - '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.10) - '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.10) - '@rolldown/pluginutils': 1.0.0-beta.9 + '@babel/core': 7.27.4 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.4) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.4) + '@rolldown/pluginutils': 1.0.0-beta.11 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 vite: 6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.88.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.8.0) @@ -11234,7 +11405,7 @@ snapshots: alien-signals@0.4.14: {} - allotment@1.20.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + allotment@1.20.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: classnames: 2.5.1 eventemitter3: 5.0.1 @@ -14874,14 +15045,14 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - react-hook-form-mui@7.6.1(d57264b30a79ce6f9a19367b42c73611): + react-hook-form-mui@7.6.1(a709df8d501e7bdf4d7009cd73340429): dependencies: '@mui/material': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 react-hook-form: 7.52.1(react@19.1.0) optionalDependencies: '@mui/icons-material': 7.1.1(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.6)(react@19.1.0) - '@mui/x-date-pickers': 8.5.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@mui/x-date-pickers': 8.5.2(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@mui/material@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(dayjs@1.11.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-hook-form@7.52.1(react@19.1.0): dependencies: @@ -15000,7 +15171,7 @@ snapshots: regenerator-transform@0.15.2: dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.6 regex-recursion@6.0.2: dependencies: @@ -15075,6 +15246,8 @@ snapshots: require-from-string@2.0.2: {} + reselect@5.1.1: {} + reserved-words@0.1.2: {} resize-observer-polyfill@1.5.1: {} @@ -15167,7 +15340,7 @@ snapshots: rtl-css-js@1.16.1: dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.6 run-parallel@1.2.0: dependencies: @@ -15788,7 +15961,7 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - tailwind-merge@3.3.0: {} + tailwind-merge@3.3.1: {} tailwindcss@4.1.8: {} diff --git a/clash-verge-rev/UPDATELOG.md b/clash-verge-rev/UPDATELOG.md index 0b55cdb76d..de1ae001da 100644 --- a/clash-verge-rev/UPDATELOG.md +++ b/clash-verge-rev/UPDATELOG.md @@ -1,22 +1,27 @@ +## v2.3.1 + +### 🐞 修复问题 + +- 增加配置文件校验,修复从古老版本升级上来的"No such file or directory (os error 2)"错误 + ## v2.3.0 -尽管 `external-controller` 密钥现已自动补全默认值且不允许为空,**仍建议手动修改密钥以提高安全性**。 +**发行代号:御** +代号释义: 「御」,象征掌控与守护,寓意本次版本对系统稳定性、安全性与用户体验的全面驾驭与提升。 ---- +尽管 `external-controller` 密钥现已自动补全默认值且不允许为空,**仍建议手动修改密钥以提高安全性**。 ### ⚠️ 已知问题 - 仅在 Ubuntu 22.04/24.04、Fedora 41 的 **GNOME 桌面环境** 做过简单测试,不保证其他 Linux 发行版兼容,后续将逐步适配和优化。 - macOS: + - MacOS 下自动升级成功后请关闭程序等待 30 秒重启,因为 MacOS 的端口释放特性,卸载服务后需重启应用等 30 秒才能恢复内核通信。立即启动可能无法正常启动内核。 - 墙贴主要为浅色,深色 Tray 图标存在闪烁问题; - 彩色 Tray 图标颜色偏淡; - - 卸载服务后需重启应用才能恢复内核通信。 - 已确认窗口状态管理器存在上游缺陷,已暂时移除窗口大小与位置记忆功能。 ---- - ### 🐞 修复问题 - 修复首页“代理模式”快速切换导致的卡死问题 @@ -40,8 +45,6 @@ - 修复 JS 脚本转义特殊字符报错 - 修复 macOS 静默启动时异常启动 Dock 栏图标 ---- - ### ✨ 新增功能 - **Mihomo(Meta) 内核升级至 v1.19.10** @@ -70,8 +73,6 @@ - 新增 Zashboard 一键跳转入口 - 使用系统默认窗口管理器 ---- - ### 🚀 优化改进 - **系统相关:** @@ -110,23 +111,9 @@ - 网络延迟测试替换为 HTTPS 协议:`https://cp.cloudflare.com/generate_204` - 优化 IP 信息获取流程,添加去重机制与轮询检测算法 ---- - -### 🌐 I18N 多语言支持 - -- 增加对以下语言的支持: - - - 🇹🇷 土耳其语(Turkish) - - 🇯🇵 日语(Japanese) - - 🇩🇪 德语(German) - - 🇪🇸 西班牙语(Spanish) - - 🇨🇳 繁体中文(Traditional Chinese) - - 同步修复翻译错误与不一致项,优化整体语言体验 - 加强语言切换后的页面稳定性,避免加载异常 ---- - ### 🗑️ 移除内容 - 窗口状态管理器(上游存在缺陷) diff --git a/clash-verge-rev/src-tauri/src/cmd/save_profile.rs b/clash-verge-rev/src-tauri/src/cmd/save_profile.rs index 5c4b73ef11..5e2b7bc1b1 100644 --- a/clash-verge-rev/src-tauri/src/cmd/save_profile.rs +++ b/clash-verge-rev/src-tauri/src/cmd/save_profile.rs @@ -1,5 +1,11 @@ use super::CmdResult; -use crate::{config::*, core::*, utils::dirs, wrap_err}; +use crate::{ + config::*, + core::*, + logging, + utils::{dirs, logging::Type}, + wrap_err, +}; use std::fs; /// 保存profiles的配置 @@ -26,29 +32,54 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR wrap_err!(fs::write(&file_path, file_data.clone().unwrap()))?; let file_path_str = file_path.to_string_lossy().to_string(); - println!( + logging!( + info, + Type::Config, + true, "[cmd配置save] 开始验证配置文件: {}, 是否为merge文件: {}", - file_path_str, is_merge_file + file_path_str, + is_merge_file ); // 对于 merge 文件,只进行语法验证,不进行后续内核验证 if is_merge_file { - println!("[cmd配置save] 检测到merge文件,只进行语法验证"); + logging!( + info, + Type::Config, + true, + "[cmd配置save] 检测到merge文件,只进行语法验证" + ); match CoreManager::global() .validate_config_file(&file_path_str, Some(true)) .await { Ok((true, _)) => { - println!("[cmd配置save] merge文件语法验证通过"); + logging!( + info, + Type::Config, + true, + "[cmd配置save] merge文件语法验证通过" + ); // 成功后尝试更新整体配置 if let Err(e) = CoreManager::global().update_config().await { - println!("[cmd配置save] 更新整体配置时发生错误: {}", e); - log::warn!(target: "app", "更新整体配置时发生错误: {}", e); + logging!( + warn, + Type::Config, + true, + "[cmd配置save] 更新整体配置时发生错误: {}", + e + ); } return Ok(()); } Ok((false, error_msg)) => { - println!("[cmd配置save] merge文件语法验证失败: {}", error_msg); + logging!( + warn, + Type::Config, + true, + "[cmd配置save] merge文件语法验证失败: {}", + error_msg + ); // 恢复原始配置文件 wrap_err!(fs::write(&file_path, original_content))?; // 发送合并文件专用错误通知 @@ -57,7 +88,13 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR return Ok(()); } Err(e) => { - println!("[cmd配置save] 验证过程发生错误: {}", e); + logging!( + error, + Type::Config, + true, + "[cmd配置save] 验证过程发生错误: {}", + e + ); // 恢复原始配置文件 wrap_err!(fs::write(&file_path, original_content))?; return Err(e.to_string()); @@ -71,11 +108,17 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR .await { Ok((true, _)) => { - println!("[cmd配置save] 验证成功"); + logging!(info, Type::Config, true, "[cmd配置save] 验证成功"); Ok(()) } Ok((false, error_msg)) => { - println!("[cmd配置save] 验证失败: {}", error_msg); + logging!( + warn, + Type::Config, + true, + "[cmd配置save] 验证失败: {}", + error_msg + ); // 恢复原始配置文件 wrap_err!(fs::write(&file_path, original_content))?; @@ -90,24 +133,30 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR || (!file_path_str.ends_with(".js") && !is_script_error) { // 普通YAML错误使用YAML通知处理 - println!("[cmd配置save] YAML配置文件验证失败,发送通知"); + log::info!(target: "app", "[cmd配置save] YAML配置文件验证失败,发送通知"); let result = (false, error_msg.clone()); crate::cmd::validate::handle_yaml_validation_notice(&result, "YAML配置文件"); } else if is_script_error { // 脚本错误使用专门的通知处理 - println!("[cmd配置save] 脚本文件验证失败,发送通知"); + log::info!(target: "app", "[cmd配置save] 脚本文件验证失败,发送通知"); let result = (false, error_msg.clone()); crate::cmd::validate::handle_script_validation_notice(&result, "脚本文件"); } else { // 普通配置错误使用一般通知 - println!("[cmd配置save] 其他类型验证失败,发送一般通知"); + log::info!(target: "app", "[cmd配置save] 其他类型验证失败,发送一般通知"); handle::Handle::notice_message("config_validate::error", &error_msg); } Ok(()) } Err(e) => { - println!("[cmd配置save] 验证过程发生错误: {}", e); + logging!( + error, + Type::Config, + true, + "[cmd配置save] 验证过程发生错误: {}", + e + ); // 恢复原始配置文件 wrap_err!(fs::write(&file_path, original_content))?; Err(e.to_string()) diff --git a/clash-verge-rev/src-tauri/src/cmd/validate.rs b/clash-verge-rev/src-tauri/src/cmd/validate.rs index 94cab28b70..7275ac074a 100644 --- a/clash-verge-rev/src-tauri/src/cmd/validate.rs +++ b/clash-verge-rev/src-tauri/src/cmd/validate.rs @@ -1,5 +1,5 @@ use super::CmdResult; -use crate::core::*; +use crate::{core::*, logging, utils::logging::Type}; /// 发送脚本验证通知消息 #[tauri::command] @@ -28,7 +28,14 @@ pub fn handle_script_validation_notice(result: &(bool, String), file_type: &str) "config_validate::script_error" }; - log::warn!(target: "app", "{} 验证失败: {}", file_type, error_msg); + logging!( + warn, + Type::Config, + true, + "{} 验证失败: {}", + file_type, + error_msg + ); handle::Handle::notice_message(status, error_msg); } } @@ -36,7 +43,7 @@ pub fn handle_script_validation_notice(result: &(bool, String), file_type: &str) /// 验证指定脚本文件 #[tauri::command] pub async fn validate_script_file(file_path: String) -> CmdResult { - log::info!(target: "app", "验证脚本文件: {}", file_path); + logging!(info, Type::Config, true, "验证脚本文件: {}", file_path); match CoreManager::global() .validate_config_file(&file_path, None) @@ -48,7 +55,13 @@ pub async fn validate_script_file(file_path: String) -> CmdResult { } Err(e) => { let error_msg = e.to_string(); - log::error!(target: "app", "验证脚本文件过程发生错误: {}", error_msg); + logging!( + error, + Type::Config, + true, + "验证脚本文件过程发生错误: {}", + error_msg + ); handle::Handle::notice_message("config_validate::process_terminated", &error_msg); Ok(false) } @@ -60,7 +73,14 @@ pub async fn validate_script_file(file_path: String) -> CmdResult { pub fn handle_yaml_validation_notice(result: &(bool, String), file_type: &str) { if !result.0 { let error_msg = &result.1; - println!("[通知] 处理{}验证错误: {}", file_type, error_msg); + logging!( + info, + Type::Config, + true, + "[通知] 处理{}验证错误: {}", + file_type, + error_msg + ); // 检查是否为merge文件 let is_merge_file = file_type.contains("合并"); @@ -97,8 +117,22 @@ pub fn handle_yaml_validation_notice(result: &(bool, String), file_type: &str) { } }; - log::warn!(target: "app", "{} 验证失败: {}", file_type, error_msg); - println!("[通知] 发送通知: status={}, msg={}", status, error_msg); + logging!( + warn, + Type::Config, + true, + "{} 验证失败: {}", + file_type, + error_msg + ); + logging!( + info, + Type::Config, + true, + "[通知] 发送通知: status={}, msg={}", + status, + error_msg + ); handle::Handle::notice_message(status, error_msg); } } diff --git a/clash-verge-rev/src-tauri/src/config/verge.rs b/clash-verge-rev/src-tauri/src/config/verge.rs index c26fe7bd7f..603fed2a40 100644 --- a/clash-verge-rev/src-tauri/src/config/verge.rs +++ b/clash-verge-rev/src-tauri/src/config/verge.rs @@ -1,6 +1,7 @@ use crate::{ config::{deserialize_encrypted, serialize_encrypted, DEFAULT_PAC}, - utils::{dirs, help, i18n}, + logging, + utils::{dirs, help, i18n, logging::Type}, }; use anyhow::Result; use log::LevelFilter; @@ -232,6 +233,94 @@ pub struct IVergeTheme { } impl IVerge { + /// 有效的clash核心名称 + pub const VALID_CLASH_CORES: &'static [&'static str] = &["verge-mihomo", "verge-mihomo-alpha"]; + + /// 验证并修正配置文件中的clash_core值 + pub fn validate_and_fix_config() -> Result<()> { + let config_path = dirs::verge_path()?; + let mut config = match help::read_yaml::(&config_path) { + Ok(config) => config, + Err(_) => Self::template(), + }; + + let mut needs_fix = false; + + if let Some(ref core) = config.clash_core { + let core_str = core.trim(); + if core_str.is_empty() || !Self::VALID_CLASH_CORES.contains(&core_str) { + logging!( + warn, + Type::Config, + true, + "启动时发现无效的clash_core配置: '{}', 将自动修正为 'verge-mihomo'", + core + ); + config.clash_core = Some("verge-mihomo".to_string()); + needs_fix = true; + } + } else { + logging!( + info, + Type::Config, + true, + "启动时发现未配置clash_core, 将设置为默认值 'verge-mihomo'" + ); + config.clash_core = Some("verge-mihomo".to_string()); + needs_fix = true; + } + + // 修正后保存配置 + if needs_fix { + logging!(info, Type::Config, true, "正在保存修正后的配置文件..."); + help::save_yaml(&config_path, &config, Some("# Clash Verge Config"))?; + logging!( + info, + Type::Config, + true, + "配置文件修正完成,需要重新加载配置" + ); + + Self::reload_config_after_fix(config)?; + } else { + logging!( + info, + Type::Config, + true, + "clash_core配置验证通过: {:?}", + config.clash_core + ); + } + + Ok(()) + } + + /// 配置修正后重新加载配置 + + fn reload_config_after_fix(updated_config: IVerge) -> Result<()> { + use crate::config::Config; + + let config_draft = Config::verge(); + *config_draft.draft() = Box::new(updated_config.clone()); + config_draft.apply(); + + logging!( + info, + Type::Config, + true, + "内存配置已强制更新,新的clash_core: {:?}", + updated_config.clash_core + ); + + Ok(()) + } + + pub fn get_valid_clash_core(&self) -> String { + self.clash_core + .clone() + .unwrap_or_else(|| "verge-mihomo".to_string()) + } + fn get_system_language() -> String { let sys_lang = sys_locale::get_locale() .unwrap_or_else(|| String::from("en")) @@ -503,6 +592,8 @@ pub struct IVergeResponse { impl From for IVergeResponse { fn from(verge: IVerge) -> Self { + // 先获取验证后的clash_core值,避免后续借用冲突 + let valid_clash_core = verge.get_valid_clash_core(); Self { app_log_level: verge.app_log_level, language: verge.language, @@ -534,7 +625,7 @@ impl From for IVergeResponse { proxy_host: verge.proxy_host, theme_setting: verge.theme_setting, web_ui_list: verge.web_ui_list, - clash_core: verge.clash_core, + clash_core: Some(valid_clash_core), hotkeys: verge.hotkeys, auto_close_connection: verge.auto_close_connection, auto_check_update: verge.auto_check_update, diff --git a/clash-verge-rev/src-tauri/src/core/core.rs b/clash-verge-rev/src-tauri/src/core/core.rs index 502556002d..70a7748b35 100644 --- a/clash-verge-rev/src-tauri/src/core/core.rs +++ b/clash-verge-rev/src-tauri/src/core/core.rs @@ -54,7 +54,7 @@ impl fmt::Display for RunningMode { } } -const CLASH_CORES: [&str; 2] = ["verge-mihomo", "verge-mihomo-alpha"]; +use crate::config::IVerge; impl CoreManager { /// 检查文件是否为脚本文件 @@ -249,8 +249,7 @@ impl CoreManager { config_path ); - let clash_core = { Config::verge().latest().clash_core.clone() }; - let clash_core = clash_core.unwrap_or("verge-mihomo".into()); + let clash_core = Config::verge().latest().get_valid_clash_core(); logging!(info, Type::Config, true, "使用内核: {}", clash_core); let app_handle = handle::Handle::global().app_handle().unwrap(); @@ -442,11 +441,7 @@ impl CoreManager { let app_handle = handle::Handle::global() .app_handle() .ok_or(anyhow::anyhow!("failed to get app handle"))?; - let clash_core = Config::verge() - .latest() - .clash_core - .clone() - .unwrap_or("verge-mihomo".to_string()); + let clash_core = Config::verge().latest().get_valid_clash_core(); let config_dir = dirs::app_home_dir()?; let service_log_dir = dirs::app_home_dir()?.join("logs").join("service"); @@ -804,7 +799,7 @@ impl CoreManager { return Err(error_message.to_string()); } let core: &str = &clash_core.clone().unwrap(); - if !CLASH_CORES.contains(&core) { + if !IVerge::VALID_CLASH_CORES.contains(&core) { let error_message = format!("Clash core invalid name: {}", core); logging!(error, Type::Core, true, "{}", error_message); return Err(error_message); diff --git a/clash-verge-rev/src-tauri/src/core/service.rs b/clash-verge-rev/src-tauri/src/core/service.rs index bc8ff41783..6815180f8a 100644 --- a/clash-verge-rev/src-tauri/src/core/service.rs +++ b/clash-verge-rev/src-tauri/src/core/service.rs @@ -742,8 +742,7 @@ pub(super) async fn start_with_existing_service(config_file: &PathBuf) -> Result log::info!(target:"app", "尝试使用现有服务启动核心 (IPC)"); // logging!(info, Type::Service, true, "尝试使用现有服务启动核心"); - let clash_core = { Config::verge().latest().clash_core.clone() }; - let clash_core = clash_core.unwrap_or("verge-mihomo".into()); + let clash_core = Config::verge().latest().get_valid_clash_core(); let bin_ext = if cfg!(windows) { ".exe" } else { "" }; let clash_bin = format!("{clash_core}{bin_ext}"); diff --git a/clash-verge-rev/src-tauri/src/enhance/mod.rs b/clash-verge-rev/src-tauri/src/enhance/mod.rs index e226880f5d..000440c171 100644 --- a/clash-verge-rev/src-tauri/src/enhance/mod.rs +++ b/clash-verge-rev/src-tauri/src/enhance/mod.rs @@ -22,7 +22,7 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { let verge = Config::verge(); let verge = verge.latest(); ( - verge.clash_core.clone(), + Some(verge.get_valid_clash_core()), verge.enable_tun_mode.unwrap_or(false), verge.enable_builtin_enhanced.unwrap_or(true), verge.verge_socks_enabled.unwrap_or(false), diff --git a/clash-verge-rev/src-tauri/src/enhance/script.rs b/clash-verge-rev/src-tauri/src/enhance/script.rs index 40789f07aa..d1ced5ed02 100644 --- a/clash-verge-rev/src-tauri/src/enhance/script.rs +++ b/clash-verge-rev/src-tauri/src/enhance/script.rs @@ -45,8 +45,8 @@ pub fn use_script( let config = use_lowercase(config.clone()); let config_str = serde_json::to_string(&config)?; - // 处理 name 参数中的特殊字符 - let safe_name = escape_js_string(&name); + // 仅处理 name 参数中的特殊字符 + let safe_name = escape_js_string_for_single_quote(&name); let code = format!( r#"try{{ @@ -64,18 +64,8 @@ pub fn use_script( let result = result.to_string(&mut context).unwrap(); let result = result.to_std_string().unwrap(); - // 处理 JS 执行结果中的特殊字符 - let unescaped_result = unescape_js_string(&result); - - if unescaped_result.starts_with("__error_flag__") { - anyhow::bail!(unescaped_result[15..].to_owned()); - } - if unescaped_result == "\"\"" { - anyhow::bail!("main function should return object"); - } - - // 安全地解析 JSON 结果 - let res: Result = parse_json_safely(&unescaped_result); + // 直接解析JSON结果,不做其他解析 + let res: Result = parse_json_safely(&result); let mut out = outputs.lock().unwrap(); match res { @@ -90,72 +80,25 @@ pub fn use_script( } } -// 解析 JSON 字符串,处理可能的转义字符 fn parse_json_safely(json_str: &str) -> Result { - // 移除可能的引号包裹 - let json_str = if json_str.starts_with('"') && json_str.ends_with('"') { - &json_str[1..json_str.len() - 1] + let json_str = strip_outer_quotes(json_str); + + Ok(serde_json::from_str::(json_str)?) +} + +// 移除字符串外层的引号 +fn strip_outer_quotes(s: &str) -> &str { + let s = s.trim(); + if (s.starts_with('"') && s.ends_with('"')) || (s.starts_with('\'') && s.ends_with('\'')) { + &s[1..s.len() - 1] } else { - json_str - }; - - // 处理可能的 JSON 字符串中的转义字符 - let json_str = json_str.replace("\\\"", "\""); - - Ok(serde_json::from_str::(&json_str)?) + s + } } -// 转义 JS 字符串中的特殊字符 -fn escape_js_string(s: &str) -> String { - let mut result = String::with_capacity(s.len()); - for c in s.chars() { - match c { - '\'' => result.push_str("\\'"), - '"' => result.push_str("\\\""), - '\\' => result.push_str("\\\\"), - '\n' => result.push_str("\\n"), - '\r' => result.push_str("\\r"), - '\t' => result.push_str("\\t"), - '\0' => result.push_str("\\0"), - _ => result.push(c), - } - } - result -} - -// 反转义 JS 字符串中的特殊字符 -fn unescape_js_string(s: &str) -> String { - let mut result = String::with_capacity(s.len()); - let mut chars = s.chars(); - - while let Some(c) = chars.next() { - if c == '\\' { - match chars.next() { - Some('n') => result.push('\n'), - Some('r') => result.push('\r'), - Some('t') => result.push('\t'), - Some('0') => result.push('\0'), - Some('\\') => result.push('\\'), - Some('\'') => result.push('\''), - Some('"') => result.push('"'), - Some('u') => { - // 处理转义序列 - let hex = chars.by_ref().take(4).collect::(); - if let Ok(codepoint) = u32::from_str_radix(&hex, 16) { - if let Some(ch) = char::from_u32(codepoint) { - result.push(ch); - } - } - } - Some(other) => result.push(other), - None => break, - } - } else { - result.push(c); - } - } - - result +// 转义单引号和反斜杠,用于单引号包裹的JavaScript字符串 +fn escape_js_string_for_single_quote(s: &str) -> String { + s.replace('\\', "\\\\").replace('\'', "\\'") } #[test] @@ -197,10 +140,9 @@ fn test_script() { #[test] fn test_escape_unescape() { let test_string = r#"Hello "World"!\nThis is a test with \u00A9 copyright symbol."#; - let escaped = escape_js_string(test_string); - let unescaped = unescape_js_string(&escaped); - - assert_eq!(test_string, unescaped); + let escaped = escape_js_string_for_single_quote(test_string); + println!("Original: {}", test_string); + println!("Escaped: {}", escaped); let json_str = r#"{"key":"value","nested":{"key":"value"}}"#; let parsed = parse_json_safely(json_str).unwrap(); diff --git a/clash-verge-rev/src-tauri/src/feat/clash.rs b/clash-verge-rev/src-tauri/src/feat/clash.rs index 68b0134f8d..c57e69537d 100644 --- a/clash-verge-rev/src-tauri/src/feat/clash.rs +++ b/clash-verge-rev/src-tauri/src/feat/clash.rs @@ -84,7 +84,7 @@ pub fn change_clash_mode(mode: String) { after_change_clash_mode(); } } - Err(err) => println!("{err}"), + Err(err) => log::error!(target: "app", "{err}"), } }); } diff --git a/clash-verge-rev/src-tauri/src/feat/profile.rs b/clash-verge-rev/src-tauri/src/feat/profile.rs index f2f3419739..1b76c228ba 100644 --- a/clash-verge-rev/src-tauri/src/feat/profile.rs +++ b/clash-verge-rev/src-tauri/src/feat/profile.rs @@ -2,7 +2,9 @@ use crate::{ cmd, config::{Config, PrfItem, PrfOption}, core::{handle, CoreManager, *}, + logging, process::AsyncHandler, + utils::logging::Type, }; use anyhow::{bail, Result}; @@ -29,7 +31,7 @@ pub async fn update_profile( option: Option, auto_refresh: Option, ) -> Result<()> { - println!("[订阅更新] 开始更新订阅 {}", uid); + logging!(info, Type::Config, true, "[订阅更新] 开始更新订阅 {}", uid); let auto_refresh = auto_refresh.unwrap_or(true); // 默认为true,保持兼容性 let url_opt = { @@ -39,13 +41,13 @@ pub async fn update_profile( let is_remote = item.itype.as_ref().is_some_and(|s| s == "remote"); if !is_remote { - println!("[订阅更新] {} 不是远程订阅,跳过更新", uid); + log::info!(target: "app", "[订阅更新] {} 不是远程订阅,跳过更新", uid); None // 非远程订阅直接更新 } else if item.url.is_none() { - println!("[订阅更新] {} 缺少URL,无法更新", uid); + log::warn!(target: "app", "[订阅更新] {} 缺少URL,无法更新", uid); bail!("failed to get the profile item url"); } else { - println!( + log::info!(target: "app", "[订阅更新] {} 是远程订阅,URL: {}", uid, item.url.clone().unwrap() @@ -56,24 +58,24 @@ pub async fn update_profile( let should_update = match url_opt { Some((url, opt)) => { - println!("[订阅更新] 开始下载新的订阅内容"); + log::info!(target: "app", "[订阅更新] 开始下载新的订阅内容"); let merged_opt = PrfOption::merge(opt.clone(), option.clone()); // 尝试使用正常设置更新 match PrfItem::from_url(&url, None, None, merged_opt.clone()).await { Ok(item) => { - println!("[订阅更新] 更新订阅配置成功"); + log::info!(target: "app", "[订阅更新] 更新订阅配置成功"); let profiles = Config::profiles(); let mut profiles = profiles.latest(); profiles.update_item(uid.clone(), item)?; let is_current = Some(uid.clone()) == profiles.get_current(); - println!("[订阅更新] 是否为当前使用的订阅: {}", is_current); + log::info!(target: "app", "[订阅更新] 是否为当前使用的订阅: {}", is_current); is_current && auto_refresh } Err(err) => { // 首次更新失败,尝试使用Clash代理 - println!("[订阅更新] 正常更新失败: {},尝试使用Clash代理更新", err); + log::warn!(target: "app", "[订阅更新] 正常更新失败: {},尝试使用Clash代理更新", err); // 发送通知 handle::Handle::notice_message("update_retry_with_clash", uid.clone()); @@ -90,7 +92,7 @@ pub async fn update_profile( // 使用Clash代理重试 match PrfItem::from_url(&url, None, None, Some(fallback_opt)).await { Ok(mut item) => { - println!("[订阅更新] 使用Clash代理更新成功"); + log::info!(target: "app", "[订阅更新] 使用Clash代理更新成功"); // 恢复原始代理设置到item if let Some(option) = item.option.as_mut() { @@ -110,11 +112,11 @@ pub async fn update_profile( handle::Handle::notice_message("update_with_clash_proxy", profile_name); let is_current = Some(uid.clone()) == profiles.get_current(); - println!("[订阅更新] 是否为当前使用的订阅: {}", is_current); + log::info!(target: "app", "[订阅更新] 是否为当前使用的订阅: {}", is_current); is_current && auto_refresh } Err(retry_err) => { - println!("[订阅更新] 使用Clash代理更新仍然失败: {}", retry_err); + log::error!(target: "app", "[订阅更新] 使用Clash代理更新仍然失败: {}", retry_err); handle::Handle::notice_message( "update_failed_even_with_clash", format!("{}", retry_err), @@ -129,14 +131,14 @@ pub async fn update_profile( }; if should_update { - println!("[订阅更新] 更新内核配置"); + logging!(info, Type::Config, true, "[订阅更新] 更新内核配置"); match CoreManager::global().update_config().await { Ok(_) => { - println!("[订阅更新] 更新成功"); + logging!(info, Type::Config, true, "[订阅更新] 更新成功"); handle::Handle::refresh_clash(); } Err(err) => { - println!("[订阅更新] 更新失败: {}", err); + logging!(error, Type::Config, true, "[订阅更新] 更新失败: {}", err); handle::Handle::notice_message("update_failed", format!("{err}")); log::error!(target: "app", "{err}"); } diff --git a/clash-verge-rev/src-tauri/src/feat/window.rs b/clash-verge-rev/src-tauri/src/feat/window.rs index 40f3c4ca91..d537d8061c 100644 --- a/clash-verge-rev/src-tauri/src/feat/window.rs +++ b/clash-verge-rev/src-tauri/src/feat/window.rs @@ -3,45 +3,39 @@ use crate::AppHandleManager; use crate::{ config::Config, core::{handle, sysopt, CoreManager}, + logging, module::mihomo::MihomoManager, - utils::resolve, + utils::{logging::Type, resolve}, }; /// Open or close the dashboard window #[allow(dead_code)] pub fn open_or_close_dashboard() { - println!("Attempting to open/close dashboard"); log::info!(target: "app", "Attempting to open/close dashboard"); // 检查是否在轻量模式下 if crate::module::lightweight::is_in_lightweight_mode() { - println!("Currently in lightweight mode, exiting lightweight mode"); log::info!(target: "app", "Currently in lightweight mode, exiting lightweight mode"); crate::module::lightweight::exit_lightweight_mode(); - println!("Creating new window after exiting lightweight mode"); log::info!(target: "app", "Creating new window after exiting lightweight mode"); resolve::create_window(true); return; } if let Some(window) = handle::Handle::global().get_window() { - println!("Found existing window"); log::info!(target: "app", "Found existing window"); // 如果窗口存在,则切换其显示状态 match window.is_visible() { Ok(visible) => { - println!("Window visibility status: {}", visible); log::info!(target: "app", "Window visibility status: {}", visible); if visible { - println!("Attempting to hide window"); log::info!(target: "app", "Attempting to hide window"); let _ = window.hide(); } else { - println!("Attempting to show and focus window"); log::info!(target: "app", "Attempting to show and focus window"); if window.is_minimized().unwrap_or(false) { let _ = window.unminimize(); @@ -51,12 +45,10 @@ pub fn open_or_close_dashboard() { } } Err(e) => { - println!("Failed to get window visibility: {:?}", e); log::error!(target: "app", "Failed to get window visibility: {:?}", e); } } } else { - println!("No existing window found, creating new window"); log::info!(target: "app", "No existing window found, creating new window"); resolve::create_window(true); } @@ -65,7 +57,7 @@ pub fn open_or_close_dashboard() { /// 异步优化的应用退出函数 pub fn quit() { use crate::process::AsyncHandler; - log::debug!(target: "app", "启动退出流程"); + logging!(debug, Type::System, true, "启动退出流程"); // 获取应用句柄并设置退出标志 let app_handle = handle::Handle::global().app_handle().unwrap(); @@ -79,10 +71,16 @@ pub fn quit() { // 使用异步任务处理资源清理,避免阻塞 AsyncHandler::spawn(move || async move { - log::info!(target: "app", "开始异步清理资源"); + logging!(info, Type::System, true, "开始异步清理资源"); let cleanup_result = clean_async().await; - log::info!(target: "app", "资源清理完成,退出代码: {}", if cleanup_result { 0 } else { 1 }); + logging!( + info, + Type::System, + true, + "资源清理完成,退出代码: {}", + if cleanup_result { 0 } else { 1 } + ); app_handle.exit(if cleanup_result { 0 } else { 1 }); }); } @@ -90,7 +88,7 @@ pub fn quit() { async fn clean_async() -> bool { use tokio::time::{timeout, Duration}; - log::info!(target: "app", "开始执行异步清理操作..."); + logging!(info, Type::System, true, "开始执行异步清理操作..."); // 1. 处理TUN模式 let tun_task = async { @@ -178,10 +176,16 @@ async fn clean_async() -> bool { let all_success = tun_success && proxy_success && core_success && dns_success; - log::info!( - target: "app", + logging!( + info, + Type::System, + true, "异步清理操作完成 - TUN: {}, 代理: {}, 核心: {}, DNS: {}, 总体: {}", - tun_success, proxy_success, core_success, dns_success, all_success + tun_success, + proxy_success, + core_success, + dns_success, + all_success ); all_success @@ -193,7 +197,7 @@ pub fn clean() -> bool { let (tx, rx) = std::sync::mpsc::channel(); AsyncHandler::spawn(move || async move { - log::info!(target: "app", "开始执行清理操作..."); + logging!(info, Type::System, true, "开始执行清理操作..."); // 使用已有的异步清理函数 let cleanup_result = clean_async().await; @@ -204,11 +208,16 @@ pub fn clean() -> bool { match rx.recv_timeout(std::time::Duration::from_secs(8)) { Ok(result) => { - log::info!(target: "app", "清理操作完成,结果: {}", result); + logging!(info, Type::System, true, "清理操作完成,结果: {}", result); result } Err(_) => { - log::warn!(target: "app", "清理操作超时,返回成功状态避免阻塞"); + logging!( + warn, + Type::System, + true, + "清理操作超时,返回成功状态避免阻塞" + ); true } } diff --git a/clash-verge-rev/src-tauri/src/lib.rs b/clash-verge-rev/src-tauri/src/lib.rs index 137f32b2e1..245ad23c77 100644 --- a/clash-verge-rev/src-tauri/src/lib.rs +++ b/clash-verge-rev/src-tauri/src/lib.rs @@ -368,7 +368,7 @@ pub fn run() { if core::handle::Handle::global().is_exiting() { return; } - println!("closing window..."); + log::info!(target: "app", "closing window..."); api.prevent_close(); if let Some(window) = core::handle::Handle::global().get_window() { let _ = window.hide(); diff --git a/clash-verge-rev/src-tauri/src/utils/init.rs b/clash-verge-rev/src-tauri/src/utils/init.rs index 013f137826..3c42986d80 100644 --- a/clash-verge-rev/src-tauri/src/utils/init.rs +++ b/clash-verge-rev/src-tauri/src/utils/init.rs @@ -286,6 +286,9 @@ pub fn init_config() -> Result<()> { >::Ok(()) })); + // 验证并修正verge.yaml中的clash_core配置 + crate::log_err!(IVerge::validate_and_fix_config()); + crate::log_err!(dirs::profiles_path().map(|path| { if !path.exists() { help::save_yaml(&path, &IProfiles::template(), Some("# Clash Verge"))?; diff --git a/clash-verge-rev/src/components/setting/mods/controller-viewer.tsx b/clash-verge-rev/src/components/setting/mods/controller-viewer.tsx index 84a77f1033..5734d2b78a 100644 --- a/clash-verge-rev/src/components/setting/mods/controller-viewer.tsx +++ b/clash-verge-rev/src/components/setting/mods/controller-viewer.tsx @@ -1,6 +1,5 @@ import { BaseDialog, DialogRef } from "@/components/base"; import { useClashInfo } from "@/hooks/use-clash"; -import { patchClashConfig } from "@/services/cmds"; import { showNotice } from "@/services/noticeService"; import { ContentCopy } from "@mui/icons-material"; import { @@ -42,19 +41,19 @@ export const ControllerViewer = forwardRef((props, ref) => { // 保存配置 const onSave = useLockFn(async () => { if (!controller.trim()) { - showNotice("error", t("Controller address cannot be empty"), 3000); + showNotice("error", t("Controller address cannot be empty")); return; } if (!secret.trim()) { - showNotice("error", t("Secret cannot be empty"), 3000); + showNotice("error", t("Secret cannot be empty")); return; } try { setIsSaving(true); await patchInfo({ "external-controller": controller, secret }); - showNotice("success", t("Configuration saved successfully"), 2000); + showNotice("success", t("Configuration saved successfully")); setOpen(false); } catch (err: any) { showNotice( @@ -73,9 +72,9 @@ export const ControllerViewer = forwardRef((props, ref) => { try { await navigator.clipboard.writeText(text); setCopySuccess(type); - setTimeout(() => setCopySuccess(null), 2000); + setTimeout(() => setCopySuccess(null)); } catch (err) { - showNotice("error", t("Failed to copy"), 2000); + showNotice("error", t("Failed to copy")); } }, ); diff --git a/filebrowser/CHANGELOG.md b/filebrowser/CHANGELOG.md index 2d414dcb32..7ef7bda84d 100644 --- a/filebrowser/CHANGELOG.md +++ b/filebrowser/CHANGELOG.md @@ -2,6 +2,31 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [2.32.1](https://github.com/filebrowser/filebrowser/compare/v2.32.0...v2.32.1) (2025-06-16) + + +### Features + +* add Vietnamese translation ([#3840](https://github.com/filebrowser/filebrowser/issues/3840)) ([56b80b6](https://github.com/filebrowser/filebrowser/commit/56b80b6d9b4710538765ba7df5da1f03898f6b81)) +* improve pt-br translations with new keys and refinements ([#4903](https://github.com/filebrowser/filebrowser/issues/4903)) ([a882fb6](https://github.com/filebrowser/filebrowser/commit/a882fb6c85ab6ccc845ed0bf3908d8e5e60ce346)) +* update translation ko.json ([#3852](https://github.com/filebrowser/filebrowser/issues/3852)) ([d9ebd65](https://github.com/filebrowser/filebrowser/commit/d9ebd65ffcf9b2166fec708d51849796d12b16e0)) + + +### Bug Fixes + +* err shadowing lint ([c606a01](https://github.com/filebrowser/filebrowser/commit/c606a01a2d20932fb32ee896234d57631f8c47e4)) +* generate random admin password on quick setup ([a46acba](https://github.com/filebrowser/filebrowser/commit/a46acba5f92ee044661880d6ae349e289d984328)), closes [#3646](https://github.com/filebrowser/filebrowser/issues/3646) +* imports lint ([54b91b8](https://github.com/filebrowser/filebrowser/commit/54b91b8ff0b8ee1f02f72425ab97d27a5d942fc3)) +* set videojs locale ([#3742](https://github.com/filebrowser/filebrowser/issues/3742)) ([71a8f56](https://github.com/filebrowser/filebrowser/commit/71a8f5662c207e3cd4ee714a5b5a961121f510cd)) + + +### Build + +* **deps-dev:** bump vite from 6.0.11 to 6.1.6 in /frontend ([#3886](https://github.com/filebrowser/filebrowser/issues/3886)) ([5355629](https://github.com/filebrowser/filebrowser/commit/5355629fd1e7bd85ee3222fca22da899ba23ea95)) +* **deps:** bump golang.org/x/crypto from 0.31.0 to 0.35.0 ([#3865](https://github.com/filebrowser/filebrowser/issues/3865)) ([0ba9505](https://github.com/filebrowser/filebrowser/commit/0ba9505a19cb369653fc9f8260dc02fcc6587629)) +* **deps:** bump golang.org/x/net from 0.33.0 to 0.38.0 ([#3869](https://github.com/filebrowser/filebrowser/issues/3869)) ([cfea84f](https://github.com/filebrowser/filebrowser/commit/cfea84fd5e7ec9c1d2366293e5db12baaa4e3a81)) +* **deps:** bump vue-i18n from 11.0.1 to 11.1.2 in /frontend ([#3786](https://github.com/filebrowser/filebrowser/issues/3786)) ([35d1c09](https://github.com/filebrowser/filebrowser/commit/35d1c092434b80b22c89a614a02122e9f5965b39)) + ## [2.32.0](https://github.com/filebrowser/filebrowser/compare/v2.31.2...v2.32.0) (2025-01-31) diff --git a/filebrowser/frontend/src/components/settings/Languages.vue b/filebrowser/frontend/src/components/settings/Languages.vue index 2b8a7606a3..00129a286b 100644 --- a/filebrowser/frontend/src/components/settings/Languages.vue +++ b/filebrowser/frontend/src/components/settings/Languages.vue @@ -38,6 +38,7 @@ export default { "sv-se": "Swedish (Sweden)", tr: "Türkçe", uk: "Українська", + vi: "Tiếng Việt", "zh-cn": "中文 (简体)", "zh-tw": "中文 (繁體)", }; diff --git a/filebrowser/frontend/src/i18n/index.ts b/filebrowser/frontend/src/i18n/index.ts index f0b0304b3f..9fcbc2c441 100644 --- a/filebrowser/frontend/src/i18n/index.ts +++ b/filebrowser/frontend/src/i18n/index.ts @@ -23,6 +23,7 @@ import("dayjs/locale/sk"); import("dayjs/locale/sv"); import("dayjs/locale/tr"); import("dayjs/locale/uk"); +import("dayjs/locale/vi"); import("dayjs/locale/zh-cn"); import("dayjs/locale/zh-tw"); @@ -103,6 +104,9 @@ export function detectLocale() { case /^uk\b/.test(locale): locale = "uk"; break; + case /^vi\b/.test(locale): + locale = "vi"; + break; case /^sv-se\b/.test(locale): case /^sv\b/.test(locale): locale = "sv"; diff --git a/filebrowser/frontend/src/i18n/ko.json b/filebrowser/frontend/src/i18n/ko.json index 722da2d28b..6a6db23f29 100644 --- a/filebrowser/frontend/src/i18n/ko.json +++ b/filebrowser/frontend/src/i18n/ko.json @@ -3,47 +3,60 @@ "cancel": "취소", "clear": "지우기", "close": "닫기", + "continue": "계속", "copy": "복사", "copyFile": "파일 복사", - "copyToClipboard": "클립보드 복사", + "copyToClipboard": "클립보드에 복사", + "copyDownloadLinkToClipboard": "다운로드 링크 클립보드에 복사", "create": "생성", "delete": "삭제", "download": "다운로드", - "hideDotfiles": "숨김파일(dotfile)을 표시 안함", + "file": "파일", + "folder": "폴더", + "fullScreen": "전체 화면 전환", + "hideDotfiles": "숨김 파일 숨기기", "info": "정보", - "more": "더보기", + "more": "더 보기", "move": "이동", "moveFile": "파일 이동", - "new": "신규", + "new": "새로 만들기", "next": "다음", "ok": "확인", - "permalink": "링크 얻기", + "permalink": "영구 링크 받기", "previous": "이전", + "preview": "미리보기", "publish": "게시", "rename": "이름 바꾸기", - "replace": "대체", - "reportIssue": "이슈 보내기", + "replace": "바꾸기", + "reportIssue": "문제 보고", "save": "저장", - "schedule": "일정", + "schedule": "예약", "search": "검색", "select": "선택", "selectMultiple": "다중 선택", "share": "공유", - "shell": "쉘 전환", + "shell": "셸 전환", + "submit": "제출", "switchView": "보기 전환", "toggleSidebar": "사이드바 전환", "update": "업데이트", - "upload": "업로드" + "upload": "업로드", + "openFile": "파일 열기", + "discardChanges": "변경 사항 취소" }, "download": { "downloadFile": "파일 다운로드", "downloadFolder": "폴더 다운로드", "downloadSelected": "선택 항목 다운로드" }, + "upload": { + "abortUpload": "업로드를 중단하시겠습니까?" + }, "errors": { - "forbidden": "접근 권한이 없습니다.", - "internal": "오류가 발생하였습니다.", - "notFound": "해당 경로를 찾을 수 없습니다." + "forbidden": "이곳에 접근할 권한이 없습니다.", + "internal": "문제가 발생했습니다.", + "notFound": "이 위치에 접근할 수 없습니다.", + "connection": "서버에 연결할 수 없습니다." }, "files": { "body": "본문", @@ -51,175 +64,192 @@ "files": "파일", "folders": "폴더", "home": "홈", - "lastModified": "최종 수정", - "loading": "로딩중...", - "lonely": "폴더가 비어 있습니다...", + "lastModified": "마지막 수정일", + "loading": "로딩 중...", + "lonely": "여기에 아무것도 없네요...", "metadata": "메타데이터", - "multipleSelectionEnabled": "다중 선택 켜짐", + "multipleSelectionEnabled": "다중 선택 활성화됨", "name": "이름", "size": "크기", - "sortByLastModified": "수정시간순 정렬", - "sortByName": "이름순", - "sortBySize": "크기순" + "sortByLastModified": "마지막 수정일 순 정렬", + "sortByName": "이름 순 정렬", + "sortBySize": "크기 순 정렬", + "noPreview": "이 파일은 미리보기를 사용할 수 없습니다." }, "help": { - "click": "파일이나 디렉토리를 선택해주세요.", + "click": "파일 또는 디렉터리 선택", "ctrl": { - "click": "여러 개의 파일이나 디렉토리를 선택해주세요.", - "f": "검색창 열기", - "s": "파일 또는 디렉토리 다운로드" + "click": "여러 파일 또는 디렉터리 선택", + "f": "검색 열기", + "s": "파일 저장 또는 현재 디렉터리 다운로드" }, - "del": "선택된 파일 삭제", - "doubleClick": "파일 또는 디렉토리 열기", - "esc": "선택 취소/프롬프트 닫기", - "f1": "정보", - "f2": "파일 이름 변경", + "del": "선택한 항목 삭제", + "doubleClick": "파일 또는 디렉터리 열기", + "esc": "선택 취소 및/또는 프롬프트 닫기", + "f1": "이 정보", + "f2": "파일 이름 바꾸기", "help": "도움말" }, "login": { - "createAnAccount": "계정 생성", + "createAnAccount": "계정 만들기", "loginInstead": "이미 계정이 있습니다", "password": "비밀번호", "passwordConfirm": "비밀번호 확인", "passwordsDontMatch": "비밀번호가 일치하지 않습니다", - "signup": "가입하기", + "signup": "가입", "submit": "로그인", "username": "사용자 이름", - "usernameTaken": "사용자 이름이 존재합니다", - "wrongCredentials": "사용자 이름 또는 비밀번호를 확인하십시오" + "usernameTaken": "이미 사용 중인 사용자 이름입니다", + "wrongCredentials": "잘못된 자격 증명" }, "permanent": "영구", "prompts": { "copy": "복사", - "copyMessage": "복사할 디렉토리:", - "currentlyNavigating": "현재 위치:", - "deleteMessageMultiple": "{count} 개의 파일을 삭제하시겠습니까?", - "deleteMessageSingle": "파일 혹은 디렉토리를 삭제하시겠습니까?", + "copyMessage": "파일을 복사할 위치를 선택하세요:", + "currentlyNavigating": "현재 탐색 중:", + "deleteMessageMultiple": "{count}개의 파일을 삭제하시겠습니까?", + "deleteMessageSingle": "이 파일/폴더를 삭제하시겠습니까?", + "deleteMessageShare": "이 공유({path})를 삭제하시겠습니까?", + "deleteUser": "이 사용자를 삭제하시겠습니까?", "deleteTitle": "파일 삭제", - "displayName": "게시 이름:", + "displayName": "표시 이름:", "download": "파일 다운로드", - "downloadMessage": "다운로드 포맷 설정.", - "error": "에러 발생!", + "downloadMessage": "다운로드할 형식을 선택하세요.", + "error": "문제가 발생했습니다", "fileInfo": "파일 정보", - "filesSelected": "{count} 개의 파일이 선택되었습니다.", - "lastModified": "최종 수정", + "filesSelected": "{count}개의 파일 선택됨.", + "lastModified": "마지막 수정일", "move": "이동", - "moveMessage": "이동할 화일 또는 디렉토리를 선택하세요:", - "newArchetype": "원형을 유지하는 포스트를 생성합니다. 파일은 컨텐트 폴더에 생성됩니다.", - "newDir": "새 디렉토리", - "newDirMessage": "새 디렉토리 이름을 입력해주세요.", + "moveMessage": "파일/폴더의 새 위치를 선택하세요:", + "newArchetype": "아키타입을 기반으로 새 게시물을 만듭니다. 파일은 content 폴더에 생성됩니다.", + "newDir": "새 디렉터리", + "newDirMessage": "새 디렉터리 이름을 지정하세요.", "newFile": "새 파일", - "newFileMessage": "새 파일 이름을 입력해주세요.", - "numberDirs": "디렉토리 수", + "newFileMessage": "새 파일 이름을 지정하세요.", + "numberDirs": "디렉터리 수", "numberFiles": "파일 수", - "rename": "이름 변경", - "renameMessage": "새로운 이름을 입력하세요.", - "replace": "대체하기", - "replaceMessage": "동일한 파일 이름이 존재합니다. 현재 파일을 덮어쓸까요?\n", - "schedule": "일정", - "scheduleMessage": "이 글을 공개할 시간을 알려주세요.", - "show": "보기", + "rename": "이름 바꾸기", + "renameMessage": "새 이름을 입력하세요:", + "replace": "바꾸기", + "replaceMessage": "업로드하려는 파일 중 이름이 충돌하는 파일이 있습니다. 이 파일을 건너뛰고 업로드를 계속하거나 기존 파일을 바꾸시겠습니까?\n", + "schedule": "예약", + "scheduleMessage": "이 게시물의 게시를 예약할 날짜와 시간을 선택하세요.", + "show": "표시", "size": "크기", "upload": "업로드", - "uploadMessage": "업로드 옵션을 선택하세요." + "uploadFiles": "{files}개의 파일 업로드 중...", + "uploadMessage": "업로드할 옵션을 선택하세요.", + "optionalPassword": "선택적 비밀번호", + "resolution": "해상도", + "discardEditorChanges": "변경 사항을 취소하시겠습니까?" }, "search": { "images": "이미지", "music": "음악", "pdf": "PDF", - "pressToSearch": "검색하려면 엔터를 입력하세요", + "pressToSearch": "Enter 키를 눌러 검색...", "search": "검색...", "typeToSearch": "검색어 입력...", - "types": "Types", + "types": "유형", "video": "비디오" }, "settings": { "admin": "관리자", "administrator": "관리자", - "allowCommands": "명령 실행", - "allowEdit": "파일/디렉토리의 수정/변경/삭제 허용", - "allowNew": "파일/디렉토리 생성 허용", - "allowPublish": "새 포스트/페이지 생성 허용", + "allowCommands": "명령 실행 허용", + "allowEdit": "파일 또는 디렉터리 편집, 이름 바꾸기, 삭제 허용", + "allowNew": "새 파일 및 디렉터리 생성 허용", + "allowPublish": "새 게시물 및 페이지 게시 허용", "allowSignup": "사용자 가입 허용", - "avoidChanges": "(수정하지 않으면 비워두세요)", + "avoidChanges": "(변경하지 않으려면 비워두세요)", "branding": "브랜딩", - "brandingDirectoryPath": "브랜드 디렉토리 경로", - "brandingHelp": "File Browser 인스턴스는 이름, 로고, 스타일 등을 변경할 수 있습니다. 자세한 사항은 여기{0}에서 확인하세요.", + "brandingDirectoryPath": "브랜딩 디렉터리 경로", + "brandingHelp": "File Browser 인스턴스의 이름 변경, 로고 교체, 사용자 정의 스타일 추가, GitHub 외부 링크 비활성화를 통해 모양과 느낌을 사용자 지정할 수 있습니다.\n사용자 정의 브랜딩에 대한 자세한 내용은 {0}을(를) 확인하세요.", "changePassword": "비밀번호 변경", - "commandRunner": "명령 실행기", - "commandRunnerHelp": "이벤트에 해당하는 명령을 설정하세요. 줄당 1개의 명령을 적으세요. 환경 변수{0} 와 {1}이 사용가능하며, {0} 은 {1}에 상대 경로 입니다. 자세한 사항은 {2} 를 참조하세요.", - "commandsUpdated": "명령 수정됨!", - "createUserDir": "Auto create user home dir while adding new user", - "customStylesheet": "커스텀 스타일시트", - "defaultUserDescription": "아래 사항은 신규 사용자들에 대한 기본 설정입니다.", - "disableExternalLinks": "외부 링크 감추기", - "disableUsedDiskPercentage": "Disable used disk percentage graph", + "commandRunner": "명령어 실행기", + "commandRunnerHelp": "여기서 지정된 이벤트에서 실행될 명령어를 설정할 수 있습니다. 한 줄에 하나씩 작성해야 합니다. 환경 변수 {0} 및 {1}을(를) 사용할 수 있으며, {0}은(는) {1}에 상대적입니다. 이 기능과 사용 가능한 환경 변수에 대한 자세한 내용은 {2}을(를) 읽어보세요.", + "commandsUpdated": "명령어가 업데이트되었습니다!", + "createUserDir": "새 사용자 추가 시 사용자 홈 디렉터리 자동 생성", + "tusUploads": "청크 업로드", + "tusUploadsHelp": "File Browser는 청크 파일 업로드를 지원하여 불안정한 네트워크에서도 효율적이고 안정적이며 재개 가능하고 분할된 파일 업로드를 가능하게 합니다.", + "tusUploadsChunkSize": "요청의 최대 크기를 나타냅니다 (더 작은 업로드에는 직접 업로드가 사용됩니다). 바이트 크기를 나타내는 일반 정수 또는 10MB, 1GB 등과 같은 문자열을 입력할 수 있습니다.", + "tusUploadsRetryCount": "청크 업로드 실패 시 재시도 횟수.", + "userHomeBasePath": "사용자 홈 디렉터리의 기본 경로", + "userScopeGenerationPlaceholder": "범위가 자동으로 생성됩니다", + "createUserHomeDirectory": "사용자 홈 디렉터리 생성", + "customStylesheet": "사용자 정의 스타일시트", + "defaultUserDescription": "새 사용자의 기본 설정입니다.", + "disableExternalLinks": "외부 링크 비활성화 (문서 제외)", + "disableUsedDiskPercentage": "사용된 디스크 비율 그래프 비활성화", "documentation": "문서", - "examples": "예", - "executeOnShell": "쉘에서 실행", - "executeOnShellDescription": "기본적으로 File Browser 는 바이너리를 명령어로 호출하여 실행합니다. 쉘을 통해 실행하기를 원한다면, Bash 또는 PowerShell 에 필요한 인수와 플래그를 설정하세요. 사용자 명령어와 이벤트 훅에 모두 적용됩니다.", - "globalRules": "규칙에 대한 전역설정으로 모든 사용자에게 적용됩니다. 지정된 규칙은 사용자 설정을 덮어쓰기 합니다.", + "examples": "예시", + "executeOnShell": "셸에서 실행", + "executeOnShellDescription": "기본적으로 File Browser는 바이너리를 직접 호출하여 명령을 실행합니다. 대신 셸(예: Bash 또는 PowerShell)에서 실행하려면 필요한 인수 및 플래그와 함께 여기에 정의할 수 있습니다. 설정된 경우 실행하는 명령이 인수로 추가됩니다. 이는 사용자 명령과 이벤트 후크 모두에 적용됩니다.", + "globalRules": "이것은 전역 허용 및 차단 규칙 세트입니다. 모든 사용자에게 적용됩니다. 각 사용자 설정에서 특정 규칙을 정의하여 이 규칙을 재정의할 수 있습니다.", "globalSettings": "전역 설정", - "hideDotfiles": "숨김파일(dotfile)을 표시하지 않습니다.", - "insertPath": "경로 입력", - "insertRegex": "정규식 입력", + "hideDotfiles": "숨김 파일 숨기기", + "insertPath": "경로 삽입", + "insertRegex": "정규식 표현 삽입", "instanceName": "인스턴스 이름", "language": "언어", - "lockPassword": "사용자에 의한 비밀번호 변경을 허용하지 않음", - "newPassword": "새로운 비밀번호", - "newPasswordConfirm": "새로운 비밀번호 확인", - "newUser": "새로운 사용자", + "lockPassword": "사용자가 비밀번호를 변경하지 못하도록 잠금", + "newPassword": "새 비밀번호", + "newPasswordConfirm": "새 비밀번호 확인", + "newUser": "새 사용자", "password": "비밀번호", - "passwordUpdated": "비밀번호 수정 완료!", + "passwordUpdated": "비밀번호가 업데이트되었습니다!", "path": "경로", "perm": { - "create": "파일이나 디렉토리 생성하기", - "delete": "화일이나 디렉토리 삭제하기", + "create": "파일 및 디렉터리 생성", + "delete": "파일 및 디렉터리 삭제", "download": "다운로드", "execute": "명령 실행", "modify": "파일 편집", - "rename": "파일 이름 변경 또는 디렉토리 이동", - "share": "파일 공유하기" + "rename": "파일 및 디렉터리 이름 바꾸기 또는 이동", + "share": "파일 공유" }, "permissions": "권한", - "permissionsHelp": "사용자를 관리자로 만들거나 권한을 부여할 수 있습니다. 관리자를 선택하면, 모든 옵션이 자동으로 선택됩니다. 사용자 관리는 현재 관리자만 할 수 있습니다.\n", + "permissionsHelp": "사용자를 관리자로 설정하거나 개별적으로 권한을 선택할 수 있습니다. \"관리자\"를 선택하면 다른 모든 옵션이 자동으로 선택됩니다. 사용자 관리는 관리자의 권한으로 유지됩니다.\n", "profileSettings": "프로필 설정", - "ruleExample1": "점(.)으로 시작하는 모든 파일의 접근을 방지합니다.(예 .git, .gitignore)\n", - "ruleExample2": "Caddyfile파일의 접근을 방지합니다.", - "rules": "룰", - "rulesHelp": "사용자별로 규칙을 허용/방지를 지정할 수 있습니다. 방지된 파일은 보이지 않고 사용자들은 접근할 수 없습니다. 사용자의 접근 허용 범위와 관련해 정규표현식(regex)과 경로를 지원합니다.\n", + "ruleExample1": "모든 폴더에서 모든 숨김 파일(예: .git, .gitignore)에 대한 액세스를 방지합니다.\n", + "ruleExample2": "범위의 루트에 있는 Caddyfile이라는 파일에 대한 액세스를 차단합니다.", + "rules": "규칙", + "rulesHelp": "여기서 이 특정 사용자에 대한 허용 및 차단 규칙 세트를 정의할 수 있습니다. 차단된 파일은 목록에 표시되지 않으며 사용자가 액세스할 수 없습니다. 사용자의 범위에 상대적인 정규식 및 경로를 지원합니다.\n", "scope": "범위", - "settingsUpdated": "설정 수정됨!", + "setDateFormat": "정확한 날짜 형식 설정", + "settingsUpdated": "설정이 업데이트되었습니다!", "shareDuration": "공유 기간", - "shareManagement": "공유 내역 관리", - "singleClick": "한번 클릭으로 파일과 폴더를 열도록 합니다.", + "shareManagement": "공유 관리", + "shareDeleted": "공유가 삭제되었습니다!", + "singleClick": "파일 및 디렉터리를 열 때 한 번 클릭 사용", "themes": { - "dark": "다크테마", - "light": "라이트테마", + "default": "시스템 기본값", + "dark": "어둡게", + "light": "밝게", "title": "테마" }, "user": "사용자", "userCommands": "명령어", - "userCommandsHelp": "사용에게 허용할 명령어를 공백으로 구분하여 입력하세요. 예:\n", - "userCreated": "사용자 생성됨!", + "userCommandsHelp": "이 사용자가 사용할 수 있는 명령어 목록 (공백으로 구분). 예:\n", + "userCreated": "사용자가 생성되었습니다!", "userDefaults": "사용자 기본 설정", - "userDeleted": "사용자 삭제됨!", + "userDeleted": "사용자가 삭제되었습니다!", "userManagement": "사용자 관리", - "userUpdated": "사용자 수정됨!", + "userUpdated": "사용자가 업데이트되었습니다!", "username": "사용자 이름", "users": "사용자" }, "sidebar": { "help": "도움말", - "hugoNew": "Hugo New", + "hugoNew": "Hugo 새로 만들기", "login": "로그인", "logout": "로그아웃", "myFiles": "내 파일", - "newFile": "새로운 파일", - "newFolder": "새로운 폴더", + "newFile": "새 파일", + "newFolder": "새 폴더", "preview": "미리보기", "settings": "설정", - "signup": "가입하기", + "signup": "가입", "siteSettings": "사이트 설정" }, "success": { @@ -227,9 +257,9 @@ }, "time": { "days": "일", - "hours": "시", + "hours": "시간", "minutes": "분", "seconds": "초", - "unit": "Time Unit" + "unit": "시간 단위" } } diff --git a/filebrowser/frontend/src/i18n/pt-br.json b/filebrowser/frontend/src/i18n/pt-br.json index 53d855d12f..5e5b1116eb 100644 --- a/filebrowser/frontend/src/i18n/pt-br.json +++ b/filebrowser/frontend/src/i18n/pt-br.json @@ -38,13 +38,20 @@ "toggleSidebar": "Alternar barra lateral", "update": "Atualizar", "upload": "Enviar", - "openFile": "Abrir" + "openFile": "Abrir", + "copyDownloadLinkToClipboard": "Copiar link de download para a área de transferência", + "fullScreen": "Alternar tela cheia", + "preview": "Pré-visualizar", + "discardChanges": "Descartar" }, "download": { "downloadFile": "Baixar arquivo", "downloadFolder": "Baixar pasta", "downloadSelected": "Baixar selecionado" }, + "upload": { + "abortUpload": "Tem certeza de que deseja abortar o upload?" + }, "errors": { "forbidden": "Você não tem permissões para acessar isto.", "internal": "Ops! Algum erro ocorreu.", @@ -58,8 +65,8 @@ "folders": "Pastas", "home": "Início", "lastModified": "Última modificação", - "loading": "Carregando. Aguarde, por favor.", - "lonely": "Não existe nada aqui.", + "loading": "Carregando...", + "lonely": "Não há nada aqui...", "metadata": "Metadados", "multipleSelectionEnabled": "Seleção múltipla ativada", "name": "Nome", @@ -73,12 +80,12 @@ "click": "selecionar pasta ou arquivo", "ctrl": { "click": "selecionar várias pastas e arquivos", - "f": "pesquisar", + "f": "abrir pesquisa", "s": "salvar um arquivo ou baixar a pasta que você está" }, "del": "apagar os arquivos selecionados", "doubleClick": "abrir pasta ou arquivo", - "esc": "limpar seleção e/ou fechar menu", + "esc": "limpar seleção e/ou fechar prompt", "f1": "esta informação", "f2": "renomear arquivo", "help": "Ajuda" @@ -123,7 +130,7 @@ "rename": "Renomear", "renameMessage": "Insira um novo nome para", "replace": "Substituir", - "replaceMessage": "Já existe um arquivo com nome igual a um dos que está tentando enviar. Deseja substituir?\n", + "replaceMessage": "Um dos arquivos que você está tentando enviar possui um nome conflitante. Deseja pular este arquivo e continuar o envio ou substituir o existente?\n", "schedule": "Agendar", "scheduleMessage": "Escolha uma data para agendar a publicação deste post.", "show": "Mostrar", @@ -131,7 +138,10 @@ "upload": "Enviar", "uploadFiles": "Enviando {files} arquivos...", "uploadMessage": "Selecione uma opção para enviar.", - "optionalPassword": "Senha opcional" + "optionalPassword": "Senha opcional", + "deleteUser": "Tem certeza de que deseja apagar este usuário?", + "resolution": "Resolução", + "discardEditorChanges": "Tem certeza de que deseja descartar as alterações feitas?" }, "search": { "images": "Imagens", @@ -159,7 +169,7 @@ "commandRunner": "Execução de comandos", "commandRunnerHelp": "Aqui você pode definir comandos que serão executados nos eventos descritos. Escreva um por linha. As variáveis de ambiente {0} e {1} estão disponíveis, sendo {0} relativo a {1}. Para mais informações sobre esta função e as variáveis de ambiente disponíveis, leia a {2}.", "commandsUpdated": "Comandos atualizados!", - "createUserDir": "Criar diretório Home para novos usuários", + "createUserDir": "Criar diretório Home do usuário automaticamente ao adicionar novo usuário", "userHomeBasePath": "Caminho base para diretórios de usuários", "userScopeGenerationPlaceholder": "O escopo será gerado automaticamente", "createUserHomeDirectory": "Criar diretório Home de usuário", @@ -184,7 +194,7 @@ "newUser": "Novo usuário", "password": "Senha", "passwordUpdated": "Senha atualizada!", - "path": "", + "path": "Caminho", "perm": { "create": "Criar arquivos e diretórios", "delete": "Apagar arquivos e diretórios", @@ -209,6 +219,7 @@ "shareDeleted": "Compartilhamento apagado!", "singleClick": "Usar clique único para abrir arquivos e diretórios", "themes": { + "default": "Padrão do sistema", "dark": "Escuro", "light": "Claro", "title": "Tema" @@ -229,7 +240,7 @@ "hugoNew": "Hugo New", "login": "Login", "logout": "Sair", - "myFiles": "Arquivos", + "myFiles": "Meus arquivos", "newFile": "Novo arquivo", "newFolder": "Nova pasta", "preview": "Pré-visualizar", @@ -245,6 +256,6 @@ "hours": "Horas", "minutes": "Minutos", "seconds": "Segundos", - "unit": "Unidades de Tempo" + "unit": "Unidade de tempo" } } diff --git a/filebrowser/frontend/src/i18n/vi.json b/filebrowser/frontend/src/i18n/vi.json new file mode 100644 index 0000000000..5dea8650cb --- /dev/null +++ b/filebrowser/frontend/src/i18n/vi.json @@ -0,0 +1,265 @@ +{ + "buttons": { + "cancel": "Hủy", + "clear": "Xóa", + "close": "Đóng", + "continue": "Tiếp tục", + "copy": "Sao chép", + "copyFile": "Sao chép tập tin", + "copyToClipboard": "Sao chép vào clipboard", + "copyDownloadLinkToClipboard": "Sao chép liên kết tải xuống vào clipboard", + "create": "Tạo", + "delete": "Xóa", + "download": "Tải xuống", + "file": "Tập tin", + "folder": "Thư mục", + "fullScreen": "Toàn màn hình", + "hideDotfiles": "Ẩn tập tin ẩn", + "info": "Thông tin", + "more": "Thêm", + "move": "Di chuyển", + "moveFile": "Di chuyển tập tin", + "new": "Mới", + "next": "Tiếp theo", + "ok": "OK", + "permalink": "Lấy liên kết vĩnh viễn", + "previous": "Trước", + "preview": "Xem trước", + "publish": "Xuất bản", + "rename": "Đổi tên", + "replace": "Thay thế", + "reportIssue": "Báo cáo sự cố", + "save": "Lưu", + "schedule": "Lên lịch", + "search": "Tìm kiếm", + "select": "Chọn", + "selectMultiple": "Chọn nhiều", + "share": "Chia sẻ", + "shell": "Chuyển đổi shell", + "submit": "Gửi", + "switchView": "Chuyển chế độ xem", + "toggleSidebar": "Thanh bên", + "update": "Cập nhật", + "upload": "Tải lên", + "openFile": "Mở tệp", + "discardChanges": "Hủy bỏ thay đổi" + }, + "download": { + "downloadFile": "Tải xuống tệp tin", + "downloadFolder": "Tải xuống thư mục", + "downloadSelected": "Tải xuống đã chọn" + }, + "upload": { + "abortUpload": "Bạn có chắc chắn muốn hủy tải lên không?" + }, + "errors": { + "forbidden": "Bạn không có quyền truy cập vào nội dung này.", + "internal": "Đã xảy ra lỗi nghiêm trọng.", + "notFound": "Không thể truy cập vị trí này.", + "connection": "Không thể kết nối đến máy chủ." + }, + "files": { + "body": "Nội dung", + "closePreview": "Đóng xem trước", + "files": "Tập tin", + "folders": "Thư mục", + "home": "Trang chủ", + "lastModified": "Sửa đổi lần cuối", + "loading": "Đang tải...", + "lonely": "Không có gì ở đây...", + "metadata": "Siêu dữ liệu", + "multipleSelectionEnabled": "Đã bật chọn nhiều", + "name": "Tên", + "size": "Kích thước", + "sortByLastModified": "Sắp xếp theo ngày sửa đổi", + "sortByName": "Sắp xếp theo tên", + "sortBySize": "Sắp xếp theo kích thước", + "noPreview": "Không có bản xem trước cho tập tin này." + }, + "help": { + "click": "chọn tập tin hoặc thư mục", + "ctrl": { + "click": "chọn nhiều tập tin hoặc thư mục", + "f": "mở tìm kiếm", + "s": "lưu tập tin hoặc tải thư mục hiện tại" + }, + "del": "xóa các mục đã chọn", + "doubleClick": "mở tập tin hoặc thư mục", + "esc": "hủy chọn và/hoặc đóng hộp thoại", + "f1": "mở trợ giúp này", + "f2": "đổi tên tập tin", + "help": "Trợ giúp" + }, + "login": { + "createAnAccount": "Tạo tài khoản", + "loginInstead": "Đã có tài khoản", + "password": "Mật khẩu", + "passwordConfirm": "Xác nhận mật khẩu", + "passwordsDontMatch": "Mật khẩu không khớp", + "signup": "Đăng ký", + "submit": "Đăng nhập", + "username": "Tên người dùng", + "usernameTaken": "Tên người dùng đã tồn tại", + "wrongCredentials": "Thông tin đăng nhập không đúng" + }, + "permanent": "Vĩnh viễn", + "prompts": { + "copy": "Sao chép", + "copyMessage": "Chọn vị trí để sao chép tệp của bạn:", + "currentlyNavigating": "Đang điều hướng tại:", + "deleteMessageMultiple": "Bạn có chắc chắn muốn xóa {count} tệp không?", + "deleteMessageSingle": "Bạn có chắc chắn muốn xóa tệp/thư mục này không?", + "deleteMessageShare": "Bạn có chắc chắn muốn xóa chia sẻ này ({path}) không?", + "deleteUser": "Bạn có chắc chắn muốn xóa người dùng này không?", + "deleteTitle": "Xóa tệp", + "displayName": "Tên hiển thị:", + "download": "Tải xuống tệp", + "downloadMessage": "Chọn định dạng bạn muốn tải xuống.", + "error": "Đã xảy ra lỗi", + "fileInfo": "Thông tin tệp", + "filesSelected": "{count} tệp đã được chọn.", + "lastModified": "Chỉnh sửa lần cuối", + "move": "Di chuyển", + "moveMessage": "Chọn vị trí mới cho tệp/thư mục của bạn:", + "newArchetype": "Tạo một bài viết mới dựa trên nguyên mẫu. Tệp của bạn sẽ được tạo trong thư mục nội dung.", + "newDir": "Thư mục mới", + "newDirMessage": "Đặt tên cho thư mục mới của bạn.", + "newFile": "Tệp mới", + "newFileMessage": "Đặt tên cho tệp mới của bạn.", + "numberDirs": "Số lượng thư mục", + "numberFiles": "Số lượng tệp", + "rename": "Đổi tên", + "renameMessage": "Nhập tên mới cho", + "replace": "Thay thế", + "replaceMessage": "Một trong những tệp bạn đang cố tải lên có tên trùng lặp. Bạn có muốn bỏ qua tệp này và tiếp tục tải lên hay thay thế tệp hiện có?\n", + "schedule": "Lên lịch", + "scheduleMessage": "Chọn ngày và giờ để lên lịch xuất bản bài viết này.", + "show": "Hiển thị", + "size": "Kích thước", + "upload": "Tải lên", + "uploadFiles": "Đang tải lên {files} tệp...", + "uploadMessage": "Chọn một tùy chọn để tải lên.", + "optionalPassword": "Mật khẩu tùy chọn", + "resolution": "Độ phân giải", + "discardEditorChanges": "Bạn có chắc chắn muốn hủy bỏ các thay đổi đã thực hiện không?" + }, + "search": { + "images": "Hình ảnh", + "music": "Nhạc", + "pdf": "PDF", + "pressToSearch": "Nhấn Enter để tìm kiếm...", + "search": "Tìm kiếm...", + "typeToSearch": "Nhập để tìm kiếm...", + "types": "Loại", + "video": "Video" + }, + "settings": { + "admin": "Quản trị viên", + "administrator": "Người quản trị", + "allowCommands": "Thực thi lệnh", + "allowEdit": "Chỉnh sửa, đổi tên và xóa tệp hoặc thư mục", + "allowNew": "Tạo tệp và thư mục mới", + "allowPublish": "Xuất bản bài viết và trang mới", + "allowSignup": "Cho phép người dùng đăng ký", + "avoidChanges": "(để trống để tránh thay đổi)", + "branding": "Thương hiệu", + "brandingDirectoryPath": "Đường dẫn thư mục thương hiệu", + "brandingHelp": "Bạn có thể tùy chỉnh giao diện và trải nghiệm của File Browser bằng cách thay đổi tên, thay thế logo, thêm kiểu tùy chỉnh và thậm chí vô hiệu hóa các liên kết bên ngoài đến GitHub.\nĐể biết thêm thông tin về tùy chỉnh thương hiệu, vui lòng xem {0}.", + "changePassword": "Đổi mật khẩu", + "commandRunner": "Trình chạy lệnh", + "commandRunnerHelp": "Tại đây, bạn có thể thiết lập các lệnh được thực thi trong các sự kiện đã định. Bạn phải viết một lệnh trên mỗi dòng. Các biến môi trường {0} và {1} sẽ có sẵn, trong đó {0} tương đối với {1}. Để biết thêm thông tin về tính năng này và các biến môi trường có sẵn, vui lòng đọc {2}.", + "commandsUpdated": "Lệnh đã được cập nhật!", + "createUserDir": "Tự động tạo thư mục chính của người dùng khi thêm người dùng mới", + "tusUploads": "Tải lên theo phân đoạn", + "tusUploadsHelp": "File Browser hỗ trợ tải lên tệp theo phân đoạn, giúp việc tải lên trở nên hiệu quả, đáng tin cậy, có thể tiếp tục và phù hợp với mạng không ổn định.", + "tusUploadsChunkSize": "Kích thước tối đa của một yêu cầu (tải lên trực tiếp sẽ được sử dụng cho các tệp nhỏ hơn). Bạn có thể nhập một số nguyên biểu thị kích thước theo byte hoặc một chuỗi như 10MB, 1GB, v.v.", + "tusUploadsRetryCount": "Số lần thử lại nếu một phân đoạn tải lên thất bại.", + "userHomeBasePath": "Đường dẫn cơ bản của thư mục chính người dùng", + "userScopeGenerationPlaceholder": "Phạm vi sẽ được tạo tự động", + "createUserHomeDirectory": "Tạo thư mục chính của người dùng", + "customStylesheet": "Bảng định dạng tùy chỉnh", + "defaultUserDescription": "Đây là cài đặt mặc định cho người dùng mới.", + "disableExternalLinks": "Vô hiệu hóa các liên kết bên ngoài (trừ tài liệu)", + "disableUsedDiskPercentage": "Vô hiệu hóa biểu đồ phần trăm dung lượng đã sử dụng", + "documentation": "tài liệu", + "examples": "Ví dụ", + "executeOnShell": "Thực thi trên shell", + "executeOnShellDescription": "Theo mặc định, File Browser thực thi lệnh bằng cách gọi trực tiếp các tệp nhị phân của chúng. Nếu bạn muốn chạy chúng trên shell (chẳng hạn như Bash hoặc PowerShell), bạn có thể định nghĩa tại đây cùng với các tham số và cờ cần thiết. Nếu được đặt, lệnh bạn thực thi sẽ được thêm làm đối số. Điều này áp dụng cho cả lệnh người dùng và hook sự kiện.", + "globalRules": "Đây là tập hợp quy tắc chung về quyền cho phép và từ chối. Chúng áp dụng cho mọi người dùng. Bạn có thể đặt quy tắc riêng cho từng người dùng để ghi đè các quy tắc chung này.", + "globalSettings": "Cài đặt chung", + "hideDotfiles": "Ẩn tệp ẩn (dotfiles)", + "insertPath": "Nhập đường dẫn", + "insertRegex": "Nhập biểu thức regex", + "instanceName": "Tên phiên bản", + "language": "Ngôn ngữ", + "lockPassword": "Ngăn người dùng thay đổi mật khẩu", + "newPassword": "Mật khẩu mới của bạn", + "newPasswordConfirm": "Xác nhận mật khẩu mới", + "newUser": "Người dùng mới", + "password": "Mật khẩu", + "passwordUpdated": "Mật khẩu đã được cập nhật!", + "path": "Đường dẫn", + "perm": { + "create": "Tạo tệp và thư mục", + "delete": "Xóa tệp và thư mục", + "download": "Tải xuống", + "execute": "Thực thi lệnh", + "modify": "Chỉnh sửa tệp", + "rename": "Đổi tên hoặc di chuyển tệp và thư mục", + "share": "Chia sẻ tệp" + }, + "permissions": "Quyền", + "permissionsHelp": "Bạn có thể đặt người dùng làm quản trị viên hoặc chọn quyền riêng lẻ. Nếu chọn \"Người quản trị\", tất cả các tùy chọn khác sẽ tự động được chọn. Việc quản lý người dùng vẫn là đặc quyền của quản trị viên.\n", + "profileSettings": "Cài đặt hồ sơ", + "ruleExample1": "ngăn truy cập vào bất kỳ tệp ẩn nào (chẳng hạn như .git, .gitignore) trong mọi thư mục.\n", + "ruleExample2": "chặn truy cập vào tệp có tên Caddyfile trong thư mục gốc của phạm vi.", + "rules": "Quy tắc", + "rulesHelp": "Tại đây, bạn có thể xác định một tập hợp quy tắc cho phép hoặc từ chối cho người dùng cụ thể này. Các tệp bị chặn sẽ không hiển thị trong danh sách và người dùng không thể truy cập chúng. Chúng tôi hỗ trợ regex và đường dẫn tương đối với phạm vi của người dùng.\n", + "scope": "Phạm vi", + "setDateFormat": "Đặt định dạng ngày chính xác", + "settingsUpdated": "Cài đặt đã được cập nhật!", + "shareDuration": "Thời gian chia sẻ", + "shareManagement": "Quản lý chia sẻ", + "shareDeleted": "Chia sẻ đã bị xóa!", + "singleClick": "Dùng một lần nhấp để mở tệp và thư mục", + "themes": { + "default": "Mặc định hệ thống", + "dark": "Tối", + "light": "Sáng", + "title": "Chủ đề" + }, + "user": "Người dùng", + "userCommands": "Lệnh", + "userCommandsHelp": "Danh sách lệnh được phân tách bằng khoảng trắng dành cho người dùng này. Ví dụ:\n", + "userCreated": "Người dùng đã được tạo!", + "userDefaults": "Cài đặt mặc định của người dùng", + "userDeleted": "Người dùng đã bị xóa!", + "userManagement": "Quản lý người dùng", + "userUpdated": "Người dùng đã được cập nhật!", + "username": "Tên người dùng", + "users": "Người dùng" + }, + "sidebar": { + "help": "Trợ giúp", + "hugoNew": "Hugo New", + "login": "Đăng nhập", + "logout": "Đăng xuất", + "myFiles": "Tập tin của tôi", + "newFile": "Tập tin mới", + "newFolder": "Thư mục mới", + "preview": "Xem trước", + "settings": "Cài đặt", + "signup": "Đăng ký", + "siteSettings": "Cài đặt trang" + }, + "success": { + "linkCopied": "Liên kết đã được sao chép!" + }, + "time": { + "days": "Ngày", + "hours": "Giờ", + "minutes": "Phút", + "seconds": "Giây", + "unit": "Đơn vị" + } +} \ No newline at end of file diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ess.dtsi b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ess.dtsi index a42b7bbeaa..384d7e36f5 100644 --- a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ess.dtsi +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ess.dtsi @@ -59,10 +59,12 @@ resets = <&gcc GCC_GMAC0_BCR>, <&gcc GCC_GMAC1_BCR>, <&gcc GCC_UNIPHY_BCR>, + <&gcc GCC_UNIPHY_AHB_ARES>, <&gcc GCC_UNIPHY_SOFT_RESET>; reset-names = "gmac0_bcr_rst", "gmac1_bcr_rst", "uniphy_bcr_rst", + "uniphy1_ahb_rst", "uniphy1_soft_rst"; status = "disabled"; diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-gl-b3000.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-gl-b3000.dts index 4ddfa2644a..9bb1fabe82 100644 --- a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-gl-b3000.dts +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-gl-b3000.dts @@ -1,31 +1,31 @@ -// SPDX-License-Identifier: (GPL-2.0+) +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT /dts-v1/; + #include "ipq5018.dtsi" #include "ipq5018-ess.dtsi" + #include #include +#include / { - #address-cells = <0x2>; - #size-cells = <0x2>; model = "GL.iNet GL-B3000"; compatible = "glinet,gl-b3000", "qcom,ipq5018"; - interrupt-parent = <&intc>; aliases { ethernet1 = &dp2; label-mac-device = &dp2; + led-boot = &led_system_blue; + led-failsafe = &led_status_white; + led-running = &led_status_white; + led-upgrade = &led_system_blue; serial0 = &blsp1_uart1; - led-boot = &led_blue; - led-failsafe = &led_blue; - led-running = &led_blue; - led-upgrade = &led_white; }; chosen { + bootargs-append = " root=/dev/ubiblock0_1 swiotlb=1 coherent_pool=2M"; stdout-path = "serial0:115200n8"; - bootargs-append = " root=/dev/ubiblock0_1"; }; keys { @@ -35,8 +35,8 @@ reset { label = "reset"; - linux,code = ; gpios = <&tlmm 27 GPIO_ACTIVE_LOW>; + linux,code = ; }; }; @@ -45,23 +45,20 @@ pinctrl-0 = <&leds_pins>; pinctrl-names = "default"; - led_blue: status_blue { - label = "blue:status"; + led_system_blue: led_system_blue { + color = ; + function = LED_FUNCTION_POWER; gpio = <&tlmm 24 GPIO_ACTIVE_HIGH>; }; - led_white: status_white { - label = "white:status"; + led_status_white: led_status_white { + color = ; + function = LED_FUNCTION_POWER; gpio = <&tlmm 23 GPIO_ACTIVE_HIGH>; }; }; reserved-memory { - tz_appps@4a400000 { - no-map; - reg = <0x0 0x4a400000 0x0 0x400000>; - }; - q6_mem_regions: q6_mem_regions@4b000000 { no-map; reg = <0x0 0x4b000000 0x0 0x3000000>; @@ -69,6 +66,118 @@ }; }; +&switch { + status = "okay"; + switch_mac_mode = ; + + qcom,port_phyinfo { + // MAC0 -> GE Phy -> QCA8337 Phy2 + port@0 { + port_id = <1>; + mdiobus = <&mdio0>; + phy_address = <7>; + }; + + // MAC1 ---SGMII---> QCA8337 SerDes + port@1 { + port_id = <2>; + forced-speed = <1000>; + forced-duplex = <1>; + }; + }; +}; + +// MAC1 ---SGMII---> QCA8337 SerDes +&dp2 { + status = "okay"; + nvmem-cells = <&macaddr_dp2>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&mdio0 { + status = "okay"; +}; + +&mdio1 { + status = "okay"; + pinctrl-0 = <&mdio1_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>; + + // QCA8337 Phy0 -> WAN + qca8337_0: ethernet-phy@0 { + reg = <0>; + }; + + // QCA8337 Phy1 -> LAN1 + qca8337_1: ethernet-phy@1 { + reg = <1>; + }; + + // QCA8337 Phy3 -> LAN2 + qca8337_2: ethernet-phy@2 { + reg = <2>; + }; + + // QCA8337 switch + switch0: ethernet-switch@17 { + compatible = "qca,qca8337"; + reg = <17>; + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + switch0cpu: port@0 { + reg = <0>; + label = "cpu"; + phy-mode = "sgmii"; + ethernet = <&dp2>; + qca,sgmii-enable-pll; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + // QCA8337 Phy0 -> WAN + port@1 { + reg = <1>; + label = "wan"; + phy-handle = <&qca8337_0>; + }; + + // QCA8337 Phy1 -> LAN1 + port@2 { + reg = <2>; + label = "lan1"; + phy-handle = <&qca8337_1>; + + nvmem-cells = <&macaddr_dp2 2>; + nvmem-cell-names = "mac-address"; + }; + + // QCA8337 Phy3 -> LAN2 + port@3 { + reg = <3>; + label = "lan2"; + phy-handle = <&qca8337_2>; + + nvmem-cells = <&macaddr_dp2 2>; + nvmem-cell-names = "mac-address"; + }; + }; + }; +}; + &sleep_clk { clock-frequency = <32000>; }; @@ -78,7 +187,7 @@ }; &blsp1_uart1 { - pinctrl-0 = <&blsp0_uart_pins>; + pinctrl-0 = <&serial_0_pins>; pinctrl-names = "default"; status = "okay"; }; @@ -91,184 +200,12 @@ status = "okay"; }; -&dp1 { - status = "okay"; -}; - -&dp2 { - phy-mode = "sgmii"; - status = "okay"; - - fixed-link { - speed = <1000>; - full-duplex; - }; -}; - -&ge_phy { - status = "okay"; -}; - -&mdio0 { - status = "okay"; -}; - -&mdio1 { - pinctrl-0 = <&mdio1_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>; - status = "okay"; - - // QCA8337 Phy0 -> WAN - qca8337_0: ethernet-phy@0 { - reg = <0>; - }; - // QCA8337 Phy1 -> LAN1 - qca8337_1: ethernet-phy@1 { - reg = <1>; - }; - // QCA8337 Phy3 -> LAN2 - qca8337_2: ethernet-phy@2 { - reg = <2>; - }; - // QCA8337 Phy2 -> IPQ5018 GE Phy - qca8337_3: ethernet-phy@3 { - reg = <3>; - }; - // QCA8337 switch - switch0: ethernet-switch@17 { - compatible = "qca,qca8337"; - reg = <17>; - #address-cells = <1>; - #size-cells = <0>; - switch_cpu_bmp = <0x40>; /* cpu port bitmap */ - switch_lan_bmp = <0x0c>; /* lan port bitmap */ - switch_wan_bmp = <0x02>; /* wan port bitmap */ - - ports { - #address-cells = <1>; - #size-cells = <0>; - - switch0cpu: port@0 { - reg = <0>; - label = "cpu"; - phy-mode = "sgmii"; - ethernet = <&dp2>; - qca,sgmii-enable-pll; - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - // QCA8337 Phy0 -> WAN - port@1 { - reg = <1>; - label = "wan"; - phy-handle = <&qca8337_0>; - port_id = <1>; - phy_address = <0>; - }; - - // QCA8337 Phy1 -> LAN1 - port@2 { - reg = <2>; - label = "lan1"; - phy-handle = <&qca8337_1>; - port_id = <2>; - phy_address = <1>; - }; - // QCA8337 Phy3 -> LAN2 - port@3 { - reg = <3>; - label = "lan2"; - phy-handle = <&qca8337_2>; - port_id = <3>; - phy_address = <2>; - }; - }; - }; -}; - &prng { status = "okay"; }; -&q6v5_wcss { +&qfprom { status = "okay"; - memory-region = <&q6_mem_regions>; - firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt", - "ath11k/IPQ5018/hw1.0/m3_fw.mdt", - "ath11k/qcn6122/hw1.0/m3_fw.mdt"; - - boot-args = - ; - - // IPQ5018 - q6_wcss_pd1: pd-1 { - firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt"; - resets = - <&gcc GCC_WCSSAON_RESET>, - <&gcc GCC_WCSS_BCR>, - <&gcc GCC_CE_BCR>; - reset-names = - "wcss_aon_reset", - "wcss_reset", - "ce_reset"; - clocks = - <&gcc GCC_WCSS_AHB_S_CLK>, - <&gcc GCC_WCSS_ACMT_CLK>, - <&gcc GCC_WCSS_AXI_M_CLK>; - clock-names = - "gcc_wcss_ahb_s_clk", - "gcc_wcss_acmt_clk", - "gcc_wcss_axi_m_clk"; - - interrupts-extended = - <&wcss_smp2p_in 8 0>, - <&wcss_smp2p_in 9 0>, - <&wcss_smp2p_in 12 0>, - <&wcss_smp2p_in 11 0>; - interrupt-names = - "fatal", - "ready", - "spawn-ack", - "stop-ack"; - qcom,smem-states = - <&wcss_smp2p_out 8>, - <&wcss_smp2p_out 9>, - <&wcss_smp2p_out 10>; - qcom,smem-state-names = - "shutdown", - "stop", - "spawn"; - }; - - // QCN6102 5G - q6_wcss_pd3: pd-3 { - firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt"; - interrupts-extended = - <&wcss_smp2p_in 24 0>, - <&wcss_smp2p_in 25 0>, - <&wcss_smp2p_in 28 0>, - <&wcss_smp2p_in 27 0>; - interrupt-names = - "fatal", - "ready", - "spawn-ack", - "stop-ack"; - qcom,smem-states = - <&wcss_smp2p_out 24>, - <&wcss_smp2p_out 25>, - <&wcss_smp2p_out 26>; - qcom,smem-state-names = - "shutdown", - "stop", - "spawn"; - }; }; &qpic_bam { @@ -282,69 +219,40 @@ nand@0 { compatible = "spi-nand"; + reg = <0>; #address-cells = <1>; #size-cells = <1>; - reg = <0>; nand-ecc-engine = <&qpic_nand>; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; nand-bus-width = <8>; partitions { compatible = "qcom,smem-part"; - }; - }; -}; -&switch { - switch_mac_mode = ; - status = "okay"; + partition-0-art { + compatible = "fixed-partitions"; + label = "0:ART"; + read-only; + #address-cells = <1>; + #size-cells = <1>; - qcom,port_phyinfo { - // MAC0 -> GE Phy -> QCA8337 Phy2 - port@0 { - port_id = <1>; - mdiobus = <&mdio0>; - phy_address = <7>; - phy_dac = <0x10 0x10>; - }; - // MAC1 ---SGMII---> QCA8337 SerDes - port@1 { - port_id = <2>; - forced-speed = <1000>; - forced-duplex = <1>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_dp2: macaddr@0 { + compatible = "mac-base"; + #nvmem-cell-cells = <1>; + reg = <0x0 0x6>; + }; + }; + }; }; }; }; &tlmm { - blsp0_uart_pins: uart_pins { - blsp0_uart_rx_tx { - pins = "gpio20", "gpio21"; - function = "blsp0_uart0"; - bias-disable; - }; - }; - - button_pins: button_pins { - mux { - pins = "gpio27"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - leds_pins: leds_pins { - mux { - pins = "gpio23", "gpio24"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; - mdio1_pins: mdio-state { mdc-pins { pins = "gpio36"; @@ -352,6 +260,7 @@ drive-strength = <8>; bias-pull-up; }; + mdio-pins { pins = "gpio37"; function = "mdio"; @@ -360,6 +269,20 @@ }; }; + leds_pins: leds-pins { + pins = "gpio23", "gpio24"; + function = "gpio"; + drive-strength = <8>; + bias-pull-down; + }; + + button_pins: button-pins { + pins = "gpio27"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + qpic_pins: qpic-state { clock-pins { pins = "gpio9"; @@ -367,12 +290,14 @@ drive-strength = <8>; bias-disable; }; + cs-pins { pins = "gpio8"; function = "qspi_cs"; drive-strength = <8>; bias-disable; }; + data-pins { pins = "gpio4", "gpio5", "gpio6", "gpio7"; function = "qspi_data"; @@ -380,23 +305,124 @@ bias-disable; }; }; + + serial_0_pins: uart0-state { + pins = "gpio20", "gpio21"; + function = "blsp0_uart0"; + drive-strength = <8>; + bias-disable; + }; +}; + +&tsens { + status = "okay"; +}; + +&q6v5_wcss { + status = "okay"; + + memory-region = <&q6_mem_regions>; + firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt", + "ath11k/IPQ5018/hw1.0/m3_fw.mdt", + "ath11k/QCN6122/hw1.0/m3_fw.mdt"; + + /* B3000 currently doesn't support passing bootargs */ + /*boot-args = < */ + /* type: 0x1 PCIE0 */ + /* length: 4 */ + /* PD id: 3 */ + /* reset GPIO: 15 */ + /* reserved: 0 0>; */ + + // IPQ5018 + q6_wcss_pd1: pd-1 { + firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt"; + + resets = + <&gcc GCC_WCSSAON_RESET>, + <&gcc GCC_WCSS_BCR>, + <&gcc GCC_CE_BCR>; + reset-names = + "wcss_aon_reset", + "wcss_reset", + "ce_reset"; + + clocks = + <&gcc GCC_WCSS_AHB_S_CLK>, + <&gcc GCC_WCSS_ACMT_CLK>, + <&gcc GCC_WCSS_AXI_M_CLK>; + clock-names = + "gcc_wcss_ahb_s_clk", + "gcc_wcss_acmt_clk", + "gcc_wcss_axi_m_clk"; + + // qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>; + interrupts-extended = + <&wcss_smp2p_in 8 IRQ_TYPE_NONE>, + <&wcss_smp2p_in 9 IRQ_TYPE_NONE>, + <&wcss_smp2p_in 12 IRQ_TYPE_NONE>, + <&wcss_smp2p_in 11 IRQ_TYPE_NONE>; + interrupt-names = + "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = + <&wcss_smp2p_out 8>, + <&wcss_smp2p_out 9>, + <&wcss_smp2p_out 10>; + qcom,smem-state-names = + "shutdown", + "stop", + "spawn"; + }; + + // QCN6102 5G + q6_wcss_pd3: pd-3 { + firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt"; + + interrupts-extended = + <&wcss_smp2p_in 24 IRQ_TYPE_NONE>, + <&wcss_smp2p_in 25 IRQ_TYPE_NONE>, + <&wcss_smp2p_in 28 IRQ_TYPE_NONE>, + <&wcss_smp2p_in 27 IRQ_TYPE_NONE>; + interrupt-names = + "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = + <&wcss_smp2p_out 24>, + <&wcss_smp2p_out 25>, + <&wcss_smp2p_out 26>; + qcom,smem-state-names = + "shutdown", + "stop", + "spawn"; + }; }; &wifi0 { + // IPQ5018 + status = "okay"; + qcom,rproc = <&q6_wcss_pd1>; qcom,userpd-subsys-name = "q6v5_wcss_userpd1"; qcom,ath11k-calibration-variant = "GL-iNet-GL-B3000"; - qcom,ath11k-fw-memory-mode = <2>; + qcom,ath11k-fw-memory-mode = <1>; qcom,bdf-addr = <0x4c400000>; - status = "okay"; }; &wifi1 { + // QCN6102 5G + status = "okay"; + qcom,rproc = <&q6_wcss_pd3>; qcom,userpd-subsys-name = "q6v5_wcss_userpd3"; qcom,ath11k-calibration-variant = "GL-iNet-GL-B3000"; - qcom,ath11k-fw-memory-mode = <2>; + qcom,ath11k-fw-memory-mode = <1>; qcom,bdf-addr = <0x4d100000>; qcom,m3-dump-addr = <0x4df00000>; - status = "okay"; }; diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mr5500.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mr5500.dts new file mode 100644 index 0000000000..a92a60482b --- /dev/null +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mr5500.dts @@ -0,0 +1,379 @@ +/dts-v1/; + +#include "ipq5018.dtsi" +#include "ipq5018-mx-base.dtsi" + +/ { + model = "Linksys MR5500"; + compatible = "linksys,mr5500", "qcom,ipq5018"; + + gpio-leds { + compatible = "gpio-leds"; + + usb { + color = ; + function = LED_FUNCTION_USB; + gpios = <&tlmm 19 GPIO_ACTIVE_HIGH>; + trigger-sources = <&usb_port1>; + linux,default-trigger = "usbport"; + }; + }; + + regulator_fixed_5p0: regulator-s0500 { + compatible = "regulator-fixed"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <500000>; + regulator-name = "fixed_5p0"; + gpio = <&tlmm 17 GPIO_ACTIVE_LOW>; + }; +}; + +/* + * =============================================================== + * _______________________ _______________________ + * | IPQ5018 | | QCA8337 | + * | +------+ +--------+ | | +--------+ +------+ | + * | | MAC0 |---| GE Phy | | | | Phy0 |---| MAC1 | | + * | +------+ +--------+ | | +--------+ +------+ | + * | +------+ +--------+ | | +--------+ +------+ | + * | | MAC1 |---| Uniphy |-+-SGMII-+-| SerDes |---| MAC6 | | + * | +------+ +--------+ | | +--------+ +------+ | + * |_______________________| |_______________________| + * + * =============================================================== + */ + +&switch { + status = "okay"; + + switch_mac_mode = ; + + qcom,port_phyinfo { + // MAC0 -> GE Phy + port@0 { + port_id = <1>; + mdiobus = <&mdio0>; + phy_address = <7>; + }; + + // MAC1 ---SGMII---> QCA8337 SerDes + port@1 { + port_id = <2>; + forced-speed = <1000>; + forced-duplex = <1>; + }; + }; +}; + +// MAC1 ---SGMII---> QCA8337 SerDes +&dp2 { + status = "okay"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&mdio0 { + status = "okay"; +}; + +&mdio1 { + status = "okay"; + + pinctrl-0 = <&mdio1_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>; + + switch1: ethernet-switch@17 { + compatible = "qca,qca8337"; + reg = <17>; + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan1"; + phy-handle = <&qca8337_0>; + phy-mode = "internal"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + default-state = "keep"; + }; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_LAN; + default-state = "keep"; + }; + }; + }; + + port@2 { + reg = <2>; + label = "lan2"; + phy-handle = <&qca8337_1>; + phy-mode = "internal"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + default-state = "keep"; + }; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_LAN; + default-state = "keep"; + }; + }; + }; + + port@3 { + reg = <3>; + label = "lan3"; + phy-handle = <&qca8337_2>; + phy-mode = "internal"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + default-state = "keep"; + }; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_LAN; + default-state = "keep"; + }; + }; + }; + + port@4 { + reg = <4>; + label = "lan4"; + phy-handle = <&qca8337_3>; + phy-mode = "internal"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + default-state = "keep"; + }; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_LAN; + default-state = "keep"; + }; + }; + }; + + port@5 { + reg = <5>; + label = "wan"; + phy-handle = <&qca8337_4>; + phy-mode = "internal"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_WAN; + default-state = "keep"; + }; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_WAN; + default-state = "keep"; + }; + }; + }; + + port@6 { + reg = <6>; + label = "cpu"; + phy-mode = "sgmii"; + ethernet = <&dp2>; + qca,sgmii-enable-pll; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + // QCA8337 Phy0 -> LAN1 + qca8337_0: ethernet-phy@0 { + reg = <0>; + }; + + // QCA8337 Phy1 -> LAN2 + qca8337_1: ethernet-phy@1 { + reg = <1>; + }; + + // QCA8337 Phy2 -> LAN3 + qca8337_2: ethernet-phy@2 { + reg = <2>; + }; + + // QCA8337 Phy3 -> LAN4 + qca8337_3: ethernet-phy@3 { + reg = <3>; + }; + + // QCA8337 Phy4 -> WAN + qca8337_4: ethernet-phy@4 { + reg = <4>; + }; + }; + }; +}; + +&usbphy0 { + status = "okay"; + + vdd-supply = <®ulator_fixed_5p0>; +}; + +&usb { + status = "okay"; + + vbus-supply = <®ulator_fixed_5p0>; +}; + +&usb_dwc { + #address-cells = <1>; + #size-cells = <0>; + dr_mode = "host"; + + usb_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; +}; + +&pcie0_phy { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + perst-gpios = <&tlmm 15 GPIO_ACTIVE_LOW>; + + pcie@0 { + wifi@0,0 { + status = "okay"; + + /* QCN9074: ath11k lacks DT compatible for PCI cards */ + compatible = "pci17cb,1104"; + reg = <0x00010000 0 0 0 0>; + + qcom,ath11k-calibration-variant = "Linksys-MR5500"; + }; + }; +}; + +&q6v5_wcss { + status = "okay"; + + memory-region = <&q6_mem_regions>; + firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt", + "ath11k/IPQ5018/hw1.0/m3_fw.mdt"; + + // IPQ5018 + q6_wcss_pd1: pd-1 { + firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt"; + + resets = + <&gcc GCC_WCSSAON_RESET>, + <&gcc GCC_WCSS_BCR>, + <&gcc GCC_CE_BCR>; + reset-names = + "wcss_aon_reset", + "wcss_reset", + "ce_reset"; + + clocks = + <&gcc GCC_WCSS_AHB_S_CLK>, + <&gcc GCC_WCSS_ACMT_CLK>, + <&gcc GCC_WCSS_AXI_M_CLK>; + clock-names = + "gcc_wcss_ahb_s_clk", + "gcc_wcss_acmt_clk", + "gcc_wcss_axi_m_clk"; + + interrupts-extended = + <&wcss_smp2p_in 8 0>, + <&wcss_smp2p_in 9 0>, + <&wcss_smp2p_in 12 0>, + <&wcss_smp2p_in 11 0>; + interrupt-names = + "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = + <&wcss_smp2p_out 8>, + <&wcss_smp2p_out 9>, + <&wcss_smp2p_out 10>; + qcom,smem-state-names = + "shutdown", + "stop", + "spawn"; + }; +}; + +&wifi0 { + // IPQ5018 + qcom,rproc = <&q6_wcss_pd1>; + qcom,ath11k-calibration-variant = "Linksys-MR5500"; + qcom,ath11k-fw-memory-mode = <1>; + qcom,bdf-addr = <0x4c400000>; + + status = "okay"; +}; diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi index 57fe5c53a9..27d0236926 100644 --- a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi @@ -6,10 +6,7 @@ #include / { - aliases { - ethernet0 = &dp1; - ethernet1 = &dp2; led-boot = &led_system_blue; led-failsafe = &led_system_red; led-running = &led_system_blue; @@ -132,9 +129,6 @@ #size-cells = <1>; nand-ecc-engine = <&qpic_nand>; - - nand-ecc-strength = <8>; - nand-ecc-step-size = <512>; nand-bus-width = <8>; partitions { diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx2000.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx2000.dts index db045d9a5c..e254f03439 100644 --- a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx2000.dts +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx2000.dts @@ -48,7 +48,6 @@ // MAC1 ---SGMII---> QCA8337 SerDes &dp2 { status = "okay"; - phy-mode = "sgmii"; fixed-link { speed = <1000>; @@ -60,13 +59,6 @@ status = "okay"; }; -/* IPQ5018 GE Phy -> Not connected - * needs to be enabled for QSDK to identify the IPQ5018 dummy switch - */ -&ge_phy { - status = "okay"; -}; - &mdio1 { status = "okay"; @@ -155,8 +147,8 @@ memory-region = <&q6_mem_regions>; firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt", - "ath11k/IPQ5018/hw1.0/m3_fw.mdt", - "ath11k/QCN6122/hw1.0/m3_fw.mdt"; + "ath11k/IPQ5018/hw1.0/m3_fw.mdt", + "ath11k/QCN6122/hw1.0/m3_fw.mdt"; /* The QCN6102 radio should map to UPD ID 2. Without */ /* bootargs, the firmware will expect it to be on UPD ID 3 */ @@ -243,7 +235,7 @@ // IPQ5018 qcom,rproc = <&q6_wcss_pd1>; qcom,ath11k-calibration-variant = "Linksys-MX2000"; - qcom,ath11k-fw-memory-mode = <2>; + qcom,ath11k-fw-memory-mode = <1>; qcom,bdf-addr = <0x4c400000>; status = "okay"; @@ -254,7 +246,7 @@ qcom,rproc = <&q6_wcss_pd2>; qcom,userpd-subsys-name = "q6v5_wcss_userpd2"; qcom,ath11k-calibration-variant = "Linksys-MX2000"; - qcom,ath11k-fw-memory-mode = <2>; + qcom,ath11k-fw-memory-mode = <1>; qcom,bdf-addr = <0x4d100000>; qcom,m3-dump-addr = <0x4df00000>; diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx5500.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx5500.dts index 43672d3b53..f7a6936b38 100644 --- a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx5500.dts +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx5500.dts @@ -48,7 +48,6 @@ // MAC1 ---SGMII---> QCA8337 SerDes &dp2 { status = "okay"; - phy-mode = "sgmii"; fixed-link { speed = <1000>; @@ -60,13 +59,6 @@ status = "okay"; }; -/* IPQ5018 GE Phy -> Not connected - * needs to be enabled for QSDK to identify the IPQ5018 dummy switch - */ -&ge_phy { - status = "okay"; -}; - &mdio1 { status = "okay"; @@ -159,13 +151,8 @@ perst-gpios = <&tlmm 15 GPIO_ACTIVE_LOW>; - bridge@0,0 { - reg = <0x00000000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - ranges; - - wifi@1,0 { + pcie@0 { + wifi@0,0 { status = "okay"; /* QCN9074: ath11k lacks DT compatible for PCI cards */ @@ -182,7 +169,7 @@ memory-region = <&q6_mem_regions>; firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt", - "ath11k/IPQ5018/hw1.0/m3_fw.mdt"; + "ath11k/IPQ5018/hw1.0/m3_fw.mdt"; // IPQ5018 q6_wcss_pd1: pd-1 { @@ -233,7 +220,7 @@ // IPQ5018 qcom,rproc = <&q6_wcss_pd1>; qcom,ath11k-calibration-variant = "Linksys-MX5500"; - qcom,ath11k-fw-memory-mode = <2>; + qcom,ath11k-fw-memory-mode = <1>; qcom,bdf-addr = <0x4c400000>; status = "okay"; diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-spnmx56.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-spnmx56.dts new file mode 100644 index 0000000000..dc287ce5ff --- /dev/null +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-spnmx56.dts @@ -0,0 +1,235 @@ +/dts-v1/; + +#include "ipq5018.dtsi" +#include "ipq5018-mx-base.dtsi" + +/ { + model = "Linksys SPNMX56"; + compatible = "linksys,spnmx56", "qcom,ipq5018"; +}; + +/* +* ================================================================= +* _______________________ _______________________ +* | IPQ5018 | | QCA8337 | +* | +------+ +--------+ | | +--------+ +------+ | +* | | MAC0 |---| GE Phy |-+--- MDI ---+ | Phy4 |---| MAC5 | | +* | +------+ +--------+ | | +--------+ +------+ | +* | | |_______________________| +* | | _______________________ +* | | | QCA8081 | +* | +------+ +--------+ | | +--------+ +------+ | +* | | MAC1 |---| Uniphy |-+-- SGMII+--+ | Phy |---| MAC | | +* | +------+ +--------+ | | +--------+ +------+ | +* |_______________________| |_______________________| +* +* ================================================================= +*/ + +&switch { + status = "okay"; + + switch_mac_mode = ; + + qcom,port_phyinfo { + // MAC0 -> GE Phy --- MDI --- QCA8337 Switch + port@0 { + port_id = <1>; + mdiobus = <&mdio0>; + phy_address = <7>; + phy_dac = <0x10 0x10>; + }; + + // MAC1 -> Uniphy --- SGMII --- QCA8081 + port@1 { + port_id = <2>; + mdiobus = <&mdio1>; + phy_address = <28>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +// MAC0 -> GE Phy +&dp1 { + status = "okay"; +}; + +// MAC1 ---SGMII---> QCA8081 +&dp2 { + status = "okay"; + + label = "wan"; + phy-handle = <&qca8081>; +}; + +&mdio0 { + status = "okay"; +}; + +// IPQ5018 GE Phy -> QCA8337 PHY4 +&ge_phy { + qcom,dac-preset-short-cable; +}; + +&mdio1 { + status = "okay"; + + pinctrl-0 = <&mdio1_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>; + + // Not connected + qca8337_0: ethernet-phy@0 { + reg = <0>; + }; + + // QCA8337 Phy1 -> LAN1 + qca8337_1: ethernet-phy@1 { + reg = <1>; + }; + + // QCA8337 Phy2 -> LAN2 + qca8337_2: ethernet-phy@2 { + reg = <2>; + }; + + // QCA8337 Phy3 -> LAN3 + qca8337_3: ethernet-phy@3 { + reg = <3>; + }; + + // QCA8337 Phy4 -> MDI -> IPQ5018 GE PHY + qca8337_4: ethernet-phy@4 { + reg = <4>; + }; + + // QCA8081 Phy -> WAN + qca8081: ethernet-phy@28 { + compatible = "ethernet-phy-id004d.d101"; + reg = <28>; + reset-deassert-us = <10000>; + reset-gpios = <&tlmm 24 GPIO_ACTIVE_LOW>; + }; + + // QCA8337 switch + switch1: ethernet-switch@17 { + compatible = "qca,qca8337"; + reg = <17>; + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + label = "lan3"; + phy-handle = <&qca8337_1>; + }; + + port@3 { + reg = <3>; + label = "lan2"; + phy-handle = <&qca8337_2>; + }; + + port@4 { + reg = <4>; + label = "lan1"; + phy-handle = <&qca8337_3>; + }; + + port@5 { + reg = <5>; + phy-handle = <&qca8337_4>; + phy-mode = "gmii"; + ethernet = <&dp1>; + }; + }; + }; +}; + +&pcie0_phy { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + perst-gpios = <&tlmm 15 GPIO_ACTIVE_LOW>; + + pcie@0 { + wifi@0,0 { + status = "okay"; + + /* QCN9074: ath11k lacks DT compatible for PCI cards */ + compatible = "pci17cb,1104"; + reg = <0x00010000 0 0 0 0>; + + qcom,ath11k-calibration-variant = "Linksys-SPNMX56"; + }; + }; +}; + +&q6v5_wcss { + status = "okay"; + + memory-region = <&q6_mem_regions>; + firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt", + "ath11k/IPQ5018/hw1.0/m3_fw.mdt"; + + // IPQ5018 + q6_wcss_pd1: pd-1 { + firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt"; + + resets = + <&gcc GCC_WCSSAON_RESET>, + <&gcc GCC_WCSS_BCR>, + <&gcc GCC_CE_BCR>; + reset-names = + "wcss_aon_reset", + "wcss_reset", + "ce_reset"; + + clocks = + <&gcc GCC_WCSS_AHB_S_CLK>, + <&gcc GCC_WCSS_ACMT_CLK>, + <&gcc GCC_WCSS_AXI_M_CLK>; + clock-names = + "gcc_wcss_ahb_s_clk", + "gcc_wcss_acmt_clk", + "gcc_wcss_axi_m_clk"; + + interrupts-extended = + <&wcss_smp2p_in 8 0>, + <&wcss_smp2p_in 9 0>, + <&wcss_smp2p_in 12 0>, + <&wcss_smp2p_in 11 0>; + interrupt-names = + "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = + <&wcss_smp2p_out 8>, + <&wcss_smp2p_out 9>, + <&wcss_smp2p_out 10>; + qcom,smem-state-names = + "shutdown", + "stop", + "spawn"; + }; +}; + +&wifi0 { + // IPQ5018 + qcom,rproc = <&q6_wcss_pd1>; + qcom,ath11k-calibration-variant = "Linksys-SPNMX56"; + qcom,ath11k-fw-memory-mode = <1>; + qcom,bdf-addr = <0x4c400000>; + + status = "okay"; +}; diff --git a/lede/target/linux/qualcommax/image/ipq50xx.mk b/lede/target/linux/qualcommax/image/ipq50xx.mk index 2de1b7669d..661f18cd40 100644 --- a/lede/target/linux/qualcommax/image/ipq50xx.mk +++ b/lede/target/linux/qualcommax/image/ipq50xx.mk @@ -5,29 +5,21 @@ define Device/EmmcImage IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-to 64k | sysupgrade-tar rootfs=$$$$@ | append-metadata endef -define Device/cmcc_rax3000q - $(call Device/FitImage) - $(call Device/UbiFit) - SOC := ipq5018 - DEVICE_VENDOR := CMCC - DEVICE_MODEL := RAX3000Q - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@mp02.1 - DEVICE_PACKAGES := ath11k-firmware-qcn6122 ipq-wifi-cmcc_rax3000q -endef -TARGET_DEVICES += cmcc_rax3000q - define Device/glinet_gl-b3000 - $(call Device/FitImage) - $(call Device/UbiFit) - SOC := ipq5018 - DEVICE_VENDOR := GL.iNET - DEVICE_MODEL := GL-B3000 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@mp03.5-c1 - DEVICE_PACKAGES := ath11k-firmware-qcn6122 ipq-wifi-gl-b3000 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := GL.iNet + DEVICE_MODEL := GL-B3000 + SOC := ipq5018 + KERNEL_IN_UBI := 1 + BLOCKSIZE := 128k + PAGESIZE := 2048 + NAND_SIZE := 128m + DEVICE_DTS_CONFIG := config@mp03.5-c1 + SUPPORTED_DEVICES += b3000 + DEVICE_PACKAGES := \ + ath11k-firmware-qcn6122 \ + ipq-wifi-glinet_gl-b3000 endef TARGET_DEVICES += glinet_gl-b3000 @@ -57,6 +49,17 @@ define Device/linksys_ipq50xx_mx_base append-ubi | linksys-image type=$$$$(DEVICE_MODEL) endef +define Device/linksys_mr5500 + $(call Device/linksys_ipq50xx_mx_base) + DEVICE_MODEL := MR5500 + DEVICE_DTS_CONFIG := config@mp03.1 + DEVICE_PACKAGES := kmod-ath11k-pci \ + ath11k-firmware-qcn9074 \ + ipq-wifi-linksys_mr5500 \ + kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += linksys_mr5500 + define Device/linksys_mx2000 $(call Device/linksys_ipq50xx_mx_base) DEVICE_MODEL := MX2000 @@ -75,3 +78,13 @@ define Device/linksys_mx5500 ipq-wifi-linksys_mx5500 endef TARGET_DEVICES += linksys_mx5500 + +define Device/linksys_spnmx56 + $(call Device/linksys_ipq50xx_mx_base) + DEVICE_MODEL := SPNMX56 + DEVICE_DTS_CONFIG := config@mp03.1 + DEVICE_PACKAGES := kmod-ath11k-pci \ + ath11k-firmware-qcn9074 \ + ipq-wifi-linksys_spnmx56 +endef +TARGET_DEVICES += linksys_spnmx56 diff --git a/lede/target/linux/qualcommax/ipq50xx/base-files/etc/board.d/02_network b/lede/target/linux/qualcommax/ipq50xx/base-files/etc/board.d/02_network index 0beda336ff..ef881c940e 100644 --- a/lede/target/linux/qualcommax/ipq50xx/base-files/etc/board.d/02_network +++ b/lede/target/linux/qualcommax/ipq50xx/base-files/etc/board.d/02_network @@ -10,12 +10,15 @@ ipq50xx_setup_interfaces() glinet,gl-b3000) ucidef_set_interfaces_lan_wan "lan1 lan2" "wan" ;; - cmcc,rax3000q|\ jdcloud,re-cs-03|\ linksys,mx2000|\ - linksys,mx5500) + linksys,mx5500|\ + linksys,spnmx56) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" ;; + linksys,mr5500) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" + ;; esac } @@ -27,12 +30,13 @@ ipq50xx_setup_macs() local label_mac="" case "$board" in + linksys,mr5500|\ linksys,mx2000|\ - linksys,mx5500) + linksys,mx5500|\ + linksys,spnmx56) label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) lan_mac=$label_mac wan_mac=$label_mac - ucidef_set_network_device_mac eth0 $label_mac ;; esac diff --git a/lede/target/linux/qualcommax/ipq50xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/lede/target/linux/qualcommax/ipq50xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata index e815bc17fe..890525190b 100644 --- a/lede/target/linux/qualcommax/ipq50xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata +++ b/lede/target/linux/qualcommax/ipq50xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata @@ -9,18 +9,15 @@ board=$(board_name) case "$FIRMWARE" in "ath11k/IPQ5018/hw1.0/cal-ahb-c000000.wifi.bin") case "$board" in - cmcc,rax3000q|\ glinet,gl-b3000) - caldata_extract "0:ART" 0x1000 0x20000 - addr=$(mtd_get_mac_binary "0:ART" 0x6) - ath11k_patch_mac $(macaddr_add $addr 3) 0 + caldata_extract "0:art" 0x1000 0x20000 + ath11k_patch_mac $(macaddr_add $(get_mac_label_dt) 3) 0 ath11k_set_macflag ;; - jdcloud,re-cs-03) - caldata_extract_mmc "0:ART" 0x1000 0x20000 - ;; + linksys,mr5500|\ linksys,mx2000|\ - linksys,mx5500) + linksys,mx5500|\ + linksys,spnmx56) caldata_extract "0:ART" 0x1000 0x20000 label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) ath11k_patch_mac $(macaddr_add $label_mac 1) 0 @@ -31,16 +28,11 @@ case "$FIRMWARE" in ;; "ath11k/QCN6122/hw1.0/cal-ahb-b00a040.wifi1.bin") case "$board" in - cmcc,rax3000q|\ glinet,gl-b3000) - caldata_extract "0:ART" 0x26800 0x20000 - addr=$(mtd_get_mac_binary "0:ART" 0x6) - ath11k_patch_mac $(macaddr_add $addr 4) 0 + caldata_extract "0:art" 0x26800 0x20000 + ath11k_patch_mac $(macaddr_add $(get_mac_label_dt) 4) 0 ath11k_set_macflag ;; - jdcloud,re-cs-03) - caldata_extract_mmc "0:ART" 0x26800 0x20000 - ;; linksys,mx2000) caldata_extract "0:ART" 0x26800 0x20000 label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) @@ -50,9 +42,11 @@ case "$FIRMWARE" in ;; esac ;; -"ath11k/QCN9074/hw1.0/cal-pci-0001:01:00.0.bin") +"ath11k/QCN9074/hw1.0/cal-pci-0000:01:00.0.bin") case "$board" in - linksys,mx5500) + linksys,mr5500|\ + linksys,mx5500|\ + linksys,spnmx56) caldata_extract "0:ART" 0x26800 0x20000 label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) ath11k_patch_mac $(macaddr_add $label_mac 2) 0 diff --git a/lede/target/linux/qualcommax/ipq50xx/base-files/etc/init.d/bootcount b/lede/target/linux/qualcommax/ipq50xx/base-files/etc/init.d/bootcount index b570428aef..0e573a1407 100755 --- a/lede/target/linux/qualcommax/ipq50xx/base-files/etc/init.d/bootcount +++ b/lede/target/linux/qualcommax/ipq50xx/base-files/etc/init.d/bootcount @@ -4,8 +4,10 @@ START=99 boot() { case $(board_name) in + linksys,mr5500|\ linksys,mx2000|\ - linksys,mx5500) + linksys,mx5500|\ + linksys,spnmx56) mtd resetbc s_env || true ;; esac diff --git a/lede/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh b/lede/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh index cb5ae74e7e..23733a0090 100644 --- a/lede/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh +++ b/lede/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh @@ -1,9 +1,70 @@ PART_NAME=firmware REQUIRE_IMAGE_METADATA=1 -RAMFS_COPY_BIN='fw_printenv fw_setenv head' +RAMFS_COPY_BIN='dumpimage fw_printenv fw_setenv head seq' RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' +remove_oem_ubi_volume() { + local oem_volume_name="$1" + local oem_ubivol + local mtdnum + local ubidev + + mtdnum=$(find_mtd_index "$CI_UBIPART") + if [ ! "$mtdnum" ]; then + return + fi + + ubidev=$(nand_find_ubi "$CI_UBIPART") + if [ ! "$ubidev" ]; then + ubiattach --mtdn="$mtdnum" + ubidev=$(nand_find_ubi "$CI_UBIPART") + fi + + if [ "$ubidev" ]; then + oem_ubivol=$(nand_find_volume "$ubidev" "$oem_volume_name") + [ "$oem_ubivol" ] && ubirmvol "/dev/$ubidev" --name="$oem_volume_name" + fi +} + +linksys_mx_pre_upgrade() { + local setenv_script="/tmp/fw_env_upgrade" + + CI_UBIPART="rootfs" + boot_part="$(fw_printenv -n boot_part)" + if [ -n "$UPGRADE_OPT_USE_CURR_PART" ]; then + if [ "$boot_part" -eq "2" ]; then + CI_KERNPART="alt_kernel" + CI_UBIPART="alt_rootfs" + fi + else + if [ "$boot_part" -eq "1" ]; then + echo "boot_part 2" >> $setenv_script + CI_KERNPART="alt_kernel" + CI_UBIPART="alt_rootfs" + else + echo "boot_part 1" >> $setenv_script + fi + fi + + boot_part_ready="$(fw_printenv -n boot_part_ready)" + if [ "$boot_part_ready" -ne "3" ]; then + echo "boot_part_ready 3" >> $setenv_script + fi + + auto_recovery="$(fw_printenv -n auto_recovery)" + if [ "$auto_recovery" != "yes" ]; then + echo "auto_recovery yes" >> $setenv_script + fi + + if [ -f "$setenv_script" ]; then + fw_setenv -s $setenv_script || { + echo "failed to update U-Boot environment" + return 1 + } + fi +} + platform_check_image() { return 0; } @@ -18,19 +79,12 @@ platform_do_upgrade() { CI_ROOTPART="rootfs" emmc_do_upgrade "$1" ;; + linksys,mr5500|\ linksys,mx2000|\ - linksys,mx5500) - boot_part="$(fw_printenv -n boot_part)" - if [ "$boot_part" -eq "1" ]; then - fw_setenv boot_part 2 - CI_KERNPART="alt_kernel" - CI_UBIPART="alt_rootfs" - else - fw_setenv boot_part 1 - CI_UBIPART="rootfs" - fi - fw_setenv boot_part_ready 3 - fw_setenv auto_recovery yes + linksys,mx5500|\ + linksys,spnmx56) + linksys_mx_pre_upgrade "$1" + remove_oem_ubi_volume squashfs nand_do_upgrade "$1" ;; *) diff --git a/openclash/.github/workflows/compile_meta_core.yml b/openclash/.github/workflows/compile_meta_core.yml index 912b23e030..61cf1a5c2d 100644 --- a/openclash/.github/workflows/compile_meta_core.yml +++ b/openclash/.github/workflows/compile_meta_core.yml @@ -1,5 +1,4 @@ - -name: Compile The New Clash Meta Core +name: Compile The New Clash Core on: schedule: @@ -11,7 +10,9 @@ jobs: runs-on: ubuntu-latest outputs: current_id: ${{ steps.current_id.outputs.current_id }} - upstream_id: ${{ steps.upstream_id.outputs.upstream_id }} + current_smart_id: ${{ steps.current_id.outputs.current_smart_id }} + upstream_id: ${{ steps.upstream_id.outputs.upstream_id }} + upstream_smart_id: ${{ steps.upstream_id.outputs.upstream_smart_id }} steps: - name: Apt Update env: @@ -28,26 +29,42 @@ jobs: - name: Get Current Version id: current_id run: | - echo "current_id=$(sed -n 3p ./dev/core_version)" >> $GITHUB_OUTPUT - echo "current_id: $(sed -n 3p ./dev/core_version)" + current_meta_ver=$(sed -n '1p' ./dev/core_version 2>/dev/null || echo "null") + echo "current_id=$current_meta_ver" >> $GITHUB_OUTPUT + echo "current_id: $current_meta_ver" - - name: Clone Clash Meta Repository - uses: actions/checkout@v4 - with: - repository: MetaCubeX/mihomo - ref: Alpha + current_smart_ver=$(sed -n '2p' ./dev/core_version 2>/dev/null || echo "null") + echo "current_smart_id=$current_smart_ver" >> $GITHUB_OUTPUT + echo "current_smart_id: $current_smart_ver" - name: Get Upstream Version id: upstream_id run: | + # MetaCubeX/mihomo + git clone --depth=1 --branch=Alpha https://github.com/MetaCubeX/mihomo.git metacubex_mihomo + cd metacubex_mihomo echo "upstream_id=alpha-g$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT echo "upstream_id: alpha-g$(git rev-parse --short HEAD)" + cd .. + # vernesong/mihomo + git clone --depth=1 --branch=Alpha https://github.com/vernesong/mihomo.git vernesong_mihomo + cd vernesong_mihomo + echo "upstream_smart_id=alpha-smart-g$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + echo "upstream_smart_id: alpha-smart-g$(git rev-parse --short HEAD)" - Compile: + Compile_Meta_Core: runs-on: ubuntu-latest needs: Get-Commit-id if: ${{ needs.Get-Commit-id.outputs.current_id != needs.Get-Commit-id.outputs.upstream_id }} + strategy: + matrix: + arch: [normal, loongarch_abi1, loongarch_abi2] steps: + - name: Checkout OpenClash Repository + uses: actions/checkout@v4 + with: + ref: core + - name: Apt Update env: DEBIAN_FRONTEND: noninteractive @@ -57,105 +74,373 @@ jobs: - name: Setup UPX run: | - cd .. wget https://github.com/upx/upx/releases/download/v3.95/upx-3.95-amd64_linux.tar.xz tar xf upx-3.95-amd64_linux.tar.xz - echo "upx=../upx-3.95-amd64_linux/upx" >> $GITHUB_ENV + echo "upx=${{ github.workspace }}/upx-3.95-amd64_linux/upx" >> $GITHUB_ENV - - name: Clone OpenClash Repository - uses: actions/checkout@v4 - with: - ref: core - - - name: Copy Makefile + - name: Prepare Makefiles and Temp Dirs for Meta run: | - cd .. - mkdir tmp - mkdir tmp/bin - cp ./OpenClash/.github/makefile/meta ./tmp/Makefile + mkdir -p ${{ github.workspace }}/build_temp/meta_makefiles/normal + cp ${{ github.workspace }}/.github/makefile/meta ${{ github.workspace }}/build_temp/meta_makefiles/normal/Makefile - - name: Copy loongarch abi1 Makefile - run: | - cd .. - mkdir -p tmp/loong64_abi1/bin - cp ./OpenClash/.github/makefile/meta_loongarch_abi1 ./tmp/loong64_abi1/Makefile + mkdir -p ${{ github.workspace }}/build_temp/meta_makefiles/loong64_abi1 + cp ${{ github.workspace }}/.github/makefile/meta_loongarch_abi1 ${{ github.workspace }}/build_temp/meta_makefiles/loong64_abi1/Makefile + + mkdir -p ${{ github.workspace }}/build_temp/meta_makefiles/loong64_abi2 + cp ${{ github.workspace }}/.github/makefile/meta_loongarch_abi2 ${{ github.workspace }}/build_temp/meta_makefiles/loong64_abi2/Makefile + + mkdir -p ${{ github.workspace }}/build_temp/meta_output/${{ matrix.arch }}/bin - - name: Copy loongarch abi2 Makefile - run: | - cd .. - mkdir -p tmp/loong64_abi2/bin - cp ./OpenClash/.github/makefile/meta_loongarch_abi2 ./tmp/loong64_abi2/Makefile - - name: Setup Go uses: actions/setup-go@v5 with: go-version: "1.24" check-latest: true + + - name: Define Go Archive Directory + id: go_paths + run: | + echo "archive_dir=${{ runner.temp }}/go-archives" >> $GITHUB_OUTPUT + mkdir -p ${{ runner.temp }}/go-archives - - name: Clone Clash Meta Repository + - name: Cache Go loongarch abi1 tarball + id: cache_go_abi1 + uses: actions/cache@v4 + with: + path: ${{ steps.go_paths.outputs.archive_dir }}/go1.22.4.linux-amd64-abi1.tar.gz + key: go-loongarch-abi1-1.22.4-${{ matrix.arch }} + restore-keys: | + go-loongarch-abi1-1.22.4- + + - name: Cache Go loongarch abi2 tarball + id: cache_go_abi2 + uses: actions/cache@v4 + with: + path: ${{ steps.go_paths.outputs.archive_dir }}/go1.22.4.linux-amd64-abi2.tar.gz + key: go-loongarch-abi2-1.22.4-${{ matrix.arch }} + restore-keys: | + go-loongarch-abi2-1.22.4- + + - name: Clone MetaCubeX/mihomo source uses: actions/checkout@v4 with: repository: MetaCubeX/mihomo ref: Alpha - - - name: Compile Meta Clash + path: ./metacubex_src + + - name: Compile Meta Core for ${{ matrix.arch }} run: | - cp ../tmp/Makefile ./Makefile + set -e + cd ./metacubex_src + GO_ARCHIVE_DIR="${{ steps.go_paths.outputs.archive_dir }}" + + case "${{ matrix.arch }}" in + normal) + echo "Using default Go and Makefile" + cp ../build_temp/meta_makefiles/normal/Makefile ./Makefile + ;; + loongarch_abi1) + echo "Setup Go for loongarch abi1" + GO_TAR_FILE="go1.22.4.linux-amd64-abi1.tar.gz" + if [[ "${{ steps.cache_go_abi1.outputs.cache-hit }}" != 'true' ]]; then + echo "Cache not found for $GO_TAR_FILE, downloading..." + wget -q "https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/$GO_TAR_FILE" -O "$GO_ARCHIVE_DIR/$GO_TAR_FILE" + else + echo "Restored $GO_TAR_FILE from cache." + fi + sudo rm -rf /usr/local/go || true + sudo tar zxf "$GO_ARCHIVE_DIR/$GO_TAR_FILE" -C /usr/local + echo "/usr/local/go/bin" >> $GITHUB_PATH + cp ../build_temp/meta_makefiles/loong64_abi1/Makefile ./Makefile + ;; + loongarch_abi2) + echo "Setup Go for loongarch abi2" + GO_TAR_FILE="go1.22.4.linux-amd64-abi2.tar.gz" + if [[ "${{ steps.cache_go_abi2.outputs.cache-hit }}" != 'true' ]]; then + echo "Cache not found for $GO_TAR_FILE, downloading..." + wget -q "https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/$GO_TAR_FILE" -O "$GO_ARCHIVE_DIR/$GO_TAR_FILE" + else + echo "Restored $GO_TAR_FILE from cache." + fi + sudo rm -rf /usr/local/go || true + sudo tar zxf "$GO_ARCHIVE_DIR/$GO_TAR_FILE" -C /usr/local + echo "/usr/local/go/bin" >> $GITHUB_PATH + cp ../build_temp/meta_makefiles/loong64_abi2/Makefile ./Makefile + ;; + esac + go version make releases - - - name: Copy Clash Bin - run: | - cp -rf "./bin/." "../tmp/bin/" + cp -rf ./bin/. ../build_temp/meta_output/${{ matrix.arch }}/bin/ rm -rf ./bin/* - - name: Setup loongarch abi1 Go - run: | - wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/go1.22.4.linux-amd64-abi1.tar.gz - sudo tar zxf go1.22.4.linux-amd64-abi1.tar.gz -C /usr/local - echo "/usr/local/go/bin" >> $GITHUB_PATH + - name: Upload Meta Core Artifact + uses: actions/upload-artifact@v4 + with: + name: meta-core-${{ matrix.arch }} + path: build_temp/meta_output/${{ matrix.arch }}/bin - - name: Compile Meta loongarch abi1 Clash - run: | - cp ../tmp/loong64_abi1/Makefile ./Makefile - make releases - - - name: Copy loongarch abi1 Clash Bin - run: | - cp -rf "./bin/." "../tmp/loong64_abi1/bin/" - rm -rf ./bin/* - - - name: Setup loongarch abi2 Go - run: | - wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/go1.22.4.linux-amd64-abi2.tar.gz - sudo tar zxf go1.22.4.linux-amd64-abi2.tar.gz -C /usr/local - - - name: Compile Meta loongarch abi2 Clash - run: | - cp ../tmp/loong64_abi2/Makefile ./Makefile - make releases - - - name: Copy loongarch abi2 Clash Bin - run: | - cp -rf "./bin/." "../tmp/loong64_abi2/bin/" - - - name: Clone OpenClash Repository + Compile_Smart_Core: + runs-on: ubuntu-latest + needs: Get-Commit-id + if: ${{ needs.Get-Commit-id.outputs.current_smart_id != needs.Get-Commit-id.outputs.upstream_smart_id }} + strategy: + matrix: + arch: [normal, loongarch_abi1, loongarch_abi2] + steps: + - name: Checkout OpenClash Repository uses: actions/checkout@v4 with: ref: core - - name: Change Version + - name: Apt Update + env: + DEBIAN_FRONTEND: noninteractive run: | - sed -i '3d' ./dev/core_version - sed -i "2a ${{ needs.Get-Commit-id.outputs.upstream_id }}" ./dev/core_version + sudo apt-get update + sudo apt-get -y install wget git tar + + - name: Setup UPX + run: | + wget https://github.com/upx/upx/releases/download/v3.95/upx-3.95-amd64_linux.tar.xz + tar xf upx-3.95-amd64_linux.tar.xz + echo "upx=${{ github.workspace }}/upx-3.95-amd64_linux/upx" >> $GITHUB_ENV + + - name: Prepare Makefiles and Temp Dirs for Smart + run: | + mkdir -p ${{ github.workspace }}/build_temp/smart_makefiles/normal + cp ${{ github.workspace }}/.github/makefile/meta ${{ github.workspace }}/build_temp/smart_makefiles/normal/Makefile + sed -i 's/VERSION=alpha-g/VERSION=alpha-smart-g/' ${{ github.workspace }}/build_temp/smart_makefiles/normal/Makefile + + mkdir -p ${{ github.workspace }}/build_temp/smart_makefiles/loong64_abi1 + cp ${{ github.workspace }}/.github/makefile/meta_loongarch_abi1 ${{ github.workspace }}/build_temp/smart_makefiles/loong64_abi1/Makefile + sed -i 's/VERSION=alpha-g/VERSION=alpha-smart-g/' ${{ github.workspace }}/build_temp/smart_makefiles/loong64_abi1/Makefile + + mkdir -p ${{ github.workspace }}/build_temp/smart_makefiles/loong64_abi2 + cp ${{ github.workspace }}/.github/makefile/meta_loongarch_abi2 ${{ github.workspace }}/build_temp/smart_makefiles/loong64_abi2/Makefile + sed -i 's/VERSION=alpha-g/VERSION=alpha-smart-g/' ${{ github.workspace }}/build_temp/smart_makefiles/loong64_abi2/Makefile + + mkdir -p ${{ github.workspace }}/build_temp/smart_output/${{ matrix.arch }}/bin + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: "1.24" + check-latest: true + + - name: Define Go Archive Directory + id: go_paths + run: | + echo "archive_dir=${{ runner.temp }}/go-archives" >> $GITHUB_OUTPUT + mkdir -p ${{ runner.temp }}/go-archives + + - name: Cache Go loongarch abi1 tarball + id: cache_go_abi1 + uses: actions/cache@v4 + with: + path: ${{ steps.go_paths.outputs.archive_dir }}/go1.22.4.linux-amd64-abi1.tar.gz + key: go-loongarch-abi1-1.22.4-${{ matrix.arch }} + restore-keys: | + go-loongarch-abi1-1.22.4- + + - name: Cache Go loongarch abi2 tarball + id: cache_go_abi2 + uses: actions/cache@v4 + with: + path: ${{ steps.go_paths.outputs.archive_dir }}/go1.22.4.linux-amd64-abi2.tar.gz + key: go-loongarch-abi2-1.22.4-${{ matrix.arch }} + restore-keys: | + go-loongarch-abi2-1.22.4- + + - name: Clone vernesong/mihomo source + uses: actions/checkout@v4 + with: + repository: vernesong/mihomo + ref: Alpha + path: ./vernesong_src + + - name: Compile Smart Core for ${{ matrix.arch }} + run: | + set -e + cd ./vernesong_src + GO_ARCHIVE_DIR="${{ steps.go_paths.outputs.archive_dir }}" + + case "${{ matrix.arch }}" in + normal) + echo "Using default Go and Makefile" + cp ../build_temp/smart_makefiles/normal/Makefile ./Makefile + ;; + loongarch_abi1) + echo "Setup Go for loongarch abi1" + GO_TAR_FILE="go1.22.4.linux-amd64-abi1.tar.gz" + if [ ! -f "$GO_ARCHIVE_DIR/$GO_TAR_FILE" ]; then + echo "CRITICAL: $GO_TAR_FILE not found in $GO_ARCHIVE_DIR. Attempting fallback download." + wget -q "https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/$GO_TAR_FILE" -O "$GO_ARCHIVE_DIR/$GO_TAR_FILE" + if [ ! -f "$GO_ARCHIVE_DIR/$GO_TAR_FILE" ]; then + echo "ERROR: Fallback download for $GO_TAR_FILE failed. Exiting." + exit 1 + fi + fi + sudo rm -rf /usr/local/go || true + sudo tar zxf "$GO_ARCHIVE_DIR/$GO_TAR_FILE" -C /usr/local + echo "/usr/local/go/bin" >> $GITHUB_PATH + cp ../build_temp/smart_makefiles/loong64_abi1/Makefile ./Makefile + ;; + loongarch_abi2) + echo "Setup Go for loongarch abi2" + GO_TAR_FILE="go1.22.4.linux-amd64-abi2.tar.gz" + if [ ! -f "$GO_ARCHIVE_DIR/$GO_TAR_FILE" ]; then + echo "CRITICAL: $GO_TAR_FILE not found in $GO_ARCHIVE_DIR. Attempting fallback download." + wget -q "https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/$GO_TAR_FILE" -O "$GO_ARCHIVE_DIR/$GO_TAR_FILE" + if [ ! -f "$GO_ARCHIVE_DIR/$GO_TAR_FILE" ]; then + echo "ERROR: Fallback download for $GO_TAR_FILE failed. Exiting." + exit 1 + fi + fi + sudo rm -rf /usr/local/go || true + sudo tar zxf "$GO_ARCHIVE_DIR/$GO_TAR_FILE" -C /usr/local + echo "/usr/local/go/bin" >> $GITHUB_PATH + cp ../build_temp/smart_makefiles/loong64_abi2/Makefile ./Makefile + ;; + esac + go version + make releases + cp -rf ./bin/. ../build_temp/smart_output/${{ matrix.arch }}/bin/ + rm -rf ./bin/* + + - name: Upload Smart Core Artifact + uses: actions/upload-artifact@v4 + with: + name: smart-core-${{ matrix.arch }} + path: build_temp/smart_output/${{ matrix.arch }}/bin + + Publish: + runs-on: ubuntu-latest + needs: [Get-Commit-id, Compile_Meta_Core, Compile_Smart_Core] + if: always() && (needs.Get-Commit-id.outputs.current_id != needs.Get-Commit-id.outputs.upstream_id || needs.Get-Commit-id.outputs.current_smart_id != needs.Get-Commit-id.outputs.upstream_smart_id) + steps: + - name: Checkout OpenClash Repository + uses: actions/checkout@v4 + with: + ref: core + + - name: Download All Artifacts + uses: actions/download-artifact@v4 + with: + path: ./downloaded-artifacts + + - name: Organize Artifacts, Update Version, and Prepare Commit Data + id: organize_commit_data + run: | + commit_description="" + changes_made_to_dev_meta=false + changes_made_to_dev_smart=false + core_version_updated=false + + mkdir -p ./dev/meta + mkdir -p ./dev/smart + + if [ "${{ needs.Get-Commit-id.outputs.current_id }}" != "${{ needs.Get-Commit-id.outputs.upstream_id }}" ]; then + echo "Organizing MetaCubeX compiled files..." + if [ "${{ needs.Compile_Meta_Core.result }}" == "success" ] || [ "${{ needs.Compile_Meta_Core.result }}" == "skipped" ]; then + rm -rf ./dev/meta/* + for arch_type in normal loongarch_abi1 loongarch_abi2; do + if [ -d ./downloaded-artifacts/meta-core-$arch_type ] && [ -n "$(ls -A ./downloaded-artifacts/meta-core-$arch_type)" ]; then + echo "Copying meta-core-$arch_type files..." + cp -rf ./downloaded-artifacts/meta-core-$arch_type/. ./dev/meta/ + changes_made_to_dev_meta=true + fi + done + if [ "$changes_made_to_dev_meta" = true ]; then + git add ./dev/meta + commit_description="Meta to ${{ needs.Get-Commit-id.outputs.upstream_id }}" + fi + else + echo "Compile_Meta_Core job failed, skipping..." + fi + fi + + if [ "${{ needs.Get-Commit-id.outputs.current_smart_id }}" != "${{ needs.Get-Commit-id.outputs.upstream_smart_id }}" ]; then + echo "Organizing vernesong compiled files..." + if [ "${{ needs.Compile_Smart_Core.result }}" == "success" ] || [ "${{ needs.Compile_Smart_Core.result }}" == "skipped" ]; then + rm -rf ./dev/smart/* + for arch_type in normal loongarch_abi1 loongarch_abi2; do + if [ -d ./downloaded-artifacts/smart-core-$arch_type ] && [ -n "$(ls -A ./downloaded-artifacts/smart-core-$arch_type)" ]; then + echo "Copying smart-core-$arch_type files..." + cp -rf ./downloaded-artifacts/smart-core-$arch_type/. ./dev/smart/ + changes_made_to_dev_smart=true + fi + done + if [ "$changes_made_to_dev_smart" = true ]; then + git add ./dev/smart + if [ -n "$commit_description" ]; then + commit_description="$commit_description, " + fi + commit_description="${commit_description}Smart to ${{ needs.Get-Commit-id.outputs.upstream_smart_id }}" + fi + else + echo "Compile_Smart_Core job failed, skipping..." + fi + fi + + final_meta_id="${{ needs.Get-Commit-id.outputs.current_id }}" + if [ "${{ needs.Get-Commit-id.outputs.current_id }}" != "${{ needs.Get-Commit-id.outputs.upstream_id }}" ] && [ "$changes_made_to_dev_meta" = true ]; then + final_meta_id="${{ needs.Get-Commit-id.outputs.upstream_id }}" + fi + + final_smart_id="${{ needs.Get-Commit-id.outputs.current_smart_id }}" + if [ "${{ needs.Get-Commit-id.outputs.current_smart_id }}" != "${{ needs.Get-Commit-id.outputs.upstream_smart_id }}" ] && [ "$changes_made_to_dev_smart" = true ]; then + final_smart_id="${{ needs.Get-Commit-id.outputs.upstream_smart_id }}" + fi + + echo "Updating ./dev/core_version with:" + echo "Meta: $final_meta_id" + echo "Smart: $final_smart_id" + + current_core_version_content=$(cat ./dev/core_version 2>/dev/null || printf "null\nnull") + new_core_version_content=$(printf "%s\n%s" "$final_meta_id" "$final_smart_id") + + if [ "$current_core_version_content" != "$new_core_version_content" ]; then + echo "$final_meta_id" > ./dev/core_version + echo "$final_smart_id" >> ./dev/core_version + git add ./dev/core_version + core_version_updated=true + echo "./dev/core_version updated." + else + echo "./dev/core_version is already up to date." + fi + echo "Content of ./dev/core_version after potential update:" + cat ./dev/core_version + + overall_changes_exist=false + if [ "$changes_made_to_dev_meta" = true ] || [ "$changes_made_to_dev_smart" = true ] || [ "$core_version_updated" = true ]; then + overall_changes_exist=true + fi + + echo "commit_description_output=$commit_description" >> $GITHUB_OUTPUT + echo "overall_changes_exist_output=$overall_changes_exist" >> $GITHUB_OUTPUT - name: Commit and push + env: + COMMIT_DESCRIPTION: ${{ steps.organize_commit_data.outputs.commit_description_output }} + OVERALL_CHANGES_EXIST: ${{ steps.organize_commit_data.outputs.overall_changes_exist_output }} run: | - rm -rf ./dev/meta/* - cp -rf "../tmp/bin/." "./dev/meta/" - cp -rf "../tmp/loong64_abi1/bin/." "./dev/meta/" - cp -rf "../tmp/loong64_abi2/bin/." "./dev/meta/" git config user.name 'github-actions[bot]' git config user.email 'github-actions[bot]@users.noreply.github.com' - git add . - git commit -m "Auto update Meta core: ${{ needs.Get-Commit-id.outputs.upstream_id }}" - git push + + echo "Commit description from output: $COMMIT_DESCRIPTION" + echo "Overall changes exist from output: $OVERALL_CHANGES_EXIST" + + if ! git diff --staged --quiet || [ "$OVERALL_CHANGES_EXIST" = "true" ]; then + final_commit_message="Auto update" + if [ -n "$COMMIT_DESCRIPTION" ]; then + final_commit_message="$final_commit_message: $COMMIT_DESCRIPTION" + elif [ "$OVERALL_CHANGES_EXIST" = "true" ]; then + final_commit_message="$final_commit_message: Update core versions" + fi + + echo "Committing with message: $final_commit_message" + git commit -m "$final_commit_message" + git push + else + echo "No changes to commit." + fi \ No newline at end of file diff --git a/openclash/.github/workflows/master_release_sync.yml b/openclash/.github/workflows/master_release_sync.yml index 1d4f7dc1d6..887732b819 100644 --- a/openclash/.github/workflows/master_release_sync.yml +++ b/openclash/.github/workflows/master_release_sync.yml @@ -24,9 +24,10 @@ jobs: - name: Sync dev core to master run: | if [ -n "$(diff -r ./master/ ./dev/)" ]; then - rm -rf ./master/premium/* - rm -rf ./master/dev/* + rm -rf ./master/premium + rm -rf ./master/dev rm -rf ./master/meta/* + rm -rf ./master/smart/* rm -rf ./master/core_version cp -rf "./dev/." "./master/" git config user.name 'github-actions[bot]' diff --git a/openclash/luci-app-openclash/luasrc/controller/openclash.lua b/openclash/luci-app-openclash/luasrc/controller/openclash.lua index 37450df085..b434157a68 100644 --- a/openclash/luci-app-openclash/luasrc/controller/openclash.lua +++ b/openclash/luci-app-openclash/luasrc/controller/openclash.lua @@ -245,9 +245,14 @@ end local function corelv() local status = process_status("/usr/share/openclash/clash_version.sh") local core_meta_lv = "" + local core_smart_enable = uci:get("openclash", "config", "smart_enable") or "0" if not status then if fs.access("/tmp/clash_last_version") then - core_meta_lv = luci.sys.exec("sed -n 3p /tmp/clash_last_version 2>/dev/null |tr -d '\n'") + if core_smart_enable == "1" then + core_meta_lv = luci.sys.exec("sed -n 2p /tmp/clash_last_version 2>/dev/null |tr -d '\n'") + else + core_meta_lv = luci.sys.exec("sed -n 1p /tmp/clash_last_version 2>/dev/null |tr -d '\n'") + end else action_get_last_version() core_meta_lv = "loading..." @@ -307,6 +312,10 @@ local function release_branch() return uci:get("openclash", "config", "release_branch") end +local function smart_enable() + return uci:get("openclash", "config", "smart_enable") +end + local function save_corever_branch() if luci.http.formvalue("core_ver") then uci:set("openclash", "config", "core_version", luci.http.formvalue("core_ver")) @@ -314,6 +323,9 @@ local function save_corever_branch() if luci.http.formvalue("release_branch") then uci:set("openclash", "config", "release_branch", luci.http.formvalue("release_branch")) end + if luci.http.formvalue("smart_enable") then + uci:set("openclash", "config", "smart_enable", luci.http.formvalue("smart_enable")) + end uci:commit("openclash") return "success" end @@ -1027,12 +1039,9 @@ function action_dler_login() end function action_one_key_update_check() - luci.sys.call("rm -rf /tmp/*_last_version 2>/dev/null") luci.http.prepare_content("application/json") luci.http.write_json({ - corever = corever(), - corelv = corelv(), - oplv = oplv(); + corever = corever(); }) end @@ -1163,7 +1172,8 @@ function action_update_info() luci.http.prepare_content("application/json") luci.http.write_json({ corever = corever(), - release_branch = release_branch(); + release_branch = release_branch(), + smart_enable = smart_enable(); }) end diff --git a/openclash/luci-app-openclash/luasrc/view/openclash/select_git_cdn.htm b/openclash/luci-app-openclash/luasrc/view/openclash/select_git_cdn.htm index f7b00691cc..45795d8a7e 100644 --- a/openclash/luci-app-openclash/luasrc/view/openclash/select_git_cdn.htm +++ b/openclash/luci-app-openclash/luasrc/view/openclash/select_git_cdn.htm @@ -66,8 +66,8 @@