Optimize DNS strategy

Fix the problem that the tray is not displayed in some cases

Optimize tray

Update core

Fix some error
This commit is contained in:
chen08209
2024-09-05 08:59:45 +08:00
parent 6e5f1b8e5f
commit 846ec9728f
54 changed files with 903 additions and 391 deletions

View File

@@ -4,6 +4,7 @@ import "C"
import ( import (
"context" "context"
"errors" "errors"
route "github.com/metacubex/mihomo/hub/route"
"math" "math"
"os" "os"
"os/exec" "os/exec"
@@ -21,13 +22,11 @@ import (
"github.com/metacubex/mihomo/common/batch" "github.com/metacubex/mihomo/common/batch"
"github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/component/resolver"
"github.com/metacubex/mihomo/component/sniffer"
"github.com/metacubex/mihomo/config" "github.com/metacubex/mihomo/config"
"github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/constant"
cp "github.com/metacubex/mihomo/constant/provider" cp "github.com/metacubex/mihomo/constant/provider"
"github.com/metacubex/mihomo/hub" "github.com/metacubex/mihomo/hub"
"github.com/metacubex/mihomo/hub/executor" "github.com/metacubex/mihomo/hub/executor"
"github.com/metacubex/mihomo/hub/route"
"github.com/metacubex/mihomo/listener" "github.com/metacubex/mihomo/listener"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
rp "github.com/metacubex/mihomo/rules/provider" rp "github.com/metacubex/mihomo/rules/provider"
@@ -191,7 +190,7 @@ func toExternalProvider(p cp.Provider) (*ExternalProvider, error) {
VehicleType: psp.VehicleType().String(), VehicleType: psp.VehicleType().String(),
Count: psp.Count(), Count: psp.Count(),
Path: psp.Vehicle().Path(), Path: psp.Vehicle().Path(),
UpdateAt: psp.UpdatedAt, UpdateAt: psp.UpdatedAt(),
}, nil }, nil
case *rp.RuleSetProvider: case *rp.RuleSetProvider:
rsp := p.(*rp.RuleSetProvider) rsp := p.(*rp.RuleSetProvider)
@@ -201,7 +200,7 @@ func toExternalProvider(p cp.Provider) (*ExternalProvider, error) {
VehicleType: rsp.VehicleType().String(), VehicleType: rsp.VehicleType().String(),
Count: rsp.Count(), Count: rsp.Count(),
Path: rsp.Vehicle().Path(), Path: rsp.Vehicle().Path(),
UpdateAt: rsp.UpdatedAt, UpdateAt: rsp.UpdatedAt(),
}, nil }, nil
default: default:
return nil, errors.New("not external provider") return nil, errors.New("not external provider")
@@ -411,12 +410,13 @@ func overwriteConfig(targetConfig *config.RawConfig, patchConfig config.RawConfi
targetConfig.Profile.StoreSelected = false targetConfig.Profile.StoreSelected = false
targetConfig.GeoXUrl = patchConfig.GeoXUrl targetConfig.GeoXUrl = patchConfig.GeoXUrl
targetConfig.GlobalUA = patchConfig.GlobalUA targetConfig.GlobalUA = patchConfig.GlobalUA
//if targetConfig.DNS.Enable == false {
// targetConfig.DNS = patchConfig.DNS
//}
genHosts(targetConfig.Hosts, patchConfig.Hosts) genHosts(targetConfig.Hosts, patchConfig.Hosts)
if configParams.OverrideDns { if configParams.OverrideDns {
targetConfig.DNS = patchConfig.DNS targetConfig.DNS = patchConfig.DNS
} else {
if targetConfig.DNS.Enable == false {
targetConfig.DNS.Enable = true
}
} }
//if runtime.GOOS == "android" { //if runtime.GOOS == "android" {
// targetConfig.DNS.NameServer = append(targetConfig.DNS.NameServer, "dhcp://"+dns.SystemDNSPlaceholder) // targetConfig.DNS.NameServer = append(targetConfig.DNS.NameServer, "dhcp://"+dns.SystemDNSPlaceholder)
@@ -430,12 +430,10 @@ func overwriteConfig(targetConfig *config.RawConfig, patchConfig config.RawConfi
//} //}
} }
func patchConfig(general *config.General) { func patchConfig(general *config.General, controller *config.Controller) {
log.Infoln("[Apply] patch") log.Infoln("[Apply] patch")
route.ReStartServer(general.ExternalController) route.ReStartServer(controller.ExternalController)
if sniffer.Dispatcher != nil { tunnel.SetSniffing(general.Sniffing)
tunnel.SetSniffing(general.Sniffing)
}
tunnel.SetFindProcessMode(general.FindProcessMode) tunnel.SetFindProcessMode(general.FindProcessMode)
dialer.SetTcpConcurrent(general.TCPConcurrent) dialer.SetTcpConcurrent(general.TCPConcurrent)
dialer.DefaultInterface.Store(general.Interface) dialer.DefaultInterface.Store(general.Interface)
@@ -455,6 +453,7 @@ func updateListeners(general *config.General, listeners map[string]constant.Inbo
} }
runLock.Lock() runLock.Lock()
defer runLock.Unlock() defer runLock.Unlock()
listener.PatchInboundListeners(listeners, tunnel.Tunnel, true) listener.PatchInboundListeners(listeners, tunnel.Tunnel, true)
listener.SetAllowLan(general.AllowLan) listener.SetAllowLan(general.AllowLan)
inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes) inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes)
@@ -464,14 +463,12 @@ func updateListeners(general *config.General, listeners map[string]constant.Inbo
listener.ReCreateHTTP(general.Port, tunnel.Tunnel) listener.ReCreateHTTP(general.Port, tunnel.Tunnel)
listener.ReCreateSocks(general.SocksPort, tunnel.Tunnel) listener.ReCreateSocks(general.SocksPort, tunnel.Tunnel)
listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel) listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel)
listener.ReCreateAutoRedir(general.EBpf.AutoRedir, tunnel.Tunnel)
listener.ReCreateTProxy(general.TProxyPort, tunnel.Tunnel) listener.ReCreateTProxy(general.TProxyPort, tunnel.Tunnel)
listener.ReCreateMixed(general.MixedPort, tunnel.Tunnel) listener.ReCreateMixed(general.MixedPort, tunnel.Tunnel)
listener.ReCreateShadowSocks(general.ShadowSocksConfig, tunnel.Tunnel) listener.ReCreateShadowSocks(general.ShadowSocksConfig, tunnel.Tunnel)
listener.ReCreateVmess(general.VmessConfig, tunnel.Tunnel) listener.ReCreateVmess(general.VmessConfig, tunnel.Tunnel)
listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel) listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel)
listener.ReCreateTun(general.Tun, tunnel.Tunnel) listener.ReCreateTun(general.Tun, tunnel.Tunnel)
listener.ReCreateRedirToTun(general.EBpf.RedirectToTun)
} }
func stopListeners() { func stopListeners() {
@@ -533,7 +530,7 @@ func applyConfig() error {
constant.DefaultTestURL = *configParams.TestURL constant.DefaultTestURL = *configParams.TestURL
} }
if configParams.IsPatch { if configParams.IsPatch {
patchConfig(cfg.General) patchConfig(cfg.General, cfg.Controller)
} else { } else {
closeConnections() closeConnections()
runtime.GC() runtime.GC()
@@ -541,7 +538,9 @@ func applyConfig() error {
patchSelectGroup() patchSelectGroup()
} }
updateListeners(cfg.General, cfg.Listeners) updateListeners(cfg.General, cfg.Listeners)
hcCompatibleProvider(cfg.Providers) if isRunning {
hcCompatibleProvider(cfg.Providers)
}
externalProviders = getExternalProvidersRaw() externalProviders = getExternalProvidersRaw()
return err return err
} }

View File

