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:
Submodule core/Clash.Meta updated: 8d1f6620f7...53b2dbba62
@@ -4,6 +4,7 @@ import "C"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
route "github.com/metacubex/mihomo/hub/route"
|
||||
"math"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -21,13 +22,11 @@ import (
|
||||
"github.com/metacubex/mihomo/common/batch"
|
||||
"github.com/metacubex/mihomo/component/dialer"
|
||||
"github.com/metacubex/mihomo/component/resolver"
|
||||
"github.com/metacubex/mihomo/component/sniffer"
|
||||
"github.com/metacubex/mihomo/config"
|
||||
"github.com/metacubex/mihomo/constant"
|
||||
cp "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/hub"
|
||||
"github.com/metacubex/mihomo/hub/executor"
|
||||
"github.com/metacubex/mihomo/hub/route"
|
||||
"github.com/metacubex/mihomo/listener"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
rp "github.com/metacubex/mihomo/rules/provider"
|
||||
@@ -191,7 +190,7 @@ func toExternalProvider(p cp.Provider) (*ExternalProvider, error) {
|
||||
VehicleType: psp.VehicleType().String(),
|
||||
Count: psp.Count(),
|
||||
Path: psp.Vehicle().Path(),
|
||||
UpdateAt: psp.UpdatedAt,
|
||||
UpdateAt: psp.UpdatedAt(),
|
||||
}, nil
|
||||
case *rp.RuleSetProvider:
|
||||
rsp := p.(*rp.RuleSetProvider)
|
||||
@@ -201,7 +200,7 @@ func toExternalProvider(p cp.Provider) (*ExternalProvider, error) {
|
||||
VehicleType: rsp.VehicleType().String(),
|
||||
Count: rsp.Count(),
|
||||
Path: rsp.Vehicle().Path(),
|
||||
UpdateAt: rsp.UpdatedAt,
|
||||
UpdateAt: rsp.UpdatedAt(),
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.New("not external provider")
|
||||
@@ -411,12 +410,13 @@ func overwriteConfig(targetConfig *config.RawConfig, patchConfig config.RawConfi
|
||||
targetConfig.Profile.StoreSelected = false
|
||||
targetConfig.GeoXUrl = patchConfig.GeoXUrl
|
||||
targetConfig.GlobalUA = patchConfig.GlobalUA
|
||||
//if targetConfig.DNS.Enable == false {
|
||||
// targetConfig.DNS = patchConfig.DNS
|
||||
//}
|
||||
genHosts(targetConfig.Hosts, patchConfig.Hosts)
|
||||
if configParams.OverrideDns {
|
||||
targetConfig.DNS = patchConfig.DNS
|
||||
} else {
|
||||
if targetConfig.DNS.Enable == false {
|
||||
targetConfig.DNS.Enable = true
|
||||
}
|
||||
}
|
||||
//if runtime.GOOS == "android" {
|
||||
// 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")
|
||||
route.ReStartServer(general.ExternalController)
|
||||
if sniffer.Dispatcher != nil {
|
||||
route.ReStartServer(controller.ExternalController)
|
||||
tunnel.SetSniffing(general.Sniffing)
|
||||
}
|
||||
tunnel.SetFindProcessMode(general.FindProcessMode)
|
||||
dialer.SetTcpConcurrent(general.TCPConcurrent)
|
||||
dialer.DefaultInterface.Store(general.Interface)
|
||||
@@ -455,6 +453,7 @@ func updateListeners(general *config.General, listeners map[string]constant.Inbo
|
||||
}
|
||||
runLock.Lock()
|
||||
defer runLock.Unlock()
|
||||
|
||||
listener.PatchInboundListeners(listeners, tunnel.Tunnel, true)
|
||||
listener.SetAllowLan(general.AllowLan)
|
||||
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.ReCreateSocks(general.SocksPort, tunnel.Tunnel)
|
||||
listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel)
|
||||
listener.ReCreateAutoRedir(general.EBpf.AutoRedir, tunnel.Tunnel)
|
||||
listener.ReCreateTProxy(general.TProxyPort, tunnel.Tunnel)
|
||||
listener.ReCreateMixed(general.MixedPort, tunnel.Tunnel)
|
||||
listener.ReCreateShadowSocks(general.ShadowSocksConfig, tunnel.Tunnel)
|
||||
listener.ReCreateVmess(general.VmessConfig, tunnel.Tunnel)
|
||||
listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel)
|
||||
listener.ReCreateTun(general.Tun, tunnel.Tunnel)
|
||||
listener.ReCreateRedirToTun(general.EBpf.RedirectToTun)
|
||||
}
|
||||
|
||||
func stopListeners() {
|
||||
@@ -533,7 +530,7 @@ func applyConfig() error {
|
||||
constant.DefaultTestURL = *configParams.TestURL
|
||||
}
|
||||
if configParams.IsPatch {
|
||||
patchConfig(cfg.General)
|
||||
patchConfig(cfg.General, cfg.Controller)
|
||||
} else {
|
||||
closeConnections()
|
||||
runtime.GC()
|
||||
@@ -541,7 +538,9 @@ func applyConfig() error {
|
||||
patchSelectGroup()
|
||||
}
|
||||
updateListeners(cfg.General, cfg.Listeners)
|
||||
if isRunning {
|
||||
hcCompatibleProvider(cfg.Providers)
|
||||
}
|
||||
externalProviders = getExternalProvidersRaw()
|
||||
return err
|
||||
}
|
||||
|
||||
47
core/go.mod
47
core/go.mod
@@ -7,9 +7,8 @@ replace github.com/metacubex/mihomo => ./Clash.Meta
|
||||
require (
|
||||
github.com/Kr328/tun2socket v0.0.0-20220414050025-d07c78d06d34
|
||||
github.com/metacubex/mihomo v1.17.1
|
||||
github.com/miekg/dns v1.1.61
|
||||
golang.org/x/net v0.26.0
|
||||
golang.org/x/sync v0.7.0
|
||||
github.com/miekg/dns v1.1.62
|
||||
golang.org/x/sync v0.8.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -20,17 +19,16 @@ require (
|
||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // 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/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/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
|
||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
|
||||
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // 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/render v1.0.3 // 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/pool v0.2.1 // 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/go-cmp v0.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // 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/klauspost/compress v1.17.9 // 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/mdlayher/netlink v1.7.2 // 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/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // 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/sing-quic v0.0.0-20240518034124-7696d3f7da72 // indirect
|
||||
github.com/metacubex/sing-shadowsocks v0.2.7 // indirect
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.1 // indirect
|
||||
github.com/metacubex/sing-tun v0.2.7-0.20240719141246-19c49ac9589d // indirect
|
||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 // indirect
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8 // indirect
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.2 // 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-wireguard v0.0.0-20240618022557-a6efaa37127a // indirect
|
||||
github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66 // indirect
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20240826061955-1e4e67afe5cd // indirect
|
||||
github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785 // indirect
|
||||
github.com/metacubex/utls v1.6.6 // indirect
|
||||
github.com/mroth/weightedrand/v2 v2.1.0 // 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/pierrec/lz4/v4 v4.1.14 // 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/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/netlink v0.0.0-20240612041022-b9a21c07ac6a // 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/smux v0.0.0-20231208180855-7041f6ea79e7 // 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/shoenig/go-m1cpu v0.1.6 // 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
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||
golang.org/x/crypto v0.24.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/crypto v0.26.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/net v0.28.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/tools v0.22.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
|
||||
106
core/go.sum
106
core/go.sum
@@ -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/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/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/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
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.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||
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/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I=
|
||||
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/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA=
|
||||
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/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
|
||||
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.0.14/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||
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/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
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/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs=
|
||||
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.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
|
||||
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.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
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/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
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-20240529192340-51bc6136a0a6/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240812123929-b105c29bd1b5 h1:GkMacU5ftc+IEg1449N3UEy2XLDz58W4fkrRu2fibb8=
|
||||
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/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
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/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
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/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
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/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
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/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/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/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw=
|
||||
github.com/metacubex/quic-go v0.45.1-0.20240610004319-163fee60637e h1:bLYn3GuRvWDcBDAkIv5kUYIhzHwafDVq635BuybnKqI=
|
||||
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 h1:T6OxROLZBr9SOQxN5TzUslv81hEREy/dEgaUKVjaG7U=
|
||||
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/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-20240518034124-7696d3f7da72/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.7/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.1/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.20240719141246-19c49ac9589d/go.mod h1:olbEx9yVcaw5tHTNlRamRoxmMKcvDvcVS1YLnQGzvWE=
|
||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 h1:HobpULaPK6OoxrHMmgcwLkwwIduXVmwdcznwUfH1GQM=
|
||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8=
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4=
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0=
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo=
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q=
|
||||
github.com/metacubex/sing-tun v0.2.7-0.20240729131039-ed03f557dee1 h1:ypfofGDZbP8p3Y4P/m74JYu7sQViesi3c8nbmT6cS0Y=
|
||||
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/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-20240618022557-a6efaa37127a/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-20240228025757-be1269474a66/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts=
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20240826061955-1e4e67afe5cd h1:r7alry8u4qlUFLNMwGvG1A8ZcfPM6AMSmrm6E2yKdB4=
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20240826061955-1e4e67afe5cd/go.mod h1:uY+BYb0UEknLrqvbGcwi9i++KgrKxsurysgI6G1Pveo=
|
||||
github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785 h1:NNmI+ZV0DzNuqaAInRQuZFLHlWVuyHeow8jYpdKjHjo=
|
||||
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/go.mod h1:+WLFUnXjcpdxXCnyX25nggw8C6YonZ8zOK2Zm/oRvdo=
|
||||
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
||||
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
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/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU=
|
||||
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/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/puzpuzpuz/xsync/v3 v3.2.0 h1:9AzuUeF88YC5bK8u2vEG1Fpvu4wgpM1wfPIExfaaDxQ=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.2.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4=
|
||||
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/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/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/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
|
||||
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/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/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
|
||||
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
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/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
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=
|
||||
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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||
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/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.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
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-20190412213103-97732733099d/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.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.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
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.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
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/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.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
|
||||
@@ -5,9 +5,11 @@ package main
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
bridge "core/dart-bridge"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
@@ -18,7 +20,6 @@ import (
|
||||
"github.com/metacubex/mihomo/adapter"
|
||||
"github.com/metacubex/mihomo/adapter/outboundgroup"
|
||||
"github.com/metacubex/mihomo/adapter/provider"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"github.com/metacubex/mihomo/component/updater"
|
||||
"github.com/metacubex/mihomo/config"
|
||||
"github.com/metacubex/mihomo/constant"
|
||||
@@ -27,7 +28,6 @@ import (
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
"github.com/metacubex/mihomo/tunnel/statistic"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var currentRawConfig = config.DefaultRawConfig()
|
||||
@@ -225,11 +225,13 @@ func asyncTestDelay(s *C.char, port C.longlong) {
|
||||
var params = &TestDelayParams{}
|
||||
err := json.Unmarshal([]byte(paramsString), params)
|
||||
if err != nil {
|
||||
bridge.SendToPort(i, "")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
expectedStatus, err := utils.NewUnsignedRanges[uint16]("")
|
||||
if err != nil {
|
||||
bridge.SendToPort(i, "")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -238,7 +240,6 @@ func asyncTestDelay(s *C.char, port C.longlong) {
|
||||
|
||||
proxies := tunnel.ProxiesWithProviders()
|
||||
proxy := proxies[params.ProxyName]
|
||||
proxy.Name()
|
||||
|
||||
delayData := &Delay{
|
||||
Name: params.ProxyName,
|
||||
|
||||
@@ -158,7 +158,9 @@ class ApplicationState extends State<Application> {
|
||||
GlobalWidgetsLocalizations.delegate
|
||||
],
|
||||
builder: (_, child) {
|
||||
return _buildPage(child!);
|
||||
return MediaContainer(
|
||||
child: _buildPage(child!),
|
||||
);
|
||||
},
|
||||
scrollBehavior: BaseScrollBehavior(),
|
||||
title: appName,
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:webdav_client/webdav_client.dart';
|
||||
class DAVClient {
|
||||
late Client client;
|
||||
Completer<bool> pingCompleter = Completer();
|
||||
late String fileName;
|
||||
|
||||
DAVClient(DAV dav) {
|
||||
client = newClient(
|
||||
@@ -15,6 +16,7 @@ class DAVClient {
|
||||
user: dav.user,
|
||||
password: dav.password,
|
||||
);
|
||||
fileName = dav.fileName;
|
||||
client.setHeaders(
|
||||
{
|
||||
'accept-charset': 'utf-8',
|
||||
@@ -38,7 +40,7 @@ class DAVClient {
|
||||
|
||||
get root => "/$appName";
|
||||
|
||||
get backupFile => "$root/backup.zip";
|
||||
get backupFile => "$root/$fileName";
|
||||
|
||||
backup(Uint8List data) async {
|
||||
await client.mkdir("$root");
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import '../state.dart';
|
||||
|
||||
class FlClashHttpOverrides extends HttpOverrides {
|
||||
|
||||
@override
|
||||
HttpClient createHttpClient(SecurityContext? context) {
|
||||
final client = super.createHttpClient(context);
|
||||
client.badCertificateCallback = (_, __, ___) => true;
|
||||
client.findProxy = (url) {
|
||||
debugPrint("find $url");
|
||||
final port = globalState.appController.clashConfig.mixedPort;
|
||||
final isStart = globalState.appController.appState.isStart;
|
||||
if(!isStart) return "DIRECT";
|
||||
return "PROXY localhost:$port;DIRECT";
|
||||
if (!isStart) return "DIRECT";
|
||||
return "PROXY localhost:$port";
|
||||
};
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -2,4 +2,17 @@ extension ListExtension<T> on List<T> {
|
||||
List<T> intersection(List<T> list) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -3,23 +3,21 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Measure {
|
||||
Measure.of(this.context);
|
||||
final TextScaler _textScale;
|
||||
late BuildContext context;
|
||||
|
||||
final _textScaleFactor =
|
||||
WidgetsBinding.instance.platformDispatcher.textScaleFactor;
|
||||
Measure.of(this.context) : _textScale = MediaQuery.of(context).textScaler;
|
||||
|
||||
Size computeTextSize(Text text) {
|
||||
final textPainter = TextPainter(
|
||||
text: TextSpan(text: text.data, style: text.style),
|
||||
maxLines: text.maxLines,
|
||||
textScaler: TextScaler.linear(_textScaleFactor),
|
||||
textScaler: _textScale,
|
||||
textDirection: text.textDirection ?? TextDirection.ltr,
|
||||
)..layout();
|
||||
return textPainter.size;
|
||||
}
|
||||
|
||||
late BuildContext context;
|
||||
|
||||
double? _bodyMediumHeight;
|
||||
double? _bodySmallHeight;
|
||||
double? _labelSmallHeight;
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:fl_clash/common/archive.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lpinyin/lpinyin.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
@@ -22,7 +21,6 @@ class AppController {
|
||||
late AppState appState;
|
||||
late Config config;
|
||||
late ClashConfig clashConfig;
|
||||
late Measure measure;
|
||||
late Function updateClashConfigDebounce;
|
||||
late Function updateGroupDebounce;
|
||||
late Function addCheckIpNumDebounce;
|
||||
@@ -44,7 +42,6 @@ class AppController {
|
||||
updateGroupDebounce = debounce(() async {
|
||||
await updateGroups();
|
||||
});
|
||||
measure = Measure.of(context);
|
||||
}
|
||||
|
||||
updateStatus(bool isStart) async {
|
||||
@@ -125,10 +122,6 @@ class AppController {
|
||||
);
|
||||
}
|
||||
|
||||
updateTray(){
|
||||
|
||||
}
|
||||
|
||||
Future applyProfile({bool isPrue = false}) async {
|
||||
if (isPrue) {
|
||||
await globalState.applyProfile(
|
||||
@@ -317,6 +310,14 @@ class AppController {
|
||||
autoCheckUpdate();
|
||||
}
|
||||
|
||||
updateTray() {
|
||||
globalState.updateTray(
|
||||
appState: appState,
|
||||
config: config,
|
||||
clashConfig: clashConfig,
|
||||
);
|
||||
}
|
||||
|
||||
setDelay(Delay delay) {
|
||||
appState.setDelay(delay);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ class BackupAndRecovery extends StatelessWidget {
|
||||
other.getBackupFileName(),
|
||||
Uint8List.fromList(backupData),
|
||||
);
|
||||
if(value == null) return false;
|
||||
if (value == null) return false;
|
||||
return true;
|
||||
},
|
||||
title: appLocalizations.backup,
|
||||
@@ -204,6 +204,24 @@ class BackupAndRecovery extends StatelessWidget {
|
||||
const SizedBox(
|
||||
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(
|
||||
onTap: () {
|
||||
_backupOnWebDAV(context, client);
|
||||
|
||||
@@ -72,6 +72,7 @@ class _ConfigFragmentState extends State<ConfigFragment> {
|
||||
widget: generateListView(
|
||||
dnsItems,
|
||||
),
|
||||
isScaffold: true,
|
||||
isBlur: false,
|
||||
extendPageWidth: 360,
|
||||
),
|
||||
|
||||
@@ -11,8 +11,27 @@ import 'package:provider/provider.dart';
|
||||
class OverrideItem extends StatelessWidget {
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
_initActions(context);
|
||||
return Selector<Config, bool>(
|
||||
selector: (_, config) => config.overrideDns,
|
||||
builder: (_, override, __) {
|
||||
@@ -35,8 +54,7 @@ class OverrideItem extends StatelessWidget {
|
||||
class DnsDisabledContainer extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const DnsDisabledContainer(
|
||||
this.child, {
|
||||
const DnsDisabledContainer(this.child, {
|
||||
super.key,
|
||||
});
|
||||
|
||||
@@ -260,7 +278,8 @@ class FakeIpFilterItem extends StatelessWidget {
|
||||
final clashConfig = globalState.appController.clashConfig;
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fakeIpFilter: List.from(dns.fakeIpFilter)..remove(value),
|
||||
fakeIpFilter: List.from(dns.fakeIpFilter)
|
||||
..remove(value),
|
||||
);
|
||||
},
|
||||
onAdd: (value) {
|
||||
@@ -268,7 +287,8 @@ class FakeIpFilterItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
if (fakeIpFilter.contains(value)) return;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fakeIpFilter: List.from(dns.fakeIpFilter)..add(value),
|
||||
fakeIpFilter: List.from(dns.fakeIpFilter)
|
||||
..add(value),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -350,7 +370,8 @@ class NameserverItem extends StatelessWidget {
|
||||
final clashConfig = globalState.appController.clashConfig;
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
nameserver: List.from(dns.nameserver)..remove(value),
|
||||
nameserver: List.from(dns.nameserver)
|
||||
..remove(value),
|
||||
);
|
||||
},
|
||||
onAdd: (value) {
|
||||
@@ -358,7 +379,8 @@ class NameserverItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
if (nameserver.contains(value)) return;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
nameserver: List.from(dns.nameserver)..add(value),
|
||||
nameserver: List.from(dns.nameserver)
|
||||
..add(value),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -539,7 +561,8 @@ class FallbackItem extends StatelessWidget {
|
||||
final clashConfig = globalState.appController.clashConfig;
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallback: List.from(dns.fallback)..remove(value),
|
||||
fallback: List.from(dns.fallback)
|
||||
..remove(value),
|
||||
);
|
||||
},
|
||||
onAdd: (value) {
|
||||
@@ -547,7 +570,8 @@ class FallbackItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
if (fallback.contains(value)) return;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallback: List.from(dns.fallback)..add(value),
|
||||
fallback: List.from(dns.fallback)
|
||||
..add(value),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -650,7 +674,8 @@ class GeositeItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.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;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallbackFilter: dns.fallbackFilter.copyWith(
|
||||
geosite: List.from(geosite)..add(value),
|
||||
geosite: List.from(geosite)
|
||||
..add(value),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -696,7 +722,8 @@ class IpcidrItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.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;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallbackFilter: dns.fallbackFilter.copyWith(
|
||||
ipcidr: List.from(ipcidr)..add(value),
|
||||
ipcidr: List.from(ipcidr)
|
||||
..add(value),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -742,7 +770,8 @@ class DomainItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.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;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallbackFilter: dns.fallbackFilter.copyWith(
|
||||
domain: List.from(domain)..add(value),
|
||||
domain: List.from(domain)
|
||||
..add(value),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -85,7 +85,8 @@ class KeepAliveIntervalItem extends StatelessWidget {
|
||||
delegate: InputDelegate(
|
||||
title: appLocalizations.keepAliveIntervalDesc,
|
||||
suffixText: appLocalizations.seconds,
|
||||
value: value.toString(),
|
||||
resetValue: "$defaultKeepAliveInterval",
|
||||
value: "$value",
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
@@ -125,6 +126,7 @@ class TestUrlItem extends StatelessWidget {
|
||||
title: Text(appLocalizations.testUrl),
|
||||
subtitle: Text(value),
|
||||
delegate: InputDelegate(
|
||||
resetValue: defaultTestUrl,
|
||||
title: appLocalizations.testUrl,
|
||||
value: value,
|
||||
onChanged: (String? value) {
|
||||
@@ -165,7 +167,7 @@ class MixedPortItem extends StatelessWidget {
|
||||
subtitle: Text("$value"),
|
||||
delegate: InputDelegate(
|
||||
title: appLocalizations.proxyPort,
|
||||
value: value.toString(),
|
||||
value: "$value",
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
@@ -184,6 +186,7 @@ class MixedPortItem extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
},
|
||||
resetValue: "$defaultMixedPort",
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -53,7 +53,7 @@ class _IntranetIPState extends State<IntranetIP> {
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16).copyWith(top: 0),
|
||||
height: globalState.appController.measure.titleLargeHeight + 24 - 2,
|
||||
height: globalState.measure.titleLargeHeight + 24 - 2,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: ipNotifier,
|
||||
builder: (_, value, __) {
|
||||
|
||||
@@ -46,9 +46,7 @@ class _NetworkDetectionState extends State<NetworkDetection> {
|
||||
isTesting: false,
|
||||
ipInfo: ipInfo,
|
||||
);
|
||||
} catch (_) {
|
||||
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
_checkIpContainer(Widget child) {
|
||||
@@ -122,7 +120,7 @@ class _NetworkDetectionState extends State<NetworkDetection> {
|
||||
: ipInfo != null
|
||||
? Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
height: globalState.appController
|
||||
height: globalState
|
||||
.measure.titleMediumHeight,
|
||||
child: Text(
|
||||
countryCodeToEmoji(
|
||||
@@ -150,9 +148,7 @@ class _NetworkDetectionState extends State<NetworkDetection> {
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: globalState.appController.measure.titleLargeHeight +
|
||||
24 -
|
||||
2,
|
||||
height: globalState.measure.titleLargeHeight + 24 - 2,
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: const EdgeInsets.all(16).copyWith(top: 0),
|
||||
child: FadeBox(
|
||||
|
||||
@@ -59,7 +59,7 @@ class _NetworkSpeedState extends State<NetworkSpeed> {
|
||||
style: bodyMedium,
|
||||
maxLines: 1,
|
||||
);
|
||||
final size = globalState.appController.measure.computeTextSize(valueText);
|
||||
final size = globalState.measure.computeTextSize(valueText);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
|
||||
@@ -74,7 +74,7 @@ class _StartButtonState extends State<StartButton>
|
||||
if (!state.isInit || !state.hasProfile) {
|
||||
return Container();
|
||||
}
|
||||
final textWidth = globalState.appController.measure
|
||||
final textWidth = globalState.measure
|
||||
.computeTextSize(
|
||||
Text(
|
||||
other.getTimeDifference(
|
||||
|
||||
@@ -495,28 +495,31 @@ class _ReorderableProfilesState extends State<ReorderableProfiles> {
|
||||
itemCount: profiles.length,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 12,
|
||||
horizontal: 24,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
IconButton(
|
||||
child: FilledButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
globalState.appController.config.profiles = profiles;
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.check,
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(
|
||||
const EdgeInsets.symmetric(vertical: 16),
|
||||
),
|
||||
iconSize: 32,
|
||||
padding: const EdgeInsets.all(8),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
appLocalizations.confirm,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class ProxyCard extends StatelessWidget {
|
||||
required this.type,
|
||||
});
|
||||
|
||||
Measure get measure => globalState.appController.measure;
|
||||
Measure get measure => globalState.measure;
|
||||
|
||||
Widget _buildDelayText() {
|
||||
return SizedBox(
|
||||
@@ -119,7 +119,7 @@ class ProxyCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final measure = globalState.appController.measure;
|
||||
final measure = globalState.measure;
|
||||
final delayText = _buildDelayText();
|
||||
final proxyNameText = _buildProxyNameText(context);
|
||||
return currentGroupProxyNameBuilder(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:math';
|
||||
|
||||
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/models/models.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
@@ -25,12 +25,12 @@ Widget currentGroupProxyNameBuilder({
|
||||
}
|
||||
|
||||
double get listHeaderHeight {
|
||||
final measure = globalState.appController.measure;
|
||||
final measure = globalState.measure;
|
||||
return 24 + measure.titleMediumHeight + 4 + measure.bodyMediumHeight;
|
||||
}
|
||||
|
||||
double getItemHeight(ProxyCardType proxyCardType) {
|
||||
final measure = globalState.appController.measure;
|
||||
final measure = globalState.measure;
|
||||
final baseHeight =
|
||||
12 * 2 + measure.bodyMediumHeight * 2 + measure.bodySmallHeight + 8;
|
||||
return switch (proxyCardType) {
|
||||
@@ -51,8 +51,12 @@ delayTest(List<Proxy> proxies) async {
|
||||
),
|
||||
);
|
||||
globalState.appController.setDelay(await clashCore.getDelay(proxyName));
|
||||
});
|
||||
await Future.wait(delayProxies);
|
||||
}).toList();
|
||||
|
||||
final batchesDelayProxies = delayProxies.batch(100);
|
||||
for (final batchDelayProxies in batchesDelayProxies) {
|
||||
await Future.wait(batchDelayProxies);
|
||||
}
|
||||
appController.appState.sortNum++;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class _ProxiesFragmentState extends State<ProxiesFragment> {
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showExtendPage(
|
||||
forceNotSide: true,
|
||||
isScaffold: true,
|
||||
extendPageWidth: 360,
|
||||
context,
|
||||
body: const Providers(),
|
||||
|
||||
@@ -33,13 +33,21 @@ class Resources extends StatelessWidget {
|
||||
fileName: geoIpFileName,
|
||||
key: "geoip",
|
||||
),
|
||||
GeoItem(label: "GeoSite", fileName: geoSiteFileName, key: "geosite"),
|
||||
GeoItem(
|
||||
label: "GeoSite",
|
||||
fileName: geoSiteFileName,
|
||||
key: "geosite",
|
||||
),
|
||||
GeoItem(
|
||||
label: "MMDB",
|
||||
fileName: mmdbFileName,
|
||||
key: "mmdb",
|
||||
),
|
||||
GeoItem(label: "ASN", fileName: asnFileName, key: "asn"),
|
||||
GeoItem(
|
||||
label: "ASN",
|
||||
fileName: asnFileName,
|
||||
key: "asn",
|
||||
),
|
||||
];
|
||||
|
||||
return ListView.separated(
|
||||
@@ -81,6 +89,7 @@ class _GeoDataListItemState extends State<GeoDataListItem> {
|
||||
child: UpdateGeoUrlFormDialog(
|
||||
title: geoItem.label,
|
||||
url: url,
|
||||
defaultValue: defaultGeoXMap[geoItem.key],
|
||||
),
|
||||
);
|
||||
if (newUrl != null && newUrl != url && mounted) {
|
||||
@@ -238,11 +247,13 @@ class _GeoDataListItemState extends State<GeoDataListItem> {
|
||||
class UpdateGeoUrlFormDialog extends StatefulWidget {
|
||||
final String title;
|
||||
final String url;
|
||||
final String? defaultValue;
|
||||
|
||||
const UpdateGeoUrlFormDialog({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.url,
|
||||
this.defaultValue
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -258,6 +269,13 @@ class _UpdateGeoUrlFormDialogState extends State<UpdateGeoUrlFormDialog> {
|
||||
urlController = TextEditingController(text: widget.url);
|
||||
}
|
||||
|
||||
_handleReset() async {
|
||||
if (widget.defaultValue == null) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pop<String>(widget.defaultValue);
|
||||
}
|
||||
|
||||
_handleUpdate() async {
|
||||
final url = urlController.value.text;
|
||||
if (url.isEmpty) return;
|
||||
@@ -285,6 +303,16 @@ class _UpdateGeoUrlFormDialogState extends State<UpdateGeoUrlFormDialog> {
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
if (widget.defaultValue != null &&
|
||||
urlController.value.text != widget.defaultValue) ...[
|
||||
TextButton(
|
||||
onPressed: _handleReset,
|
||||
child: Text(appLocalizations.reset),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
],
|
||||
TextButton(
|
||||
onPressed: _handleUpdate,
|
||||
child: Text(appLocalizations.submit),
|
||||
|
||||
@@ -239,14 +239,65 @@ class _ThemeColorsBoxState extends State<ThemeColorsBox> {
|
||||
title: Text(appLocalizations.prueBlackMode),
|
||||
delegate: SwitchDelegate(
|
||||
value: value,
|
||||
onChanged: (value){
|
||||
onChanged: (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,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -286,5 +286,7 @@
|
||||
"fallbackFilter": "Fallback filter",
|
||||
"geoipCode": "Geoip code",
|
||||
"ipcidr": "Ipcidr",
|
||||
"domain": "Domain"
|
||||
"domain": "Domain",
|
||||
"resetDns": "Reset Dns",
|
||||
"reset": "Reset"
|
||||
}
|
||||
@@ -286,5 +286,7 @@
|
||||
"fallbackFilter": "Fallback过滤",
|
||||
"geoipCode": "Geoip代码",
|
||||
"ipcidr": "IP/掩码",
|
||||
"domain": "域名"
|
||||
"domain": "域名",
|
||||
"resetDns": "重置DNS",
|
||||
"reset": "重置"
|
||||
}
|
||||
@@ -346,6 +346,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"requests": MessageLookupByLibrary.simpleMessage("Requests"),
|
||||
"requestsDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"View recently request records"),
|
||||
"reset": MessageLookupByLibrary.simpleMessage("Reset"),
|
||||
"resetDns": MessageLookupByLibrary.simpleMessage("Reset Dns"),
|
||||
"resources": MessageLookupByLibrary.simpleMessage("Resources"),
|
||||
"resourcesDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"External resource related info"),
|
||||
|
||||
@@ -271,6 +271,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("通过WebDAV恢复数据"),
|
||||
"requests": MessageLookupByLibrary.simpleMessage("请求"),
|
||||
"requestsDesc": MessageLookupByLibrary.simpleMessage("查看最近请求记录"),
|
||||
"reset": MessageLookupByLibrary.simpleMessage("重置"),
|
||||
"resetDns": MessageLookupByLibrary.simpleMessage("重置DNS"),
|
||||
"resources": MessageLookupByLibrary.simpleMessage("资源"),
|
||||
"resourcesDesc": MessageLookupByLibrary.simpleMessage("外部资源相关信息"),
|
||||
"respectRules": MessageLookupByLibrary.simpleMessage("遵守规则"),
|
||||
|
||||
@@ -2929,6 +2929,26 @@ class AppLocalizations {
|
||||
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> {
|
||||
|
||||
@@ -32,6 +32,11 @@ Future<void> main() async {
|
||||
openLogs: config.openLogs,
|
||||
hasProxies: false,
|
||||
);
|
||||
globalState.updateTray(
|
||||
appState: appState,
|
||||
config: config,
|
||||
clashConfig: clashConfig,
|
||||
);
|
||||
await globalState.init(
|
||||
appState: appState,
|
||||
config: config,
|
||||
|
||||
@@ -111,6 +111,9 @@ typedef GeoXMap = Map<String, String>;
|
||||
|
||||
typedef HostsMap = Map<String, String>;
|
||||
|
||||
const defaultMixedPort = 7890;
|
||||
const defaultKeepAliveInterval = 30;
|
||||
|
||||
@JsonSerializable()
|
||||
class ClashConfig extends ChangeNotifier {
|
||||
int _mixedPort;
|
||||
@@ -132,7 +135,7 @@ class ClashConfig extends ChangeNotifier {
|
||||
HostsMap _hosts;
|
||||
|
||||
ClashConfig()
|
||||
: _mixedPort = 7890,
|
||||
: _mixedPort = defaultMixedPort,
|
||||
_mode = Mode.rule,
|
||||
_ipv6 = false,
|
||||
_findProcessMode = FindProcessMode.off,
|
||||
@@ -143,13 +146,13 @@ class ClashConfig extends ChangeNotifier {
|
||||
_unifiedDelay = false,
|
||||
_geodataLoader = geodataLoaderMemconservative,
|
||||
_externalController = '',
|
||||
_keepAliveInterval = 30,
|
||||
_keepAliveInterval = defaultKeepAliveInterval,
|
||||
_dns = const Dns(),
|
||||
_geoXUrl = defaultGeoXMap,
|
||||
_rules = [],
|
||||
_hosts = {};
|
||||
|
||||
@JsonKey(name: "mixed-port", defaultValue: 7890)
|
||||
@JsonKey(name: "mixed-port", defaultValue: defaultMixedPort)
|
||||
int get mixedPort => _mixedPort;
|
||||
|
||||
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;
|
||||
|
||||
set keepAliveInterval(int value) {
|
||||
|
||||
@@ -95,6 +95,21 @@ class DesktopProps with _$DesktopProps {
|
||||
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()
|
||||
class Config extends ChangeNotifier {
|
||||
List<Profile> _profiles;
|
||||
@@ -124,6 +139,7 @@ class Config extends ChangeNotifier {
|
||||
bool _onlyProxy;
|
||||
bool _prueBlack;
|
||||
VpnProps _vpnProps;
|
||||
ScaleProps _scaleProps;
|
||||
DesktopProps _desktopProps;
|
||||
bool _showLabel;
|
||||
bool _overrideDns;
|
||||
@@ -155,7 +171,8 @@ class Config extends ChangeNotifier {
|
||||
_vpnProps = const VpnProps(),
|
||||
_desktopProps = const DesktopProps(),
|
||||
_showLabel = false,
|
||||
_overrideDns = false;
|
||||
_overrideDns = false,
|
||||
_scaleProps = const ScaleProps();
|
||||
|
||||
deleteProfileById(String id) {
|
||||
_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)
|
||||
bool get showLabel => _showLabel;
|
||||
|
||||
@@ -589,6 +615,7 @@ class Config extends ChangeNotifier {
|
||||
_isCloseConnections = config._isCloseConnections;
|
||||
_isCompatible = config._isCompatible;
|
||||
_autoLaunch = config._autoLaunch;
|
||||
_dav = config._dav;
|
||||
_silentLaunch = config._silentLaunch;
|
||||
_autoRun = config._autoRun;
|
||||
_proxiesType = config._proxiesType;
|
||||
|
||||
@@ -4,14 +4,16 @@ part 'generated/dav.g.dart';
|
||||
|
||||
part 'generated/dav.freezed.dart';
|
||||
|
||||
const defaultDavFileName = "backup.zip";
|
||||
|
||||
@freezed
|
||||
class DAV with _$DAV{
|
||||
class DAV with _$DAV {
|
||||
const factory DAV({
|
||||
required String uri,
|
||||
required String user,
|
||||
required String password,
|
||||
@Default(defaultDavFileName) String fileName,
|
||||
}) = _DAV;
|
||||
|
||||
factory DAV.fromJson(Map<String, Object?> json) =>
|
||||
_$DAVFromJson(json);
|
||||
factory DAV.fromJson(Map<String, Object?> json) => _$DAVFromJson(json);
|
||||
}
|
||||
@@ -1240,3 +1240,159 @@ abstract class _DesktopProps implements DesktopProps {
|
||||
_$$DesktopPropsImplCopyWith<_$DesktopPropsImpl> get copyWith =>
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ Config _$ConfigFromJson(Map<String, dynamic> json) => Config()
|
||||
..vpnProps = VpnProps.fromJson(json['vpnProps'] as Map<String, dynamic>?)
|
||||
..desktopProps =
|
||||
DesktopProps.fromJson(json['desktopProps'] as Map<String, dynamic>?)
|
||||
..scaleProps =
|
||||
ScaleProps.fromJson(json['scaleProps'] as Map<String, dynamic>?)
|
||||
..showLabel = json['showLabel'] as bool? ?? false
|
||||
..overrideDns = json['overrideDns'] as bool? ?? false;
|
||||
|
||||
@@ -85,6 +87,7 @@ Map<String, dynamic> _$ConfigToJson(Config instance) => <String, dynamic>{
|
||||
'windowProps': instance.windowProps,
|
||||
'vpnProps': instance.vpnProps,
|
||||
'desktopProps': instance.desktopProps,
|
||||
'scaleProps': instance.scaleProps,
|
||||
'showLabel': instance.showLabel,
|
||||
'overrideDns': instance.overrideDns,
|
||||
};
|
||||
@@ -234,3 +237,15 @@ Map<String, dynamic> _$$DesktopPropsImplToJson(_$DesktopPropsImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'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,
|
||||
};
|
||||
|
||||
@@ -23,6 +23,7 @@ mixin _$DAV {
|
||||
String get uri => throw _privateConstructorUsedError;
|
||||
String get user => throw _privateConstructorUsedError;
|
||||
String get password => throw _privateConstructorUsedError;
|
||||
String get fileName => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
@@ -34,7 +35,7 @@ abstract class $DAVCopyWith<$Res> {
|
||||
factory $DAVCopyWith(DAV value, $Res Function(DAV) then) =
|
||||
_$DAVCopyWithImpl<$Res, DAV>;
|
||||
@useResult
|
||||
$Res call({String uri, String user, String password});
|
||||
$Res call({String uri, String user, String password, String fileName});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -52,6 +53,7 @@ class _$DAVCopyWithImpl<$Res, $Val extends DAV> implements $DAVCopyWith<$Res> {
|
||||
Object? uri = null,
|
||||
Object? user = null,
|
||||
Object? password = null,
|
||||
Object? fileName = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
uri: null == uri
|
||||
@@ -66,6 +68,10 @@ class _$DAVCopyWithImpl<$Res, $Val extends DAV> implements $DAVCopyWith<$Res> {
|
||||
? _value.password
|
||||
: password // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
fileName: null == fileName
|
||||
? _value.fileName
|
||||
: fileName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@@ -76,7 +82,7 @@ abstract class _$$DAVImplCopyWith<$Res> implements $DAVCopyWith<$Res> {
|
||||
__$$DAVImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String uri, String user, String password});
|
||||
$Res call({String uri, String user, String password, String fileName});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -91,6 +97,7 @@ class __$$DAVImplCopyWithImpl<$Res> extends _$DAVCopyWithImpl<$Res, _$DAVImpl>
|
||||
Object? uri = null,
|
||||
Object? user = null,
|
||||
Object? password = null,
|
||||
Object? fileName = null,
|
||||
}) {
|
||||
return _then(_$DAVImpl(
|
||||
uri: null == uri
|
||||
@@ -105,6 +112,10 @@ class __$$DAVImplCopyWithImpl<$Res> extends _$DAVCopyWithImpl<$Res, _$DAVImpl>
|
||||
? _value.password
|
||||
: password // ignore: cast_nullable_to_non_nullable
|
||||
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()
|
||||
class _$DAVImpl implements _DAV {
|
||||
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) =>
|
||||
_$$DAVImplFromJson(json);
|
||||
@@ -124,10 +138,13 @@ class _$DAVImpl implements _DAV {
|
||||
final String user;
|
||||
@override
|
||||
final String password;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String fileName;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DAV(uri: $uri, user: $user, password: $password)';
|
||||
return 'DAV(uri: $uri, user: $user, password: $password, fileName: $fileName)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -138,12 +155,14 @@ class _$DAVImpl implements _DAV {
|
||||
(identical(other.uri, uri) || other.uri == uri) &&
|
||||
(identical(other.user, user) || other.user == user) &&
|
||||
(identical(other.password, password) ||
|
||||
other.password == password));
|
||||
other.password == password) &&
|
||||
(identical(other.fileName, fileName) ||
|
||||
other.fileName == fileName));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, uri, user, password);
|
||||
int get hashCode => Object.hash(runtimeType, uri, user, password, fileName);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@@ -163,7 +182,8 @@ abstract class _DAV implements DAV {
|
||||
const factory _DAV(
|
||||
{required final String uri,
|
||||
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;
|
||||
|
||||
@@ -174,6 +194,8 @@ abstract class _DAV implements DAV {
|
||||
@override
|
||||
String get password;
|
||||
@override
|
||||
String get fileName;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$DAVImplCopyWith<_$DAVImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@@ -10,10 +10,12 @@ _$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl(
|
||||
uri: json['uri'] as String,
|
||||
user: json['user'] as String,
|
||||
password: json['password'] as String,
|
||||
fileName: json['fileName'] as String? ?? defaultDavFileName,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DAVImplToJson(_$DAVImpl instance) => <String, dynamic>{
|
||||
'uri': instance.uri,
|
||||
'user': instance.user,
|
||||
'password': instance.password,
|
||||
'fileName': instance.fileName,
|
||||
};
|
||||
|
||||
@@ -3472,6 +3472,7 @@ mixin _$ClashConfigState {
|
||||
int get mixedPort => throw _privateConstructorUsedError;
|
||||
bool get allowLan => throw _privateConstructorUsedError;
|
||||
bool get ipv6 => throw _privateConstructorUsedError;
|
||||
bool get overrideDns => throw _privateConstructorUsedError;
|
||||
String get geodataLoader => throw _privateConstructorUsedError;
|
||||
LogLevel get logLevel => throw _privateConstructorUsedError;
|
||||
String get externalController => throw _privateConstructorUsedError;
|
||||
@@ -3502,6 +3503,7 @@ abstract class $ClashConfigStateCopyWith<$Res> {
|
||||
{int mixedPort,
|
||||
bool allowLan,
|
||||
bool ipv6,
|
||||
bool overrideDns,
|
||||
String geodataLoader,
|
||||
LogLevel logLevel,
|
||||
String externalController,
|
||||
@@ -3537,6 +3539,7 @@ class _$ClashConfigStateCopyWithImpl<$Res, $Val extends ClashConfigState>
|
||||
Object? mixedPort = null,
|
||||
Object? allowLan = null,
|
||||
Object? ipv6 = null,
|
||||
Object? overrideDns = null,
|
||||
Object? geodataLoader = null,
|
||||
Object? logLevel = null,
|
||||
Object? externalController = null,
|
||||
@@ -3565,6 +3568,10 @@ class _$ClashConfigStateCopyWithImpl<$Res, $Val extends ClashConfigState>
|
||||
? _value.ipv6
|
||||
: ipv6 // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
overrideDns: null == overrideDns
|
||||
? _value.overrideDns
|
||||
: overrideDns // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
geodataLoader: null == geodataLoader
|
||||
? _value.geodataLoader
|
||||
: geodataLoader // ignore: cast_nullable_to_non_nullable
|
||||
@@ -3653,6 +3660,7 @@ abstract class _$$ClashConfigStateImplCopyWith<$Res>
|
||||
{int mixedPort,
|
||||
bool allowLan,
|
||||
bool ipv6,
|
||||
bool overrideDns,
|
||||
String geodataLoader,
|
||||
LogLevel logLevel,
|
||||
String externalController,
|
||||
@@ -3688,6 +3696,7 @@ class __$$ClashConfigStateImplCopyWithImpl<$Res>
|
||||
Object? mixedPort = null,
|
||||
Object? allowLan = null,
|
||||
Object? ipv6 = null,
|
||||
Object? overrideDns = null,
|
||||
Object? geodataLoader = null,
|
||||
Object? logLevel = null,
|
||||
Object? externalController = null,
|
||||
@@ -3716,6 +3725,10 @@ class __$$ClashConfigStateImplCopyWithImpl<$Res>
|
||||
? _value.ipv6
|
||||
: ipv6 // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
overrideDns: null == overrideDns
|
||||
? _value.overrideDns
|
||||
: overrideDns // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
geodataLoader: null == geodataLoader
|
||||
? _value.geodataLoader
|
||||
: geodataLoader // ignore: cast_nullable_to_non_nullable
|
||||
@@ -3783,6 +3796,7 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
{required this.mixedPort,
|
||||
required this.allowLan,
|
||||
required this.ipv6,
|
||||
required this.overrideDns,
|
||||
required this.geodataLoader,
|
||||
required this.logLevel,
|
||||
required this.externalController,
|
||||
@@ -3808,6 +3822,8 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
@override
|
||||
final bool ipv6;
|
||||
@override
|
||||
final bool overrideDns;
|
||||
@override
|
||||
final String geodataLoader;
|
||||
@override
|
||||
final LogLevel logLevel;
|
||||
@@ -3856,7 +3872,7 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
|
||||
@override
|
||||
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
|
||||
@@ -3869,6 +3885,8 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
(identical(other.allowLan, allowLan) ||
|
||||
other.allowLan == allowLan) &&
|
||||
(identical(other.ipv6, ipv6) || other.ipv6 == ipv6) &&
|
||||
(identical(other.overrideDns, overrideDns) ||
|
||||
other.overrideDns == overrideDns) &&
|
||||
(identical(other.geodataLoader, geodataLoader) ||
|
||||
other.geodataLoader == geodataLoader) &&
|
||||
(identical(other.logLevel, logLevel) ||
|
||||
@@ -3899,6 +3917,7 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
mixedPort,
|
||||
allowLan,
|
||||
ipv6,
|
||||
overrideDns,
|
||||
geodataLoader,
|
||||
logLevel,
|
||||
externalController,
|
||||
@@ -3927,6 +3946,7 @@ abstract class _ClashConfigState implements ClashConfigState {
|
||||
{required final int mixedPort,
|
||||
required final bool allowLan,
|
||||
required final bool ipv6,
|
||||
required final bool overrideDns,
|
||||
required final String geodataLoader,
|
||||
required final LogLevel logLevel,
|
||||
required final String externalController,
|
||||
@@ -3949,6 +3969,8 @@ abstract class _ClashConfigState implements ClashConfigState {
|
||||
@override
|
||||
bool get ipv6;
|
||||
@override
|
||||
bool get overrideDns;
|
||||
@override
|
||||
String get geodataLoader;
|
||||
@override
|
||||
LogLevel get logLevel;
|
||||
|
||||
@@ -228,6 +228,7 @@ class ClashConfigState with _$ClashConfigState {
|
||||
required int mixedPort,
|
||||
required bool allowLan,
|
||||
required bool ipv6,
|
||||
required bool overrideDns,
|
||||
required String geodataLoader,
|
||||
required LogLevel logLevel,
|
||||
required String externalController,
|
||||
|
||||
121
lib/state.dart
121
lib/state.dart
@@ -7,11 +7,15 @@ import 'package:fl_clash/plugins/service.dart';
|
||||
import 'package:fl_clash/plugins/vpn.dart';
|
||||
import 'package:fl_clash/widgets/scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.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 'controller.dart';
|
||||
|
||||
import 'enum/enum.dart';
|
||||
import 'l10n/l10n.dart';
|
||||
import 'models/models.dart';
|
||||
import 'common/common.dart';
|
||||
|
||||
@@ -23,11 +27,13 @@ class GlobalState {
|
||||
late PackageInfo packageInfo;
|
||||
Function? updateCurrentDelayDebounce;
|
||||
PageController? pageController;
|
||||
late Measure measure;
|
||||
DateTime? startTime;
|
||||
final navigatorKey = GlobalKey<NavigatorState>();
|
||||
late AppController appController;
|
||||
GlobalKey<CommonScaffoldState> homeScaffoldKey = GlobalKey();
|
||||
List<Function> updateFunctionLists = [];
|
||||
var isTrayInit = false;
|
||||
|
||||
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({
|
||||
required Config config,
|
||||
required String groupName,
|
||||
|
||||
@@ -24,8 +24,9 @@ class _ClashContainerState extends State<ClashContainer>
|
||||
Function? updateClashConfigDebounce;
|
||||
|
||||
Widget _updateContainer(Widget child) {
|
||||
return Selector<ClashConfig, ClashConfigState>(
|
||||
selector: (_, clashConfig) => ClashConfigState(
|
||||
return Selector2<Config,ClashConfig, ClashConfigState>(
|
||||
selector: (_,config, clashConfig) => ClashConfigState(
|
||||
overrideDns: config.overrideDns,
|
||||
mixedPort: clashConfig.mixedPort,
|
||||
allowLan: clashConfig.allowLan,
|
||||
ipv6: clashConfig.ipv6,
|
||||
|
||||
@@ -33,7 +33,8 @@ class ColorSchemeBox extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Theme(
|
||||
return AspectRatio(aspectRatio: 1,
|
||||
child: Theme(
|
||||
data: _getTheme(context),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
@@ -94,6 +95,7 @@ class ColorSchemeBox extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,12 +57,14 @@ class InputDialog extends StatefulWidget {
|
||||
final String title;
|
||||
final String value;
|
||||
final String? suffixText;
|
||||
final String? resetValue;
|
||||
|
||||
const InputDialog({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.value,
|
||||
this.suffixText,
|
||||
this.resetValue,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -92,6 +94,13 @@ class _InputDialogState extends State<InputDialog> {
|
||||
Navigator.of(context).pop<String>(text);
|
||||
}
|
||||
|
||||
_handleReset() async {
|
||||
if (widget.resetValue == null) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pop<String>(widget.resetValue);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
@@ -114,6 +123,16 @@ class _InputDialogState extends State<InputDialog> {
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
if (widget.resetValue != null &&
|
||||
textController.value.text != widget.resetValue) ...[
|
||||
TextButton(
|
||||
onPressed: _handleReset,
|
||||
child: Text(appLocalizations.reset),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
],
|
||||
TextButton(
|
||||
onPressed: _handleUpdate,
|
||||
child: Text(appLocalizations.submit),
|
||||
|
||||
@@ -120,9 +120,19 @@ class _LineChartState extends State<LineChart>
|
||||
Path getPath(List<Point> points, Size size) {
|
||||
final path = Path()
|
||||
..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;
|
||||
}
|
||||
|
||||
@@ -132,7 +142,7 @@ class _LineChartState extends State<LineChart>
|
||||
required progress,
|
||||
}) {
|
||||
nextPoints = getInterpolatePoints(prevPoints, points, progress);
|
||||
Path setSize(Size size) {
|
||||
return (size) {
|
||||
final prevPath = getPath(prevPoints, size);
|
||||
final nextPath = getPath(nextPoints, size);
|
||||
final prevMetric = prevPath.computeMetrics().first;
|
||||
@@ -143,9 +153,7 @@ class _LineChartState extends State<LineChart>
|
||||
0,
|
||||
prevLength + (nextLength - prevLength) * progress,
|
||||
);
|
||||
}
|
||||
|
||||
return setSize;
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -50,12 +50,14 @@ class OpenDelegate extends Delegate {
|
||||
final String title;
|
||||
final double? extendPageWidth;
|
||||
final bool isBlur;
|
||||
final bool isScaffold;
|
||||
|
||||
const OpenDelegate({
|
||||
required this.title,
|
||||
required this.widget,
|
||||
this.extendPageWidth,
|
||||
this.isBlur = true,
|
||||
this.isScaffold = false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -92,12 +94,14 @@ class InputDelegate extends Delegate {
|
||||
final String value;
|
||||
final String? suffixText;
|
||||
final Function(String? value) onChanged;
|
||||
final String? resetValue;
|
||||
|
||||
const InputDelegate({
|
||||
required this.title,
|
||||
required this.value,
|
||||
this.suffixText,
|
||||
required this.onChanged,
|
||||
this.resetValue,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -287,6 +291,7 @@ class ListItem<T> extends StatelessWidget {
|
||||
title: openDelegate.title,
|
||||
extendPageWidth: openDelegate.extendPageWidth,
|
||||
isBlur: openDelegate.isBlur,
|
||||
isScaffold: openDelegate.isScaffold,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -332,6 +337,7 @@ class ListItem<T> extends StatelessWidget {
|
||||
title: inputDelegate.title,
|
||||
value: inputDelegate.value,
|
||||
suffixText: inputDelegate.suffixText,
|
||||
resetValue: inputDelegate.resetValue,
|
||||
),
|
||||
);
|
||||
inputDelegate.onChanged(value);
|
||||
|
||||
35
lib/widgets/media_container.dart
Normal file
35
lib/widgets/media_container.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ showExtendPage(
|
||||
required Widget body,
|
||||
required String title,
|
||||
double? extendPageWidth,
|
||||
bool forceNotSide = false,
|
||||
bool isScaffold = false,
|
||||
bool isBlur = true,
|
||||
Widget? action,
|
||||
}) {
|
||||
@@ -33,7 +33,7 @@ showExtendPage(
|
||||
);
|
||||
return;
|
||||
}
|
||||
final isNotSide = isMobile || forceNotSide;
|
||||
final isNotSide = isMobile || isScaffold;
|
||||
navigator.push(
|
||||
ModalSideSheetRoute(
|
||||
modalBarrierColor: Colors.black38,
|
||||
|
||||
@@ -16,7 +16,7 @@ class TooltipText extends StatelessWidget {
|
||||
return LayoutBuilder(
|
||||
builder: (context, container) {
|
||||
final maxWidth = container.maxWidth;
|
||||
final size = globalState.appController.measure.computeTextSize(
|
||||
final size = globalState.measure.computeTextSize(
|
||||
text,
|
||||
);
|
||||
if (maxWidth < size.width) {
|
||||
|
||||
@@ -22,7 +22,6 @@ class TrayContainer extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _TrayContainerState extends State<TrayContainer> with TrayListener {
|
||||
var isTrayInit = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -30,113 +29,6 @@ class _TrayContainerState extends State<TrayContainer> with TrayListener {
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
return Selector3<AppState, Config, ClashConfig, TrayContainerSelectorState>(
|
||||
@@ -149,8 +41,13 @@ class _TrayContainerState extends State<TrayContainer> with TrayListener {
|
||||
systemProxy: config.desktopProps.systemProxy,
|
||||
tunEnable: clashConfig.tun.enable,
|
||||
),
|
||||
shouldRebuild: (prev,next){
|
||||
if(prev != next){
|
||||
globalState.appController.updateTray();
|
||||
}
|
||||
return prev != next;
|
||||
},
|
||||
builder: (_, state, child) {
|
||||
updateMenu(state);
|
||||
return child!;
|
||||
},
|
||||
child: widget.child,
|
||||
|
||||
@@ -28,3 +28,4 @@ export 'builder.dart';
|
||||
export 'setting.dart';
|
||||
export 'vpn_container.dart';
|
||||
export 'input.dart';
|
||||
export 'media_container.dart';
|
||||
|
||||
Submodule plugins/flutter_distributor updated: 7701c7be83...4a8384e48a
@@ -1,7 +1,7 @@
|
||||
name: fl_clash
|
||||
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
||||
publish_to: 'none'
|
||||
version: 0.8.57+202409021
|
||||
version: 0.8.58+202409081
|
||||
environment:
|
||||
sdk: '>=3.1.0 <4.0.0'
|
||||
flutter: 3.22.3
|
||||
|
||||
@@ -2,16 +2,14 @@
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/common/other.dart';
|
||||
import 'package:lpinyin/lpinyin.dart';
|
||||
|
||||
void main() {
|
||||
final res = const [
|
||||
"https://doh.pub/dns-query",
|
||||
"https://dns.alidns.com/dns-query"
|
||||
];
|
||||
final res = [1, 2, 3, 4, 5, 6,7,8,9,10,11];
|
||||
|
||||
List.from(res)..remove("https://doh.pub/dns-query");
|
||||
print(res.batch(5));
|
||||
}
|
||||
|
||||
startService() async {
|
||||
|
||||
Reference in New Issue
Block a user