diff --git a/.github/update.log b/.github/update.log index 4bfa50e916..a7d73dc550 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1020,3 +1020,4 @@ Update On Sun Jun 1 20:35:02 CEST 2025 Update On Mon Jun 2 20:41:58 CEST 2025 Update On Tue Jun 3 20:38:26 CEST 2025 Update On Wed Jun 4 20:38:34 CEST 2025 +Update On Fri Jun 6 20:37:19 CEST 2025 diff --git a/clash-meta/common/atomic/value.go b/clash-meta/common/atomic/value.go index 82d400766b..0de9fade37 100644 --- a/clash-meta/common/atomic/value.go +++ b/clash-meta/common/atomic/value.go @@ -27,11 +27,16 @@ type tValue[T any] struct { } func (t *TypedValue[T]) Load() T { + value, _ := t.LoadOk() + return value +} + +func (t *TypedValue[T]) LoadOk() (_ T, ok bool) { value := t.value.Load() if value == nil { - return DefaultValue[T]() + return DefaultValue[T](), false } - return value.(tValue[T]).value + return value.(tValue[T]).value, true } func (t *TypedValue[T]) Store(value T) { @@ -47,7 +52,11 @@ func (t *TypedValue[T]) Swap(new T) T { } func (t *TypedValue[T]) CompareAndSwap(old, new T) bool { - return t.value.CompareAndSwap(tValue[T]{old}, tValue[T]{new}) + return t.value.CompareAndSwap(tValue[T]{old}, tValue[T]{new}) || + // In the edge-case where [atomic.Value.Store] is uninitialized + // and trying to compare with the zero value of T, + // then compare-and-swap with the nil any value. + (any(old) == any(DefaultValue[T]()) && t.value.CompareAndSwap(any(nil), tValue[T]{new})) } func (t *TypedValue[T]) MarshalJSON() ([]byte, error) { diff --git a/clash-meta/common/atomic/value_test.go b/clash-meta/common/atomic/value_test.go new file mode 100644 index 0000000000..881b3e8d8e --- /dev/null +++ b/clash-meta/common/atomic/value_test.go @@ -0,0 +1,77 @@ +package atomic + +import ( + "io" + "os" + "testing" +) + +func TestTypedValue(t *testing.T) { + { + // Always wrapping should not allocate for simple values + // because tValue[T] has the same memory layout as T. + var v TypedValue[bool] + bools := []bool{true, false} + if n := int(testing.AllocsPerRun(1000, func() { + for _, b := range bools { + v.Store(b) + } + })); n != 0 { + t.Errorf("AllocsPerRun = %d, want 0", n) + } + } + + { + var v TypedValue[int] + got, gotOk := v.LoadOk() + if got != 0 || gotOk { + t.Fatalf("LoadOk = (%v, %v), want (0, false)", got, gotOk) + } + v.Store(1) + got, gotOk = v.LoadOk() + if got != 1 || !gotOk { + t.Fatalf("LoadOk = (%v, %v), want (1, true)", got, gotOk) + } + } + + { + var v TypedValue[error] + got, gotOk := v.LoadOk() + if got != nil || gotOk { + t.Fatalf("LoadOk = (%v, %v), want (nil, false)", got, gotOk) + } + v.Store(io.EOF) + got, gotOk = v.LoadOk() + if got != io.EOF || !gotOk { + t.Fatalf("LoadOk = (%v, %v), want (EOF, true)", got, gotOk) + } + err := &os.PathError{} + v.Store(err) + got, gotOk = v.LoadOk() + if got != err || !gotOk { + t.Fatalf("LoadOk = (%v, %v), want (%v, true)", got, gotOk, err) + } + v.Store(nil) + got, gotOk = v.LoadOk() + if got != nil || !gotOk { + t.Fatalf("LoadOk = (%v, %v), want (nil, true)", got, gotOk) + } + } + + { + c1, c2, c3 := make(chan struct{}), make(chan struct{}), make(chan struct{}) + var v TypedValue[chan struct{}] + if v.CompareAndSwap(c1, c2) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if v.CompareAndSwap(nil, c1) != true { + t.Fatalf("CompareAndSwap = false, want true") + } + if v.CompareAndSwap(c2, c3) != false { + t.Fatalf("CompareAndSwap = true, want false") + } + if v.CompareAndSwap(c1, c2) != true { + t.Fatalf("CompareAndSwap = false, want true") + } + } +} diff --git a/clash-meta/component/resolver/relay.go b/clash-meta/component/resolver/relay.go index 818b4152a3..ca7b32b988 100644 --- a/clash-meta/component/resolver/relay.go +++ b/clash-meta/component/resolver/relay.go @@ -46,17 +46,24 @@ func RelayDnsConn(ctx context.Context, conn net.Conn, readTimeout time.Duration) ctx, cancel := context.WithTimeout(ctx, DefaultDnsRelayTimeout) defer cancel() inData := buff[:n] - msg, err := relayDnsPacket(ctx, inData, buff, 0) + outBuff := buff[2:] + msg, err := relayDnsPacket(ctx, inData, outBuff, 0) if err != nil { return err } - err = binary.Write(conn, binary.BigEndian, uint16(len(msg))) - if err != nil { - return err + if &msg[0] == &outBuff[0] { // msg is still in the buff + binary.BigEndian.PutUint16(buff[:2], uint16(len(msg))) + outBuff = buff[:2+len(msg)] + } else { // buff not big enough (WTF???) + newBuff := pool.Get(len(msg) + 2) + defer pool.Put(newBuff) + binary.BigEndian.PutUint16(newBuff[:2], uint16(len(msg))) + copy(newBuff[2:], msg) + outBuff = newBuff } - _, err = conn.Write(msg) + _, err = conn.Write(outBuff) if err != nil { return err } diff --git a/clash-meta/config/config.go b/clash-meta/config/config.go index d79ab65c5b..498c7c20f1 100644 --- a/clash-meta/config/config.go +++ b/clash-meta/config/config.go @@ -1168,10 +1168,21 @@ func parseNameServer(servers []string, respectRules bool, preferH3 bool) ([]dns. return nil, fmt.Errorf("DNS NameServer[%d] format error: %s", idx, err.Error()) } - proxyName := u.Fragment + var proxyName string + params := map[string]string{} + for _, s := range strings.Split(u.Fragment, "&") { + arr := strings.SplitN(s, "=", 2) + switch len(arr) { + case 0: + continue + case 1: + proxyName = arr[0] + case 2: + params[arr[0]] = arr[1] + } + } var addr, dnsNetType string - params := map[string]string{} switch u.Scheme { case "udp": addr, err = hostWithDefaultPort(u.Host, "53") @@ -1189,23 +1200,8 @@ func parseNameServer(servers []string, respectRules bool, preferH3 bool) ([]dns. addr, err = hostWithDefaultPort(u.Host, "80") } if err == nil { - proxyName = "" clearURL := url.URL{Scheme: u.Scheme, Host: addr, Path: u.Path, User: u.User} addr = clearURL.String() - if len(u.Fragment) != 0 { - for _, s := range strings.Split(u.Fragment, "&") { - arr := strings.Split(s, "=") - if len(arr) == 0 { - continue - } else if len(arr) == 1 { - proxyName = arr[0] - } else if len(arr) == 2 { - params[arr[0]] = arr[1] - } else { - params[arr[0]] = strings.Join(arr[1:], "=") - } - } - } } case "quic": addr, err = hostWithDefaultPort(u.Host, "853") diff --git a/clash-meta/dns/client.go b/clash-meta/dns/client.go index abdad3a690..359cb443ae 100644 --- a/clash-meta/dns/client.go +++ b/clash-meta/dns/client.go @@ -6,8 +6,10 @@ import ( "fmt" "net" "strings" + "time" "github.com/metacubex/mihomo/component/ca" + C "github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/log" D "github.com/miekg/dns" @@ -105,3 +107,24 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) } func (c *client) ResetConnection() {} + +func newClient(addr string, resolver *Resolver, netType string, params map[string]string, proxyAdapter C.ProxyAdapter, proxyName string) *client { + host, port, _ := net.SplitHostPort(addr) + c := &client{ + Client: &D.Client{ + Net: netType, + TLSConfig: &tls.Config{ + ServerName: host, + }, + UDPSize: 4096, + Timeout: 5 * time.Second, + }, + port: port, + host: host, + dialer: newDNSDialer(resolver, proxyAdapter, proxyName), + } + if params["skip-cert-verify"] == "true" { + c.TLSConfig.InsecureSkipVerify = true + } + return c +} diff --git a/clash-meta/dns/doh.go b/clash-meta/dns/doh.go index c6f7c67b5d..7c804f268b 100644 --- a/clash-meta/dns/doh.go +++ b/clash-meta/dns/doh.go @@ -9,7 +9,6 @@ import ( "io" "net" "net/http" - "net/netip" "net/url" "runtime" "strconv" @@ -71,8 +70,6 @@ type dnsOverHTTPS struct { dialer *dnsDialer addr string skipCertVerify bool - ecsPrefix netip.Prefix - ecsOverride bool } // type check @@ -105,28 +102,6 @@ func newDoHClient(urlString string, r *Resolver, preferH3 bool, params map[strin doh.skipCertVerify = true } - if ecs := params["ecs"]; ecs != "" { - prefix, err := netip.ParsePrefix(ecs) - if err != nil { - addr, err := netip.ParseAddr(ecs) - if err != nil { - log.Warnln("DOH [%s] config with invalid ecs: %s", doh.addr, ecs) - } else { - doh.ecsPrefix = netip.PrefixFrom(addr, addr.BitLen()) - } - } else { - doh.ecsPrefix = prefix - } - } - - if doh.ecsPrefix.IsValid() { - log.Debugln("DOH [%s] config with ecs: %s", doh.addr, doh.ecsPrefix) - } - - if params["ecs-override"] == "true" { - doh.ecsOverride = true - } - runtime.SetFinalizer(doh, (*dnsOverHTTPS).Close) return doh @@ -154,10 +129,6 @@ func (doh *dnsOverHTTPS) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D. } }() - if doh.ecsPrefix.IsValid() { - setEdns0Subnet(m, doh.ecsPrefix, doh.ecsOverride) - } - // Check if there was already an active client before sending the request. // We'll only attempt to re-connect if there was one. client, isCached, err := doh.getClient(ctx) @@ -552,8 +523,8 @@ func (doh *dnsOverHTTPS) createTransportH3( Dial: func( ctx context.Context, - // Ignore the address and always connect to the one that we got - // from the bootstrapper. + // Ignore the address and always connect to the one that we got + // from the bootstrapper. _ string, tlsCfg *tlsC.Config, cfg *quic.Config, diff --git a/clash-meta/dns/doq.go b/clash-meta/dns/doq.go index af0a0d4601..f16300efbd 100644 --- a/clash-meta/dns/doq.go +++ b/clash-meta/dns/doq.go @@ -61,15 +61,16 @@ type dnsOverQUIC struct { bytesPool *sync.Pool bytesPoolGuard sync.Mutex - addr string - dialer *dnsDialer + addr string + dialer *dnsDialer + skipCertVerify bool } // type check var _ dnsClient = (*dnsOverQUIC)(nil) // newDoQ returns the DNS-over-QUIC Upstream. -func newDoQ(resolver *Resolver, addr string, proxyAdapter C.ProxyAdapter, proxyName string) (dnsClient, error) { +func newDoQ(addr string, resolver *Resolver, params map[string]string, proxyAdapter C.ProxyAdapter, proxyName string) *dnsOverQUIC { doq := &dnsOverQUIC{ addr: addr, dialer: newDNSDialer(resolver, proxyAdapter, proxyName), @@ -79,8 +80,12 @@ func newDoQ(resolver *Resolver, addr string, proxyAdapter C.ProxyAdapter, proxyN }, } + if params["skip-cert-verify"] == "true" { + doq.skipCertVerify = true + } + runtime.SetFinalizer(doq, (*dnsOverQUIC).Close) - return doq, nil + return doq } // Address implements the Upstream interface for *dnsOverQUIC. @@ -329,7 +334,7 @@ func (doq *dnsOverQUIC) openConnection(ctx context.Context) (conn quic.Connectio tlsConfig := ca.GetGlobalTLSConfig( &tls.Config{ ServerName: host, - InsecureSkipVerify: false, + InsecureSkipVerify: doq.skipCertVerify, NextProtos: []string{ NextProtoDQ, }, diff --git a/clash-meta/dns/util.go b/clash-meta/dns/util.go index a4ca98d4f1..c0fd0ea807 100644 --- a/clash-meta/dns/util.go +++ b/clash-meta/dns/util.go @@ -2,10 +2,8 @@ package dns import ( "context" - "crypto/tls" "errors" "fmt" - "net" "net/netip" "strings" "time" @@ -92,46 +90,95 @@ func isIPRequest(q D.Question) bool { func transform(servers []NameServer, resolver *Resolver) []dnsClient { ret := make([]dnsClient, 0, len(servers)) for _, s := range servers { + var c dnsClient switch s.Net { case "https": - ret = append(ret, newDoHClient(s.Addr, resolver, s.PreferH3, s.Params, s.ProxyAdapter, s.ProxyName)) - continue + c = newDoHClient(s.Addr, resolver, s.PreferH3, s.Params, s.ProxyAdapter, s.ProxyName) case "dhcp": - ret = append(ret, newDHCPClient(s.Addr)) - continue + c = newDHCPClient(s.Addr) case "system": - ret = append(ret, newSystemClient()) - continue + c = newSystemClient() case "rcode": - ret = append(ret, newRCodeClient(s.Addr)) - continue + c = newRCodeClient(s.Addr) case "quic": - if doq, err := newDoQ(resolver, s.Addr, s.ProxyAdapter, s.ProxyName); err == nil { - ret = append(ret, doq) - } else { - log.Fatalln("DoQ format error: %v", err) - } - continue + c = newDoQ(s.Addr, resolver, s.Params, s.ProxyAdapter, s.ProxyName) + default: + c = newClient(s.Addr, resolver, s.Net, s.Params, s.ProxyAdapter, s.ProxyName) } - host, port, _ := net.SplitHostPort(s.Addr) - ret = append(ret, &client{ - Client: &D.Client{ - Net: s.Net, - TLSConfig: &tls.Config{ - ServerName: host, - }, - UDPSize: 4096, - Timeout: 5 * time.Second, - }, - port: port, - host: host, - dialer: newDNSDialer(resolver, s.ProxyAdapter, s.ProxyName), - }) + c = warpClientWithEdns0Subnet(c, s.Params) + + if s.Params["disable-ipv4"] == "true" { + c = warpClientWithDisableType(c, D.TypeA) + } + + if s.Params["disable-ipv6"] == "true" { + c = warpClientWithDisableType(c, D.TypeAAAA) + } + + ret = append(ret, c) } return ret } +type clientWithDisableType struct { + dnsClient + qType uint16 +} + +func (c clientWithDisableType) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { + if len(m.Question) > 0 { + q := m.Question[0] + if q.Qtype == c.qType { + return handleMsgWithEmptyAnswer(m), nil + } + } + return c.dnsClient.ExchangeContext(ctx, m) +} + +func warpClientWithDisableType(c dnsClient, qType uint16) dnsClient { + return clientWithDisableType{c, qType} +} + +type clientWithEdns0Subnet struct { + dnsClient + ecsPrefix netip.Prefix + ecsOverride bool +} + +func (c clientWithEdns0Subnet) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) { + m = m.Copy() + setEdns0Subnet(m, c.ecsPrefix, c.ecsOverride) + return c.dnsClient.ExchangeContext(ctx, m) +} + +func warpClientWithEdns0Subnet(c dnsClient, params map[string]string) dnsClient { + var ecsPrefix netip.Prefix + var ecsOverride bool + if ecs := params["ecs"]; ecs != "" { + prefix, err := netip.ParsePrefix(ecs) + if err != nil { + addr, err := netip.ParseAddr(ecs) + if err != nil { + log.Warnln("DNS [%s] config with invalid ecs: %s", c.Address(), ecs) + } else { + ecsPrefix = netip.PrefixFrom(addr, addr.BitLen()) + } + } else { + ecsPrefix = prefix + } + } + + if ecsPrefix.IsValid() { + log.Debugln("DNS [%s] config with ecs: %s", c.Address(), ecsPrefix) + if params["ecs-override"] == "true" { + ecsOverride = true + } + return clientWithEdns0Subnet{c, ecsPrefix, ecsOverride} + } + return c +} + func handleMsgWithEmptyAnswer(r *D.Msg) *D.Msg { msg := &D.Msg{} msg.Answer = []D.RR{} diff --git a/clash-meta/go.mod b/clash-meta/go.mod index b808996efa..31b96a0896 100644 --- a/clash-meta/go.mod +++ b/clash-meta/go.mod @@ -25,11 +25,11 @@ require ( github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 github.com/metacubex/quic-go v0.52.1-0.20250522021943-aef454b9e639 github.com/metacubex/randv2 v0.2.0 - github.com/metacubex/sing v0.5.3 + github.com/metacubex/sing v0.5.4-0.20250605054047-54dc6097da29 github.com/metacubex/sing-mux v0.3.2 github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f - github.com/metacubex/sing-shadowsocks v0.2.10 - github.com/metacubex/sing-shadowsocks2 v0.2.4 + github.com/metacubex/sing-shadowsocks v0.2.11-0.20250531133822-e545de386d4c + github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250531133559-f4d53bd59335 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 github.com/metacubex/sing-tun v0.4.6-0.20250524142129-9d110c0af70c github.com/metacubex/sing-vmess v0.2.2 diff --git a/clash-meta/go.sum b/clash-meta/go.sum index 7f2c16fe7d..040073a982 100644 --- a/clash-meta/go.sum +++ b/clash-meta/go.sum @@ -116,16 +116,16 @@ github.com/metacubex/quic-go v0.52.1-0.20250522021943-aef454b9e639/go.mod h1:Kc6 github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing v0.5.3 h1:QWdN16WFKMk06x4nzkc8SvZ7y2x+TLQrpkPoHs+WSVM= -github.com/metacubex/sing v0.5.3/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= +github.com/metacubex/sing v0.5.4-0.20250605054047-54dc6097da29 h1:SD9q025FNTaepuFXFOKDhnGLVu6PQYChBvw2ZYPXeLo= +github.com/metacubex/sing v0.5.4-0.20250605054047-54dc6097da29/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing-mux v0.3.2 h1:nJv52pyRivHcaZJKk2JgxpaVvj1GAXG81scSa9N7ncw= github.com/metacubex/sing-mux v0.3.2/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f h1:mP3vIm+9hRFI0C0Vl3pE0NESF/L85FDbuB0tGgUii6I= github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f/go.mod h1:JPTpf7fpnojsSuwRJExhSZSy63pVbp3VM39+zj+sAJM= -github.com/metacubex/sing-shadowsocks v0.2.10 h1:Pr7LDbjMANIQHl07zWgl1vDuhpsfDQUpZ8cX6DPabfg= -github.com/metacubex/sing-shadowsocks v0.2.10/go.mod h1:MtRM0ZZjR0kaDOzy9zWSt6/4/UlrnsNBq+1FNAF4vBk= -github.com/metacubex/sing-shadowsocks2 v0.2.4 h1:Ec0x3hHR7xkld5Z09IGh16wtUUpBb2HgqZ9DExd8Q7s= -github.com/metacubex/sing-shadowsocks2 v0.2.4/go.mod h1:WP8+S0kqtnSbX1vlIpo5i8Irm/ijZITEPBcZ26B5unY= +github.com/metacubex/sing-shadowsocks v0.2.11-0.20250531133822-e545de386d4c h1:ZfgQx24XIN807046dp9CVBjAh0t9NJIzXG3X5jk+PEM= +github.com/metacubex/sing-shadowsocks v0.2.11-0.20250531133822-e545de386d4c/go.mod h1:MtRM0ZZjR0kaDOzy9zWSt6/4/UlrnsNBq+1FNAF4vBk= +github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250531133559-f4d53bd59335 h1:nSSdMV+I7Tjcb7s6FzNDMj7jH/ZdryY1DHPlgtFjW98= +github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250531133559-f4d53bd59335/go.mod h1:WP8+S0kqtnSbX1vlIpo5i8Irm/ijZITEPBcZ26B5unY= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= github.com/metacubex/sing-tun v0.4.6-0.20250524142129-9d110c0af70c h1:Y6jk7AH5BEg9Dsvczrf/KokYsvxeKSZZlCLHg+hC4ro= diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index c2543e4a49..35cd942c27 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -1688,7 +1688,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -4106,7 +4106,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.58.0", + "windows-core 0.61.2", ] [[package]] @@ -4986,7 +4986,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.53.0", ] [[package]] @@ -6501,9 +6501,9 @@ checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" [[package]] name = "oxc-miette" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8c278d00ecc50ee84aba4768a7ab74eb325dff4dca8c0581495b850d53480ba" +checksum = "98b2c44324a4372caf6e3128a22744263c973e809fc598db3749ef3ff5e9fed4" dependencies = [ "cfg-if", "owo-colors", @@ -6515,9 +6515,9 @@ dependencies = [ [[package]] name = "oxc-miette-derive" -version = "2.1.2" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c0c893f53900e3fe01eca3d6d3b54085573c3e48fe25af9d57dd94ef600dcd3" +checksum = "3bd3da01a295024fa79e3b4aba14b590d91256a274ff29cc5ee8f55183b2df24" dependencies = [ "proc-macro2", "quote", @@ -6526,23 +6526,22 @@ dependencies = [ [[package]] name = "oxc_allocator" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8248980c6d9db21f8ad42e0c85c172ef4dd20335522fc81e4ac72b6b70f806" +checksum = "94677be5d1874da150784b9d551bae0dfad7e5a6121a2c6acccda335c05504ea" dependencies = [ "allocator-api2", "bumpalo", "hashbrown 0.15.3", "oxc_data_structures", "rustc-hash 2.1.1", - "simdutf8", ] [[package]] name = "oxc_ast" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a05110cb2af185324857a9a5d1a1986196e2cf3c5127cd90a7694c6b326e97c9" +checksum = "26f7b73c9a8e265169d98cd2395cbab52fcb849d3297b1ec2511a1d908775c73" dependencies = [ "bitflags 2.9.1", "cow-utils", @@ -6557,9 +6556,9 @@ dependencies = [ [[package]] name = "oxc_ast_macros" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24598056bb57788599997bbdb6ebf21a24b3331805aa9190c5b1204c973e636e" +checksum = "3f411489fef9ace92fdea3105490f9aab07a78c9adff25b62345b1a1bd49ee0c" dependencies = [ "phf 0.11.3", "proc-macro2", @@ -6569,9 +6568,9 @@ dependencies = [ [[package]] name = "oxc_ast_visit" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a263a5d0fcb1fd60696b54cc5fd8fba020266522effdb48ae3c74744602e0116" +checksum = "cf97a9b275654d7fc921c0c472ceab1ae167b670c9a761e5c2aec66b9076157b" dependencies = [ "oxc_allocator", "oxc_ast", @@ -6581,18 +6580,18 @@ dependencies = [ [[package]] name = "oxc_data_structures" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112fcb78e9c0f3dda6beb1d93865f319d1c0165b0bf067fafda7f6529118328d" +checksum = "09ebee1a21c5d47b6e845357274904ec9568b001d3ff6ab04d4cc4754fd148c2" dependencies = [ "rustversion", ] [[package]] name = "oxc_diagnostics" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b801ff7bbda76e11e0d5a43c06a80b3c105219e564c05e0b2fdb56d87b832a" +checksum = "7fa03ff098ecf135235ed3c88e013a22e9b58caf1108d32eca5261daf2d88330" dependencies = [ "cow-utils", "oxc-miette", @@ -6600,9 +6599,9 @@ dependencies = [ [[package]] name = "oxc_ecmascript" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea29dc44ee5ed0b63adb6d377dd07bf5870b6ae76d986965a92af1fac101dfd4" +checksum = "e1b5dba7d2918b9a59f82ce974b85cc6de1e577d06f49d1e608505e9da6a0b02" dependencies = [ "cow-utils", "num-bigint", @@ -6614,9 +6613,9 @@ dependencies = [ [[package]] name = "oxc_estree" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ffa7908363d884399956c8971e924f1abba00ebe9995853bc70f536c0ccaaf" +checksum = "7a870fcc8a8a8eeb3471cb51df3628f04e9f53521608e735a34bd9b6f96ce78c" [[package]] name = "oxc_index" @@ -6626,9 +6625,9 @@ checksum = "2fa07b0cfa997730afed43705766ef27792873fdf5215b1391949fec678d2392" [[package]] name = "oxc_parser" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d4e22dc3630700e32320bbbc9f04396f109e8be2bb18791a00950485b049a5" +checksum = "ca8194f22ac433d9f2575f3f5a35fdc2ec403877a2c98b8bbb7047acc73e07e6" dependencies = [ "bitflags 2.9.1", "cow-utils", @@ -6649,9 +6648,9 @@ dependencies = [ [[package]] name = "oxc_regular_expression" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4691c62894d99f689da38419894e6e38c33862ac414206a65f0539d80c3ef252" +checksum = "bac34c62476a83f00f36fb08991730db51a722082125067f9562257fd97cbb88" dependencies = [ "bitflags 2.9.1", "oxc_allocator", @@ -6665,9 +6664,9 @@ dependencies = [ [[package]] name = "oxc_span" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d915cbabe501873b16236ae0e8ddfd5c001fd764b1dd073128858b5a0641a4" +checksum = "886510fc6db2c5a7a905feeb966e613527bdbe2e544057923957ba79e3e93142" dependencies = [ "compact_str", "oxc-miette", @@ -6678,9 +6677,9 @@ dependencies = [ [[package]] name = "oxc_syntax" -version = "0.71.0" +version = "0.72.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6318faa445653106b56da5497a080e4fcf9231d5121035639d8c003f992378" +checksum = "3dddefc02737686c68da8597a88ba5514e7134aba006c61f72fb1752451f95cc" dependencies = [ "bitflags 2.9.1", "cow-utils", @@ -8984,7 +8983,7 @@ dependencies = [ "ntapi", "objc2-core-foundation", "objc2-io-kit", - "windows 0.59.0", + "windows 0.61.1", ] [[package]] @@ -11223,7 +11222,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/clash-nyanpasu/backend/tauri/Cargo.toml b/clash-nyanpasu/backend/tauri/Cargo.toml index 850e373759..90aa354e95 100644 --- a/clash-nyanpasu/backend/tauri/Cargo.toml +++ b/clash-nyanpasu/backend/tauri/Cargo.toml @@ -172,12 +172,12 @@ display-info = "0.5.0" # should be removed after upgrading to tauri v2 # OXC (The Oxidation Compiler) # We use it to parse and transpile the old script profile to esm based script profile -oxc_parser = "0.71" -oxc_allocator = "0.71" -oxc_span = "0.71" -oxc_ast = "0.71" -oxc_syntax = "0.71" -oxc_ast_visit = "0.71" +oxc_parser = "0.72" +oxc_allocator = "0.72" +oxc_span = "0.72" +oxc_ast = "0.72" +oxc_syntax = "0.72" +oxc_ast_visit = "0.72" # Lua Integration mlua = { version = "0.10", features = [ diff --git a/clash-nyanpasu/frontend/interface/package.json b/clash-nyanpasu/frontend/interface/package.json index 1255dfb30c..e8d7742903 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.79.0", + "@tanstack/react-query": "5.80.5", "@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 a53d2ba10d..aad132802c 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -55,9 +55,9 @@ "@csstools/normalize.css": "12.1.1", "@emotion/babel-plugin": "11.13.5", "@emotion/react": "11.14.0", - "@iconify/json": "2.2.345", + "@iconify/json": "2.2.346", "@monaco-editor/react": "4.7.0", - "@tanstack/react-query": "5.79.0", + "@tanstack/react-query": "5.80.5", "@tanstack/react-router": "1.120.15", "@tanstack/react-router-devtools": "1.120.15", "@tanstack/router-plugin": "1.120.15", @@ -92,6 +92,6 @@ "vite-plugin-sass-dts": "1.3.31", "vite-plugin-svgr": "4.3.0", "vite-tsconfig-paths": "5.1.4", - "zod": "3.24.4" + "zod": "3.25.51" } } diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 5b4b8c4287..65e3b354f5 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.10", - "mihomo_alpha": "alpha-71a8705", + "mihomo_alpha": "alpha-40587b6", "clash_rs": "v0.7.8", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.7.8-alpha+sha.9e09f8c" @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-06-03T22:22:46.410Z" + "updated_at": "2025-06-05T22:21:11.895Z" } diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index d5d1a84c07..2805174531 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -84,7 +84,7 @@ "eslint-plugin-react-compiler": "19.1.0-rc.2", "eslint-plugin-react-hooks": "5.2.0", "globals": "16.2.0", - "knip": "5.59.1", + "knip": "5.60.0", "lint-staged": "16.1.0", "neostandard": "0.12.1", "npm-run-all2": "8.0.4", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index ced46f1763..fb14d9bd0f 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -101,8 +101,8 @@ importers: specifier: 16.2.0 version: 16.2.0 knip: - specifier: 5.59.1 - version: 5.59.1(@types/node@22.15.29)(typescript@5.8.3) + specifier: 5.60.0 + version: 5.60.0(@types/node@22.15.29)(typescript@5.8.3) lint-staged: specifier: 16.1.0 version: 16.1.0 @@ -173,8 +173,8 @@ importers: frontend/interface: dependencies: '@tanstack/react-query': - specifier: 5.79.0 - version: 5.79.0(react@19.1.0) + specifier: 5.80.5 + version: 5.80.5(react@19.1.0) '@tauri-apps/api': specifier: 2.5.0 version: 2.5.0 @@ -247,7 +247,7 @@ importers: version: 4.1.8 '@tanstack/router-zod-adapter': specifier: 1.81.5 - version: 1.81.5(@tanstack/react-router@1.120.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(zod@3.24.4) + version: 1.81.5(@tanstack/react-router@1.120.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(zod@3.25.51) '@tauri-apps/api': specifier: 2.5.0 version: 2.5.0 @@ -337,14 +337,14 @@ importers: specifier: 11.14.0 version: 11.14.0(@types/react@19.1.6)(react@19.1.0) '@iconify/json': - specifier: 2.2.345 - version: 2.2.345 + specifier: 2.2.346 + version: 2.2.346 '@monaco-editor/react': 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.79.0 - version: 5.79.0(react@19.1.0) + specifier: 5.80.5 + version: 5.80.5(react@19.1.0) '@tanstack/react-router': specifier: 1.120.15 version: 1.120.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -448,8 +448,8 @@ importers: specifier: 5.1.4 version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.29)(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)) zod: - specifier: 3.24.4 - version: 3.24.4 + specifier: 3.25.51 + version: 3.25.51 frontend/ui: dependencies: @@ -566,8 +566,8 @@ importers: specifier: 7.7.2 version: 7.7.2 zod: - specifier: 3.24.4 - version: 3.24.4 + specifier: 3.25.51 + version: 3.25.51 devDependencies: '@octokit/types': specifier: 14.1.0 @@ -1648,8 +1648,8 @@ packages: '@vue/compiler-sfc': optional: true - '@iconify/json@2.2.345': - resolution: {integrity: sha512-cWcTkpSw42OcltXXlLRMp4bnoFEMvEXEIZDPazqqpT7nr4dPN/ztEqOk6T3z0fXrN2E3OEgW0GnHlQqZz4qDgw==} + '@iconify/json@2.2.346': + resolution: {integrity: sha512-QcJNRnHf9UMuGdtbIISsGbUf/AArTpBr4ItaoBYryRjPiq7DHH7kcvbMdHpYcGvAMa6vidaL7g31iTLhOBgnyA==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -2066,68 +2066,68 @@ packages: resolution: {integrity: sha512-5Kva+/Gi7c+39d0/0MM/v/5RCZuwqm75fUD+t7Es3Iz/adui54GnjfNmJpkkPkXGC+5IWnEvgqwY6gstK/JlUQ==} engines: {node: '>= 18'} - '@oxc-resolver/binding-darwin-arm64@9.0.2': - resolution: {integrity: sha512-MVyRgP2gzJJtAowjG/cHN3VQXwNLWnY+FpOEsyvDepJki1SdAX/8XDijM1yN6ESD1kr9uhBKjGelC6h3qtT+rA==} + '@oxc-resolver/binding-darwin-arm64@11.1.0': + resolution: {integrity: sha512-n9y3Lb1+BwsOtm3BmXSUPu3iDtTq7Sf0gX4e+izFTfNrj+u6uTKqbmlq8ggV8CRdg1zGUaCvKNvg/9q3C/19gg==} cpu: [arm64] os: [darwin] - '@oxc-resolver/binding-darwin-x64@9.0.2': - resolution: {integrity: sha512-7kV0EOFEZ3sk5Hjy4+bfA6XOQpCwbDiDkkHN4BHHyrBHsXxUR05EcEJPPL1WjItefg+9+8hrBmoK0xRoDs41+A==} + '@oxc-resolver/binding-darwin-x64@11.1.0': + resolution: {integrity: sha512-2aJTPN9/lTmq0xw1YYsy5GDPkTyp92EoYRtw9nVgGErwMvA87duuLnIdoztYk66LGa3g5y4RgOaEapZbK7132A==} cpu: [x64] os: [darwin] - '@oxc-resolver/binding-freebsd-x64@9.0.2': - resolution: {integrity: sha512-6OvkEtRXrt8sJ4aVfxHRikjain9nV1clIsWtJ1J3J8NG1ZhjyJFgT00SCvqxbK+pzeWJq6XzHyTCN78ML+lY2w==} + '@oxc-resolver/binding-freebsd-x64@11.1.0': + resolution: {integrity: sha512-GoPEd9GvEyuS1YyqvAhAlccZeBEyHFkrHPEhS/+UTPcrzDzZ16ckJSmZtwOPhci5FWHK/th4L6NPiOnDLGFrqQ==} cpu: [x64] os: [freebsd] - '@oxc-resolver/binding-linux-arm-gnueabihf@9.0.2': - resolution: {integrity: sha512-aYpNL6o5IRAUIdoweW21TyLt54Hy/ZS9tvzNzF6ya1ckOQ8DLaGVPjGpmzxdNja9j/bbV6aIzBH7lNcBtiOTkQ==} + '@oxc-resolver/binding-linux-arm-gnueabihf@11.1.0': + resolution: {integrity: sha512-mQdQDTbw2/RcJKvMi8RAmDECuEC4waM5jeUBn8Cz1pLVddH8MfYJgKbZJUATBNNaHjw/u+Sq9Q1tcJbm8dhpYQ==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm64-gnu@9.0.2': - resolution: {integrity: sha512-RGFW4vCfKMFEIzb9VCY0oWyyY9tR1/o+wDdNePhiUXZU4SVniRPQaZ1SJ0sUFI1k25pXZmzQmIP6cBmazi/Dew==} + '@oxc-resolver/binding-linux-arm64-gnu@11.1.0': + resolution: {integrity: sha512-HDFQiPl7cX2DVXFlulWOinjqXa5Rj4ydFY9xJCwWAHGx2LmqwLDD8MI0UrHVUaHhLLWn54vjGtwsJK94dtkCwg==} cpu: [arm64] os: [linux] - '@oxc-resolver/binding-linux-arm64-musl@9.0.2': - resolution: {integrity: sha512-lxx/PibBfzqYvut2Y8N2D0Ritg9H8pKO+7NUSJb9YjR/bfk2KRmP8iaUz3zB0JhPtf/W3REs65oKpWxgflGToA==} + '@oxc-resolver/binding-linux-arm64-musl@11.1.0': + resolution: {integrity: sha512-0TFcZSVUQPV1r6sFUf7U2fz0mFCaqh5qMlb2zCioZj0C+xUJghC8bz88/qQUc5SA5K4gqg0WEOXzdqz/mXCLLA==} cpu: [arm64] os: [linux] - '@oxc-resolver/binding-linux-riscv64-gnu@9.0.2': - resolution: {integrity: sha512-yD28ptS/OuNhwkpXRPNf+/FvrO7lwURLsEbRVcL1kIE0GxNJNMtKgIE4xQvtKDzkhk6ZRpLho5VSrkkF+3ARTQ==} + '@oxc-resolver/binding-linux-riscv64-gnu@11.1.0': + resolution: {integrity: sha512-crG0iy5U9ac99Xkt9trWo5YvtCoSpPUrNZMeUVDkIy1qy1znfv66CveOgCm0G5TwooIIWLJrtFUqi0AkazS3fw==} cpu: [riscv64] os: [linux] - '@oxc-resolver/binding-linux-s390x-gnu@9.0.2': - resolution: {integrity: sha512-WBwEJdspoga2w+aly6JVZeHnxuPVuztw3fPfWrei2P6rNM5hcKxBGWKKT6zO1fPMCB4sdDkFohGKkMHVV1eryQ==} + '@oxc-resolver/binding-linux-s390x-gnu@11.1.0': + resolution: {integrity: sha512-aPemnsn/FXADFu7/VnSprO8uVb9UhNVdBdrIlAREh3s7LoW1QksKyP8/DlFe0o2E79MRQ3XF1ONOgW5zLcUmzA==} cpu: [s390x] os: [linux] - '@oxc-resolver/binding-linux-x64-gnu@9.0.2': - resolution: {integrity: sha512-a2z3/cbOOTUq0UTBG8f3EO/usFcdwwXnCejfXv42HmV/G8GjrT4fp5+5mVDoMByH3Ce3iVPxj1LmS6OvItKMYQ==} + '@oxc-resolver/binding-linux-x64-gnu@11.1.0': + resolution: {integrity: sha512-eMQ0Iue4Bs0jabCIHiEJbZMPoczdx1oBGOiNS/ykCE76Oos/Hb5uD1FB+Vw4agP2cAxzcp8zHO7MpEW450yswg==} cpu: [x64] os: [linux] - '@oxc-resolver/binding-linux-x64-musl@9.0.2': - resolution: {integrity: sha512-bHZF+WShYQWpuswB9fyxcgMIWVk4sZQT0wnwpnZgQuvGTZLkYJ1JTCXJMtaX5mIFHf69ngvawnwPIUA4Feil0g==} + '@oxc-resolver/binding-linux-x64-musl@11.1.0': + resolution: {integrity: sha512-5IjxRv0vWiGb102QmwF+ljutUWA1+BZbdW+58lFOVzVVo29L+m5PrEtijY5kK0FMTDvwb/xFXpGq3/vQx+bpSg==} cpu: [x64] os: [linux] - '@oxc-resolver/binding-wasm32-wasi@9.0.2': - resolution: {integrity: sha512-I5cSgCCh5nFozGSHz+PjIOfrqW99eUszlxKLgoNNzQ1xQ2ou9ZJGzcZ94BHsM9SpyYHLtgHljmOZxCT9bgxYNA==} + '@oxc-resolver/binding-wasm32-wasi@11.1.0': + resolution: {integrity: sha512-+yz7LYHKW1GK+fJoHh9JibgIWDeBHf5wiu1tgDD92y5eLFEBxP+CjJ2caTZnVRREH74l03twOfcTR9EaLsEidQ==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-resolver/binding-win32-arm64-msvc@9.0.2': - resolution: {integrity: sha512-5IhoOpPr38YWDWRCA5kP30xlUxbIJyLAEsAK7EMyUgqygBHEYLkElaKGgS0X5jRXUQ6l5yNxuW73caogb2FYaw==} + '@oxc-resolver/binding-win32-arm64-msvc@11.1.0': + resolution: {integrity: sha512-aTF/1TIq9v86Qy3++YFhKJVKXYSTO54yRRWIXwzpgGvZu41acjN/UsNOG7C2QFy/xdkitrZf1awYgawSqNox3g==} cpu: [arm64] os: [win32] - '@oxc-resolver/binding-win32-x64-msvc@9.0.2': - resolution: {integrity: sha512-Qc40GDkaad9rZksSQr2l/V9UubigIHsW69g94Gswc2sKYB3XfJXfIfyV8WTJ67u6ZMXsZ7BH1msSC6Aen75mCg==} + '@oxc-resolver/binding-win32-x64-msvc@11.1.0': + resolution: {integrity: sha512-CxalsPMU4oSoZviLMaw01RhLglyN7jrUUhTDRv4pYGcsRxxt5S7e/wO9P/lm5BYgAAq4TtP5MkGuGuMrm//a0g==} cpu: [x64] os: [win32] @@ -2754,11 +2754,11 @@ packages: resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} engines: {node: '>=12'} - '@tanstack/query-core@5.79.0': - resolution: {integrity: sha512-s+epTqqLM0/TbJzMAK7OEhZIzh63P9sWz5HEFc5XHL4FvKQXQkcjI8F3nee+H/xVVn7mrP610nVXwOytTSYd0w==} + '@tanstack/query-core@5.80.5': + resolution: {integrity: sha512-kFWXdQOUcjL/Ugk3GrI9eMuG3DsKBGaLIgyOLekR2UOrRrJgkLgPUNzZ10i8FCkfi4SgLABhOtQhx1HjoB9EZQ==} - '@tanstack/react-query@5.79.0': - resolution: {integrity: sha512-DjC4JIYZnYzxaTzbg3osOU63VNLP67dOrWet2cZvXgmgwAXNxfS52AMq86M5++ILuzW+BqTUEVMTjhrZ7/XBuA==} + '@tanstack/react-query@5.80.5': + resolution: {integrity: sha512-C0d+pvIahk6fJK5bXxyf36r9Ft6R9O0mwl781CjBrYGRJc76XRJcKhkVpxIo68cjMy3i47gd4O1EGooAke/OCQ==} peerDependencies: react: ^18 || ^19 @@ -4754,8 +4754,8 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fd-package-json@1.2.0: - resolution: {integrity: sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==} + fd-package-json@2.0.0: + resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} @@ -4823,8 +4823,8 @@ packages: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} - formatly@0.2.3: - resolution: {integrity: sha512-WH01vbXEjh9L3bqn5V620xUAWs32CmK4IzWRRY6ep5zpa/mrisL4d9+pRVuETORVDTQw8OycSO1WC68PL51RaA==} + formatly@0.2.4: + resolution: {integrity: sha512-lIN7GpcvX/l/i24r/L9bnJ0I8Qn01qijWpQpDDvTLL29nKqSaJJu4h20+7VJ6m2CAhQ2/En/GbxDiHCzq/0MyA==} engines: {node: '>=18.3.0'} hasBin: true @@ -5658,8 +5658,8 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - knip@5.59.1: - resolution: {integrity: sha512-pOMBw6sLQhi/RfnpI6TwBY6NrAtKXDO5wkmMm+pCsSK5eWbVfDnDtPXbLDGNCoZPXiuAojb27y4XOpp4JPNxlA==} + knip@5.60.0: + resolution: {integrity: sha512-r6oIbaV0Ztz/7DKe1voxg2O5IRhLi9Q0GjhplfRqUZ1gvTChew6ywmLzehuaXIHVKkPs8LF5UKOxFlc93RKzow==} engines: {node: '>=18.18.0'} hasBin: true peerDependencies: @@ -6300,8 +6300,8 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - oxc-resolver@9.0.2: - resolution: {integrity: sha512-w838ygc1p7rF+7+h5vR9A+Y9Fc4imy6C3xPthCMkdFUgFvUWkmABeNB8RBDQ6+afk44Q60/UMMQ+gfDUW99fBA==} + oxc-resolver@11.1.0: + resolution: {integrity: sha512-/W/9O6m7lkDJMIXtXvNKXE6THIoNWwstsKpR/R8+yI9e7vC9wu92MDqLBxkgckZ2fTFmKEjozTxVibHBaRUgCA==} p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} @@ -7248,8 +7248,8 @@ packages: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - smol-toml@1.3.1: - resolution: {integrity: sha512-tEYNll18pPKHroYSmLLrksq233j021G0giwW7P3D24jC54pQ5W5BXMsQ/Mvw1OJCmEYDgY+lrzT+3nNUtoNfXQ==} + smol-toml@1.3.4: + resolution: {integrity: sha512-UOPtVuYkzYGee0Bd2Szz8d2G3RfMfJ2t3qVdZUAozZyAk+a0Sxa+QKix0YCwjL/A1RR0ar44nCxaoN9FxdJGwA==} engines: {node: '>= 18'} snake-case@3.0.4: @@ -7403,8 +7403,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-json-comments@5.0.1: - resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} + strip-json-comments@5.0.2: + resolution: {integrity: sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g==} engines: {node: '>=14.16'} strip-literal@3.0.0: @@ -8036,8 +8036,9 @@ packages: vscode-uri@3.0.8: resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} - walk-up-path@3.0.1: - resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==} + walk-up-path@4.0.0: + resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} + engines: {node: 20 || >=22} web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} @@ -8200,6 +8201,9 @@ packages: zod@3.24.4: resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==} + zod@3.25.51: + resolution: {integrity: sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==} + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -9421,7 +9425,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@iconify/json@2.2.345': + '@iconify/json@2.2.346': dependencies: '@iconify/types': 2.0.0 pathe: 1.1.2 @@ -9906,45 +9910,45 @@ snapshots: '@octokit/request-error': 6.1.8 '@octokit/webhooks-methods': 5.1.1 - '@oxc-resolver/binding-darwin-arm64@9.0.2': + '@oxc-resolver/binding-darwin-arm64@11.1.0': optional: true - '@oxc-resolver/binding-darwin-x64@9.0.2': + '@oxc-resolver/binding-darwin-x64@11.1.0': optional: true - '@oxc-resolver/binding-freebsd-x64@9.0.2': + '@oxc-resolver/binding-freebsd-x64@11.1.0': optional: true - '@oxc-resolver/binding-linux-arm-gnueabihf@9.0.2': + '@oxc-resolver/binding-linux-arm-gnueabihf@11.1.0': optional: true - '@oxc-resolver/binding-linux-arm64-gnu@9.0.2': + '@oxc-resolver/binding-linux-arm64-gnu@11.1.0': optional: true - '@oxc-resolver/binding-linux-arm64-musl@9.0.2': + '@oxc-resolver/binding-linux-arm64-musl@11.1.0': optional: true - '@oxc-resolver/binding-linux-riscv64-gnu@9.0.2': + '@oxc-resolver/binding-linux-riscv64-gnu@11.1.0': optional: true - '@oxc-resolver/binding-linux-s390x-gnu@9.0.2': + '@oxc-resolver/binding-linux-s390x-gnu@11.1.0': optional: true - '@oxc-resolver/binding-linux-x64-gnu@9.0.2': + '@oxc-resolver/binding-linux-x64-gnu@11.1.0': optional: true - '@oxc-resolver/binding-linux-x64-musl@9.0.2': + '@oxc-resolver/binding-linux-x64-musl@11.1.0': optional: true - '@oxc-resolver/binding-wasm32-wasi@9.0.2': + '@oxc-resolver/binding-wasm32-wasi@11.1.0': dependencies: '@napi-rs/wasm-runtime': 0.2.10 optional: true - '@oxc-resolver/binding-win32-arm64-msvc@9.0.2': + '@oxc-resolver/binding-win32-arm64-msvc@11.1.0': optional: true - '@oxc-resolver/binding-win32-x64-msvc@9.0.2': + '@oxc-resolver/binding-win32-x64-msvc@11.1.0': optional: true '@parcel/watcher-android-arm64@2.4.1': @@ -10470,11 +10474,11 @@ snapshots: dependencies: remove-accents: 0.5.0 - '@tanstack/query-core@5.79.0': {} + '@tanstack/query-core@5.80.5': {} - '@tanstack/react-query@5.79.0(react@19.1.0)': + '@tanstack/react-query@5.80.5(react@19.1.0)': dependencies: - '@tanstack/query-core': 5.79.0 + '@tanstack/query-core': 5.80.5 react: 19.1.0 '@tanstack/react-router-devtools@1.120.15(@tanstack/react-router@1.120.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@tanstack/router-core@1.120.15)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tiny-invariant@1.3.3)': @@ -10540,7 +10544,7 @@ snapshots: '@tanstack/virtual-file-routes': 1.115.0 prettier: 3.5.3 tsx: 4.19.4 - zod: 3.24.4 + zod: 3.25.51 optionalDependencies: '@tanstack/react-router': 1.120.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -10562,7 +10566,7 @@ snapshots: babel-dead-code-elimination: 1.0.10 chokidar: 3.6.0 unplugin: 2.3.5 - zod: 3.24.4 + zod: 3.25.51 optionalDependencies: '@tanstack/react-router': 1.120.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0) vite: 6.3.5(@types/node@22.15.29)(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) @@ -10576,10 +10580,10 @@ snapshots: ansis: 3.12.0 diff: 7.0.0 - '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.120.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(zod@3.24.4)': + '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.120.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(zod@3.25.51)': dependencies: '@tanstack/react-router': 1.120.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - zod: 3.24.4 + zod: 3.25.51 '@tanstack/store@0.7.0': {} @@ -12863,9 +12867,9 @@ snapshots: dependencies: reusify: 1.0.4 - fd-package-json@1.2.0: + fd-package-json@2.0.0: dependencies: - walk-up-path: 3.0.1 + walk-up-path: 4.0.0 fd-slicer@1.1.0: dependencies: @@ -12935,9 +12939,9 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - formatly@0.2.3: + formatly@0.2.4: dependencies: - fd-package-json: 1.2.0 + fd-package-json: 2.0.0 formdata-polyfill@4.0.10: dependencies: @@ -13782,20 +13786,20 @@ snapshots: kind-of@6.0.3: {} - knip@5.59.1(@types/node@22.15.29)(typescript@5.8.3): + knip@5.60.0(@types/node@22.15.29)(typescript@5.8.3): dependencies: '@nodelib/fs.walk': 1.2.8 '@types/node': 22.15.29 fast-glob: 3.3.3 - formatly: 0.2.3 + formatly: 0.2.4 jiti: 2.4.2 js-yaml: 4.1.0 minimist: 1.2.8 - oxc-resolver: 9.0.2 + oxc-resolver: 11.1.0 picocolors: 1.1.1 picomatch: 4.0.2 - smol-toml: 1.3.1 - strip-json-comments: 5.0.1 + smol-toml: 1.3.4 + strip-json-comments: 5.0.2 typescript: 5.8.3 zod: 3.24.4 zod-validation-error: 3.3.1(zod@3.24.4) @@ -14581,21 +14585,21 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - oxc-resolver@9.0.2: + oxc-resolver@11.1.0: optionalDependencies: - '@oxc-resolver/binding-darwin-arm64': 9.0.2 - '@oxc-resolver/binding-darwin-x64': 9.0.2 - '@oxc-resolver/binding-freebsd-x64': 9.0.2 - '@oxc-resolver/binding-linux-arm-gnueabihf': 9.0.2 - '@oxc-resolver/binding-linux-arm64-gnu': 9.0.2 - '@oxc-resolver/binding-linux-arm64-musl': 9.0.2 - '@oxc-resolver/binding-linux-riscv64-gnu': 9.0.2 - '@oxc-resolver/binding-linux-s390x-gnu': 9.0.2 - '@oxc-resolver/binding-linux-x64-gnu': 9.0.2 - '@oxc-resolver/binding-linux-x64-musl': 9.0.2 - '@oxc-resolver/binding-wasm32-wasi': 9.0.2 - '@oxc-resolver/binding-win32-arm64-msvc': 9.0.2 - '@oxc-resolver/binding-win32-x64-msvc': 9.0.2 + '@oxc-resolver/binding-darwin-arm64': 11.1.0 + '@oxc-resolver/binding-darwin-x64': 11.1.0 + '@oxc-resolver/binding-freebsd-x64': 11.1.0 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.1.0 + '@oxc-resolver/binding-linux-arm64-gnu': 11.1.0 + '@oxc-resolver/binding-linux-arm64-musl': 11.1.0 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.1.0 + '@oxc-resolver/binding-linux-s390x-gnu': 11.1.0 + '@oxc-resolver/binding-linux-x64-gnu': 11.1.0 + '@oxc-resolver/binding-linux-x64-musl': 11.1.0 + '@oxc-resolver/binding-wasm32-wasi': 11.1.0 + '@oxc-resolver/binding-win32-arm64-msvc': 11.1.0 + '@oxc-resolver/binding-win32-x64-msvc': 11.1.0 p-cancelable@2.1.1: {} @@ -15500,7 +15504,7 @@ snapshots: smart-buffer@4.2.0: {} - smol-toml@1.3.1: {} + smol-toml@1.3.4: {} snake-case@3.0.4: dependencies: @@ -15675,7 +15679,7 @@ snapshots: strip-json-comments@3.1.1: {} - strip-json-comments@5.0.1: {} + strip-json-comments@5.0.2: {} strip-literal@3.0.0: dependencies: @@ -16409,7 +16413,7 @@ snapshots: vscode-uri@3.0.8: {} - walk-up-path@3.0.1: {} + walk-up-path@4.0.0: {} web-streams-polyfill@3.3.3: {} @@ -16589,4 +16593,6 @@ snapshots: zod@3.24.4: {} + zod@3.25.51: {} + zwitch@2.0.4: {} diff --git a/clash-nyanpasu/scripts/package.json b/clash-nyanpasu/scripts/package.json index 1c9d45d6ab..a000c1d64c 100644 --- a/clash-nyanpasu/scripts/package.json +++ b/clash-nyanpasu/scripts/package.json @@ -10,7 +10,7 @@ "filesize": "10.1.6", "p-retry": "6.2.1", "semver": "7.7.2", - "zod": "3.24.4" + "zod": "3.25.51" }, "devDependencies": { "@octokit/types": "14.1.0", diff --git a/clash-verge-rev/.github/ISSUE_TEMPLATE/i18n_request.yml b/clash-verge-rev/.github/ISSUE_TEMPLATE/i18n_request.yml new file mode 100644 index 0000000000..451e8b62f5 --- /dev/null +++ b/clash-verge-rev/.github/ISSUE_TEMPLATE/i18n_request.yml @@ -0,0 +1,58 @@ +name: I18N / 多语言相关 +title: "[I18N] " +description: 用于多语言翻译、国际化相关问题或建议 / For issues or suggestions related to translations and internationalization +labels: ["I18n"] +type: "Task" + +body: + - type: markdown + attributes: + value: | + ## I18N 相关问题/建议 + 请用此模板提交翻译错误、缺失、建议或新增语言请求。 + Please use this template for translation errors, missing translations, suggestions, or new language requests. + + - type: textarea + id: description + attributes: + label: 问题描述 / Description + description: 详细描述你的 I18N 问题或建议 / Please describe your I18N issue or suggestion in detail + validations: + required: true + + - type: input + id: language + attributes: + label: 相关语言 / Language + description: 例如 zh, en, jp, ru, ... / e.g. zh, en, jp, ru, ... + validations: + required: true + + - type: textarea + id: suggestion + attributes: + label: 建议或修正内容 / Suggestion or Correction + description: 如果是翻译修正或建议,请填写建议的内容 / If this is a translation correction or suggestion, please provide the suggested content + validations: + required: false + + - type: checkboxes + id: i18n-type + attributes: + label: 问题类型 / Issue Type + description: 请选择适用类型(可多选) / Please select the applicable type(s) + options: + - label: 翻译错误 / Translation error + - label: 翻译缺失 / Missing translation + - label: 建议优化 / Suggestion + - label: 新增语言 / New language + validations: + required: true + + - type: input + id: verge-version + attributes: + label: 软件版本 / Verge Version + description: 请提供你使用的 Verge 具体版本 / Please provide the specific version of Verge you are using + validations: + required: true diff --git a/clash-verge-rev/.github/workflows/alpha.yml b/clash-verge-rev/.github/workflows/alpha.yml index 876461790a..08bcf36fa2 100644 --- a/clash-verge-rev/.github/workflows/alpha.yml +++ b/clash-verge-rev/.github/workflows/alpha.yml @@ -4,10 +4,21 @@ on: # 因为 alpha 不再负责频繁构建,且需要相对于 autobuild 更稳定使用环境 # 所以不再使用 workflow_dispatch 触发 # 应当通过 git tag 来触发构建 - # workflow_dispatch: - push: - tags: - - "v*.*.*-alpha*" + # TODO 手动控制版本号 + workflow_dispatch: + # inputs: + # tag_name: + # description: "Alpha tag name (e.g. v1.2.3-alpha.1)" + # required: true + # type: string + + # push: + # # 应当限制在 dev 分支上触发发布。 + # branches: + # - dev + # # 应当限制 v*.*.*-alpha* 的 tag 来触发发布。 + # tags: + # - "v*.*.*-alpha*" permissions: write-all env: TAG_NAME: alpha @@ -18,8 +29,37 @@ concurrency: group: "${{ github.workflow }} - ${{ github.head_ref || github.ref }}" jobs: + check_alpha_tag: + name: Check Alpha Tag package.json Version Consistency + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check tag and package.json version + id: check_tag + run: | + TAG_REF="${GITHUB_REF##*/}" + echo "Current tag: $TAG_REF" + if [[ ! "$TAG_REF" =~ -alpha ]]; then + echo "Current tag is not an alpha tag." + exit 1 + fi + PKG_VERSION=$(jq -r .version package.json) + echo "package.json version: $PKG_VERSION" + if [[ "$PKG_VERSION" != *alpha* ]]; then + echo "package.json version is not an alpha version." + exit 1 + fi + if [[ "$TAG_REF" != "v$PKG_VERSION" ]]; then + echo "Tag ($TAG_REF) does not match package.json version (v$PKG_VERSION)." + exit 1 + fi + echo "Alpha tag and package.json version are consistent." + delete_old_assets: name: Delete Old Alpha Release Assets and Tags + needs: check_alpha_tag runs-on: ubuntu-latest steps: - name: Delete Old Alpha Tags Except Latest diff --git a/clash-verge-rev/.github/workflows/cross_check.yaml b/clash-verge-rev/.github/workflows/cross_check.yaml new file mode 100644 index 0000000000..433c5279ae --- /dev/null +++ b/clash-verge-rev/.github/workflows/cross_check.yaml @@ -0,0 +1,65 @@ +name: Cross Platform Cargo Check + +on: + workflow_dispatch: +# pull_request: +# push: +# branches: [main, dev] + +permissions: + contents: read + +jobs: + cargo-check: + # Treat all Rust compiler warnings as errors + env: + RUSTFLAGS: "-D warnings" + strategy: + fail-fast: false + matrix: + include: + - os: macos-latest + target: aarch64-apple-darwin + - os: windows-latest + target: x86_64-pc-windows-msvc + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + runs-on: ${{ matrix.os }} + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Install Rust Stable + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Add Rust Target + run: rustup target add ${{ matrix.target }} + + - name: Install Node + uses: actions/setup-node@v4 + with: + node-version: "20" + + - uses: pnpm/action-setup@v4 + name: Install pnpm + with: + run_install: false + + - name: Pnpm install and check + run: | + pnpm i + pnpm check ${{ matrix.target }} + + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + with: + workspaces: src-tauri + cache-all-crates: true + cache-on-failure: true + + - name: Cargo Check (deny warnings) + working-directory: src-tauri + run: | + cargo check --target ${{ matrix.target }} --workspace --all-features diff --git a/clash-verge-rev/.github/workflows/fmt.yml b/clash-verge-rev/.github/workflows/fmt.yml new file mode 100644 index 0000000000..1eef2560a4 --- /dev/null +++ b/clash-verge-rev/.github/workflows/fmt.yml @@ -0,0 +1,51 @@ +# Copyright 2019-2024 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT + +name: Check Formatting + +on: + pull_request: + +jobs: + rustfmt: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: install Rust stable and rustfmt + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + + - name: run cargo fmt + run: cargo fmt --manifest-path ./src-tauri/Cargo.toml --all -- --check + + prettier: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npm i -g --force corepack + - uses: actions/setup-node@v4 + with: + node-version: "lts/*" + cache: "pnpm" + - run: pnpm i --frozen-lockfile + - run: pnpm format:check + + # taplo: + # name: taplo (.toml files) + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + + # - name: install Rust stable + # uses: dtolnay/rust-toolchain@stable + + # - name: install taplo-cli + # uses: taiki-e/install-action@v2 + # with: + # tool: taplo-cli + + # - run: taplo fmt --check --diff diff --git a/clash-verge-rev/.github/workflows/release.yml b/clash-verge-rev/.github/workflows/release.yml index 8372eeeee8..1ad8f4d939 100644 --- a/clash-verge-rev/.github/workflows/release.yml +++ b/clash-verge-rev/.github/workflows/release.yml @@ -5,9 +5,10 @@ on: # ! 不再使用 workflow_dispatch 触发。 # workflow_dispatch: push: - # ? 应当限制在 main 分支上触发发布。 - # branches: - # - main + # 应当限制在 main 分支上触发发布。 + branches: + - main + # 应当限制 v*.*.* 的 tag 触发发布。 tags: - "v*.*.*" permissions: write-all @@ -20,8 +21,28 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: + check_tag_version: + name: Check Release Tag and package.json Version Consistency + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check tag and package.json version + run: | + TAG_REF="${GITHUB_REF##*/}" + echo "Current tag: $TAG_REF" + PKG_VERSION=$(jq -r .version package.json) + echo "package.json version: $PKG_VERSION" + if [[ "$TAG_REF" != "v$PKG_VERSION" ]]; then + echo "Tag ($TAG_REF) does not match package.json version (v$PKG_VERSION)." + exit 1 + fi + echo "Tag and package.json version are consistent." + release: name: Release Build + needs: check_tag_version strategy: fail-fast: false matrix: diff --git a/clash-verge-rev/.husky/pre-commit b/clash-verge-rev/.husky/pre-commit index 9774924235..4f437094de 100755 --- a/clash-verge-rev/.husky/pre-commit +++ b/clash-verge-rev/.husky/pre-commit @@ -2,15 +2,23 @@ #pnpm pretty-quick --staged -# 运行 clippy fmt -cd src-tauri -cargo fmt - -if [ $? -ne 0 ]; then - echo "rustfmt failed to format the code. Please fix the issues and try again." - exit 1 +if git diff --cached --name-only | grep -q '^src/'; then + pnpm format:check + if [ $? -ne 0 ]; then + echo "Code format check failed in src/. Please fix formatting issues." + exit 1 + fi +fi + +if git diff --cached --name-only | grep -q '^src-tauri/'; then + cd src-tauri + cargo fmt + if [ $? -ne 0 ]; then + echo "rustfmt failed to format the code. Please fix the issues and try again." + exit 1 + fi + cd .. fi -cd .. git add . diff --git a/clash-verge-rev/.prettierignore b/clash-verge-rev/.prettierignore new file mode 100644 index 0000000000..34a8e568c3 --- /dev/null +++ b/clash-verge-rev/.prettierignore @@ -0,0 +1,7 @@ +# README.md +# UPDATELOG.md +# CONTRIBUTING.md + +pnpm-lock.yaml + +src-tauri/target/ diff --git a/clash-verge-rev/.prettierrc b/clash-verge-rev/.prettierrc new file mode 100644 index 0000000000..6ca6fdd25b --- /dev/null +++ b/clash-verge-rev/.prettierrc @@ -0,0 +1,6 @@ +{ + "singleQuote": true, + "semi": false, + "trailingComma": "none", + "experimentalOperatorPosition": "start" +} diff --git a/clash-verge-rev/CONTRIBUTING.md b/clash-verge-rev/CONTRIBUTING.md index c19b67e7aa..7ad870501d 100644 --- a/clash-verge-rev/CONTRIBUTING.md +++ b/clash-verge-rev/CONTRIBUTING.md @@ -33,12 +33,15 @@ npm install pnpm -g ``` ### Install Dependencies + Install node packages + ```shell pnpm install ``` Install apt packages ONLY for Ubuntu + ```shell apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf ``` @@ -105,20 +108,25 @@ pnpm portable If you changed the rust code, it's recommanded to execute code style formatting and quailty checks. -1. Code style formatting +1. Code quailty checks ```bash +# For rust backend +$ clash-verge-rev: pnpm clippy +# For frontend (not yet). +``` + +2. Code style formatting + +```bash +# For rust backend $ clash-verge-rev: cd src-tauri $ clash-verge-rev/src-tauri: cargo fmt +# For frontend +$ clash-verge-rev: pnpm format:check +$ clash-verge-rev: pnpm format ``` -2. Code quailty checks - -```bash -$ clash-verge-rev: pnpm clippy -``` - - Once you have made your changes: 1. Fork the repository. diff --git a/clash-verge-rev/README.md b/clash-verge-rev/README.md index 724674f7fd..6aa3321b98 100644 --- a/clash-verge-rev/README.md +++ b/clash-verge-rev/README.md @@ -23,13 +23,13 @@ Supports Windows (x64/x86), Linux (x64/arm64) and macOS 10.15+ (intel/apple). #### 我应当怎样选择发行版 -| 版本 | 特征 | 链接 | -|:-----|:-----|:-----| -|Stable|正式版,高可靠性,适合日常使用。|[Release](https://github.com/clash-verge-rev/clash-verge-rev/releases) | -|Alpha|早期测试版,功能未完善,可能存在缺陷。|[Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha)| -|AutoBuild|滚动更新版,持续集成更新,适合开发测试。|[AutoBuild](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/autobuild)| +| 版本 | 特征 | 链接 | +| :-------- | :--------------------------------------- | :------------------------------------------------------------------------------------- | +| Stable | 正式版,高可靠性,适合日常使用。 | [Release](https://github.com/clash-verge-rev/clash-verge-rev/releases) | +| Alpha | 早期测试版,功能未完善,可能存在缺陷。 | [Alpha](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/alpha) | +| AutoBuild | 滚动更新版,持续集成更新,适合开发测试。 | [AutoBuild](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/autobuild) | -#### 安装说明和常见问题,请到 [文档页](https://clash-verge-rev.github.io/) 查看 +#### 安装说明和常见问题,请到 [文档页](https://clash-verge-rev.github.io/) 查看 --- @@ -49,11 +49,12 @@ Supports Windows (x64/x86), Linux (x64/arm64) and macOS 10.15+ (intel/apple). - 解锁流媒体及 ChatGPT - 官网:[https://狗狗加速.com](https://verge.dginv.click/#/register?code=oaxsAGo6) - #### 本项目的构建与发布环境由 [YXVM](https://yxvm.com/aff.php?aff=827) 独立服务器全力支持, + 感谢提供 独享资源、高性能、高速网络 的强大后端环境。如果你觉得下载够快、使用够爽,那是因为我们用了好服务器! 🧩 YXVM 独立服务器优势: + - 🌎 优质网络,回程优化,下载快到飞起 - 🔧 物理机独享资源,非VPS可比,性能拉满 - 🧠 适合跑代理、搭建 WEB 站 CDN 站 、搞 CI/CD 或任何高负载应用 diff --git a/clash-verge-rev/UPDATELOG.md b/clash-verge-rev/UPDATELOG.md index 217bf63852..4583c7b982 100644 --- a/clash-verge-rev/UPDATELOG.md +++ b/clash-verge-rev/UPDATELOG.md @@ -3,141 +3,153 @@ 尽管外部控制密钥已自动补全默认值且不允许为空。仍然推荐自行修改外部控制密钥。 #### ⚠️ 已知问题 - - 仅在Ubuntu 22.04/24.04,Fedora 41 **Gnome桌面环境** 做过简单测试,不保证其他其他Linux发行版可用,将在未来做进一步适配和调优 - - MacOS 下 墙贴主要为浅色,Tray 图标深色时图标闪烁;彩色 Tray 速率颜色淡 - - 窗口状态管理器已确定上游存在缺陷,暂时移除。当前不再内置窗口大小和位置记忆。 - - MacOS 下卸载服务后需手动重启软件才能与内核通信。 + +- 仅在Ubuntu 22.04/24.04,Fedora 41 **Gnome桌面环境** 做过简单测试,不保证其他其他Linux发行版可用,将在未来做进一步适配和调优 +- MacOS 下 墙贴主要为浅色,Tray 图标深色时图标闪烁;彩色 Tray 速率颜色淡 +- 窗口状态管理器已确定上游存在缺陷,暂时移除。当前不再内置窗口大小和位置记忆。 +- MacOS 下卸载服务后需手动重启软件才能与内核通信。 ### 2.3.0 相对于 2.2.3 + #### 🐞 修复问题 - - 首页"代理模式"快速切换导致的卡死问题 - - 解锁测试报错信息 - - Macos 快捷键关闭窗口无法启用自动轻量模式 - - 静默启动异常窗口创建和关闭流程 - - Windows 错误的全局快捷键 `Ctrl+Q` 注册 - - Vless URL 解码时网络类型错误 - - 切换自定义代理地址导致系统代理状态异常 - - Macos TUN 默认无效网卡名称 - - 托盘更改订阅后 UI 不同步的问题 - - 修复提权漏洞,改用带认证的 IPC 通信 - - 编辑器中连字符问题 - - 安装服务模式后无法立即开启 TUN 模式 - - 同步更新多语言翻译 - - 修复 .window-state.json 无法删除的问题 - - 无法修改配置更新 HTTP 请求超时 - - 修复 getDelayFix 钩子问题 - - 使用外部扩展脚本覆写代理组时首页无法显示代理组 - - 导出诊断 Verge 版本与设置页面不同步 - - 切换语言时可能造成设置页面无法加载 + +- 首页"代理模式"快速切换导致的卡死问题 +- 解锁测试报错信息 +- Macos 快捷键关闭窗口无法启用自动轻量模式 +- 静默启动异常窗口创建和关闭流程 +- Windows 错误的全局快捷键 `Ctrl+Q` 注册 +- Vless URL 解码时网络类型错误 +- 切换自定义代理地址导致系统代理状态异常 +- Macos TUN 默认无效网卡名称 +- 托盘更改订阅后 UI 不同步的问题 +- 修复提权漏洞,改用带认证的 IPC 通信 +- 编辑器中连字符问题 +- 安装服务模式后无法立即开启 TUN 模式 +- 同步更新多语言翻译 +- 修复 .window-state.json 无法删除的问题 +- 无法修改配置更新 HTTP 请求超时 +- 修复 getDelayFix 钩子问题 +- 使用外部扩展脚本覆写代理组时首页无法显示代理组 +- 导出诊断 Verge 版本与设置页面不同步 +- 切换语言时可能造成设置页面无法加载 #### ✨ 新增功能 - - Mihomo(Meta)内核升级至 1.19.10 - - 允许代理主机地址设置为非 127.0.0.1 对 WSL 代理友好 - - 关闭系统代理时关闭已建立的网络连接 - - 托盘显示当前轻量模式状态 - - Webdav 请求加入 UA - - Webdav 支持目录重定向 - - Webdav 备份目录检查和文件上传重试机制 - - 系统代理守卫可检查意外设置变更并恢复 - - 定时自动订阅更新也能自动回退使用代理 - - 订阅请求超时机制,防止订阅更新的时候卡死 - - 订阅卡片点击时间可切换下次自动更新时间,自动更新触发后页面有明确的成功与否提示 - - 添加网络管理器以优化网络请求处理,防止资源竞争导致的启动时 UI 卡死 - - 更新依赖,替换弃用元素 - - 首页当前节点增加排序功能 - - DNS 覆写下增加 Hosts 设置功能 - - 修复服务模式安装后无法立即开启 TUN 模式的问题 - - 支持手动卸载服务模式,回退到 Sidecar 模式 - - 添加了土耳其语,日本语,德语,西班牙语,繁体中文的支持 - - 卸载服务的按钮 - - 添加了Zashboard的一键跳转URL - - 使用操作系统默认的窗口管理器 - - 切换、升级、重启内核的状态管理 - - 更精细化控制自动日志清理,新增1天选项 - - Winodws 快捷键名称改为 `Clash Verge` - - 配置加载阶段自动补全 external-controller secret 字段。 + +- Mihomo(Meta)内核升级至 1.19.10 +- 允许代理主机地址设置为非 127.0.0.1 对 WSL 代理友好 +- 关闭系统代理时关闭已建立的网络连接 +- 托盘显示当前轻量模式状态 +- Webdav 请求加入 UA +- Webdav 支持目录重定向 +- Webdav 备份目录检查和文件上传重试机制 +- 系统代理守卫可检查意外设置变更并恢复 +- 定时自动订阅更新也能自动回退使用代理 +- 订阅请求超时机制,防止订阅更新的时候卡死 +- 订阅卡片点击时间可切换下次自动更新时间,自动更新触发后页面有明确的成功与否提示 +- 添加网络管理器以优化网络请求处理,防止资源竞争导致的启动时 UI 卡死 +- 更新依赖,替换弃用元素 +- 首页当前节点增加排序功能 +- DNS 覆写下增加 Hosts 设置功能 +- 修复服务模式安装后无法立即开启 TUN 模式的问题 +- 支持手动卸载服务模式,回退到 Sidecar 模式 +- 添加了土耳其语,日本语,德语,西班牙语,繁体中文的支持 +- 卸载服务的按钮 +- 添加了Zashboard的一键跳转URL +- 使用操作系统默认的窗口管理器 +- 切换、升级、重启内核的状态管理 +- 更精细化控制自动日志清理,新增1天选项 +- Winodws 快捷键名称改为 `Clash Verge` +- 配置加载阶段自动补全 external-controller secret 字段。 #### 🚀 优化改进 - - 系统代理 Bypass 设置 - - Windows 下使用 Startup 文件夹的方式实现开机自启,解决管理员模式下开机自启的各种问题 - - 切换到规则页面时自动刷新规则数据 - - 重构更新失败回退机制,使用后端完成更新失败后回退到使用 Clash 代理再次尝试更新 - - 编辑非激活订阅的时候不在触发当前订阅配置重载 - - 改进核心功能防止主进程阻塞、改进MihomoManager实现,以及优化窗口创建流程 - - 优化系统代理设置更新逻辑 - - 重构前端通知系统分离通知线程防止前端卡死 - - 优化网络请求和错误处理 - - 重构通知系统 - - 使用异步方法重构 UI 启动逻辑,解决启动软件过程中的各种卡死问题 - - MacOS 下默认关闭托盘速率显示 - - 优化服务操作流程,提升系统服务相关操作的稳定性和用户体验 - - 优化了其他语言的翻译问题 - - Mihomo 内核默认日志等级为 warn - - Clash Verge Rev 应用默认日志等级为 warn - - 重构了原来的 IP 信息请求重试机制,采用轮询检测,解决了 Network Error 和超时问题 - - 对轮询检测机制进行了优化,引入洗牌算法来增强随机性 - - 对获取系统信息的流程进行了优化,并添加了去重检测机制,确保剔除重复的信息 - - 优化窗口状态初始化逻辑和添加缺失的权限设置 - - 异步化配置:优化端口查找和配置保存逻辑 - - 重构事件通知机制到独立线程,避免前端卡死 - - 优化端口设置,每个端口可随机设置端口号 - - 优化了保存机制,使用平滑函数,防止客户端卡死 - - 优化端口设置退出和保存机制 - - 强制为 Mihomo 配置补全并覆盖 external-controller-cors 字段,默认不允许跨域和仅本地请求,提升 cors 安全性,升级配置时自动覆盖 - - 修改 端口检测范围 (1111-65536) - - 配置文件缺失 secret 字段时自动填充默认值 set-your-secret - - 优化异步处理,防止部分组件 UI 阻塞 - - 关闭 DNS 启用 - - 延迟测试链接更换为 Https 协议 https://cp.cloudflare.com/generate_204 + +- 系统代理 Bypass 设置 +- Windows 下使用 Startup 文件夹的方式实现开机自启,解决管理员模式下开机自启的各种问题 +- 切换到规则页面时自动刷新规则数据 +- 重构更新失败回退机制,使用后端完成更新失败后回退到使用 Clash 代理再次尝试更新 +- 编辑非激活订阅的时候不在触发当前订阅配置重载 +- 改进核心功能防止主进程阻塞、改进MihomoManager实现,以及优化窗口创建流程 +- 优化系统代理设置更新逻辑 +- 重构前端通知系统分离通知线程防止前端卡死 +- 优化网络请求和错误处理 +- 重构通知系统 +- 使用异步方法重构 UI 启动逻辑,解决启动软件过程中的各种卡死问题 +- MacOS 下默认关闭托盘速率显示 +- 优化服务操作流程,提升系统服务相关操作的稳定性和用户体验 +- 优化了其他语言的翻译问题 +- Mihomo 内核默认日志等级为 warn +- Clash Verge Rev 应用默认日志等级为 warn +- 重构了原来的 IP 信息请求重试机制,采用轮询检测,解决了 Network Error 和超时问题 +- 对轮询检测机制进行了优化,引入洗牌算法来增强随机性 +- 对获取系统信息的流程进行了优化,并添加了去重检测机制,确保剔除重复的信息 +- 优化窗口状态初始化逻辑和添加缺失的权限设置 +- 异步化配置:优化端口查找和配置保存逻辑 +- 重构事件通知机制到独立线程,避免前端卡死 +- 优化端口设置,每个端口可随机设置端口号 +- 优化了保存机制,使用平滑函数,防止客户端卡死 +- 优化端口设置退出和保存机制 +- 强制为 Mihomo 配置补全并覆盖 external-controller-cors 字段,默认不允许跨域和仅本地请求,提升 cors 安全性,升级配置时自动覆盖 +- 修改 端口检测范围 (1111-65536) +- 配置文件缺失 secret 字段时自动填充默认值 set-your-secret +- 优化异步处理,防止部分组件 UI 阻塞 +- 关闭 DNS 启用 +- 延迟测试链接更换为 Https 协议 https://cp.cloudflare.com/generate_204 #### 🗑️ 移除内容 - - 窗口状态管理器 - - Webdav 跨平台备份恢复限制 + +- 窗口状态管理器 +- Webdav 跨平台备份恢复限制 ## v2.2.3 #### 已知问题 - - 仅在Ubuntu 22.04/24.04,Fedora 41 **Gnome桌面环境** 做过简单测试,不保证其他其他Linux发行版可用,将在未来做进一步适配和调优 - - MacOS 自定义图标与速率显示推荐图标尺寸为 256x256。其他尺寸(可能)会导致不正常图标和速率间隙 - - MacOS 下 墙贴主要为浅色,Tray 图标深色时图标闪烁;彩色 Tray 速率颜色淡 - - Linux 下 Clash Verge Rev 内存占用显著高于 Windows / MacOS + +- 仅在Ubuntu 22.04/24.04,Fedora 41 **Gnome桌面环境** 做过简单测试,不保证其他其他Linux发行版可用,将在未来做进一步适配和调优 +- MacOS 自定义图标与速率显示推荐图标尺寸为 256x256。其他尺寸(可能)会导致不正常图标和速率间隙 +- MacOS 下 墙贴主要为浅色,Tray 图标深色时图标闪烁;彩色 Tray 速率颜色淡 +- Linux 下 Clash Verge Rev 内存占用显著高于 Windows / MacOS ### 2.2.3 相对于 2.2.2 + #### 修复了: - - 首页“当前代理”因为重复刷新导致的CPU占用过高的问题 - - “开机自启”和“DNS覆写”开关跳动问题 - - 自定义托盘图标未能应用更改 - - MacOS 自定义托盘图标显示速率时图标和文本间隙过大 - - MacOS 托盘速率显示不全 - - Linux 在系统服务模式下无法拉起 Mihomo 内核 - - 使用异步操作,避免获取系统信息和切换代理模式可能带来的崩溃 - - 相同节点名称可能导致的页面渲染出错 - - URL Schemes被截断的问题 - - 首页流量统计卡更好的时间戳范围 - - 静默启动无法触发自动轻量化计时器 + +- 首页“当前代理”因为重复刷新导致的CPU占用过高的问题 +- “开机自启”和“DNS覆写”开关跳动问题 +- 自定义托盘图标未能应用更改 +- MacOS 自定义托盘图标显示速率时图标和文本间隙过大 +- MacOS 托盘速率显示不全 +- Linux 在系统服务模式下无法拉起 Mihomo 内核 +- 使用异步操作,避免获取系统信息和切换代理模式可能带来的崩溃 +- 相同节点名称可能导致的页面渲染出错 +- URL Schemes被截断的问题 +- 首页流量统计卡更好的时间戳范围 +- 静默启动无法触发自动轻量化计时器 #### 新增了: - - Mihomo(Meta)内核升级至 1.19.4 - - Clash Verge Rev 从现在开始不再强依赖系统服务和管理权限 - - 支持根据用户偏好选择Sidecar(用户空间)模式或安装服务 - - 增加载入初始配置文件的错误提示,防止切换到错误的订阅配置 - - 检测是否以管理员模式运行软件,如果是提示无法使用开机自启 - - 代理组显示节点数量 - - 统一运行模式检测,支持管理员模式下开启TUN模式 - - 托盘切换代理模式会根据设置自动断开之前连接 - - 如订阅获取失败回退使用Clash内核代理再次尝试 + +- Mihomo(Meta)内核升级至 1.19.4 +- Clash Verge Rev 从现在开始不再强依赖系统服务和管理权限 +- 支持根据用户偏好选择Sidecar(用户空间)模式或安装服务 +- 增加载入初始配置文件的错误提示,防止切换到错误的订阅配置 +- 检测是否以管理员模式运行软件,如果是提示无法使用开机自启 +- 代理组显示节点数量 +- 统一运行模式检测,支持管理员模式下开启TUN模式 +- 托盘切换代理模式会根据设置自动断开之前连接 +- 如订阅获取失败回退使用Clash内核代理再次尝试 #### 移除了: - - 实时保存窗口位置和大小。这个功能可能会导致窗口异常大小和位置,还需观察。 + +- 实时保存窗口位置和大小。这个功能可能会导致窗口异常大小和位置,还需观察。 #### 优化了: - - 重构了后端内核管理逻辑,更轻量化和有效的管理内核,提高了性能和稳定性 - - 前端统一刷新应用数据,优化数据获取和刷新逻辑 - - 优化首页流量图表代码,调整图表文字边距 - - MacOS 托盘速率更好的显示样式和更新逻辑 - - 首页仅在有流量图表时显示流量图表区域 - - 更新DNS默认覆写配置 - - 移除测试目录,简化资源初始化逻辑 + +- 重构了后端内核管理逻辑,更轻量化和有效的管理内核,提高了性能和稳定性 +- 前端统一刷新应用数据,优化数据获取和刷新逻辑 +- 优化首页流量图表代码,调整图表文字边距 +- MacOS 托盘速率更好的显示样式和更新逻辑 +- 首页仅在有流量图表时显示流量图表区域 +- 更新DNS默认覆写配置 +- 移除测试目录,简化资源初始化逻辑 ## v2.2.2 @@ -148,23 +160,29 @@ 代号释义: 本次发布在功能上的大幅扩展。新首页设计为用户带来全新交互体验,DNS 覆写功能增强网络控制能力,解锁测试页面助力内容访问自由度提升,轻量模式提供灵活使用选择。此外,macOS 应用菜单集成、sidecar 模式、诊断信息导出等新特性进一步丰富了软件的适用场景。这些新增功能显著拓宽了 Clash Verge 的功能边界,为用户提供了更强大的工具和可能性。 #### 已知问题 - - 仅在Ubuntu 22.04/24.04,Fedora 41 **Gnome桌面环境** 做过简单测试,不保证其他其他Linux发行版可用,将在未来做进一步适配和调优 + +- 仅在Ubuntu 22.04/24.04,Fedora 41 **Gnome桌面环境** 做过简单测试,不保证其他其他Linux发行版可用,将在未来做进一步适配和调优 ### 2.2.2 相对于 2.2.1(已下架不再提供) + #### 修复了: - - 弹黑框的问题(原因是服务崩溃触发重装机制) - - MacOS进入轻量模式以后隐藏Dock图标 - - 增加轻量模式缺失的tray翻译 - - Linux下的窗口边框被削掉的问题 + +- 弹黑框的问题(原因是服务崩溃触发重装机制) +- MacOS进入轻量模式以后隐藏Dock图标 +- 增加轻量模式缺失的tray翻译 +- Linux下的窗口边框被削掉的问题 #### 新增了: - - 加强服务检测和重装逻辑 - - 增强内核与服务保活机制 - - 增加服务模式下的僵尸进程清理机制 - - 新增当服务模式多次尝试失败后自动回退至用户空间模式 + +- 加强服务检测和重装逻辑 +- 增强内核与服务保活机制 +- 增加服务模式下的僵尸进程清理机制 +- 新增当服务模式多次尝试失败后自动回退至用户空间模式 ### 2.2.1 相对于 2.2.0(已下架不再提供) + #### 修复了: + 1. **首页** - 修复 Direct 模式首页无法渲染 - 修复 首页启用轻量模式导致 ClashVergeRev 从托盘退出 @@ -181,6 +199,7 @@ - 修复 MacOS 轻量模式下 Dock 栏图标无法隐藏。 #### 新增了: + 1. **首页** - 首页文本过长自动截断 2. **轻量模式** @@ -197,7 +216,9 @@ ## 2.2.0(已下架不再提供) #### 新增功能 + 1. **首页** + - 新增首页功能,默认启动页面改为首页。 - 首页流量图卡片显示上传/下载名称。 - 首页支持轻量模式切换。 @@ -205,17 +226,21 @@ - 限制首页配置文件卡片URL长度。 2. **DNS 设置与覆写** + - 新增 DNS 覆写功能。 - 默认启用 DNS 覆写。 3. **解锁测试** + - 新增解锁测试页面。 4. **轻量模式** + - 新增轻量模式及设置。 - 添加自动轻量模式定时器。 5. **系统支持** + - Mihomo(meta)内核升级 1.19.3 - macOS 支持 CMD+W 关闭窗口。 - 新增 macOS 应用菜单。 @@ -228,7 +253,9 @@ - 新增代理命令。 #### 修复 + 1. **系统** + - 修复 Windows 热键崩溃。 - 修复 macOS 无框标题。 - 修复 macOS 静默启动崩溃。 @@ -241,7 +268,9 @@ - 修复构建失败问题。 #### 优化 + 1. **性能** + - 重构后端,巨幅性能优化。 - 优化首页组件性能。 - 优化流量图表资源使用。 @@ -254,6 +283,7 @@ - 优化修改verge配置性能。 2. **重构** + - 重构后端,巨幅性能优化。 - 优化定时器管理。 - 重构 MihomoManager 处理流量。 diff --git a/clash-verge-rev/package.json b/clash-verge-rev/package.json index 7bdb9e4d83..ea726270a3 100644 --- a/clash-verge-rev/package.json +++ b/clash-verge-rev/package.json @@ -1,6 +1,6 @@ { "name": "clash-verge", - "version": "2.3.0-alpha", + "version": "2.3.0", "license": "GPL-3.0-only", "scripts": { "dev": "cross-env RUST_BACKTRACE=1 tauri dev -f verge-dev", @@ -21,7 +21,9 @@ "publish-version": "node scripts/publish-version.mjs", "prepare": "husky", "fmt": "cargo fmt --manifest-path ./src-tauri/Cargo.toml", - "clippy": "cargo clippy --manifest-path ./src-tauri/Cargo.toml" + "clippy": "cargo clippy --manifest-path ./src-tauri/Cargo.toml", + "format": "prettier --write .", + "format:check": "prettier --check ." }, "dependencies": { "@dnd-kit/core": "^6.3.1", @@ -30,15 +32,15 @@ "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@juggle/resize-observer": "^3.4.0", - "@mui/icons-material": "^7.0.2", - "@mui/lab": "7.0.0-beta.12", - "@mui/material": "^7.0.2", - "@mui/x-data-grid": "^8.2.0", + "@mui/icons-material": "^7.1.1", + "@mui/lab": "7.0.0-beta.13", + "@mui/material": "^7.1.1", + "@mui/x-data-grid": "^8.5.0", "@tauri-apps/api": "2.5.0", "@tauri-apps/plugin-clipboard-manager": "^2.2.2", - "@tauri-apps/plugin-dialog": "^2.2.1", - "@tauri-apps/plugin-fs": "^2.2.1", - "@tauri-apps/plugin-global-shortcut": "^2.2.0", + "@tauri-apps/plugin-dialog": "^2.2.2", + "@tauri-apps/plugin-fs": "^2.3.0", + "@tauri-apps/plugin-global-shortcut": "^2.2.1", "@tauri-apps/plugin-notification": "^2.2.2", "@tauri-apps/plugin-process": "^2.2.1", "@tauri-apps/plugin-shell": "2.2.1", @@ -46,61 +48,61 @@ "@tauri-apps/plugin-window-state": "^2.2.2", "@types/d3-shape": "^3.1.7", "@types/json-schema": "^7.0.15", - "ahooks": "^3.8.4", - "axios": "^1.8.3", + "ahooks": "^3.8.5", + "axios": "^1.9.0", "chart.js": "^4.4.9", "cli-color": "^2.0.4", "d3-shape": "^3.2.0", "dayjs": "1.11.13", - "foxact": "^0.2.44", - "glob": "^11.0.1", - "i18next": "^25.0.2", + "foxact": "^0.2.45", + "glob": "^11.0.2", + "i18next": "^25.2.1", "js-base64": "^3.7.7", "js-yaml": "^4.1.0", "lodash-es": "^4.17.21", "monaco-editor": "^0.52.2", - "monaco-yaml": "^5.3.1", + "monaco-yaml": "^5.4.0", "nanoid": "^5.1.5", - "peggy": "^5.0.0", + "peggy": "^5.0.3", "react": "19.1.0", "react-chartjs-2": "^5.3.0", "react-dom": "19.1.0", "react-error-boundary": "6.0.0", - "react-hook-form": "^7.54.2", - "react-i18next": "15.5.1", + "react-hook-form": "^7.57.0", + "react-i18next": "15.5.2", "react-markdown": "10.1.0", "react-monaco-editor": "0.58.0", - "react-router-dom": "7.6.0", - "react-virtuoso": "^4.12.7", + "react-router-dom": "7.6.2", + "react-virtuoso": "^4.12.8", "sockette": "^2.0.6", "swr": "^2.3.3", "tar": "^7.4.3", "types-pac": "^1.0.3", - "zustand": "^5.0.3" + "zustand": "^5.0.5" }, "devDependencies": { - "@actions/github": "^6.0.0", - "@tauri-apps/cli": "2.2.7", + "@actions/github": "^6.0.1", + "@tauri-apps/cli": "2.5.0", "@types/js-cookie": "^3.0.6", "@types/js-yaml": "^4.0.9", "@types/lodash-es": "^4.17.12", - "@types/react": "19.1.4", - "@types/react-dom": "19.1.5", - "@vitejs/plugin-legacy": "^6.0.2", - "@vitejs/plugin-react": "4.4.1", + "@types/react": "19.1.6", + "@types/react-dom": "19.1.6", + "@vitejs/plugin-legacy": "^6.1.1", + "@vitejs/plugin-react": "4.5.1", "adm-zip": "^0.5.16", "commander": "^14.0.0", "cross-env": "^7.0.3", "https-proxy-agent": "^7.0.6", "husky": "^9.1.7", - "meta-json-schema": "^1.19.3", + "meta-json-schema": "^1.19.10", "node-fetch": "^3.3.2", "prettier": "^3.5.3", - "pretty-quick": "^4.1.1", - "sass": "^1.86.0", - "terser": "^5.39.0", - "typescript": "^5.8.2", - "vite": "^6.2.2", + "pretty-quick": "^4.2.2", + "sass": "^1.89.1", + "terser": "^5.40.0", + "typescript": "^5.8.3", + "vite": "^6.3.5", "vite-plugin-monaco-editor": "^1.1.0", "vite-plugin-svgr": "^4.3.0" }, @@ -112,4 +114,4 @@ }, "type": "module", "packageManager": "pnpm@9.13.2" -} \ No newline at end of file +} diff --git a/clash-verge-rev/pnpm-lock.yaml b/clash-verge-rev/pnpm-lock.yaml index 4391a30a9f..45343e0fa5 100644 --- a/clash-verge-rev/pnpm-lock.yaml +++ b/clash-verge-rev/pnpm-lock.yaml @@ -19,25 +19,25 @@ importers: version: 3.2.2(react@19.1.0) '@emotion/react': specifier: ^11.14.0 - version: 11.14.0(@types/react@19.1.4)(react@19.1.0) + version: 11.14.0(@types/react@19.1.6)(react@19.1.0) '@emotion/styled': specifier: ^11.14.0 - version: 11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) + version: 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) '@juggle/resize-observer': specifier: ^3.4.0 version: 3.4.0 '@mui/icons-material': - specifier: ^7.0.2 - version: 7.1.0(@mui/material@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) + specifier: ^7.1.1 + version: 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/lab': - specifier: 7.0.0-beta.12 - version: 7.0.0-beta.12(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@mui/material@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 7.0.0-beta.13 + version: 7.0.0-beta.13(@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))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@mui/material': - specifier: ^7.0.2 - version: 7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + 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-data-grid': - specifier: ^8.2.0 - version: 8.3.1(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@mui/material@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^8.5.0 + version: 8.5.0(@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)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@tauri-apps/api': specifier: 2.5.0 version: 2.5.0 @@ -45,14 +45,14 @@ importers: specifier: ^2.2.2 version: 2.2.2 '@tauri-apps/plugin-dialog': - specifier: ^2.2.1 - version: 2.2.1 + specifier: ^2.2.2 + version: 2.2.2 '@tauri-apps/plugin-fs': + specifier: ^2.3.0 + version: 2.3.0 + '@tauri-apps/plugin-global-shortcut': specifier: ^2.2.1 version: 2.2.1 - '@tauri-apps/plugin-global-shortcut': - specifier: ^2.2.0 - version: 2.2.0 '@tauri-apps/plugin-notification': specifier: ^2.2.2 version: 2.2.2 @@ -75,10 +75,10 @@ importers: specifier: ^7.0.15 version: 7.0.15 ahooks: - specifier: ^3.8.4 - version: 3.8.4(react@19.1.0) + specifier: ^3.8.5 + version: 3.8.5(react@19.1.0) axios: - specifier: ^1.8.3 + specifier: ^1.9.0 version: 1.9.0 chart.js: specifier: ^4.4.9 @@ -93,14 +93,14 @@ importers: specifier: 1.11.13 version: 1.11.13 foxact: - specifier: ^0.2.44 + specifier: ^0.2.45 version: 0.2.45(react@19.1.0) glob: - specifier: ^11.0.1 + specifier: ^11.0.2 version: 11.0.2 i18next: - specifier: ^25.0.2 - version: 25.1.2(typescript@5.8.3) + specifier: ^25.2.1 + version: 25.2.1(typescript@5.8.3) js-base64: specifier: ^3.7.7 version: 3.7.7 @@ -114,14 +114,14 @@ importers: specifier: ^0.52.2 version: 0.52.2 monaco-yaml: - specifier: ^5.3.1 + specifier: ^5.4.0 version: 5.4.0(monaco-editor@0.52.2) nanoid: specifier: ^5.1.5 version: 5.1.5 peggy: - specifier: ^5.0.0 - version: 5.0.2 + specifier: ^5.0.3 + version: 5.0.3 react: specifier: 19.1.0 version: 19.1.0 @@ -135,23 +135,23 @@ importers: specifier: 6.0.0 version: 6.0.0(react@19.1.0) react-hook-form: - specifier: ^7.54.2 - version: 7.56.3(react@19.1.0) + specifier: ^7.57.0 + version: 7.57.0(react@19.1.0) react-i18next: - specifier: 15.5.1 - version: 15.5.1(i18next@25.1.2(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3) + 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) react-markdown: specifier: 10.1.0 - version: 10.1.0(@types/react@19.1.4)(react@19.1.0) + version: 10.1.0(@types/react@19.1.6)(react@19.1.0) react-monaco-editor: specifier: 0.58.0 version: 0.58.0(monaco-editor@0.52.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-router-dom: - specifier: 7.6.0 - version: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 7.6.2 + version: 7.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-virtuoso: - specifier: ^4.12.7 - version: 4.12.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^4.12.8 + version: 4.12.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0) sockette: specifier: ^2.0.6 version: 2.0.6 @@ -165,15 +165,15 @@ importers: specifier: ^1.0.3 version: 1.0.3 zustand: - specifier: ^5.0.3 - version: 5.0.4(@types/react@19.1.4)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) + specifier: ^5.0.5 + version: 5.0.5(@types/react@19.1.6)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) devDependencies: '@actions/github': - specifier: ^6.0.0 + specifier: ^6.0.1 version: 6.0.1 '@tauri-apps/cli': - specifier: 2.2.7 - version: 2.2.7 + specifier: 2.5.0 + version: 2.5.0 '@types/js-cookie': specifier: ^3.0.6 version: 3.0.6 @@ -184,17 +184,17 @@ importers: specifier: ^4.17.12 version: 4.17.12 '@types/react': - specifier: 19.1.4 - version: 19.1.4 + specifier: 19.1.6 + version: 19.1.6 '@types/react-dom': - specifier: 19.1.5 - version: 19.1.5(@types/react@19.1.4) + specifier: 19.1.6 + version: 19.1.6(@types/react@19.1.6) '@vitejs/plugin-legacy': - specifier: ^6.0.2 - version: 6.1.1(terser@5.39.1)(vite@6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1)) + specifier: ^6.1.1 + version: 6.1.1(terser@5.40.0)(vite@6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1)) '@vitejs/plugin-react': - specifier: 4.4.1 - version: 4.4.1(vite@6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1)) + specifier: 4.5.1 + version: 4.5.1(vite@6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1)) adm-zip: specifier: ^0.5.16 version: 0.5.16 @@ -211,8 +211,8 @@ importers: specifier: ^9.1.7 version: 9.1.7 meta-json-schema: - specifier: ^1.19.3 - version: 1.19.5 + specifier: ^1.19.10 + version: 1.19.10 node-fetch: specifier: ^3.3.2 version: 3.3.2 @@ -220,26 +220,26 @@ importers: specifier: ^3.5.3 version: 3.5.3 pretty-quick: - specifier: ^4.1.1 - version: 4.1.1(prettier@3.5.3) + specifier: ^4.2.2 + version: 4.2.2(prettier@3.5.3) sass: - specifier: ^1.86.0 - version: 1.88.0 + specifier: ^1.89.1 + version: 1.89.1 terser: - specifier: ^5.39.0 - version: 5.39.1 + specifier: ^5.40.0 + version: 5.40.0 typescript: - specifier: ^5.8.2 + specifier: ^5.8.3 version: 5.8.3 vite: - specifier: ^6.2.2 - version: 6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1) + specifier: ^6.3.5 + version: 6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1) vite-plugin-monaco-editor: specifier: ^1.1.0 version: 1.1.0(monaco-editor@0.52.2) vite-plugin-svgr: specifier: ^4.3.0 - version: 4.3.0(rollup@4.40.2)(typescript@5.8.3)(vite@6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1)) + version: 4.3.0(rollup@4.40.2)(typescript@5.8.3)(vite@6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1)) packages: @@ -1015,28 +1015,28 @@ packages: '@kurkle/color@0.3.4': resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==} - '@mui/core-downloads-tracker@7.1.0': - resolution: {integrity: sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ==} + '@mui/core-downloads-tracker@7.1.1': + resolution: {integrity: sha512-yBckQs4aQ8mqukLnPC6ivIRv6guhaXi8snVl00VtyojBbm+l6VbVhyTSZ68Abcx7Ah8B+GZhrB7BOli+e+9LkQ==} - '@mui/icons-material@7.1.0': - resolution: {integrity: sha512-1mUPMAZ+Qk3jfgL5ftRR06ATH/Esi0izHl1z56H+df6cwIlCWG66RXciUqeJCttbOXOQ5y2DCjLZI/4t3Yg3LA==} + '@mui/icons-material@7.1.1': + resolution: {integrity: sha512-X37+Yc8QpEnl0sYmz+WcLFy2dWgNRzbswDzLPXG7QU1XDVlP5TPp1HXjdmCupOWLL/I9m1fyhcyZl8/HPpp/Cg==} engines: {node: '>=14.0.0'} peerDependencies: - '@mui/material': ^7.1.0 + '@mui/material': ^7.1.1 '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: '@types/react': optional: true - '@mui/lab@7.0.0-beta.12': - resolution: {integrity: sha512-685MmzByCy3Vmb7xI6J8qOQm4l7yqfVTOLwxVmNV1EHBKuJiMuoX4/2vAAEGfNbDeEfWQsp7aBWanYpSWe1iRA==} + '@mui/lab@7.0.0-beta.13': + resolution: {integrity: sha512-wLSeePenug3+/kek4cFMIF3QZVC2fHt2Z3O3HwOFvakgErmT39WltYsNpWNojCnXUqcIExUp9xNW0Wk+tJShgA==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.5.0 '@emotion/styled': ^11.3.0 - '@mui/material': ^7.1.0 - '@mui/material-pigment-css': ^7.1.0 + '@mui/material': ^7.1.1 + '@mui/material-pigment-css': ^7.1.1 '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -1050,13 +1050,13 @@ packages: '@types/react': optional: true - '@mui/material@7.1.0': - resolution: {integrity: sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg==} + '@mui/material@7.1.1': + resolution: {integrity: sha512-mTpdmdZCaHCGOH3SrYM41+XKvNL0iQfM9KlYgpSjgadXx/fEKhhvOktxm8++Xw6FFeOHoOiV+lzOI8X1rsv71A==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.5.0 '@emotion/styled': ^11.3.0 - '@mui/material-pigment-css': ^7.1.0 + '@mui/material-pigment-css': ^7.1.1 '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -1070,8 +1070,8 @@ packages: '@types/react': optional: true - '@mui/private-theming@7.1.0': - resolution: {integrity: sha512-4Kck4jxhqF6YxNwJdSae1WgDfXVg0lIH6JVJ7gtuFfuKcQCgomJxPvUEOySTFRPz1IZzwz5OAcToskRdffElDA==} + '@mui/private-theming@7.1.1': + resolution: {integrity: sha512-M8NbLUx+armk2ZuaxBkkMk11ultnWmrPlN0Xe3jUEaBChg/mcxa5HWIWS1EE4DF36WRACaAHVAvyekWlDQf0PQ==} engines: {node: '>=14.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -1080,8 +1080,8 @@ packages: '@types/react': optional: true - '@mui/styled-engine@7.1.0': - resolution: {integrity: sha512-m0mJ0c6iRC+f9hMeRe0W7zZX1wme3oUX0+XTVHjPG7DJz6OdQ6K/ggEOq7ZdwilcpdsDUwwMfOmvO71qDkYd2w==} + '@mui/styled-engine@7.1.1': + resolution: {integrity: sha512-R2wpzmSN127j26HrCPYVQ53vvMcT5DaKLoWkrfwUYq3cYytL6TQrCH8JBH3z79B6g4nMZZVoaXrxO757AlShaw==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.4.1 @@ -1093,8 +1093,8 @@ packages: '@emotion/styled': optional: true - '@mui/system@7.1.0': - resolution: {integrity: sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA==} + '@mui/system@7.1.1': + resolution: {integrity: sha512-Kj1uhiqnj4Zo7PDjAOghtXJtNABunWvhcRU0O7RQJ7WOxeynoH6wXPcilphV8QTFtkKaip8EiNJRiCD+B3eROA==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -1109,16 +1109,16 @@ packages: '@types/react': optional: true - '@mui/types@7.4.2': - resolution: {integrity: sha512-edRc5JcLPsrlNFYyTPxds+d5oUovuUxnnDtpJUbP6WMeV4+6eaX/mqai1ZIWT62lCOe0nlrON0s9HDiv5en5bA==} + '@mui/types@7.4.3': + resolution: {integrity: sha512-2UCEiK29vtiZTeLdS2d4GndBKacVyxGvReznGXGr+CzW/YhjIX+OHUdCIczZjzcRAgKBGmE9zCIgoV9FleuyRQ==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: '@types/react': optional: true - '@mui/utils@7.1.0': - resolution: {integrity: sha512-/OM3S8kSHHmWNOP+NH9xEtpYSG10upXeQ0wLZnfDgmgadTAk5F4MQfFLyZ5FCRJENB3eRzltMmaNl6UtDnPovw==} + '@mui/utils@7.1.1': + resolution: {integrity: sha512-BkOt2q7MBYl7pweY2JWwfrlahhp+uGLR8S+EhiyRaofeRYUWL2YKbSGQvN4hgSN1i8poN0PaUiii1kEMrchvzg==} engines: {node: '>=14.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -1127,8 +1127,8 @@ packages: '@types/react': optional: true - '@mui/x-data-grid@8.3.1': - resolution: {integrity: sha512-mSo2g0ZZzasDQ4kKrFdJVk7dJgz77jF/e8udvGqnnTgnQXlqLMpKne/veL3gRdi3TJxxTv2vqXtX7IZfWGJecQ==} + '@mui/x-data-grid@8.5.0': + resolution: {integrity: sha512-5rrMm9anFaLk9O5XRIw3J9tAAnaiE1GxFeocyqhDj23RUReMg0YSp3FYnCaFLAehRQVgT9pC4675XO571paxKw==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.9.0 @@ -1143,10 +1143,11 @@ packages: '@emotion/styled': optional: true - '@mui/x-internals@8.3.1': - resolution: {integrity: sha512-8kIxT66cea63iEseEIHSWzKju2Wzl7MsWFoAUQEyRvYqOFa2j9Un2Vn/EH2vy9nm/MtMAYpwOE/nt68/KTIA2w==} + '@mui/x-internals@8.5.0': + resolution: {integrity: sha512-Ef4KJij1pBGk6/xILyVZHf76tcuRpJIX30k4Ghklsd5QJujZ9ENCGAjvd7aWRAFAs5p3ffn0H8UDESoIcroj1Q==} engines: {node: '>=14.0.0'} peerDependencies: + '@mui/system': ^5.15.14 || ^6.0.0 || ^7.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 '@octokit/auth-token@4.0.0': @@ -1283,9 +1284,16 @@ packages: resolution: {integrity: sha512-f+pL/s2DiT+2dxwheSoJT0P/KJy/s0klzE+ZqRdXHlkeyFk/DpKtyjLZIiA79kx56g3oEPA8Zu9EzEKzAwuvhw==} engines: {node: '>=20'} + '@pkgr/core@0.2.7': + resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + '@rolldown/pluginutils@1.0.0-beta.9': + resolution: {integrity: sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==} + '@rollup/pluginutils@5.1.4': resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} engines: {node: '>=14.0.0'} @@ -1466,82 +1474,88 @@ packages: '@tauri-apps/api@2.5.0': resolution: {integrity: sha512-Ldux4ip+HGAcPUmuLT8EIkk6yafl5vK0P0c0byzAKzxJh7vxelVtdPONjfgTm96PbN24yjZNESY8CKo8qniluA==} - '@tauri-apps/cli-darwin-arm64@2.2.7': - resolution: {integrity: sha512-54kcpxZ3X1Rq+pPTzk3iIcjEVY4yv493uRx/80rLoAA95vAC0c//31Whz75UVddDjJfZvXlXZ3uSZ+bnCOnt0A==} + '@tauri-apps/cli-darwin-arm64@2.5.0': + resolution: {integrity: sha512-VuVAeTFq86dfpoBDNYAdtQVLbP0+2EKCHIIhkaxjeoPARR0sLpFHz2zs0PcFU76e+KAaxtEtAJAXGNUc8E1PzQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tauri-apps/cli-darwin-x64@2.2.7': - resolution: {integrity: sha512-Vgu2XtBWemLnarB+6LqQeLanDlRj7CeFN//H8bVVdjbNzxcSxsvbLYMBP8+3boa7eBnjDrqMImRySSgL6IrwTw==} + '@tauri-apps/cli-darwin-x64@2.5.0': + resolution: {integrity: sha512-hUF01sC06cZVa8+I0/VtsHOk9BbO75rd+YdtHJ48xTdcYaQ5QIwL4yZz9OR1AKBTaUYhBam8UX9Pvd5V2/4Dpw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tauri-apps/cli-linux-arm-gnueabihf@2.2.7': - resolution: {integrity: sha512-+Clha2iQAiK9zoY/KKW0KLHkR0k36O78YLx5Sl98tWkwI3OBZFg5H5WT1plH/4sbZIS2aLFN6dw58/JlY9Bu/g==} + '@tauri-apps/cli-linux-arm-gnueabihf@2.5.0': + resolution: {integrity: sha512-LQKqttsK252LlqYyX8R02MinUsfFcy3+NZiJwHFgi5Y3+ZUIAED9cSxJkyNtuY5KMnR4RlpgWyLv4P6akN1xhg==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tauri-apps/cli-linux-arm64-gnu@2.2.7': - resolution: {integrity: sha512-Z/Lp4SQe6BUEOays9BQAEum2pvZF4w9igyXijP+WbkOejZx4cDvarFJ5qXrqSLmBh7vxrdZcLwoLk9U//+yQrg==} + '@tauri-apps/cli-linux-arm64-gnu@2.5.0': + resolution: {integrity: sha512-mTQufsPcpdHg5RW0zypazMo4L55EfeE5snTzrPqbLX4yCK2qalN7+rnP8O8GT06xhp6ElSP/Ku1M2MR297SByQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tauri-apps/cli-linux-arm64-musl@2.2.7': - resolution: {integrity: sha512-+8HZ+txff/Y3YjAh80XcLXcX8kpGXVdr1P8AfjLHxHdS6QD4Md+acSxGTTNbplmHuBaSHJvuTvZf9tU1eDCTDg==} + '@tauri-apps/cli-linux-arm64-musl@2.5.0': + resolution: {integrity: sha512-rQO1HhRUQqyEaal5dUVOQruTRda/TD36s9kv1hTxZiFuSq3558lsTjAcUEnMAtBcBkps20sbyTJNMT0AwYIk8Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tauri-apps/cli-linux-x64-gnu@2.2.7': - resolution: {integrity: sha512-ahlSnuCnUntblp9dG7/w5ZWZOdzRFi3zl0oScgt7GF4KNAOEa7duADsxPA4/FT2hLRa0SvpqtD4IYFvCxoVv3Q==} + '@tauri-apps/cli-linux-riscv64-gnu@2.5.0': + resolution: {integrity: sha512-7oS18FN46yDxyw1zX/AxhLAd7T3GrLj3Ai6s8hZKd9qFVzrAn36ESL7d3G05s8wEtsJf26qjXnVF4qleS3dYsA==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + + '@tauri-apps/cli-linux-x64-gnu@2.5.0': + resolution: {integrity: sha512-SG5sFNL7VMmDBdIg3nO3EzNRT306HsiEQ0N90ILe3ZABYAVoPDO/ttpCO37ApLInTzrq/DLN+gOlC/mgZvLw1w==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tauri-apps/cli-linux-x64-musl@2.2.7': - resolution: {integrity: sha512-+qKAWnJRSX+pjjRbKAQgTdFY8ecdcu8UdJ69i7wn3ZcRn2nMMzOO2LOMOTQV42B7/Q64D1pIpmZj9yblTMvadA==} + '@tauri-apps/cli-linux-x64-musl@2.5.0': + resolution: {integrity: sha512-QXDM8zp/6v05PNWju5ELsVwF0VH1n6b5pk2E6W/jFbbiwz80Vs1lACl9pv5kEHkrxBj+aWU/03JzGuIj2g3SkQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tauri-apps/cli-win32-arm64-msvc@2.2.7': - resolution: {integrity: sha512-aa86nRnrwT04u9D9fhf5JVssuAZlUCCc8AjqQjqODQjMd4BMA2+d4K9qBMpEG/1kVh95vZaNsLogjEaqSTTw4A==} + '@tauri-apps/cli-win32-arm64-msvc@2.5.0': + resolution: {integrity: sha512-pFSHFK6b+o9y4Un8w0gGLwVyFTZaC3P0kQ7umRt/BLDkzD5RnQ4vBM7CF8BCU5nkwmEBUCZd7Wt3TWZxe41o6Q==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tauri-apps/cli-win32-ia32-msvc@2.2.7': - resolution: {integrity: sha512-EiJ5/25tLSQOSGvv+t6o3ZBfOTKB5S3vb+hHQuKbfmKdRF0XQu2YPdIi1CQw1DU97ZAE0Dq4frvnyYEKWgMzVQ==} + '@tauri-apps/cli-win32-ia32-msvc@2.5.0': + resolution: {integrity: sha512-EArv1IaRlogdLAQyGlKmEqZqm5RfHCUMhJoedWu7GtdbOMUfSAz6FMX2boE1PtEmNO4An+g188flLeVErrxEKg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@tauri-apps/cli-win32-x64-msvc@2.2.7': - resolution: {integrity: sha512-ZB8Kw90j8Ld+9tCWyD2fWCYfIrzbQohJ4DJSidNwbnehlZzP7wAz6Z3xjsvUdKtQ3ibtfoeTqVInzCCEpI+pWg==} + '@tauri-apps/cli-win32-x64-msvc@2.5.0': + resolution: {integrity: sha512-lj43EFYbnAta8pd9JnUq87o+xRUR0odz+4rixBtTUwUgdRdwQ2V9CzFtsMu6FQKpFQ6mujRK6P1IEwhL6ADRsQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tauri-apps/cli@2.2.7': - resolution: {integrity: sha512-ZnsS2B4BplwXP37celanNANiIy8TCYhvg5RT09n72uR/o+navFZtGpFSqljV8fy1Y4ixIPds8FrGSXJCN2BerA==} + '@tauri-apps/cli@2.5.0': + resolution: {integrity: sha512-rAtHqG0Gh/IWLjN2zTf3nZqYqbo81oMbqop56rGTjrlWk9pTTAjkqOjSL9XQLIMZ3RbeVjveCqqCA0s8RnLdMg==} engines: {node: '>= 10'} hasBin: true '@tauri-apps/plugin-clipboard-manager@2.2.2': resolution: {integrity: sha512-bZvDLMqfcNmsw7Ag8I49jlaCjdpDvvlJHnpp6P+Gg/3xtpSERdwlDxm7cKGbs2mj46dsw4AuG3RoAgcpwgioUA==} - '@tauri-apps/plugin-dialog@2.2.1': - resolution: {integrity: sha512-wZmCouo4PgTosh/UoejPw9DPs6RllS5Pp3fuOV2JobCu36mR5AXU2MzU9NZiVaFi/5Zfc8RN0IhcZHnksJ1o8A==} + '@tauri-apps/plugin-dialog@2.2.2': + resolution: {integrity: sha512-Pm9qnXQq8ZVhAMFSEPwxvh+nWb2mk7LASVlNEHYaksHvcz8P6+ElR5U5dNL9Ofrm+uwhh1/gYKWswK8JJJAh6A==} - '@tauri-apps/plugin-fs@2.2.1': - resolution: {integrity: sha512-KdGzvvA4Eg0Dhw55MwczFbjxLxsTx0FvwwC/0StXlr6IxwPUxh5ziZQoaugkBFs8t+wfebdQrjBEzd8NmmDXNw==} + '@tauri-apps/plugin-fs@2.3.0': + resolution: {integrity: sha512-G9gEyYVUaaxhdRJBgQTTLmzAe0vtHYxYyN1oTQzU3zwvb8T+tVLcAqCdFMWHq0qGeGbmynI5whvYpcXo5LvZ1w==} - '@tauri-apps/plugin-global-shortcut@2.2.0': - resolution: {integrity: sha512-clI9Bg/BcxWXNDK+ij601o1qC2WxMEy8ovhGgEW5Ai17oPy0KK8uwzmc59KiVnOYKpBWHCUPqBxG+KBNUFXgzw==} + '@tauri-apps/plugin-global-shortcut@2.2.1': + resolution: {integrity: sha512-b64/TI1t5LIi2JY4OWlYjZpPRq60T5GVVL/no27sUuxaNUZY8dVtwsMtDUgxUpln2yR+P2PJsYlqY5V8sLSxEw==} '@tauri-apps/plugin-notification@2.2.2': resolution: {integrity: sha512-d71rJdtkFUTcG4dqydnv6d7ZwlNZVcdjrVOPwc9GsF6y9DgVN1WCZ9T/vbfD2qrJslf7ai+rnNJc62TLLC2IdA==} @@ -1615,8 +1629,8 @@ packages: '@types/prop-types@15.7.14': resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} - '@types/react-dom@19.1.5': - resolution: {integrity: sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==} + '@types/react-dom@19.1.6': + resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} peerDependencies: '@types/react': ^19.0.0 @@ -1625,8 +1639,8 @@ packages: peerDependencies: '@types/react': '*' - '@types/react@19.1.4': - resolution: {integrity: sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==} + '@types/react@19.1.6': + resolution: {integrity: sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==} '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -1644,8 +1658,8 @@ packages: terser: ^5.16.0 vite: ^6.0.0 - '@vitejs/plugin-react@4.4.1': - resolution: {integrity: sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==} + '@vitejs/plugin-react@4.5.1': + resolution: {integrity: sha512-uPZBqSI0YD4lpkIru6M35sIfylLGTyhGHvDZbNLuMA73lMlwJKz5xweH7FajfcCAc2HnINciejA9qTz0dr0M7A==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 @@ -1663,11 +1677,11 @@ packages: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} - ahooks@3.8.4: - resolution: {integrity: sha512-39wDEw2ZHvypaT14EpMMk4AzosHWt0z9bulY0BeDsvc9PqJEV+Kjh/4TZfftSsotBMq52iYIOFPd3PR56e0ZJg==} + ahooks@3.8.5: + resolution: {integrity: sha512-Y+MLoJpBXVdjsnnBjE5rOSPkQ4DK+8i5aPDzLJdIOsCpo/fiAeXcBY1Y7oWgtOK0TpOz0gFa/XcyO1UGdoqLcw==} engines: {node: '>=8.0.0'} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -1811,10 +1825,6 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - commander@13.1.0: - resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} - engines: {node: '>=18'} - commander@14.0.0: resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} engines: {node: '>=20'} @@ -2027,10 +2037,6 @@ packages: find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -2129,16 +2135,16 @@ packages: engines: {node: '>=18'} hasBin: true - i18next@25.1.2: - resolution: {integrity: sha512-SP63m8LzdjkrAjruH7SCI3ndPSgjt4/wX7ouUUOzCW/eY+HzlIo19IQSfYA9X3qRiRP1SYtaTsg/Oz/PGsfD8w==} + i18next@25.2.1: + resolution: {integrity: sha512-+UoXK5wh+VlE1Zy5p6MjcvctHXAhRwQKCxiJD8noKZzIXmnAX8gdHX5fLPA3MEVxEN4vbZkQFy8N0LyD9tUqPw==} peerDependencies: typescript: ^5 peerDependenciesMeta: typescript: optional: true - ignore@7.0.4: - resolution: {integrity: sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} immutable@5.1.2: @@ -2241,10 +2247,6 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} @@ -2313,8 +2315,8 @@ packages: resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} engines: {node: '>=18'} - meta-json-schema@1.19.5: - resolution: {integrity: sha512-hjI5avhH265Ef8l2szO+XjxmjSaJSP501wdKFxxz11lYXTWbnMASoYx39Adm0/1B76VEKgBIAguDKawsq8Q9Uw==} + meta-json-schema@1.19.10: + resolution: {integrity: sha512-eLj5v4hlnqeHacRXDiE+/dFR2Ly0MQKCMXqRNZzbwyPXu0QPMkFu9+mYlZDHZErUJlXKM2RLbnkfVoHvxcm3DA==} engines: {node: '>=18', pnpm: '>=9'} micromark-core-commonmark@2.0.3: @@ -2476,14 +2478,6 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -2501,10 +2495,6 @@ packages: path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2520,8 +2510,8 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - peggy@5.0.2: - resolution: {integrity: sha512-s7cQVFZ845bskMM60L3pjWv/6QkC0dZeWd/qrj9g7vvjjS/gkHLTA4Bzs6dxIBezDPdD+WUjoEKgiH7OJA3JAw==} + peggy@5.0.3: + resolution: {integrity: sha512-QErYmLjj/ehiNNJRqx2qb36hzkanuascpMqREs2RQqaXhU3cflIRScP/u2BoobIfu/FaeI3GGxNB/vFX/Ar9lg==} engines: {node: '>=20'} hasBin: true @@ -2545,8 +2535,8 @@ packages: engines: {node: '>=14'} hasBin: true - pretty-quick@4.1.1: - resolution: {integrity: sha512-9Ud0l/CspNTmyIdYac9X7Inb3o8fuUsw+1zJFvCGn+at0t1UwUcUdo2RSZ41gcmfLv1fxgWQxWEfItR7CBwugg==} + pretty-quick@4.2.2: + resolution: {integrity: sha512-uAh96tBW1SsD34VhhDmWuEmqbpfYc/B3j++5MC/6b3Cb8Ow7NJsvKFhg0eoGu2xXX+o9RkahkTK6sUdd8E7g5w==} engines: {node: '>=14'} hasBin: true peerDependencies: @@ -2580,14 +2570,14 @@ packages: react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} - react-hook-form@7.56.3: - resolution: {integrity: sha512-IK18V6GVbab4TAo1/cz3kqajxbDPGofdF0w7VHdCo0Nt8PrPlOZcuuDq9YYIV1BtjcX78x0XsldbQRQnQXWXmw==} + react-hook-form@7.57.0: + resolution: {integrity: sha512-RbEks3+cbvTP84l/VXGUZ+JMrKOS8ykQCRYdm5aYsxnDquL0vspsyNhGRO7pcH6hsZqWlPOjLye7rJqdtdAmlg==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-i18next@15.5.1: - resolution: {integrity: sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA==} + react-i18next@15.5.2: + resolution: {integrity: sha512-ePODyXgmZQAOYTbZXQn5rRsSBu3Gszo69jxW6aKmlSgxKAI1fOhDwSu6bT4EKHciWPKQ7v7lPrjeiadR6Gi+1A==} peerDependencies: i18next: '>= 23.2.3' react: '>= 16.8.0' @@ -2625,15 +2615,15 @@ packages: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} - react-router-dom@7.6.0: - resolution: {integrity: sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==} + react-router-dom@7.6.2: + resolution: {integrity: sha512-Q8zb6VlTbdYKK5JJBLQEN06oTUa/RAbG/oQS1auK1I0TbJOXktqm+QENEVJU6QvWynlXPRBXI3fiOQcSEA78rA==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' react-dom: '>=18' - react-router@7.6.0: - resolution: {integrity: sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==} + react-router@7.6.2: + resolution: {integrity: sha512-U7Nv3y+bMimgWjhlT5CRdzHPu2/KVmqPwKUCChW8en5P3znxUqwlYFlbmyj8Rgp1SF6zs5X4+77kBVknkg6a0w==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' @@ -2648,8 +2638,8 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' - react-virtuoso@4.12.7: - resolution: {integrity: sha512-njJp764he6Fi1p89PUW0k2kbyWu9w/y+MwdxmwK2kvdwwzVDbz2c2wMj5xdSruBFVgFTsI7Z85hxZR7aSHBrbQ==} + react-virtuoso@4.12.8: + resolution: {integrity: sha512-NMMKfDBr/+xZZqCQF3tN1SZsh6FwOJkYgThlfnsPLkaEhdyQo0EuWUzu3ix6qjnI7rYwJhMwRGoJBi+aiDfGsA==} peerDependencies: react: '>=16 || >=17 || >= 18 || >= 19' react-dom: '>=16 || >=17 || >= 18 || >=19' @@ -2709,8 +2699,8 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - sass@1.88.0: - resolution: {integrity: sha512-sF6TWQqjFvr4JILXzG4ucGOLELkESHL+I5QJhh7CNaE+Yge0SI+ehCatsXhJ7ymU1hAFcIS3/PBpjdIbXoyVbg==} + sass@1.89.1: + resolution: {integrity: sha512-eMLLkl+qz7tx/0cJ9wI+w09GQ2zodTkcE/aVfywwdlRcI3EO19xGnbmJwg/JMIm+5MxVJ6outddLZ4Von4E++Q==} engines: {node: '>=14.0.0'} hasBin: true @@ -2823,8 +2813,8 @@ packages: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} - terser@5.39.1: - resolution: {integrity: sha512-Mm6+uad0ZuDtcV8/4uOZQDQ8RuiC5Pu+iZRedJtF7yA/27sPL7d++In/AJKpWZlU3SYMPPkVfwetn6sgZ66pUA==} + terser@5.40.0: + resolution: {integrity: sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA==} engines: {node: '>=10'} hasBin: true @@ -3031,12 +3021,8 @@ packages: engines: {node: '>= 14'} hasBin: true - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - - zustand@5.0.4: - resolution: {integrity: sha512-39VFTN5InDtMd28ZhjLyuTnlytDr9HfwO512Ai4I8ZABCoyAj4F1+sr7sD1jP/+p7k77Iko0Pb5NhgBFDCX0kQ==} + zustand@5.0.5: + resolution: {integrity: sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==} engines: {node: '>=12.20.0'} peerDependencies: '@types/react': '>=18.0.0' @@ -3782,7 +3768,7 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0)': + '@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0)': dependencies: '@babel/runtime': 7.27.1 '@emotion/babel-plugin': 11.13.5 @@ -3794,7 +3780,7 @@ snapshots: hoist-non-react-statics: 3.3.2 react: 19.1.0 optionalDependencies: - '@types/react': 19.1.4 + '@types/react': 19.1.6 transitivePeerDependencies: - supports-color @@ -3808,18 +3794,18 @@ snapshots: '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(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)': dependencies: '@babel/runtime': 7.27.1 '@emotion/babel-plugin': 11.13.5 '@emotion/is-prop-valid': 1.3.1 - '@emotion/react': 11.14.0(@types/react@19.1.4)(react@19.1.0) + '@emotion/react': 11.14.0(@types/react@19.1.6)(react@19.1.0) '@emotion/serialize': 1.3.3 '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.1.0) '@emotion/utils': 1.4.2 react: 19.1.0 optionalDependencies: - '@types/react': 19.1.4 + '@types/react': 19.1.6 transitivePeerDependencies: - supports-color @@ -3949,41 +3935,41 @@ snapshots: '@kurkle/color@0.3.4': {} - '@mui/core-downloads-tracker@7.1.0': {} + '@mui/core-downloads-tracker@7.1.1': {} - '@mui/icons-material@7.1.0(@mui/material@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.4)(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)': dependencies: '@babel/runtime': 7.27.1 - '@mui/material': 7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(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) react: 19.1.0 optionalDependencies: - '@types/react': 19.1.4 + '@types/react': 19.1.6 - '@mui/lab@7.0.0-beta.12(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@mui/material@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@mui/lab@7.0.0-beta.13(@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))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@babel/runtime': 7.27.1 - '@mui/material': 7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@mui/system': 7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) - '@mui/types': 7.4.2(@types/react@19.1.4) - '@mui/utils': 7.1.0(@types/react@19.1.4)(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) + '@mui/types': 7.4.3(@types/react@19.1.6) + '@mui/utils': 7.1.1(@types/react@19.1.6)(react@19.1.0) clsx: 2.1.1 prop-types: 15.8.1 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.1.4)(react@19.1.0) - '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) - '@types/react': 19.1.4 + '@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 - '@mui/material@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(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)': dependencies: '@babel/runtime': 7.27.1 - '@mui/core-downloads-tracker': 7.1.0 - '@mui/system': 7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) - '@mui/types': 7.4.2(@types/react@19.1.4) - '@mui/utils': 7.1.0(@types/react@19.1.4)(react@19.1.0) + '@mui/core-downloads-tracker': 7.1.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) + '@mui/types': 7.4.3(@types/react@19.1.6) + '@mui/utils': 7.1.1(@types/react@19.1.6)(react@19.1.0) '@popperjs/core': 2.11.8 - '@types/react-transition-group': 4.4.12(@types/react@19.1.4) + '@types/react-transition-group': 4.4.12(@types/react@19.1.6) clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 @@ -3992,20 +3978,20 @@ snapshots: react-is: 19.1.0 react-transition-group: 4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.1.4)(react@19.1.0) - '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) - '@types/react': 19.1.4 + '@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 - '@mui/private-theming@7.1.0(@types/react@19.1.4)(react@19.1.0)': + '@mui/private-theming@7.1.1(@types/react@19.1.6)(react@19.1.0)': dependencies: '@babel/runtime': 7.27.1 - '@mui/utils': 7.1.0(@types/react@19.1.4)(react@19.1.0) + '@mui/utils': 7.1.1(@types/react@19.1.6)(react@19.1.0) prop-types: 15.8.1 react: 19.1.0 optionalDependencies: - '@types/react': 19.1.4 + '@types/react': 19.1.6 - '@mui/styled-engine@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(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)': dependencies: '@babel/runtime': 7.27.1 '@emotion/cache': 11.14.0 @@ -4015,50 +4001,50 @@ snapshots: prop-types: 15.8.1 react: 19.1.0 optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.1.4)(react@19.1.0) - '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) + '@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/system@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(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)': dependencies: '@babel/runtime': 7.27.1 - '@mui/private-theming': 7.1.0(@types/react@19.1.4)(react@19.1.0) - '@mui/styled-engine': 7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(react@19.1.0) - '@mui/types': 7.4.2(@types/react@19.1.4) - '@mui/utils': 7.1.0(@types/react@19.1.4)(react@19.1.0) + '@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) + '@mui/utils': 7.1.1(@types/react@19.1.6)(react@19.1.0) clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 react: 19.1.0 optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.1.4)(react@19.1.0) - '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) - '@types/react': 19.1.4 + '@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 - '@mui/types@7.4.2(@types/react@19.1.4)': + '@mui/types@7.4.3(@types/react@19.1.6)': dependencies: '@babel/runtime': 7.27.1 optionalDependencies: - '@types/react': 19.1.4 + '@types/react': 19.1.6 - '@mui/utils@7.1.0(@types/react@19.1.4)(react@19.1.0)': + '@mui/utils@7.1.1(@types/react@19.1.6)(react@19.1.0)': dependencies: '@babel/runtime': 7.27.1 - '@mui/types': 7.4.2(@types/react@19.1.4) + '@mui/types': 7.4.3(@types/react@19.1.6) '@types/prop-types': 15.7.14 clsx: 2.1.1 prop-types: 15.8.1 react: 19.1.0 react-is: 19.1.0 optionalDependencies: - '@types/react': 19.1.4 + '@types/react': 19.1.6 - '@mui/x-data-grid@8.3.1(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@mui/material@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@mui/x-data-grid@8.5.0(@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)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@babel/runtime': 7.27.1 - '@mui/material': 7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@mui/system': 7.1.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) - '@mui/utils': 7.1.0(@types/react@19.1.4)(react@19.1.0) - '@mui/x-internals': 8.3.1(@types/react@19.1.4)(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) + '@mui/utils': 7.1.1(@types/react@19.1.6)(react@19.1.0) + '@mui/x-internals': 8.5.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)(react@19.1.0) clsx: 2.1.1 prop-types: 15.8.1 react: 19.1.0 @@ -4066,15 +4052,16 @@ snapshots: reselect: 5.1.1 use-sync-external-store: 1.5.0(react@19.1.0) optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.1.4)(react@19.1.0) - '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.4)(react@19.1.0))(@types/react@19.1.4)(react@19.1.0) + '@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) transitivePeerDependencies: - '@types/react' - '@mui/x-internals@8.3.1(@types/react@19.1.4)(react@19.1.0)': + '@mui/x-internals@8.5.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)(react@19.1.0)': dependencies: '@babel/runtime': 7.27.1 - '@mui/utils': 7.1.0(@types/react@19.1.4)(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) react: 19.1.0 transitivePeerDependencies: - '@types/react' @@ -4202,8 +4189,12 @@ snapshots: dependencies: semver: 7.7.1 + '@pkgr/core@0.2.7': {} + '@popperjs/core@2.11.8': {} + '@rolldown/pluginutils@1.0.0-beta.9': {} + '@rollup/pluginutils@5.1.4(rollup@4.40.2)': dependencies: '@types/estree': 1.0.7 @@ -4344,62 +4335,66 @@ snapshots: '@tauri-apps/api@2.5.0': {} - '@tauri-apps/cli-darwin-arm64@2.2.7': + '@tauri-apps/cli-darwin-arm64@2.5.0': optional: true - '@tauri-apps/cli-darwin-x64@2.2.7': + '@tauri-apps/cli-darwin-x64@2.5.0': optional: true - '@tauri-apps/cli-linux-arm-gnueabihf@2.2.7': + '@tauri-apps/cli-linux-arm-gnueabihf@2.5.0': optional: true - '@tauri-apps/cli-linux-arm64-gnu@2.2.7': + '@tauri-apps/cli-linux-arm64-gnu@2.5.0': optional: true - '@tauri-apps/cli-linux-arm64-musl@2.2.7': + '@tauri-apps/cli-linux-arm64-musl@2.5.0': optional: true - '@tauri-apps/cli-linux-x64-gnu@2.2.7': + '@tauri-apps/cli-linux-riscv64-gnu@2.5.0': optional: true - '@tauri-apps/cli-linux-x64-musl@2.2.7': + '@tauri-apps/cli-linux-x64-gnu@2.5.0': optional: true - '@tauri-apps/cli-win32-arm64-msvc@2.2.7': + '@tauri-apps/cli-linux-x64-musl@2.5.0': optional: true - '@tauri-apps/cli-win32-ia32-msvc@2.2.7': + '@tauri-apps/cli-win32-arm64-msvc@2.5.0': optional: true - '@tauri-apps/cli-win32-x64-msvc@2.2.7': + '@tauri-apps/cli-win32-ia32-msvc@2.5.0': optional: true - '@tauri-apps/cli@2.2.7': + '@tauri-apps/cli-win32-x64-msvc@2.5.0': + optional: true + + '@tauri-apps/cli@2.5.0': optionalDependencies: - '@tauri-apps/cli-darwin-arm64': 2.2.7 - '@tauri-apps/cli-darwin-x64': 2.2.7 - '@tauri-apps/cli-linux-arm-gnueabihf': 2.2.7 - '@tauri-apps/cli-linux-arm64-gnu': 2.2.7 - '@tauri-apps/cli-linux-arm64-musl': 2.2.7 - '@tauri-apps/cli-linux-x64-gnu': 2.2.7 - '@tauri-apps/cli-linux-x64-musl': 2.2.7 - '@tauri-apps/cli-win32-arm64-msvc': 2.2.7 - '@tauri-apps/cli-win32-ia32-msvc': 2.2.7 - '@tauri-apps/cli-win32-x64-msvc': 2.2.7 + '@tauri-apps/cli-darwin-arm64': 2.5.0 + '@tauri-apps/cli-darwin-x64': 2.5.0 + '@tauri-apps/cli-linux-arm-gnueabihf': 2.5.0 + '@tauri-apps/cli-linux-arm64-gnu': 2.5.0 + '@tauri-apps/cli-linux-arm64-musl': 2.5.0 + '@tauri-apps/cli-linux-riscv64-gnu': 2.5.0 + '@tauri-apps/cli-linux-x64-gnu': 2.5.0 + '@tauri-apps/cli-linux-x64-musl': 2.5.0 + '@tauri-apps/cli-win32-arm64-msvc': 2.5.0 + '@tauri-apps/cli-win32-ia32-msvc': 2.5.0 + '@tauri-apps/cli-win32-x64-msvc': 2.5.0 '@tauri-apps/plugin-clipboard-manager@2.2.2': dependencies: '@tauri-apps/api': 2.5.0 - '@tauri-apps/plugin-dialog@2.2.1': + '@tauri-apps/plugin-dialog@2.2.2': dependencies: '@tauri-apps/api': 2.5.0 - '@tauri-apps/plugin-fs@2.2.1': + '@tauri-apps/plugin-fs@2.3.0': dependencies: '@tauri-apps/api': 2.5.0 - '@tauri-apps/plugin-global-shortcut@2.2.0': + '@tauri-apps/plugin-global-shortcut@2.2.1': dependencies: '@tauri-apps/api': 2.5.0 @@ -4486,15 +4481,15 @@ snapshots: '@types/prop-types@15.7.14': {} - '@types/react-dom@19.1.5(@types/react@19.1.4)': + '@types/react-dom@19.1.6(@types/react@19.1.6)': dependencies: - '@types/react': 19.1.4 + '@types/react': 19.1.6 - '@types/react-transition-group@4.4.12(@types/react@19.1.4)': + '@types/react-transition-group@4.4.12(@types/react@19.1.6)': dependencies: - '@types/react': 19.1.4 + '@types/react': 19.1.6 - '@types/react@19.1.4': + '@types/react@19.1.6': dependencies: csstype: 3.1.3 @@ -4504,7 +4499,7 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitejs/plugin-legacy@6.1.1(terser@5.39.1)(vite@6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1))': + '@vitejs/plugin-legacy@6.1.1(terser@5.40.0)(vite@6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1))': dependencies: '@babel/core': 7.27.1 '@babel/preset-env': 7.27.2(@babel/core@7.27.1) @@ -4514,19 +4509,20 @@ snapshots: magic-string: 0.30.17 regenerator-runtime: 0.14.1 systemjs: 6.15.1 - terser: 5.39.1 - vite: 6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1) + terser: 5.40.0 + vite: 6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@4.4.1(vite@6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1))': + '@vitejs/plugin-react@4.5.1(vite@6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1))': dependencies: '@babel/core': 7.27.1 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.1) '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.1) + '@rolldown/pluginutils': 1.0.0-beta.9 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1) + vite: 6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1) transitivePeerDependencies: - supports-color @@ -4536,7 +4532,7 @@ snapshots: agent-base@7.1.3: {} - ahooks@3.8.4(react@19.1.0): + ahooks@3.8.5(react@19.1.0): dependencies: '@babel/runtime': 7.27.1 dayjs: 1.11.13 @@ -4685,8 +4681,6 @@ snapshots: comma-separated-tokens@2.0.3: {} - commander@13.1.0: {} - commander@14.0.0: {} commander@2.20.3: {} @@ -4910,11 +4904,6 @@ snapshots: find-root@1.1.0: {} - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - follow-redirects@1.15.9: {} foreground-child@3.3.1: @@ -5031,13 +5020,13 @@ snapshots: husky@9.1.7: {} - i18next@25.1.2(typescript@5.8.3): + i18next@25.2.1(typescript@5.8.3): dependencies: '@babel/runtime': 7.27.1 optionalDependencies: typescript: 5.8.3 - ignore@7.0.4: {} + ignore@7.0.5: {} immutable@5.1.2: {} @@ -5112,10 +5101,6 @@ snapshots: lines-and-columns@1.2.4: {} - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - lodash-es@4.17.21: {} lodash.debounce@4.0.8: {} @@ -5250,7 +5235,7 @@ snapshots: meow@13.2.0: {} - meta-json-schema@1.19.5: {} + meta-json-schema@1.19.10: {} micromark-core-commonmark@2.0.3: dependencies: @@ -5476,14 +5461,6 @@ snapshots: dependencies: wrappy: 1.0.2 - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - package-json-from-dist@1.0.1: {} parent-module@1.0.1: @@ -5509,8 +5486,6 @@ snapshots: path-browserify@1.0.1: {} - path-exists@4.0.0: {} - path-key@3.1.1: {} path-parse@1.0.7: {} @@ -5522,10 +5497,10 @@ snapshots: path-type@4.0.0: {} - peggy@5.0.2: + peggy@5.0.3: dependencies: '@peggyjs/from-mem': 2.0.0 - commander: 13.1.0 + commander: 14.0.0 source-map-generator: 2.0.0 picocolors@1.1.1: {} @@ -5543,10 +5518,10 @@ snapshots: prettier@3.5.3: {} - pretty-quick@4.1.1(prettier@3.5.3): + pretty-quick@4.2.2(prettier@3.5.3): dependencies: - find-up: 5.0.0 - ignore: 7.0.4 + '@pkgr/core': 0.2.7 + ignore: 7.0.5 mri: 1.2.0 picocolors: 1.1.1 picomatch: 4.0.2 @@ -5581,15 +5556,15 @@ snapshots: react-fast-compare@3.2.2: {} - react-hook-form@7.56.3(react@19.1.0): + react-hook-form@7.57.0(react@19.1.0): dependencies: react: 19.1.0 - react-i18next@15.5.1(i18next@25.1.2(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3): + react-i18next@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): dependencies: '@babel/runtime': 7.27.1 html-parse-stringify: 3.0.1 - i18next: 25.1.2(typescript@5.8.3) + i18next: 25.2.1(typescript@5.8.3) react: 19.1.0 optionalDependencies: react-dom: 19.1.0(react@19.1.0) @@ -5599,11 +5574,11 @@ snapshots: react-is@19.1.0: {} - react-markdown@10.1.0(@types/react@19.1.4)(react@19.1.0): + react-markdown@10.1.0(@types/react@19.1.6)(react@19.1.0): dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@types/react': 19.1.4 + '@types/react': 19.1.6 devlop: 1.1.0 hast-util-to-jsx-runtime: 2.3.6 html-url-attributes: 3.0.1 @@ -5625,13 +5600,13 @@ snapshots: react-refresh@0.17.0: {} - react-router-dom@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + react-router-dom@7.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - react-router: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react-router: 7.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + react-router@7.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: cookie: 1.0.2 react: 19.1.0 @@ -5648,7 +5623,7 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - react-virtuoso@4.12.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + react-virtuoso@4.12.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -5735,7 +5710,7 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.40.2 fsevents: 2.3.3 - sass@1.88.0: + sass@1.89.1: dependencies: chokidar: 4.0.3 immutable: 5.1.2 @@ -5841,7 +5816,7 @@ snapshots: mkdirp: 3.0.1 yallist: 5.0.0 - terser@5.39.1: + terser@5.40.0: dependencies: '@jridgewell/source-map': 0.3.6 acorn: 8.14.1 @@ -5953,18 +5928,18 @@ snapshots: dependencies: monaco-editor: 0.52.2 - vite-plugin-svgr@4.3.0(rollup@4.40.2)(typescript@5.8.3)(vite@6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1)): + vite-plugin-svgr@4.3.0(rollup@4.40.2)(typescript@5.8.3)(vite@6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1)): dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.40.2) '@svgr/core': 8.1.0(typescript@5.8.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.8.3)) - vite: 6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1) + vite: 6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1) transitivePeerDependencies: - rollup - supports-color - typescript - vite@6.3.5(sass@1.88.0)(terser@5.39.1)(yaml@2.7.1): + vite@6.3.5(sass@1.89.1)(terser@5.40.0)(yaml@2.7.1): dependencies: esbuild: 0.25.4 fdir: 6.4.4(picomatch@4.0.2) @@ -5974,8 +5949,8 @@ snapshots: tinyglobby: 0.2.13 optionalDependencies: fsevents: 2.3.3 - sass: 1.88.0 - terser: 5.39.1 + sass: 1.89.1 + terser: 5.40.0 yaml: 2.7.1 void-elements@3.1.0: {} @@ -6021,11 +5996,9 @@ snapshots: yaml@2.7.1: {} - yocto-queue@0.1.0: {} - - zustand@5.0.4(@types/react@19.1.4)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)): + zustand@5.0.5(@types/react@19.1.6)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)): optionalDependencies: - '@types/react': 19.1.4 + '@types/react': 19.1.6 react: 19.1.0 use-sync-external-store: 1.5.0(react@19.1.0) diff --git a/clash-verge-rev/renovate.json b/clash-verge-rev/renovate.json new file mode 100644 index 0000000000..dfa93e8537 --- /dev/null +++ b/clash-verge-rev/renovate.json @@ -0,0 +1,42 @@ +{ + "extends": ["config:recommended"], + "baseBranches": ["dev"], + "enabledManagers": ["cargo", "npm"], + "labels": ["dependencies"], + "ignorePaths": [ + "**/node_modules/**", + "**/bower_components/**", + "**/vendor/**", + "**/__tests__/**", + "**/test/**", + "**/tests/**", + "**/__fixtures__/**", + "**/crate/**", + "shared/**" + ], + "rangeStrategy": "bump", + "packageRules": [ + { + "semanticCommitType": "chore", + "matchPackageNames": ["*"] + }, + { + "description": "Disable node/pnpm version updates", + "matchPackageNames": ["node", "pnpm"], + "matchDepTypes": ["engines", "packageManager"], + "enabled": false + }, + { + "description": "Group all cargo dependencies into a single PR", + "matchManagers": ["cargo"], + "groupName": "cargo dependencies" + }, + { + "description": "Group all npm dependencies into a single PR", + "matchManagers": ["npm"], + "groupName": "npm dependencies" + } + ], + "postUpdateOptions": ["pnpmDedupe"], + "ignoreDeps": ["serde_yaml"] +} diff --git a/clash-verge-rev/scripts/check-unused-i18n.js b/clash-verge-rev/scripts/check-unused-i18n.js index 381c6590bf..95958df4a1 100644 --- a/clash-verge-rev/scripts/check-unused-i18n.js +++ b/clash-verge-rev/scripts/check-unused-i18n.js @@ -1,21 +1,21 @@ -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const LOCALES_DIR = path.resolve(__dirname, '../src/locales'); +const LOCALES_DIR = path.resolve(__dirname, "../src/locales"); const SRC_DIRS = [ - path.resolve(__dirname, '../src'), - path.resolve(__dirname, '../src-tauri') + path.resolve(__dirname, "../src"), + path.resolve(__dirname, "../src-tauri"), ]; -const exts = ['.js', '.ts', '.tsx', '.jsx', '.vue', '.rs']; +const exts = [".js", ".ts", ".tsx", ".jsx", ".vue", ".rs"]; // 递归获取所有文件 function getAllFiles(dir, exts) { let files = []; - fs.readdirSync(dir).forEach(file => { + fs.readdirSync(dir).forEach((file) => { const full = path.join(dir, file); if (fs.statSync(full).isDirectory()) { files = files.concat(getAllFiles(full, exts)); @@ -28,21 +28,21 @@ function getAllFiles(dir, exts) { // 读取所有源码内容为一个大字符串 function getAllSourceContent() { - const files = SRC_DIRS.flatMap(dir => getAllFiles(dir, exts)); - return files.map(f => fs.readFileSync(f, 'utf8')).join('\n'); + const files = SRC_DIRS.flatMap((dir) => getAllFiles(dir, exts)); + return files.map((f) => fs.readFileSync(f, "utf8")).join("\n"); } // 白名单 key,不检查这些 key 是否被使用 const WHITELIST_KEYS = [ - 'theme.light', - 'theme.dark', - 'theme.system', - "Already Using Latest Core Version" + "theme.light", + "theme.dark", + "theme.system", + "Already Using Latest Core Version", ]; // 主流程 function processI18nFile(i18nPath, lang, allSource) { - const i18n = JSON.parse(fs.readFileSync(i18nPath, 'utf8')); + const i18n = JSON.parse(fs.readFileSync(i18nPath, "utf8")); const keys = Object.keys(i18n); const used = {}; @@ -50,7 +50,7 @@ function processI18nFile(i18nPath, lang, allSource) { let checked = 0; const total = keys.length; - keys.forEach(key => { + keys.forEach((key) => { if (WHITELIST_KEYS.includes(key)) { used[key] = i18n[key]; } else { @@ -65,8 +65,10 @@ function processI18nFile(i18nPath, lang, allSource) { checked++; if (checked % 20 === 0 || checked === total) { const percent = ((checked / total) * 100).toFixed(1); - process.stdout.write(`\r[${lang}] Progress: ${checked}/${total} (${percent}%)`); - if (checked === total) process.stdout.write('\n'); + process.stdout.write( + `\r[${lang}] Progress: ${checked}/${total} (${percent}%)`, + ); + if (checked === total) process.stdout.write("\n"); } }); @@ -74,25 +76,27 @@ function processI18nFile(i18nPath, lang, allSource) { console.log(`\n[${lang}] Unused keys:`, unused); // 备份原文件 - const oldPath = i18nPath + '.old'; + const oldPath = i18nPath + ".old"; fs.renameSync(i18nPath, oldPath); // 写入精简后的 i18n 文件(保留原文件名) - fs.writeFileSync(i18nPath, JSON.stringify(used, null, 2), 'utf8'); - console.log(`[${lang}] Cleaned i18n file written to src/locales/${path.basename(i18nPath)}`); + fs.writeFileSync(i18nPath, JSON.stringify(used, null, 2), "utf8"); + console.log( + `[${lang}] Cleaned i18n file written to src/locales/${path.basename(i18nPath)}`, + ); console.log(`[${lang}] Original file backed up as ${path.basename(oldPath)}`); } function main() { // 支持 zhtw.json、zh-tw.json、zh_CN.json 等 - const files = fs.readdirSync(LOCALES_DIR).filter(f => - /^[a-z0-9\-_]+\.json$/i.test(f) && !f.endsWith('.old') - ); + const files = fs + .readdirSync(LOCALES_DIR) + .filter((f) => /^[a-z0-9\-_]+\.json$/i.test(f) && !f.endsWith(".old")); const allSource = getAllSourceContent(); - files.forEach(file => { - const lang = path.basename(file, '.json'); + files.forEach((file) => { + const lang = path.basename(file, ".json"); processI18nFile(path.join(LOCALES_DIR, file), lang, allSource); }); } -main(); \ No newline at end of file +main(); diff --git a/clash-verge-rev/scripts/publish-version.mjs b/clash-verge-rev/scripts/publish-version.mjs index 617e38bf77..e5f4158fd8 100644 --- a/clash-verge-rev/scripts/publish-version.mjs +++ b/clash-verge-rev/scripts/publish-version.mjs @@ -29,7 +29,7 @@ const runRelease = () => // 2. 判断是否需要打 tag function isSemver(version) { - return /^v?\d+\.\d+\.\d+(-alpha)?$/.test(version); + return /^v?\d+\.\d+\.\d+(-[0-9A-Za-z-.]+)?$/.test(version); } async function run() { @@ -38,7 +38,9 @@ async function run() { let tag = null; if (versionArg === "alpha") { // 读取 package.json 里的主版本 - const pkg = await import(path.join(rootDir, "package.json"), { assert: { type: "json" } }); + const pkg = await import(path.join(rootDir, "package.json"), { + assert: { type: "json" }, + }); tag = `v${pkg.default.version}-alpha`; } else if (isSemver(versionArg)) { // 1.2.3 或 v1.2.3 @@ -61,4 +63,4 @@ async function run() { } } -run(); \ No newline at end of file +run(); diff --git a/clash-verge-rev/scripts/release-version.mjs b/clash-verge-rev/scripts/release-version.mjs index de463d2262..13314265ae 100644 --- a/clash-verge-rev/scripts/release-version.mjs +++ b/clash-verge-rev/scripts/release-version.mjs @@ -1,5 +1,3 @@ - - /** * CLI tool to update version numbers in package.json, src-tauri/Cargo.toml, and src-tauri/tauri.conf.json. * @@ -51,7 +49,9 @@ function generateShortTimestamp() { * @returns {boolean} */ function isValidVersion(version) { - return /^v?\d+\.\d+\.\d+(-(alpha|beta|rc)(\.\d+)?)?(\+[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*)?$/i.test(version); + return /^v?\d+\.\d+\.\d+(-(alpha|beta|rc)(\.\d+)?)?(\+[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*)?$/i.test( + version, + ); } /** @@ -69,8 +69,8 @@ function normalizeVersion(version) { * @returns {string} */ function getBaseVersion(version) { - let base = version.replace(/-(alpha|beta|rc)(\.\d+)?/i, ''); - base = base.replace(/\+[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*/g, ''); + let base = version.replace(/-(alpha|beta|rc)(\.\d+)?/i, ""); + base = base.replace(/\+[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*/g, ""); return base; } @@ -85,10 +85,21 @@ async function updatePackageVersion(newVersion) { const data = await fs.readFile(packageJsonPath, "utf8"); const packageJson = JSON.parse(data); - console.log("[INFO]: Current package.json version is: ", packageJson.version); - packageJson.version = newVersion.startsWith("v") ? newVersion.slice(1) : newVersion; - await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf8"); - console.log(`[INFO]: package.json version updated to: ${packageJson.version}`); + console.log( + "[INFO]: Current package.json version is: ", + packageJson.version, + ); + packageJson.version = newVersion.startsWith("v") + ? newVersion.slice(1) + : newVersion; + await fs.writeFile( + packageJsonPath, + JSON.stringify(packageJson, null, 2), + "utf8", + ); + console.log( + `[INFO]: package.json version updated to: ${packageJson.version}`, + ); } catch (error) { console.error("Error updating package.json version:", error); throw error; @@ -105,12 +116,17 @@ async function updateCargoVersion(newVersion) { try { const data = await fs.readFile(cargoTomlPath, "utf8"); const lines = data.split("\n"); - const versionWithoutV = newVersion.startsWith("v") ? newVersion.slice(1) : newVersion; + const versionWithoutV = newVersion.startsWith("v") + ? newVersion.slice(1) + : newVersion; const baseVersion = getBaseVersion(versionWithoutV); const updatedLines = lines.map((line) => { if (line.trim().startsWith("version =")) { - return line.replace(/version\s*=\s*"[^"]+"/, `version = "${baseVersion}"`); + return line.replace( + /version\s*=\s*"[^"]+"/, + `version = "${baseVersion}"`, + ); } return line; }); @@ -133,12 +149,21 @@ async function updateTauriConfigVersion(newVersion) { try { const data = await fs.readFile(tauriConfigPath, "utf8"); const tauriConfig = JSON.parse(data); - const versionWithoutV = newVersion.startsWith("v") ? newVersion.slice(1) : newVersion; + const versionWithoutV = newVersion.startsWith("v") + ? newVersion.slice(1) + : newVersion; const baseVersion = getBaseVersion(versionWithoutV); - console.log("[INFO]: Current tauri.conf.json version is: ", tauriConfig.version); + console.log( + "[INFO]: Current tauri.conf.json version is: ", + tauriConfig.version, + ); tauriConfig.version = baseVersion; - await fs.writeFile(tauriConfigPath, JSON.stringify(tauriConfig, null, 2), "utf8"); + await fs.writeFile( + tauriConfigPath, + JSON.stringify(tauriConfig, null, 2), + "utf8", + ); console.log(`[INFO]: tauri.conf.json version updated to: ${baseVersion}`); } catch (error) { console.error("Error updating tauri.conf.json version:", error); @@ -210,4 +235,3 @@ program .argument("", "version tag or full version") .action(main) .parse(process.argv); - diff --git a/clash-verge-rev/src-tauri/Cargo.lock b/clash-verge-rev/src-tauri/Cargo.lock index 836798de8b..9db3b6f0c8 100644 --- a/clash-verge-rev/src-tauri/Cargo.lock +++ b/clash-verge-rev/src-tauri/Cargo.lock @@ -1057,7 +1057,7 @@ dependencies = [ "dunce", "futures", "gethostname 1.0.2", - "getrandom 0.3.2", + "getrandom 0.3.3", "hex", "hmac", "image", @@ -1106,7 +1106,7 @@ dependencies = [ "warp", "winapi", "winreg 0.55.0", - "zip", + "zip 4.0.0", ] [[package]] @@ -1337,21 +1337,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - [[package]] name = "crc32fast" version = "1.4.2" @@ -1666,7 +1651,7 @@ dependencies = [ "tonic-health", "tonic-web", "tower 0.4.13", - "tower-http", + "tower-http 0.4.4", "tower-layer", "tracing", "tracing-core", @@ -2100,11 +2085,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", + "libz-rs-sys", "miniz_oxide", ] @@ -2462,9 +2448,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "js-sys", @@ -2587,9 +2573,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "global-hotkey" -version = "0.6.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fbb3a4e56c901ee66c190fdb3fa08344e6d09593cc6c61f8eb9add7144b271" +checksum = "b9247516746aa8e53411a0db9b62b0e24efbcf6a76e0ba73e5a91b512ddabed7" dependencies = [ "crossbeam-channel", "keyboard-types", @@ -2599,7 +2585,8 @@ dependencies = [ "serde", "thiserror 2.0.12", "windows-sys 0.59.0", - "x11-dl", + "x11rb", + "xkeysym", ] [[package]] @@ -2939,7 +2926,7 @@ dependencies = [ "httpdate", "itoa 1.0.15", "pin-project-lite", - "socket2 0.5.8", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -2981,7 +2968,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots", + "webpki-roots 0.26.8", ] [[package]] @@ -3014,21 +3001,28 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http 1.3.1", "http-body 1.0.1", "hyper 1.6.0", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", - "socket2 0.5.8", + "socket2 0.5.10", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -3380,6 +3374,16 @@ dependencies = [ "regex", ] +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is-docker" version = "0.2.0" @@ -3607,6 +3611,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "liblzma" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66352d7a8ac12d4877b6e6ea5a9b7650ee094257dc40889955bea5bc5b08c1d0" +dependencies = [ + "liblzma-sys", +] + +[[package]] +name = "liblzma-sys" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5839bad90c3cc2e0b8c4ed8296b80e86040240f81d46b9c0e9bc8dd51ddd3af1" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "libm" version = "0.2.11" @@ -3624,6 +3648,15 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "libz-rs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6489ca9bd760fe9642d7644e827b0c9add07df89857b0416ee15c1cc1a3b8c5a" +dependencies = [ + "zlib-rs", +] + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -3668,9 +3701,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -3743,27 +3776,6 @@ dependencies = [ "hashbrown 0.15.2", ] -[[package]] -name = "lzma-rs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" -dependencies = [ - "byteorder", - "crc", -] - -[[package]] -name = "lzma-sys" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "mac" version = "0.1.1" @@ -4777,9 +4789,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -4787,9 +4799,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", @@ -5381,7 +5393,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.8", + "socket2 0.5.10", "thiserror 2.0.12", "tokio", "tracing", @@ -5395,7 +5407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" dependencies = [ "bytes", - "getrandom 0.3.2", + "getrandom 0.3.3", "rand 0.9.0", "ring", "rustc-hash", @@ -5417,7 +5429,7 @@ dependencies = [ "cfg_aliases 0.2.1", "libc", "once_cell", - "socket2 0.5.8", + "socket2 0.5.10", "tracing", "windows-sys 0.59.0", ] @@ -5527,7 +5539,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -5727,9 +5739,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119" dependencies = [ "base64 0.22.1", "bytes", @@ -5756,26 +5768,24 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.2", - "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls", "tokio-util", "tower 0.5.2", + "tower-http 0.6.6", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", - "windows-registry 0.4.0", + "webpki-roots 1.0.0", ] [[package]] @@ -5967,15 +5977,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.11.0" @@ -6521,9 +6522,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -6708,9 +6709,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.35.0" +version = "0.35.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b897c8ea620e181c7955369a31be5f48d9a9121cb59fd33ecef9ff2a34323422" +checksum = "3c3ffa3e4ff2b324a57f7aeb3c349656c7b127c3c189520251a648102a92496e" dependencies = [ "libc", "memchr", @@ -7006,9 +7007,9 @@ dependencies = [ [[package]] name = "tauri-plugin-deep-link" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba4412f30eaff6f5d210e20383c2d6835593977402092e95b72497a4f8632fa" +checksum = "e4976ac728ebc0487515aa956cfdf200abcc52b784e441493fc544bc6ce369c8" dependencies = [ "dunce", "rust-ini", @@ -7020,7 +7021,7 @@ dependencies = [ "thiserror 2.0.12", "tracing", "url", - "windows-registry 0.5.1", + "windows-registry", "windows-result 0.3.2", ] @@ -7053,9 +7054,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcaf6e5d6062423a0f711a23c2a573ccba222b6a16a9322d8499928f27e41376" +checksum = "a33318fe222fc2a612961de8b0419e2982767f213f54a4d3a21b0d7b85c41df8" dependencies = [ "log", "raw-window-handle", @@ -7071,9 +7072,9 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88371e340ad2f07409a3b68294abe73f20bc9c1bc1b631a31dc37a3d0161f682" +checksum = "33ead0daec5d305adcefe05af9d970fc437bcc7996052d564e7393eb291252da" dependencies = [ "anyhow", "dunce", @@ -7089,14 +7090,13 @@ dependencies = [ "thiserror 2.0.12", "toml", "url", - "uuid", ] [[package]] name = "tauri-plugin-global-shortcut" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f646a09511e8d283267dcdaa08c2ef27c4116bf271d9114849d9ca215606c3" +checksum = "31919f3c07bcb585afef217c0c33cde80da9ebccf5b8e2c90e0e0a535b14ab47" dependencies = [ "global-hotkey", "log", @@ -7167,7 +7167,7 @@ dependencies = [ "tokio", "url", "windows-sys 0.59.0", - "zip", + "zip 2.6.1", ] [[package]] @@ -7285,12 +7285,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.19.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand 2.3.0", - "getrandom 0.3.2", + "getrandom 0.3.3", "once_cell", "rustix 1.0.3", "windows-sys 0.59.0", @@ -7514,9 +7514,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.2" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", @@ -7525,7 +7525,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.8", + "socket2 0.5.10", "tokio-macros", "tracing", "windows-sys 0.52.0", @@ -7730,7 +7730,7 @@ dependencies = [ "pin-project", "tokio-stream", "tonic", - "tower-http", + "tower-http 0.4.4", "tower-layer", "tower-service", "tracing", @@ -7789,6 +7789,24 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.0", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower 0.5.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -8144,7 +8162,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", "serde", ] @@ -8514,6 +8532,15 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webview2-com" version = "0.37.0" @@ -8761,17 +8788,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result 0.3.2", - "windows-strings 0.3.1", - "windows-targets 0.53.0", -] - [[package]] name = "windows-registry" version = "0.5.1" @@ -8811,15 +8827,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-strings" version = "0.4.0" @@ -8904,29 +8911,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - [[package]] name = "windows-version" version = "0.1.4" @@ -8954,12 +8945,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -8978,12 +8963,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -9002,24 +8981,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -9038,12 +9005,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -9062,12 +9023,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -9086,12 +9041,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -9110,12 +9059,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winnow" version = "0.5.40" @@ -9313,21 +9256,18 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + [[package]] name = "xml-rs" version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" -[[package]] -name = "xz2" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" -dependencies = [ - "lzma-sys", -] - [[package]] name = "yoke" version = "0.7.5" @@ -9517,29 +9457,46 @@ name = "zip" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dcb24d0152526ae49b9b96c1dcf71850ca1e0b882e4e28ed898a93c41334744" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "indexmap 2.8.0", + "memchr", +] + +[[package]] +name = "zip" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "153a6fff49d264c4babdcfa6b4d534747f520e56e8f0f384f3b808c4b64cc1fd" dependencies = [ "aes", "arbitrary", "bzip2", "constant_time_eq", "crc32fast", - "crossbeam-utils", "deflate64", "flate2", - "getrandom 0.3.2", + "getrandom 0.3.3", "hmac", "indexmap 2.8.0", - "lzma-rs", + "liblzma", "memchr", "pbkdf2", "sha1", "time", - "xz2", "zeroize", "zopfli", "zstd", ] +[[package]] +name = "zlib-rs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8" + [[package]] name = "zopfli" version = "0.8.1" diff --git a/clash-verge-rev/src-tauri/Cargo.toml b/clash-verge-rev/src-tauri/Cargo.toml index f8544bda25..be32876341 100755 --- a/clash-verge-rev/src-tauri/Cargo.toml +++ b/clash-verge-rev/src-tauri/Cargo.toml @@ -16,33 +16,33 @@ identifier = "io.github.clash-verge-rev.clash-verge-rev" tauri-build = { version = "2.2.0", features = [] } [dependencies] -warp = "0.3" +warp = "0.3.7" anyhow = "1.0.98" dirs = "6.0" -open = "5.3" -log = "0.4" -dunce = "1.0" -log4rs = "1" +open = "5.3.2" +log = "0.4.27" +dunce = "1.0.5" +log4rs = "1.3.0" nanoid = "0.4" chrono = "0.4.41" -sysinfo = "0.35.0" +sysinfo = "0.35.2" boa_engine = "0.20.0" serde_json = "1.0.140" -serde_yaml = "0.9.34" +serde_yaml = "0.9.34-deprecated" once_cell = "1.21.3" lazy_static = "1.5.0" port_scanner = "0.1.5" delay_timer = "0.11.6" -parking_lot = "0.12.3" +parking_lot = "0.12.4" percent-encoding = "2.3.1" -tokio = { version = "1.44.2", features = [ +tokio = { version = "1.45.1", features = [ "rt-multi-thread", "macros", "time", "sync", ] } serde = { version = "1.0.219", features = ["derive"] } -reqwest = { version = "0.12.15", features = ["json", "rustls-tls", "cookies"] } +reqwest = { version = "0.12.19", features = ["json", "rustls-tls", "cookies"] } regex = "1.11.1" sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs" } image = "0.25.6" @@ -56,18 +56,18 @@ tauri = { version = "2.5.1", features = [ ] } network-interface = { version = "2.0.1", features = ["serde"] } tauri-plugin-shell = "2.2.1" -tauri-plugin-dialog = "2.2.1" -tauri-plugin-fs = "2.2.1" +tauri-plugin-dialog = "2.2.2" +tauri-plugin-fs = "2.3.0" tauri-plugin-process = "2.2.1" tauri-plugin-clipboard-manager = "2.2.2" -tauri-plugin-deep-link = "2.2.1" +tauri-plugin-deep-link = "2.3.0" tauri-plugin-devtools = "2.0.0" tauri-plugin-window-state = "2.2.2" -zip = "2.6.1" +zip = "4.0.0" reqwest_dav = "0.2.1" aes-gcm = { version = "0.10.3", features = ["std"] } base64 = "0.22.1" -getrandom = "0.3.2" +getrandom = "0.3.3" tokio-tungstenite = "0.26.2" futures = "0.3.31" sys-locale = "0.3.2" @@ -85,7 +85,7 @@ hex = "0.4.3" runas = "=1.2.0" deelevate = "0.2.0" winreg = "0.55.0" -winapi = { version = "0.3", features = [ +winapi = { version = "0.3.9", features = [ "winbase", "fileapi", "winnt", @@ -100,7 +100,7 @@ users = "0.11.0" [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } -tauri-plugin-global-shortcut = "2.2.0" +tauri-plugin-global-shortcut = "2.2.1" tauri-plugin-updater = "2.7.1" [features] @@ -136,7 +136,7 @@ name = "app_lib" crate-type = ["staticlib", "cdylib", "rlib"] [dev-dependencies] -tempfile = "3.19.1" +tempfile = "3.20.0" [workspace] members = ["src_crates/crate_mihomo_api"] diff --git a/clash-verge-rev/src-tauri/capabilities/desktop-windows.json b/clash-verge-rev/src-tauri/capabilities/desktop-windows.json index ccfaa17e64..0017ef4ea3 100644 --- a/clash-verge-rev/src-tauri/capabilities/desktop-windows.json +++ b/clash-verge-rev/src-tauri/capabilities/desktop-windows.json @@ -1,4 +1,7 @@ { + "identifier": "desktop-windows-capability", + "description": "permissions for desktop windows applications", + "windows": ["main"], "permissions": [ "core:webview:allow-create-webview", "core:webview:allow-create-webview-window" diff --git a/clash-verge-rev/src-tauri/rustfmt.toml b/clash-verge-rev/src-tauri/rustfmt.toml index 11eda8825f..baaa750e30 100644 --- a/clash-verge-rev/src-tauri/rustfmt.toml +++ b/clash-verge-rev/src-tauri/rustfmt.toml @@ -11,4 +11,3 @@ merge_derives = true use_try_shorthand = false use_field_init_shorthand = false force_explicit_abi = true -imports_granularity = "Crate" diff --git a/clash-verge-rev/src-tauri/src/cmd/profile.rs b/clash-verge-rev/src-tauri/src/cmd/profile.rs index f98e17a6e1..459563767c 100644 --- a/clash-verge-rev/src-tauri/src/cmd/profile.rs +++ b/clash-verge-rev/src-tauri/src/cmd/profile.rs @@ -22,7 +22,7 @@ pub async fn get_profiles() -> CmdResult { .await; match profiles_result { - Ok(Ok(profiles)) => Ok(profiles), + Ok(Ok(profiles)) => Ok(*profiles), Ok(Err(join_err)) => { logging!(error, Type::Cmd, true, "获取配置列表任务失败: {}", join_err); Ok(IProfiles { @@ -41,7 +41,7 @@ pub async fn get_profiles() -> CmdResult { match tokio::task::spawn_blocking(move || Config::profiles().latest().clone()).await { Ok(profiles) => { logging!(info, Type::Cmd, true, "使用latest()成功获取配置"); - Ok(profiles) + Ok(*profiles) } Err(_) => { logging!(error, Type::Cmd, true, "fallback获取配置也失败,返回空配置"); diff --git a/clash-verge-rev/src-tauri/src/cmd/proxy.rs b/clash-verge-rev/src-tauri/src/cmd/proxy.rs index 4e56047f09..c6b58a0352 100644 --- a/clash-verge-rev/src-tauri/src/cmd/proxy.rs +++ b/clash-verge-rev/src-tauri/src/cmd/proxy.rs @@ -1,71 +1,77 @@ use super::CmdResult; -use crate::module::mihomo::MihomoManager; -use once_cell::sync::Lazy; -use parking_lot::Mutex; +use crate::{core::handle, module::mihomo::MihomoManager, state::proxy::CmdProxyState}; use std::{ - sync::atomic::{AtomicBool, Ordering}, + sync::Mutex, time::{Duration, Instant}, }; +use tauri::Manager; -static LAST_REFRESH_TIME: Lazy>> = Lazy::new(|| Mutex::new(None)); -static IS_REFRESHING: AtomicBool = AtomicBool::new(false); -const REFRESH_INTERVAL: Duration = Duration::from_secs(5); +const PROVIDERS_REFRESH_INTERVAL: Duration = Duration::from_secs(3); +const PROXIES_REFRESH_INTERVAL: Duration = Duration::from_secs(1); #[tauri::command] pub async fn get_proxies() -> CmdResult { let manager = MihomoManager::global(); - manager - .refresh_proxies() - .await - .map(|_| manager.get_proxies()) - .or_else(|_| Ok(manager.get_proxies())) + let app_handle = handle::Handle::global().app_handle().unwrap(); + let cmd_proxy_state = app_handle.state::>(); + + let should_refresh = { + let mut state = cmd_proxy_state.lock().unwrap(); + let now = Instant::now(); + if now.duration_since(state.last_refresh_time) > PROXIES_REFRESH_INTERVAL { + state.need_refresh = true; + state.last_refresh_time = now; + } + state.need_refresh + }; + + if should_refresh { + let proxies = manager.get_refresh_proxies().await?; + { + let mut state = cmd_proxy_state.lock().unwrap(); + state.proxies = Box::new(proxies); + state.need_refresh = false; + } + log::debug!(target: "app", "proxies刷新成功"); + } + + let proxies = { + let state = cmd_proxy_state.lock().unwrap(); + state.proxies.clone() + }; + Ok(*proxies) } #[tauri::command] pub async fn get_providers_proxies() -> CmdResult { - let manager = MihomoManager::global(); - let cached_data = manager.get_providers_proxies(); + let app_handle = handle::Handle::global().app_handle().unwrap(); + let cmd_proxy_state = app_handle.state::>(); - let safe_data = if cached_data.is_null() { - serde_json::json!({ - "providers": {} - }) - } else { - cached_data - }; - - // 检查是否需要刷新 let should_refresh = { - let last_refresh = LAST_REFRESH_TIME.lock(); - match *last_refresh { - Some(last_time) => last_time.elapsed() > REFRESH_INTERVAL, - None => true, + let mut state = cmd_proxy_state.lock().unwrap(); + let now = Instant::now(); + if now.duration_since(state.last_refresh_time) > PROVIDERS_REFRESH_INTERVAL { + state.need_refresh = true; + state.last_refresh_time = now; } + state.need_refresh }; - if should_refresh && !IS_REFRESHING.load(Ordering::Acquire) { - IS_REFRESHING.store(true, Ordering::Release); - - crate::process::AsyncHandler::spawn(|| async move { - let manager = MihomoManager::global(); - match manager.refresh_providers_proxies().await { - Ok(_) => { - log::debug!(target: "app", "providers_proxies静默后台刷新成功"); - } - Err(e) => { - log::warn!(target: "app", "providers_proxies后台刷新失败: {}", e); - } - } - - { - let mut last_refresh = LAST_REFRESH_TIME.lock(); - *last_refresh = Some(Instant::now()); - } - - IS_REFRESHING.store(false, Ordering::Release); - }); + if should_refresh { + let manager = MihomoManager::global(); + let providers = manager.get_providers_proxies().await?; + { + let mut state = cmd_proxy_state.lock().unwrap(); + state.providers_proxies = Box::new(providers); + state.need_refresh = false; + } + log::debug!(target: "app", "providers_proxies刷新成功"); } - Ok(safe_data) + let providers_proxies = { + let state = cmd_proxy_state.lock().unwrap(); + state.providers_proxies.clone() + }; + Ok(*providers_proxies) } diff --git a/clash-verge-rev/src-tauri/src/cmd/verge.rs b/clash-verge-rev/src-tauri/src/cmd/verge.rs index 7e8bc7a8f7..9d7c4fd2e0 100644 --- a/clash-verge-rev/src-tauri/src/cmd/verge.rs +++ b/clash-verge-rev/src-tauri/src/cmd/verge.rs @@ -6,7 +6,7 @@ use crate::{config::*, feat, wrap_err}; pub fn get_verge_config() -> CmdResult { let verge = Config::verge(); let verge_data = verge.data().clone(); - Ok(IVergeResponse::from(verge_data)) + Ok(IVergeResponse::from(*verge_data)) } /// 修改Verge配置 diff --git a/clash-verge-rev/src-tauri/src/config/config.rs b/clash-verge-rev/src-tauri/src/config/config.rs index 7cefb5d199..c0429b126b 100644 --- a/clash-verge-rev/src-tauri/src/config/config.rs +++ b/clash-verge-rev/src-tauri/src/config/config.rs @@ -15,10 +15,10 @@ pub const RUNTIME_CONFIG: &str = "clash-verge.yaml"; pub const CHECK_CONFIG: &str = "clash-verge-check.yaml"; pub struct Config { - clash_config: Draft, - verge_config: Draft, - profiles_config: Draft, - runtime_config: Draft, + clash_config: Draft>, + verge_config: Draft>, + profiles_config: Draft>, + runtime_config: Draft>, } impl Config { @@ -26,26 +26,26 @@ impl Config { static CONFIG: OnceCell = OnceCell::new(); CONFIG.get_or_init(|| Config { - clash_config: Draft::from(IClashTemp::new()), - verge_config: Draft::from(IVerge::new()), - profiles_config: Draft::from(IProfiles::new()), - runtime_config: Draft::from(IRuntime::new()), + clash_config: Draft::from(Box::new(IClashTemp::new())), + verge_config: Draft::from(Box::new(IVerge::new())), + profiles_config: Draft::from(Box::new(IProfiles::new())), + runtime_config: Draft::from(Box::new(IRuntime::new())), }) } - pub fn clash() -> Draft { + pub fn clash() -> Draft> { Self::global().clash_config.clone() } - pub fn verge() -> Draft { + pub fn verge() -> Draft> { Self::global().verge_config.clone() } - pub fn profiles() -> Draft { + pub fn profiles() -> Draft> { Self::global().profiles_config.clone() } - pub fn runtime() -> Draft { + pub fn runtime() -> Draft> { Self::global().runtime_config.clone() } @@ -149,11 +149,11 @@ impl Config { pub async fn generate() -> Result<()> { let (config, exists_keys, logs) = enhance::enhance().await; - *Config::runtime().draft() = IRuntime { + *Config::runtime().draft() = Box::new(IRuntime { config: Some(config), exists_keys, chain_logs: logs, - }; + }); Ok(()) } @@ -164,3 +164,42 @@ pub enum ConfigType { Run, Check, } +#[cfg(test)] +mod tests { + use super::*; + use std::mem; + + #[test] + fn test_prfitem_from_merge_size() { + let merge_item = PrfItem::from_merge(Some("Merge".to_string())).unwrap(); + dbg!(&merge_item); + let prfitem_size = mem::size_of_val(&merge_item); + dbg!(prfitem_size); + // Boxed version + let boxed_merge_item = Box::new(merge_item); + let box_prfitem_size = mem::size_of_val(&boxed_merge_item); + dbg!(box_prfitem_size); + // The size of Box is always pointer-sized (usually 8 bytes on 64-bit) + // assert_eq!(box_prfitem_size, mem::size_of::>()); + assert!(box_prfitem_size < prfitem_size); + } + + #[test] + fn test_draft_size_non_boxed() { + let draft = Draft::from(IRuntime::new()); + let iruntime_size = std::mem::size_of_val(&draft); + dbg!(iruntime_size); + assert_eq!(iruntime_size, std::mem::size_of::>()); + } + + #[test] + fn test_draft_size_boxed() { + let draft = Draft::from(Box::new(IRuntime::new())); + let box_iruntime_size = std::mem::size_of_val(&draft); + dbg!(box_iruntime_size); + assert_eq!( + box_iruntime_size, + std::mem::size_of::>>() + ); + } +} diff --git a/clash-verge-rev/src-tauri/src/config/draft.rs b/clash-verge-rev/src-tauri/src/config/draft.rs index 5876f1bbbb..97ef74123a 100644 --- a/clash-verge-rev/src-tauri/src/config/draft.rs +++ b/clash-verge-rev/src-tauri/src/config/draft.rs @@ -9,13 +9,21 @@ pub struct Draft { macro_rules! draft_define { ($id: ident) => { - impl Draft<$id> { + impl From<$id> for Draft<$id> { + fn from(data: $id) -> Self { + Draft { + inner: Arc::new(Mutex::new((data, None))), + } + } + } + + impl Draft> { #[allow(unused)] - pub fn data(&self) -> MappedMutexGuard<$id> { + pub fn data(&self) -> MappedMutexGuard> { MutexGuard::map(self.inner.lock(), |guard| &mut guard.0) } - pub fn latest(&self) -> MappedMutexGuard<$id> { + pub fn latest(&self) -> MappedMutexGuard> { MutexGuard::map(self.inner.lock(), |inner| { if inner.1.is_none() { &mut inner.0 @@ -25,7 +33,7 @@ macro_rules! draft_define { }) } - pub fn draft(&self) -> MappedMutexGuard<$id> { + pub fn draft(&self) -> MappedMutexGuard> { MutexGuard::map(self.inner.lock(), |inner| { if inner.1.is_none() { inner.1 = Some(inner.0.clone()); @@ -35,7 +43,7 @@ macro_rules! draft_define { }) } - pub fn apply(&self) -> Option<$id> { + pub fn apply(&self) -> Option> { let mut inner = self.inner.lock(); match inner.1.take() { @@ -48,14 +56,14 @@ macro_rules! draft_define { } } - pub fn discard(&self) -> Option<$id> { + pub fn discard(&self) -> Option> { let mut inner = self.inner.lock(); inner.1.take() } } - impl From<$id> for Draft<$id> { - fn from(data: $id) -> Self { + impl From> for Draft> { + fn from(data: Box<$id>) -> Self { Draft { inner: Arc::new(Mutex::new((data, None))), } @@ -71,12 +79,12 @@ draft_define!(IRuntime); draft_define!(IVerge); #[test] -fn test_draft() { - let verge = IVerge { +fn test_draft_box() { + let verge = Box::new(IVerge { enable_auto_launch: Some(true), enable_tun_mode: Some(false), ..IVerge::default() - }; + }); let draft = Draft::from(verge); @@ -86,10 +94,11 @@ fn test_draft() { assert_eq!(draft.draft().enable_auto_launch, Some(true)); assert_eq!(draft.draft().enable_tun_mode, Some(false)); - let mut d = draft.draft(); - d.enable_auto_launch = Some(false); - d.enable_tun_mode = Some(true); - drop(d); + { + let mut d = draft.draft(); + d.enable_auto_launch = Some(false); + d.enable_tun_mode = Some(true); + } assert_eq!(draft.data().enable_auto_launch, Some(true)); assert_eq!(draft.data().enable_tun_mode, Some(false)); @@ -109,18 +118,17 @@ fn test_draft() { assert_eq!(draft.draft().enable_auto_launch, Some(false)); assert_eq!(draft.draft().enable_tun_mode, Some(true)); - let mut d = draft.draft(); - d.enable_auto_launch = Some(true); - drop(d); + { + let mut d = draft.draft(); + d.enable_auto_launch = Some(true); + } assert_eq!(draft.data().enable_auto_launch, Some(false)); - assert_eq!(draft.draft().enable_auto_launch, Some(true)); assert!(draft.discard().is_some()); assert_eq!(draft.data().enable_auto_launch, Some(false)); - assert!(draft.discard().is_none()); assert_eq!(draft.draft().enable_auto_launch, Some(false)); diff --git a/clash-verge-rev/src-tauri/src/core/core.rs b/clash-verge-rev/src-tauri/src/core/core.rs index 7734fbc9d4..502556002d 100644 --- a/clash-verge-rev/src-tauri/src/core/core.rs +++ b/clash-verge-rev/src-tauri/src/core/core.rs @@ -140,11 +140,11 @@ impl CoreManager { /// 使用默认配置 pub async fn use_default_config(&self, msg_type: &str, msg_content: &str) -> Result<()> { let runtime_path = dirs::app_home_dir()?.join(RUNTIME_CONFIG); - *Config::runtime().draft() = IRuntime { + *Config::runtime().draft() = Box::new(IRuntime { config: Some(Config::clash().latest().0.clone()), exists_keys: vec![], chain_logs: Default::default(), - }; + }); help::save_yaml( &runtime_path, &Config::clash().latest().0, diff --git a/clash-verge-rev/src-tauri/src/enhance/script.rs b/clash-verge-rev/src-tauri/src/enhance/script.rs index 22ad0cef64..98919794af 100644 --- a/clash-verge-rev/src-tauri/src/enhance/script.rs +++ b/clash-verge-rev/src-tauri/src/enhance/script.rs @@ -104,6 +104,10 @@ fn test_script() { let (config, results) = use_script(script.into(), config, "".to_string()).unwrap(); let _ = serde_yaml::to_string(&config).unwrap(); - + let yaml_config_size = std::mem::size_of_val(&config); + dbg!(yaml_config_size); + let box_yaml_config_size = std::mem::size_of_val(&Box::new(config)); + dbg!(box_yaml_config_size); dbg!(results); + assert!(box_yaml_config_size < yaml_config_size); } diff --git a/clash-verge-rev/src-tauri/src/error/mod.rs b/clash-verge-rev/src-tauri/src/error/mod.rs deleted file mode 100644 index 1f278a4d51..0000000000 --- a/clash-verge-rev/src-tauri/src/error/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod service; diff --git a/clash-verge-rev/src-tauri/src/error/service.rs b/clash-verge-rev/src-tauri/src/error/service.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/clash-verge-rev/src-tauri/src/error/service.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/clash-verge-rev/src-tauri/src/lib.rs b/clash-verge-rev/src-tauri/src/lib.rs index 3c030667d7..4c83036e3e 100644 --- a/clash-verge-rev/src-tauri/src/lib.rs +++ b/clash-verge-rev/src-tauri/src/lib.rs @@ -2,10 +2,10 @@ mod cmd; mod config; mod core; mod enhance; -mod error; mod feat; mod module; mod process; +mod state; mod utils; use crate::{ core::hotkey, @@ -15,7 +15,6 @@ use crate::{ use config::Config; use std::sync::{Mutex, Once}; use tauri::AppHandle; -#[cfg(target_os = "macos")] use tauri::Manager; use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_deep_link::DeepLinkExt; @@ -205,6 +204,8 @@ pub fn run() { logging!(error, Type::Setup, true, "初始化资源失败: {}", e); } + app.manage(Mutex::new(state::proxy::CmdProxyState::default())); + logging!(info, Type::Setup, true, "初始化完成,继续执行"); Ok(()) }) diff --git a/clash-verge-rev/src-tauri/src/state/mod.rs b/clash-verge-rev/src-tauri/src/state/mod.rs new file mode 100644 index 0000000000..94f453c3a5 --- /dev/null +++ b/clash-verge-rev/src-tauri/src/state/mod.rs @@ -0,0 +1,4 @@ +// Tauri Manager 会进行 Arc 管理,无需额外 Arc +// https://tauri.app/develop/state-management/#do-you-need-arc + +pub mod proxy; diff --git a/clash-verge-rev/src-tauri/src/state/proxy.rs b/clash-verge-rev/src-tauri/src/state/proxy.rs new file mode 100644 index 0000000000..c3df7d8dbc --- /dev/null +++ b/clash-verge-rev/src-tauri/src/state/proxy.rs @@ -0,0 +1,19 @@ +use serde_json::Value; + +pub struct CmdProxyState { + pub last_refresh_time: std::time::Instant, + pub need_refresh: bool, + pub proxies: Box, + pub providers_proxies: Box, +} + +impl Default for CmdProxyState { + fn default() -> Self { + Self { + last_refresh_time: std::time::Instant::now(), + need_refresh: true, + proxies: Box::new(Value::Null), + providers_proxies: Box::new(Value::Null), + } + } +} diff --git a/clash-verge-rev/src-tauri/src/utils/help.rs b/clash-verge-rev/src-tauri/src/utils/help.rs index d785478a23..0df0573bee 100644 --- a/clash-verge-rev/src-tauri/src/utils/help.rs +++ b/clash-verge-rev/src-tauri/src/utils/help.rs @@ -204,8 +204,8 @@ pub fn format_bytes_speed(speed: u64) -> String { #[cfg(target_os = "macos")] #[test] fn test_format_bytes_speed() { - assert_eq!(format_bytes_speed(0), "0B/s"); - assert_eq!(format_bytes_speed(1023), "1023B/s"); + assert_eq!(format_bytes_speed(0), "0.0B/s"); + assert_eq!(format_bytes_speed(1023), "1.0KB/s"); assert_eq!(format_bytes_speed(1024), "1.0KB/s"); assert_eq!(format_bytes_speed(1024 * 1024), "1.0MB/s"); assert_eq!(format_bytes_speed(1024 * 1024 * 1024), "1.0GB/s"); diff --git a/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/Cargo.toml b/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/Cargo.toml index c38c3a17fc..1691bbd69a 100644 --- a/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/Cargo.toml +++ b/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/Cargo.toml @@ -2,13 +2,10 @@ name = "mihomo_api" edition = "2024" -[features] -debug = [] - [dependencies] -reqwest = { version = "0.12.15", features = ["json"] } +reqwest = { version = "0.12.19", features = ["json"] } serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" -tokio = { version = "1.44.1", features = ["rt", "macros", "time"] } +tokio = { version = "1.45.1", features = ["rt", "macros", "time"] } [dev-dependencies] diff --git a/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/src/lib.rs b/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/src/lib.rs index 757796b1d2..ecbee81fea 100644 --- a/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/src/lib.rs +++ b/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/src/lib.rs @@ -1,11 +1,8 @@ use reqwest::{Method, header::HeaderMap}; -use serde_json::json; -use std::{ - sync::{Arc, Mutex}, - time::Duration, -}; +use serde_json::{Value, json}; +use std::time::Duration; pub mod model; -pub use model::{MihomoData, MihomoManager}; +pub use model::MihomoManager; impl MihomoManager { pub fn new(mihomo_server: String, headers: HeaderMap) -> Self { @@ -20,38 +17,10 @@ impl MihomoManager { Self { mihomo_server, - data: Arc::new(Mutex::new(MihomoData { - proxies: serde_json::Value::Null, - providers_proxies: serde_json::Value::Null, - })), client, } } - fn update_proxies(&self, proxies: serde_json::Value) { - let mut data = self.data.lock().expect("Mutex poisoned"); - data.proxies = proxies; - } - - fn update_providers_proxies(&self, providers_proxies: serde_json::Value) { - let mut data = self.data.lock().expect("Mutex poisoned"); - data.providers_proxies = providers_proxies; - } - - pub fn get_mihomo_server(&self) -> String { - self.mihomo_server.clone() - } - - pub fn get_proxies(&self) -> serde_json::Value { - let data = self.data.lock().expect("Mutex poisoned"); - data.proxies.clone() - } - - pub fn get_providers_proxies(&self) -> serde_json::Value { - let data = self.data.lock().expect("Mutex poisoned"); - data.providers_proxies.clone() - } - async fn send_request( &self, method: Method, @@ -87,18 +56,16 @@ impl MihomoManager { Ok(response) } - pub async fn refresh_proxies(&self) -> Result<&Self, String> { + pub async fn get_refresh_proxies(&self) -> Result { let url = format!("{}/proxies", self.mihomo_server); let proxies = self.send_request(Method::GET, url, None).await?; - self.update_proxies(proxies); - Ok(self) + Ok(proxies) } - pub async fn refresh_providers_proxies(&self) -> Result<&Self, String> { + pub async fn get_providers_proxies(&self) -> Result { let url = format!("{}/providers/proxies", self.mihomo_server); let providers_proxies = self.send_request(Method::GET, url, None).await?; - self.update_providers_proxies(providers_proxies); - Ok(self) + Ok(providers_proxies) } pub async fn close_all_connections(&self) -> Result<(), String> { diff --git a/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/src/model.rs b/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/src/model.rs index fbc4c862dd..aed81a9547 100644 --- a/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/src/model.rs +++ b/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/src/model.rs @@ -1,27 +1,5 @@ -use std::sync::{Arc, Mutex}; - -pub struct MihomoData { - pub(crate) proxies: serde_json::Value, - pub(crate) providers_proxies: serde_json::Value, -} - #[derive(Clone)] pub struct MihomoManager { pub(crate) mihomo_server: String, - pub(crate) data: Arc>, pub(crate) client: reqwest::Client, } - -#[cfg(feature = "debug")] -impl Drop for MihomoData { - fn drop(&mut self) { - println!("Dropping MihomoData"); - } -} - -#[cfg(feature = "debug")] -impl Drop for MihomoManager { - fn drop(&mut self) { - println!("Dropping MihomoManager"); - } -} diff --git a/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/tests/test_mihomo_api.rs b/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/tests/test_mihomo_api.rs index 9ef272ca38..bee8d8d3ee 100644 --- a/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/tests/test_mihomo_api.rs +++ b/clash-verge-rev/src-tauri/src_crates/crate_mihomo_api/tests/test_mihomo_api.rs @@ -1,29 +1,7 @@ -use mihomo_api; use reqwest::header::HeaderMap; #[test] fn test_mihomo_manager_init() { - let manager = mihomo_api::MihomoManager::new("url".into(), HeaderMap::new()); - assert_eq!(manager.get_proxies(), serde_json::Value::Null); - assert_eq!(manager.get_providers_proxies(), serde_json::Value::Null); -} - -#[tokio::test] -async fn test_refresh_proxies() { - let manager = mihomo_api::MihomoManager::new("http://127.0.0.1:9097".into(), HeaderMap::new()); - let manager = manager.refresh_proxies().await.unwrap(); - let proxies = manager.get_proxies(); - let providers = manager.get_providers_proxies(); - assert_ne!(proxies, serde_json::Value::Null); - assert_eq!(providers, serde_json::Value::Null); -} - -#[tokio::test] -async fn test_refresh_providers_proxies() { - let manager = mihomo_api::MihomoManager::new("http://127.0.0.1:9097".into(), HeaderMap::new()); - let manager = manager.refresh_providers_proxies().await.unwrap(); - let proxies = manager.get_proxies(); - let providers = manager.get_providers_proxies(); - assert_eq!(proxies, serde_json::Value::Null); - assert_ne!(providers, serde_json::Value::Null); + let _ = mihomo_api::MihomoManager::new("url".into(), HeaderMap::new()); + assert_eq!(true, true); } diff --git a/clash-verge-rev/src-tauri/tauri.conf.json b/clash-verge-rev/src-tauri/tauri.conf.json index 0d52e46b73..04f10958dd 100755 --- a/clash-verge-rev/src-tauri/tauri.conf.json +++ b/clash-verge-rev/src-tauri/tauri.conf.json @@ -11,15 +11,9 @@ "icons/icon.icns", "icons/icon.ico" ], - "resources": [ - "resources", - "resources/locales/*" - ], + "resources": ["resources", "resources/locales/*"], "publisher": "Clash Verge Rev", - "externalBin": [ - "sidecar/verge-mihomo", - "sidecar/verge-mihomo-alpha" - ], + "externalBin": ["sidecar/verge-mihomo", "sidecar/verge-mihomo-alpha"], "copyright": "GNU General Public License v3.0", "category": "DeveloperTool", "shortDescription": "Clash Verge Rev", @@ -50,28 +44,18 @@ }, "deep-link": { "desktop": { - "schemes": [ - "clash", - "clash-verge" - ] + "schemes": ["clash", "clash-verge"] } } }, "app": { "security": { - "capabilities": [ - "desktop-capability", - "migrated" - ], + "capabilities": ["desktop-capability", "migrated"], "assetProtocol": { - "scope": [ - "$APPDATA/**", - "$RESOURCE/../**", - "**" - ], + "scope": ["$APPDATA/**", "$RESOURCE/../**", "**"], "enable": true }, "csp": null } } -} \ No newline at end of file +} diff --git a/clash-verge-rev/src-tauri/tauri.windows.conf.json b/clash-verge-rev/src-tauri/tauri.windows.conf.json index 8e0b1881f5..5e73474fb7 100644 --- a/clash-verge-rev/src-tauri/tauri.windows.conf.json +++ b/clash-verge-rev/src-tauri/tauri.windows.conf.json @@ -23,7 +23,11 @@ "app": { "windows": [], "security": { - "capabilities": ["desktop-capability", "desktop-windows", "migrated"] + "capabilities": [ + "desktop-capability", + "desktop-windows-capability", + "migrated" + ] } } } diff --git a/clash-verge-rev/src/assets/styles/index.scss b/clash-verge-rev/src/assets/styles/index.scss index eeb6845840..aa12ded7c1 100644 --- a/clash-verge-rev/src/assets/styles/index.scss +++ b/clash-verge-rev/src/assets/styles/index.scss @@ -4,9 +4,9 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; user-select: none; diff --git a/clash-verge-rev/src/components/base/NoticeManager.tsx b/clash-verge-rev/src/components/base/NoticeManager.tsx index 0fb261f470..b7fedf98d5 100644 --- a/clash-verge-rev/src/components/base/NoticeManager.tsx +++ b/clash-verge-rev/src/components/base/NoticeManager.tsx @@ -1,7 +1,11 @@ -import React, { useState, useEffect } from 'react'; -import { Snackbar, Alert, IconButton, Box } from '@mui/material'; -import { CloseRounded } from '@mui/icons-material'; -import { subscribeNotices, hideNotice, NoticeItem } from '@/services/noticeService'; +import React, { useState, useEffect } from "react"; +import { Snackbar, Alert, IconButton, Box } from "@mui/material"; +import { CloseRounded } from "@mui/icons-material"; +import { + subscribeNotices, + hideNotice, + NoticeItem, +} from "@/services/noticeService"; export const NoticeManager: React.FC = () => { const [currentNotices, setCurrentNotices] = useState([]); @@ -23,49 +27,49 @@ export const NoticeManager: React.FC = () => { return ( {currentNotices.map((notice) => ( - handleClose(notice.id)} - > - - - } - > - {notice.message} - + handleClose(notice.id)} + > + + + } + > + {notice.message} + ))} ); -}; \ No newline at end of file +}; diff --git a/clash-verge-rev/src/components/base/base-search-box.tsx b/clash-verge-rev/src/components/base/base-search-box.tsx index ff35d9badb..a01789fd5d 100644 --- a/clash-verge-rev/src/components/base/base-search-box.tsx +++ b/clash-verge-rev/src/components/base/base-search-box.tsx @@ -157,7 +157,7 @@ export const BaseSearchBox = (props: SearchProps) => { ), - } + }, }} /> diff --git a/clash-verge-rev/src/components/connection/connection-detail.tsx b/clash-verge-rev/src/components/connection/connection-detail.tsx index 172c0f57f2..6c4dc89ef9 100644 --- a/clash-verge-rev/src/components/connection/connection-detail.tsx +++ b/clash-verge-rev/src/components/connection/connection-detail.tsx @@ -107,7 +107,14 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { {information.map((each) => (
{each.label} - : {each.value} + + : {each.value} +
))} diff --git a/clash-verge-rev/src/components/home/clash-info-card.tsx b/clash-verge-rev/src/components/home/clash-info-card.tsx index cefb4f2fef..029f174c82 100644 --- a/clash-verge-rev/src/components/home/clash-info-card.tsx +++ b/clash-verge-rev/src/components/home/clash-info-card.tsx @@ -25,7 +25,7 @@ export const ClashInfoCard = () => { // 使用备忘录组件内容,减少重新渲染 const cardContent = useMemo(() => { if (!clashConfig) return null; - + return ( diff --git a/clash-verge-rev/src/components/home/clash-mode-card.tsx b/clash-verge-rev/src/components/home/clash-mode-card.tsx index 198811822f..8faafceb76 100644 --- a/clash-verge-rev/src/components/home/clash-mode-card.tsx +++ b/clash-verge-rev/src/components/home/clash-mode-card.tsx @@ -24,11 +24,14 @@ export const ClashModeCard = () => { const currentMode = clashConfig?.mode?.toLowerCase(); // 模式图标映射 - const modeIcons = useMemo(() => ({ - rule: , - global: , - direct: - }), []); + const modeIcons = useMemo( + () => ({ + rule: , + global: , + direct: , + }), + [], + ); // 切换模式的处理函数 const onChangeMode = useLockFn(async (mode: string) => { @@ -68,18 +71,19 @@ export const ClashModeCard = () => { "&:active": { transform: "translateY(1px)", }, - "&::after": mode === currentMode - ? { - content: '""', - position: "absolute", - bottom: -16, - left: "50%", - width: 2, - height: 16, - bgcolor: "primary.main", - transform: "translateX(-50%)", - } - : {}, + "&::after": + mode === currentMode + ? { + content: '""', + position: "absolute", + bottom: -16, + left: "50%", + width: 2, + height: 16, + bgcolor: "primary.main", + transform: "translateX(-50%)", + } + : {}, }); // 描述样式 @@ -143,12 +147,10 @@ export const ClashModeCard = () => { overflow: "visible", }} > - - {t(`${currentMode?.charAt(0).toUpperCase()}${currentMode?.slice(1)} Mode Description`)} + + {t( + `${currentMode?.charAt(0).toUpperCase()}${currentMode?.slice(1)} Mode Description`, + )} diff --git a/clash-verge-rev/src/components/home/current-proxy-card.tsx b/clash-verge-rev/src/components/home/current-proxy-card.tsx index 57a14e1d6d..ce4914bf86 100644 --- a/clash-verge-rev/src/components/home/current-proxy-card.tsx +++ b/clash-verge-rev/src/components/home/current-proxy-card.tsx @@ -105,7 +105,7 @@ export const CurrentProxyCard = () => { // 添加排序类型状态 const [sortType, setSortType] = useState(() => { const savedSortType = localStorage.getItem(STORAGE_KEY_SORT_TYPE); - return savedSortType ? Number(savedSortType) as ProxySortType : 0; + return savedSortType ? (Number(savedSortType) as ProxySortType) : 0; }); // 定义状态类型 @@ -156,7 +156,8 @@ export const CurrentProxyCard = () => { primaryKeywords.some((keyword) => group.name.toLowerCase().includes(keyword.toLowerCase()), ), - ) || proxies.groups.filter((g: { name: string }) => g.name !== "GLOBAL")[0]; + ) || + proxies.groups.filter((g: { name: string }) => g.name !== "GLOBAL")[0]; return primaryGroup?.name || ""; }; @@ -200,11 +201,13 @@ export const CurrentProxyCard = () => { // 只保留 Selector 类型的组用于选择 const filteredGroups = proxies.groups .filter((g: { name: string; type?: string }) => g.type === "Selector") - .map((g: { name: string; now: string; all: Array<{ name: string }> }) => ({ - name: g.name, - now: g.now || "", - all: g.all.map((p: { name: string }) => p.name), - })); + .map( + (g: { name: string; now: string; all: Array<{ name: string }> }) => ({ + name: g.name, + now: g.now || "", + all: g.all.map((p: { name: string }) => p.name), + }), + ); let newProxy = ""; let newDisplayProxy = null; @@ -230,12 +233,12 @@ export const CurrentProxyCard = () => { if (selectorGroup) { newGroup = selectorGroup.name; newProxy = selectorGroup.now || selectorGroup.all[0] || ""; - newDisplayProxy = proxies.records?.[newProxy] || null; + newDisplayProxy = proxies.records?.[newProxy] || null; - if (!isGlobalMode && !isDirectMode) { - localStorage.setItem(STORAGE_KEY_GROUP, newGroup); - if (newProxy) { - localStorage.setItem(STORAGE_KEY_PROXY, newProxy); + if (!isGlobalMode && !isDirectMode) { + localStorage.setItem(STORAGE_KEY_GROUP, newGroup); + if (newProxy) { + localStorage.setItem(STORAGE_KEY_PROXY, newProxy); } } } @@ -280,7 +283,9 @@ export const CurrentProxyCard = () => { localStorage.setItem(STORAGE_KEY_GROUP, newGroup); setState((prev) => { - const group = prev.proxyData.groups.find((g: { name: string }) => g.name === newGroup); + const group = prev.proxyData.groups.find( + (g: { name: string }) => g.name === newGroup, + ); if (group) { return { ...prev, @@ -368,14 +373,16 @@ export const CurrentProxyCard = () => { }, [state.displayProxy]); // 获取当前节点的延迟(增加非空校验) - const currentDelay = currentProxy && state.selection.group - ? delayManager.getDelayFix(currentProxy, state.selection.group) - : -1; + const currentDelay = + currentProxy && state.selection.group + ? delayManager.getDelayFix(currentProxy, state.selection.group) + : -1; // 信号图标(增加非空校验) - const signalInfo = currentProxy && state.selection.group - ? getSignalIcon(currentDelay) - : { icon: , text: "未初始化", color: "text.secondary" }; + const signalInfo = + currentProxy && state.selection.group + ? getSignalIcon(currentDelay) + : { icon: , text: "未初始化", color: "text.secondary" }; // 自定义渲染选择框中的值 const renderProxyValue = useCallback( @@ -384,7 +391,7 @@ export const CurrentProxyCard = () => { const delayValue = delayManager.getDelayFix( state.proxyData.records[selected], - state.selection.group + state.selection.group, ); return ( @@ -441,7 +448,7 @@ export const CurrentProxyCard = () => { return list; }, - [sortType, state.proxyData.records, state.selection.group] + [sortType, state.proxyData.records, state.selection.group], ); // 计算要显示的代理选项(增加非空校验) @@ -452,11 +459,11 @@ export const CurrentProxyCard = () => { if (isGlobalMode && proxies?.global) { const options = proxies.global.all .filter((p: any) => { - const name = typeof p === 'string' ? p : p.name; + const name = typeof p === "string" ? p : p.name; return name !== "DIRECT" && name !== "REJECT"; }) .map((p: any) => ({ - name: typeof p === 'string' ? p : p.name + name: typeof p === "string" ? p : p.name, })); return sortProxies(options); @@ -464,7 +471,7 @@ export const CurrentProxyCard = () => { // 规则模式 const group = state.selection.group - ? state.proxyData.groups.find(g => g.name === state.selection.group) + ? state.proxyData.groups.find((g) => g.name === state.selection.group) : null; if (group) { @@ -473,7 +480,14 @@ export const CurrentProxyCard = () => { } return []; - }, [isDirectMode, isGlobalMode, proxies, state.proxyData, state.selection.group, sortProxies]); + }, [ + isDirectMode, + isGlobalMode, + proxies, + state.proxyData, + state.selection.group, + sortProxies, + ]); // 获取排序图标 const getSortIcon = () => { @@ -660,12 +674,14 @@ export const CurrentProxyCard = () => { {isDirectMode ? null : proxyOptions.map((proxy, index) => { - const delayValue = state.proxyData.records[proxy.name] && state.selection.group - ? delayManager.getDelayFix( - state.proxyData.records[proxy.name], - state.selection.group, - ) - : -1; + const delayValue = + state.proxyData.records[proxy.name] && + state.selection.group + ? delayManager.getDelayFix( + state.proxyData.records[proxy.name], + state.selection.group, + ) + : -1; return ( { )} ); -}; +}; diff --git a/clash-verge-rev/src/components/home/enhanced-card.tsx b/clash-verge-rev/src/components/home/enhanced-card.tsx index 814e4be107..68548a5411 100644 --- a/clash-verge-rev/src/components/home/enhanced-card.tsx +++ b/clash-verge-rev/src/components/home/enhanced-card.tsx @@ -38,7 +38,7 @@ export const EnhancedCard = ({ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", - display: "block" + display: "block", }; return ( @@ -62,13 +62,15 @@ export const EnhancedCard = ({ borderColor: "divider", }} > - + {typeof title === "string" ? ( - ) : ( - - {title} - + {title} )} diff --git a/clash-verge-rev/src/components/home/enhanced-traffic-graph.tsx b/clash-verge-rev/src/components/home/enhanced-traffic-graph.tsx index 2f93a6ee6a..1da338985e 100644 --- a/clash-verge-rev/src/components/home/enhanced-traffic-graph.tsx +++ b/clash-verge-rev/src/components/home/enhanced-traffic-graph.tsx @@ -30,7 +30,7 @@ ChartJS.register( PointElement, LineElement, Tooltip, - Filler + Filler, ); // 流量数据项接口 @@ -54,8 +54,8 @@ type DataPoint = ITrafficItem & { name: string; timestamp: number }; /** * 增强型流量图表组件 */ -export const EnhancedTrafficGraph = memo(forwardRef( - (props, ref) => { +export const EnhancedTrafficGraph = memo( + forwardRef((props, ref) => { const theme = useTheme(); const { t } = useTranslation(); @@ -63,20 +63,20 @@ export const EnhancedTrafficGraph = memo(forwardRef( const [timeRange, setTimeRange] = useState(10); const [chartStyle, setChartStyle] = useState<"line" | "area">("area"); const [displayData, setDisplayData] = useState([]); - + // 数据缓冲区 const dataBufferRef = useRef([]); // 根据时间范围计算保留的数据点数量 const getMaxPointsByTimeRange = useCallback( (minutes: TimeRange): number => minutes * 60, - [] + [], ); // 最大数据点数量 const MAX_BUFFER_SIZE = useMemo( () => getMaxPointsByTimeRange(10), - [getMaxPointsByTimeRange] + [getMaxPointsByTimeRange], ); // 颜色配置 @@ -89,23 +89,28 @@ export const EnhancedTrafficGraph = memo(forwardRef( text: theme.palette.text.primary, tooltipBorder: theme.palette.divider, }), - [theme] + [theme], ); // 切换时间范围 - const handleTimeRangeClick = useCallback((event: React.MouseEvent) => { - event.stopPropagation(); - setTimeRange((prevRange) => { - return prevRange === 1 ? 5 : prevRange === 5 ? 10 : 1; - }); - }, []); - - // 点击图表主体或图例时切换样式 - const handleToggleStyleClick = useCallback((event: React.MouseEvent) => { - event.stopPropagation(); - setChartStyle((prev) => (prev === "line" ? "area" : "line")); - }, []); + const handleTimeRangeClick = useCallback( + (event: React.MouseEvent) => { + event.stopPropagation(); + setTimeRange((prevRange) => { + return prevRange === 1 ? 5 : prevRange === 5 ? 10 : 1; + }); + }, + [], + ); + // 点击图表主体或图例时切换样式 + const handleToggleStyleClick = useCallback( + (event: React.MouseEvent) => { + event.stopPropagation(); + setChartStyle((prev) => (prev === "line" ? "area" : "line")); + }, + [], + ); // 初始化数据缓冲区 useEffect(() => { @@ -121,7 +126,9 @@ export const EnhancedTrafficGraph = memo(forwardRef( let nameValue: string; try { if (isNaN(date.getTime())) { - console.warn(`Initial data generation: Invalid date for timestamp ${pointTime}`); + console.warn( + `Initial data generation: Invalid date for timestamp ${pointTime}`, + ); nameValue = "??:??:??"; } else { nameValue = date.toLocaleTimeString("en-US", { @@ -132,7 +139,14 @@ export const EnhancedTrafficGraph = memo(forwardRef( }); } } catch (e) { - console.error("Error in toLocaleTimeString during initial data gen:", e, "Date:", date, "Timestamp:", pointTime); + console.error( + "Error in toLocaleTimeString during initial data gen:", + e, + "Date:", + date, + "Timestamp:", + pointTime, + ); nameValue = "Err:Time"; } @@ -142,55 +156,66 @@ export const EnhancedTrafficGraph = memo(forwardRef( timestamp: pointTime, name: nameValue, }; - } + }, ); dataBufferRef.current = initialBuffer; - + // 更新显示数据 const pointsToShow = getMaxPointsByTimeRange(timeRange); setDisplayData(initialBuffer.slice(-pointsToShow)); }, [MAX_BUFFER_SIZE, getMaxPointsByTimeRange]); // 添加数据点方法 - const appendData = useCallback((data: ITrafficItem) => { - const safeData = { - up: typeof data.up === "number" && !isNaN(data.up) ? data.up : 0, - down: typeof data.down === "number" && !isNaN(data.down) ? data.down : 0, - }; + const appendData = useCallback( + (data: ITrafficItem) => { + const safeData = { + up: typeof data.up === "number" && !isNaN(data.up) ? data.up : 0, + down: + typeof data.down === "number" && !isNaN(data.down) ? data.down : 0, + }; - const timestamp = data.timestamp || Date.now(); - const date = new Date(timestamp); + const timestamp = data.timestamp || Date.now(); + const date = new Date(timestamp); - let nameValue: string; - try { - if (isNaN(date.getTime())) { - console.warn(`appendData: Invalid date for timestamp ${timestamp}`); - nameValue = "??:??:??"; - } else { - nameValue = date.toLocaleTimeString("en-US", { - hour12: false, - hour: "2-digit", - minute: "2-digit", - second: "2-digit", - }); + let nameValue: string; + try { + if (isNaN(date.getTime())) { + console.warn(`appendData: Invalid date for timestamp ${timestamp}`); + nameValue = "??:??:??"; + } else { + nameValue = date.toLocaleTimeString("en-US", { + hour12: false, + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + }); + } + } catch (e) { + console.error( + "Error in toLocaleTimeString in appendData:", + e, + "Date:", + date, + "Timestamp:", + timestamp, + ); + nameValue = "Err:Time"; } - } catch (e) { - console.error("Error in toLocaleTimeString in appendData:", e, "Date:", date, "Timestamp:", timestamp); - nameValue = "Err:Time"; - } - // 带时间标签的新数据点 - const newPoint: DataPoint = { - ...safeData, - name: nameValue, - timestamp: timestamp, - }; + // 带时间标签的新数据点 + const newPoint: DataPoint = { + ...safeData, + name: nameValue, + timestamp: timestamp, + }; - const newBuffer = [...dataBufferRef.current.slice(1), newPoint]; - dataBufferRef.current = newBuffer; + const newBuffer = [...dataBufferRef.current.slice(1), newPoint]; + dataBufferRef.current = newBuffer; - const pointsToShow = getMaxPointsByTimeRange(timeRange); - setDisplayData(newBuffer.slice(-pointsToShow)); - }, [timeRange, getMaxPointsByTimeRange]); + const pointsToShow = getMaxPointsByTimeRange(timeRange); + setDisplayData(newBuffer.slice(-pointsToShow)); + }, + [timeRange, getMaxPointsByTimeRange], + ); // 监听时间范围变化 useEffect(() => { @@ -202,7 +227,7 @@ export const EnhancedTrafficGraph = memo(forwardRef( // 切换图表样式 const toggleStyle = useCallback(() => { - setChartStyle((prev) => prev === "line" ? "area" : "line"); + setChartStyle((prev) => (prev === "line" ? "area" : "line")); }, []); // 暴露方法给父组件 @@ -212,30 +237,31 @@ export const EnhancedTrafficGraph = memo(forwardRef( appendData, toggleStyle, }), - [appendData, toggleStyle] + [appendData, toggleStyle], ); - const formatYAxis = useCallback((value: number | string): string => { - if (typeof value !== 'number') return String(value); + if (typeof value !== "number") return String(value); const [num, unit] = parseTraffic(value); return `${num}${unit}`; }, []); - const formatXLabel = useCallback((tickValue: string | number, index: number, ticks: any[]) => { - const dataPoint = displayData[index as number]; - if (dataPoint && dataPoint.name) { - const parts = dataPoint.name.split(":"); - return `${parts[0]}:${parts[1]}`; - } - if(typeof tickValue === 'string') { - const parts = tickValue.split(":"); - if (parts.length >= 2) return `${parts[0]}:${parts[1]}`; - return tickValue; - } - return ''; - }, [displayData]); - + const formatXLabel = useCallback( + (tickValue: string | number, index: number, ticks: any[]) => { + const dataPoint = displayData[index as number]; + if (dataPoint && dataPoint.name) { + const parts = dataPoint.name.split(":"); + return `${parts[0]}:${parts[1]}`; + } + if (typeof tickValue === "string") { + const parts = tickValue.split(":"); + if (parts.length >= 2) return `${parts[0]}:${parts[1]}`; + return tickValue; + } + return ""; + }, + [displayData], + ); // 获取当前时间范围文本 const getTimeRangeText = useCallback(() => { @@ -243,13 +269,13 @@ export const EnhancedTrafficGraph = memo(forwardRef( }, [timeRange, t]); const chartData = useMemo(() => { - const labels = displayData.map(d => d.name); + const labels = displayData.map((d) => d.name); return { labels, datasets: [ { label: t("Upload"), - data: displayData.map(d => d.up), + data: displayData.map((d) => d.up), borderColor: colors.up, backgroundColor: chartStyle === "area" ? colors.up : colors.up, fill: chartStyle === "area", @@ -260,7 +286,7 @@ export const EnhancedTrafficGraph = memo(forwardRef( }, { label: t("Download"), - data: displayData.map(d => d.down), + data: displayData.map((d) => d.down), borderColor: colors.down, backgroundColor: chartStyle === "area" ? colors.down : colors.down, fill: chartStyle === "area", @@ -268,113 +294,130 @@ export const EnhancedTrafficGraph = memo(forwardRef( pointRadius: 0, pointHoverRadius: 4, borderWidth: 2, - } - ] + }, + ], }; }, [displayData, colors.up, colors.down, t, chartStyle]); - const chartOptions = useMemo(() => ({ - responsive: true, - maintainAspectRatio: false, - animation: false as false, - scales: { - x: { - display: true, - type: 'category' as const, - labels: displayData.map(d => d.name), - ticks: { + const chartOptions = useMemo( + () => ({ + responsive: true, + maintainAspectRatio: false, + animation: false as false, + scales: { + x: { display: true, - color: colors.text, - font: { size: 10 }, - callback: function(this: Scale, tickValue: string | number, index: number, ticks: Tick[]): string | undefined { - let labelToFormat: string | undefined = undefined; + type: "category" as const, + labels: displayData.map((d) => d.name), + ticks: { + display: true, + color: colors.text, + font: { size: 10 }, + callback: function ( + this: Scale, + tickValue: string | number, + index: number, + ticks: Tick[], + ): string | undefined { + let labelToFormat: string | undefined = undefined; - const currentDisplayTick = ticks[index]; - if (currentDisplayTick && typeof currentDisplayTick.label === 'string') { - labelToFormat = currentDisplayTick.label; - } else { - const sourceLabels = displayData.map(d => d.name); - if (typeof tickValue === 'number' && tickValue >= 0 && tickValue < sourceLabels.length) { - labelToFormat = sourceLabels[tickValue]; - } else if (typeof tickValue === 'string') { - labelToFormat = tickValue; + const currentDisplayTick = ticks[index]; + if ( + currentDisplayTick && + typeof currentDisplayTick.label === "string" + ) { + labelToFormat = currentDisplayTick.label; + } else { + const sourceLabels = displayData.map((d) => d.name); + if ( + typeof tickValue === "number" && + tickValue >= 0 && + tickValue < sourceLabels.length + ) { + labelToFormat = sourceLabels[tickValue]; + } else if (typeof tickValue === "string") { + labelToFormat = tickValue; + } } - } - if (typeof labelToFormat !== 'string') { - return undefined; - } + if (typeof labelToFormat !== "string") { + return undefined; + } - const parts: string[] = labelToFormat.split(':'); - return parts.length >= 2 ? `${parts[0]}:${parts[1]}` : labelToFormat; + const parts: string[] = labelToFormat.split(":"); + return parts.length >= 2 + ? `${parts[0]}:${parts[1]}` + : labelToFormat; + }, + autoSkip: true, + maxTicksLimit: Math.max( + 5, + Math.floor(displayData.length / (timeRange * 2)), + ), + minRotation: 0, + maxRotation: 0, + }, + grid: { + display: true, + drawOnChartArea: false, + drawTicks: true, + tickLength: 2, + color: colors.text, }, - autoSkip: true, - maxTicksLimit: Math.max(5, Math.floor(displayData.length / (timeRange * 2))), - minRotation: 0, - maxRotation: 0, }, - grid: { - display: true, - drawOnChartArea: false, - drawTicks: true, - tickLength: 2, - color: colors.text, - + y: { + beginAtZero: true, + ticks: { + color: colors.text, + font: { size: 10 }, + callback: formatYAxis, + }, + grid: { + display: true, + drawTicks: true, + tickLength: 3, + color: colors.grid, + }, }, }, - y: { - beginAtZero: true, - ticks: { - color: colors.text, - font: { size: 10 }, - callback: formatYAxis, - }, - grid: { - display: true, - drawTicks: true, - tickLength: 3, - color: colors.grid, - - }, - } - }, - plugins: { - tooltip: { - enabled: true, - mode: 'index' as const, - intersect: false, - backgroundColor: colors.tooltipBg, - titleColor: colors.text, - bodyColor: colors.text, - borderColor: colors.tooltipBorder, - borderWidth: 1, - cornerRadius: 4, - padding: 8, - callbacks: { - title: (tooltipItems: any[]) => { - return `${t("Time")}: ${tooltipItems[0].label}`; + plugins: { + tooltip: { + enabled: true, + mode: "index" as const, + intersect: false, + backgroundColor: colors.tooltipBg, + titleColor: colors.text, + bodyColor: colors.text, + borderColor: colors.tooltipBorder, + borderWidth: 1, + cornerRadius: 4, + padding: 8, + callbacks: { + title: (tooltipItems: any[]) => { + return `${t("Time")}: ${tooltipItems[0].label}`; + }, + label: (context: any): string => { + const label = context.dataset.label || ""; + const value = context.parsed.y; + const [num, unit] = parseTraffic(value); + return `${label}: ${num} ${unit}/s`; + }, }, - label: (context: any): string => { - const label = context.dataset.label || ''; - const value = context.parsed.y; - const [num, unit] = parseTraffic(value); - return `${label}: ${num} ${unit}/s`; - } - } + }, + legend: { + display: false, + }, }, - legend: { - display: false - } - }, - layout: { - padding: { - top: 16, - right: 7, - left: 3, - } - } - }), [colors, t, formatYAxis, timeRange, displayData]); - + layout: { + padding: { + top: 16, + right: 7, + left: 3, + }, + }, + }), + [colors, t, formatYAxis, timeRange, displayData], + ); return ( ( {displayData.length > 0 && ( )} - - + + ( fontSize={11} fontWeight="bold" onClick={handleTimeRangeClick} - style={{ cursor: "pointer", pointerEvents: 'all' }} + style={{ cursor: "pointer", pointerEvents: "all" }} > {getTimeRangeText()} - + ( fontSize={12} fontWeight="bold" onClick={handleToggleStyleClick} - style={{ cursor: "pointer", pointerEvents: 'all' }} + style={{ cursor: "pointer", pointerEvents: "all" }} > {t("Upload")} @@ -428,7 +480,7 @@ export const EnhancedTrafficGraph = memo(forwardRef( fontSize={12} fontWeight="bold" onClick={handleToggleStyleClick} - style={{ cursor: "pointer", pointerEvents: 'all' }} + style={{ cursor: "pointer", pointerEvents: "all" }} > {t("Download")} @@ -436,7 +488,7 @@ export const EnhancedTrafficGraph = memo(forwardRef( ); - }, -)); + }), +); EnhancedTrafficGraph.displayName = "EnhancedTrafficGraph"; diff --git a/clash-verge-rev/src/components/home/enhanced-traffic-stats.tsx b/clash-verge-rev/src/components/home/enhanced-traffic-stats.tsx index 81cc065ec1..29999f31c8 100644 --- a/clash-verge-rev/src/components/home/enhanced-traffic-stats.tsx +++ b/clash-verge-rev/src/components/home/enhanced-traffic-stats.tsx @@ -66,85 +66,90 @@ const CONNECTIONS_UPDATE_INTERVAL = 5000; // 5秒更新一次连接数据 const THROTTLE_TRAFFIC_UPDATE = 500; // 500ms节流流量数据更新 // 统计卡片组件 - 使用memo优化 -const CompactStatCard = memo(({ - icon, - title, - value, - unit, - color, - onClick, -}: StatCardProps) => { - const theme = useTheme(); +const CompactStatCard = memo( + ({ icon, title, value, unit, color, onClick }: StatCardProps) => { + const theme = useTheme(); - // 获取调色板颜色 - 使用useMemo避免重复计算 - const colorValue = useMemo(() => { - const palette = theme.palette; - if ( - color in palette && - palette[color as keyof typeof palette] && - "main" in (palette[color as keyof typeof palette] as PaletteColor) - ) { - return (palette[color as keyof typeof palette] as PaletteColor).main; - } - return palette.primary.main; - }, [theme.palette, color]); + // 获取调色板颜色 - 使用useMemo避免重复计算 + const colorValue = useMemo(() => { + const palette = theme.palette; + if ( + color in palette && + palette[color as keyof typeof palette] && + "main" in (palette[color as keyof typeof palette] as PaletteColor) + ) { + return (palette[color as keyof typeof palette] as PaletteColor).main; + } + return palette.primary.main; + }, [theme.palette, color]); - return ( - - {/* 图标容器 */} - - {icon} - - - {/* 文本内容 */} - - - {title} - - - - {value} - - - {unit} - + {/* 图标容器 */} + + {icon} - - - ); -}); + + {/* 文本内容 */} + + + {title} + + + + {value} + + + {unit} + + + + + ); + }, +); // 添加显示名称 CompactStatCard.displayName = "CompactStatCard"; @@ -205,25 +210,25 @@ export const EnhancedTrafficStats = () => { down: data.down, timestamp: now, }); - } catch { } + } catch {} return; } lastUpdateRef.current.traffic = now; const safeUp = isNaN(data.up) ? 0 : data.up; const safeDown = isNaN(data.down) ? 0 : data.down; try { - setStats(prev => ({ + setStats((prev) => ({ ...prev, - traffic: { up: safeUp, down: safeDown } + traffic: { up: safeUp, down: safeDown }, })); - } catch { } + } catch {} try { trafficRef.current?.appendData({ up: safeUp, down: safeDown, timestamp: now, }); - } catch { } + } catch {} } } catch (err) { console.error("[Traffic] 解析数据错误:", err, event.data); @@ -235,12 +240,12 @@ export const EnhancedTrafficStats = () => { try { const data = JSON.parse(event.data) as MemoryUsage; if (data && typeof data.inuse === "number") { - setStats(prev => ({ + setStats((prev) => ({ ...prev, memory: { inuse: isNaN(data.inuse) ? 0 : data.inuse, oslimit: data.oslimit, - } + }, })); } } catch (err) { @@ -257,7 +262,7 @@ export const EnhancedTrafficStats = () => { // 清理现有连接的函数 const cleanupSockets = () => { - Object.values(socketRefs.current).forEach(socket => { + Object.values(socketRefs.current).forEach((socket) => { if (socket) { socket.close(); } @@ -269,40 +274,78 @@ export const EnhancedTrafficStats = () => { cleanupSockets(); // 创建新连接 - console.log(`[Traffic][${EnhancedTrafficStats.name}] 正在连接: ${server}/traffic`); - socketRefs.current.traffic = createAuthSockette(`${server}/traffic`, secret, { - onmessage: handleTrafficUpdate, - onopen: (event) => { - console.log(`[Traffic][${EnhancedTrafficStats.name}] WebSocket 连接已建立`, event); + console.log( + `[Traffic][${EnhancedTrafficStats.name}] 正在连接: ${server}/traffic`, + ); + socketRefs.current.traffic = createAuthSockette( + `${server}/traffic`, + secret, + { + onmessage: handleTrafficUpdate, + onopen: (event) => { + console.log( + `[Traffic][${EnhancedTrafficStats.name}] WebSocket 连接已建立`, + event, + ); + }, + onerror: (event) => { + console.error( + `[Traffic][${EnhancedTrafficStats.name}] WebSocket 连接错误或达到最大重试次数`, + event, + ); + setStats((prev) => ({ ...prev, traffic: { up: 0, down: 0 } })); + }, + onclose: (event) => { + console.log( + `[Traffic][${EnhancedTrafficStats.name}] WebSocket 连接关闭`, + event.code, + event.reason, + ); + if (event.code !== 1000 && event.code !== 1001) { + console.warn( + `[Traffic][${EnhancedTrafficStats.name}] 连接非正常关闭,重置状态`, + ); + setStats((prev) => ({ ...prev, traffic: { up: 0, down: 0 } })); + } + }, }, - onerror: (event) => { - console.error(`[Traffic][${EnhancedTrafficStats.name}] WebSocket 连接错误或达到最大重试次数`, event); - setStats(prev => ({ ...prev, traffic: { up: 0, down: 0 } })); - }, - onclose: (event) => { - console.log(`[Traffic][${EnhancedTrafficStats.name}] WebSocket 连接关闭`, event.code, event.reason); - if (event.code !== 1000 && event.code !== 1001) { - console.warn(`[Traffic][${EnhancedTrafficStats.name}] 连接非正常关闭,重置状态`); - setStats(prev => ({ ...prev, traffic: { up: 0, down: 0 } })); - } - }, - }); + ); - console.log(`[Memory][${EnhancedTrafficStats.name}] 正在连接: ${server}/memory`); + console.log( + `[Memory][${EnhancedTrafficStats.name}] 正在连接: ${server}/memory`, + ); socketRefs.current.memory = createAuthSockette(`${server}/memory`, secret, { onmessage: handleMemoryUpdate, onopen: (event) => { - console.log(`[Memory][${EnhancedTrafficStats.name}] WebSocket 连接已建立`, event); + console.log( + `[Memory][${EnhancedTrafficStats.name}] WebSocket 连接已建立`, + event, + ); }, onerror: (event) => { - console.error(`[Memory][${EnhancedTrafficStats.name}] WebSocket 连接错误或达到最大重试次数`, event); - setStats(prev => ({ ...prev, memory: { inuse: 0, oslimit: undefined } })); + console.error( + `[Memory][${EnhancedTrafficStats.name}] WebSocket 连接错误或达到最大重试次数`, + event, + ); + setStats((prev) => ({ + ...prev, + memory: { inuse: 0, oslimit: undefined }, + })); }, onclose: (event) => { - console.log(`[Memory][${EnhancedTrafficStats.name}] WebSocket 连接关闭`, event.code, event.reason); + console.log( + `[Memory][${EnhancedTrafficStats.name}] WebSocket 连接关闭`, + event.code, + event.reason, + ); if (event.code !== 1000 && event.code !== 1001) { - console.warn(`[Memory][${EnhancedTrafficStats.name}] 连接非正常关闭,重置状态`); - setStats(prev => ({ ...prev, memory: { inuse: 0, oslimit: undefined } })); + console.warn( + `[Memory][${EnhancedTrafficStats.name}] 连接非正常关闭,重置状态`, + ); + setStats((prev) => ({ + ...prev, + memory: { inuse: 0, oslimit: undefined }, + })); } }, }); @@ -314,11 +357,11 @@ export const EnhancedTrafficStats = () => { useEffect(() => { return () => { try { - Object.values(socketRefs.current).forEach(socket => { + Object.values(socketRefs.current).forEach((socket) => { if (socket) socket.close(); }); socketRefs.current = { traffic: null, memory: null }; - } catch { } + } catch {} }; }, []); @@ -339,13 +382,25 @@ export const EnhancedTrafficStats = () => { const [up, upUnit] = parseTraffic(stats.traffic.up); const [down, downUnit] = parseTraffic(stats.traffic.down); const [inuse, inuseUnit] = parseTraffic(stats.memory.inuse); - const [uploadTotal, uploadTotalUnit] = parseTraffic(connections.uploadTotal); - const [downloadTotal, downloadTotalUnit] = parseTraffic(connections.downloadTotal); + const [uploadTotal, uploadTotalUnit] = parseTraffic( + connections.uploadTotal, + ); + const [downloadTotal, downloadTotalUnit] = parseTraffic( + connections.downloadTotal, + ); return { - up, upUnit, down, downUnit, inuse, inuseUnit, - uploadTotal, uploadTotalUnit, downloadTotal, downloadTotalUnit, - connectionsCount: connections.count + up, + upUnit, + down, + downUnit, + inuse, + inuseUnit, + uploadTotal, + uploadTotalUnit, + downloadTotal, + downloadTotalUnit, + connectionsCount: connections.count, }; }, [stats, connections]); @@ -392,51 +447,54 @@ export const EnhancedTrafficStats = () => { }, [trafficGraph, pageVisible, theme.palette.divider, isDebug]); // 使用useMemo计算统计卡片配置 - const statCards = useMemo(() => [ - { - icon: , - title: t("Upload Speed"), - value: parsedData.up, - unit: `${parsedData.upUnit}/s`, - color: "secondary" as const, - }, - { - icon: , - title: t("Download Speed"), - value: parsedData.down, - unit: `${parsedData.downUnit}/s`, - color: "primary" as const, - }, - { - icon: , - title: t("Active Connections"), - value: parsedData.connectionsCount, - unit: "", - color: "success" as const, - }, - { - icon: , - title: t("Uploaded"), - value: parsedData.uploadTotal, - unit: parsedData.uploadTotalUnit, - color: "secondary" as const, - }, - { - icon: , - title: t("Downloaded"), - value: parsedData.downloadTotal, - unit: parsedData.downloadTotalUnit, - color: "primary" as const, - }, - { - icon: , - title: t("Memory Usage"), - value: parsedData.inuse, - unit: parsedData.inuseUnit, - color: "error" as const, - onClick: isDebug ? handleGarbageCollection : undefined, - }, - ], [t, parsedData, isDebug, handleGarbageCollection]); + const statCards = useMemo( + () => [ + { + icon: , + title: t("Upload Speed"), + value: parsedData.up, + unit: `${parsedData.upUnit}/s`, + color: "secondary" as const, + }, + { + icon: , + title: t("Download Speed"), + value: parsedData.down, + unit: `${parsedData.downUnit}/s`, + color: "primary" as const, + }, + { + icon: , + title: t("Active Connections"), + value: parsedData.connectionsCount, + unit: "", + color: "success" as const, + }, + { + icon: , + title: t("Uploaded"), + value: parsedData.uploadTotal, + unit: parsedData.uploadTotalUnit, + color: "secondary" as const, + }, + { + icon: , + title: t("Downloaded"), + value: parsedData.downloadTotal, + unit: parsedData.downloadTotalUnit, + color: "primary" as const, + }, + { + icon: , + title: t("Memory Usage"), + value: parsedData.inuse, + unit: parsedData.inuseUnit, + color: "error" as const, + onClick: isDebug ? handleGarbageCollection : undefined, + }, + ], + [t, parsedData, isDebug, handleGarbageCollection], + ); return ( diff --git a/clash-verge-rev/src/components/home/home-profile-card.tsx b/clash-verge-rev/src/components/home/home-profile-card.tsx index 1762002d44..8a02d1c834 100644 --- a/clash-verge-rev/src/components/home/home-profile-card.tsx +++ b/clash-verge-rev/src/components/home/home-profile-card.tsx @@ -78,12 +78,16 @@ const truncateStyle = { maxWidth: "calc(100% - 28px)", overflow: "hidden", textOverflow: "ellipsis", - whiteSpace: "nowrap" + whiteSpace: "nowrap", }; // 提取独立组件减少主组件复杂度 -const ProfileDetails = ({ current, onUpdateProfile, updating }: { - current: ProfileItem; +const ProfileDetails = ({ + current, + onUpdateProfile, + updating, +}: { + current: ProfileItem; onUpdateProfile: () => void; updating: boolean; }) => { @@ -99,7 +103,7 @@ const ProfileDetails = ({ current, onUpdateProfile, updating }: { if (!current.extra || !current.extra.total) return 1; return Math.min( Math.round((usedTraffic * 100) / (current.extra.total + 0.01)) + 1, - 100 + 100, ); }, [current.extra, usedTraffic]); @@ -109,19 +113,24 @@ const ProfileDetails = ({ current, onUpdateProfile, updating }: { {current.url && ( - + {t("From")}: {current.home ? ( current.home && openWebUrl(current.home)} - sx={{ + sx={{ display: "inline-flex", alignItems: "center", minWidth: 0, maxWidth: "calc(100% - 40px)", - ml: 0.5 + ml: 0.5, }} title={parseUrl(current.url)} > @@ -132,14 +141,19 @@ const ProfileDetails = ({ current, onUpdateProfile, updating }: { textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0, - flex: 1 + flex: 1, }} > {parseUrl(current.url)} ) : ( @@ -152,7 +166,7 @@ const ProfileDetails = ({ current, onUpdateProfile, updating }: { whiteSpace: "nowrap", minWidth: 0, flex: 1, - ml: 0.5 + ml: 0.5, }} title={parseUrl(current.url)} > @@ -195,7 +209,8 @@ const ProfileDetails = ({ current, onUpdateProfile, updating }: { {t("Used / Total")}:{" "} - {parseTraffic(usedTraffic)} / {parseTraffic(current.extra.total)} + {parseTraffic(usedTraffic)} /{" "} + {parseTraffic(current.extra.total)} @@ -240,7 +255,7 @@ const ProfileDetails = ({ current, onUpdateProfile, updating }: { // 提取空配置组件 const EmptyProfile = ({ onClick }: { onClick: () => void }) => { const { t } = useTranslation(); - + return ( void }) => { ); }; -export const HomeProfileCard = ({ current, onProfileUpdated }: HomeProfileCardProps) => { +export const HomeProfileCard = ({ + current, + onProfileUpdated, +}: HomeProfileCardProps) => { const { t } = useTranslation(); const navigate = useNavigate(); const { refreshAll } = useAppData(); // 更新当前订阅 const [updating, setUpdating] = useState(false); - + const onUpdateProfile = useLockFn(async () => { if (!current?.uid) return; setUpdating(true); try { await updateProfile(current.uid, current.option); - showNotice('success', t("Update subscription successfully"), 1000); + showNotice("success", t("Update subscription successfully"), 1000); onProfileUpdated?.(); - + // 刷新首页数据 refreshAll(); } catch (err: any) { - showNotice('error', err.message || err.toString(), 3000); + showNotice("error", err.message || err.toString(), 3000); } finally { setUpdating(false); } @@ -302,9 +320,9 @@ export const HomeProfileCard = ({ current, onProfileUpdated }: HomeProfileCardPr // 卡片标题 const cardTitle = useMemo(() => { if (!current) return t("Profiles"); - + if (!current.home) return current.name; - + return ( {current.name} @@ -345,7 +363,7 @@ export const HomeProfileCard = ({ current, onProfileUpdated }: HomeProfileCardPr // 卡片操作按钮 const cardAction = useMemo(() => { if (!current) return null; - + return ( - - + + - + {t("Proxy Provider")} - - + + - + {t("Rule Providers")} - + {Object.entries(ruleProviders || {}).map(([key, item]) => { const provider = item as RuleProviderItem; const time = dayjs(provider.updatedAt); const isUpdating = updating[key]; - + return ( { const bgcolor = mode === "light" ? "#ffffff" : "#24252f"; - const hoverColor = mode === "light" - ? alpha(primary.main, 0.1) - : alpha(primary.main, 0.2); - + const hoverColor = + mode === "light" + ? alpha(primary.main, 0.1) + : alpha(primary.main, 0.2); + return { backgroundColor: bgcolor, "&:hover": { backgroundColor: hoverColor, - borderColor: alpha(primary.main, 0.3) - } + borderColor: alpha(primary.main, 0.3), + }, }; - } + }, ]} > + { title={key} sx={{ display: "flex", alignItems: "center" }} > - {key} + {key} {provider.ruleCount} - - - {t("Update At")}: {time.fromNow()} + + + {t("Update At")}: + {time.fromNow()} } @@ -219,30 +232,32 @@ export const ProviderButton = () => { {provider.vehicleType} - - {provider.behavior} - + {provider.behavior} } /> - + updateProvider(key)} disabled={isUpdating} sx={{ - animation: isUpdating ? "spin 1s linear infinite" : "none", + animation: isUpdating + ? "spin 1s linear infinite" + : "none", "@keyframes spin": { "0%": { transform: "rotate(0deg)" }, - "100%": { transform: "rotate(360deg)" } - } + "100%": { transform: "rotate(360deg)" }, + }, }} title={t("Update Provider") as string} > @@ -254,7 +269,7 @@ export const ProviderButton = () => { })} - +