@@ -7,9 +7,8 @@ replace github.com/metacubex/mihomo => ./Clash.Meta
require ( require (
github.com/Kr328/tun2socket v0.0.0-20220414050025-d07c78d06d34 github.com/Kr328/tun2socket v0.0.0-20220414050025-d07c78d06d34
github.com/metacubex/mihomo v1.17.1 github.com/metacubex/mihomo v1.17.1
github.com/miekg/dns v1.1.61 github.com/miekg/dns v1.1.62
golang.org/x/net v0.26.0 golang.org/x/sync v0.8.0
golang.org/x/sync v0.7.0
) )
require ( require (
@@ -20,17 +19,16 @@ require (
github.com/andybalholm/brotli v1.0.6 // indirect github.com/andybalholm/brotli v1.0.6 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect
github.com/cilium/ebpf v0.12.3 // indirect
github.com/cloudflare/circl v1.3.7 // indirect github.com/cloudflare/circl v1.3.7 // indirect
github.com/coreos/go-iptables v0.7.0 // indirect github.com/coreos/go-iptables v0.7.0 // indirect
github.com/dlclark/regexp2 v1.11.0 // indirect github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 // indirect github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 // indirect
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gaukas/godicttls v0.0.4 // indirect github.com/gaukas/godicttls v0.0.4 // indirect
github.com/go-chi/chi/v5 v5.0.14 // indirect github.com/go-chi/chi/v5 v5.1.0 // indirect
github.com/go-chi/cors v1.2.1 // indirect github.com/go-chi/cors v1.2.1 // indirect
github.com/go-chi/render v1.0.3 // indirect github.com/go-chi/render v1.0.3 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
@@ -38,12 +36,12 @@ require (
github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.4.0 // indirect github.com/gobwas/ws v1.4.0 // indirect
github.com/gofrs/uuid/v5 v5.2.0 // indirect github.com/gofrs/uuid/v5 v5.3.0 // indirect
github.com/google/btree v1.1.2 // indirect github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect
github.com/insomniacslk/dhcp v0.0.0-20240529192340-51bc6136a0a6 // indirect github.com/insomniacslk/dhcp v0.0.0-20240812123929-b105c29bd1b5 // indirect
github.com/josharian/native v1.1.0 // indirect github.com/josharian/native v1.1.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect
@@ -52,18 +50,19 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/netlink v1.7.2 // indirect
github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/socket v0.4.1 // indirect
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 // indirect
github.com/metacubex/chacha v0.1.0 // indirect github.com/metacubex/chacha v0.1.0 // indirect
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec // indirect github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec // indirect
github.com/metacubex/quic-go v0.45.1-0.20240610004319-163fee60637e // indirect github.com/metacubex/quic-go v0.46.1-0.20240807232329-1c6cb2d67f58 // indirect
github.com/metacubex/randv2 v0.2.0 // indirect github.com/metacubex/randv2 v0.2.0 // indirect
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 // indirect github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 // indirect
github.com/metacubex/sing-shadowsocks v0.2.7 // indirect github.com/metacubex/sing-shadowsocks v0.2.8 // indirect
github.com/metacubex/sing-shadowsocks2 v0.2.1 // indirect github.com/metacubex/sing-shadowsocks2 v0.2.2 // indirect
github.com/metacubex/sing-tun v0.2.7-0.20240719141246-19c49ac9589d // indirect github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1 // indirect
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 // indirect github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 // indirect
github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a // indirect github.com/metacubex/sing-wireguard v0.0.0-20240826061955-1e4e67afe5cd // indirect
github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66 // indirect github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785 // indirect
github.com/metacubex/utls v1.6.6 // indirect github.com/metacubex/utls v1.6.6 // indirect
github.com/mroth/weightedrand/v2 v2.1.0 // indirect github.com/mroth/weightedrand/v2 v2.1.0 // indirect
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
@@ -72,10 +71,9 @@ require (
github.com/oschwald/maxminddb-golang v1.12.0 // indirect github.com/oschwald/maxminddb-golang v1.12.0 // indirect
github.com/pierrec/lz4/v4 v4.1.14 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/puzpuzpuz/xsync/v3 v3.2.0 // indirect github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect
github.com/sagernet/fswatch v0.1.1 // indirect github.com/sagernet/fswatch v0.1.1 // indirect
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
github.com/sagernet/nftables v0.3.0-beta.4 // indirect github.com/sagernet/nftables v0.3.0-beta.4 // indirect
@@ -84,7 +82,7 @@ require (
github.com/sagernet/sing-shadowtls v0.1.4 // indirect github.com/sagernet/sing-shadowtls v0.1.4 // indirect
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
github.com/sagernet/wireguard-go v0.0.0-20231209092712-9a439356a62e // indirect github.com/sagernet/wireguard-go v0.0.0-20231209092712-9a439356a62e // indirect
github.com/samber/lo v1.39.0 // indirect github.com/samber/lo v1.47.0 // indirect
github.com/shirou/gopsutil/v3 v3.24.5 // indirect github.com/shirou/gopsutil/v3 v3.24.5 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
@@ -101,13 +99,14 @@ require (
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
go.uber.org/mock v0.4.0 // indirect go.uber.org/mock v0.4.0 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/crypto v0.24.0 // indirect golang.org/x/crypto v0.26.0 // indirect
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
golang.org/x/mod v0.18.0 // indirect golang.org/x/mod v0.20.0 // indirect
golang.org/x/sys v0.22.0 // indirect golang.org/x/net v0.28.0 // indirect
golang.org/x/text v0.16.0 // indirect golang.org/x/sys v0.24.0 // indirect
golang.org/x/text v0.17.0 // indirect
golang.org/x/time v0.5.0 // indirect golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.22.0 // indirect golang.org/x/tools v0.24.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.3.0 // indirect lukechampine.com/blake3 v1.3.0 // indirect

View File

@@ -19,8 +19,6 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4=
github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8= github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8=
@@ -28,8 +26,8 @@ github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFE
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8= github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8=
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I= github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I=
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g= github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
@@ -40,14 +38,12 @@ github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 h1:tlDMEdcPRQKBE
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4= github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4=
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA= github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA=
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010/go.mod h1:JtBcj7sBuTTRupn7c2bFspMDIObMJsVK8TeUvpShPok= github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010/go.mod h1:JtBcj7sBuTTRupn7c2bFspMDIObMJsVK8TeUvpShPok=
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/go-chi/chi/v5 v5.0.14 h1:PyEwo2Vudraa0x/Wl6eDRRW2NXBvekgfxyydcM0WGE0= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.0.14/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
@@ -65,8 +61,8 @@ github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs= github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs=
github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc= github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc=
github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM= github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
@@ -82,8 +78,8 @@ github.com/google/tink/go v1.6.1/go.mod h1:IGW53kTgag+st5yPhKKwJ6u2l+SSp5/v9XF7s
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/insomniacslk/dhcp v0.0.0-20240529192340-51bc6136a0a6 h1:dh8D8FksyMhD64mRMbUhZHWYJfNoNMCxfVq6eexleMw= github.com/insomniacslk/dhcp v0.0.0-20240812123929-b105c29bd1b5 h1:GkMacU5ftc+IEg1449N3UEy2XLDz58W4fkrRu2fibb8=
github.com/insomniacslk/dhcp v0.0.0-20240529192340-51bc6136a0a6/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic= github.com/insomniacslk/dhcp v0.0.0-20240812123929-b105c29bd1b5/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
@@ -92,10 +88,6 @@ github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
@@ -106,34 +98,36 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 h1:oBowHVKZycNtAFbZ6avaCSZJYeme2Nrj+4RpV2cNJig=
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399/go.mod h1:4xcieuIK+M4bGQmQYZVqEaIYqjS1ahO4kXG7EmDgEro=
github.com/metacubex/chacha v0.1.0 h1:tg9RSJ18NvL38cCWNyYH1eiG6qDCyyXIaTLQthon0sc= github.com/metacubex/chacha v0.1.0 h1:tg9RSJ18NvL38cCWNyYH1eiG6qDCyyXIaTLQthon0sc=
github.com/metacubex/chacha v0.1.0/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8= github.com/metacubex/chacha v0.1.0/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI=
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc=
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw=
github.com/metacubex/quic-go v0.45.1-0.20240610004319-163fee60637e h1:bLYn3GuRvWDcBDAkIv5kUYIhzHwafDVq635BuybnKqI= github.com/metacubex/quic-go v0.46.1-0.20240807232329-1c6cb2d67f58 h1:T6OxROLZBr9SOQxN5TzUslv81hEREy/dEgaUKVjaG7U=
github.com/metacubex/quic-go v0.45.1-0.20240610004319-163fee60637e/go.mod h1:Yza2H7Ax1rxWPUcJx0vW+oAt9EsPuSiyQFhFabUPzwU= github.com/metacubex/quic-go v0.46.1-0.20240807232329-1c6cb2d67f58/go.mod h1:Yza2H7Ax1rxWPUcJx0vW+oAt9EsPuSiyQFhFabUPzwU=
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 h1:Wr4g1HCb5Z/QIFwFiVNjO2qL+dRu25+Mdn9xtAZZ+ew= github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 h1:HobpULaPK6OoxrHMmgcwLkwwIduXVmwdcznwUfH1GQM=
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8= github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8=
github.com/metacubex/sing-shadowsocks v0.2.7 h1:9f3Dt2+71TNp0e202llA2ug5h/rkWs2EZxQ5IMpf+9g= github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4=
github.com/metacubex/sing-shadowsocks v0.2.7/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0= github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0=
github.com/metacubex/sing-shadowsocks2 v0.2.1 h1:XIZBXlazp8EEoPp1S0DViAhLkJakjQ2f+AOwwdKKNYg= github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo=
github.com/metacubex/sing-shadowsocks2 v0.2.1/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q= github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q=
github.com/metacubex/sing-tun v0.2.7-0.20240719141246-19c49ac9589d h1:iYlepjRCYlPXtELupDL+pQjGqkCnQz4KQOfKImP9sog= github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1 h1:ypfofGDZbP8p3Y4P/m74JYu7sQViesi3c8nbmT6cS0Y=
github.com/metacubex/sing-tun v0.2.7-0.20240719141246-19c49ac9589d/go.mod h1:olbEx9yVcaw5tHTNlRamRoxmMKcvDvcVS1YLnQGzvWE= github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1/go.mod h1:olbEx9yVcaw5tHTNlRamRoxmMKcvDvcVS1YLnQGzvWE=
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 h1:OAXiCosqY8xKDp3pqTW3qbrCprZ1l6WkrXSFSCwyY4I= github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 h1:OAXiCosqY8xKDp3pqTW3qbrCprZ1l6WkrXSFSCwyY4I=
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY= github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY=
github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a h1:NpSGclHJUYndUwBmyIpFBSoBVg8PoVX7QQKhYg0DjM0= github.com/metacubex/sing-wireguard v0.0.0-20240826061955-1e4e67afe5cd h1:r7alry8u4qlUFLNMwGvG1A8ZcfPM6AMSmrm6E2yKdB4=
github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a/go.mod h1:uY+BYb0UEknLrqvbGcwi9i++KgrKxsurysgI6G1Pveo= github.com/metacubex/sing-wireguard v0.0.0-20240826061955-1e4e67afe5cd/go.mod h1:uY+BYb0UEknLrqvbGcwi9i++KgrKxsurysgI6G1Pveo=
github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66 h1:as/aO/fM8nv4W4pOr9EETP6kV/Oaujk3fUNyQSJK61c= github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785 h1:NNmI+ZV0DzNuqaAInRQuZFLHlWVuyHeow8jYpdKjHjo=
github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts= github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts=
github.com/metacubex/utls v1.6.6 h1:3D12YKHTf2Z41UPhQU2dWerNWJ5TVQD9gKoQ+H+iLC8= github.com/metacubex/utls v1.6.6 h1:3D12YKHTf2Z41UPhQU2dWerNWJ5TVQD9gKoQ+H+iLC8=
github.com/metacubex/utls v1.6.6/go.mod h1:+WLFUnXjcpdxXCnyX25nggw8C6YonZ8zOK2Zm/oRvdo= github.com/metacubex/utls v1.6.6/go.mod h1:+WLFUnXjcpdxXCnyX25nggw8C6YonZ8zOK2Zm/oRvdo=
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd5E/OeU= github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd5E/OeU=
github.com/mroth/weightedrand/v2 v2.1.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU= github.com/mroth/weightedrand/v2 v2.1.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU=
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 h1:1102pQc2SEPp5+xrS26wEaeb26sZy6k9/ZXlZN+eXE4= github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 h1:1102pQc2SEPp5+xrS26wEaeb26sZy6k9/ZXlZN+eXE4=
@@ -156,16 +150,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/puzpuzpuz/xsync/v3 v3.2.0 h1:9AzuUeF88YC5bK8u2vEG1Fpvu4wgpM1wfPIExfaaDxQ= github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4=
github.com/puzpuzpuz/xsync/v3 v3.2.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs= github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
@@ -183,8 +173,8 @@ github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxe
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
github.com/sagernet/wireguard-go v0.0.0-20231209092712-9a439356a62e h1:iGH0RMv2FzELOFNFQtvsxH7NPmlo7X5JizEK51UCojo= github.com/sagernet/wireguard-go v0.0.0-20231209092712-9a439356a62e h1:iGH0RMv2FzELOFNFQtvsxH7NPmlo7X5JizEK51UCojo=
github.com/sagernet/wireguard-go v0.0.0-20231209092712-9a439356a62e/go.mod h1:YbL4TKHRR6APYQv3U2RGfwLDpPYSyWz6oUlpISBEzBE= github.com/sagernet/wireguard-go v0.0.0-20231209092712-9a439356a62e/go.mod h1:YbL4TKHRR6APYQv3U2RGfwLDpPYSyWz6oUlpISBEzBE=
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
@@ -230,21 +220,21 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -261,18 +251,18 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=

View File

@@ -5,9 +5,11 @@ package main
*/ */
import "C" import "C"
import ( import (
"context"
bridge "core/dart-bridge" bridge "core/dart-bridge"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/metacubex/mihomo/common/utils"
"os" "os"
"runtime" "runtime"
"sort" "sort"
@@ -18,7 +20,6 @@ import (
"github.com/metacubex/mihomo/adapter" "github.com/metacubex/mihomo/adapter"
"github.com/metacubex/mihomo/adapter/outboundgroup" "github.com/metacubex/mihomo/adapter/outboundgroup"
"github.com/metacubex/mihomo/adapter/provider" "github.com/metacubex/mihomo/adapter/provider"
"github.com/metacubex/mihomo/common/utils"
"github.com/metacubex/mihomo/component/updater" "github.com/metacubex/mihomo/component/updater"
"github.com/metacubex/mihomo/config" "github.com/metacubex/mihomo/config"
"github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/constant"
@@ -27,7 +28,6 @@ import (
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/tunnel"
"github.com/metacubex/mihomo/tunnel/statistic" "github.com/metacubex/mihomo/tunnel/statistic"
"golang.org/x/net/context"
) )
var currentRawConfig = config.DefaultRawConfig() var currentRawConfig = config.DefaultRawConfig()
@@ -225,11 +225,13 @@ func asyncTestDelay(s *C.char, port C.longlong) {
var params = &TestDelayParams{} var params = &TestDelayParams{}
err := json.Unmarshal([]byte(paramsString), params) err := json.Unmarshal([]byte(paramsString), params)
if err != nil { if err != nil {
bridge.SendToPort(i, "")
return false, nil return false, nil
} }
expectedStatus, err := utils.NewUnsignedRanges[uint16]("") expectedStatus, err := utils.NewUnsignedRanges[uint16]("")
if err != nil { if err != nil {
bridge.SendToPort(i, "")
return false, nil return false, nil
} }
@@ -238,7 +240,6 @@ func asyncTestDelay(s *C.char, port C.longlong) {
proxies := tunnel.ProxiesWithProviders() proxies := tunnel.ProxiesWithProviders()
proxy := proxies[params.ProxyName] proxy := proxies[params.ProxyName]
proxy.Name()
delayData := &Delay{ delayData := &Delay{
Name: params.ProxyName, Name: params.ProxyName,

View File

@@ -158,7 +158,9 @@ class ApplicationState extends State<Application> {
GlobalWidgetsLocalizations.delegate GlobalWidgetsLocalizations.delegate
], ],
builder: (_, child) { builder: (_, child) {
return _buildPage(child!); return MediaContainer(
child: _buildPage(child!),
);
}, },
scrollBehavior: BaseScrollBehavior(), scrollBehavior: BaseScrollBehavior(),
title: appName, title: appName,

View File

@@ -8,6 +8,7 @@ import 'package:webdav_client/webdav_client.dart';
class DAVClient { class DAVClient {
late Client client; late Client client;
Completer<bool> pingCompleter = Completer(); Completer<bool> pingCompleter = Completer();
late String fileName;
DAVClient(DAV dav) { DAVClient(DAV dav) {
client = newClient( client = newClient(
@@ -15,6 +16,7 @@ class DAVClient {
user: dav.user, user: dav.user,
password: dav.password, password: dav.password,
); );
fileName = dav.fileName;
client.setHeaders( client.setHeaders(
{ {
'accept-charset': 'utf-8', 'accept-charset': 'utf-8',
@@ -38,7 +40,7 @@ class DAVClient {
get root => "/$appName"; get root => "/$appName";
get backupFile => "$root/backup.zip"; get backupFile => "$root/$fileName";
backup(Uint8List data) async { backup(Uint8List data) async {
await client.mkdir("$root"); await client.mkdir("$root");

View File

@@ -1,18 +1,20 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter/cupertino.dart';
import '../state.dart'; import '../state.dart';
class FlClashHttpOverrides extends HttpOverrides { class FlClashHttpOverrides extends HttpOverrides {
@override @override
HttpClient createHttpClient(SecurityContext? context) { HttpClient createHttpClient(SecurityContext? context) {
final client = super.createHttpClient(context); final client = super.createHttpClient(context);
client.badCertificateCallback = (_, __, ___) => true; client.badCertificateCallback = (_, __, ___) => true;
client.findProxy = (url) { client.findProxy = (url) {
debugPrint("find $url");
final port = globalState.appController.clashConfig.mixedPort; final port = globalState.appController.clashConfig.mixedPort;
final isStart = globalState.appController.appState.isStart; final isStart = globalState.appController.appState.isStart;
if(!isStart) return "DIRECT"; if (!isStart) return "DIRECT";
return "PROXY localhost:$port;DIRECT"; return "PROXY localhost:$port";
}; };
return client; return client;
} }

View File

@@ -2,4 +2,17 @@ extension ListExtension<T> on List<T> {
List<T> intersection(List<T> list) { List<T> intersection(List<T> list) {
return where((item) => list.contains(item)).toList(); return where((item) => list.contains(item)).toList();
} }
}
List<List<T>> batch(int maxConcurrent) {
final batches = (length / maxConcurrent).ceil();
final List<List<T>> res = [];
for (int i = 0; i < batches; i++) {
if (i != batches - 1) {
res.add(sublist(i * maxConcurrent, maxConcurrent * (i + 1)));
} else {
res.add(sublist(i * maxConcurrent, length));
}
}
return res;
}
}

View File

@@ -3,23 +3,21 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class Measure { class Measure {
Measure.of(this.context); final TextScaler _textScale;
late BuildContext context;
final _textScaleFactor = Measure.of(this.context) : _textScale = MediaQuery.of(context).textScaler;
WidgetsBinding.instance.platformDispatcher.textScaleFactor;
Size computeTextSize(Text text) { Size computeTextSize(Text text) {
final textPainter = TextPainter( final textPainter = TextPainter(
text: TextSpan(text: text.data, style: text.style), text: TextSpan(text: text.data, style: text.style),
maxLines: text.maxLines, maxLines: text.maxLines,
textScaler: TextScaler.linear(_textScaleFactor), textScaler: _textScale,
textDirection: text.textDirection ?? TextDirection.ltr, textDirection: text.textDirection ?? TextDirection.ltr,
)..layout(); )..layout();
return textPainter.size; return textPainter.size;
} }
late BuildContext context;
double? _bodyMediumHeight; double? _bodyMediumHeight;
double? _bodySmallHeight; double? _bodySmallHeight;
double? _labelSmallHeight; double? _labelSmallHeight;

View File

@@ -8,7 +8,6 @@ import 'package:fl_clash/common/archive.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lpinyin/lpinyin.dart';
import 'package:path/path.dart'; import 'package:path/path.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@@ -22,7 +21,6 @@ class AppController {
late AppState appState; late AppState appState;
late Config config; late Config config;
late ClashConfig clashConfig; late ClashConfig clashConfig;
late Measure measure;
late Function updateClashConfigDebounce; late Function updateClashConfigDebounce;
late Function updateGroupDebounce; late Function updateGroupDebounce;
late Function addCheckIpNumDebounce; late Function addCheckIpNumDebounce;
@@ -44,7 +42,6 @@ class AppController {
updateGroupDebounce = debounce(() async { updateGroupDebounce = debounce(() async {
await updateGroups(); await updateGroups();
}); });
measure = Measure.of(context);
} }
updateStatus(bool isStart) async { updateStatus(bool isStart) async {
@@ -125,10 +122,6 @@ class AppController {
); );
} }
updateTray(){
}
Future applyProfile({bool isPrue = false}) async { Future applyProfile({bool isPrue = false}) async {
if (isPrue) { if (isPrue) {
await globalState.applyProfile( await globalState.applyProfile(
@@ -317,6 +310,14 @@ class AppController {
autoCheckUpdate(); autoCheckUpdate();
} }
updateTray() {
globalState.updateTray(
appState: appState,
config: config,
clashConfig: clashConfig,
);
}
setDelay(Delay delay) { setDelay(Delay delay) {
appState.setDelay(delay); appState.setDelay(delay);
} }

View File

@@ -73,11 +73,11 @@ class BackupAndRecovery extends StatelessWidget {
final res = await commonScaffoldState?.loadingRun<bool>( final res = await commonScaffoldState?.loadingRun<bool>(
() async { () async {
final backupData = await globalState.appController.backupData(); final backupData = await globalState.appController.backupData();
final value = await picker.saveFile( final value = await picker.saveFile(
other.getBackupFileName(), other.getBackupFileName(),
Uint8List.fromList(backupData), Uint8List.fromList(backupData),
); );
if(value == null) return false; if (value == null) return false;
return true; return true;
}, },
title: appLocalizations.backup, title: appLocalizations.backup,
@@ -204,6 +204,24 @@ class BackupAndRecovery extends StatelessWidget {
const SizedBox( const SizedBox(
height: 4, height: 4,
), ),
ListItem.input(
title: Text(appLocalizations.file),
subtitle: Text(dav.fileName),
delegate: InputDelegate(
title: appLocalizations.file,
value: dav.fileName,
resetValue: defaultDavFileName,
onChanged: (String? value) {
if (value == null) {
return;
}
globalState.appController.config.dav =
globalState.appController.config.dav?.copyWith(
fileName: value,
);
},
),
),
ListItem( ListItem(
onTap: () { onTap: () {
_backupOnWebDAV(context, client); _backupOnWebDAV(context, client);

View File

@@ -72,6 +72,7 @@ class _ConfigFragmentState extends State<ConfigFragment> {
widget: generateListView( widget: generateListView(
dnsItems, dnsItems,
), ),
isScaffold: true,
isBlur: false, isBlur: false,
extendPageWidth: 360, extendPageWidth: 360,
), ),

View File

@@ -11,8 +11,27 @@ import 'package:provider/provider.dart';
class OverrideItem extends StatelessWidget { class OverrideItem extends StatelessWidget {
const OverrideItem({super.key}); const OverrideItem({super.key});
_initActions(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final commonScaffoldState =
context.findAncestorStateOfType<CommonScaffoldState>();
commonScaffoldState?.actions = [
IconButton(
onPressed: () {
globalState.appController.clashConfig.dns = const Dns();
},
tooltip: appLocalizations.resetDns,
icon: const Icon(
Icons.replay,
),
)
];
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_initActions(context);
return Selector<Config, bool>( return Selector<Config, bool>(
selector: (_, config) => config.overrideDns, selector: (_, config) => config.overrideDns,
builder: (_, override, __) { builder: (_, override, __) {
@@ -35,8 +54,7 @@ class OverrideItem extends StatelessWidget {
class DnsDisabledContainer extends StatelessWidget { class DnsDisabledContainer extends StatelessWidget {
final Widget child; final Widget child;
const DnsDisabledContainer( const DnsDisabledContainer(this.child, {
this.child, {
super.key, super.key,
}); });
@@ -250,7 +268,7 @@ class FakeIpFilterItem extends StatelessWidget {
widget: Selector<ClashConfig, List<String>>( widget: Selector<ClashConfig, List<String>>(
selector: (_, clashConfig) => clashConfig.dns.fakeIpFilter, selector: (_, clashConfig) => clashConfig.dns.fakeIpFilter,
shouldRebuild: (prev, next) => shouldRebuild: (prev, next) =>
!const ListEquality<String>().equals(prev, next), !const ListEquality<String>().equals(prev, next),
builder: (_, fakeIpFilter, __) { builder: (_, fakeIpFilter, __) {
return UpdatePage( return UpdatePage(
title: appLocalizations.fakeipFilter, title: appLocalizations.fakeipFilter,
@@ -260,7 +278,8 @@ class FakeIpFilterItem extends StatelessWidget {
final clashConfig = globalState.appController.clashConfig; final clashConfig = globalState.appController.clashConfig;
final dns = clashConfig.dns; final dns = clashConfig.dns;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fakeIpFilter: List.from(dns.fakeIpFilter)..remove(value), fakeIpFilter: List.from(dns.fakeIpFilter)
..remove(value),
); );
}, },
onAdd: (value) { onAdd: (value) {
@@ -268,7 +287,8 @@ class FakeIpFilterItem extends StatelessWidget {
final dns = clashConfig.dns; final dns = clashConfig.dns;
if (fakeIpFilter.contains(value)) return; if (fakeIpFilter.contains(value)) return;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fakeIpFilter: List.from(dns.fakeIpFilter)..add(value), fakeIpFilter: List.from(dns.fakeIpFilter)
..add(value),
); );
}, },
); );
@@ -294,7 +314,7 @@ class DefaultNameserverItem extends StatelessWidget {
widget: Selector<ClashConfig, List<String>>( widget: Selector<ClashConfig, List<String>>(
selector: (_, clashConfig) => clashConfig.dns.defaultNameserver, selector: (_, clashConfig) => clashConfig.dns.defaultNameserver,
shouldRebuild: (prev, next) => shouldRebuild: (prev, next) =>
!const ListEquality<String>().equals(prev, next), !const ListEquality<String>().equals(prev, next),
builder: (_, defaultNameserver, __) { builder: (_, defaultNameserver, __) {
return UpdatePage( return UpdatePage(
title: appLocalizations.defaultNameserver, title: appLocalizations.defaultNameserver,
@@ -340,7 +360,7 @@ class NameserverItem extends StatelessWidget {
widget: Selector<ClashConfig, List<String>>( widget: Selector<ClashConfig, List<String>>(
selector: (_, clashConfig) => clashConfig.dns.nameserver, selector: (_, clashConfig) => clashConfig.dns.nameserver,
shouldRebuild: (prev, next) => shouldRebuild: (prev, next) =>
!const ListEquality<String>().equals(prev, next), !const ListEquality<String>().equals(prev, next),
builder: (_, nameserver, __) { builder: (_, nameserver, __) {
return UpdatePage( return UpdatePage(
title: "域名服务器", title: "域名服务器",
@@ -350,7 +370,8 @@ class NameserverItem extends StatelessWidget {
final clashConfig = globalState.appController.clashConfig; final clashConfig = globalState.appController.clashConfig;
final dns = clashConfig.dns; final dns = clashConfig.dns;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
nameserver: List.from(dns.nameserver)..remove(value), nameserver: List.from(dns.nameserver)
..remove(value),
); );
}, },
onAdd: (value) { onAdd: (value) {
@@ -358,7 +379,8 @@ class NameserverItem extends StatelessWidget {
final dns = clashConfig.dns; final dns = clashConfig.dns;
if (nameserver.contains(value)) return; if (nameserver.contains(value)) return;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
nameserver: List.from(dns.nameserver)..add(value), nameserver: List.from(dns.nameserver)
..add(value),
); );
}, },
); );
@@ -436,7 +458,7 @@ class NameserverPolicyItem extends StatelessWidget {
widget: Selector<ClashConfig, Map<String, String>>( widget: Selector<ClashConfig, Map<String, String>>(
selector: (_, clashConfig) => clashConfig.dns.nameserverPolicy, selector: (_, clashConfig) => clashConfig.dns.nameserverPolicy,
shouldRebuild: (prev, next) => shouldRebuild: (prev, next) =>
!const MapEquality<String, String>().equals(prev, next), !const MapEquality<String, String>().equals(prev, next),
builder: (_, nameserverPolicy, __) { builder: (_, nameserverPolicy, __) {
return UpdatePage( return UpdatePage(
title: appLocalizations.nameserverPolicy, title: appLocalizations.nameserverPolicy,
@@ -483,7 +505,7 @@ class ProxyServerNameserverItem extends StatelessWidget {
widget: Selector<ClashConfig, List<String>>( widget: Selector<ClashConfig, List<String>>(
selector: (_, clashConfig) => clashConfig.dns.proxyServerNameserver, selector: (_, clashConfig) => clashConfig.dns.proxyServerNameserver,
shouldRebuild: (prev, next) => shouldRebuild: (prev, next) =>
!const ListEquality<String>().equals(prev, next), !const ListEquality<String>().equals(prev, next),
builder: (_, proxyServerNameserver, __) { builder: (_, proxyServerNameserver, __) {
return UpdatePage( return UpdatePage(
title: appLocalizations.proxyNameserver, title: appLocalizations.proxyNameserver,
@@ -529,7 +551,7 @@ class FallbackItem extends StatelessWidget {
widget: Selector<ClashConfig, List<String>>( widget: Selector<ClashConfig, List<String>>(
selector: (_, clashConfig) => clashConfig.dns.fallback, selector: (_, clashConfig) => clashConfig.dns.fallback,
shouldRebuild: (prev, next) => shouldRebuild: (prev, next) =>
!const ListEquality<String>().equals(prev, next), !const ListEquality<String>().equals(prev, next),
builder: (_, fallback, __) { builder: (_, fallback, __) {
return UpdatePage( return UpdatePage(
title: appLocalizations.fallback, title: appLocalizations.fallback,
@@ -539,7 +561,8 @@ class FallbackItem extends StatelessWidget {
final clashConfig = globalState.appController.clashConfig; final clashConfig = globalState.appController.clashConfig;
final dns = clashConfig.dns; final dns = clashConfig.dns;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fallback: List.from(dns.fallback)..remove(value), fallback: List.from(dns.fallback)
..remove(value),
); );
}, },
onAdd: (value) { onAdd: (value) {
@@ -547,7 +570,8 @@ class FallbackItem extends StatelessWidget {
final dns = clashConfig.dns; final dns = clashConfig.dns;
if (fallback.contains(value)) return; if (fallback.contains(value)) return;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fallback: List.from(dns.fallback)..add(value), fallback: List.from(dns.fallback)
..add(value),
); );
}, },
); );
@@ -639,7 +663,7 @@ class GeositeItem extends StatelessWidget {
widget: Selector<ClashConfig, List<String>>( widget: Selector<ClashConfig, List<String>>(
selector: (_, clashConfig) => clashConfig.dns.fallbackFilter.geosite, selector: (_, clashConfig) => clashConfig.dns.fallbackFilter.geosite,
shouldRebuild: (prev, next) => shouldRebuild: (prev, next) =>
!const ListEquality<String>().equals(prev, next), !const ListEquality<String>().equals(prev, next),
builder: (_, geosite, __) { builder: (_, geosite, __) {
return UpdatePage( return UpdatePage(
title: "Geosite", title: "Geosite",
@@ -650,7 +674,8 @@ class GeositeItem extends StatelessWidget {
final dns = clashConfig.dns; final dns = clashConfig.dns;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fallbackFilter: dns.fallbackFilter.copyWith( fallbackFilter: dns.fallbackFilter.copyWith(
geosite: List.from(geosite)..remove(value), geosite: List.from(geosite)
..remove(value),
), ),
); );
}, },
@@ -659,7 +684,8 @@ class GeositeItem extends StatelessWidget {
final dns = clashConfig.dns; final dns = clashConfig.dns;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fallbackFilter: dns.fallbackFilter.copyWith( fallbackFilter: dns.fallbackFilter.copyWith(
geosite: List.from(geosite)..add(value), geosite: List.from(geosite)
..add(value),
), ),
); );
}, },
@@ -685,7 +711,7 @@ class IpcidrItem extends StatelessWidget {
widget: Selector<ClashConfig, List<String>>( widget: Selector<ClashConfig, List<String>>(
selector: (_, clashConfig) => clashConfig.dns.fallbackFilter.ipcidr, selector: (_, clashConfig) => clashConfig.dns.fallbackFilter.ipcidr,
shouldRebuild: (prev, next) => shouldRebuild: (prev, next) =>
!const ListEquality<String>().equals(prev, next), !const ListEquality<String>().equals(prev, next),
builder: (_, ipcidr, __) { builder: (_, ipcidr, __) {
return UpdatePage( return UpdatePage(
title: appLocalizations.ipcidr, title: appLocalizations.ipcidr,
@@ -696,7 +722,8 @@ class IpcidrItem extends StatelessWidget {
final dns = clashConfig.dns; final dns = clashConfig.dns;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fallbackFilter: dns.fallbackFilter.copyWith( fallbackFilter: dns.fallbackFilter.copyWith(
ipcidr: List.from(ipcidr)..remove(value), ipcidr: List.from(ipcidr)
..remove(value),
), ),
); );
}, },
@@ -705,7 +732,8 @@ class IpcidrItem extends StatelessWidget {
final dns = clashConfig.dns; final dns = clashConfig.dns;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fallbackFilter: dns.fallbackFilter.copyWith( fallbackFilter: dns.fallbackFilter.copyWith(
ipcidr: List.from(ipcidr)..add(value), ipcidr: List.from(ipcidr)
..add(value),
), ),
); );
}, },
@@ -724,14 +752,14 @@ class DomainItem extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListItem.open( return ListItem.open(
title: Text(appLocalizations.domain), title: Text(appLocalizations.domain),
delegate: OpenDelegate( delegate: OpenDelegate(
isBlur: false, isBlur: false,
title: appLocalizations.domain, title: appLocalizations.domain,
widget: Selector<ClashConfig, List<String>>( widget: Selector<ClashConfig, List<String>>(
selector: (_, clashConfig) => clashConfig.dns.fallbackFilter.domain, selector: (_, clashConfig) => clashConfig.dns.fallbackFilter.domain,
shouldRebuild: (prev, next) => shouldRebuild: (prev, next) =>
!const ListEquality<String>().equals(prev, next), !const ListEquality<String>().equals(prev, next),
builder: (_, domain, __) { builder: (_, domain, __) {
return UpdatePage( return UpdatePage(
title: appLocalizations.domain, title: appLocalizations.domain,
@@ -742,7 +770,8 @@ class DomainItem extends StatelessWidget {
final dns = clashConfig.dns; final dns = clashConfig.dns;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fallbackFilter: dns.fallbackFilter.copyWith( fallbackFilter: dns.fallbackFilter.copyWith(
domain: List.from(domain)..remove(value), domain: List.from(domain)
..remove(value),
), ),
); );
}, },
@@ -751,7 +780,8 @@ class DomainItem extends StatelessWidget {
final dns = clashConfig.dns; final dns = clashConfig.dns;
clashConfig.dns = dns.copyWith( clashConfig.dns = dns.copyWith(
fallbackFilter: dns.fallbackFilter.copyWith( fallbackFilter: dns.fallbackFilter.copyWith(
domain: List.from(domain)..add(value), domain: List.from(domain)
..add(value),
), ),
); );
}, },

View File

@@ -85,7 +85,8 @@ class KeepAliveIntervalItem extends StatelessWidget {
delegate: InputDelegate( delegate: InputDelegate(
title: appLocalizations.keepAliveIntervalDesc, title: appLocalizations.keepAliveIntervalDesc,
suffixText: appLocalizations.seconds, suffixText: appLocalizations.seconds,
value: value.toString(), resetValue: "$defaultKeepAliveInterval",
value: "$value",
onChanged: (String? value) { onChanged: (String? value) {
if (value != null) { if (value != null) {
try { try {
@@ -125,6 +126,7 @@ class TestUrlItem extends StatelessWidget {
title: Text(appLocalizations.testUrl), title: Text(appLocalizations.testUrl),
subtitle: Text(value), subtitle: Text(value),
delegate: InputDelegate( delegate: InputDelegate(
resetValue: defaultTestUrl,
title: appLocalizations.testUrl, title: appLocalizations.testUrl,
value: value, value: value,
onChanged: (String? value) { onChanged: (String? value) {
@@ -165,7 +167,7 @@ class MixedPortItem extends StatelessWidget {
subtitle: Text("$value"), subtitle: Text("$value"),
delegate: InputDelegate( delegate: InputDelegate(
title: appLocalizations.proxyPort, title: appLocalizations.proxyPort,
value: value.toString(), value: "$value",
onChanged: (String? value) { onChanged: (String? value) {
if (value != null) { if (value != null) {
try { try {
@@ -184,6 +186,7 @@ class MixedPortItem extends StatelessWidget {
} }
} }
}, },
resetValue: "$defaultMixedPort",
), ),
); );
}, },

View File

@@ -53,7 +53,7 @@ class _IntranetIPState extends State<IntranetIP> {
}, },
child: Container( child: Container(
padding: const EdgeInsets.all(16).copyWith(top: 0), padding: const EdgeInsets.all(16).copyWith(top: 0),
height: globalState.appController.measure.titleLargeHeight + 24 - 2, height: globalState.measure.titleLargeHeight + 24 - 2,
child: ValueListenableBuilder( child: ValueListenableBuilder(
valueListenable: ipNotifier, valueListenable: ipNotifier,
builder: (_, value, __) { builder: (_, value, __) {

View File

@@ -46,9 +46,7 @@ class _NetworkDetectionState extends State<NetworkDetection> {
isTesting: false, isTesting: false,
ipInfo: ipInfo, ipInfo: ipInfo,
); );
} catch (_) { } catch (_) {}
}
} }
_checkIpContainer(Widget child) { _checkIpContainer(Widget child) {
@@ -122,7 +120,7 @@ class _NetworkDetectionState extends State<NetworkDetection> {
: ipInfo != null : ipInfo != null
? Container( ? Container(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
height: globalState.appController height: globalState
.measure.titleMediumHeight, .measure.titleMediumHeight,
child: Text( child: Text(
countryCodeToEmoji( countryCodeToEmoji(
@@ -150,9 +148,7 @@ class _NetworkDetectionState extends State<NetworkDetection> {
), ),
), ),
Container( Container(
height: globalState.appController.measure.titleLargeHeight + height: globalState.measure.titleLargeHeight + 24 - 2,
24 -
2,
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
padding: const EdgeInsets.all(16).copyWith(top: 0), padding: const EdgeInsets.all(16).copyWith(top: 0),
child: FadeBox( child: FadeBox(

View File

@@ -59,7 +59,7 @@ class _NetworkSpeedState extends State<NetworkSpeed> {
style: bodyMedium, style: bodyMedium,
maxLines: 1, maxLines: 1,
); );
final size = globalState.appController.measure.computeTextSize(valueText); final size = globalState.measure.computeTextSize(valueText);
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,

View File

@@ -74,7 +74,7 @@ class _StartButtonState extends State<StartButton>
if (!state.isInit || !state.hasProfile) { if (!state.isInit || !state.hasProfile) {
return Container(); return Container();
} }
final textWidth = globalState.appController.measure final textWidth = globalState.measure
.computeTextSize( .computeTextSize(
Text( Text(
other.getTimeDifference( other.getTimeDifference(

View File

@@ -495,26 +495,29 @@ class _ReorderableProfilesState extends State<ReorderableProfiles> {
itemCount: profiles.length, itemCount: profiles.length,
), ),
), ),
Padding( Container(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
vertical: 8, vertical: 8,
horizontal: 12, horizontal: 24,
), ),
child: Row( child: FilledButton(
mainAxisAlignment: MainAxisAlignment.end, onPressed: () {
children: [ Navigator.of(context).pop();
IconButton( globalState.appController.config.profiles = profiles;
onPressed: () { },
Navigator.of(context).pop(); style: ButtonStyle(
globalState.appController.config.profiles = profiles; padding: WidgetStateProperty.all(
}, const EdgeInsets.symmetric(vertical: 16),
icon: const Icon(
Icons.check,
),
iconSize: 32,
padding: const EdgeInsets.all(8),
), ),
], ),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
appLocalizations.confirm,
),
],
),
), ),
), ),
], ],

View File

@@ -23,7 +23,7 @@ class ProxyCard extends StatelessWidget {
required this.type, required this.type,
}); });
Measure get measure => globalState.appController.measure; Measure get measure => globalState.measure;
Widget _buildDelayText() { Widget _buildDelayText() {
return SizedBox( return SizedBox(
@@ -119,7 +119,7 @@ class ProxyCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final measure = globalState.appController.measure; final measure = globalState.measure;
final delayText = _buildDelayText(); final delayText = _buildDelayText();
final proxyNameText = _buildProxyNameText(context); final proxyNameText = _buildProxyNameText(context);
return currentGroupProxyNameBuilder( return currentGroupProxyNameBuilder(

View File

@@ -1,7 +1,7 @@
import 'dart:math'; import 'dart:math';
import 'package:fl_clash/clash/clash.dart'; import 'package:fl_clash/clash/clash.dart';
import 'package:fl_clash/common/other.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
@@ -25,12 +25,12 @@ Widget currentGroupProxyNameBuilder({
} }
double get listHeaderHeight { double get listHeaderHeight {
final measure = globalState.appController.measure; final measure = globalState.measure;
return 24 + measure.titleMediumHeight + 4 + measure.bodyMediumHeight; return 24 + measure.titleMediumHeight + 4 + measure.bodyMediumHeight;
} }
double getItemHeight(ProxyCardType proxyCardType) { double getItemHeight(ProxyCardType proxyCardType) {
final measure = globalState.appController.measure; final measure = globalState.measure;
final baseHeight = final baseHeight =
12 * 2 + measure.bodyMediumHeight * 2 + measure.bodySmallHeight + 8; 12 * 2 + measure.bodyMediumHeight * 2 + measure.bodySmallHeight + 8;
return switch (proxyCardType) { return switch (proxyCardType) {
@@ -51,8 +51,12 @@ delayTest(List<Proxy> proxies) async {
), ),
); );
globalState.appController.setDelay(await clashCore.getDelay(proxyName)); globalState.appController.setDelay(await clashCore.getDelay(proxyName));
}); }).toList();
await Future.wait(delayProxies);
final batchesDelayProxies = delayProxies.batch(100);
for (final batchDelayProxies in batchesDelayProxies) {
await Future.wait(batchDelayProxies);
}
appController.appState.sortNum++; appController.appState.sortNum++;
} }

View File

@@ -29,7 +29,7 @@ class _ProxiesFragmentState extends State<ProxiesFragment> {
IconButton( IconButton(
onPressed: () { onPressed: () {
showExtendPage( showExtendPage(
forceNotSide: true, isScaffold: true,
extendPageWidth: 360, extendPageWidth: 360,
context, context,
body: const Providers(), body: const Providers(),

View File

@@ -33,13 +33,21 @@ class Resources extends StatelessWidget {
fileName: geoIpFileName, fileName: geoIpFileName,
key: "geoip", key: "geoip",
), ),
GeoItem(label: "GeoSite", fileName: geoSiteFileName, key: "geosite"), GeoItem(
label: "GeoSite",
fileName: geoSiteFileName,
key: "geosite",
),
GeoItem( GeoItem(
label: "MMDB", label: "MMDB",
fileName: mmdbFileName, fileName: mmdbFileName,
key: "mmdb", key: "mmdb",
), ),
GeoItem(label: "ASN", fileName: asnFileName, key: "asn"), GeoItem(
label: "ASN",
fileName: asnFileName,
key: "asn",
),
]; ];
return ListView.separated( return ListView.separated(
@@ -81,6 +89,7 @@ class _GeoDataListItemState extends State<GeoDataListItem> {
child: UpdateGeoUrlFormDialog( child: UpdateGeoUrlFormDialog(
title: geoItem.label, title: geoItem.label,
url: url, url: url,
defaultValue: defaultGeoXMap[geoItem.key],
), ),
); );
if (newUrl != null && newUrl != url && mounted) { if (newUrl != null && newUrl != url && mounted) {
@@ -238,11 +247,13 @@ class _GeoDataListItemState extends State<GeoDataListItem> {
class UpdateGeoUrlFormDialog extends StatefulWidget { class UpdateGeoUrlFormDialog extends StatefulWidget {
final String title; final String title;
final String url; final String url;
final String? defaultValue;
const UpdateGeoUrlFormDialog({ const UpdateGeoUrlFormDialog({
super.key, super.key,
required this.title, required this.title,
required this.url, required this.url,
this.defaultValue
}); });
@override @override
@@ -258,6 +269,13 @@ class _UpdateGeoUrlFormDialogState extends State<UpdateGeoUrlFormDialog> {
urlController = TextEditingController(text: widget.url); urlController = TextEditingController(text: widget.url);
} }
_handleReset() async {
if (widget.defaultValue == null) {
return;
}
Navigator.of(context).pop<String>(widget.defaultValue);
}
_handleUpdate() async { _handleUpdate() async {
final url = urlController.value.text; final url = urlController.value.text;
if (url.isEmpty) return; if (url.isEmpty) return;
@@ -285,6 +303,16 @@ class _UpdateGeoUrlFormDialogState extends State<UpdateGeoUrlFormDialog> {
), ),
), ),
actions: [ actions: [
if (widget.defaultValue != null &&
urlController.value.text != widget.defaultValue) ...[
TextButton(
onPressed: _handleReset,
child: Text(appLocalizations.reset),
),
const SizedBox(
width: 4,
),
],
TextButton( TextButton(
onPressed: _handleUpdate, onPressed: _handleUpdate,
child: Text(appLocalizations.submit), child: Text(appLocalizations.submit),

View File

@@ -238,15 +238,66 @@ class _ThemeColorsBoxState extends State<ThemeColorsBox> {
), ),
title: Text(appLocalizations.prueBlackMode), title: Text(appLocalizations.prueBlackMode),
delegate: SwitchDelegate( delegate: SwitchDelegate(
value: value, value: value,
onChanged: (value){ onChanged: (value) {
globalState.appController.config.prueBlack = value; globalState.appController.config.prueBlack = value;
} }),
),
); );
}, },
), ),
) ),
// Padding(
// padding: const EdgeInsets.symmetric(vertical: 16),
// child: Selector<Config, bool>(
// selector: (_, config) => config.scaleProps.custom,
// builder: (_, value, ___) {
// return ListItem.switchItem(
// leading: Icon(
// Icons.format_size_sharp,
// color: context.colorScheme.primary,
// ),
// title: const Text("自定义字体大小"),
// delegate: SwitchDelegate(
// value: value,
// onChanged: (value) {
// globalState.appController.config.scaleProps =
// globalState.appController.config.scaleProps.copyWith(
// custom: value,
// );
// },
// ),
// );
// },
// ),
// ),
// SizedBox(
// height: 20,
// child: Selector<Config, ScaleProps>(
// selector: (_, config) => config.scaleProps,
// builder: (_, props, ___) {
// return AbsorbPointer(
// absorbing: !props.custom,
// child: DisabledMask(
// status: !props.custom,
// child: Slider(
// value: props.scale,
// min: 0.8,
// max: 1.2,
// onChanged: (value) {
// globalState.appController.config.scaleProps =
// globalState.appController.config.scaleProps.copyWith(
// scale: value,
// );
// },
// ),
// ),
// );
// },
// ),
// ),
const SizedBox(
height: 64,
),
], ],
); );
} }

View File

@@ -286,5 +286,7 @@
"fallbackFilter": "Fallback filter", "fallbackFilter": "Fallback filter",
"geoipCode": "Geoip code", "geoipCode": "Geoip code",
"ipcidr": "Ipcidr", "ipcidr": "Ipcidr",
"domain": "Domain" "domain": "Domain",
"resetDns": "Reset Dns",
"reset": "Reset"
} }

View File

@@ -286,5 +286,7 @@
"fallbackFilter": "Fallback过滤", "fallbackFilter": "Fallback过滤",
"geoipCode": "Geoip代码", "geoipCode": "Geoip代码",
"ipcidr": "IP/掩码", "ipcidr": "IP/掩码",
"domain": "域名" "domain": "域名",
"resetDns": "重置DNS",
"reset": "重置"
} }

View File

@@ -346,6 +346,8 @@ class MessageLookup extends MessageLookupByLibrary {
"requests": MessageLookupByLibrary.simpleMessage("Requests"), "requests": MessageLookupByLibrary.simpleMessage("Requests"),
"requestsDesc": MessageLookupByLibrary.simpleMessage( "requestsDesc": MessageLookupByLibrary.simpleMessage(
"View recently request records"), "View recently request records"),
"reset": MessageLookupByLibrary.simpleMessage("Reset"),
"resetDns": MessageLookupByLibrary.simpleMessage("Reset Dns"),
"resources": MessageLookupByLibrary.simpleMessage("Resources"), "resources": MessageLookupByLibrary.simpleMessage("Resources"),
"resourcesDesc": MessageLookupByLibrary.simpleMessage( "resourcesDesc": MessageLookupByLibrary.simpleMessage(
"External resource related info"), "External resource related info"),

View File

@@ -271,6 +271,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("通过WebDAV恢复数据"), MessageLookupByLibrary.simpleMessage("通过WebDAV恢复数据"),
"requests": MessageLookupByLibrary.simpleMessage("请求"), "requests": MessageLookupByLibrary.simpleMessage("请求"),
"requestsDesc": MessageLookupByLibrary.simpleMessage("查看最近请求记录"), "requestsDesc": MessageLookupByLibrary.simpleMessage("查看最近请求记录"),
"reset": MessageLookupByLibrary.simpleMessage("重置"),
"resetDns": MessageLookupByLibrary.simpleMessage("重置DNS"),
"resources": MessageLookupByLibrary.simpleMessage("资源"), "resources": MessageLookupByLibrary.simpleMessage("资源"),
"resourcesDesc": MessageLookupByLibrary.simpleMessage("外部资源相关信息"), "resourcesDesc": MessageLookupByLibrary.simpleMessage("外部资源相关信息"),
"respectRules": MessageLookupByLibrary.simpleMessage("遵守规则"), "respectRules": MessageLookupByLibrary.simpleMessage("遵守规则"),

View File

@@ -2929,6 +2929,26 @@ class AppLocalizations {
args: [], args: [],
); );
} }
/// `Reset Dns`
String get resetDns {
return Intl.message(
'Reset Dns',
name: 'resetDns',
desc: '',
args: [],
);
}
/// `Reset`
String get reset {
return Intl.message(
'Reset',
name: 'reset',
desc: '',
args: [],
);
}
} }
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> { class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {

View File

@@ -32,6 +32,11 @@ Future<void> main() async {
openLogs: config.openLogs, openLogs: config.openLogs,
hasProxies: false, hasProxies: false,
); );
globalState.updateTray(
appState: appState,
config: config,
clashConfig: clashConfig,
);
await globalState.init( await globalState.init(
appState: appState, appState: appState,
config: config, config: config,

View File

@@ -111,6 +111,9 @@ typedef GeoXMap = Map<String, String>;
typedef HostsMap = Map<String, String>; typedef HostsMap = Map<String, String>;
const defaultMixedPort = 7890;
const defaultKeepAliveInterval = 30;
@JsonSerializable() @JsonSerializable()
class ClashConfig extends ChangeNotifier { class ClashConfig extends ChangeNotifier {
int _mixedPort; int _mixedPort;
@@ -132,7 +135,7 @@ class ClashConfig extends ChangeNotifier {
HostsMap _hosts; HostsMap _hosts;
ClashConfig() ClashConfig()
: _mixedPort = 7890, : _mixedPort = defaultMixedPort,
_mode = Mode.rule, _mode = Mode.rule,
_ipv6 = false, _ipv6 = false,
_findProcessMode = FindProcessMode.off, _findProcessMode = FindProcessMode.off,
@@ -143,13 +146,13 @@ class ClashConfig extends ChangeNotifier {
_unifiedDelay = false, _unifiedDelay = false,
_geodataLoader = geodataLoaderMemconservative, _geodataLoader = geodataLoaderMemconservative,
_externalController = '', _externalController = '',
_keepAliveInterval = 30, _keepAliveInterval = defaultKeepAliveInterval,
_dns = const Dns(), _dns = const Dns(),
_geoXUrl = defaultGeoXMap, _geoXUrl = defaultGeoXMap,
_rules = [], _rules = [],
_hosts = {}; _hosts = {};
@JsonKey(name: "mixed-port", defaultValue: 7890) @JsonKey(name: "mixed-port", defaultValue: defaultMixedPort)
int get mixedPort => _mixedPort; int get mixedPort => _mixedPort;
set mixedPort(int value) { set mixedPort(int value) {
@@ -209,7 +212,7 @@ class ClashConfig extends ChangeNotifier {
} }
} }
@JsonKey(name: "keep-alive-interval", defaultValue: 30) @JsonKey(name: "keep-alive-interval", defaultValue: defaultKeepAliveInterval)
int get keepAliveInterval => _keepAliveInterval; int get keepAliveInterval => _keepAliveInterval;
set keepAliveInterval(int value) { set keepAliveInterval(int value) {

View File

@@ -95,6 +95,21 @@ class DesktopProps with _$DesktopProps {
json == null ? const DesktopProps() : _$DesktopPropsFromJson(json); json == null ? const DesktopProps() : _$DesktopPropsFromJson(json);
} }
const defaultCustomFontSizeScale = 1.0;
const defaultScaleProps = ScaleProps();
@freezed
class ScaleProps with _$ScaleProps {
const factory ScaleProps({
@Default(false) bool custom,
@Default(defaultCustomFontSizeScale) double scale,
}) = _ScaleProps;
factory ScaleProps.fromJson(Map<String, Object?>? json) =>
json == null ? defaultScaleProps : _$ScalePropsFromJson(json);
}
@JsonSerializable() @JsonSerializable()
class Config extends ChangeNotifier { class Config extends ChangeNotifier {
List<Profile> _profiles; List<Profile> _profiles;
@@ -124,6 +139,7 @@ class Config extends ChangeNotifier {
bool _onlyProxy; bool _onlyProxy;
bool _prueBlack; bool _prueBlack;
VpnProps _vpnProps; VpnProps _vpnProps;
ScaleProps _scaleProps;
DesktopProps _desktopProps; DesktopProps _desktopProps;
bool _showLabel; bool _showLabel;
bool _overrideDns; bool _overrideDns;
@@ -155,7 +171,8 @@ class Config extends ChangeNotifier {
_vpnProps = const VpnProps(), _vpnProps = const VpnProps(),
_desktopProps = const DesktopProps(), _desktopProps = const DesktopProps(),
_showLabel = false, _showLabel = false,
_overrideDns = false; _overrideDns = false,
_scaleProps = const ScaleProps();
deleteProfileById(String id) { deleteProfileById(String id) {
_profiles = profiles.where((element) => element.id != id).toList(); _profiles = profiles.where((element) => element.id != id).toList();
@@ -551,6 +568,15 @@ class Config extends ChangeNotifier {
} }
} }
ScaleProps get scaleProps => _scaleProps;
set scaleProps(ScaleProps value) {
if (_scaleProps != value) {
_scaleProps = value;
notifyListeners();
}
}
@JsonKey(defaultValue: false) @JsonKey(defaultValue: false)
bool get showLabel => _showLabel; bool get showLabel => _showLabel;
@@ -589,6 +615,7 @@ class Config extends ChangeNotifier {
_isCloseConnections = config._isCloseConnections; _isCloseConnections = config._isCloseConnections;
_isCompatible = config._isCompatible; _isCompatible = config._isCompatible;
_autoLaunch = config._autoLaunch; _autoLaunch = config._autoLaunch;
_dav = config._dav;
_silentLaunch = config._silentLaunch; _silentLaunch = config._silentLaunch;
_autoRun = config._autoRun; _autoRun = config._autoRun;
_proxiesType = config._proxiesType; _proxiesType = config._proxiesType;

View File

@@ -4,14 +4,16 @@ part 'generated/dav.g.dart';
part 'generated/dav.freezed.dart'; part 'generated/dav.freezed.dart';
const defaultDavFileName = "backup.zip";
@freezed @freezed
class DAV with _$DAV{ class DAV with _$DAV {
const factory DAV({ const factory DAV({
required String uri, required String uri,
required String user, required String user,
required String password, required String password,
@Default(defaultDavFileName) String fileName,
}) = _DAV; }) = _DAV;
factory DAV.fromJson(Map<String, Object?> json) => factory DAV.fromJson(Map<String, Object?> json) => _$DAVFromJson(json);
_$DAVFromJson(json); }
}

View File

@@ -1240,3 +1240,159 @@ abstract class _DesktopProps implements DesktopProps {
_$$DesktopPropsImplCopyWith<_$DesktopPropsImpl> get copyWith => _$$DesktopPropsImplCopyWith<_$DesktopPropsImpl> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
} }
ScaleProps _$ScalePropsFromJson(Map<String, dynamic> json) {
return _ScaleProps.fromJson(json);
}
/// @nodoc
mixin _$ScaleProps {
bool get custom => throw _privateConstructorUsedError;
double get scale => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ScalePropsCopyWith<ScaleProps> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ScalePropsCopyWith<$Res> {
factory $ScalePropsCopyWith(
ScaleProps value, $Res Function(ScaleProps) then) =
_$ScalePropsCopyWithImpl<$Res, ScaleProps>;
@useResult
$Res call({bool custom, double scale});
}
/// @nodoc
class _$ScalePropsCopyWithImpl<$Res, $Val extends ScaleProps>
implements $ScalePropsCopyWith<$Res> {
_$ScalePropsCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? custom = null,
Object? scale = null,
}) {
return _then(_value.copyWith(
custom: null == custom
? _value.custom
: custom // ignore: cast_nullable_to_non_nullable
as bool,
scale: null == scale
? _value.scale
: scale // ignore: cast_nullable_to_non_nullable
as double,
) as $Val);
}
}
/// @nodoc
abstract class _$$ScalePropsImplCopyWith<$Res>
implements $ScalePropsCopyWith<$Res> {
factory _$$ScalePropsImplCopyWith(
_$ScalePropsImpl value, $Res Function(_$ScalePropsImpl) then) =
__$$ScalePropsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({bool custom, double scale});
}
/// @nodoc
class __$$ScalePropsImplCopyWithImpl<$Res>
extends _$ScalePropsCopyWithImpl<$Res, _$ScalePropsImpl>
implements _$$ScalePropsImplCopyWith<$Res> {
__$$ScalePropsImplCopyWithImpl(
_$ScalePropsImpl _value, $Res Function(_$ScalePropsImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? custom = null,
Object? scale = null,
}) {
return _then(_$ScalePropsImpl(
custom: null == custom
? _value.custom
: custom // ignore: cast_nullable_to_non_nullable
as bool,
scale: null == scale
? _value.scale
: scale // ignore: cast_nullable_to_non_nullable
as double,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ScalePropsImpl implements _ScaleProps {
const _$ScalePropsImpl(
{this.custom = false, this.scale = defaultCustomFontSizeScale});
factory _$ScalePropsImpl.fromJson(Map<String, dynamic> json) =>
_$$ScalePropsImplFromJson(json);
@override
@JsonKey()
final bool custom;
@override
@JsonKey()
final double scale;
@override
String toString() {
return 'ScaleProps(custom: $custom, scale: $scale)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ScalePropsImpl &&
(identical(other.custom, custom) || other.custom == custom) &&
(identical(other.scale, scale) || other.scale == scale));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, custom, scale);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ScalePropsImplCopyWith<_$ScalePropsImpl> get copyWith =>
__$$ScalePropsImplCopyWithImpl<_$ScalePropsImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ScalePropsImplToJson(
this,
);
}
}
abstract class _ScaleProps implements ScaleProps {
const factory _ScaleProps({final bool custom, final double scale}) =
_$ScalePropsImpl;
factory _ScaleProps.fromJson(Map<String, dynamic> json) =
_$ScalePropsImpl.fromJson;
@override
bool get custom;
@override
double get scale;
@override
@JsonKey(ignore: true)
_$$ScalePropsImplCopyWith<_$ScalePropsImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -53,6 +53,8 @@ Config _$ConfigFromJson(Map<String, dynamic> json) => Config()
..vpnProps = VpnProps.fromJson(json['vpnProps'] as Map<String, dynamic>?) ..vpnProps = VpnProps.fromJson(json['vpnProps'] as Map<String, dynamic>?)
..desktopProps = ..desktopProps =
DesktopProps.fromJson(json['desktopProps'] as Map<String, dynamic>?) DesktopProps.fromJson(json['desktopProps'] as Map<String, dynamic>?)
..scaleProps =
ScaleProps.fromJson(json['scaleProps'] as Map<String, dynamic>?)
..showLabel = json['showLabel'] as bool? ?? false ..showLabel = json['showLabel'] as bool? ?? false
..overrideDns = json['overrideDns'] as bool? ?? false; ..overrideDns = json['overrideDns'] as bool? ?? false;
@@ -85,6 +87,7 @@ Map<String, dynamic> _$ConfigToJson(Config instance) => <String, dynamic>{
'windowProps': instance.windowProps, 'windowProps': instance.windowProps,
'vpnProps': instance.vpnProps, 'vpnProps': instance.vpnProps,
'desktopProps': instance.desktopProps, 'desktopProps': instance.desktopProps,
'scaleProps': instance.scaleProps,
'showLabel': instance.showLabel, 'showLabel': instance.showLabel,
'overrideDns': instance.overrideDns, 'overrideDns': instance.overrideDns,
}; };
@@ -234,3 +237,15 @@ Map<String, dynamic> _$$DesktopPropsImplToJson(_$DesktopPropsImpl instance) =>
<String, dynamic>{ <String, dynamic>{
'systemProxy': instance.systemProxy, 'systemProxy': instance.systemProxy,
}; };
_$ScalePropsImpl _$$ScalePropsImplFromJson(Map<String, dynamic> json) =>
_$ScalePropsImpl(
custom: json['custom'] as bool? ?? false,
scale: (json['scale'] as num?)?.toDouble() ?? defaultCustomFontSizeScale,
);
Map<String, dynamic> _$$ScalePropsImplToJson(_$ScalePropsImpl instance) =>
<String, dynamic>{
'custom': instance.custom,
'scale': instance.scale,
};

View File

@@ -23,6 +23,7 @@ mixin _$DAV {
String get uri => throw _privateConstructorUsedError; String get uri => throw _privateConstructorUsedError;
String get user => throw _privateConstructorUsedError; String get user => throw _privateConstructorUsedError;
String get password => throw _privateConstructorUsedError; String get password => throw _privateConstructorUsedError;
String get fileName => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
@@ -34,7 +35,7 @@ abstract class $DAVCopyWith<$Res> {
factory $DAVCopyWith(DAV value, $Res Function(DAV) then) = factory $DAVCopyWith(DAV value, $Res Function(DAV) then) =
_$DAVCopyWithImpl<$Res, DAV>; _$DAVCopyWithImpl<$Res, DAV>;
@useResult @useResult
$Res call({String uri, String user, String password}); $Res call({String uri, String user, String password, String fileName});
} }
/// @nodoc /// @nodoc
@@ -52,6 +53,7 @@ class _$DAVCopyWithImpl<$Res, $Val extends DAV> implements $DAVCopyWith<$Res> {
Object? uri = null, Object? uri = null,
Object? user = null, Object? user = null,
Object? password = null, Object? password = null,
Object? fileName = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
uri: null == uri uri: null == uri
@@ -66,6 +68,10 @@ class _$DAVCopyWithImpl<$Res, $Val extends DAV> implements $DAVCopyWith<$Res> {
? _value.password ? _value.password
: password // ignore: cast_nullable_to_non_nullable : password // ignore: cast_nullable_to_non_nullable
as String, as String,
fileName: null == fileName
? _value.fileName
: fileName // ignore: cast_nullable_to_non_nullable
as String,
) as $Val); ) as $Val);
} }
} }
@@ -76,7 +82,7 @@ abstract class _$$DAVImplCopyWith<$Res> implements $DAVCopyWith<$Res> {
__$$DAVImplCopyWithImpl<$Res>; __$$DAVImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({String uri, String user, String password}); $Res call({String uri, String user, String password, String fileName});
} }
/// @nodoc /// @nodoc
@@ -91,6 +97,7 @@ class __$$DAVImplCopyWithImpl<$Res> extends _$DAVCopyWithImpl<$Res, _$DAVImpl>
Object? uri = null, Object? uri = null,
Object? user = null, Object? user = null,
Object? password = null, Object? password = null,
Object? fileName = null,
}) { }) {
return _then(_$DAVImpl( return _then(_$DAVImpl(
uri: null == uri uri: null == uri
@@ -105,6 +112,10 @@ class __$$DAVImplCopyWithImpl<$Res> extends _$DAVCopyWithImpl<$Res, _$DAVImpl>
? _value.password ? _value.password
: password // ignore: cast_nullable_to_non_nullable : password // ignore: cast_nullable_to_non_nullable
as String, as String,
fileName: null == fileName
? _value.fileName
: fileName // ignore: cast_nullable_to_non_nullable
as String,
)); ));
} }
} }
@@ -113,7 +124,10 @@ class __$$DAVImplCopyWithImpl<$Res> extends _$DAVCopyWithImpl<$Res, _$DAVImpl>
@JsonSerializable() @JsonSerializable()
class _$DAVImpl implements _DAV { class _$DAVImpl implements _DAV {
const _$DAVImpl( const _$DAVImpl(
{required this.uri, required this.user, required this.password}); {required this.uri,
required this.user,
required this.password,
this.fileName = defaultDavFileName});
factory _$DAVImpl.fromJson(Map<String, dynamic> json) => factory _$DAVImpl.fromJson(Map<String, dynamic> json) =>
_$$DAVImplFromJson(json); _$$DAVImplFromJson(json);
@@ -124,10 +138,13 @@ class _$DAVImpl implements _DAV {
final String user; final String user;
@override @override
final String password; final String password;
@override
@JsonKey()
final String fileName;
@override @override
String toString() { String toString() {
return 'DAV(uri: $uri, user: $user, password: $password)'; return 'DAV(uri: $uri, user: $user, password: $password, fileName: $fileName)';
} }
@override @override
@@ -138,12 +155,14 @@ class _$DAVImpl implements _DAV {
(identical(other.uri, uri) || other.uri == uri) && (identical(other.uri, uri) || other.uri == uri) &&
(identical(other.user, user) || other.user == user) && (identical(other.user, user) || other.user == user) &&
(identical(other.password, password) || (identical(other.password, password) ||
other.password == password)); other.password == password) &&
(identical(other.fileName, fileName) ||
other.fileName == fileName));
} }
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
int get hashCode => Object.hash(runtimeType, uri, user, password); int get hashCode => Object.hash(runtimeType, uri, user, password, fileName);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@@ -163,7 +182,8 @@ abstract class _DAV implements DAV {
const factory _DAV( const factory _DAV(
{required final String uri, {required final String uri,
required final String user, required final String user,
required final String password}) = _$DAVImpl; required final String password,
final String fileName}) = _$DAVImpl;
factory _DAV.fromJson(Map<String, dynamic> json) = _$DAVImpl.fromJson; factory _DAV.fromJson(Map<String, dynamic> json) = _$DAVImpl.fromJson;
@@ -174,6 +194,8 @@ abstract class _DAV implements DAV {
@override @override
String get password; String get password;
@override @override
String get fileName;
@override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$DAVImplCopyWith<_$DAVImpl> get copyWith => _$$DAVImplCopyWith<_$DAVImpl> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;

View File

@@ -10,10 +10,12 @@ _$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl(
uri: json['uri'] as String, uri: json['uri'] as String,
user: json['user'] as String, user: json['user'] as String,
password: json['password'] as String, password: json['password'] as String,
fileName: json['fileName'] as String? ?? defaultDavFileName,
); );
Map<String, dynamic> _$$DAVImplToJson(_$DAVImpl instance) => <String, dynamic>{ Map<String, dynamic> _$$DAVImplToJson(_$DAVImpl instance) => <String, dynamic>{
'uri': instance.uri, 'uri': instance.uri,
'user': instance.user, 'user': instance.user,
'password': instance.password, 'password': instance.password,
'fileName': instance.fileName,
}; };

View File

@@ -3472,6 +3472,7 @@ mixin _$ClashConfigState {
int get mixedPort => throw _privateConstructorUsedError; int get mixedPort => throw _privateConstructorUsedError;
bool get allowLan => throw _privateConstructorUsedError; bool get allowLan => throw _privateConstructorUsedError;
bool get ipv6 => throw _privateConstructorUsedError; bool get ipv6 => throw _privateConstructorUsedError;
bool get overrideDns => throw _privateConstructorUsedError;
String get geodataLoader => throw _privateConstructorUsedError; String get geodataLoader => throw _privateConstructorUsedError;
LogLevel get logLevel => throw _privateConstructorUsedError; LogLevel get logLevel => throw _privateConstructorUsedError;
String get externalController => throw _privateConstructorUsedError; String get externalController => throw _privateConstructorUsedError;
@@ -3502,6 +3503,7 @@ abstract class $ClashConfigStateCopyWith<$Res> {
{int mixedPort, {int mixedPort,
bool allowLan, bool allowLan,
bool ipv6, bool ipv6,
bool overrideDns,
String geodataLoader, String geodataLoader,
LogLevel logLevel, LogLevel logLevel,
String externalController, String externalController,
@@ -3537,6 +3539,7 @@ class _$ClashConfigStateCopyWithImpl<$Res, $Val extends ClashConfigState>
Object? mixedPort = null, Object? mixedPort = null,
Object? allowLan = null, Object? allowLan = null,
Object? ipv6 = null, Object? ipv6 = null,
Object? overrideDns = null,
Object? geodataLoader = null, Object? geodataLoader = null,
Object? logLevel = null, Object? logLevel = null,
Object? externalController = null, Object? externalController = null,
@@ -3565,6 +3568,10 @@ class _$ClashConfigStateCopyWithImpl<$Res, $Val extends ClashConfigState>
? _value.ipv6 ? _value.ipv6
: ipv6 // ignore: cast_nullable_to_non_nullable : ipv6 // ignore: cast_nullable_to_non_nullable
as bool, as bool,
overrideDns: null == overrideDns
? _value.overrideDns
: overrideDns // ignore: cast_nullable_to_non_nullable
as bool,
geodataLoader: null == geodataLoader geodataLoader: null == geodataLoader
? _value.geodataLoader ? _value.geodataLoader
: geodataLoader // ignore: cast_nullable_to_non_nullable : geodataLoader // ignore: cast_nullable_to_non_nullable
@@ -3653,6 +3660,7 @@ abstract class _$$ClashConfigStateImplCopyWith<$Res>
{int mixedPort, {int mixedPort,
bool allowLan, bool allowLan,
bool ipv6, bool ipv6,
bool overrideDns,
String geodataLoader, String geodataLoader,
LogLevel logLevel, LogLevel logLevel,
String externalController, String externalController,
@@ -3688,6 +3696,7 @@ class __$$ClashConfigStateImplCopyWithImpl<$Res>
Object? mixedPort = null, Object? mixedPort = null,
Object? allowLan = null, Object? allowLan = null,
Object? ipv6 = null, Object? ipv6 = null,
Object? overrideDns = null,
Object? geodataLoader = null, Object? geodataLoader = null,
Object? logLevel = null, Object? logLevel = null,
Object? externalController = null, Object? externalController = null,
@@ -3716,6 +3725,10 @@ class __$$ClashConfigStateImplCopyWithImpl<$Res>
? _value.ipv6 ? _value.ipv6
: ipv6 // ignore: cast_nullable_to_non_nullable : ipv6 // ignore: cast_nullable_to_non_nullable
as bool, as bool,
overrideDns: null == overrideDns
? _value.overrideDns
: overrideDns // ignore: cast_nullable_to_non_nullable
as bool,
geodataLoader: null == geodataLoader geodataLoader: null == geodataLoader
? _value.geodataLoader ? _value.geodataLoader
: geodataLoader // ignore: cast_nullable_to_non_nullable : geodataLoader // ignore: cast_nullable_to_non_nullable
@@ -3783,6 +3796,7 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
{required this.mixedPort, {required this.mixedPort,
required this.allowLan, required this.allowLan,
required this.ipv6, required this.ipv6,
required this.overrideDns,
required this.geodataLoader, required this.geodataLoader,
required this.logLevel, required this.logLevel,
required this.externalController, required this.externalController,
@@ -3808,6 +3822,8 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
@override @override
final bool ipv6; final bool ipv6;
@override @override
final bool overrideDns;
@override
final String geodataLoader; final String geodataLoader;
@override @override
final LogLevel logLevel; final LogLevel logLevel;
@@ -3856,7 +3872,7 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
@override @override
String toString() { String toString() {
return 'ClashConfigState(mixedPort: $mixedPort, allowLan: $allowLan, ipv6: $ipv6, geodataLoader: $geodataLoader, logLevel: $logLevel, externalController: $externalController, mode: $mode, findProcessMode: $findProcessMode, keepAliveInterval: $keepAliveInterval, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, hosts: $hosts, tun: $tun, dns: $dns, geoXUrl: $geoXUrl, rules: $rules, globalRealUa: $globalRealUa)'; return 'ClashConfigState(mixedPort: $mixedPort, allowLan: $allowLan, ipv6: $ipv6, overrideDns: $overrideDns, geodataLoader: $geodataLoader, logLevel: $logLevel, externalController: $externalController, mode: $mode, findProcessMode: $findProcessMode, keepAliveInterval: $keepAliveInterval, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, hosts: $hosts, tun: $tun, dns: $dns, geoXUrl: $geoXUrl, rules: $rules, globalRealUa: $globalRealUa)';
} }
@override @override
@@ -3869,6 +3885,8 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
(identical(other.allowLan, allowLan) || (identical(other.allowLan, allowLan) ||
other.allowLan == allowLan) && other.allowLan == allowLan) &&
(identical(other.ipv6, ipv6) || other.ipv6 == ipv6) && (identical(other.ipv6, ipv6) || other.ipv6 == ipv6) &&
(identical(other.overrideDns, overrideDns) ||
other.overrideDns == overrideDns) &&
(identical(other.geodataLoader, geodataLoader) || (identical(other.geodataLoader, geodataLoader) ||
other.geodataLoader == geodataLoader) && other.geodataLoader == geodataLoader) &&
(identical(other.logLevel, logLevel) || (identical(other.logLevel, logLevel) ||
@@ -3899,6 +3917,7 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
mixedPort, mixedPort,
allowLan, allowLan,
ipv6, ipv6,
overrideDns,
geodataLoader, geodataLoader,
logLevel, logLevel,
externalController, externalController,
@@ -3927,6 +3946,7 @@ abstract class _ClashConfigState implements ClashConfigState {
{required final int mixedPort, {required final int mixedPort,
required final bool allowLan, required final bool allowLan,
required final bool ipv6, required final bool ipv6,
required final bool overrideDns,
required final String geodataLoader, required final String geodataLoader,
required final LogLevel logLevel, required final LogLevel logLevel,
required final String externalController, required final String externalController,
@@ -3949,6 +3969,8 @@ abstract class _ClashConfigState implements ClashConfigState {
@override @override
bool get ipv6; bool get ipv6;
@override @override
bool get overrideDns;
@override
String get geodataLoader; String get geodataLoader;
@override @override
LogLevel get logLevel; LogLevel get logLevel;

View File

@@ -228,6 +228,7 @@ class ClashConfigState with _$ClashConfigState {
required int mixedPort, required int mixedPort,
required bool allowLan, required bool allowLan,
required bool ipv6, required bool ipv6,
required bool overrideDns,
required String geodataLoader, required String geodataLoader,
required LogLevel logLevel, required LogLevel logLevel,
required String externalController, required String externalController,

View File

@@ -7,11 +7,15 @@ import 'package:fl_clash/plugins/service.dart';
import 'package:fl_clash/plugins/vpn.dart'; import 'package:fl_clash/plugins/vpn.dart';
import 'package:fl_clash/widgets/scaffold.dart'; import 'package:fl_clash/widgets/scaffold.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:tray_manager/tray_manager.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'controller.dart'; import 'controller.dart';
import 'enum/enum.dart';
import 'l10n/l10n.dart';
import 'models/models.dart'; import 'models/models.dart';
import 'common/common.dart'; import 'common/common.dart';
@@ -23,11 +27,13 @@ class GlobalState {
late PackageInfo packageInfo; late PackageInfo packageInfo;
Function? updateCurrentDelayDebounce; Function? updateCurrentDelayDebounce;
PageController? pageController; PageController? pageController;
late Measure measure;
DateTime? startTime; DateTime? startTime;
final navigatorKey = GlobalKey<NavigatorState>(); final navigatorKey = GlobalKey<NavigatorState>();
late AppController appController; late AppController appController;
GlobalKey<CommonScaffoldState> homeScaffoldKey = GlobalKey(); GlobalKey<CommonScaffoldState> homeScaffoldKey = GlobalKey();
List<Function> updateFunctionLists = []; List<Function> updateFunctionLists = [];
var isTrayInit = false;
bool get isStart => startTime != null && startTime!.isBeforeNow; bool get isStart => startTime != null && startTime!.isBeforeNow;
@@ -190,6 +196,121 @@ class GlobalState {
); );
} }
_updateOtherTray() async {
if (isTrayInit == false) {
await trayManager.setIcon(
other.getTrayIconPath(),
);
await trayManager.setToolTip(
appName,
);
isTrayInit = true;
}
}
_updateLinuxTray() async {
await trayManager.destroy();
await trayManager.setIcon(
other.getTrayIconPath(),
);
await trayManager.setToolTip(
appName,
);
}
updateTray({
required AppState appState,
required Config config,
required ClashConfig clashConfig,
}) async {
final appLocalizations = await AppLocalizations.load(
other.getLocaleForString(config.locale) ??
WidgetsBinding.instance.platformDispatcher.locale,
);
if (!Platform.isLinux) {
_updateOtherTray();
}
List<MenuItem> menuItems = [];
final showMenuItem = MenuItem(
label: appLocalizations.show,
onClick: (_) {
window?.show();
},
);
menuItems.add(showMenuItem);
final startMenuItem = MenuItem.checkbox(
label: appState.isStart ? appLocalizations.stop : appLocalizations.start,
onClick: (_) async {
globalState.appController.updateStatus(!appState.isStart);
},
checked: false,
);
menuItems.add(startMenuItem);
menuItems.add(MenuItem.separator());
for (final mode in Mode.values) {
menuItems.add(
MenuItem.checkbox(
label: Intl.message(mode.name),
onClick: (_) {
globalState.appController.clashConfig.mode = mode;
},
checked: mode == appState.mode,
),
);
}
menuItems.add(MenuItem.separator());
if (appState.isStart) {
menuItems.add(
MenuItem.checkbox(
label: appLocalizations.tun,
onClick: (_) {
final clashConfig = globalState.appController.clashConfig;
clashConfig.tun = clashConfig.tun.copyWith(
enable: !clashConfig.tun.enable,
);
},
checked: clashConfig.tun.enable,
),
);
menuItems.add(
MenuItem.checkbox(
label: appLocalizations.systemProxy,
onClick: (_) {
final config = globalState.appController.config;
config.desktopProps = config.desktopProps.copyWith(
systemProxy: !config.desktopProps.systemProxy,
);
},
checked: config.desktopProps.systemProxy,
),
);
menuItems.add(MenuItem.separator());
}
final autoStartMenuItem = MenuItem.checkbox(
label: appLocalizations.autoLaunch,
onClick: (_) async {
globalState.appController.config.autoLaunch =
!globalState.appController.config.autoLaunch;
},
checked: config.autoLaunch,
);
menuItems.add(autoStartMenuItem);
menuItems.add(MenuItem.separator());
final exitMenuItem = MenuItem(
label: appLocalizations.exit,
onClick: (_) async {
await globalState.appController.handleExit();
},
);
menuItems.add(exitMenuItem);
final menu = Menu();
menu.items = menuItems;
trayManager.setContextMenu(menu);
if (Platform.isLinux) {
_updateLinuxTray();
}
}
changeProxy({ changeProxy({
required Config config, required Config config,
required String groupName, required String groupName,

View File

@@ -24,8 +24,9 @@ class _ClashContainerState extends State<ClashContainer>
Function? updateClashConfigDebounce; Function? updateClashConfigDebounce;
Widget _updateContainer(Widget child) { Widget _updateContainer(Widget child) {
return Selector<ClashConfig, ClashConfigState>( return Selector2<Config,ClashConfig, ClashConfigState>(
selector: (_, clashConfig) => ClashConfigState( selector: (_,config, clashConfig) => ClashConfigState(
overrideDns: config.overrideDns,
mixedPort: clashConfig.mixedPort, mixedPort: clashConfig.mixedPort,
allowLan: clashConfig.allowLan, allowLan: clashConfig.allowLan,
ipv6: clashConfig.ipv6, ipv6: clashConfig.ipv6,

View File

@@ -33,66 +33,68 @@ class ColorSchemeBox extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Theme( return AspectRatio(aspectRatio: 1,
data: _getTheme(context), child: Theme(
child: Builder( data: _getTheme(context),
builder: (context) { child: Builder(
final colorScheme = Theme.of(context).colorScheme; builder: (context) {
return Stack( final colorScheme = Theme.of(context).colorScheme;
children: [ return Stack(
CommonCard( children: [
isSelected: isSelected, CommonCard(
onPressed: onPressed, isSelected: isSelected,
selectWidget: Container( onPressed: onPressed,
alignment: Alignment.center, selectWidget: Container(
child: const SelectIcon(), alignment: Alignment.center,
), child: const SelectIcon(),
child: Container( ),
padding: const EdgeInsets.all(8), child: Container(
child: ClipRRect( padding: const EdgeInsets.all(8),
borderRadius: BorderRadius.circular(36), child: ClipRRect(
child: SizedBox( borderRadius: BorderRadius.circular(36),
width: 72, child: SizedBox(
height: 72, width: 72,
child: Grid( height: 72,
crossAxisCount: 2, child: Grid(
children: [ crossAxisCount: 2,
GridItem( children: [
mainAxisCellCount: 2, GridItem(
child: Container( mainAxisCellCount: 2,
color: colorScheme.primary, child: Container(
color: colorScheme.primary,
),
), ),
), GridItem(
GridItem( mainAxisCellCount: 1,
mainAxisCellCount: 1, child: Container(
child: Container( color: colorScheme.secondary,
color: colorScheme.secondary, ),
), ),
), GridItem(
GridItem( mainAxisCellCount: 1,
mainAxisCellCount: 1, child: Container(
child: Container( color: colorScheme.tertiary,
color: colorScheme.tertiary, ),
), )
) ],
], ),
), ),
), ),
), ),
), ),
), if (primaryColor == null)
if (primaryColor == null) const Positioned(
const Positioned( bottom: 4,
bottom: 4, right: 4,
right: 4, child: Icon(
child: Icon( Icons.colorize,
Icons.colorize, size: 20,
size: 20, ),
), )
) ],
], );
); },
}, ),
), ),
); );
} }

View File

@@ -57,12 +57,14 @@ class InputDialog extends StatefulWidget {
final String title; final String title;
final String value; final String value;
final String? suffixText; final String? suffixText;
final String? resetValue;
const InputDialog({ const InputDialog({
super.key, super.key,
required this.title, required this.title,
required this.value, required this.value,
this.suffixText, this.suffixText,
this.resetValue,
}); });
@override @override
@@ -92,6 +94,13 @@ class _InputDialogState extends State<InputDialog> {
Navigator.of(context).pop<String>(text); Navigator.of(context).pop<String>(text);
} }
_handleReset() async {
if (widget.resetValue == null) {
return;
}
Navigator.of(context).pop<String>(widget.resetValue);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
@@ -114,6 +123,16 @@ class _InputDialogState extends State<InputDialog> {
), ),
), ),
actions: [ actions: [
if (widget.resetValue != null &&
textController.value.text != widget.resetValue) ...[
TextButton(
onPressed: _handleReset,
child: Text(appLocalizations.reset),
),
const SizedBox(
width: 4,
),
],
TextButton( TextButton(
onPressed: _handleUpdate, onPressed: _handleUpdate,
child: Text(appLocalizations.submit), child: Text(appLocalizations.submit),

View File

@@ -120,9 +120,19 @@ class _LineChartState extends State<LineChart>
Path getPath(List<Point> points, Size size) { Path getPath(List<Point> points, Size size) {
final path = Path() final path = Path()
..moveTo(points[0].x * size.width, (1 - points[0].y) * size.height); ..moveTo(points[0].x * size.width, (1 - points[0].y) * size.height);
for (var i = 1; i < points.length; i++) {
path.lineTo(points[i].x * size.width, (1 - points[i].y) * size.height); for (var i = 1; i < points.length - 1; i++) {
final nextPoint = points[i + 1];
final currentPoint = points[i];
final midX = (currentPoint.x + nextPoint.x) / 2;
final midY = (currentPoint.y + nextPoint.y) / 2;
path.quadraticBezierTo(
currentPoint.x * size.width, (1 - currentPoint.y) * size.height,
midX * size.width, (1 - midY) * size.height,
);
} }
path.lineTo(points.last.x * size.width, (1 - points.last.y) * size.height);
return path; return path;
} }
@@ -132,7 +142,7 @@ class _LineChartState extends State<LineChart>
required progress, required progress,
}) { }) {
nextPoints = getInterpolatePoints(prevPoints, points, progress); nextPoints = getInterpolatePoints(prevPoints, points, progress);
Path setSize(Size size) { return (size) {
final prevPath = getPath(prevPoints, size); final prevPath = getPath(prevPoints, size);
final nextPath = getPath(nextPoints, size); final nextPath = getPath(nextPoints, size);
final prevMetric = prevPath.computeMetrics().first; final prevMetric = prevPath.computeMetrics().first;
@@ -143,9 +153,7 @@ class _LineChartState extends State<LineChart>
0, 0,
prevLength + (nextLength - prevLength) * progress, prevLength + (nextLength - prevLength) * progress,
); );
} };
return setSize;
} }
@override @override

View File

@@ -50,12 +50,14 @@ class OpenDelegate extends Delegate {
final String title; final String title;
final double? extendPageWidth; final double? extendPageWidth;
final bool isBlur; final bool isBlur;
final bool isScaffold;
const OpenDelegate({ const OpenDelegate({
required this.title, required this.title,
required this.widget, required this.widget,
this.extendPageWidth, this.extendPageWidth,
this.isBlur = true, this.isBlur = true,
this.isScaffold = false,
}); });
} }
@@ -92,12 +94,14 @@ class InputDelegate extends Delegate {
final String value; final String value;
final String? suffixText; final String? suffixText;
final Function(String? value) onChanged; final Function(String? value) onChanged;
final String? resetValue;
const InputDelegate({ const InputDelegate({
required this.title, required this.title,
required this.value, required this.value,
this.suffixText, this.suffixText,
required this.onChanged, required this.onChanged,
this.resetValue,
}); });
} }
@@ -287,6 +291,7 @@ class ListItem<T> extends StatelessWidget {
title: openDelegate.title, title: openDelegate.title,
extendPageWidth: openDelegate.extendPageWidth, extendPageWidth: openDelegate.extendPageWidth,
isBlur: openDelegate.isBlur, isBlur: openDelegate.isBlur,
isScaffold: openDelegate.isScaffold,
); );
return; return;
} }
@@ -332,6 +337,7 @@ class ListItem<T> extends StatelessWidget {
title: inputDelegate.title, title: inputDelegate.title,
value: inputDelegate.value, value: inputDelegate.value,
suffixText: inputDelegate.suffixText, suffixText: inputDelegate.suffixText,
resetValue: inputDelegate.resetValue,
), ),
); );
inputDelegate.onChanged(value); inputDelegate.onChanged(value);

View File

@@ -0,0 +1,35 @@
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/models/config.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class MediaContainer extends StatelessWidget {
final Widget child;
const MediaContainer({
super.key,
required this.child,
});
@override
Widget build(BuildContext context) {
return Selector<Config, ScaleProps>(
selector: (_, config) => config.scaleProps,
builder: (_, props, child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: props.custom ? TextScaler.linear(props.scale) : null,
),
child: Builder(
builder: (context) {
globalState.measure = Measure.of(context);
return child!;
},
),
);
},
child: child,
);
}
}

View File

@@ -10,7 +10,7 @@ showExtendPage(
required Widget body, required Widget body,
required String title, required String title,
double? extendPageWidth, double? extendPageWidth,
bool forceNotSide = false, bool isScaffold = false,
bool isBlur = true, bool isBlur = true,
Widget? action, Widget? action,
}) { }) {
@@ -33,7 +33,7 @@ showExtendPage(
); );
return; return;
} }
final isNotSide = isMobile || forceNotSide; final isNotSide = isMobile || isScaffold;
navigator.push( navigator.push(
ModalSideSheetRoute( ModalSideSheetRoute(
modalBarrierColor: Colors.black38, modalBarrierColor: Colors.black38,

View File

@@ -16,7 +16,7 @@ class TooltipText extends StatelessWidget {
return LayoutBuilder( return LayoutBuilder(
builder: (context, container) { builder: (context, container) {
final maxWidth = container.maxWidth; final maxWidth = container.maxWidth;
final size = globalState.appController.measure.computeTextSize( final size = globalState.measure.computeTextSize(
text, text,
); );
if (maxWidth < size.width) { if (maxWidth < size.width) {

View File

@@ -22,7 +22,6 @@ class TrayContainer extends StatefulWidget {
} }
class _TrayContainerState extends State<TrayContainer> with TrayListener { class _TrayContainerState extends State<TrayContainer> with TrayListener {
var isTrayInit = false;
@override @override
void initState() { void initState() {
@@ -30,113 +29,6 @@ class _TrayContainerState extends State<TrayContainer> with TrayListener {
trayManager.addListener(this); trayManager.addListener(this);
} }
_updateOtherTray() async {
if (isTrayInit == false) {
await trayManager.setIcon(
other.getTrayIconPath(),
);
await trayManager.setToolTip(
appName,
);
isTrayInit = true;
}
}
_updateLinuxTray() async {
await trayManager.destroy();
await trayManager.setIcon(
other.getTrayIconPath(),
);
await trayManager.setToolTip(
appName,
);
}
updateMenu(TrayContainerSelectorState state) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!Platform.isLinux) {
_updateOtherTray();
}
List<MenuItem> menuItems = [];
final showMenuItem = MenuItem(
label: appLocalizations.show,
onClick: (_) {
window?.show();
},
);
menuItems.add(showMenuItem);
final startMenuItem = MenuItem.checkbox(
label: state.isStart ? appLocalizations.stop : appLocalizations.start,
onClick: (_) async {
globalState.appController.updateStatus(!state.isStart);
},
checked: false,
);
menuItems.add(startMenuItem);
menuItems.add(MenuItem.separator());
for (final mode in Mode.values) {
menuItems.add(
MenuItem.checkbox(
label: Intl.message(mode.name),
onClick: (_) {
globalState.appController.clashConfig.mode = mode;
},
checked: mode == state.mode,
),
);
}
menuItems.add(MenuItem.separator());
if (state.isStart) {
menuItems.add(
MenuItem.checkbox(
label: appLocalizations.tun,
onClick: (_) {
final clashConfig = globalState.appController.clashConfig;
clashConfig.tun =
clashConfig.tun.copyWith(enable: !state.tunEnable);
},
checked: state.tunEnable,
),
);
menuItems.add(
MenuItem.checkbox(
label: appLocalizations.systemProxy,
onClick: (_) {
final config = globalState.appController.config;
config.desktopProps =
config.desktopProps.copyWith(systemProxy: !state.systemProxy);
},
checked: state.systemProxy,
),
);
menuItems.add(MenuItem.separator());
}
final autoStartMenuItem = MenuItem.checkbox(
label: appLocalizations.autoLaunch,
onClick: (_) async {
globalState.appController.config.autoLaunch =
!globalState.appController.config.autoLaunch;
},
checked: state.autoLaunch,
);
menuItems.add(autoStartMenuItem);
menuItems.add(MenuItem.separator());
final exitMenuItem = MenuItem(
label: appLocalizations.exit,
onClick: (_) async {
await globalState.appController.handleExit();
},
);
menuItems.add(exitMenuItem);
final menu = Menu();
menu.items = menuItems;
trayManager.setContextMenu(menu);
if (Platform.isLinux) {
_updateLinuxTray();
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Selector3<AppState, Config, ClashConfig, TrayContainerSelectorState>( return Selector3<AppState, Config, ClashConfig, TrayContainerSelectorState>(
@@ -149,8 +41,13 @@ class _TrayContainerState extends State<TrayContainer> with TrayListener {
systemProxy: config.desktopProps.systemProxy, systemProxy: config.desktopProps.systemProxy,
tunEnable: clashConfig.tun.enable, tunEnable: clashConfig.tun.enable,
), ),
shouldRebuild: (prev,next){
if(prev != next){
globalState.appController.updateTray();
}
return prev != next;
},
builder: (_, state, child) { builder: (_, state, child) {
updateMenu(state);
return child!; return child!;
}, },
child: widget.child, child: widget.child,

View File

@@ -28,3 +28,4 @@ export 'builder.dart';
export 'setting.dart'; export 'setting.dart';
export 'vpn_container.dart'; export 'vpn_container.dart';
export 'input.dart'; export 'input.dart';
export 'media_container.dart';

View File

@@ -1,7 +1,7 @@
name: fl_clash name: fl_clash
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free. description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
publish_to: 'none' publish_to: 'none'
version: 0.8.57+202409021 version: 0.8.58+202409081
environment: environment:
sdk: '>=3.1.0 <4.0.0' sdk: '>=3.1.0 <4.0.0'
flutter: 3.22.3 flutter: 3.22.3

View File

@@ -2,16 +2,14 @@
import 'dart:io'; import 'dart:io';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/common/other.dart'; import 'package:fl_clash/common/other.dart';
import 'package:lpinyin/lpinyin.dart'; import 'package:lpinyin/lpinyin.dart';
void main() { void main() {
final res = const [ final res = [1, 2, 3, 4, 5, 6,7,8,9,10,11];
"https://doh.pub/dns-query",
"https://dns.alidns.com/dns-query"
];
List.from(res)..remove("https://doh.pub/dns-query"); print(res.batch(5));
} }
startService() async { startService() async {