Optimize desktop view

Optimize logs, requests, connection pages

Optimize windows tray auto hide

Optimize some details

Update core
This commit is contained in:
chen08209
2025-06-07 01:48:34 +08:00
parent adb890d763
commit 1154e7b245
169 changed files with 6484 additions and 5230 deletions

View File

@@ -1 +1,8 @@
include: package:flutter_lints/flutter.yaml include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- lib/l10n/intl/**
linter:
rules:
prefer_single_quotes: true

View File

@@ -406,5 +406,20 @@
"import": "Import", "import": "Import",
"importFile": "Import from file", "importFile": "Import from file",
"importUrl": "Import from URL", "importUrl": "Import from URL",
"autoSetSystemDns": "Auto set system DNS" "autoSetSystemDns": "Auto set system DNS",
"details": "{label} details",
"creationTime": "Creation time",
"progress": "Progress",
"host": "Host",
"destination": "Destination",
"destinationGeoIP": "Destination GeoIP",
"destinationIPASN": "Destination IPASN",
"specialProxy": "Special proxy",
"specialRules": "special rules",
"remoteDestination": "Remote destination",
"networkType": "Network type",
"proxyChains": "Proxy chains",
"log": "Log",
"connection": "Connection",
"request": "Request"
} }

View File

@@ -407,5 +407,20 @@
"import": "インポート", "import": "インポート",
"importFile": "ファイルからインポート", "importFile": "ファイルからインポート",
"importUrl": "URLからインポート", "importUrl": "URLからインポート",
"autoSetSystemDns": "オートセットシステムDNS" "autoSetSystemDns": "オートセットシステムDNS",
"details": "{label}詳細",
"creationTime": "作成時間",
"progress": "進捗",
"host": "ホスト",
"destination": "宛先",
"destinationGeoIP": "宛先地理情報",
"destinationIPASN": "宛先IP ASN",
"specialProxy": "特殊プロキシ",
"specialRules": "特殊ルール",
"remoteDestination": "リモート宛先",
"networkType": "ネットワーク種別",
"proxyChains": "プロキシチェーン",
"log": "ログ",
"connection": "接続",
"request": "リクエスト"
} }

View File

@@ -407,5 +407,20 @@
"import": "Импорт", "import": "Импорт",
"importFile": "Импорт из файла", "importFile": "Импорт из файла",
"importUrl": "Импорт по URL", "importUrl": "Импорт по URL",
"autoSetSystemDns": "Автоматическая настройка системного DNS" "autoSetSystemDns": "Автоматическая настройка системного DNS",
"details": "Детали {}",
"creationTime": "Время создания",
"progress": "Прогресс",
"host": "Хост",
"destination": "Назначение",
"destinationGeoIP": "Геолокация назначения",
"destinationIPASN": "ASN назначения",
"specialProxy": "Специальный прокси",
"specialRules": "Специальные правила",
"remoteDestination": "Удалённое назначение",
"networkType": "Тип сети",
"proxyChains": "Цепочки прокси",
"log": "Журнал",
"connection": "Соединение",
"request": "Запрос"
} }

View File

@@ -407,5 +407,20 @@
"import": "导入", "import": "导入",
"importFile": "通过文件导入", "importFile": "通过文件导入",
"importUrl": "通过URL导入", "importUrl": "通过URL导入",
"autoSetSystemDns": "自动设置系统DNS" "autoSetSystemDns": "自动设置系统DNS",
"details": "{label}详情",
"creationTime": "创建时间",
"progress": "进度",
"host": "主机",
"destination": "目标地址",
"destinationGeoIP": "目标地理定位",
"destinationIPASN": "目标IP ASN",
"specialProxy": "特殊代理",
"specialRules": "特殊规则",
"remoteDestination": "远程目标",
"networkType": "网络类型",
"proxyChains": "代理链",
"log": "日志",
"connection": "连接",
"request": "请求"
} }

View File

@@ -52,25 +52,25 @@ require (
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab // indirect github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab // indirect
github.com/metacubex/bart v0.20.5 // indirect github.com/metacubex/bart v0.20.5 // indirect
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 // indirect github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 // indirect
github.com/metacubex/chacha v0.1.2 // indirect github.com/metacubex/chacha v0.1.5 // indirect
github.com/metacubex/fswatch v0.1.1 // indirect github.com/metacubex/fswatch v0.1.1 // indirect
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect
github.com/metacubex/quic-go v0.52.1-0.20250522021943-aef454b9e639 // indirect github.com/metacubex/quic-go v0.52.1-0.20250522021943-aef454b9e639 // indirect
github.com/metacubex/randv2 v0.2.0 // indirect github.com/metacubex/randv2 v0.2.0 // indirect
github.com/metacubex/sing v0.5.3 // indirect github.com/metacubex/sing v0.5.4-0.20250605054047-54dc6097da29 // indirect
github.com/metacubex/sing-mux v0.3.2 // indirect github.com/metacubex/sing-mux v0.3.2 // indirect
github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f // indirect github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f // indirect
github.com/metacubex/sing-shadowsocks v0.2.10 // indirect github.com/metacubex/sing-shadowsocks v0.2.11-0.20250621023810-0e9ef9dd0c92 // indirect
github.com/metacubex/sing-shadowsocks2 v0.2.4 // indirect github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250621023950-93d605a2143d // indirect
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 // indirect github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 // indirect
github.com/metacubex/sing-tun v0.4.6-0.20250524142129-9d110c0af70c // indirect github.com/metacubex/sing-tun v0.4.7-0.20250611091011-60774779fdd8 // indirect
github.com/metacubex/sing-vmess v0.2.2 // indirect github.com/metacubex/sing-vmess v0.2.2 // indirect
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f // indirect github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f // indirect
github.com/metacubex/smux v0.0.0-20250503055512-501391591dee // indirect github.com/metacubex/smux v0.0.0-20250503055512-501391591dee // indirect
github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 // indirect github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 // indirect
github.com/metacubex/utls v1.7.3 // indirect github.com/metacubex/utls v1.7.4-0.20250610022031-808d767c8c73 // indirect
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 // indirect github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 // indirect
github.com/miekg/dns v1.1.63 // indirect github.com/miekg/dns v1.1.63 // indirect
github.com/mroth/weightedrand/v2 v2.1.0 // indirect github.com/mroth/weightedrand/v2 v2.1.0 // indirect

View File

@@ -101,8 +101,8 @@ github.com/metacubex/bart v0.20.5 h1:XkgLZ17QxfxkqKdGsojoM2Zu01mmHyyQSFzt2/calTM
github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI= github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI=
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 h1:oBowHVKZycNtAFbZ6avaCSZJYeme2Nrj+4RpV2cNJig= 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/bbolt v0.0.0-20240822011022-aed6d4850399/go.mod h1:4xcieuIK+M4bGQmQYZVqEaIYqjS1ahO4kXG7EmDgEro=
github.com/metacubex/chacha v0.1.2 h1:QulCq3eVm3TO6+4nVIWJtmSe7BT2GMrgVHuAoqRQnlc= github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M=
github.com/metacubex/chacha v0.1.2/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8= github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU= github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU=
github.com/metacubex/fswatch v0.1.1/go.mod h1:czrTT7Zlbz7vWft8RQu9Qqh+JoX+Nnb+UabuyN1YsgI= github.com/metacubex/fswatch v0.1.1/go.mod h1:czrTT7Zlbz7vWft8RQu9Qqh+JoX+Nnb+UabuyN1YsgI=
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI=
@@ -116,20 +116,20 @@ github.com/metacubex/quic-go v0.52.1-0.20250522021943-aef454b9e639/go.mod h1:Kc6
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
github.com/metacubex/sing v0.5.3 h1:QWdN16WFKMk06x4nzkc8SvZ7y2x+TLQrpkPoHs+WSVM= github.com/metacubex/sing v0.5.4-0.20250605054047-54dc6097da29 h1:SD9q025FNTaepuFXFOKDhnGLVu6PQYChBvw2ZYPXeLo=
github.com/metacubex/sing v0.5.3/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing v0.5.4-0.20250605054047-54dc6097da29/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
github.com/metacubex/sing-mux v0.3.2 h1:nJv52pyRivHcaZJKk2JgxpaVvj1GAXG81scSa9N7ncw= github.com/metacubex/sing-mux v0.3.2 h1:nJv52pyRivHcaZJKk2JgxpaVvj1GAXG81scSa9N7ncw=
github.com/metacubex/sing-mux v0.3.2/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= github.com/metacubex/sing-mux v0.3.2/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw=
github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f h1:mP3vIm+9hRFI0C0Vl3pE0NESF/L85FDbuB0tGgUii6I= github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f h1:mP3vIm+9hRFI0C0Vl3pE0NESF/L85FDbuB0tGgUii6I=
github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f/go.mod h1:JPTpf7fpnojsSuwRJExhSZSy63pVbp3VM39+zj+sAJM= github.com/metacubex/sing-quic v0.0.0-20250523120938-f1a248e5ec7f/go.mod h1:JPTpf7fpnojsSuwRJExhSZSy63pVbp3VM39+zj+sAJM=
github.com/metacubex/sing-shadowsocks v0.2.10 h1:Pr7LDbjMANIQHl07zWgl1vDuhpsfDQUpZ8cX6DPabfg= github.com/metacubex/sing-shadowsocks v0.2.11-0.20250621023810-0e9ef9dd0c92 h1:Y9ebcKya6ow7VHoESCN5+l4zZvg5eaL2IhI5LLCQxQA=
github.com/metacubex/sing-shadowsocks v0.2.10/go.mod h1:MtRM0ZZjR0kaDOzy9zWSt6/4/UlrnsNBq+1FNAF4vBk= github.com/metacubex/sing-shadowsocks v0.2.11-0.20250621023810-0e9ef9dd0c92/go.mod h1:/squZ38pXrYjqtg8qn+joVvwbpGNYQNp8yxKsMVbCto=
github.com/metacubex/sing-shadowsocks2 v0.2.4 h1:Ec0x3hHR7xkld5Z09IGh16wtUUpBb2HgqZ9DExd8Q7s= github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250621023950-93d605a2143d h1:Ey3A1tA8lVkRbK1FDmwuWj/57Nr8JMdpoVqe45mFzJg=
github.com/metacubex/sing-shadowsocks2 v0.2.4/go.mod h1:WP8+S0kqtnSbX1vlIpo5i8Irm/ijZITEPBcZ26B5unY= github.com/metacubex/sing-shadowsocks2 v0.2.5-0.20250621023950-93d605a2143d/go.mod h1:+ukTd0OPFglT3bnKAYTJWYPbuox6HYNXE235r5tHdUk=
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI=
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E=
github.com/metacubex/sing-tun v0.4.6-0.20250524142129-9d110c0af70c h1:Y6jk7AH5BEg9Dsvczrf/KokYsvxeKSZZlCLHg+hC4ro= github.com/metacubex/sing-tun v0.4.7-0.20250611091011-60774779fdd8 h1:4zWKqxTx75TbfW2EmlQ3hxM6RTRg2PYOAVMCnU4I61I=
github.com/metacubex/sing-tun v0.4.6-0.20250524142129-9d110c0af70c/go.mod h1:HDaHDL6onAX2ZGbAGUXKp++PohRdNb7Nzt6zxzhox+U= github.com/metacubex/sing-tun v0.4.7-0.20250611091011-60774779fdd8/go.mod h1:2YywXPWW8Z97kTH7RffOeykKzU+l0aiKlglWV1PAS64=
github.com/metacubex/sing-vmess v0.2.2 h1:nG6GIKF1UOGmlzs+BIetdGHkFZ20YqFVIYp5Htqzp+4= github.com/metacubex/sing-vmess v0.2.2 h1:nG6GIKF1UOGmlzs+BIetdGHkFZ20YqFVIYp5Htqzp+4=
github.com/metacubex/sing-vmess v0.2.2/go.mod h1:CVDNcdSLVYFgTHQlubr88d8CdqupAUDqLjROos+H9xk= github.com/metacubex/sing-vmess v0.2.2/go.mod h1:CVDNcdSLVYFgTHQlubr88d8CdqupAUDqLjROos+H9xk=
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU=
@@ -138,8 +138,8 @@ github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113a
github.com/metacubex/smux v0.0.0-20250503055512-501391591dee/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= github.com/metacubex/smux v0.0.0-20250503055512-501391591dee/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE=
github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 h1:j1VRTiC9JLR4nUbSikx9OGdu/3AgFDqgcLj4GoqyQkc= github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 h1:j1VRTiC9JLR4nUbSikx9OGdu/3AgFDqgcLj4GoqyQkc=
github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
github.com/metacubex/utls v1.7.3 h1:yDcMEWojFh+t8rU9X0HPcZDPAoFze/rIIyssqivzj8A= github.com/metacubex/utls v1.7.4-0.20250610022031-808d767c8c73 h1:HWKsf92BqLYqugATFIJ3hYiEBZ7JF6AoqyvqF39afuI=
github.com/metacubex/utls v1.7.3/go.mod h1:oknYT0qTOwE4hjPmZOEpzVdefnW7bAdGLvZcqmk4TLU= github.com/metacubex/utls v1.7.4-0.20250610022031-808d767c8c73/go.mod h1:oknYT0qTOwE4hjPmZOEpzVdefnW7bAdGLvZcqmk4TLU=
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ= github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ=
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y= github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y=
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=

View File

@@ -62,7 +62,7 @@ class ApplicationState extends ConsumerState<Application> {
}); });
} }
_autoUpdateGroupTask() { void _autoUpdateGroupTask() {
_autoUpdateGroupTaskTimer = Timer(const Duration(milliseconds: 20000), () { _autoUpdateGroupTaskTimer = Timer(const Duration(milliseconds: 20000), () {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
globalState.appController.updateGroupsDebounce(); globalState.appController.updateGroupsDebounce();
@@ -71,14 +71,14 @@ class ApplicationState extends ConsumerState<Application> {
}); });
} }
_autoUpdateProfilesTask() { void _autoUpdateProfilesTask() {
_autoUpdateProfilesTaskTimer = Timer(const Duration(minutes: 20), () async { _autoUpdateProfilesTaskTimer = Timer(const Duration(minutes: 20), () async {
await globalState.appController.autoUpdateProfiles(); await globalState.appController.autoUpdateProfiles();
_autoUpdateProfilesTask(); _autoUpdateProfilesTask();
}); });
} }
_buildPlatformState(Widget child) { Widget _buildPlatformState(Widget child) {
if (system.isDesktop) { if (system.isDesktop) {
return WindowManager( return WindowManager(
child: TrayManager( child: TrayManager(
@@ -97,13 +97,13 @@ class ApplicationState extends ConsumerState<Application> {
); );
} }
_buildState(Widget child) { Widget _buildState(Widget child) {
return AppStateManager( return AppStateManager(
child: ClashManager( child: ClashManager(
child: ConnectivityManager( child: ConnectivityManager(
onConnectivityChanged: (results) async { onConnectivityChanged: (results) async {
if (!results.contains(ConnectivityResult.vpn)) { if (!results.contains(ConnectivityResult.vpn)) {
await clashCore.closeConnections(); clashCore.closeConnections();
} }
globalState.appController.updateLocalIp(); globalState.appController.updateLocalIp();
globalState.appController.addCheckIpNumDebounce(); globalState.appController.addCheckIpNumDebounce();
@@ -114,7 +114,7 @@ class ApplicationState extends ConsumerState<Application> {
); );
} }
_buildPlatformApp(Widget child) { Widget _buildPlatformApp(Widget child) {
if (system.isDesktop) { if (system.isDesktop) {
return WindowHeaderContainer( return WindowHeaderContainer(
child: child, child: child,
@@ -125,7 +125,7 @@ class ApplicationState extends ConsumerState<Application> {
); );
} }
_buildApp(Widget child) { Widget _buildApp(Widget child) {
return MessageManager( return MessageManager(
child: ThemeManager( child: ThemeManager(
child: child, child: child,
@@ -153,8 +153,12 @@ class ApplicationState extends ConsumerState<Application> {
], ],
builder: (_, child) { builder: (_, child) {
return AppEnvManager( return AppEnvManager(
child: _buildPlatformApp( child: _buildApp(
_buildApp(child!), AppSidebarContainer(
child: _buildPlatformApp(
child!,
),
),
), ),
); );
}, },
@@ -179,7 +183,7 @@ class ApplicationState extends ConsumerState<Application> {
primaryColor: themeProps.primaryColor, primaryColor: themeProps.primaryColor,
).toPureBlack(themeProps.pureBlack), ).toPureBlack(themeProps.pureBlack),
), ),
home: child, home: child!,
); );
}, },
child: const HomePage(), child: const HomePage(),

View File

@@ -17,7 +17,7 @@ class ClashCore {
late ClashHandlerInterface clashInterface; late ClashHandlerInterface clashInterface;
ClashCore._internal() { ClashCore._internal() {
if (Platform.isAndroid) { if (system.isAndroid) {
clashInterface = clashLib!; clashInterface = clashLib!;
} else { } else {
clashInterface = clashService!; clashInterface = clashService!;
@@ -84,7 +84,7 @@ class ClashCore {
return await clashInterface.setState(state); return await clashInterface.setState(state);
} }
shutdown() async { Future<void> shutdown() async {
await clashInterface.shutdown(); await clashInterface.shutdown();
} }
@@ -107,14 +107,14 @@ class ClashCore {
if (proxies.isEmpty) return []; if (proxies.isEmpty) return [];
final groupNames = [ final groupNames = [
UsedProxy.GLOBAL.name, UsedProxy.GLOBAL.name,
...(proxies[UsedProxy.GLOBAL.name]["all"] as List).where((e) { ...(proxies[UsedProxy.GLOBAL.name]['all'] as List).where((e) {
final proxy = proxies[e] ?? {}; final proxy = proxies[e] ?? {};
return GroupTypeExtension.valueList.contains(proxy['type']); return GroupTypeExtension.valueList.contains(proxy['type']);
}) })
]; ];
final groupsRaw = groupNames.map((groupName) { final groupsRaw = groupNames.map((groupName) {
final group = proxies[groupName]; final group = proxies[groupName];
group["all"] = ((group["all"] ?? []) as List) group['all'] = ((group['all'] ?? []) as List)
.map( .map(
(name) => proxies[name], (name) => proxies[name],
) )
@@ -133,22 +133,22 @@ class ClashCore {
return await clashInterface.changeProxy(changeProxyParams); return await clashInterface.changeProxy(changeProxyParams);
} }
Future<List<Connection>> getConnections() async { Future<List<TrackerInfo>> getConnections() async {
final res = await clashInterface.getConnections(); final res = await clashInterface.getConnections();
final connectionsData = json.decode(res) as Map; final connectionsData = json.decode(res) as Map;
final connectionsRaw = connectionsData['connections'] as List? ?? []; final connectionsRaw = connectionsData['connections'] as List? ?? [];
return connectionsRaw.map((e) => Connection.fromJson(e)).toList(); return connectionsRaw.map((e) => TrackerInfo.fromJson(e)).toList();
} }
closeConnection(String id) { void closeConnection(String id) {
clashInterface.closeConnection(id); clashInterface.closeConnection(id);
} }
closeConnections() { void closeConnections() {
clashInterface.closeConnections(); clashInterface.closeConnections();
} }
resetConnections() { void resetConnections() {
clashInterface.resetConnections(); clashInterface.resetConnections();
} }
@@ -202,11 +202,11 @@ class ClashCore {
return clashInterface.updateExternalProvider(providerName); return clashInterface.updateExternalProvider(providerName);
} }
startListener() async { Future<void> startListener() async {
await clashInterface.startListener(); await clashInterface.startListener();
} }
stopListener() async { Future<void> stopListener() async {
await clashInterface.stopListener(); await clashInterface.stopListener();
} }
@@ -260,23 +260,23 @@ class ClashCore {
return int.parse(value); return int.parse(value);
} }
resetTraffic() { void resetTraffic() {
clashInterface.resetTraffic(); clashInterface.resetTraffic();
} }
startLog() { void startLog() {
clashInterface.startLog(); clashInterface.startLog();
} }
stopLog() { void stopLog() {
clashInterface.stopLog(); clashInterface.stopLog();
} }
requestGc() { Future<void> requestGc() async {
clashInterface.forceGc(); await clashInterface.forceGc();
} }
destroy() async { Future<void> destroy() async {
await clashInterface.destroy(); await clashInterface.destroy();
} }
} }

View File

@@ -57,11 +57,11 @@ mixin ClashInterface {
FutureOr<String> getMemory(); FutureOr<String> getMemory();
resetTraffic(); FutureOr<void> resetTraffic();
startLog(); FutureOr<void> startLog();
stopLog(); FutureOr<void> stopLog();
Future<bool> crash(); Future<bool> crash();
@@ -89,7 +89,7 @@ mixin AndroidClashInterface {
abstract class ClashHandlerInterface with ClashInterface { abstract class ClashHandlerInterface with ClashInterface {
Map<String, Completer> callbackCompleterMap = {}; Map<String, Completer> callbackCompleterMap = {};
handleResult(ActionResult result) async { Future<void> handleResult(ActionResult result) async {
final completer = callbackCompleterMap[result.id]; final completer = callbackCompleterMap[result.id];
try { try {
switch (result.method) { switch (result.method) {
@@ -105,13 +105,13 @@ abstract class ClashHandlerInterface with ClashInterface {
return; return;
} }
} catch (e) { } catch (e) {
commonPrint.log("${result.id} error $e"); commonPrint.log('${result.id} error $e');
} }
} }
sendMessage(String message); void sendMessage(String message);
reStart(); FutureOr<void> reStart();
FutureOr<bool> destroy(); FutureOr<bool> destroy();
@@ -122,14 +122,14 @@ abstract class ClashHandlerInterface with ClashInterface {
FutureOr<T> Function()? onTimeout, FutureOr<T> Function()? onTimeout,
T? defaultValue, T? defaultValue,
}) async { }) async {
final id = "${method.name}#${utils.id}"; final id = '${method.name}#${utils.id}';
callbackCompleterMap[id] = Completer<T>(); callbackCompleterMap[id] = Completer<T>();
dynamic mDefaultValue = defaultValue; dynamic mDefaultValue = defaultValue;
if (mDefaultValue == null) { if (mDefaultValue == null) {
if (T == String) { if (T == String) {
mDefaultValue = ""; mDefaultValue = '';
} else if (T == bool) { } else if (T == bool) {
mDefaultValue = false; mDefaultValue = false;
} else if (T == Map) { } else if (T == Map) {
@@ -290,8 +290,8 @@ abstract class ClashHandlerInterface with ClashInterface {
return invoke<String>( return invoke<String>(
method: ActionMethod.sideLoadExternalProvider, method: ActionMethod.sideLoadExternalProvider,
data: json.encode({ data: json.encode({
"providerName": providerName, 'providerName': providerName,
"data": data, 'data': data,
}), }),
); );
} }
@@ -382,9 +382,9 @@ abstract class ClashHandlerInterface with ClashInterface {
@override @override
Future<String> asyncTestDelay(String url, String proxyName) { Future<String> asyncTestDelay(String url, String proxyName) {
final delayParams = { final delayParams = {
"proxy-name": proxyName, 'proxy-name': proxyName,
"timeout": httpTimeoutDuration.inMilliseconds, 'timeout': httpTimeoutDuration.inMilliseconds,
"test-url": url, 'test-url': url,
}; };
return invoke<String>( return invoke<String>(
method: ActionMethod.asyncTestDelay, method: ActionMethod.asyncTestDelay,

View File

@@ -1,7 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:ffi'; import 'dart:ffi';
import 'dart:io';
import 'dart:isolate'; import 'dart:isolate';
import 'dart:ui'; import 'dart:ui';
@@ -30,7 +29,7 @@ class ClashLib extends ClashHandlerInterface with AndroidClashInterface {
return _canSendCompleter.future; return _canSendCompleter.future;
} }
_initService() async { Future<void> _initService() async {
await service?.destroy(); await service?.destroy();
_registerMainPort(receiverPort.sendPort); _registerMainPort(receiverPort.sendPort);
receiverPort.listen((message) { receiverPort.listen((message) {
@@ -52,7 +51,7 @@ class ClashLib extends ClashHandlerInterface with AndroidClashInterface {
await service?.init(); await service?.init();
} }
_registerMainPort(SendPort sendPort) { void _registerMainPort(SendPort sendPort) {
IsolateNameServer.removePortNameMapping(mainIsolate); IsolateNameServer.removePortNameMapping(mainIsolate);
IsolateNameServer.registerPortWithName(sendPort, mainIsolate); IsolateNameServer.registerPortWithName(sendPort, mainIsolate);
} }
@@ -139,7 +138,7 @@ class ClashLibHandler {
late final DynamicLibrary lib; late final DynamicLibrary lib;
ClashLibHandler._internal() { ClashLibHandler._internal() {
lib = DynamicLibrary.open("libclash.so"); lib = DynamicLibrary.open('libclash.so');
clashFFI = ClashFFI(lib); clashFFI = ClashFFI(lib);
clashFFI.initNativeApiBridge( clashFFI.initNativeApiBridge(
NativeApi.initializeApiDLData, NativeApi.initializeApiDLData,
@@ -169,19 +168,19 @@ class ClashLibHandler {
return completer.future; return completer.future;
} }
attachMessagePort(int messagePort) { void attachMessagePort(int messagePort) {
clashFFI.attachMessagePort( clashFFI.attachMessagePort(
messagePort, messagePort,
); );
} }
updateDns(String dns) { void updateDns(String dns) {
final dnsChar = dns.toNativeUtf8().cast<Char>(); final dnsChar = dns.toNativeUtf8().cast<Char>();
clashFFI.updateDns(dnsChar); clashFFI.updateDns(dnsChar);
malloc.free(dnsChar); malloc.free(dnsChar);
} }
setState(CoreState state) { void setState(CoreState state) {
final stateChar = json.encode(state).toNativeUtf8().cast<Char>(); final stateChar = json.encode(state).toNativeUtf8().cast<Char>();
clashFFI.setState(stateChar); clashFFI.setState(stateChar);
malloc.free(stateChar); malloc.free(stateChar);
@@ -221,12 +220,12 @@ class ClashLibHandler {
return Traffic.fromMap(json.decode(trafficString)); return Traffic.fromMap(json.decode(trafficString));
} }
startListener() async { Future<bool> startListener() async {
clashFFI.startListener(); clashFFI.startListener();
return true; return true;
} }
stopListener() async { Future<bool> stopListener() async {
clashFFI.stopListener(); clashFFI.stopListener();
return true; return true;
} }
@@ -287,7 +286,7 @@ class ClashLibHandler {
} }
ClashLib? get clashLib => ClashLib? get clashLib =>
Platform.isAndroid && !globalState.isService ? ClashLib() : null; system.isAndroid && !globalState.isService ? ClashLib() : null;
ClashLibHandler? get clashLibHandler => ClashLibHandler? get clashLibHandler =>
Platform.isAndroid && globalState.isService ? ClashLibHandler() : null; system.isAndroid && globalState.isService ? ClashLibHandler() : null;

View File

@@ -23,7 +23,7 @@ class ClashMessage {
listener.onDelay(Delay.fromJson(m.data)); listener.onDelay(Delay.fromJson(m.data));
break; break;
case AppMessageType.request: case AppMessageType.request:
listener.onRequest(Connection.fromJson(m.data)); listener.onRequest(TrackerInfo.fromJson(m.data));
break; break;
case AppMessageType.loaded: case AppMessageType.loaded:
listener.onLoaded(m.data); listener.onLoaded(m.data);

View File

@@ -28,9 +28,9 @@ class ClashService extends ClashHandlerInterface {
reStart(); reStart();
} }
_initServer() async { Future<void> _initServer() async {
runZonedGuarded(() async { runZonedGuarded(() async {
final address = !Platform.isWindows final address = !system.isWindows
? InternetAddress( ? InternetAddress(
unixSocketPath, unixSocketPath,
type: InternetAddressType.unix, type: InternetAddressType.unix,
@@ -83,10 +83,10 @@ class ClashService extends ClashHandlerInterface {
await shutdown(); await shutdown();
} }
final serverSocket = await serverCompleter.future; final serverSocket = await serverCompleter.future;
final arg = Platform.isWindows final arg = system.isWindows
? "${serverSocket.port}" ? '${serverSocket.port}'
: serverSocket.address.address; : serverSocket.address.address;
if (Platform.isWindows && await system.checkIsAdmin()) { if (system.isWindows && await system.checkIsAdmin()) {
final isSuccess = await request.startCoreByHelper(arg); final isSuccess = await request.startCoreByHelper(arg);
if (isSuccess) { if (isSuccess) {
return; return;
@@ -122,8 +122,8 @@ class ClashService extends ClashHandlerInterface {
socket.writeln(message); socket.writeln(message);
} }
_deleteSocketFile() async { Future<void> _deleteSocketFile() async {
if (!Platform.isWindows) { if (!system.isWindows) {
final file = File(unixSocketPath); final file = File(unixSocketPath);
if (await file.exists()) { if (await file.exists()) {
await file.delete(); await file.delete();
@@ -131,7 +131,7 @@ class ClashService extends ClashHandlerInterface {
} }
} }
_destroySocket() async { Future<void> _destroySocket() async {
if (socketCompleter.isCompleted) { if (socketCompleter.isCompleted) {
final lastSocket = await socketCompleter.future; final lastSocket = await socketCompleter.future;
await lastSocket.close(); await lastSocket.close();
@@ -141,7 +141,7 @@ class ClashService extends ClashHandlerInterface {
@override @override
shutdown() async { shutdown() async {
if (Platform.isWindows) { if (system.isWindows) {
await request.stopCoreByHelper(); await request.stopCoreByHelper();
} }
await _destroySocket(); await _destroySocket();

View File

@@ -1,14 +1,14 @@
import 'dart:io';
import 'package:fl_clash/plugins/app.dart'; import 'package:fl_clash/plugins/app.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'system.dart';
class Android { class Android {
init() async { Future<void> init() async {
app?.onExit = () async { app?.onExit = () async {
await globalState.appController.savePreferences(); await globalState.appController.savePreferences();
}; };
} }
} }
final android = Platform.isAndroid ? Android() : null; final android = system.isAndroid ? Android() : null;

View File

@@ -1,10 +1,11 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:archive/archive_io.dart'; import 'package:archive/archive_io.dart';
import 'package:path/path.dart'; import 'package:path/path.dart';
extension ArchiveExt on Archive { extension ArchiveExt on Archive {
addDirectoryToArchive(String dirPath, String parentPath) { void addDirectoryToArchive(String dirPath, String parentPath) {
final dir = Directory(dirPath); final dir = Directory(dirPath);
final entities = dir.listSync(recursive: false); final entities = dir.listSync(recursive: false);
for (final entity in entities) { for (final entity in entities) {
@@ -19,7 +20,7 @@ extension ArchiveExt on Archive {
} }
} }
add<T>(String name, T raw) { void add<T>(String name, T raw) {
final data = json.encode(raw); final data = json.encode(raw);
addFile( addFile(
ArchiveFile(name, data.length, data), ArchiveFile(name, data.length, data),

View File

@@ -23,6 +23,10 @@ extension ColorExtension on Color {
return withAlpha(77); return withAlpha(77);
} }
Color get opacity12 {
return withAlpha(31);
}
Color get opacity15 { Color get opacity15 {
return withAlpha(38); return withAlpha(38);
} }

View File

@@ -37,4 +37,3 @@ export 'text.dart';
export 'tray.dart'; export 'tray.dart';
export 'utils.dart'; export 'utils.dart';
export 'window.dart'; export 'window.dart';
export 'windows.dart';

View File

@@ -1,4 +1,3 @@
import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'dart:ui'; import 'dart:ui';
@@ -8,13 +7,13 @@ import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
const appName = "FlClash"; const appName = 'FlClash';
const appHelperService = "FlClashHelperService"; const appHelperService = 'FlClashHelperService';
const coreName = "clash.meta"; const coreName = 'clash.meta';
const browserUa = const browserUa =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"; 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
const packageName = "com.follow.clash"; const packageName = 'com.follow.clash';
final unixSocketPath = "/tmp/FlClashSocket_${Random().nextInt(10000)}.sock"; final unixSocketPath = '/tmp/FlClashSocket_${Random().nextInt(10000)}.sock';
const helperPort = 47890; const helperPort = 47890;
const maxTextScale = 1.4; const maxTextScale = 1.4;
const minTextScale = 0.8; const minTextScale = 0.8;
@@ -31,25 +30,25 @@ const animateDuration = Duration(milliseconds: 100);
const midDuration = Duration(milliseconds: 200); const midDuration = Duration(milliseconds: 200);
const commonDuration = Duration(milliseconds: 300); const commonDuration = Duration(milliseconds: 300);
const defaultUpdateDuration = Duration(days: 1); const defaultUpdateDuration = Duration(days: 1);
const mmdbFileName = "geoip.metadb"; const mmdbFileName = 'geoip.metadb';
const asnFileName = "ASN.mmdb"; const asnFileName = 'ASN.mmdb';
const geoIpFileName = "GeoIP.dat"; const geoIpFileName = 'GeoIP.dat';
const geoSiteFileName = "GeoSite.dat"; const geoSiteFileName = 'GeoSite.dat';
final double kHeaderHeight = system.isDesktop final double kHeaderHeight = system.isDesktop
? !Platform.isMacOS ? !system.isMacOS
? 40 ? 40
: 28 : 28
: 0; : 0;
const profilesDirectoryName = "profiles"; const profilesDirectoryName = 'profiles';
const localhost = "127.0.0.1"; const localhost = '127.0.0.1';
const clashConfigKey = "clash_config"; const clashConfigKey = 'clash_config';
const configKey = "config"; const configKey = 'config';
const double dialogCommonWidth = 300; const double dialogCommonWidth = 300;
const repository = "chen08209/FlClash"; const repository = 'chen08209/FlClash';
const defaultExternalController = "127.0.0.1:9090"; const defaultExternalController = '127.0.0.1:9090';
const maxMobileWidth = 600; const maxMobileWidth = 600;
const maxLaptopWidth = 840; const maxLaptopWidth = 840;
const defaultTestUrl = "https://www.gstatic.com/generate_204"; const defaultTestUrl = 'https://www.gstatic.com/generate_204';
final commonFilter = ImageFilter.blur( final commonFilter = ImageFilter.blur(
sigmaX: 5, sigmaX: 5,
sigmaY: 5, sigmaY: 5,
@@ -57,7 +56,7 @@ final commonFilter = ImageFilter.blur(
); );
const navigationItemListEquality = ListEquality<NavigationItem>(); const navigationItemListEquality = ListEquality<NavigationItem>();
const connectionListEquality = ListEquality<Connection>(); const trackerInfoListEquality = ListEquality<TrackerInfo>();
const stringListEquality = ListEquality<String>(); const stringListEquality = ListEquality<String>();
const intListEquality = ListEquality<int>(); const intListEquality = ListEquality<int>();
const logListEquality = ListEquality<Log>(); const logListEquality = ListEquality<Log>();
@@ -78,9 +77,9 @@ const viewModeColumnsMap = {
ViewMode.desktop: [4, 3], ViewMode.desktop: [4, 3],
}; };
// const proxiesStoreKey = PageStorageKey<String>('proxies'); const proxiesListStoreKey = PageStorageKey<String>('proxies_list');
// const toolsStoreKey = PageStorageKey<String>('tools'); const toolsStoreKey = PageStorageKey<String>('tools');
// const profilesStoreKey = PageStorageKey<String>('profiles'); const profilesStoreKey = PageStorageKey<String>('profiles');
const defaultPrimaryColor = 0XFFD8C0C3; const defaultPrimaryColor = 0XFFD8C0C3;
@@ -88,11 +87,11 @@ double getWidgetHeight(num lines) {
return max(lines * 84 + (lines - 1) * 16, 0).ap; return max(lines * 84 + (lines - 1) * 16, 0).ap;
} }
const maxLength = 150; const maxLength = 1000;
final mainIsolate = "FlClashMainIsolate"; final mainIsolate = 'FlClashMainIsolate';
final serviceIsolate = "FlClashServiceIsolate"; final serviceIsolate = 'FlClashServiceIsolate';
const defaultPrimaryColors = [ const defaultPrimaryColors = [
0xFF795548, 0xFF795548,
@@ -104,7 +103,7 @@ const defaultPrimaryColors = [
0XFF665390, 0XFF665390,
]; ];
const scriptTemplate = """ const scriptTemplate = '''
const main = (config) => { const main = (config) => {
return config; return config;
}"""; }''';

View File

@@ -7,11 +7,11 @@ extension BuildContextExtension on BuildContext {
return findAncestorStateOfType<CommonScaffoldState>(); return findAncestorStateOfType<CommonScaffoldState>();
} }
showNotifier(String text) { Future<void>? showNotifier(String text) {
return findAncestorStateOfType<MessageManagerState>()?.message(text); return findAncestorStateOfType<MessageManagerState>()?.message(text);
} }
showSnackBar( void showSnackBar(
String message, { String message, {
SnackBarAction? action, SnackBarAction? action,
}) { }) {
@@ -72,3 +72,18 @@ extension BuildContextExtension on BuildContext {
return state; return state;
} }
} }
class BackHandleInherited extends InheritedWidget {
final Function handleBack;
const BackHandleInherited(
{super.key, required this.handleBack, required super.child});
static BackHandleInherited? of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<BackHandleInherited>();
@override
bool updateShouldNotify(BackHandleInherited oldWidget) {
return handleBack != oldWidget.handleBack;
}
}

View File

@@ -17,26 +17,34 @@ extension DateTimeExtension on DateTime {
final difference = currentDateTime.difference(this); final difference = currentDateTime.difference(this);
final days = difference.inDays; final days = difference.inDays;
if (days >= 365) { if (days >= 365) {
return "${(days / 365).floor()} ${appLocalizations.years}${appLocalizations.ago}"; return '${(days / 365).floor()} ${appLocalizations.years}${appLocalizations.ago}';
} }
if (days >= 30) { if (days >= 30) {
return "${(days / 30).floor()} ${appLocalizations.months}${appLocalizations.ago}"; return '${(days / 30).floor()} ${appLocalizations.months}${appLocalizations.ago}';
} }
if (days >= 1) { if (days >= 1) {
return "$days ${appLocalizations.days}${appLocalizations.ago}"; return '$days ${appLocalizations.days}${appLocalizations.ago}';
} }
final hours = difference.inHours; final hours = difference.inHours;
if (hours >= 1) { if (hours >= 1) {
return "$hours ${appLocalizations.hours}${appLocalizations.ago}"; return '$hours ${appLocalizations.hours}${appLocalizations.ago}';
} }
final minutes = difference.inMinutes; final minutes = difference.inMinutes;
if (minutes >= 1) { if (minutes >= 1) {
return "$minutes ${appLocalizations.minutes}${appLocalizations.ago}"; return '$minutes ${appLocalizations.minutes}${appLocalizations.ago}';
} }
return appLocalizations.just; return appLocalizations.just;
} }
String get show { String get show {
return toIso8601String().substring(0, 10); return toString().substring(0, 10);
}
String get showFull {
return toString().substring(0, 19);
}
String get showTime {
return toString().substring(10, 19);
} }
} }

View File

@@ -38,18 +38,18 @@ class DAVClient {
} }
} }
get root => "/$appName"; String get root => '/$appName';
get backupFile => "$root/$fileName"; String get backupFile => '$root/$fileName';
backup(Uint8List data) async { Future<bool> backup(Uint8List data) async {
await client.mkdir("$root"); await client.mkdir(root);
await client.write("$backupFile", data); await client.write(backupFile, data);
return true; return true;
} }
Future<List<int>> recovery() async { Future<List<int>> recovery() async {
await client.mkdir("$root"); await client.mkdir(root);
final data = await client.read(backupFile); final data = await client.read(backupFile);
return data; return data;
} }

View File

@@ -1,5 +1,7 @@
import 'iterable.dart'; import 'iterable.dart';
typedef ValueCallback<T> = T Function();
class FixedList<T> { class FixedList<T> {
final int maxLength; final int maxLength;
final List<T> _list; final List<T> _list;
@@ -7,12 +9,12 @@ class FixedList<T> {
FixedList(this.maxLength, {List<T>? list}) FixedList(this.maxLength, {List<T>? list})
: _list = (list ?? [])..truncate(maxLength); : _list = (list ?? [])..truncate(maxLength);
add(T item) { void add(T item) {
_list.add(item); _list.add(item);
_list.truncate(maxLength); _list.truncate(maxLength);
} }
clear() { void clear() {
_list.clear(); _list.clear();
} }
@@ -38,7 +40,7 @@ class FixedMap<K, V> {
_map = map ?? {}; _map = map ?? {};
} }
updateCacheValue(K key, V Function() callback) { V updateCacheValue(K key, ValueCallback<V> callback) {
final realValue = _map.updateCacheValue( final realValue = _map.updateCacheValue(
key, key,
callback, callback,
@@ -47,21 +49,21 @@ class FixedMap<K, V> {
return realValue; return realValue;
} }
clear() { void clear() {
_map.clear(); _map.clear();
} }
updateMaxLength(int size) { void updateMaxLength(int size) {
maxLength = size; maxLength = size;
_adjustMap(); _adjustMap();
} }
updateMap(Map<K, V> map) { void updateMap(Map<K, V> map) {
_map = map; _map = map;
_adjustMap(); _adjustMap();
} }
_adjustMap() { void _adjustMap() {
if (_map.length > maxLength) { if (_map.length > maxLength) {
_map = Map.fromEntries( _map = Map.fromEntries(
map.entries.toList()..truncate(maxLength), map.entries.toList()..truncate(maxLength),

View File

@@ -5,7 +5,7 @@ import 'package:fl_clash/enum/enum.dart';
class Debouncer { class Debouncer {
final Map<FunctionTag, Timer?> _operations = {}; final Map<FunctionTag, Timer?> _operations = {};
call( void call(
FunctionTag tag, FunctionTag tag,
Function func, { Function func, {
List<dynamic>? args, List<dynamic>? args,
@@ -28,7 +28,7 @@ class Debouncer {
); );
} }
cancel(dynamic tag) { void cancel(dynamic tag) {
_operations[tag]?.cancel(); _operations[tag]?.cancel();
_operations[tag] = null; _operations[tag] = null;
} }
@@ -37,7 +37,7 @@ class Debouncer {
class Throttler { class Throttler {
final Map<FunctionTag, Timer?> _operations = {}; final Map<FunctionTag, Timer?> _operations = {};
call( bool call(
FunctionTag tag, FunctionTag tag,
Function func, { Function func, {
List<dynamic>? args, List<dynamic>? args,
@@ -61,7 +61,7 @@ class Throttler {
return false; return false;
} }
cancel(dynamic tag) { void cancel(dynamic tag) {
_operations[tag]?.cancel(); _operations[tag]?.cancel();
_operations[tag] = null; _operations[tag] = null;
} }
@@ -81,7 +81,7 @@ Future<T> retry<T>({
} }
attempts++; attempts++;
} }
throw "unknown error"; throw 'unknown error';
} }
final debouncer = Debouncer(); final debouncer = Debouncer();

View File

@@ -4,7 +4,7 @@ import 'dart:ui';
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
extension CompleterExt<T> on Completer<T> { extension CompleterExt<T> on Completer<T> {
safeFuture({ Future<T> safeFuture({
Duration? timeout, Duration? timeout,
VoidCallback? onLast, VoidCallback? onLast,
FutureOr<T> Function()? onTimeout, FutureOr<T> Function()? onTimeout,

View File

@@ -6,13 +6,13 @@ import 'package:fl_clash/state.dart';
class FlClashHttpOverrides extends HttpOverrides { class FlClashHttpOverrides extends HttpOverrides {
static String handleFindProxy(Uri url) { static String handleFindProxy(Uri url) {
if ([localhost].contains(url.host)) { if ([localhost].contains(url.host)) {
return "DIRECT"; return 'DIRECT';
} }
final port = globalState.config.patchClashConfig.mixedPort; final port = globalState.config.patchClashConfig.mixedPort;
final isStart = globalState.appState.runTime != null; final isStart = globalState.appState.runTime != null;
commonPrint.log("find $url proxy:$isStart"); commonPrint.log('find $url proxy:$isStart');
if (!isStart) return "DIRECT"; if (!isStart) return 'DIRECT';
return "PROXY localhost:$port"; return 'PROXY localhost:$port';
} }
@override @override

View File

@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class IconsExt{ class IconsExt {
static const IconData target = static const IconData target = IconData(0xe900, fontFamily: 'Icons');
IconData(0xe900, fontFamily: "Icons"); }
}

View File

@@ -47,7 +47,9 @@ extension IterableExt<T> on Iterable<T> {
extension ListExt<T> on List<T> { extension ListExt<T> on List<T> {
void truncate(int maxLength) { void truncate(int maxLength) {
assert(maxLength > 0); if (maxLength == 0) {
return;
}
if (length > maxLength) { if (length > maxLength) {
removeRange(0, length - maxLength); removeRange(0, length - maxLength);
} }
@@ -70,11 +72,19 @@ extension ListExt<T> on List<T> {
return res; return res;
} }
List<T> safeSublist(int start) { List<T> safeSublist(int start, [int? end]) {
if (start <= 0) return this; if (start <= 0) return this;
if (start > length) return []; if (start > length) return [];
if (end != null) {
return sublist(start, end.clamp(start, length));
}
return sublist(start); return sublist(start);
} }
T safeGet(int index) {
if (length > index) return this[index];
return last;
}
} }
extension DoubleListExt on List<double> { extension DoubleListExt on List<double> {
@@ -104,10 +114,10 @@ extension DoubleListExt on List<double> {
} }
extension MapExt<K, V> on Map<K, V> { extension MapExt<K, V> on Map<K, V> {
updateCacheValue(K key, V Function() callback) { V updateCacheValue(K key, V Function() callback) {
if (this[key] == null) { if (this[key] == null) {
this[key] = callback(); this[key] = callback();
} }
return this[key]; return this[key]!;
} }
} }

View File

@@ -1,8 +1,8 @@
import 'dart:io';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:uni_platform/uni_platform.dart'; import 'package:uni_platform/uni_platform.dart';
import 'system.dart';
final Map<PhysicalKeyboardKey, String> _knownKeyLabels = final Map<PhysicalKeyboardKey, String> _knownKeyLabels =
<PhysicalKeyboardKey, String>{ <PhysicalKeyboardKey, String>{
PhysicalKeyboardKey.keyA: 'A', PhysicalKeyboardKey.keyA: 'A',
@@ -79,14 +79,14 @@ final Map<PhysicalKeyboardKey, String> _knownKeyLabels =
PhysicalKeyboardKey.arrowLeft: '', PhysicalKeyboardKey.arrowLeft: '',
PhysicalKeyboardKey.arrowDown: '', PhysicalKeyboardKey.arrowDown: '',
PhysicalKeyboardKey.arrowUp: '', PhysicalKeyboardKey.arrowUp: '',
PhysicalKeyboardKey.controlLeft: "CTRL", PhysicalKeyboardKey.controlLeft: 'CTRL',
PhysicalKeyboardKey.shiftLeft: 'SHIFT', PhysicalKeyboardKey.shiftLeft: 'SHIFT',
PhysicalKeyboardKey.altLeft: "ALT", PhysicalKeyboardKey.altLeft: 'ALT',
PhysicalKeyboardKey.metaLeft: Platform.isMacOS ? '' : 'WIN', PhysicalKeyboardKey.metaLeft: system.isMacOS ? '' : 'WIN',
PhysicalKeyboardKey.controlRight: "CTRL", PhysicalKeyboardKey.controlRight: 'CTRL',
PhysicalKeyboardKey.shiftRight: 'SHIFT', PhysicalKeyboardKey.shiftRight: 'SHIFT',
PhysicalKeyboardKey.altRight: "ALT", PhysicalKeyboardKey.altRight: 'ALT',
PhysicalKeyboardKey.metaRight: Platform.isMacOS ? '' : 'WIN', PhysicalKeyboardKey.metaRight: system.isMacOS ? '' : 'WIN',
PhysicalKeyboardKey.fn: 'FN', PhysicalKeyboardKey.fn: 'FN',
}; };
@@ -101,6 +101,3 @@ extension KeyboardKeyExt on KeyboardKey {
return _knownKeyLabels[physicalKey] ?? physicalKey?.debugName ?? 'Unknown'; return _knownKeyLabels[physicalKey] ?? physicalKey?.debugName ?? 'Unknown';
} }
} }

View File

@@ -34,8 +34,8 @@ class AutoLaunch {
return await launchAtStartup.disable(); return await launchAtStartup.disable();
} }
updateStatus(bool isAutoLaunch) async { Future<void> updateStatus(bool isAutoLaunch) async {
if(kDebugMode){ if (kDebugMode) {
return; return;
} }
if (await isEnable == isAutoLaunch) return; if (await isEnable == isAutoLaunch) return;

View File

@@ -15,8 +15,9 @@ class LinkManager {
_appLinks = AppLinks(); _appLinks = AppLinks();
} }
initAppLinksListen(installConfigCallBack) async { Future<void> initAppLinksListen(
commonPrint.log("initAppLinksListen"); Function(String url) installConfigCallBack) async {
commonPrint.log('initAppLinksListen');
destroy(); destroy();
subscription = _appLinks.uriLinkStream.listen( subscription = _appLinks.uriLinkStream.listen(
(uri) { (uri) {
@@ -32,7 +33,7 @@ class LinkManager {
); );
} }
destroy() { void destroy() {
if (subscription != null) { if (subscription != null) {
subscription?.cancel(); subscription?.cancel();
subscription = null; subscription = null;

View File

@@ -33,10 +33,10 @@ class Measure {
double get bodyMediumHeight { double get bodyMediumHeight {
return _measureMap.updateCacheValue( return _measureMap.updateCacheValue(
"bodyMediumHeight", 'bodyMediumHeight',
() => computeTextSize( () => computeTextSize(
Text( Text(
"X", 'X',
style: context.textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
).height, ).height,
@@ -45,10 +45,10 @@ class Measure {
double get bodyLargeHeight { double get bodyLargeHeight {
return _measureMap.updateCacheValue( return _measureMap.updateCacheValue(
"bodyLargeHeight", 'bodyLargeHeight',
() => computeTextSize( () => computeTextSize(
Text( Text(
"X", 'X',
style: context.textTheme.bodyLarge, style: context.textTheme.bodyLarge,
), ),
).height, ).height,
@@ -57,10 +57,10 @@ class Measure {
double get bodySmallHeight { double get bodySmallHeight {
return _measureMap.updateCacheValue( return _measureMap.updateCacheValue(
"bodySmallHeight", 'bodySmallHeight',
() => computeTextSize( () => computeTextSize(
Text( Text(
"X", 'X',
style: context.textTheme.bodySmall, style: context.textTheme.bodySmall,
), ),
).height, ).height,
@@ -69,10 +69,10 @@ class Measure {
double get labelSmallHeight { double get labelSmallHeight {
return _measureMap.updateCacheValue( return _measureMap.updateCacheValue(
"labelSmallHeight", 'labelSmallHeight',
() => computeTextSize( () => computeTextSize(
Text( Text(
"X", 'X',
style: context.textTheme.labelSmall, style: context.textTheme.labelSmall,
), ),
).height, ).height,
@@ -81,10 +81,10 @@ class Measure {
double get labelMediumHeight { double get labelMediumHeight {
return _measureMap.updateCacheValue( return _measureMap.updateCacheValue(
"labelMediumHeight", 'labelMediumHeight',
() => computeTextSize( () => computeTextSize(
Text( Text(
"X", 'X',
style: context.textTheme.labelMedium, style: context.textTheme.labelMedium,
), ),
).height, ).height,
@@ -93,10 +93,10 @@ class Measure {
double get titleLargeHeight { double get titleLargeHeight {
return _measureMap.updateCacheValue( return _measureMap.updateCacheValue(
"titleLargeHeight", 'titleLargeHeight',
() => computeTextSize( () => computeTextSize(
Text( Text(
"X", 'X',
style: context.textTheme.titleLarge, style: context.textTheme.titleLarge,
), ),
).height, ).height,
@@ -105,10 +105,10 @@ class Measure {
double get titleMediumHeight { double get titleMediumHeight {
return _measureMap.updateCacheValue( return _measureMap.updateCacheValue(
"titleMediumHeight", 'titleMediumHeight',
() => computeTextSize( () => computeTextSize(
Text( Text(
"X", 'X',
style: context.textTheme.titleMedium, style: context.textTheme.titleMedium,
), ),
).height, ).height,

View File

@@ -1,7 +1,4 @@
import 'package:fl_clash/models/models.dart';
import 'package:flutter/material.dart';
import 'package:riverpod/riverpod.dart'; import 'package:riverpod/riverpod.dart';
import 'context.dart';
mixin AutoDisposeNotifierMixin<T> on AutoDisposeNotifier<T> { mixin AutoDisposeNotifierMixin<T> on AutoDisposeNotifier<T> {
set value(T value) { set value(T value) {
@@ -17,37 +14,31 @@ mixin AutoDisposeNotifierMixin<T> on AutoDisposeNotifier<T> {
return res; return res;
} }
onUpdate(T value) {} void onUpdate(T value) {}
} }
mixin PageMixin<T extends StatefulWidget> on State<T> { // mixin PageMixin<T extends StatefulWidget> on State<T> {
void onPageShow() { // initPageState() {
initPageState(); // WidgetsBinding.instance.addPostFrameCallback((_) {
} // final commonScaffoldState = context.commonScaffoldState;
// commonScaffoldState?.actions = actions;
initPageState() { // commonScaffoldState?.floatingActionButton = floatingActionButton;
WidgetsBinding.instance.addPostFrameCallback((_) { // commonScaffoldState?.onKeywordsUpdate = onKeywordsUpdate;
final commonScaffoldState = context.commonScaffoldState; // commonScaffoldState?.updateSearchState(
commonScaffoldState?.actions = actions; // (_) => onSearch != null
commonScaffoldState?.floatingActionButton = floatingActionButton; // ? AppBarSearchState(
commonScaffoldState?.onKeywordsUpdate = onKeywordsUpdate; // onSearch: onSearch!,
commonScaffoldState?.updateSearchState( // )
(_) => onSearch != null // : null,
? AppBarSearchState( // );
onSearch: onSearch!, // });
) // }
: null, //
); // List<Widget> get actions => [];
}); //
} // Widget? get floatingActionButton => null;
//
void onPageHidden() {} // Function(String)? get onSearch => null;
//
List<Widget> get actions => []; // Function(List<String>)? get onKeywordsUpdate => null;
// }
Widget? get floatingActionButton => null;
Function(String)? get onSearch => null;
Function(List<String>)? get onKeywordsUpdate => null;
}

View File

@@ -1,7 +1,9 @@
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/providers/providers.dart';
import 'package:fl_clash/views/views.dart'; import 'package:fl_clash/views/views.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class Navigation { class Navigation {
static Navigation? _instance; static Navigation? _instance;
@@ -11,62 +13,69 @@ class Navigation {
bool hasProxies = false, bool hasProxies = false,
}) { }) {
return [ return [
const NavigationItem( NavigationItem(
keep: false, keep: false,
icon: Icon(Icons.space_dashboard), icon: Icon(Icons.space_dashboard),
label: PageLabel.dashboard, label: PageLabel.dashboard,
view: DashboardView( builder: (_) => const DashboardView(
key: GlobalObjectKey(PageLabel.dashboard), key: GlobalObjectKey(PageLabel.dashboard),
), ),
), ),
NavigationItem( NavigationItem(
icon: const Icon(Icons.article), icon: const Icon(Icons.article),
label: PageLabel.proxies, label: PageLabel.proxies,
view: const ProxiesView( builder: (_) => ProviderScope(
key: GlobalObjectKey( overrides: [
PageLabel.proxies, queryProvider.overrideWith(
() => Query(),
),
],
child: const ProxiesView(
key: GlobalObjectKey(
PageLabel.proxies,
),
), ),
), ),
modes: hasProxies modes: hasProxies
? [NavigationItemMode.mobile, NavigationItemMode.desktop] ? [NavigationItemMode.mobile, NavigationItemMode.desktop]
: [], : [],
), ),
const NavigationItem( NavigationItem(
icon: Icon(Icons.folder), icon: Icon(Icons.folder),
label: PageLabel.profiles, label: PageLabel.profiles,
view: ProfilesView( builder: (_) => const ProfilesView(
key: GlobalObjectKey( key: GlobalObjectKey(
PageLabel.profiles, PageLabel.profiles,
), ),
), ),
), ),
const NavigationItem( NavigationItem(
icon: Icon(Icons.view_timeline), icon: Icon(Icons.view_timeline),
label: PageLabel.requests, label: PageLabel.requests,
view: RequestsView( builder: (_) => const RequestsView(
key: GlobalObjectKey( key: GlobalObjectKey(
PageLabel.requests, PageLabel.requests,
), ),
), ),
description: "requestsDesc", description: 'requestsDesc',
modes: [NavigationItemMode.desktop, NavigationItemMode.more], modes: [NavigationItemMode.desktop, NavigationItemMode.more],
), ),
const NavigationItem( NavigationItem(
icon: Icon(Icons.ballot), icon: Icon(Icons.ballot),
label: PageLabel.connections, label: PageLabel.connections,
view: ConnectionsView( builder: (_) => const ConnectionsView(
key: GlobalObjectKey( key: GlobalObjectKey(
PageLabel.connections, PageLabel.connections,
), ),
), ),
description: "connectionsDesc", description: 'connectionsDesc',
modes: [NavigationItemMode.desktop, NavigationItemMode.more], modes: [NavigationItemMode.desktop, NavigationItemMode.more],
), ),
const NavigationItem( NavigationItem(
icon: Icon(Icons.storage), icon: Icon(Icons.storage),
label: PageLabel.resources, label: PageLabel.resources,
description: "resourcesDesc", description: 'resourcesDesc',
view: ResourcesView( builder: (_) => const ResourcesView(
key: GlobalObjectKey( key: GlobalObjectKey(
PageLabel.resources, PageLabel.resources,
), ),
@@ -76,20 +85,20 @@ class Navigation {
NavigationItem( NavigationItem(
icon: const Icon(Icons.adb), icon: const Icon(Icons.adb),
label: PageLabel.logs, label: PageLabel.logs,
view: const LogsView( builder: (_) => const LogsView(
key: GlobalObjectKey( key: GlobalObjectKey(
PageLabel.logs, PageLabel.logs,
), ),
), ),
description: "logsDesc", description: 'logsDesc',
modes: openLogs modes: openLogs
? [NavigationItemMode.desktop, NavigationItemMode.more] ? [NavigationItemMode.desktop, NavigationItemMode.more]
: [], : [],
), ),
const NavigationItem( NavigationItem(
icon: Icon(Icons.construction), icon: Icon(Icons.construction),
label: PageLabel.tools, label: PageLabel.tools,
view: ToolsView( builder: (_) => const ToolsView(
key: GlobalObjectKey( key: GlobalObjectKey(
PageLabel.tools, PageLabel.tools,
), ),

View File

@@ -2,7 +2,6 @@ import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:fl_clash/widgets/dialog.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class BaseNavigator { class BaseNavigator {
@@ -21,20 +20,20 @@ class BaseNavigator {
); );
} }
static Future<T?> modal<T>(BuildContext context, Widget child) async { // static Future<T?> modal<T>(BuildContext context, Widget child) async {
if (globalState.appState.viewMode != ViewMode.mobile) { // if (globalState.appState.viewMode != ViewMode.mobile) {
return await globalState.showCommonDialog<T>( // return await globalState.showCommonDialog<T>(
child: CommonModal( // child: CommonModal(
child: child, // child: child,
), // ),
); // );
} // }
return await Navigator.of(context).push<T>( // return await Navigator.of(context).push<T>(
CommonRoute( // CommonRoute(
builder: (context) => child, // builder: (context) => child,
), // ),
); // );
} // }
} }
class CommonDesktopRoute<T> extends PageRoute<T> { class CommonDesktopRoute<T> extends PageRoute<T> {

View File

@@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
extension NumExt on num { extension NumExt on num {
String fixed({decimals = 2}) { String fixed({int decimals = 2}) {
String formatted = toStringAsFixed(decimals); String formatted = toStringAsFixed(decimals);
if (formatted.contains('.')) { if (formatted.contains('.')) {
formatted = formatted.replaceAll(RegExp(r'0*$'), ''); formatted = formatted.replaceAll(RegExp(r'0*$'), '');
@@ -20,7 +20,7 @@ extension NumExt on num {
} }
extension DoubleExt on double { extension DoubleExt on double {
moreOrEqual(double value) { bool moreOrEqual(double value) {
return this > value || (value - this).abs() < precisionErrorTolerance + 1; return this > value || (value - this).abs() < precisionErrorTolerance + 1;
} }
} }
@@ -46,7 +46,7 @@ extension OffsetExt on Offset {
} }
extension RectExt on Rect { extension RectExt on Rect {
doRectIntersect(Rect rect) { bool doRectIntersect(Rect rect) {
return left < rect.right && return left < rect.right &&
right > rect.left && right > rect.left &&
top < rect.bottom && top < rect.bottom &&

View File

@@ -6,8 +6,8 @@ import 'common.dart';
extension PackageInfoExtension on PackageInfo { extension PackageInfoExtension on PackageInfo {
String get ua => [ String get ua => [
"$appName/v$version", '$appName/v$version',
"clash-verge", 'clash-verge',
"Platform/${Platform.operatingSystem}", 'Platform/${Platform.operatingSystem}',
].join(" "); ].join(' ');
} }

View File

@@ -31,7 +31,7 @@ class AppPath {
} }
String get executableExtension { String get executableExtension {
return Platform.isWindows ? ".exe" : ""; return system.isWindows ? '.exe' : '';
} }
String get executableDirPath { String get executableDirPath {
@@ -40,11 +40,11 @@ class AppPath {
} }
String get corePath { String get corePath {
return join(executableDirPath, "FlClashCore$executableExtension"); return join(executableDirPath, 'FlClashCore$executableExtension');
} }
String get helperPath { String get helperPath {
return join(executableDirPath, "$appHelperService$executableExtension"); return join(executableDirPath, '$appHelperService$executableExtension');
} }
Future<String> get downloadDirPath async { Future<String> get downloadDirPath async {
@@ -59,12 +59,12 @@ class AppPath {
Future<String> get lockFilePath async { Future<String> get lockFilePath async {
final directory = await dataDir.future; final directory = await dataDir.future;
return join(directory.path, "FlClash.lock"); return join(directory.path, 'FlClash.lock');
} }
Future<String> get sharedPreferencesPath async { Future<String> get sharedPreferencesPath async {
final directory = await dataDir.future; final directory = await dataDir.future;
return join(directory.path, "shared_preferences.json"); return join(directory.path, 'shared_preferences.json');
} }
Future<String> get profilesPath async { Future<String> get profilesPath async {
@@ -74,14 +74,14 @@ class AppPath {
Future<String> getProfilePath(String id) async { Future<String> getProfilePath(String id) async {
final directory = await profilesPath; final directory = await profilesPath;
return join(directory, "$id.yaml"); return join(directory, '$id.yaml');
} }
Future<String> getProvidersDirPath(String id) async { Future<String> getProvidersDirPath(String id) async {
final directory = await profilesPath; final directory = await profilesPath;
return join( return join(
directory, directory,
"providers", 'providers',
id, id,
); );
} }
@@ -94,7 +94,7 @@ class AppPath {
final directory = await profilesPath; final directory = await profilesPath;
return join( return join(
directory, directory,
"providers", 'providers',
id, id,
type, type,
url.toMd5(), url.toMd5(),

View File

@@ -20,9 +20,9 @@ class Picker {
final path = await FilePicker.platform.saveFile( final path = await FilePicker.platform.saveFile(
fileName: fileName, fileName: fileName,
initialDirectory: await appPath.downloadDirPath, initialDirectory: await appPath.downloadDirPath,
bytes: Platform.isAndroid ? bytes : null, bytes: system.isAndroid ? bytes : null,
); );
if (!Platform.isAndroid && path != null) { if (!system.isAndroid && path != null) {
final file = await File(path).create(recursive: true); final file = await File(path).create(recursive: true);
await file.writeAsBytes(bytes); await file.writeAsBytes(bytes);
} }

View File

@@ -49,12 +49,12 @@ class Preferences {
false; false;
} }
clearClashConfig() async { Future<void> clearClashConfig() async {
final preferences = await sharedPreferencesCompleter.future; final preferences = await sharedPreferencesCompleter.future;
preferences?.remove(clashConfigKey); preferences?.remove(clashConfigKey);
} }
clearPreferences() async { Future<void> clearPreferences() async {
final sharedPreferencesIns = await sharedPreferencesCompleter.future; final sharedPreferencesIns = await sharedPreferencesCompleter.future;
sharedPreferencesIns?.clear(); sharedPreferencesIns?.clear();
} }

View File

@@ -12,8 +12,8 @@ class CommonPrint {
return _instance!; return _instance!;
} }
log(String? text) { void log(String? text) {
final payload = "[FlClash] $text"; final payload = '[APP] $text';
debugPrint(payload); debugPrint(payload);
if (!globalState.isInit) { if (!globalState.isInit) {
return; return;

View File

@@ -16,12 +16,12 @@ class Render {
return _instance!; return _instance!;
} }
active() { void active() {
resume(); resume();
pause(); pause();
} }
pause() { void pause() {
throttler.call( throttler.call(
FunctionTag.renderPause, FunctionTag.renderPause,
_pause, _pause,
@@ -29,7 +29,7 @@ class Render {
); );
} }
resume() { void resume() {
throttler.cancel(FunctionTag.renderPause); throttler.cancel(FunctionTag.renderPause);
_resume(); _resume();
} }
@@ -41,7 +41,7 @@ class Render {
_drawFrame = _dispatcher.onDrawFrame; _drawFrame = _dispatcher.onDrawFrame;
_dispatcher.onBeginFrame = null; _dispatcher.onBeginFrame = null;
_dispatcher.onDrawFrame = null; _dispatcher.onDrawFrame = null;
commonPrint.log("pause"); commonPrint.log('pause');
} }
void _resume() { void _resume() {
@@ -50,7 +50,7 @@ class Render {
_dispatcher.onBeginFrame = _beginFrame; _dispatcher.onBeginFrame = _beginFrame;
_dispatcher.onDrawFrame = _drawFrame; _dispatcher.onDrawFrame = _drawFrame;
_dispatcher.scheduleFrame(); _dispatcher.scheduleFrame();
commonPrint.log("resume"); commonPrint.log('resume');
} }
} }

View File

@@ -19,7 +19,7 @@ class Request {
_dio = Dio( _dio = Dio(
BaseOptions( BaseOptions(
headers: { headers: {
"User-Agent": browserUa, 'User-Agent': browserUa,
}, },
), ),
); );
@@ -69,7 +69,7 @@ class Request {
Future<Map<String, dynamic>?> checkForUpdate() async { Future<Map<String, dynamic>?> checkForUpdate() async {
final response = await _dio.get( final response = await _dio.get(
"https://api.github.com/repos/$repository/releases/latest", 'https://api.github.com/repos/$repository/releases/latest',
options: Options( options: Options(
responseType: ResponseType.json, responseType: ResponseType.json,
), ),
@@ -85,16 +85,22 @@ class Request {
} }
final Map<String, IpInfo Function(Map<String, dynamic>)> _ipInfoSources = { final Map<String, IpInfo Function(Map<String, dynamic>)> _ipInfoSources = {
"https://ipwho.is/": IpInfo.fromIpwhoIsJson, 'https://ipwho.is/': IpInfo.fromIpwhoIsJson,
"https://api.ip.sb/geoip/": IpInfo.fromIpSbJson, 'https://api.ip.sb/geoip/': IpInfo.fromIpSbJson,
"https://ipapi.co/json/": IpInfo.fromIpApiCoJson, 'https://ipapi.co/json/': IpInfo.fromIpApiCoJson,
"https://ipinfo.io/json/": IpInfo.fromIpInfoIoJson, 'https://ipinfo.io/json/': IpInfo.fromIpInfoIoJson,
}; };
Future<Result<IpInfo?>> checkIp({CancelToken? cancelToken}) async { Future<Result<IpInfo?>> checkIp({CancelToken? cancelToken}) async {
var failureCount = 0; var failureCount = 0;
final futures = _ipInfoSources.entries.map((source) async { final futures = _ipInfoSources.entries.map((source) async {
final Completer<Result<IpInfo?>> completer = Completer(); final Completer<Result<IpInfo?>> completer = Completer();
handleFailRes() {
if (!completer.isCompleted && failureCount == _ipInfoSources.length) {
completer.complete(Result.success(null));
}
}
final future = Dio().get<Map<String, dynamic>>( final future = Dio().get<Map<String, dynamic>>(
source.key, source.key,
cancelToken: cancelToken, cancelToken: cancelToken,
@@ -107,15 +113,14 @@ class Request {
completer.complete(Result.success(source.value(res.data!))); completer.complete(Result.success(source.value(res.data!)));
} else { } else {
failureCount++; failureCount++;
if (failureCount == _ipInfoSources.length) { handleFailRes();
completer.complete(Result.success(null));
}
} }
}).catchError((e) { }).catchError((e) {
failureCount++; failureCount++;
if (e == DioExceptionType.cancel) { if (e is DioException && e.type == DioExceptionType.cancel) {
completer.complete(Result.error("cancelled")); completer.complete(Result.error('cancelled'));
} }
handleFailRes();
}); });
return completer.future; return completer.future;
}); });
@@ -128,7 +133,7 @@ class Request {
try { try {
final response = await _dio final response = await _dio
.get( .get(
"http://$localhost:$helperPort/ping", 'http://$localhost:$helperPort/ping',
options: Options( options: Options(
responseType: ResponseType.plain, responseType: ResponseType.plain,
), ),
@@ -151,10 +156,10 @@ class Request {
try { try {
final response = await _dio final response = await _dio
.post( .post(
"http://$localhost:$helperPort/start", 'http://$localhost:$helperPort/start',
data: json.encode({ data: json.encode({
"path": appPath.corePath, 'path': appPath.corePath,
"arg": arg, 'arg': arg,
}), }),
options: Options( options: Options(
responseType: ResponseType.plain, responseType: ResponseType.plain,
@@ -179,7 +184,7 @@ class Request {
try { try {
final response = await _dio final response = await _dio
.post( .post(
"http://$localhost:$helperPort/stop", 'http://$localhost:$helperPort/stop',
options: Options( options: Options(
responseType: ResponseType.plain, responseType: ResponseType.plain,
), ),

View File

@@ -35,7 +35,7 @@ class ShowBarScrollBehavior extends BaseScrollBehavior {
Widget child, Widget child,
ScrollableDetails details, ScrollableDetails details,
) { ) {
return CommonAutoHiddenScrollBar( return CommonScrollBar(
controller: details.controller, controller: details.controller,
child: child, child: child,
); );
@@ -88,6 +88,54 @@ class NextClampingScrollPhysics extends ClampingScrollPhysics {
} }
} }
// class CacheScrollPositionController extends ScrollController {
// final String key;
//
// CacheScrollPositionController({
// required this.key,
// double initialScrollOffset = 0.0,
// super.keepScrollOffset = true,
// super.debugLabel,
// super.onAttach,
// super.onDetach,
// });
//
// @override
// ScrollPosition createScrollPosition(
// ScrollPhysics physics,
// ScrollContext context,
// ScrollPosition? oldPosition,
// ) {
// return ScrollPositionWithSingleContext(
// physics: physics,
// context: context,
// initialPixels:
// globalState.scrollPositionCache[key] ?? initialScrollOffset,
// keepScrollOffset: keepScrollOffset,
// oldPosition: oldPosition,
// debugLabel: debugLabel,
// );
// }
//
// double? get cacheOffset => globalState.scrollPositionCache[key];
//
// _handleScroll() {
// globalState.scrollPositionCache[key] = position.pixels;
// }
//
// @override
// void attach(ScrollPosition position) {
// super.attach(position);
// addListener(_handleScroll);
// }
//
// @override
// void detach(ScrollPosition position) {
// removeListener(_handleScroll);
// super.detach(position);
// }
// }
class ReverseScrollController extends ScrollController { class ReverseScrollController extends ScrollController {
ReverseScrollController({ ReverseScrollController({
super.initialScrollOffset, super.initialScrollOffset,

View File

@@ -48,7 +48,7 @@ extension StringExtension on String {
} }
bool get isSvg { bool get isSvg {
return endsWith(".svg"); return endsWith('.svg');
} }
bool get isRegex { bool get isRegex {

View File

@@ -1,16 +1,18 @@
import 'dart:ffi';
import 'dart:io'; import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:ffi/ffi.dart';
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/plugins/app.dart'; import 'package:fl_clash/plugins/app.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:fl_clash/widgets/input.dart'; import 'package:fl_clash/widgets/input.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:path/path.dart';
class System { class System {
static System? _instance; static System? _instance;
List<String>? originDns;
System._internal(); System._internal();
@@ -19,25 +21,32 @@ class System {
return _instance!; return _instance!;
} }
bool get isDesktop => bool get isDesktop => isWindows || isMacOS || isLinux;
Platform.isWindows || Platform.isMacOS || Platform.isLinux;
bool get isWindows => Platform.isWindows;
bool get isMacOS => Platform.isMacOS;
bool get isAndroid => Platform.isAndroid;
bool get isLinux => Platform.isLinux;
Future<int> get version async { Future<int> get version async {
final deviceInfo = await DeviceInfoPlugin().deviceInfo; final deviceInfo = await DeviceInfoPlugin().deviceInfo;
return switch (Platform.operatingSystem) { return switch (Platform.operatingSystem) {
"macos" => (deviceInfo as MacOsDeviceInfo).majorVersion, 'macos' => (deviceInfo as MacOsDeviceInfo).majorVersion,
"android" => (deviceInfo as AndroidDeviceInfo).version.sdkInt, 'android' => (deviceInfo as AndroidDeviceInfo).version.sdkInt,
"windows" => (deviceInfo as WindowsDeviceInfo).majorVersion, 'windows' => (deviceInfo as WindowsDeviceInfo).majorVersion,
String() => 0 String() => 0
}; };
} }
Future<bool> checkIsAdmin() async { Future<bool> checkIsAdmin() async {
final corePath = appPath.corePath.replaceAll(' ', '\\\\ '); final corePath = appPath.corePath.replaceAll(' ', '\\\\ ');
if (Platform.isWindows) { if (system.isWindows) {
final result = await windows?.checkService(); final result = await windows?.checkService();
return result == WindowsHelperServiceStatus.running; return result == WindowsHelperServiceStatus.running;
} else if (Platform.isMacOS) { } else if (system.isMacOS) {
final result = await Process.run('stat', ['-f', '%Su:%Sg %Sp', corePath]); final result = await Process.run('stat', ['-f', '%Su:%Sg %Sp', corePath]);
final output = result.stdout.trim(); final output = result.stdout.trim();
if (output.startsWith('root:admin') && output.contains('rws')) { if (output.startsWith('root:admin') && output.contains('rws')) {
@@ -56,7 +65,7 @@ class System {
} }
Future<AuthorizeCode> authorizeCore() async { Future<AuthorizeCode> authorizeCore() async {
if (Platform.isAndroid) { if (system.isAndroid) {
return AuthorizeCode.error; return AuthorizeCode.error;
} }
final corePath = appPath.corePath.replaceAll(' ', '\\\\ '); final corePath = appPath.corePath.replaceAll(' ', '\\\\ ');
@@ -65,7 +74,7 @@ class System {
return AuthorizeCode.none; return AuthorizeCode.none;
} }
if (Platform.isWindows) { if (system.isWindows) {
final result = await windows?.registerService(); final result = await windows?.registerService();
if (result == true) { if (result == true) {
return AuthorizeCode.success; return AuthorizeCode.success;
@@ -73,13 +82,13 @@ class System {
return AuthorizeCode.error; return AuthorizeCode.error;
} }
if (Platform.isMacOS) { if (system.isMacOS) {
final shell = 'chown root:admin $corePath; chmod +sx $corePath'; final shell = 'chown root:admin $corePath; chmod +sx $corePath';
final arguments = [ final arguments = [
"-e", '-e',
'do shell script "$shell" with administrator privileges', 'do shell script "$shell" with administrator privileges',
]; ];
final result = await Process.run("osascript", arguments); final result = await Process.run('osascript', arguments);
if (result.exitCode != 0) { if (result.exitCode != 0) {
return AuthorizeCode.error; return AuthorizeCode.error;
} }
@@ -88,12 +97,13 @@ class System {
final shell = Platform.environment['SHELL'] ?? 'bash'; final shell = Platform.environment['SHELL'] ?? 'bash';
final password = await globalState.showCommonDialog<String>( final password = await globalState.showCommonDialog<String>(
child: InputDialog( child: InputDialog(
obscureText: true,
title: appLocalizations.pleaseInputAdminPassword, title: appLocalizations.pleaseInputAdminPassword,
value: '', value: '',
), ),
); );
final arguments = [ final arguments = [
"-c", '-c',
'echo "$password" | sudo -S chown root:root "$corePath" && echo "$password" | sudo -S chmod +sx "$corePath"' 'echo "$password" | sudo -S chown root:root "$corePath" && echo "$password" | sudo -S chmod +sx "$corePath"'
]; ];
final result = await Process.run(shell, arguments); final result = await Process.run(shell, arguments);
@@ -105,15 +115,223 @@ class System {
return AuthorizeCode.error; return AuthorizeCode.error;
} }
Future<String?> getMacOSDefaultServiceName() async { Future<void> back() async {
if (!Platform.isMacOS) { await app?.moveTaskToBack();
return null; await window?.hide();
}
Future<void> exit() async {
if (system.isAndroid) {
await SystemNavigator.pop();
} }
await window?.close();
}
}
final system = System();
class Windows {
static Windows? _instance;
late DynamicLibrary _shell32;
Windows._internal() {
_shell32 = DynamicLibrary.open('shell32.dll');
}
factory Windows() {
_instance ??= Windows._internal();
return _instance!;
}
bool runas(String command, String arguments) {
final commandPtr = command.toNativeUtf16();
final argumentsPtr = arguments.toNativeUtf16();
final operationPtr = 'runas'.toNativeUtf16();
final shellExecute = _shell32.lookupFunction<
Int32 Function(
Pointer<Utf16> hwnd,
Pointer<Utf16> lpOperation,
Pointer<Utf16> lpFile,
Pointer<Utf16> lpParameters,
Pointer<Utf16> lpDirectory,
Int32 nShowCmd),
int Function(
Pointer<Utf16> hwnd,
Pointer<Utf16> lpOperation,
Pointer<Utf16> lpFile,
Pointer<Utf16> lpParameters,
Pointer<Utf16> lpDirectory,
int nShowCmd)>('ShellExecuteW');
final result = shellExecute(
nullptr,
operationPtr,
commandPtr,
argumentsPtr,
nullptr,
1,
);
calloc.free(commandPtr);
calloc.free(argumentsPtr);
calloc.free(operationPtr);
commonPrint.log('windows runas: $command $arguments resultCode:$result');
if (result < 42) {
return false;
}
return true;
}
Future<void> _killProcess(int port) async {
final result = await Process.run('netstat', ['-ano']);
final lines = result.stdout.toString().trim().split('\n');
for (final line in lines) {
if (!line.contains(':$port') || !line.contains('LISTENING')) {
continue;
}
final parts = line.trim().split(RegExp(r'\s+'));
final pid = int.tryParse(parts.last);
if (pid != null) {
await Process.run('taskkill', ['/PID', pid.toString(), '/F']);
}
}
}
Future<WindowsHelperServiceStatus> checkService() async {
// final qcResult = await Process.run('sc', ['qc', appHelperService]);
// final qcOutput = qcResult.stdout.toString();
// if (qcResult.exitCode != 0 || !qcOutput.contains(appPath.helperPath)) {
// return WindowsHelperServiceStatus.none;
// }
final result = await Process.run('sc', ['query', appHelperService]);
if (result.exitCode != 0) {
return WindowsHelperServiceStatus.none;
}
final output = result.stdout.toString();
if (output.contains('RUNNING') && await request.pingHelper()) {
return WindowsHelperServiceStatus.running;
}
return WindowsHelperServiceStatus.presence;
}
Future<bool> registerService() async {
final status = await checkService();
if (status == WindowsHelperServiceStatus.running) {
return true;
}
await _killProcess(helperPort);
final command = [
'/c',
if (status == WindowsHelperServiceStatus.presence) ...[
'sc',
'delete',
appHelperService,
'/force',
'&&',
],
'sc',
'create',
appHelperService,
'binPath= "${appPath.helperPath}"',
'start= auto',
'&&',
'sc',
'start',
appHelperService,
].join(' ');
final res = runas('cmd.exe', command);
await Future.delayed(
Duration(milliseconds: 300),
);
return res;
}
Future<bool> registerTask(String appName) async {
final taskXml = '''
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<Principals>
<Principal id="Author">
<LogonType>InteractiveToken</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Triggers>
<LogonTrigger/>
</Triggers>
<Settings>
<MultipleInstancesPolicy>Parallel</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>false</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>false</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>"${Platform.resolvedExecutable}"</Command>
</Exec>
</Actions>
</Task>''';
final taskPath = join(await appPath.tempPath, 'task.xml');
await File(taskPath).create(recursive: true);
await File(taskPath)
.writeAsBytes(taskXml.encodeUtf16LeWithBom, flush: true);
final commandLine = [
'/Create',
'/TN',
appName,
'/XML',
'%s',
'/F',
].join(' ');
return runas(
'schtasks',
commandLine.replaceFirst('%s', taskPath),
);
}
}
final windows = system.isWindows ? Windows() : null;
class MacOS {
static MacOS? _instance;
List<String>? originDns;
MacOS._internal();
factory MacOS() {
_instance ??= MacOS._internal();
return _instance!;
}
Future<String?> get defaultServiceName async {
final result = await Process.run('route', ['-n', 'get', 'default']); final result = await Process.run('route', ['-n', 'get', 'default']);
final output = result.stdout.toString(); final output = result.stdout.toString();
final deviceLine = output final deviceLine = output
.split('\n') .split('\n')
.firstWhere((s) => s.contains('interface:'), orElse: () => ""); .firstWhere((s) => s.contains('interface:'), orElse: () => '');
final lineSplits = deviceLine.trim().split(' '); final lineSplits = deviceLine.trim().split(' ');
if (lineSplits.length != 2) { if (lineSplits.length != 2) {
return null; return null;
@@ -125,15 +343,15 @@ class System {
); );
final serviceResultOutput = serviceResult.stdout.toString(); final serviceResultOutput = serviceResult.stdout.toString();
final currentService = serviceResultOutput.split('\n\n').firstWhere( final currentService = serviceResultOutput.split('\n\n').firstWhere(
(s) => s.contains("Device: $device"), (s) => s.contains('Device: $device'),
orElse: () => "", orElse: () => '',
); );
if (currentService.isEmpty) { if (currentService.isEmpty) {
return null; return null;
} }
final currentServiceNameLine = currentService.split("\n").firstWhere( final currentServiceNameLine = currentService.split('\n').firstWhere(
(line) => RegExp(r'^\(\d+\).*').hasMatch(line), (line) => RegExp(r'^\(\d+\).*').hasMatch(line),
orElse: () => ""); orElse: () => '');
final currentServiceNameLineSplits = final currentServiceNameLineSplits =
currentServiceNameLine.trim().split(' '); currentServiceNameLine.trim().split(' ');
if (currentServiceNameLineSplits.length < 2) { if (currentServiceNameLineSplits.length < 2) {
@@ -142,11 +360,8 @@ class System {
return currentServiceNameLineSplits[1]; return currentServiceNameLineSplits[1];
} }
Future<List<String>?> getMacOSOriginDns() async { Future<List<String>?> get systemDns async {
if (!Platform.isMacOS) { final deviceServiceName = await defaultServiceName;
return null;
}
final deviceServiceName = await getMacOSDefaultServiceName();
if (deviceServiceName == null) { if (deviceServiceName == null) {
return null; return null;
} }
@@ -158,16 +373,13 @@ class System {
if (output.startsWith("There aren't any DNS Servers set on")) { if (output.startsWith("There aren't any DNS Servers set on")) {
originDns = []; originDns = [];
} else { } else {
originDns = output.split("\n"); originDns = output.split('\n');
} }
return originDns; return originDns;
} }
setMacOSDns(bool restore) async { Future<void> updateDns(bool restore) async {
if (!Platform.isMacOS) { final serviceName = await defaultServiceName;
return;
}
final serviceName = await getMacOSDefaultServiceName();
if (serviceName == null) { if (serviceName == null) {
return; return;
} }
@@ -175,11 +387,11 @@ class System {
if (restore) { if (restore) {
nextDns = originDns; nextDns = originDns;
} else { } else {
final originDns = await system.getMacOSOriginDns(); final originDns = await systemDns;
if (originDns == null) { if (originDns == null) {
return; return;
} }
final needAddDns = "223.5.5.5"; final needAddDns = '223.5.5.5';
if (originDns.contains(needAddDns)) { if (originDns.contains(needAddDns)) {
return; return;
} }
@@ -194,22 +406,10 @@ class System {
'-setdnsservers', '-setdnsservers',
serviceName, serviceName,
if (nextDns.isNotEmpty) ...nextDns, if (nextDns.isNotEmpty) ...nextDns,
if (nextDns.isEmpty) "Empty", if (nextDns.isEmpty) 'Empty',
], ],
); );
} }
back() async {
await app?.moveTaskToBack();
await window?.hide();
}
exit() async {
if (Platform.isAndroid) {
await SystemNavigator.pop();
}
await window?.close();
}
} }
final system = System(); final macOS = system.isMacOS ? MacOS() : null;

View File

@@ -13,7 +13,7 @@ class CommonTheme {
Color get darkenSecondaryContainer { Color get darkenSecondaryContainer {
return _colorMap.updateCacheValue( return _colorMap.updateCacheValue(
"darkenSecondaryContainer", 'darkenSecondaryContainer',
() => context.colorScheme.secondaryContainer () => context.colorScheme.secondaryContainer
.blendDarken(context, factor: 0.1), .blendDarken(context, factor: 0.1),
); );
@@ -21,7 +21,7 @@ class CommonTheme {
Color get darkenSecondaryContainerLighter { Color get darkenSecondaryContainerLighter {
return _colorMap.updateCacheValue( return _colorMap.updateCacheValue(
"darkenSecondaryContainerLighter", 'darkenSecondaryContainerLighter',
() => context.colorScheme.secondaryContainer () => context.colorScheme.secondaryContainer
.blendDarken(context, factor: 0.1) .blendDarken(context, factor: 0.1)
.opacity60, .opacity60,
@@ -30,7 +30,7 @@ class CommonTheme {
Color get darken2SecondaryContainer { Color get darken2SecondaryContainer {
return _colorMap.updateCacheValue( return _colorMap.updateCacheValue(
"darken2SecondaryContainer", 'darken2SecondaryContainer',
() => context.colorScheme.secondaryContainer () => context.colorScheme.secondaryContainer
.blendDarken(context, factor: 0.2), .blendDarken(context, factor: 0.2),
); );
@@ -38,7 +38,7 @@ class CommonTheme {
Color get darken3PrimaryContainer { Color get darken3PrimaryContainer {
return _colorMap.updateCacheValue( return _colorMap.updateCacheValue(
"darken3PrimaryContainer", 'darken3PrimaryContainer',
() => context.colorScheme.primaryContainer () => context.colorScheme.primaryContainer
.blendDarken(context, factor: 0.3), .blendDarken(context, factor: 0.3),
); );

View File

@@ -11,6 +11,7 @@ import 'package:tray_manager/tray_manager.dart';
import 'app_localizations.dart'; import 'app_localizations.dart';
import 'constant.dart'; import 'constant.dart';
import 'system.dart';
import 'window.dart'; import 'window.dart';
class Tray { class Tray {
@@ -18,7 +19,7 @@ class Tray {
required Brightness? brightness, required Brightness? brightness,
bool force = false, bool force = false,
}) async { }) async {
if (Platform.isAndroid) { if (system.isAndroid) {
return; return;
} }
if (Platform.isLinux || force) { if (Platform.isLinux || force) {
@@ -38,11 +39,11 @@ class Tray {
} }
} }
update({ Future<void> update({
required TrayState trayState, required TrayState trayState,
bool focus = false, bool focus = false,
}) async { }) async {
if (Platform.isAndroid) { if (system.isAndroid) {
return; return;
} }
if (!Platform.isLinux) { if (!Platform.isLinux) {
@@ -80,7 +81,7 @@ class Tray {
); );
} }
menuItems.add(MenuItem.separator()); menuItems.add(MenuItem.separator());
if (Platform.isMacOS) { if (system.isMacOS) {
for (final group in trayState.groups) { for (final group in trayState.groups) {
List<MenuItem> subMenuItems = []; List<MenuItem> subMenuItems = [];
for (final proxy in group.all) { for (final proxy in group.all) {
@@ -169,8 +170,8 @@ class Tray {
} }
} }
updateTrayTitle([Traffic? traffic]) async { Future<void> updateTrayTitle([Traffic? traffic]) async {
// if (!Platform.isMacOS) { // if (!system.isMacOS) {
// return; // return;
// } // }
// if (traffic == null) { // if (traffic == null) {
@@ -183,11 +184,10 @@ class Tray {
} }
Future<void> _copyEnv(int port) async { Future<void> _copyEnv(int port) async {
final url = "http://127.0.0.1:$port"; final url = 'http://127.0.0.1:$port';
final cmdline = Platform.isWindows final cmdline =
? "set \$env:all_proxy=$url" system.isWindows ? 'set \$env:all_proxy=$url' : 'export all_proxy=$url';
: "export all_proxy=$url";
await Clipboard.setData( await Clipboard.setData(
ClipboardData( ClipboardData(

View File

@@ -23,11 +23,11 @@ class Utils {
final random = Random(); final random = Random();
final randomStr = final randomStr =
String.fromCharCodes(List.generate(8, (_) => random.nextInt(26) + 97)); String.fromCharCodes(List.generate(8, (_) => random.nextInt(26) + 97));
return "$timestamp$randomStr"; return '$timestamp$randomStr';
} }
String getDateStringLast2(int value) { String getDateStringLast2(int value) {
var valueRaw = "0$value"; var valueRaw = '0$value';
return valueRaw.substring( return valueRaw.substring(
valueRaw.length - 2, valueRaw.length - 2,
); );
@@ -73,7 +73,7 @@ class Utils {
var inMinutes = difference.inMinutes; var inMinutes = difference.inMinutes;
var inSeconds = difference.inSeconds; var inSeconds = difference.inSeconds;
return "${getDateStringLast2(inHours)}:${getDateStringLast2(inMinutes)}:${getDateStringLast2(inSeconds)}"; return '${getDateStringLast2(inHours)}:${getDateStringLast2(inMinutes)}:${getDateStringLast2(inSeconds)}';
} }
String getTimeText(int? timeStamp) { String getTimeText(int? timeStamp) {
@@ -83,17 +83,17 @@ class Utils {
final diff = timeStamp / 1000; final diff = timeStamp / 1000;
final inHours = (diff / 3600).floor(); final inHours = (diff / 3600).floor();
if (inHours > 99) { if (inHours > 99) {
return "99:59:59"; return '99:59:59';
} }
final inMinutes = (diff / 60 % 60).floor(); final inMinutes = (diff / 60 % 60).floor();
final inSeconds = (diff % 60).floor(); final inSeconds = (diff % 60).floor();
return "${getDateStringLast2(inHours)}:${getDateStringLast2(inMinutes)}:${getDateStringLast2(inSeconds)}"; return '${getDateStringLast2(inHours)}:${getDateStringLast2(inMinutes)}:${getDateStringLast2(inSeconds)}';
} }
Locale? getLocaleForString(String? localString) { Locale? getLocaleForString(String? localString) {
if (localString == null) return null; if (localString == null) return null;
var localSplit = localString.split("_"); var localSplit = localString.split('_');
if (localSplit.length == 1) { if (localSplit.length == 1) {
return Locale(localSplit[0]); return Locale(localSplit[0]);
} }
@@ -137,18 +137,18 @@ class Utils {
final number = int.parse(match[1] ?? '0') + 1; final number = int.parse(match[1] ?? '0') + 1;
return label.replaceFirst(reg, '($number)', label.length - 3 - 1); return label.replaceFirst(reg, '($number)', label.length - 3 - 1);
} else { } else {
return "$label(1)"; return '$label(1)';
} }
} }
String getTrayIconPath({ String getTrayIconPath({
required Brightness brightness, required Brightness brightness,
}) { }) {
if (Platform.isMacOS) { if (system.isMacOS) {
return "assets/images/icon_white.png"; return 'assets/images/icon_white.png';
} }
final suffix = Platform.isWindows ? "ico" : "png"; final suffix = system.isWindows ? 'ico' : 'png';
return "assets/images/icon.$suffix"; return 'assets/images/icon.$suffix';
// return switch (brightness) { // return switch (brightness) {
// Brightness.dark => "assets/images/icon_white.$suffix", // Brightness.dark => "assets/images/icon_white.$suffix",
// Brightness.light => "assets/images/icon_black.$suffix", // Brightness.light => "assets/images/icon_black.$suffix",
@@ -181,7 +181,7 @@ class Utils {
String getPinyin(String value) { String getPinyin(String value) {
return value.isNotEmpty return value.isNotEmpty
? PinyinHelper.getFirstWordPinyin(value.substring(0, 1)) ? PinyinHelper.getFirstWordPinyin(value.substring(0, 1))
: ""; : '';
} }
String? getFileNameForDisposition(String? disposition) { String? getFileNameForDisposition(String? disposition) {
@@ -189,7 +189,7 @@ class Utils {
final parseValue = HeaderValue.parse(disposition); final parseValue = HeaderValue.parse(disposition);
final parameters = parseValue.parameters; final parameters = parseValue.parameters;
final fileNamePointKey = parameters.keys final fileNamePointKey = parameters.keys
.firstWhere((key) => key == "filename*", orElse: () => ""); .firstWhere((key) => key == 'filename*', orElse: () => '');
if (fileNamePointKey.isNotEmpty) { if (fileNamePointKey.isNotEmpty) {
final res = parameters[fileNamePointKey]?.split("''") ?? []; final res = parameters[fileNamePointKey]?.split("''") ?? [];
if (res.length >= 2) { if (res.length >= 2) {
@@ -197,7 +197,7 @@ class Utils {
} }
} }
final fileNameKey = parameters.keys final fileNameKey = parameters.keys
.firstWhere((key) => key == "filename", orElse: () => ""); .firstWhere((key) => key == 'filename', orElse: () => '');
if (fileNameKey.isEmpty) return null; if (fileNameKey.isEmpty) return null;
return parameters[fileNameKey]; return parameters[fileNameKey];
} }
@@ -250,7 +250,7 @@ class Utils {
900, 900,
]; ];
_createPrimarySwatch(Color color) { MaterialColor _createPrimarySwatch(Color color) {
final Map<int, Color> swatch = <int, Color>{}; final Map<int, Color> swatch = <int, Color>{};
final int a = color.alpha8bit; final int a = color.alpha8bit;
final int r = color.red8bit; final int r = color.red8bit;
@@ -294,11 +294,11 @@ class Utils {
} }
String getBackupFileName() { String getBackupFileName() {
return "${appName}_backup_${DateTime.now().show}.zip"; return '${appName}_backup_${DateTime.now().show}.zip';
} }
String get logFile { String get logFile {
return "${appName}_${DateTime.now().show}.log"; return '${appName}_${DateTime.now().show}.log';
} }
Future<String?> getLocalIpAddress() async { Future<String?> getLocalIpAddress() async {
@@ -324,11 +324,11 @@ class Utils {
}); });
return addresses.first.address; return addresses.first.address;
} }
return ""; return '';
} }
SingleActivator controlSingleActivator(LogicalKeyboardKey trigger) { SingleActivator controlSingleActivator(LogicalKeyboardKey trigger) {
final control = Platform.isMacOS ? false : true; final control = system.isMacOS ? false : true;
return SingleActivator( return SingleActivator(
trigger, trigger,
control: control, control: control,

View File

@@ -3,30 +3,34 @@ import 'dart:io';
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart' as acrylic;
import 'package:screen_retriever/screen_retriever.dart'; import 'package:screen_retriever/screen_retriever.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
class Window { class Window {
init(int version) async { Future<void> init(int version) async {
final props = globalState.config.windowProps; final props = globalState.config.windowProps;
final acquire = await singleInstanceLock.acquire(); final acquire = await singleInstanceLock.acquire();
if (!acquire) { if (!acquire) {
exit(0); exit(0);
} }
if (Platform.isWindows) { if (system.isWindows) {
protocol.register("clash"); protocol.register('clash');
protocol.register("clashmeta"); protocol.register('clashmeta');
protocol.register("flclash"); protocol.register('flclash');
}
if ((version > 10 && system.isMacOS)) {
await acrylic.Window.initialize();
} }
await windowManager.ensureInitialized(); await windowManager.ensureInitialized();
WindowOptions windowOptions = WindowOptions( WindowOptions windowOptions = WindowOptions(
size: Size(props.width, props.height), size: Size(props.width, props.height),
minimumSize: const Size(380, 400), minimumSize: const Size(380, 400),
); );
if (!Platform.isMacOS || version > 10) { if (!system.isMacOS || version > 10) {
await windowManager.setTitleBarStyle(TitleBarStyle.hidden); await windowManager.setTitleBarStyle(TitleBarStyle.hidden);
} }
if (!Platform.isMacOS) { if (!system.isMacOS) {
final left = props.left ?? 0; final left = props.left ?? 0;
final top = props.top ?? 0; final top = props.top ?? 0;
final right = left + props.width; final right = left + props.width;
@@ -62,7 +66,14 @@ class Window {
}); });
} }
show() async { void updateMacOSBrightness(Brightness brightness) {
if (!system.isMacOS) {
return;
}
acrylic.Window.overrideMacOSBrightness(dark: brightness == Brightness.dark);
}
Future<void> show() async {
render?.resume(); render?.resume();
await windowManager.show(); await windowManager.show();
await windowManager.focus(); await windowManager.focus();
@@ -71,15 +82,15 @@ class Window {
Future<bool> get isVisible async { Future<bool> get isVisible async {
final value = await windowManager.isVisible(); final value = await windowManager.isVisible();
commonPrint.log("window visible check: $value"); commonPrint.log('window visible check: $value');
return value; return value;
} }
close() async { Future<void> close() async {
exit(0); exit(0);
} }
hide() async { Future<void> hide() async {
render?.pause(); render?.pause();
await windowManager.hide(); await windowManager.hide();
await windowManager.setSkipTaskbar(true); await windowManager.setSkipTaskbar(true);

View File

@@ -1,191 +0,0 @@
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:path/path.dart';
class Windows {
static Windows? _instance;
late DynamicLibrary _shell32;
Windows._internal() {
_shell32 = DynamicLibrary.open('shell32.dll');
}
factory Windows() {
_instance ??= Windows._internal();
return _instance!;
}
bool runas(String command, String arguments) {
final commandPtr = command.toNativeUtf16();
final argumentsPtr = arguments.toNativeUtf16();
final operationPtr = 'runas'.toNativeUtf16();
final shellExecute = _shell32.lookupFunction<
Int32 Function(
Pointer<Utf16> hwnd,
Pointer<Utf16> lpOperation,
Pointer<Utf16> lpFile,
Pointer<Utf16> lpParameters,
Pointer<Utf16> lpDirectory,
Int32 nShowCmd),
int Function(
Pointer<Utf16> hwnd,
Pointer<Utf16> lpOperation,
Pointer<Utf16> lpFile,
Pointer<Utf16> lpParameters,
Pointer<Utf16> lpDirectory,
int nShowCmd)>('ShellExecuteW');
final result = shellExecute(
nullptr,
operationPtr,
commandPtr,
argumentsPtr,
nullptr,
1,
);
calloc.free(commandPtr);
calloc.free(argumentsPtr);
calloc.free(operationPtr);
commonPrint.log("windows runas: $command $arguments resultCode:$result");
if (result < 42) {
return false;
}
return true;
}
_killProcess(int port) async {
final result = await Process.run('netstat', ['-ano']);
final lines = result.stdout.toString().trim().split('\n');
for (final line in lines) {
if (!line.contains(":$port") || !line.contains("LISTENING")) {
continue;
}
final parts = line.trim().split(RegExp(r'\s+'));
final pid = int.tryParse(parts.last);
if (pid != null) {
await Process.run('taskkill', ['/PID', pid.toString(), '/F']);
}
}
}
Future<WindowsHelperServiceStatus> checkService() async {
// final qcResult = await Process.run('sc', ['qc', appHelperService]);
// final qcOutput = qcResult.stdout.toString();
// if (qcResult.exitCode != 0 || !qcOutput.contains(appPath.helperPath)) {
// return WindowsHelperServiceStatus.none;
// }
final result = await Process.run('sc', ['query', appHelperService]);
if(result.exitCode != 0){
return WindowsHelperServiceStatus.none;
}
final output = result.stdout.toString();
if (output.contains("RUNNING") && await request.pingHelper()) {
return WindowsHelperServiceStatus.running;
}
return WindowsHelperServiceStatus.presence;
}
Future<bool> registerService() async {
final status = await checkService();
if (status == WindowsHelperServiceStatus.running) {
return true;
}
await _killProcess(helperPort);
final command = [
"/c",
if (status == WindowsHelperServiceStatus.presence) ...[
"sc",
"delete",
appHelperService,
"/force",
"&&",
],
"sc",
"create",
appHelperService,
'binPath= "${appPath.helperPath}"',
'start= auto',
"&&",
"sc",
"start",
appHelperService,
].join(" ");
final res = runas("cmd.exe", command);
await Future.delayed(
Duration(milliseconds: 300),
);
return res;
}
Future<bool> registerTask(String appName) async {
final taskXml = '''
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<Principals>
<Principal id="Author">
<LogonType>InteractiveToken</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Triggers>
<LogonTrigger/>
</Triggers>
<Settings>
<MultipleInstancesPolicy>Parallel</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>false</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>false</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>"${Platform.resolvedExecutable}"</Command>
</Exec>
</Actions>
</Task>''';
final taskPath = join(await appPath.tempPath, "task.xml");
await File(taskPath).create(recursive: true);
await File(taskPath)
.writeAsBytes(taskXml.encodeUtf16LeWithBom, flush: true);
final commandLine = [
'/Create',
'/TN',
appName,
'/XML',
"%s",
'/F',
].join(" ");
return runas(
'schtasks',
commandLine.replaceFirst("%s", taskPath),
);
}
}
final windows = Platform.isWindows ? Windows() : null;

View File

@@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:isolate'; import 'dart:isolate';
import 'dart:typed_data';
import 'package:archive/archive.dart'; import 'package:archive/archive.dart';
import 'package:fl_clash/clash/clash.dart'; import 'package:fl_clash/clash/clash.dart';
@@ -12,7 +11,9 @@ import 'package:fl_clash/plugins/app.dart';
import 'package:fl_clash/providers/providers.dart'; import 'package:fl_clash/providers/providers.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:fl_clash/widgets/dialog.dart'; import 'package:fl_clash/widgets/dialog.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:path/path.dart'; import 'package:path/path.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@@ -29,29 +30,29 @@ class AppController {
AppController(this.context, WidgetRef ref) : _ref = ref; AppController(this.context, WidgetRef ref) : _ref = ref;
setupClashConfigDebounce() { void setupClashConfigDebounce() {
debouncer.call(FunctionTag.setupClashConfig, () async { debouncer.call(FunctionTag.setupClashConfig, () async {
await setupClashConfig(); await setupClashConfig();
}); });
} }
updateClashConfigDebounce() { Future<void> updateClashConfigDebounce() async {
debouncer.call(FunctionTag.updateClashConfig, () async { debouncer.call(FunctionTag.updateClashConfig, () async {
await updateClashConfig(); await updateClashConfig();
}); });
} }
updateGroupsDebounce() { void updateGroupsDebounce() {
debouncer.call(FunctionTag.updateGroups, updateGroups); debouncer.call(FunctionTag.updateGroups, updateGroups);
} }
addCheckIpNumDebounce() { void addCheckIpNumDebounce() {
debouncer.call(FunctionTag.addCheckIpNum, () { debouncer.call(FunctionTag.addCheckIpNum, () {
_ref.read(checkIpNumProvider.notifier).add(); _ref.read(checkIpNumProvider.notifier).add();
}); });
} }
applyProfileDebounce({ void applyProfileDebounce({
bool silence = false, bool silence = false,
}) { }) {
debouncer.call(FunctionTag.applyProfile, (silence) { debouncer.call(FunctionTag.applyProfile, (silence) {
@@ -59,11 +60,11 @@ class AppController {
}, args: [silence]); }, args: [silence]);
} }
savePreferencesDebounce() { void savePreferencesDebounce() {
debouncer.call(FunctionTag.savePreferences, savePreferences); debouncer.call(FunctionTag.savePreferences, savePreferences);
} }
changeProxyDebounce(String groupName, String proxyName) { void changeProxyDebounce(String groupName, String proxyName) {
debouncer.call(FunctionTag.changeProxy, debouncer.call(FunctionTag.changeProxy,
(String groupName, String proxyName) async { (String groupName, String proxyName) async {
await changeProxy( await changeProxy(
@@ -74,8 +75,8 @@ class AppController {
}, args: [groupName, proxyName]); }, args: [groupName, proxyName]);
} }
restartCore() async { Future<void> restartCore() async {
commonPrint.log("restart core"); commonPrint.log('restart core');
await clashService?.reStart(); await clashService?.reStart();
await _initCore(); await _initCore();
if (_ref.read(runTimeProvider.notifier).isStart) { if (_ref.read(runTimeProvider.notifier).isStart) {
@@ -83,7 +84,7 @@ class AppController {
} }
} }
updateStatus(bool isStart) async { Future<void> updateStatus(bool isStart) async {
if (isStart) { if (isStart) {
await globalState.handleStart([ await globalState.handleStart([
updateRunTime, updateRunTime,
@@ -102,7 +103,7 @@ class AppController {
applyProfileDebounce(); applyProfileDebounce();
} else { } else {
await globalState.handleStop(); await globalState.handleStop();
await clashCore.resetTraffic(); clashCore.resetTraffic();
_ref.read(trafficsProvider.notifier).clear(); _ref.read(trafficsProvider.notifier).clear();
_ref.read(totalTrafficProvider.notifier).value = Traffic(); _ref.read(totalTrafficProvider.notifier).value = Traffic();
_ref.read(runTimeProvider.notifier).value = null; _ref.read(runTimeProvider.notifier).value = null;
@@ -110,7 +111,7 @@ class AppController {
} }
} }
updateRunTime() { void updateRunTime() {
final startTime = globalState.startTime; final startTime = globalState.startTime;
if (startTime != null) { if (startTime != null) {
final startTimeStamp = startTime.millisecondsSinceEpoch; final startTimeStamp = startTime.millisecondsSinceEpoch;
@@ -121,20 +122,20 @@ class AppController {
} }
} }
updateTraffic() async { Future<void> updateTraffic() async {
final traffic = await clashCore.getTraffic(); final traffic = await clashCore.getTraffic();
_ref.read(trafficsProvider.notifier).addTraffic(traffic); _ref.read(trafficsProvider.notifier).addTraffic(traffic);
_ref.read(totalTrafficProvider.notifier).value = _ref.read(totalTrafficProvider.notifier).value =
await clashCore.getTotalTraffic(); await clashCore.getTotalTraffic();
} }
addProfile(Profile profile) async { Future<void> addProfile(Profile profile) async {
_ref.read(profilesProvider.notifier).setProfile(profile); _ref.read(profilesProvider.notifier).setProfile(profile);
if (_ref.read(currentProfileIdProvider) != null) return; if (_ref.read(currentProfileIdProvider) != null) return;
_ref.read(currentProfileIdProvider.notifier).value = profile.id; _ref.read(currentProfileIdProvider.notifier).value = profile.id;
} }
deleteProfile(String id) async { Future<void> deleteProfile(String id) async {
_ref.read(profilesProvider.notifier).deleteProfileById(id); _ref.read(profilesProvider.notifier).deleteProfileById(id);
clearEffect(id); clearEffect(id);
if (globalState.config.currentProfileId == id) { if (globalState.config.currentProfileId == id) {
@@ -150,12 +151,12 @@ class AppController {
} }
} }
updateProviders() async { Future<void> updateProviders() async {
_ref.read(providersProvider.notifier).value = _ref.read(providersProvider.notifier).value =
await clashCore.getExternalProviders(); await clashCore.getExternalProviders();
} }
updateLocalIp() async { Future<void> updateLocalIp() async {
_ref.read(localIpProvider.notifier).value = null; _ref.read(localIpProvider.notifier).value = null;
await Future.delayed(commonDuration); await Future.delayed(commonDuration);
_ref.read(localIpProvider.notifier).value = await utils.getLocalIpAddress(); _ref.read(localIpProvider.notifier).value = await utils.getLocalIpAddress();
@@ -171,26 +172,26 @@ class AppController {
} }
} }
setProfile(Profile profile) { void setProfile(Profile profile) {
_ref.read(profilesProvider.notifier).setProfile(profile); _ref.read(profilesProvider.notifier).setProfile(profile);
} }
setProfileAndAutoApply(Profile profile) { void setProfileAndAutoApply(Profile profile) {
_ref.read(profilesProvider.notifier).setProfile(profile); _ref.read(profilesProvider.notifier).setProfile(profile);
if (profile.id == _ref.read(currentProfileIdProvider)) { if (profile.id == _ref.read(currentProfileIdProvider)) {
applyProfileDebounce(silence: true); applyProfileDebounce(silence: true);
} }
} }
setProfiles(List<Profile> profiles) { void setProfiles(List<Profile> profiles) {
_ref.read(profilesProvider.notifier).value = profiles; _ref.read(profilesProvider.notifier).value = profiles;
} }
addLog(Log log) { void addLog(Log log) {
_ref.read(logsProvider).add(log); _ref.read(logsProvider).add(log);
} }
updateOrAddHotKeyAction(HotKeyAction hotKeyAction) { void updateOrAddHotKeyAction(HotKeyAction hotKeyAction) {
final hotKeyActions = _ref.read(hotKeyActionsProvider); final hotKeyActions = _ref.read(hotKeyActionsProvider);
final index = final index =
hotKeyActions.indexWhere((item) => item.action == hotKeyAction.action); hotKeyActions.indexWhere((item) => item.action == hotKeyAction.action);
@@ -219,26 +220,26 @@ class AppController {
return _ref.read(getProxiesColumnsProvider); return _ref.read(getProxiesColumnsProvider);
} }
addSortNum() { dynamic addSortNum() {
return _ref.read(sortNumProvider.notifier).add(); return _ref.read(sortNumProvider.notifier).add();
} }
getCurrentGroupName() { String? getCurrentGroupName() {
final currentGroupName = _ref.read(currentProfileProvider.select( final currentGroupName = _ref.read(currentProfileProvider.select(
(state) => state?.currentGroupName, (state) => state?.currentGroupName,
)); ));
return currentGroupName; return currentGroupName;
} }
ProxyCardState getProxyCardState(proxyName) { ProxyCardState getProxyCardState(String proxyName) {
return _ref.read(getProxyCardStateProvider(proxyName)); return _ref.read(getProxyCardStateProvider(proxyName));
} }
getSelectedProxyName(groupName) { String? getSelectedProxyName(String groupName) {
return _ref.read(getSelectedProxyNameProvider(groupName)); return _ref.read(getSelectedProxyNameProvider(groupName));
} }
updateCurrentGroupName(String groupName) { void updateCurrentGroupName(String groupName) {
final profile = _ref.read(currentProfileProvider); final profile = _ref.read(currentProfileProvider);
if (profile == null || profile.currentGroupName == groupName) { if (profile == null || profile.currentGroupName == groupName) {
return; return;
@@ -249,11 +250,12 @@ class AppController {
} }
Future<void> updateClashConfig() async { Future<void> updateClashConfig() async {
final commonScaffoldState = globalState.homeScaffoldKey.currentState; await safeRun(
if (commonScaffoldState?.mounted != true) return; () async {
await commonScaffoldState?.loadingRun(() async { await _updateClashConfig();
await _updateClashConfig(); },
}); needLoading: true,
);
} }
Future<void> _updateClashConfig() async { Future<void> _updateClashConfig() async {
@@ -272,13 +274,16 @@ class AppController {
} }
Future<Result<bool>> _requestAdmin(bool enableTun) async { Future<Result<bool>> _requestAdmin(bool enableTun) async {
if(system.isWindows && kDebugMode){
return Result.success(false);
}
final realTunEnable = _ref.read(realTunEnableProvider); final realTunEnable = _ref.read(realTunEnableProvider);
if (enableTun != realTunEnable && realTunEnable == false) { if (enableTun != realTunEnable && realTunEnable == false) {
final code = await system.authorizeCore(); final code = await system.authorizeCore();
switch (code) { switch (code) {
case AuthorizeCode.success: case AuthorizeCode.success:
await restartCore(); await restartCore();
return Result.error(""); return Result.error('');
case AuthorizeCode.none: case AuthorizeCode.none:
break; break;
case AuthorizeCode.error: case AuthorizeCode.error:
@@ -291,14 +296,15 @@ class AppController {
} }
Future<void> setupClashConfig() async { Future<void> setupClashConfig() async {
final commonScaffoldState = globalState.homeScaffoldKey.currentState; await safeRun(
if (commonScaffoldState?.mounted != true) return; () async {
await commonScaffoldState?.loadingRun(() async { await _setupClashConfig();
await _setupClashConfig(); },
}); needLoading: true,
);
} }
_setupClashConfig() async { Future<void> _setupClashConfig() async {
await _ref.read(currentProfileProvider)?.checkAndUpdate(); await _ref.read(currentProfileProvider)?.checkAndUpdate();
final patchConfig = _ref.read(patchClashConfigProvider); final patchConfig = _ref.read(patchClashConfigProvider);
final res = await _requestAdmin(patchConfig.tun.enable); final res = await _requestAdmin(patchConfig.tun.enable);
@@ -332,29 +338,32 @@ class AppController {
if (silence) { if (silence) {
await _applyProfile(); await _applyProfile();
} else { } else {
final commonScaffoldState = globalState.homeScaffoldKey.currentState; await safeRun(
if (commonScaffoldState?.mounted != true) return; () async {
await commonScaffoldState?.loadingRun(() async { await _applyProfile();
await _applyProfile(); },
}); needLoading: true,
);
} }
addCheckIpNumDebounce(); addCheckIpNumDebounce();
} }
handleChangeProfile() { void handleChangeProfile() {
_ref.read(delayDataSourceProvider.notifier).value = {}; _ref.read(delayDataSourceProvider.notifier).value = {};
applyProfile(); applyProfile();
_ref.read(logsProvider.notifier).value = FixedList(500); _ref.read(logsProvider.notifier).value = FixedList(500);
_ref.read(requestsProvider.notifier).value = FixedList(500); _ref.read(requestsProvider.notifier).value = FixedList(500);
globalState.cacheHeightMap = {}; globalState.computeHeightMapCache = {};
globalState.cacheScrollPosition = {};
} }
updateBrightness(Brightness brightness) { void updateBrightness() {
_ref.read(appBrightnessProvider.notifier).value = brightness; WidgetsBinding.instance.addPostFrameCallback((_) {
_ref.read(systemBrightnessProvider.notifier).value =
WidgetsBinding.instance.platformDispatcher.platformBrightness;
});
} }
autoUpdateProfiles() async { Future<void> autoUpdateProfiles() async {
for (final profile in _ref.read(profilesProvider)) { for (final profile in _ref.read(profilesProvider)) {
if (!profile.autoUpdate) continue; if (!profile.autoUpdate) continue;
final isNotNeedUpdate = profile.lastUpdateDate final isNotNeedUpdate = profile.lastUpdateDate
@@ -386,7 +395,7 @@ class AppController {
} }
} }
updateProfiles() async { Future<void> updateProfiles() async {
for (final profile in _ref.read(profilesProvider)) { for (final profile in _ref.read(profilesProvider)) {
if (profile.type == ProfileType.file) { if (profile.type == ProfileType.file) {
continue; continue;
@@ -395,12 +404,12 @@ class AppController {
} }
} }
savePreferences() async { Future<void> savePreferences() async {
commonPrint.log("save preferences"); commonPrint.log('save preferences');
await preferences.saveConfig(globalState.config); await preferences.saveConfig(globalState.config);
} }
changeProxy({ Future<void> changeProxy({
required String groupName, required String groupName,
required String proxyName, required String proxyName,
}) async { }) async {
@@ -416,13 +425,13 @@ class AppController {
addCheckIpNumDebounce(); addCheckIpNumDebounce();
} }
handleBackOrExit() async { Future<void> handleBackOrExit() async {
if (_ref.read(backBlockProvider)) { if (_ref.read(backBlockProvider)) {
return; return;
} }
if (_ref.read(appSettingProvider).minimizeOnExit) { if (_ref.read(appSettingProvider).minimizeOnExit) {
if (system.isDesktop) { if (system.isDesktop) {
await savePreferencesDebounce(); await savePreferences();
} }
await system.back(); await system.back();
} else { } else {
@@ -430,21 +439,21 @@ class AppController {
} }
} }
backBlock() { void backBlock() {
_ref.read(backBlockProvider.notifier).value = true; _ref.read(backBlockProvider.notifier).value = true;
} }
unBackBlock() { void unBackBlock() {
_ref.read(backBlockProvider.notifier).value = false; _ref.read(backBlockProvider.notifier).value = false;
} }
handleExit() async { Future<void> handleExit() async {
Future.delayed(commonDuration, () { Future.delayed(commonDuration, () {
system.exit(); system.exit();
}); });
try { try {
await savePreferences(); await savePreferences();
await system.setMacOSDns(true); await macOS?.updateDns(true);
await proxy?.stopProxy(); await proxy?.stopProxy();
await clashCore.shutdown(); await clashCore.shutdown();
await clashService?.destroy(); await clashService?.destroy();
@@ -455,19 +464,19 @@ class AppController {
Future handleClear() async { Future handleClear() async {
await preferences.clearPreferences(); await preferences.clearPreferences();
commonPrint.log("clear preferences"); commonPrint.log('clear preferences');
globalState.config = Config( globalState.config = Config(
themeProps: defaultThemeProps, themeProps: defaultThemeProps,
); );
} }
autoCheckUpdate() async { Future<void> autoCheckUpdate() async {
if (!_ref.read(appSettingProvider).autoCheckUpdate) return; if (!_ref.read(appSettingProvider).autoCheckUpdate) return;
final res = await request.checkForUpdate(); final res = await request.checkForUpdate();
checkUpdateResultHandle(data: res); checkUpdateResultHandle(data: res);
} }
checkUpdateResultHandle({ Future<void> checkUpdateResultHandle({
Map<String, dynamic>? data, Map<String, dynamic>? data,
bool handleError = false, bool handleError = false,
}) async { }) async {
@@ -482,16 +491,16 @@ class AppController {
final res = await globalState.showMessage( final res = await globalState.showMessage(
title: appLocalizations.discoverNewVersion, title: appLocalizations.discoverNewVersion,
message: TextSpan( message: TextSpan(
text: "$tagName \n", text: '$tagName \n',
style: textTheme.headlineSmall, style: textTheme.headlineSmall,
children: [ children: [
TextSpan( TextSpan(
text: "\n", text: '\n',
style: textTheme.bodyMedium, style: textTheme.bodyMedium,
), ),
for (final submit in submits) for (final submit in submits)
TextSpan( TextSpan(
text: "- $submit \n", text: '- $submit \n',
style: textTheme.bodyMedium, style: textTheme.bodyMedium,
), ),
], ],
@@ -502,7 +511,7 @@ class AppController {
return; return;
} }
launchUrl( launchUrl(
Uri.parse("https://github.com/$repository/releases/latest"), Uri.parse('https://github.com/$repository/releases/latest'),
); );
} else if (handleError) { } else if (handleError) {
globalState.showMessage( globalState.showMessage(
@@ -514,7 +523,7 @@ class AppController {
} }
} }
_handlePreference() async { Future<void> _handlePreference() async {
if (await preferences.isInit) { if (await preferences.isInit) {
return; return;
} }
@@ -543,9 +552,11 @@ class AppController {
await applyProfile(); await applyProfile();
} }
init() async { Future<void> init() async {
FlutterError.onError = (details) { FlutterError.onError = (details) {
commonPrint.log(details.stack.toString()); if (kDebugMode) {
commonPrint.log(details.stack.toString());
}
}; };
updateTray(true); updateTray(true);
await _initCore(); await _initCore();
@@ -565,8 +576,8 @@ class AppController {
_ref.read(initProvider.notifier).value = true; _ref.read(initProvider.notifier).value = true;
} }
_initStatus() async { Future<void> _initStatus() async {
if (Platform.isAndroid) { if (system.isAndroid) {
await globalState.updateStartTime(); await globalState.updateStartTime();
} }
final status = globalState.isStart == true final status = globalState.isStart == true
@@ -579,28 +590,28 @@ class AppController {
} }
} }
setDelay(Delay delay) { void setDelay(Delay delay) {
_ref.read(delayDataSourceProvider.notifier).setDelay(delay); _ref.read(delayDataSourceProvider.notifier).setDelay(delay);
} }
toPage(PageLabel pageLabel) { void toPage(PageLabel pageLabel) {
_ref.read(currentPageLabelProvider.notifier).value = pageLabel; _ref.read(currentPageLabelProvider.notifier).value = pageLabel;
} }
toProfiles() { void toProfiles() {
toPage(PageLabel.profiles); toPage(PageLabel.profiles);
} }
initLink() { void initLink() {
linkManager.initAppLinksListen( linkManager.initAppLinksListen(
(url) async { (url) async {
final res = await globalState.showMessage( final res = await globalState.showMessage(
title: "${appLocalizations.add}${appLocalizations.profile}", title: '${appLocalizations.add}${appLocalizations.profile}',
message: TextSpan( message: TextSpan(
children: [ children: [
TextSpan(text: appLocalizations.doYouWantToPass), TextSpan(text: appLocalizations.doYouWantToPass),
TextSpan( TextSpan(
text: " $url ", text: ' $url ',
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
decoration: TextDecoration.underline, decoration: TextDecoration.underline,
@@ -609,7 +620,7 @@ class AppController {
), ),
TextSpan( TextSpan(
text: text:
"${appLocalizations.create}${appLocalizations.profile}"), '${appLocalizations.create}${appLocalizations.profile}'),
], ],
), ),
); );
@@ -652,7 +663,7 @@ class AppController {
false; false;
} }
_handlerDisclaimer() async { Future<void> _handlerDisclaimer() async {
if (_ref.read(appSettingProvider).disclaimerAccepted) { if (_ref.read(appSettingProvider).disclaimerAccepted) {
return; return;
} }
@@ -663,62 +674,64 @@ class AppController {
return; return;
} }
addProfileFormURL(String url) async { Future<void> addProfileFormURL(String url) async {
if (globalState.navigatorKey.currentState?.canPop() ?? false) { if (globalState.navigatorKey.currentState?.canPop() ?? false) {
globalState.navigatorKey.currentState?.popUntil((route) => route.isFirst); globalState.navigatorKey.currentState?.popUntil((route) => route.isFirst);
} }
toProfiles(); toProfiles();
final commonScaffoldState = globalState.homeScaffoldKey.currentState;
if (commonScaffoldState?.mounted != true) return; final profile = await safeRun(
final profile = await commonScaffoldState?.loadingRun<Profile>(
() async { () async {
return await Profile.normal( return await Profile.normal(
url: url, url: url,
).update(); ).update();
}, },
title: "${appLocalizations.add}${appLocalizations.profile}", needLoading: true,
title: '${appLocalizations.add}${appLocalizations.profile}',
); );
if (profile != null) { if (profile != null) {
await addProfile(profile); await addProfile(profile);
} }
} }
addProfileFormFile() async { Future<void> addProfileFormFile() async {
final platformFile = await globalState.safeRun(picker.pickerFile); final platformFile = await safeRun(picker.pickerFile);
final bytes = platformFile?.bytes; final bytes = platformFile?.bytes;
if (bytes == null) { if (bytes == null) {
return null; return;
} }
if (!context.mounted) return; if (!context.mounted) return;
globalState.navigatorKey.currentState?.popUntil((route) => route.isFirst); globalState.navigatorKey.currentState?.popUntil((route) => route.isFirst);
toProfiles(); toProfiles();
final commonScaffoldState = globalState.homeScaffoldKey.currentState;
if (commonScaffoldState?.mounted != true) return; final profile = await safeRun(
final profile = await commonScaffoldState?.loadingRun<Profile?>(
() async { () async {
await Future.delayed(const Duration(milliseconds: 300)); await Future.delayed(const Duration(milliseconds: 300));
return await Profile.normal(label: platformFile?.name).saveFile(bytes); return await Profile.normal(label: platformFile?.name).saveFile(bytes);
}, },
title: "${appLocalizations.add}${appLocalizations.profile}", needLoading: true,
title: '${appLocalizations.add}${appLocalizations.profile}',
); );
if (profile != null) { if (profile != null) {
await addProfile(profile); await addProfile(profile);
} }
} }
addProfileFormQrCode() async { Future<void> addProfileFormQrCode() async {
final url = await globalState.safeRun(picker.pickerConfigQRCode); final url = await safeRun(
picker.pickerConfigQRCode,
);
if (url == null) return; if (url == null) return;
addProfileFormURL(url); addProfileFormURL(url);
} }
updateViewSize(Size size) { void updateViewSize(Size size) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_ref.read(viewSizeProvider.notifier).value = size; _ref.read(viewSizeProvider.notifier).value = size;
}); });
} }
setProvider(ExternalProvider? provider) { void setProvider(ExternalProvider? provider) {
_ref.read(providersProvider.notifier).setProvider(provider); _ref.read(providersProvider.notifier).setProvider(provider);
} }
@@ -763,18 +776,22 @@ class AppController {
); );
} }
List<Proxy> getSortProxies(List<Proxy> proxies, [String? url]) { List<Proxy> getSortProxies({
return switch (_ref.read(proxiesStyleSettingProvider).sortType) { required List<Proxy> proxies,
required ProxiesSortType sortType,
String? testUrl,
}) {
return switch (sortType) {
ProxiesSortType.none => proxies, ProxiesSortType.none => proxies,
ProxiesSortType.delay => _sortOfDelay( ProxiesSortType.delay => _sortOfDelay(
proxies: proxies, proxies: proxies,
testUrl: url, testUrl: testUrl,
), ),
ProxiesSortType.name => _sortOfName(proxies), ProxiesSortType.name => _sortOfName(proxies),
}; };
} }
clearEffect(String profileId) async { Future<Null> clearEffect(String profileId) async {
final profilePath = await appPath.getProfilePath(profileId); final profilePath = await appPath.getProfilePath(profileId);
final providersDirPath = await appPath.getProvidersDirPath(profileId); final providersDirPath = await appPath.getProvidersDirPath(profileId);
return await Isolate.run(() async { return await Isolate.run(() async {
@@ -791,13 +808,13 @@ class AppController {
}); });
} }
updateTun() { void updateTun() {
_ref.read(patchClashConfigProvider.notifier).updateState( _ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.tun(enable: !state.tun.enable), (state) => state.copyWith.tun(enable: !state.tun.enable),
); );
} }
updateSystemProxy() { void updateSystemProxy() {
_ref.read(networkSettingProvider.notifier).updateState( _ref.read(networkSettingProvider.notifier).updateState(
(state) => state.copyWith( (state) => state.copyWith(
systemProxy: !state.systemProxy, systemProxy: !state.systemProxy,
@@ -816,11 +833,11 @@ class AppController {
return _ref.read(packagesProvider); return _ref.read(packagesProvider);
} }
updateStart() { void updateStart() {
updateStatus(!_ref.read(runTimeProvider.notifier).isStart); updateStatus(!_ref.read(runTimeProvider.notifier).isStart);
} }
updateCurrentSelectedMap(String groupName, String proxyName) { void updateCurrentSelectedMap(String groupName, String proxyName) {
final currentProfile = _ref.read(currentProfileProvider); final currentProfile = _ref.read(currentProfileProvider);
if (currentProfile != null && if (currentProfile != null &&
currentProfile.selectedMap[groupName] != proxyName) { currentProfile.selectedMap[groupName] != proxyName) {
@@ -835,7 +852,7 @@ class AppController {
} }
} }
updateCurrentUnfoldSet(Set<String> value) { void updateCurrentUnfoldSet(Set<String> value) {
final currentProfile = _ref.read(currentProfileProvider); final currentProfile = _ref.read(currentProfileProvider);
if (currentProfile == null) { if (currentProfile == null) {
return; return;
@@ -847,7 +864,7 @@ class AppController {
); );
} }
changeMode(Mode mode) { void changeMode(Mode mode) {
_ref.read(patchClashConfigProvider.notifier).updateState( _ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith(mode: mode), (state) => state.copyWith(mode: mode),
); );
@@ -857,7 +874,7 @@ class AppController {
addCheckIpNumDebounce(); addCheckIpNumDebounce();
} }
updateAutoLaunch() { void updateAutoLaunch() {
_ref.read(appSettingProvider.notifier).updateState( _ref.read(appSettingProvider.notifier).updateState(
(state) => state.copyWith( (state) => state.copyWith(
autoLaunch: !state.autoLaunch, autoLaunch: !state.autoLaunch,
@@ -865,7 +882,7 @@ class AppController {
); );
} }
updateVisible() async { Future<void> updateVisible() async {
final visible = await window?.isVisible; final visible = await window?.isVisible;
if (visible != null && !visible) { if (visible != null && !visible) {
window?.show(); window?.show();
@@ -874,7 +891,7 @@ class AppController {
} }
} }
updateMode() { void updateMode() {
_ref.read(patchClashConfigProvider.notifier).updateState( _ref.read(patchClashConfigProvider.notifier).updateState(
(state) { (state) {
final index = Mode.values.indexWhere((item) => item == state.mode); final index = Mode.values.indexWhere((item) => item == state.mode);
@@ -889,7 +906,7 @@ class AppController {
); );
} }
handleAddOrUpdate(WidgetRef ref, [Rule? rule]) async { Future<void> handleAddOrUpdate(WidgetRef ref, [Rule? rule]) async {
final res = await globalState.showCommonDialog<Rule>( final res = await globalState.showCommonDialog<Rule>(
child: AddRuleDialog( child: AddRuleDialog(
rule: rule, rule: rule,
@@ -926,7 +943,7 @@ class AppController {
(item) => item.toString(), (item) => item.toString(),
); );
final data = await Isolate.run<List<int>>(() async { final data = await Isolate.run<List<int>>(() async {
final logsRawString = logsRaw.join("\n"); final logsRawString = logsRaw.join('\n');
return utf8.encode(logsRawString); return utf8.encode(logsRawString);
}); });
return await picker.saveFile( return await picker.saveFile(
@@ -942,20 +959,20 @@ class AppController {
final configJson = globalState.config.toJson(); final configJson = globalState.config.toJson();
return Isolate.run<List<int>>(() async { return Isolate.run<List<int>>(() async {
final archive = Archive(); final archive = Archive();
archive.add("config.json", configJson); archive.add('config.json', configJson);
await archive.addDirectoryToArchive(profilesPath, homeDirPath); archive.addDirectoryToArchive(profilesPath, homeDirPath);
final zipEncoder = ZipEncoder(); final zipEncoder = ZipEncoder();
return zipEncoder.encode(archive) ?? []; return zipEncoder.encode(archive) ?? [];
}); });
} }
updateTray([bool focus = false]) async { Future<void> updateTray([bool focus = false]) async {
tray.update( tray.update(
trayState: _ref.read(trayStateProvider), trayState: _ref.read(trayStateProvider),
); );
} }
recoveryData( Future<void> recoveryData(
List<int> data, List<int> data,
RecoveryOption recoveryOption, RecoveryOption recoveryOption,
) async { ) async {
@@ -965,12 +982,12 @@ class AppController {
}); });
final homeDirPath = await appPath.homeDirPath; final homeDirPath = await appPath.homeDirPath;
final configs = final configs =
archive.files.where((item) => item.name.endsWith(".json")).toList(); archive.files.where((item) => item.name.endsWith('.json')).toList();
final profiles = final profiles =
archive.files.where((item) => !item.name.endsWith(".json")); archive.files.where((item) => !item.name.endsWith('.json'));
final configIndex = final configIndex =
configs.indexWhere((config) => config.name == "config.json"); configs.indexWhere((config) => config.name == 'config.json');
if (configIndex == -1) throw "invalid backup file"; if (configIndex == -1) throw 'invalid backup file';
final configFile = configs[configIndex]; final configFile = configs[configIndex];
var tempConfig = Config.compatibleFromJson( var tempConfig = Config.compatibleFromJson(
json.decode( json.decode(
@@ -984,7 +1001,7 @@ class AppController {
await file.writeAsBytes(profile.content); await file.writeAsBytes(profile.content);
} }
final clashConfigIndex = final clashConfigIndex =
configs.indexWhere((config) => config.name == "clashConfig.json"); configs.indexWhere((config) => config.name == 'clashConfig.json');
if (clashConfigIndex != -1) { if (clashConfigIndex != -1) {
final clashConfigFile = configs[clashConfigIndex]; final clashConfigFile = configs[clashConfigIndex];
tempConfig = tempConfig.copyWith( tempConfig = tempConfig.copyWith(
@@ -1003,7 +1020,7 @@ class AppController {
); );
} }
_recovery(Config config, RecoveryOption recoveryOption) { void _recovery(Config config, RecoveryOption recoveryOption) {
final recoveryStrategy = _ref.read(appSettingProvider.select( final recoveryStrategy = _ref.read(appSettingProvider.select(
(state) => state.recoveryStrategy, (state) => state.recoveryStrategy,
)); ));
@@ -1040,4 +1057,35 @@ class AppController {
_ref.read(currentProfileIdProvider.notifier).value = profiles.first.id; _ref.read(currentProfileIdProvider.notifier).value = profiles.first.id;
} }
} }
Future<T?> safeRun<T>(
FutureOr<T> Function() futureFunction, {
String? title,
bool needLoading = false,
bool silence = true,
}) async {
final realSilence = needLoading == true ? true : silence;
try {
if (needLoading) {
_ref.read(loadingProvider.notifier).value = true;
}
final res = await futureFunction();
return res;
} catch (e) {
commonPrint.log('$e');
if (realSilence) {
globalState.showNotifier(e.toString());
} else {
globalState.showMessage(
title: title ?? appLocalizations.tip,
message: TextSpan(
text: e.toString(),
),
);
}
return null;
} finally {
_ref.read(loadingProvider.notifier).value = false;
}
}
} }

View File

@@ -2,8 +2,10 @@
import 'dart:io'; import 'dart:io';
import 'package:fl_clash/common/system.dart';
import 'package:fl_clash/views/dashboard/widgets/widgets.dart'; import 'package:fl_clash/views/dashboard/widgets/widgets.dart';
import 'package:fl_clash/widgets/widgets.dart'; import 'package:fl_clash/widgets/widgets.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hotkey_manager/hotkey_manager.dart'; import 'package:hotkey_manager/hotkey_manager.dart';
@@ -15,16 +17,16 @@ enum SupportPlatform {
Android; Android;
static SupportPlatform get currentPlatform { static SupportPlatform get currentPlatform {
if (Platform.isWindows) { if (system.isWindows) {
return SupportPlatform.Windows; return SupportPlatform.Windows;
} else if (Platform.isMacOS) { } else if (system.isMacOS) {
return SupportPlatform.MacOS; return SupportPlatform.MacOS;
} else if (Platform.isLinux) { } else if (Platform.isLinux) {
return SupportPlatform.Linux; return SupportPlatform.Linux;
} else if (Platform.isAndroid) { } else if (system.isAndroid) {
return SupportPlatform.Android; return SupportPlatform.Android;
} }
throw "invalid platform"; throw 'invalid platform';
} }
} }
@@ -43,11 +45,11 @@ enum GroupType {
static GroupType parseProfileType(String type) { static GroupType parseProfileType(String type) {
return switch (type) { return switch (type) {
"url-test" => URLTest, 'url-test' => URLTest,
"select" => Selector, 'select' => Selector,
"fallback" => Fallback, 'fallback' => Fallback,
"load-balance" => LoadBalance, 'load-balance' => LoadBalance,
"relay" => Relay, 'relay' => Relay,
String() => throw UnimplementedError(), String() => throw UnimplementedError(),
}; };
} }
@@ -58,7 +60,7 @@ enum GroupName { GLOBAL, Proxy, Auto, Fallback }
extension GroupTypeExtension on GroupType { extension GroupTypeExtension on GroupType {
static List<String> get valueList => GroupType.values static List<String> get valueList => GroupType.values
.map( .map(
(e) => e.toString().split(".").last, (e) => e.toString().split('.').last,
) )
.toList(); .toList();
@@ -80,7 +82,7 @@ enum UsedProxy { GLOBAL, DIRECT, REJECT }
extension UsedProxyExtension on UsedProxy { extension UsedProxyExtension on UsedProxy {
static List<String> get valueList => UsedProxy.values static List<String> get valueList => UsedProxy.values
.map( .map(
(e) => e.toString().split(".").last, (e) => e.toString().split('.').last,
) )
.toList(); .toList();
@@ -97,7 +99,18 @@ enum LogLevel {
warning, warning,
error, error,
silent, silent,
app, }
extension LogLevelExt on LogLevel {
Color? get color {
return switch (this) {
LogLevel.silent => Colors.grey.shade700,
LogLevel.debug => Colors.grey.shade400,
LogLevel.info => null,
LogLevel.warning => Colors.yellowAccent,
LogLevel.error => Colors.redAccent,
};
}
} }
enum TransportProtocol { udp, tcp } enum TransportProtocol { udp, tcp }
@@ -160,18 +173,18 @@ enum ProxyCardType { expand, shrink, min }
enum DnsMode { enum DnsMode {
normal, normal,
@JsonValue("fake-ip") @JsonValue('fake-ip')
fakeIp, fakeIp,
@JsonValue("redir-host") @JsonValue('redir-host')
redirHost, redirHost,
hosts hosts
} }
enum ExternalControllerStatus { enum ExternalControllerStatus {
@JsonValue("") @JsonValue('')
close(""), close(''),
@JsonValue("127.0.0.1:9090") @JsonValue('127.0.0.1:9090')
open("127.0.0.1:9090"); open('127.0.0.1:9090');
final String value; final String value;
@@ -235,9 +248,9 @@ enum ProxiesIconStyle {
} }
enum FontFamily { enum FontFamily {
twEmoji("Twemoji"), twEmoji('Twemoji'),
jetBrainsMono("JetBrainsMono"), jetBrainsMono('JetBrainsMono'),
icon("Icons"); icon('Icons');
final String value; final String value;
@@ -320,6 +333,7 @@ enum FunctionTag {
proxiesTabChange, proxiesTabChange,
logs, logs,
requests, requests,
autoScrollToEnd,
} }
enum DashboardWidget { enum DashboardWidget {
@@ -423,39 +437,39 @@ enum PageLabel {
} }
enum RuleAction { enum RuleAction {
DOMAIN("DOMAIN"), DOMAIN('DOMAIN'),
DOMAIN_SUFFIX("DOMAIN-SUFFIX"), DOMAIN_SUFFIX('DOMAIN-SUFFIX'),
DOMAIN_KEYWORD("DOMAIN-KEYWORD"), DOMAIN_KEYWORD('DOMAIN-KEYWORD'),
DOMAIN_REGEX("DOMAIN-REGEX"), DOMAIN_REGEX('DOMAIN-REGEX'),
GEOSITE("GEOSITE"), GEOSITE('GEOSITE'),
IP_CIDR("IP-CIDR"), IP_CIDR('IP-CIDR'),
IP_CIDR6("IP-CIDR6"), IP_CIDR6('IP-CIDR6'),
IP_SUFFIX("IP-SUFFIX"), IP_SUFFIX('IP-SUFFIX'),
IP_ASN("IP-ASN"), IP_ASN('IP-ASN'),
GEOIP("GEOIP"), GEOIP('GEOIP'),
SRC_GEOIP("SRC-GEOIP"), SRC_GEOIP('SRC-GEOIP'),
SRC_IP_ASN("SRC-IP-ASN"), SRC_IP_ASN('SRC-IP-ASN'),
SRC_IP_CIDR("SRC-IP-CIDR"), SRC_IP_CIDR('SRC-IP-CIDR'),
SRC_IP_SUFFIX("SRC-IP-SUFFIX"), SRC_IP_SUFFIX('SRC-IP-SUFFIX'),
DST_PORT("DST-PORT"), DST_PORT('DST-PORT'),
SRC_PORT("SRC-PORT"), SRC_PORT('SRC-PORT'),
IN_PORT("IN-PORT"), IN_PORT('IN-PORT'),
IN_TYPE("IN-TYPE"), IN_TYPE('IN-TYPE'),
IN_USER("IN-USER"), IN_USER('IN-USER'),
IN_NAME("IN-NAME"), IN_NAME('IN-NAME'),
PROCESS_PATH("PROCESS-PATH"), PROCESS_PATH('PROCESS-PATH'),
PROCESS_PATH_REGEX("PROCESS-PATH-REGEX"), PROCESS_PATH_REGEX('PROCESS-PATH-REGEX'),
PROCESS_NAME("PROCESS-NAME"), PROCESS_NAME('PROCESS-NAME'),
PROCESS_NAME_REGEX("PROCESS-NAME-REGEX"), PROCESS_NAME_REGEX('PROCESS-NAME-REGEX'),
UID("UID"), UID('UID'),
NETWORK("NETWORK"), NETWORK('NETWORK'),
DSCP("DSCP"), DSCP('DSCP'),
RULE_SET("RULE-SET"), RULE_SET('RULE-SET'),
AND("AND"), AND('AND'),
OR("OR"), OR('OR'),
NOT("NOT"), NOT('NOT'),
SUB_RULE("SUB-RULE"), SUB_RULE('SUB-RULE'),
MATCH("MATCH"); MATCH('MATCH');
final String value; final String value;
@@ -493,6 +507,7 @@ enum CacheTag {
logs, logs,
rules, rules,
requests, requests,
proxiesList,
} }
enum Language { enum Language {
@@ -504,3 +519,10 @@ enum ImportOption {
file, file,
url, url,
} }
enum ScrollPositionCacheKeys {
tools,
profiles,
proxiesList,
proxiesTabList,
}

View File

@@ -26,19 +26,21 @@ class MessageLookup extends MessageLookupByLibrary {
static String m1(label) => static String m1(label) =>
"Are you sure you want to delete the current ${label}?"; "Are you sure you want to delete the current ${label}?";
static String m2(label) => "${label} cannot be empty"; static String m2(label) => "${label} details";
static String m3(label) => "Current ${label} already exists"; static String m3(label) => "${label} cannot be empty";
static String m4(label) => "No ${label} at the moment"; static String m4(label) => "Current ${label} already exists";
static String m5(label) => "${label} must be a number"; static String m5(label) => "No ${label} at the moment";
static String m6(label) => "${label} must be between 1024 and 49151"; static String m6(label) => "${label} must be a number";
static String m7(count) => "${count} items have been selected"; static String m7(label) => "${label} must be between 1024 and 49151";
static String m8(label) => "${label} must be a url"; static String m8(count) => "${count} items have been selected";
static String m9(label) => "${label} must be a url";
final messages = _notInlinedMessages(_notInlinedMessages); final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{ static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@@ -175,6 +177,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Opening it will lose part of its application ability and gain the support of full amount of Clash.", "Opening it will lose part of its application ability and gain the support of full amount of Clash.",
), ),
"confirm": MessageLookupByLibrary.simpleMessage("Confirm"), "confirm": MessageLookupByLibrary.simpleMessage("Confirm"),
"connection": MessageLookupByLibrary.simpleMessage("Connection"),
"connections": MessageLookupByLibrary.simpleMessage("Connections"), "connections": MessageLookupByLibrary.simpleMessage("Connections"),
"connectionsDesc": MessageLookupByLibrary.simpleMessage( "connectionsDesc": MessageLookupByLibrary.simpleMessage(
"View current connections data", "View current connections data",
@@ -194,6 +197,7 @@ class MessageLookup extends MessageLookupByLibrary {
"country": MessageLookupByLibrary.simpleMessage("Country"), "country": MessageLookupByLibrary.simpleMessage("Country"),
"crashTest": MessageLookupByLibrary.simpleMessage("Crash test"), "crashTest": MessageLookupByLibrary.simpleMessage("Crash test"),
"create": MessageLookupByLibrary.simpleMessage("Create"), "create": MessageLookupByLibrary.simpleMessage("Create"),
"creationTime": MessageLookupByLibrary.simpleMessage("Creation time"),
"cut": MessageLookupByLibrary.simpleMessage("Cut"), "cut": MessageLookupByLibrary.simpleMessage("Cut"),
"dark": MessageLookupByLibrary.simpleMessage("Dark"), "dark": MessageLookupByLibrary.simpleMessage("Dark"),
"dashboard": MessageLookupByLibrary.simpleMessage("Dashboard"), "dashboard": MessageLookupByLibrary.simpleMessage("Dashboard"),
@@ -214,6 +218,14 @@ class MessageLookup extends MessageLookupByLibrary {
"desc": MessageLookupByLibrary.simpleMessage( "desc": MessageLookupByLibrary.simpleMessage(
"A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.", "A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.",
), ),
"destination": MessageLookupByLibrary.simpleMessage("Destination"),
"destinationGeoIP": MessageLookupByLibrary.simpleMessage(
"Destination GeoIP",
),
"destinationIPASN": MessageLookupByLibrary.simpleMessage(
"Destination IPASN",
),
"details": m2,
"detectionTip": MessageLookupByLibrary.simpleMessage( "detectionTip": MessageLookupByLibrary.simpleMessage(
"Relying on third-party api is for reference only", "Relying on third-party api is for reference only",
), ),
@@ -242,7 +254,7 @@ class MessageLookup extends MessageLookupByLibrary {
"domain": MessageLookupByLibrary.simpleMessage("Domain"), "domain": MessageLookupByLibrary.simpleMessage("Domain"),
"download": MessageLookupByLibrary.simpleMessage("Download"), "download": MessageLookupByLibrary.simpleMessage("Download"),
"edit": MessageLookupByLibrary.simpleMessage("Edit"), "edit": MessageLookupByLibrary.simpleMessage("Edit"),
"emptyTip": m2, "emptyTip": m3,
"en": MessageLookupByLibrary.simpleMessage("English"), "en": MessageLookupByLibrary.simpleMessage("English"),
"enableOverride": MessageLookupByLibrary.simpleMessage("Enable override"), "enableOverride": MessageLookupByLibrary.simpleMessage("Enable override"),
"entries": MessageLookupByLibrary.simpleMessage(" entries"), "entries": MessageLookupByLibrary.simpleMessage(" entries"),
@@ -250,7 +262,7 @@ class MessageLookup extends MessageLookupByLibrary {
"excludeDesc": MessageLookupByLibrary.simpleMessage( "excludeDesc": MessageLookupByLibrary.simpleMessage(
"When the app is in the background, the app is hidden from the recent task", "When the app is in the background, the app is hidden from the recent task",
), ),
"existsTip": m3, "existsTip": m4,
"exit": MessageLookupByLibrary.simpleMessage("Exit"), "exit": MessageLookupByLibrary.simpleMessage("Exit"),
"expand": MessageLookupByLibrary.simpleMessage("Standard"), "expand": MessageLookupByLibrary.simpleMessage("Standard"),
"expirationTime": MessageLookupByLibrary.simpleMessage("Expiration time"), "expirationTime": MessageLookupByLibrary.simpleMessage("Expiration time"),
@@ -312,6 +324,7 @@ class MessageLookup extends MessageLookupByLibrary {
"hasCacheChange": MessageLookupByLibrary.simpleMessage( "hasCacheChange": MessageLookupByLibrary.simpleMessage(
"Do you want to cache the changes?", "Do you want to cache the changes?",
), ),
"host": MessageLookupByLibrary.simpleMessage("Host"),
"hostsDesc": MessageLookupByLibrary.simpleMessage("Add Hosts"), "hostsDesc": MessageLookupByLibrary.simpleMessage("Add Hosts"),
"hotkeyConflict": MessageLookupByLibrary.simpleMessage("Hotkey conflict"), "hotkeyConflict": MessageLookupByLibrary.simpleMessage("Hotkey conflict"),
"hotkeyManagement": MessageLookupByLibrary.simpleMessage( "hotkeyManagement": MessageLookupByLibrary.simpleMessage(
@@ -366,6 +379,7 @@ class MessageLookup extends MessageLookupByLibrary {
"localRecoveryDesc": MessageLookupByLibrary.simpleMessage( "localRecoveryDesc": MessageLookupByLibrary.simpleMessage(
"Recovery data from file", "Recovery data from file",
), ),
"log": MessageLookupByLibrary.simpleMessage("Log"),
"logLevel": MessageLookupByLibrary.simpleMessage("LogLevel"), "logLevel": MessageLookupByLibrary.simpleMessage("LogLevel"),
"logcat": MessageLookupByLibrary.simpleMessage("Logcat"), "logcat": MessageLookupByLibrary.simpleMessage("Logcat"),
"logcatDesc": MessageLookupByLibrary.simpleMessage( "logcatDesc": MessageLookupByLibrary.simpleMessage(
@@ -415,6 +429,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Network detection", "Network detection",
), ),
"networkSpeed": MessageLookupByLibrary.simpleMessage("Network speed"), "networkSpeed": MessageLookupByLibrary.simpleMessage("Network speed"),
"networkType": MessageLookupByLibrary.simpleMessage("Network type"),
"neutralScheme": MessageLookupByLibrary.simpleMessage("Neutral"), "neutralScheme": MessageLookupByLibrary.simpleMessage("Neutral"),
"noData": MessageLookupByLibrary.simpleMessage("No data"), "noData": MessageLookupByLibrary.simpleMessage("No data"),
"noHotKey": MessageLookupByLibrary.simpleMessage("No HotKey"), "noHotKey": MessageLookupByLibrary.simpleMessage("No HotKey"),
@@ -435,8 +450,8 @@ class MessageLookup extends MessageLookupByLibrary {
"nullProfileDesc": MessageLookupByLibrary.simpleMessage( "nullProfileDesc": MessageLookupByLibrary.simpleMessage(
"No profile, Please add a profile", "No profile, Please add a profile",
), ),
"nullTip": m4, "nullTip": m5,
"numberTip": m5, "numberTip": m6,
"oneColumn": MessageLookupByLibrary.simpleMessage("One column"), "oneColumn": MessageLookupByLibrary.simpleMessage("One column"),
"onlyIcon": MessageLookupByLibrary.simpleMessage("Icon"), "onlyIcon": MessageLookupByLibrary.simpleMessage("Icon"),
"onlyOtherApps": MessageLookupByLibrary.simpleMessage( "onlyOtherApps": MessageLookupByLibrary.simpleMessage(
@@ -490,7 +505,7 @@ class MessageLookup extends MessageLookupByLibrary {
"portConflictTip": MessageLookupByLibrary.simpleMessage( "portConflictTip": MessageLookupByLibrary.simpleMessage(
"Please enter a different port", "Please enter a different port",
), ),
"portTip": m6, "portTip": m7,
"preferH3Desc": MessageLookupByLibrary.simpleMessage( "preferH3Desc": MessageLookupByLibrary.simpleMessage(
"Prioritize the use of DOH\'s http/3", "Prioritize the use of DOH\'s http/3",
), ),
@@ -524,10 +539,12 @@ class MessageLookup extends MessageLookupByLibrary {
), ),
"profiles": MessageLookupByLibrary.simpleMessage("Profiles"), "profiles": MessageLookupByLibrary.simpleMessage("Profiles"),
"profilesSort": MessageLookupByLibrary.simpleMessage("Profiles sort"), "profilesSort": MessageLookupByLibrary.simpleMessage("Profiles sort"),
"progress": MessageLookupByLibrary.simpleMessage("Progress"),
"project": MessageLookupByLibrary.simpleMessage("Project"), "project": MessageLookupByLibrary.simpleMessage("Project"),
"providers": MessageLookupByLibrary.simpleMessage("Providers"), "providers": MessageLookupByLibrary.simpleMessage("Providers"),
"proxies": MessageLookupByLibrary.simpleMessage("Proxies"), "proxies": MessageLookupByLibrary.simpleMessage("Proxies"),
"proxiesSetting": MessageLookupByLibrary.simpleMessage("Proxies setting"), "proxiesSetting": MessageLookupByLibrary.simpleMessage("Proxies setting"),
"proxyChains": MessageLookupByLibrary.simpleMessage("Proxy chains"),
"proxyGroup": MessageLookupByLibrary.simpleMessage("Proxy group"), "proxyGroup": MessageLookupByLibrary.simpleMessage("Proxy group"),
"proxyNameserver": MessageLookupByLibrary.simpleMessage("Proxy nameserver"), "proxyNameserver": MessageLookupByLibrary.simpleMessage("Proxy nameserver"),
"proxyNameserverDesc": MessageLookupByLibrary.simpleMessage( "proxyNameserverDesc": MessageLookupByLibrary.simpleMessage(
@@ -566,11 +583,15 @@ class MessageLookup extends MessageLookupByLibrary {
"remoteBackupDesc": MessageLookupByLibrary.simpleMessage( "remoteBackupDesc": MessageLookupByLibrary.simpleMessage(
"Backup local data to WebDAV", "Backup local data to WebDAV",
), ),
"remoteDestination": MessageLookupByLibrary.simpleMessage(
"Remote destination",
),
"remoteRecoveryDesc": MessageLookupByLibrary.simpleMessage( "remoteRecoveryDesc": MessageLookupByLibrary.simpleMessage(
"Recovery data from WebDAV", "Recovery data from WebDAV",
), ),
"remove": MessageLookupByLibrary.simpleMessage("Remove"), "remove": MessageLookupByLibrary.simpleMessage("Remove"),
"rename": MessageLookupByLibrary.simpleMessage("Rename"), "rename": MessageLookupByLibrary.simpleMessage("Rename"),
"request": MessageLookupByLibrary.simpleMessage("Request"),
"requests": MessageLookupByLibrary.simpleMessage("Requests"), "requests": MessageLookupByLibrary.simpleMessage("Requests"),
"requestsDesc": MessageLookupByLibrary.simpleMessage( "requestsDesc": MessageLookupByLibrary.simpleMessage(
"View recently request records", "View recently request records",
@@ -611,7 +632,7 @@ class MessageLookup extends MessageLookupByLibrary {
"seconds": MessageLookupByLibrary.simpleMessage("Seconds"), "seconds": MessageLookupByLibrary.simpleMessage("Seconds"),
"selectAll": MessageLookupByLibrary.simpleMessage("Select all"), "selectAll": MessageLookupByLibrary.simpleMessage("Select all"),
"selected": MessageLookupByLibrary.simpleMessage("Selected"), "selected": MessageLookupByLibrary.simpleMessage("Selected"),
"selectedCountTitle": m7, "selectedCountTitle": m8,
"settings": MessageLookupByLibrary.simpleMessage("Settings"), "settings": MessageLookupByLibrary.simpleMessage("Settings"),
"show": MessageLookupByLibrary.simpleMessage("Show"), "show": MessageLookupByLibrary.simpleMessage("Show"),
"shrink": MessageLookupByLibrary.simpleMessage("Shrink"), "shrink": MessageLookupByLibrary.simpleMessage("Shrink"),
@@ -624,6 +645,8 @@ class MessageLookup extends MessageLookupByLibrary {
"sort": MessageLookupByLibrary.simpleMessage("Sort"), "sort": MessageLookupByLibrary.simpleMessage("Sort"),
"source": MessageLookupByLibrary.simpleMessage("Source"), "source": MessageLookupByLibrary.simpleMessage("Source"),
"sourceIp": MessageLookupByLibrary.simpleMessage("Source IP"), "sourceIp": MessageLookupByLibrary.simpleMessage("Source IP"),
"specialProxy": MessageLookupByLibrary.simpleMessage("Special proxy"),
"specialRules": MessageLookupByLibrary.simpleMessage("special rules"),
"stackMode": MessageLookupByLibrary.simpleMessage("Stack mode"), "stackMode": MessageLookupByLibrary.simpleMessage("Stack mode"),
"standard": MessageLookupByLibrary.simpleMessage("Standard"), "standard": MessageLookupByLibrary.simpleMessage("Standard"),
"start": MessageLookupByLibrary.simpleMessage("Start"), "start": MessageLookupByLibrary.simpleMessage("Start"),
@@ -692,7 +715,7 @@ class MessageLookup extends MessageLookupByLibrary {
"urlDesc": MessageLookupByLibrary.simpleMessage( "urlDesc": MessageLookupByLibrary.simpleMessage(
"Obtain profile through URL", "Obtain profile through URL",
), ),
"urlTip": m8, "urlTip": m9,
"useHosts": MessageLookupByLibrary.simpleMessage("Use hosts"), "useHosts": MessageLookupByLibrary.simpleMessage("Use hosts"),
"useSystemHosts": MessageLookupByLibrary.simpleMessage("Use system hosts"), "useSystemHosts": MessageLookupByLibrary.simpleMessage("Use system hosts"),
"value": MessageLookupByLibrary.simpleMessage("Value"), "value": MessageLookupByLibrary.simpleMessage("Value"),

View File

@@ -24,19 +24,21 @@ class MessageLookup extends MessageLookupByLibrary {
static String m1(label) => "現在の${label}を削除してもよろしいですか?"; static String m1(label) => "現在の${label}を削除してもよろしいですか?";
static String m2(label) => "${label}は空欄にできません"; static String m2(label) => "${label}詳細";
static String m3(label) => "現在の${label}既に存在しています"; static String m3(label) => "${label}空欄にできません";
static String m4(label) => "現在${label}ありません"; static String m4(label) => "現在${label}既に存在しています";
static String m5(label) => "${label}数字でなければなりません"; static String m5(label) => "現在${label}りません";
static String m6(label) => "${label} は 1024 から 49151 の間でなければなりません"; static String m6(label) => "${label}は数字でなければなりません";
static String m7(count) => "${count} 項目が選択されています"; static String m7(label) => "${label} は 1024 から 49151 の間でなければなりません";
static String m8(label) => "${label}はURLである必要があります"; static String m8(count) => "${count} 項目が選択されています";
static String m9(label) => "${label}はURLである必要があります";
final messages = _notInlinedMessages(_notInlinedMessages); final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{ static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@@ -131,6 +133,7 @@ class MessageLookup extends MessageLookupByLibrary {
"有効化すると一部機能を失いますが、Clashの完全サポートを獲得", "有効化すると一部機能を失いますが、Clashの完全サポートを獲得",
), ),
"confirm": MessageLookupByLibrary.simpleMessage("確認"), "confirm": MessageLookupByLibrary.simpleMessage("確認"),
"connection": MessageLookupByLibrary.simpleMessage("接続"),
"connections": MessageLookupByLibrary.simpleMessage("接続"), "connections": MessageLookupByLibrary.simpleMessage("接続"),
"connectionsDesc": MessageLookupByLibrary.simpleMessage("現在の接続データを表示"), "connectionsDesc": MessageLookupByLibrary.simpleMessage("現在の接続データを表示"),
"connectivity": MessageLookupByLibrary.simpleMessage("接続性:"), "connectivity": MessageLookupByLibrary.simpleMessage("接続性:"),
@@ -146,6 +149,7 @@ class MessageLookup extends MessageLookupByLibrary {
"country": MessageLookupByLibrary.simpleMessage(""), "country": MessageLookupByLibrary.simpleMessage(""),
"crashTest": MessageLookupByLibrary.simpleMessage("クラッシュテスト"), "crashTest": MessageLookupByLibrary.simpleMessage("クラッシュテスト"),
"create": MessageLookupByLibrary.simpleMessage("作成"), "create": MessageLookupByLibrary.simpleMessage("作成"),
"creationTime": MessageLookupByLibrary.simpleMessage("作成時間"),
"cut": MessageLookupByLibrary.simpleMessage("切り取り"), "cut": MessageLookupByLibrary.simpleMessage("切り取り"),
"dark": MessageLookupByLibrary.simpleMessage("ダーク"), "dark": MessageLookupByLibrary.simpleMessage("ダーク"),
"dashboard": MessageLookupByLibrary.simpleMessage("ダッシュボード"), "dashboard": MessageLookupByLibrary.simpleMessage("ダッシュボード"),
@@ -164,6 +168,10 @@ class MessageLookup extends MessageLookupByLibrary {
"desc": MessageLookupByLibrary.simpleMessage( "desc": MessageLookupByLibrary.simpleMessage(
"ClashMetaベースのマルチプラットフォームプロキシクライアント。シンプルで使いやすく、オープンソースで広告なし。", "ClashMetaベースのマルチプラットフォームプロキシクライアント。シンプルで使いやすく、オープンソースで広告なし。",
), ),
"destination": MessageLookupByLibrary.simpleMessage("宛先"),
"destinationGeoIP": MessageLookupByLibrary.simpleMessage("宛先地理情報"),
"destinationIPASN": MessageLookupByLibrary.simpleMessage("宛先IP ASN"),
"details": m2,
"detectionTip": MessageLookupByLibrary.simpleMessage("サードパーティAPIに依存参考値"), "detectionTip": MessageLookupByLibrary.simpleMessage("サードパーティAPIに依存参考値"),
"developerMode": MessageLookupByLibrary.simpleMessage("デベロッパーモード"), "developerMode": MessageLookupByLibrary.simpleMessage("デベロッパーモード"),
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage( "developerModeEnableTip": MessageLookupByLibrary.simpleMessage(
@@ -182,7 +190,7 @@ class MessageLookup extends MessageLookupByLibrary {
"domain": MessageLookupByLibrary.simpleMessage("ドメイン"), "domain": MessageLookupByLibrary.simpleMessage("ドメイン"),
"download": MessageLookupByLibrary.simpleMessage("ダウンロード"), "download": MessageLookupByLibrary.simpleMessage("ダウンロード"),
"edit": MessageLookupByLibrary.simpleMessage("編集"), "edit": MessageLookupByLibrary.simpleMessage("編集"),
"emptyTip": m2, "emptyTip": m3,
"en": MessageLookupByLibrary.simpleMessage("英語"), "en": MessageLookupByLibrary.simpleMessage("英語"),
"enableOverride": MessageLookupByLibrary.simpleMessage("上書きを有効化"), "enableOverride": MessageLookupByLibrary.simpleMessage("上書きを有効化"),
"entries": MessageLookupByLibrary.simpleMessage(" エントリ"), "entries": MessageLookupByLibrary.simpleMessage(" エントリ"),
@@ -190,7 +198,7 @@ class MessageLookup extends MessageLookupByLibrary {
"excludeDesc": MessageLookupByLibrary.simpleMessage( "excludeDesc": MessageLookupByLibrary.simpleMessage(
"アプリがバックグラウンド時に最近のタスクから非表示", "アプリがバックグラウンド時に最近のタスクから非表示",
), ),
"existsTip": m3, "existsTip": m4,
"exit": MessageLookupByLibrary.simpleMessage("終了"), "exit": MessageLookupByLibrary.simpleMessage("終了"),
"expand": MessageLookupByLibrary.simpleMessage("標準"), "expand": MessageLookupByLibrary.simpleMessage("標準"),
"expirationTime": MessageLookupByLibrary.simpleMessage("有効期限"), "expirationTime": MessageLookupByLibrary.simpleMessage("有効期限"),
@@ -236,6 +244,7 @@ class MessageLookup extends MessageLookupByLibrary {
"go": MessageLookupByLibrary.simpleMessage("移動"), "go": MessageLookupByLibrary.simpleMessage("移動"),
"goDownload": MessageLookupByLibrary.simpleMessage("ダウンロードへ"), "goDownload": MessageLookupByLibrary.simpleMessage("ダウンロードへ"),
"hasCacheChange": MessageLookupByLibrary.simpleMessage("変更をキャッシュしますか?"), "hasCacheChange": MessageLookupByLibrary.simpleMessage("変更をキャッシュしますか?"),
"host": MessageLookupByLibrary.simpleMessage("ホスト"),
"hostsDesc": MessageLookupByLibrary.simpleMessage("ホストを追加"), "hostsDesc": MessageLookupByLibrary.simpleMessage("ホストを追加"),
"hotkeyConflict": MessageLookupByLibrary.simpleMessage("ホットキー競合"), "hotkeyConflict": MessageLookupByLibrary.simpleMessage("ホットキー競合"),
"hotkeyManagement": MessageLookupByLibrary.simpleMessage("ホットキー管理"), "hotkeyManagement": MessageLookupByLibrary.simpleMessage("ホットキー管理"),
@@ -274,6 +283,7 @@ class MessageLookup extends MessageLookupByLibrary {
"local": MessageLookupByLibrary.simpleMessage("ローカル"), "local": MessageLookupByLibrary.simpleMessage("ローカル"),
"localBackupDesc": MessageLookupByLibrary.simpleMessage("ローカルにデータをバックアップ"), "localBackupDesc": MessageLookupByLibrary.simpleMessage("ローカルにデータをバックアップ"),
"localRecoveryDesc": MessageLookupByLibrary.simpleMessage("ファイルからデータを復元"), "localRecoveryDesc": MessageLookupByLibrary.simpleMessage("ファイルからデータを復元"),
"log": MessageLookupByLibrary.simpleMessage("ログ"),
"logLevel": MessageLookupByLibrary.simpleMessage("ログレベル"), "logLevel": MessageLookupByLibrary.simpleMessage("ログレベル"),
"logcat": MessageLookupByLibrary.simpleMessage("ログキャット"), "logcat": MessageLookupByLibrary.simpleMessage("ログキャット"),
"logcatDesc": MessageLookupByLibrary.simpleMessage("無効化するとログエントリを非表示"), "logcatDesc": MessageLookupByLibrary.simpleMessage("無効化するとログエントリを非表示"),
@@ -309,6 +319,7 @@ class MessageLookup extends MessageLookupByLibrary {
"networkDesc": MessageLookupByLibrary.simpleMessage("ネットワーク関連設定の変更"), "networkDesc": MessageLookupByLibrary.simpleMessage("ネットワーク関連設定の変更"),
"networkDetection": MessageLookupByLibrary.simpleMessage("ネットワーク検出"), "networkDetection": MessageLookupByLibrary.simpleMessage("ネットワーク検出"),
"networkSpeed": MessageLookupByLibrary.simpleMessage("ネットワーク速度"), "networkSpeed": MessageLookupByLibrary.simpleMessage("ネットワーク速度"),
"networkType": MessageLookupByLibrary.simpleMessage("ネットワーク種別"),
"neutralScheme": MessageLookupByLibrary.simpleMessage("ニュートラル"), "neutralScheme": MessageLookupByLibrary.simpleMessage("ニュートラル"),
"noData": MessageLookupByLibrary.simpleMessage("データなし"), "noData": MessageLookupByLibrary.simpleMessage("データなし"),
"noHotKey": MessageLookupByLibrary.simpleMessage("ホットキーなし"), "noHotKey": MessageLookupByLibrary.simpleMessage("ホットキーなし"),
@@ -329,8 +340,8 @@ class MessageLookup extends MessageLookupByLibrary {
"nullProfileDesc": MessageLookupByLibrary.simpleMessage( "nullProfileDesc": MessageLookupByLibrary.simpleMessage(
"プロファイルがありません。追加してください", "プロファイルがありません。追加してください",
), ),
"nullTip": m4, "nullTip": m5,
"numberTip": m5, "numberTip": m6,
"oneColumn": MessageLookupByLibrary.simpleMessage("1列"), "oneColumn": MessageLookupByLibrary.simpleMessage("1列"),
"onlyIcon": MessageLookupByLibrary.simpleMessage("アイコンのみ"), "onlyIcon": MessageLookupByLibrary.simpleMessage("アイコンのみ"),
"onlyOtherApps": MessageLookupByLibrary.simpleMessage("サードパーティアプリのみ"), "onlyOtherApps": MessageLookupByLibrary.simpleMessage("サードパーティアプリのみ"),
@@ -372,7 +383,7 @@ class MessageLookup extends MessageLookupByLibrary {
), ),
"port": MessageLookupByLibrary.simpleMessage("ポート"), "port": MessageLookupByLibrary.simpleMessage("ポート"),
"portConflictTip": MessageLookupByLibrary.simpleMessage("別のポートを入力してください"), "portConflictTip": MessageLookupByLibrary.simpleMessage("別のポートを入力してください"),
"portTip": m6, "portTip": m7,
"preferH3Desc": MessageLookupByLibrary.simpleMessage("DOHのHTTP/3を優先使用"), "preferH3Desc": MessageLookupByLibrary.simpleMessage("DOHのHTTP/3を優先使用"),
"pressKeyboard": MessageLookupByLibrary.simpleMessage("キーボードを押してください"), "pressKeyboard": MessageLookupByLibrary.simpleMessage("キーボードを押してください"),
"preview": MessageLookupByLibrary.simpleMessage("プレビュー"), "preview": MessageLookupByLibrary.simpleMessage("プレビュー"),
@@ -398,10 +409,12 @@ class MessageLookup extends MessageLookupByLibrary {
), ),
"profiles": MessageLookupByLibrary.simpleMessage("プロファイル一覧"), "profiles": MessageLookupByLibrary.simpleMessage("プロファイル一覧"),
"profilesSort": MessageLookupByLibrary.simpleMessage("プロファイルの並び替え"), "profilesSort": MessageLookupByLibrary.simpleMessage("プロファイルの並び替え"),
"progress": MessageLookupByLibrary.simpleMessage("進捗"),
"project": MessageLookupByLibrary.simpleMessage("プロジェクト"), "project": MessageLookupByLibrary.simpleMessage("プロジェクト"),
"providers": MessageLookupByLibrary.simpleMessage("プロバイダー"), "providers": MessageLookupByLibrary.simpleMessage("プロバイダー"),
"proxies": MessageLookupByLibrary.simpleMessage("プロキシ"), "proxies": MessageLookupByLibrary.simpleMessage("プロキシ"),
"proxiesSetting": MessageLookupByLibrary.simpleMessage("プロキシ設定"), "proxiesSetting": MessageLookupByLibrary.simpleMessage("プロキシ設定"),
"proxyChains": MessageLookupByLibrary.simpleMessage("プロキシチェーン"),
"proxyGroup": MessageLookupByLibrary.simpleMessage("プロキシグループ"), "proxyGroup": MessageLookupByLibrary.simpleMessage("プロキシグループ"),
"proxyNameserver": MessageLookupByLibrary.simpleMessage("プロキシネームサーバー"), "proxyNameserver": MessageLookupByLibrary.simpleMessage("プロキシネームサーバー"),
"proxyNameserverDesc": MessageLookupByLibrary.simpleMessage( "proxyNameserverDesc": MessageLookupByLibrary.simpleMessage(
@@ -430,11 +443,13 @@ class MessageLookup extends MessageLookupByLibrary {
"remoteBackupDesc": MessageLookupByLibrary.simpleMessage( "remoteBackupDesc": MessageLookupByLibrary.simpleMessage(
"WebDAVにデータをバックアップ", "WebDAVにデータをバックアップ",
), ),
"remoteDestination": MessageLookupByLibrary.simpleMessage("リモート宛先"),
"remoteRecoveryDesc": MessageLookupByLibrary.simpleMessage( "remoteRecoveryDesc": MessageLookupByLibrary.simpleMessage(
"WebDAVからデータを復元", "WebDAVからデータを復元",
), ),
"remove": MessageLookupByLibrary.simpleMessage("削除"), "remove": MessageLookupByLibrary.simpleMessage("削除"),
"rename": MessageLookupByLibrary.simpleMessage("リネーム"), "rename": MessageLookupByLibrary.simpleMessage("リネーム"),
"request": MessageLookupByLibrary.simpleMessage("リクエスト"),
"requests": MessageLookupByLibrary.simpleMessage("リクエスト"), "requests": MessageLookupByLibrary.simpleMessage("リクエスト"),
"requestsDesc": MessageLookupByLibrary.simpleMessage("最近のリクエスト記録を表示"), "requestsDesc": MessageLookupByLibrary.simpleMessage("最近のリクエスト記録を表示"),
"reset": MessageLookupByLibrary.simpleMessage("リセット"), "reset": MessageLookupByLibrary.simpleMessage("リセット"),
@@ -465,7 +480,7 @@ class MessageLookup extends MessageLookupByLibrary {
"seconds": MessageLookupByLibrary.simpleMessage(""), "seconds": MessageLookupByLibrary.simpleMessage(""),
"selectAll": MessageLookupByLibrary.simpleMessage("すべて選択"), "selectAll": MessageLookupByLibrary.simpleMessage("すべて選択"),
"selected": MessageLookupByLibrary.simpleMessage("選択済み"), "selected": MessageLookupByLibrary.simpleMessage("選択済み"),
"selectedCountTitle": m7, "selectedCountTitle": m8,
"settings": MessageLookupByLibrary.simpleMessage("設定"), "settings": MessageLookupByLibrary.simpleMessage("設定"),
"show": MessageLookupByLibrary.simpleMessage("表示"), "show": MessageLookupByLibrary.simpleMessage("表示"),
"shrink": MessageLookupByLibrary.simpleMessage("縮小"), "shrink": MessageLookupByLibrary.simpleMessage("縮小"),
@@ -476,6 +491,8 @@ class MessageLookup extends MessageLookupByLibrary {
"sort": MessageLookupByLibrary.simpleMessage("並び替え"), "sort": MessageLookupByLibrary.simpleMessage("並び替え"),
"source": MessageLookupByLibrary.simpleMessage("ソース"), "source": MessageLookupByLibrary.simpleMessage("ソース"),
"sourceIp": MessageLookupByLibrary.simpleMessage("送信元IP"), "sourceIp": MessageLookupByLibrary.simpleMessage("送信元IP"),
"specialProxy": MessageLookupByLibrary.simpleMessage("特殊プロキシ"),
"specialRules": MessageLookupByLibrary.simpleMessage("特殊ルール"),
"stackMode": MessageLookupByLibrary.simpleMessage("スタックモード"), "stackMode": MessageLookupByLibrary.simpleMessage("スタックモード"),
"standard": MessageLookupByLibrary.simpleMessage("標準"), "standard": MessageLookupByLibrary.simpleMessage("標準"),
"start": MessageLookupByLibrary.simpleMessage("開始"), "start": MessageLookupByLibrary.simpleMessage("開始"),
@@ -532,7 +549,7 @@ class MessageLookup extends MessageLookupByLibrary {
"upload": MessageLookupByLibrary.simpleMessage("アップロード"), "upload": MessageLookupByLibrary.simpleMessage("アップロード"),
"url": MessageLookupByLibrary.simpleMessage("URL"), "url": MessageLookupByLibrary.simpleMessage("URL"),
"urlDesc": MessageLookupByLibrary.simpleMessage("URL経由でプロファイルを取得"), "urlDesc": MessageLookupByLibrary.simpleMessage("URL経由でプロファイルを取得"),
"urlTip": m8, "urlTip": m9,
"useHosts": MessageLookupByLibrary.simpleMessage("ホストを使用"), "useHosts": MessageLookupByLibrary.simpleMessage("ホストを使用"),
"useSystemHosts": MessageLookupByLibrary.simpleMessage("システムホストを使用"), "useSystemHosts": MessageLookupByLibrary.simpleMessage("システムホストを使用"),
"value": MessageLookupByLibrary.simpleMessage(""), "value": MessageLookupByLibrary.simpleMessage(""),

View File

@@ -25,19 +25,21 @@ class MessageLookup extends MessageLookupByLibrary {
static String m1(label) => "Вы уверены, что хотите удалить текущий ${label}?"; static String m1(label) => "Вы уверены, что хотите удалить текущий ${label}?";
static String m2(label) => "${label} не может быть пустым"; static String m2(label) => "Детали {}";
static String m3(label) => "Текущий ${label} уже существует"; static String m3(label) => "${label} не может быть пустым";
static String m4(label) => "Сейчас ${label} нет"; static String m4(label) => "Текущий ${label} уже существует";
static String m5(label) => "${label} должно быть числом"; static String m5(label) => "Сейчас ${label} нет";
static String m6(label) => "${label} должен быть числом от 1024 до 49151"; static String m6(label) => "${label} должно быть числом";
static String m7(count) => "Выбрано ${count} элементов"; static String m7(label) => "${label} должен быть числом от 1024 до 49151";
static String m8(label) => "${label} должен быть URL"; static String m8(count) => "Выбрано ${count} элементов";
static String m9(label) => "${label} должен быть URL";
final messages = _notInlinedMessages(_notInlinedMessages); final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{ static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@@ -180,6 +182,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Включение приведет к потере части функциональности приложения, но обеспечит полную поддержку Clash.", "Включение приведет к потере части функциональности приложения, но обеспечит полную поддержку Clash.",
), ),
"confirm": MessageLookupByLibrary.simpleMessage("Подтвердить"), "confirm": MessageLookupByLibrary.simpleMessage("Подтвердить"),
"connection": MessageLookupByLibrary.simpleMessage("Соединение"),
"connections": MessageLookupByLibrary.simpleMessage("Соединения"), "connections": MessageLookupByLibrary.simpleMessage("Соединения"),
"connectionsDesc": MessageLookupByLibrary.simpleMessage( "connectionsDesc": MessageLookupByLibrary.simpleMessage(
"Просмотр текущих данных о соединениях", "Просмотр текущих данных о соединениях",
@@ -199,6 +202,7 @@ class MessageLookup extends MessageLookupByLibrary {
"country": MessageLookupByLibrary.simpleMessage("Страна"), "country": MessageLookupByLibrary.simpleMessage("Страна"),
"crashTest": MessageLookupByLibrary.simpleMessage("Тест на сбои"), "crashTest": MessageLookupByLibrary.simpleMessage("Тест на сбои"),
"create": MessageLookupByLibrary.simpleMessage("Создать"), "create": MessageLookupByLibrary.simpleMessage("Создать"),
"creationTime": MessageLookupByLibrary.simpleMessage("Время создания"),
"cut": MessageLookupByLibrary.simpleMessage("Вырезать"), "cut": MessageLookupByLibrary.simpleMessage("Вырезать"),
"dark": MessageLookupByLibrary.simpleMessage("Темный"), "dark": MessageLookupByLibrary.simpleMessage("Темный"),
"dashboard": MessageLookupByLibrary.simpleMessage("Панель управления"), "dashboard": MessageLookupByLibrary.simpleMessage("Панель управления"),
@@ -221,6 +225,12 @@ class MessageLookup extends MessageLookupByLibrary {
"desc": MessageLookupByLibrary.simpleMessage( "desc": MessageLookupByLibrary.simpleMessage(
"Многоплатформенный прокси-клиент на основе ClashMeta, простой и удобный в использовании, с открытым исходным кодом и без рекламы.", "Многоплатформенный прокси-клиент на основе ClashMeta, простой и удобный в использовании, с открытым исходным кодом и без рекламы.",
), ),
"destination": MessageLookupByLibrary.simpleMessage("Назначение"),
"destinationGeoIP": MessageLookupByLibrary.simpleMessage(
"Геолокация назначения",
),
"destinationIPASN": MessageLookupByLibrary.simpleMessage("ASN назначения"),
"details": m2,
"detectionTip": MessageLookupByLibrary.simpleMessage( "detectionTip": MessageLookupByLibrary.simpleMessage(
"Опирается на сторонний API, только для справки", "Опирается на сторонний API, только для справки",
), ),
@@ -251,7 +261,7 @@ class MessageLookup extends MessageLookupByLibrary {
"domain": MessageLookupByLibrary.simpleMessage("Домен"), "domain": MessageLookupByLibrary.simpleMessage("Домен"),
"download": MessageLookupByLibrary.simpleMessage("Скачивание"), "download": MessageLookupByLibrary.simpleMessage("Скачивание"),
"edit": MessageLookupByLibrary.simpleMessage("Редактировать"), "edit": MessageLookupByLibrary.simpleMessage("Редактировать"),
"emptyTip": m2, "emptyTip": m3,
"en": MessageLookupByLibrary.simpleMessage("Английский"), "en": MessageLookupByLibrary.simpleMessage("Английский"),
"enableOverride": MessageLookupByLibrary.simpleMessage( "enableOverride": MessageLookupByLibrary.simpleMessage(
"Включить переопределение", "Включить переопределение",
@@ -263,7 +273,7 @@ class MessageLookup extends MessageLookupByLibrary {
"excludeDesc": MessageLookupByLibrary.simpleMessage( "excludeDesc": MessageLookupByLibrary.simpleMessage(
"Когда приложение находится в фоновом режиме, оно скрыто из последних задач", "Когда приложение находится в фоновом режиме, оно скрыто из последних задач",
), ),
"existsTip": m3, "existsTip": m4,
"exit": MessageLookupByLibrary.simpleMessage("Выход"), "exit": MessageLookupByLibrary.simpleMessage("Выход"),
"expand": MessageLookupByLibrary.simpleMessage("Стандартный"), "expand": MessageLookupByLibrary.simpleMessage("Стандартный"),
"expirationTime": MessageLookupByLibrary.simpleMessage("Время истечения"), "expirationTime": MessageLookupByLibrary.simpleMessage("Время истечения"),
@@ -329,6 +339,7 @@ class MessageLookup extends MessageLookupByLibrary {
"hasCacheChange": MessageLookupByLibrary.simpleMessage( "hasCacheChange": MessageLookupByLibrary.simpleMessage(
"Хотите сохранить изменения в кэше?", "Хотите сохранить изменения в кэше?",
), ),
"host": MessageLookupByLibrary.simpleMessage("Хост"),
"hostsDesc": MessageLookupByLibrary.simpleMessage("Добавить Hosts"), "hostsDesc": MessageLookupByLibrary.simpleMessage("Добавить Hosts"),
"hotkeyConflict": MessageLookupByLibrary.simpleMessage( "hotkeyConflict": MessageLookupByLibrary.simpleMessage(
"Конфликт горячих клавиш", "Конфликт горячих клавиш",
@@ -387,6 +398,7 @@ class MessageLookup extends MessageLookupByLibrary {
"localRecoveryDesc": MessageLookupByLibrary.simpleMessage( "localRecoveryDesc": MessageLookupByLibrary.simpleMessage(
"Восстановление данных из файла", "Восстановление данных из файла",
), ),
"log": MessageLookupByLibrary.simpleMessage("Журнал"),
"logLevel": MessageLookupByLibrary.simpleMessage("Уровень логов"), "logLevel": MessageLookupByLibrary.simpleMessage("Уровень логов"),
"logcat": MessageLookupByLibrary.simpleMessage("Logcat"), "logcat": MessageLookupByLibrary.simpleMessage("Logcat"),
"logcatDesc": MessageLookupByLibrary.simpleMessage( "logcatDesc": MessageLookupByLibrary.simpleMessage(
@@ -440,6 +452,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Обнаружение сети", "Обнаружение сети",
), ),
"networkSpeed": MessageLookupByLibrary.simpleMessage("Скорость сети"), "networkSpeed": MessageLookupByLibrary.simpleMessage("Скорость сети"),
"networkType": MessageLookupByLibrary.simpleMessage("Тип сети"),
"neutralScheme": MessageLookupByLibrary.simpleMessage("Нейтральные"), "neutralScheme": MessageLookupByLibrary.simpleMessage("Нейтральные"),
"noData": MessageLookupByLibrary.simpleMessage("Нет данных"), "noData": MessageLookupByLibrary.simpleMessage("Нет данных"),
"noHotKey": MessageLookupByLibrary.simpleMessage("Нет горячей клавиши"), "noHotKey": MessageLookupByLibrary.simpleMessage("Нет горячей клавиши"),
@@ -462,8 +475,8 @@ class MessageLookup extends MessageLookupByLibrary {
"nullProfileDesc": MessageLookupByLibrary.simpleMessage( "nullProfileDesc": MessageLookupByLibrary.simpleMessage(
"Нет профиля, пожалуйста, добавьте профиль", "Нет профиля, пожалуйста, добавьте профиль",
), ),
"nullTip": m4, "nullTip": m5,
"numberTip": m5, "numberTip": m6,
"oneColumn": MessageLookupByLibrary.simpleMessage("Один столбец"), "oneColumn": MessageLookupByLibrary.simpleMessage("Один столбец"),
"onlyIcon": MessageLookupByLibrary.simpleMessage("Только иконка"), "onlyIcon": MessageLookupByLibrary.simpleMessage("Только иконка"),
"onlyOtherApps": MessageLookupByLibrary.simpleMessage( "onlyOtherApps": MessageLookupByLibrary.simpleMessage(
@@ -519,7 +532,7 @@ class MessageLookup extends MessageLookupByLibrary {
"portConflictTip": MessageLookupByLibrary.simpleMessage( "portConflictTip": MessageLookupByLibrary.simpleMessage(
"Введите другой порт", "Введите другой порт",
), ),
"portTip": m6, "portTip": m7,
"preferH3Desc": MessageLookupByLibrary.simpleMessage( "preferH3Desc": MessageLookupByLibrary.simpleMessage(
"Приоритетное использование HTTP/3 для DOH", "Приоритетное использование HTTP/3 для DOH",
), ),
@@ -553,10 +566,12 @@ class MessageLookup extends MessageLookupByLibrary {
), ),
"profiles": MessageLookupByLibrary.simpleMessage("Профили"), "profiles": MessageLookupByLibrary.simpleMessage("Профили"),
"profilesSort": MessageLookupByLibrary.simpleMessage("Сортировка профилей"), "profilesSort": MessageLookupByLibrary.simpleMessage("Сортировка профилей"),
"progress": MessageLookupByLibrary.simpleMessage("Прогресс"),
"project": MessageLookupByLibrary.simpleMessage("Проект"), "project": MessageLookupByLibrary.simpleMessage("Проект"),
"providers": MessageLookupByLibrary.simpleMessage("Провайдеры"), "providers": MessageLookupByLibrary.simpleMessage("Провайдеры"),
"proxies": MessageLookupByLibrary.simpleMessage("Прокси"), "proxies": MessageLookupByLibrary.simpleMessage("Прокси"),
"proxiesSetting": MessageLookupByLibrary.simpleMessage("Настройка прокси"), "proxiesSetting": MessageLookupByLibrary.simpleMessage("Настройка прокси"),
"proxyChains": MessageLookupByLibrary.simpleMessage("Цепочки прокси"),
"proxyGroup": MessageLookupByLibrary.simpleMessage("Группа прокси"), "proxyGroup": MessageLookupByLibrary.simpleMessage("Группа прокси"),
"proxyNameserver": MessageLookupByLibrary.simpleMessage( "proxyNameserver": MessageLookupByLibrary.simpleMessage(
"Прокси-сервер имен", "Прокси-сервер имен",
@@ -601,11 +616,15 @@ class MessageLookup extends MessageLookupByLibrary {
"remoteBackupDesc": MessageLookupByLibrary.simpleMessage( "remoteBackupDesc": MessageLookupByLibrary.simpleMessage(
"Резервное копирование локальных данных на WebDAV", "Резервное копирование локальных данных на WebDAV",
), ),
"remoteDestination": MessageLookupByLibrary.simpleMessage(
"Удалённое назначение",
),
"remoteRecoveryDesc": MessageLookupByLibrary.simpleMessage( "remoteRecoveryDesc": MessageLookupByLibrary.simpleMessage(
"Восстановление данных с WebDAV", "Восстановление данных с WebDAV",
), ),
"remove": MessageLookupByLibrary.simpleMessage("Удалить"), "remove": MessageLookupByLibrary.simpleMessage("Удалить"),
"rename": MessageLookupByLibrary.simpleMessage("Переименовать"), "rename": MessageLookupByLibrary.simpleMessage("Переименовать"),
"request": MessageLookupByLibrary.simpleMessage("Запрос"),
"requests": MessageLookupByLibrary.simpleMessage("Запросы"), "requests": MessageLookupByLibrary.simpleMessage("Запросы"),
"requestsDesc": MessageLookupByLibrary.simpleMessage( "requestsDesc": MessageLookupByLibrary.simpleMessage(
"Просмотр последних записей запросов", "Просмотр последних записей запросов",
@@ -648,7 +667,7 @@ class MessageLookup extends MessageLookupByLibrary {
"seconds": MessageLookupByLibrary.simpleMessage("Секунд"), "seconds": MessageLookupByLibrary.simpleMessage("Секунд"),
"selectAll": MessageLookupByLibrary.simpleMessage("Выбрать все"), "selectAll": MessageLookupByLibrary.simpleMessage("Выбрать все"),
"selected": MessageLookupByLibrary.simpleMessage("Выбрано"), "selected": MessageLookupByLibrary.simpleMessage("Выбрано"),
"selectedCountTitle": m7, "selectedCountTitle": m8,
"settings": MessageLookupByLibrary.simpleMessage("Настройки"), "settings": MessageLookupByLibrary.simpleMessage("Настройки"),
"show": MessageLookupByLibrary.simpleMessage("Показать"), "show": MessageLookupByLibrary.simpleMessage("Показать"),
"shrink": MessageLookupByLibrary.simpleMessage("Сжать"), "shrink": MessageLookupByLibrary.simpleMessage("Сжать"),
@@ -661,6 +680,8 @@ class MessageLookup extends MessageLookupByLibrary {
"sort": MessageLookupByLibrary.simpleMessage("Сортировка"), "sort": MessageLookupByLibrary.simpleMessage("Сортировка"),
"source": MessageLookupByLibrary.simpleMessage("Источник"), "source": MessageLookupByLibrary.simpleMessage("Источник"),
"sourceIp": MessageLookupByLibrary.simpleMessage("Исходный IP"), "sourceIp": MessageLookupByLibrary.simpleMessage("Исходный IP"),
"specialProxy": MessageLookupByLibrary.simpleMessage("Специальный прокси"),
"specialRules": MessageLookupByLibrary.simpleMessage("Специальные правила"),
"stackMode": MessageLookupByLibrary.simpleMessage("Режим стека"), "stackMode": MessageLookupByLibrary.simpleMessage("Режим стека"),
"standard": MessageLookupByLibrary.simpleMessage("Стандартный"), "standard": MessageLookupByLibrary.simpleMessage("Стандартный"),
"start": MessageLookupByLibrary.simpleMessage("Старт"), "start": MessageLookupByLibrary.simpleMessage("Старт"),
@@ -733,7 +754,7 @@ class MessageLookup extends MessageLookupByLibrary {
"urlDesc": MessageLookupByLibrary.simpleMessage( "urlDesc": MessageLookupByLibrary.simpleMessage(
"Получить профиль через URL", "Получить профиль через URL",
), ),
"urlTip": m8, "urlTip": m9,
"useHosts": MessageLookupByLibrary.simpleMessage("Использовать hosts"), "useHosts": MessageLookupByLibrary.simpleMessage("Использовать hosts"),
"useSystemHosts": MessageLookupByLibrary.simpleMessage( "useSystemHosts": MessageLookupByLibrary.simpleMessage(
"Использовать системные hosts", "Использовать системные hosts",

View File

@@ -24,19 +24,21 @@ class MessageLookup extends MessageLookupByLibrary {
static String m1(label) => "确定删除当前${label}吗?"; static String m1(label) => "确定删除当前${label}吗?";
static String m2(label) => "${label}不能为空"; static String m2(label) => "${label}详情";
static String m3(label) => "${label}当前已存在"; static String m3(label) => "${label}不能为空";
static String m4(label) => "暂无${label}"; static String m4(label) => "${label}当前已存在";
static String m5(label) => "${label}必须为数字"; static String m5(label) => "暂无${label}";
static String m6(label) => "${label} 必须在 1024 到 49151 之间"; static String m6(label) => "${label}必须为数字";
static String m7(count) => "已选择 ${count}"; static String m7(label) => "${label} 必须在 1024 到 49151 之间";
static String m8(label) => "${label}必须为URL"; static String m8(count) => "已选择 ${count}";
static String m9(label) => "${label}必须为URL";
final messages = _notInlinedMessages(_notInlinedMessages); final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{ static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@@ -121,6 +123,7 @@ class MessageLookup extends MessageLookupByLibrary {
"开启将失去部分应用能力获得全量的Clash的支持", "开启将失去部分应用能力获得全量的Clash的支持",
), ),
"confirm": MessageLookupByLibrary.simpleMessage("确定"), "confirm": MessageLookupByLibrary.simpleMessage("确定"),
"connection": MessageLookupByLibrary.simpleMessage("连接"),
"connections": MessageLookupByLibrary.simpleMessage("连接"), "connections": MessageLookupByLibrary.simpleMessage("连接"),
"connectionsDesc": MessageLookupByLibrary.simpleMessage("查看当前连接数据"), "connectionsDesc": MessageLookupByLibrary.simpleMessage("查看当前连接数据"),
"connectivity": MessageLookupByLibrary.simpleMessage("连通性:"), "connectivity": MessageLookupByLibrary.simpleMessage("连通性:"),
@@ -136,6 +139,7 @@ class MessageLookup extends MessageLookupByLibrary {
"country": MessageLookupByLibrary.simpleMessage("区域"), "country": MessageLookupByLibrary.simpleMessage("区域"),
"crashTest": MessageLookupByLibrary.simpleMessage("崩溃测试"), "crashTest": MessageLookupByLibrary.simpleMessage("崩溃测试"),
"create": MessageLookupByLibrary.simpleMessage("创建"), "create": MessageLookupByLibrary.simpleMessage("创建"),
"creationTime": MessageLookupByLibrary.simpleMessage("创建时间"),
"cut": MessageLookupByLibrary.simpleMessage("剪切"), "cut": MessageLookupByLibrary.simpleMessage("剪切"),
"dark": MessageLookupByLibrary.simpleMessage("深色"), "dark": MessageLookupByLibrary.simpleMessage("深色"),
"dashboard": MessageLookupByLibrary.simpleMessage("仪表盘"), "dashboard": MessageLookupByLibrary.simpleMessage("仪表盘"),
@@ -152,6 +156,10 @@ class MessageLookup extends MessageLookupByLibrary {
"desc": MessageLookupByLibrary.simpleMessage( "desc": MessageLookupByLibrary.simpleMessage(
"基于ClashMeta的多平台代理客户端简单易用开源无广告。", "基于ClashMeta的多平台代理客户端简单易用开源无广告。",
), ),
"destination": MessageLookupByLibrary.simpleMessage("目标地址"),
"destinationGeoIP": MessageLookupByLibrary.simpleMessage("目标地理定位"),
"destinationIPASN": MessageLookupByLibrary.simpleMessage("目标IP ASN"),
"details": m2,
"detectionTip": MessageLookupByLibrary.simpleMessage("依赖第三方api仅供参考"), "detectionTip": MessageLookupByLibrary.simpleMessage("依赖第三方api仅供参考"),
"developerMode": MessageLookupByLibrary.simpleMessage("开发者模式"), "developerMode": MessageLookupByLibrary.simpleMessage("开发者模式"),
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage("开发者模式已启用。"), "developerModeEnableTip": MessageLookupByLibrary.simpleMessage("开发者模式已启用。"),
@@ -168,13 +176,13 @@ class MessageLookup extends MessageLookupByLibrary {
"domain": MessageLookupByLibrary.simpleMessage("域名"), "domain": MessageLookupByLibrary.simpleMessage("域名"),
"download": MessageLookupByLibrary.simpleMessage("下载"), "download": MessageLookupByLibrary.simpleMessage("下载"),
"edit": MessageLookupByLibrary.simpleMessage("编辑"), "edit": MessageLookupByLibrary.simpleMessage("编辑"),
"emptyTip": m2, "emptyTip": m3,
"en": MessageLookupByLibrary.simpleMessage("英语"), "en": MessageLookupByLibrary.simpleMessage("英语"),
"enableOverride": MessageLookupByLibrary.simpleMessage("启用覆写"), "enableOverride": MessageLookupByLibrary.simpleMessage("启用覆写"),
"entries": MessageLookupByLibrary.simpleMessage("个条目"), "entries": MessageLookupByLibrary.simpleMessage("个条目"),
"exclude": MessageLookupByLibrary.simpleMessage("从最近任务中隐藏"), "exclude": MessageLookupByLibrary.simpleMessage("从最近任务中隐藏"),
"excludeDesc": MessageLookupByLibrary.simpleMessage("应用在后台时,从最近任务中隐藏应用"), "excludeDesc": MessageLookupByLibrary.simpleMessage("应用在后台时,从最近任务中隐藏应用"),
"existsTip": m3, "existsTip": m4,
"exit": MessageLookupByLibrary.simpleMessage("退出"), "exit": MessageLookupByLibrary.simpleMessage("退出"),
"expand": MessageLookupByLibrary.simpleMessage("标准"), "expand": MessageLookupByLibrary.simpleMessage("标准"),
"expirationTime": MessageLookupByLibrary.simpleMessage("到期时间"), "expirationTime": MessageLookupByLibrary.simpleMessage("到期时间"),
@@ -214,6 +222,7 @@ class MessageLookup extends MessageLookupByLibrary {
"go": MessageLookupByLibrary.simpleMessage("前往"), "go": MessageLookupByLibrary.simpleMessage("前往"),
"goDownload": MessageLookupByLibrary.simpleMessage("前往下载"), "goDownload": MessageLookupByLibrary.simpleMessage("前往下载"),
"hasCacheChange": MessageLookupByLibrary.simpleMessage("是否缓存修改"), "hasCacheChange": MessageLookupByLibrary.simpleMessage("是否缓存修改"),
"host": MessageLookupByLibrary.simpleMessage("主机"),
"hostsDesc": MessageLookupByLibrary.simpleMessage("追加Hosts"), "hostsDesc": MessageLookupByLibrary.simpleMessage("追加Hosts"),
"hotkeyConflict": MessageLookupByLibrary.simpleMessage("快捷键冲突"), "hotkeyConflict": MessageLookupByLibrary.simpleMessage("快捷键冲突"),
"hotkeyManagement": MessageLookupByLibrary.simpleMessage("快捷键管理"), "hotkeyManagement": MessageLookupByLibrary.simpleMessage("快捷键管理"),
@@ -248,6 +257,7 @@ class MessageLookup extends MessageLookupByLibrary {
"local": MessageLookupByLibrary.simpleMessage("本地"), "local": MessageLookupByLibrary.simpleMessage("本地"),
"localBackupDesc": MessageLookupByLibrary.simpleMessage("备份数据到本地"), "localBackupDesc": MessageLookupByLibrary.simpleMessage("备份数据到本地"),
"localRecoveryDesc": MessageLookupByLibrary.simpleMessage("通过文件恢复数据"), "localRecoveryDesc": MessageLookupByLibrary.simpleMessage("通过文件恢复数据"),
"log": MessageLookupByLibrary.simpleMessage("日志"),
"logLevel": MessageLookupByLibrary.simpleMessage("日志等级"), "logLevel": MessageLookupByLibrary.simpleMessage("日志等级"),
"logcat": MessageLookupByLibrary.simpleMessage("日志捕获"), "logcat": MessageLookupByLibrary.simpleMessage("日志捕获"),
"logcatDesc": MessageLookupByLibrary.simpleMessage("禁用将会隐藏日志入口"), "logcatDesc": MessageLookupByLibrary.simpleMessage("禁用将会隐藏日志入口"),
@@ -279,6 +289,7 @@ class MessageLookup extends MessageLookupByLibrary {
"networkDesc": MessageLookupByLibrary.simpleMessage("修改网络相关设置"), "networkDesc": MessageLookupByLibrary.simpleMessage("修改网络相关设置"),
"networkDetection": MessageLookupByLibrary.simpleMessage("网络检测"), "networkDetection": MessageLookupByLibrary.simpleMessage("网络检测"),
"networkSpeed": MessageLookupByLibrary.simpleMessage("网络速度"), "networkSpeed": MessageLookupByLibrary.simpleMessage("网络速度"),
"networkType": MessageLookupByLibrary.simpleMessage("网络类型"),
"neutralScheme": MessageLookupByLibrary.simpleMessage("中性"), "neutralScheme": MessageLookupByLibrary.simpleMessage("中性"),
"noData": MessageLookupByLibrary.simpleMessage("暂无数据"), "noData": MessageLookupByLibrary.simpleMessage("暂无数据"),
"noHotKey": MessageLookupByLibrary.simpleMessage("暂无快捷键"), "noHotKey": MessageLookupByLibrary.simpleMessage("暂无快捷键"),
@@ -293,8 +304,8 @@ class MessageLookup extends MessageLookupByLibrary {
"none": MessageLookupByLibrary.simpleMessage(""), "none": MessageLookupByLibrary.simpleMessage(""),
"notSelectedTip": MessageLookupByLibrary.simpleMessage("当前代理组无法选中"), "notSelectedTip": MessageLookupByLibrary.simpleMessage("当前代理组无法选中"),
"nullProfileDesc": MessageLookupByLibrary.simpleMessage("没有配置文件,请先添加配置文件"), "nullProfileDesc": MessageLookupByLibrary.simpleMessage("没有配置文件,请先添加配置文件"),
"nullTip": m4, "nullTip": m5,
"numberTip": m5, "numberTip": m6,
"oneColumn": MessageLookupByLibrary.simpleMessage("一列"), "oneColumn": MessageLookupByLibrary.simpleMessage("一列"),
"onlyIcon": MessageLookupByLibrary.simpleMessage("仅图标"), "onlyIcon": MessageLookupByLibrary.simpleMessage("仅图标"),
"onlyOtherApps": MessageLookupByLibrary.simpleMessage("仅第三方应用"), "onlyOtherApps": MessageLookupByLibrary.simpleMessage("仅第三方应用"),
@@ -326,7 +337,7 @@ class MessageLookup extends MessageLookupByLibrary {
), ),
"port": MessageLookupByLibrary.simpleMessage("端口"), "port": MessageLookupByLibrary.simpleMessage("端口"),
"portConflictTip": MessageLookupByLibrary.simpleMessage("请输入不同的端口"), "portConflictTip": MessageLookupByLibrary.simpleMessage("请输入不同的端口"),
"portTip": m6, "portTip": m7,
"preferH3Desc": MessageLookupByLibrary.simpleMessage("优先使用DOH的http/3"), "preferH3Desc": MessageLookupByLibrary.simpleMessage("优先使用DOH的http/3"),
"pressKeyboard": MessageLookupByLibrary.simpleMessage("请按下按键"), "pressKeyboard": MessageLookupByLibrary.simpleMessage("请按下按键"),
"preview": MessageLookupByLibrary.simpleMessage("预览"), "preview": MessageLookupByLibrary.simpleMessage("预览"),
@@ -350,10 +361,12 @@ class MessageLookup extends MessageLookupByLibrary {
), ),
"profiles": MessageLookupByLibrary.simpleMessage("配置"), "profiles": MessageLookupByLibrary.simpleMessage("配置"),
"profilesSort": MessageLookupByLibrary.simpleMessage("配置排序"), "profilesSort": MessageLookupByLibrary.simpleMessage("配置排序"),
"progress": MessageLookupByLibrary.simpleMessage("进度"),
"project": MessageLookupByLibrary.simpleMessage("项目"), "project": MessageLookupByLibrary.simpleMessage("项目"),
"providers": MessageLookupByLibrary.simpleMessage("提供者"), "providers": MessageLookupByLibrary.simpleMessage("提供者"),
"proxies": MessageLookupByLibrary.simpleMessage("代理"), "proxies": MessageLookupByLibrary.simpleMessage("代理"),
"proxiesSetting": MessageLookupByLibrary.simpleMessage("代理设置"), "proxiesSetting": MessageLookupByLibrary.simpleMessage("代理设置"),
"proxyChains": MessageLookupByLibrary.simpleMessage("代理链"),
"proxyGroup": MessageLookupByLibrary.simpleMessage("代理组"), "proxyGroup": MessageLookupByLibrary.simpleMessage("代理组"),
"proxyNameserver": MessageLookupByLibrary.simpleMessage("代理域名服务器"), "proxyNameserver": MessageLookupByLibrary.simpleMessage("代理域名服务器"),
"proxyNameserverDesc": MessageLookupByLibrary.simpleMessage("用于解析代理节点的域名"), "proxyNameserverDesc": MessageLookupByLibrary.simpleMessage("用于解析代理节点的域名"),
@@ -376,9 +389,11 @@ class MessageLookup extends MessageLookupByLibrary {
"regExp": MessageLookupByLibrary.simpleMessage("正则"), "regExp": MessageLookupByLibrary.simpleMessage("正则"),
"remote": MessageLookupByLibrary.simpleMessage("远程"), "remote": MessageLookupByLibrary.simpleMessage("远程"),
"remoteBackupDesc": MessageLookupByLibrary.simpleMessage("备份数据到WebDAV"), "remoteBackupDesc": MessageLookupByLibrary.simpleMessage("备份数据到WebDAV"),
"remoteDestination": MessageLookupByLibrary.simpleMessage("远程目标"),
"remoteRecoveryDesc": MessageLookupByLibrary.simpleMessage("通过WebDAV恢复数据"), "remoteRecoveryDesc": MessageLookupByLibrary.simpleMessage("通过WebDAV恢复数据"),
"remove": MessageLookupByLibrary.simpleMessage("移除"), "remove": MessageLookupByLibrary.simpleMessage("移除"),
"rename": MessageLookupByLibrary.simpleMessage("重命名"), "rename": MessageLookupByLibrary.simpleMessage("重命名"),
"request": MessageLookupByLibrary.simpleMessage("请求"),
"requests": MessageLookupByLibrary.simpleMessage("请求"), "requests": MessageLookupByLibrary.simpleMessage("请求"),
"requestsDesc": MessageLookupByLibrary.simpleMessage("查看最近请求记录"), "requestsDesc": MessageLookupByLibrary.simpleMessage("查看最近请求记录"),
"reset": MessageLookupByLibrary.simpleMessage("重置"), "reset": MessageLookupByLibrary.simpleMessage("重置"),
@@ -407,7 +422,7 @@ class MessageLookup extends MessageLookupByLibrary {
"seconds": MessageLookupByLibrary.simpleMessage(""), "seconds": MessageLookupByLibrary.simpleMessage(""),
"selectAll": MessageLookupByLibrary.simpleMessage("全选"), "selectAll": MessageLookupByLibrary.simpleMessage("全选"),
"selected": MessageLookupByLibrary.simpleMessage("已选择"), "selected": MessageLookupByLibrary.simpleMessage("已选择"),
"selectedCountTitle": m7, "selectedCountTitle": m8,
"settings": MessageLookupByLibrary.simpleMessage("设置"), "settings": MessageLookupByLibrary.simpleMessage("设置"),
"show": MessageLookupByLibrary.simpleMessage("显示"), "show": MessageLookupByLibrary.simpleMessage("显示"),
"shrink": MessageLookupByLibrary.simpleMessage("紧凑"), "shrink": MessageLookupByLibrary.simpleMessage("紧凑"),
@@ -418,6 +433,8 @@ class MessageLookup extends MessageLookupByLibrary {
"sort": MessageLookupByLibrary.simpleMessage("排序"), "sort": MessageLookupByLibrary.simpleMessage("排序"),
"source": MessageLookupByLibrary.simpleMessage("来源"), "source": MessageLookupByLibrary.simpleMessage("来源"),
"sourceIp": MessageLookupByLibrary.simpleMessage("源IP"), "sourceIp": MessageLookupByLibrary.simpleMessage("源IP"),
"specialProxy": MessageLookupByLibrary.simpleMessage("特殊代理"),
"specialRules": MessageLookupByLibrary.simpleMessage("特殊规则"),
"stackMode": MessageLookupByLibrary.simpleMessage("栈模式"), "stackMode": MessageLookupByLibrary.simpleMessage("栈模式"),
"standard": MessageLookupByLibrary.simpleMessage("标准"), "standard": MessageLookupByLibrary.simpleMessage("标准"),
"start": MessageLookupByLibrary.simpleMessage("启动"), "start": MessageLookupByLibrary.simpleMessage("启动"),
@@ -470,7 +487,7 @@ class MessageLookup extends MessageLookupByLibrary {
"upload": MessageLookupByLibrary.simpleMessage("上传"), "upload": MessageLookupByLibrary.simpleMessage("上传"),
"url": MessageLookupByLibrary.simpleMessage("URL"), "url": MessageLookupByLibrary.simpleMessage("URL"),
"urlDesc": MessageLookupByLibrary.simpleMessage("通过URL获取配置文件"), "urlDesc": MessageLookupByLibrary.simpleMessage("通过URL获取配置文件"),
"urlTip": m8, "urlTip": m9,
"useHosts": MessageLookupByLibrary.simpleMessage("使用Hosts"), "useHosts": MessageLookupByLibrary.simpleMessage("使用Hosts"),
"useSystemHosts": MessageLookupByLibrary.simpleMessage("使用系统Hosts"), "useSystemHosts": MessageLookupByLibrary.simpleMessage("使用系统Hosts"),
"value": MessageLookupByLibrary.simpleMessage(""), "value": MessageLookupByLibrary.simpleMessage(""),

View File

@@ -3139,6 +3139,126 @@ class AppLocalizations {
args: [], args: [],
); );
} }
/// `{label} details`
String details(Object label) {
return Intl.message(
'$label details',
name: 'details',
desc: '',
args: [label],
);
}
/// `Creation time`
String get creationTime {
return Intl.message(
'Creation time',
name: 'creationTime',
desc: '',
args: [],
);
}
/// `Progress`
String get progress {
return Intl.message('Progress', name: 'progress', desc: '', args: []);
}
/// `Host`
String get host {
return Intl.message('Host', name: 'host', desc: '', args: []);
}
/// `Destination`
String get destination {
return Intl.message('Destination', name: 'destination', desc: '', args: []);
}
/// `Destination GeoIP`
String get destinationGeoIP {
return Intl.message(
'Destination GeoIP',
name: 'destinationGeoIP',
desc: '',
args: [],
);
}
/// `Destination IPASN`
String get destinationIPASN {
return Intl.message(
'Destination IPASN',
name: 'destinationIPASN',
desc: '',
args: [],
);
}
/// `Special proxy`
String get specialProxy {
return Intl.message(
'Special proxy',
name: 'specialProxy',
desc: '',
args: [],
);
}
/// `special rules`
String get specialRules {
return Intl.message(
'special rules',
name: 'specialRules',
desc: '',
args: [],
);
}
/// `Remote destination`
String get remoteDestination {
return Intl.message(
'Remote destination',
name: 'remoteDestination',
desc: '',
args: [],
);
}
/// `Network type`
String get networkType {
return Intl.message(
'Network type',
name: 'networkType',
desc: '',
args: [],
);
}
/// `Proxy chains`
String get proxyChains {
return Intl.message(
'Proxy chains',
name: 'proxyChains',
desc: '',
args: [],
);
}
/// `Log`
String get log {
return Intl.message('Log', name: 'log', desc: '', args: []);
}
/// `Connection`
String get connection {
return Intl.message('Connection', name: 'connection', desc: '', args: []);
}
/// `Request`
String get request {
return Intl.message('Request', name: 'request', desc: '', args: []);
}
} }
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> { class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {

View File

@@ -36,7 +36,7 @@ Future<void> main() async {
Future<void> _service(List<String> flags) async { Future<void> _service(List<String> flags) async {
globalState.isService = true; globalState.isService = true;
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
final quickStart = flags.contains("quick"); final quickStart = flags.contains('quick');
final clashLibHandler = ClashLibHandler(); final clashLibHandler = ClashLibHandler();
await globalState.init(); await globalState.init();
@@ -54,15 +54,14 @@ Future<void> _service(List<String> flags) async {
vpn?.handleGetStartForegroundParams = () { vpn?.handleGetStartForegroundParams = () {
final traffic = clashLibHandler.getTraffic(); final traffic = clashLibHandler.getTraffic();
return json.encode({ return json.encode({
"title": clashLibHandler.getCurrentProfileName(), 'title': clashLibHandler.getCurrentProfileName(),
"content": "$traffic" 'content': '$traffic'
}); });
}; };
vpn?.addListener( vpn?.addListener(
_VpnListenerWithService( _VpnListenerWithService(
onDnsChanged: (String dns) { onDnsChanged: (String dns) {
print("handle dns $dns");
clashLibHandler.updateDns(dns); clashLibHandler.updateDns(dns);
}, },
), ),
@@ -70,7 +69,7 @@ Future<void> _service(List<String> flags) async {
if (!quickStart) { if (!quickStart) {
_handleMainIpc(clashLibHandler); _handleMainIpc(clashLibHandler);
} else { } else {
commonPrint.log("quick start"); commonPrint.log('quick start');
await ClashCore.initGeo(); await ClashCore.initGeo();
app?.tip(appLocalizations.startVpn); app?.tip(appLocalizations.startVpn);
final homeDirPath = await appPath.homeDirPath; final homeDirPath = await appPath.homeDirPath;
@@ -107,7 +106,7 @@ Future<void> _service(List<String> flags) async {
} }
} }
_handleMainIpc(ClashLibHandler clashLibHandler) { void _handleMainIpc(ClashLibHandler clashLibHandler) {
final sendPort = IsolateNameServer.lookupPortByName(mainIsolate); final sendPort = IsolateNameServer.lookupPortByName(mainIsolate);
if (sendPort == null) { if (sendPort == null) {
return; return;

View File

@@ -1,7 +1,6 @@
import 'package:fl_clash/plugins/app.dart'; import 'package:fl_clash/plugins/app.dart';
import 'package:fl_clash/providers/config.dart'; import 'package:fl_clash/providers/providers.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
class AndroidManager extends ConsumerStatefulWidget { class AndroidManager extends ConsumerStatefulWidget {
@@ -20,14 +19,10 @@ class _AndroidContainerState extends ConsumerState<AndroidManager> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); ref.listenManual(appSettingProvider.select((state) => state.hidden),
ref.listenManual( (prev, next) {
appSettingProvider.select((state) => state.hidden), app?.updateExcludeFromRecents(next);
(prev, next) { }, fireImmediately: true);
app?.updateExcludeFromRecents(next);
},
fireImmediately: true
);
} }
@override @override

View File

@@ -0,0 +1,291 @@
import 'dart:async';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/manager/window_manager.dart';
import 'package:fl_clash/providers/providers.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_acrylic/widgets/transparent_macos_sidebar.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
class AppStateManager extends ConsumerStatefulWidget {
final Widget child;
const AppStateManager({
super.key,
required this.child,
});
@override
ConsumerState<AppStateManager> createState() => _AppStateManagerState();
}
class _AppStateManagerState extends ConsumerState<AppStateManager>
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
ref.listenManual(layoutChangeProvider, (prev, next) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (prev != next) {
globalState.computeHeightMapCache = {};
}
});
});
ref.listenManual(
checkIpProvider,
(prev, next) {
if (prev != next && next.b) {
detectionState.startCheck();
}
},
fireImmediately: true,
);
ref.listenManual(configStateProvider, (prev, next) {
if (prev != next) {
globalState.appController.savePreferencesDebounce();
}
});
if (window == null) {
return;
}
ref.listenManual(
autoSetSystemDnsStateProvider,
(prev, next) async {
if (prev == next) {
return;
}
if (next.a == true && next.b == true) {
macOS?.updateDns(false);
} else {
macOS?.updateDns(true);
}
},
);
ref.listenManual(
currentBrightnessProvider,
(prev, next) {
if (prev == next) {
return;
}
window?.updateMacOSBrightness(next);
},
fireImmediately: true,
);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
commonPrint.log('$state');
if (state == AppLifecycleState.paused ||
state == AppLifecycleState.inactive) {
globalState.appController.savePreferences();
} else {
render?.resume();
}
if (state == AppLifecycleState.inactive) {
WidgetsBinding.instance.addPostFrameCallback((_) {
detectionState.tryStartCheck();
});
}
}
@override
void didChangePlatformBrightness() {
globalState.appController.updateBrightness();
}
@override
Widget build(BuildContext context) {
return Listener(
onPointerHover: (_) {
render?.resume();
},
child: widget.child,
);
}
}
class AppEnvManager extends StatelessWidget {
final Widget child;
const AppEnvManager({
super.key,
required this.child,
});
@override
Widget build(BuildContext context) {
if (kDebugMode) {
if (globalState.isPre) {
return Banner(
message: 'DEBUG',
location: BannerLocation.topEnd,
child: child,
);
}
}
if (globalState.isPre) {
return Banner(
message: 'PRE',
location: BannerLocation.topEnd,
child: child,
);
}
return child;
}
}
class AppSidebarContainer extends ConsumerWidget {
final Widget child;
const AppSidebarContainer({
super.key,
required this.child,
});
Widget _buildLoading() {
return Consumer(
builder: (_, ref, __) {
final loading = ref.watch(loadingProvider);
final isMobileView = ref.watch(isMobileViewProvider);
return loading && !isMobileView
? RotatedBox(
quarterTurns: 1,
child: const LinearProgressIndicator(),
)
: Container();
},
);
}
Widget _buildBackground({
required BuildContext context,
required Widget child,
}) {
if (!system.isMacOS) {
return Material(
color: context.colorScheme.surfaceContainer,
child: child,
);
}
return TransparentMacOSSidebar(
child: Material(
color: Colors.transparent,
child: child,
),
);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
final navigationState = ref.watch(navigationStateProvider);
final navigationItems = navigationState.navigationItems;
final isMobileView = navigationState.viewMode == ViewMode.mobile;
if (isMobileView) {
return child;
}
final currentIndex = navigationState.currentIndex;
final showLabel = ref.watch(appSettingProvider).showLabel;
return Row(
children: [
Stack(
alignment: Alignment.topRight,
children: [
_buildBackground(
context: context,
child: Column(
children: [
SizedBox(
height: 32,
),
if (!system.isMacOS) ...[
AppIcon(),
SizedBox(
height: 12,
),
],
Expanded(
child: ScrollConfiguration(
behavior: HiddenBarScrollBehavior(),
child: SingleChildScrollView(
child: IntrinsicHeight(
child: NavigationRail(
backgroundColor: Colors.transparent,
selectedLabelTextStyle:
context.textTheme.labelLarge!.copyWith(
color: context.colorScheme.onSurface,
),
unselectedLabelTextStyle:
context.textTheme.labelLarge!.copyWith(
color: context.colorScheme.onSurface,
),
destinations: navigationItems
.map(
(e) => NavigationRailDestination(
icon: e.icon,
label: Text(
Intl.message(e.label.name),
),
),
)
.toList(),
onDestinationSelected: (index) {
globalState.appController
.toPage(navigationItems[index].label);
},
extended: false,
selectedIndex: currentIndex,
labelType: showLabel
? NavigationRailLabelType.all
: NavigationRailLabelType.none,
),
),
),
),
),
const SizedBox(
height: 16,
),
IconButton(
onPressed: () {
ref.read(appSettingProvider.notifier).updateState(
(state) => state.copyWith(
showLabel: !state.showLabel,
),
);
},
icon: Icon(
Icons.menu,
color: context.colorScheme.onSurfaceVariant,
),
),
const SizedBox(
height: 16,
),
],
),
),
_buildLoading(),
],
),
Expanded(
flex: 1,
child: ClipRect(
child: child,
),
)
],
);
}
}

View File

@@ -1,133 +0,0 @@
import 'dart:async';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/providers/providers.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class AppStateManager extends ConsumerStatefulWidget {
final Widget child;
const AppStateManager({
super.key,
required this.child,
});
@override
ConsumerState<AppStateManager> createState() => _AppStateManagerState();
}
class _AppStateManagerState extends ConsumerState<AppStateManager>
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
ref.listenManual(layoutChangeProvider, (prev, next) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (prev != next) {
globalState.cacheHeightMap = {};
}
});
});
ref.listenManual(
checkIpProvider,
(prev, next) {
if (prev != next && next.b) {
detectionState.startCheck();
}
},
fireImmediately: true,
);
ref.listenManual(configStateProvider, (prev, next) {
if (prev != next) {
globalState.appController.savePreferencesDebounce();
}
});
ref.listenManual(
autoSetSystemDnsStateProvider,
(prev, next) async {
if (prev == next) {
return;
}
if (next.a == true && next.b == true) {
system.setMacOSDns(false);
} else {
system.setMacOSDns(true);
}
},
);
}
@override
reassemble() {
super.reassemble();
}
@override
void dispose() async {
await system.setMacOSDns(true);
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
commonPrint.log("$state");
if (state == AppLifecycleState.paused ||
state == AppLifecycleState.inactive) {
globalState.appController.savePreferences();
} else {
render?.resume();
}
}
@override
void didChangePlatformBrightness() {
globalState.appController.updateBrightness(
WidgetsBinding.instance.platformDispatcher.platformBrightness,
);
}
@override
Widget build(BuildContext context) {
return Listener(
onPointerHover: (_) {
render?.resume();
},
child: widget.child,
);
}
}
class AppEnvManager extends StatelessWidget {
final Widget child;
const AppEnvManager({
super.key,
required this.child,
});
@override
Widget build(BuildContext context) {
if (kDebugMode) {
if (globalState.isPre) {
return Banner(
message: 'DEBUG',
location: BannerLocation.topEnd,
child: child,
);
}
}
if (globalState.isPre) {
return Banner(
message: 'PRE',
location: BannerLocation.topEnd,
child: child,
);
}
return child;
}
}

View File

@@ -74,7 +74,7 @@ class _ClashContainerState extends ConsumerState<ClashManager>
debouncer.call( debouncer.call(
FunctionTag.updateDelay, FunctionTag.updateDelay,
() async { () async {
await appController.updateGroupsDebounce(); appController.updateGroupsDebounce();
}, },
duration: const Duration(milliseconds: 5000), duration: const Duration(milliseconds: 5000),
); );
@@ -90,9 +90,9 @@ class _ClashContainerState extends ConsumerState<ClashManager>
} }
@override @override
void onRequest(Connection connection) async { void onRequest(TrackerInfo trackerInfo) async {
ref.read(requestsProvider.notifier).addRequest(connection); ref.read(requestsProvider.notifier).addRequest(trackerInfo);
super.onRequest(connection); super.onRequest(trackerInfo);
} }
@override @override
@@ -102,7 +102,7 @@ class _ClashContainerState extends ConsumerState<ClashManager>
providerName, providerName,
), ),
); );
await globalState.appController.updateGroupsDebounce(); globalState.appController.updateGroupsDebounce();
super.onLoaded(providerName); super.onLoaded(providerName);
} }
} }

View File

@@ -35,7 +35,7 @@ class _HotKeyManagerState extends ConsumerState<HotKeyManager> {
); );
} }
_handleHotKeyAction(HotAction action) async { Future<void> _handleHotKeyAction(HotAction action) async {
switch (action) { switch (action) {
case HotAction.mode: case HotAction.mode:
globalState.appController.updateMode(); globalState.appController.updateMode();
@@ -50,7 +50,7 @@ class _HotKeyManagerState extends ConsumerState<HotKeyManager> {
} }
} }
_updateHotKeys({ Future<void> _updateHotKeys({
required List<HotKeyAction> hotKeyActions, required List<HotKeyAction> hotKeyActions,
}) async { }) async {
await hotKeyManager.unregisterAll(); await hotKeyManager.unregisterAll();
@@ -78,7 +78,7 @@ class _HotKeyManagerState extends ConsumerState<HotKeyManager> {
await Future.wait(hotkeyActionHandles); await Future.wait(hotkeyActionHandles);
} }
_buildShortcuts(Widget child) { Shortcuts _buildShortcuts(Widget child) {
return Shortcuts( return Shortcuts(
shortcuts: { shortcuts: {
utils.controlSingleActivator(LogicalKeyboardKey.keyW): utils.controlSingleActivator(LogicalKeyboardKey.keyW):

View File

@@ -1,11 +1,11 @@
export 'tray_manager.dart';
export 'window_manager.dart';
export 'android_manager.dart'; export 'android_manager.dart';
export 'app_manager.dart';
export 'clash_manager.dart'; export 'clash_manager.dart';
export 'tile_manager.dart';
export 'app_state_manager.dart';
export 'vpn_manager.dart';
export 'proxy_manager.dart';
export 'connectivity_manager.dart'; export 'connectivity_manager.dart';
export 'message_manager.dart'; export 'message_manager.dart';
export 'theme_manager.dart'; export 'proxy_manager.dart';
export 'theme_manager.dart';
export 'tile_manager.dart';
export 'tray_manager.dart';
export 'vpn_manager.dart';
export 'window_manager.dart';

View File

@@ -44,7 +44,7 @@ class MessageManagerState extends State<MessageManager> {
await _showMessage(); await _showMessage();
} }
_showMessage() async { Future<void> _showMessage() async {
if (_pushing == true) { if (_pushing == true) {
return; return;
} }
@@ -65,7 +65,7 @@ class MessageManagerState extends State<MessageManager> {
} }
} }
_handleRemove(CommonMessage commonMessage) async { Future<void> _handleRemove(CommonMessage commonMessage) async {
_messagesNotifier.value = List<CommonMessage>.from(_messagesNotifier.value) _messagesNotifier.value = List<CommonMessage>.from(_messagesNotifier.value)
..remove(commonMessage); ..remove(commonMessage);
} }
@@ -91,7 +91,7 @@ class MessageManagerState extends State<MessageManager> {
key: Key(messages.last.id), key: Key(messages.last.id),
builder: (_, constraints) { builder: (_, constraints) {
return Card( return Card(
shape: const RoundedSuperellipseBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all( borderRadius: BorderRadius.all(
Radius.circular(12.0), Radius.circular(12.0),
), ),

View File

@@ -14,7 +14,7 @@ class ProxyManager extends ConsumerStatefulWidget {
} }
class _ProxyManagerState extends ConsumerState<ProxyManager> { class _ProxyManagerState extends ConsumerState<ProxyManager> {
_updateProxy(ProxyState proxyState) async { Future<void> _updateProxy(ProxyState proxyState) async {
final isStart = proxyState.isStart; final isStart = proxyState.isStart;
final systemProxy = proxyState.systemProxy; final systemProxy = proxyState.systemProxy;
final port = proxyState.port; final port = proxyState.port;

View File

@@ -1,12 +1,15 @@
import 'dart:math'; import 'dart:math';
import 'package:fl_clash/common/constant.dart';
import 'package:fl_clash/common/measure.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/common/theme.dart'; import 'package:fl_clash/common/theme.dart';
import 'package:fl_clash/providers/config.dart'; import 'package:fl_clash/providers/config.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../providers/state.dart';
class ThemeManager extends ConsumerWidget { class ThemeManager extends ConsumerWidget {
final Widget child; final Widget child;
@@ -15,6 +18,54 @@ class ThemeManager extends ConsumerWidget {
required this.child, required this.child,
}); });
Widget _buildSystemUi(Widget child) {
if (!system.isAndroid) {
return child;
}
return AnnotatedRegion<SystemUiMode>(
sized: false,
value: SystemUiMode.edgeToEdge,
child: Consumer(
builder: (context, ref, _) {
final brightness = ref.watch(currentBrightnessProvider);
final iconBrightness = brightness == Brightness.light
? Brightness.dark
: Brightness.light;
globalState.appState = globalState.appState.copyWith(
systemUiOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: iconBrightness,
systemNavigationBarIconBrightness: iconBrightness,
systemNavigationBarColor: context.colorScheme.surface,
systemNavigationBarDividerColor: Colors.transparent,
),
);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: globalState.appState.systemUiOverlayStyle,
sized: false,
child: child,
);
},
),
);
}
// _buildScrollbar(Widget child) {
// return Consumer(
// builder: (_, ref, child) {
// final isMobileView = ref.read(isMobileViewProvider);
// if (isMobileView) {
// return ScrollConfiguration(
// behavior: HiddenBarScrollBehavior(),
// child: child!,
// );
// }
// return child!;
// },
// child: child,
// );
// }
@override @override
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final textScale = ref.read( final textScale = ref.read(
@@ -49,7 +100,7 @@ class ThemeManager extends ConsumerWidget {
container.maxHeight, container.maxHeight,
), ),
); );
return child; return _buildSystemUi(child);
}, },
), ),
); );

View File

@@ -39,7 +39,7 @@ class _TrayContainerState extends ConsumerState<TrayManager> with TrayListener {
@override @override
void onTrayIconRightMouseDown() { void onTrayIconRightMouseDown() {
trayManager.popUpContextMenu(); trayManager.popUpContextMenu(bringAppToFront: true);
} }
@override @override

View File

@@ -27,7 +27,7 @@ class _VpnContainerState extends ConsumerState<VpnManager> {
}); });
} }
showTip() { void showTip() {
debouncer.call( debouncer.call(
FunctionTag.vpnTip, FunctionTag.vpnTip,
() { () {

View File

@@ -1,10 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/providers/app.dart'; import 'package:fl_clash/providers/providers.dart';
import 'package:fl_clash/providers/config.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -59,7 +57,7 @@ class _WindowContainerState extends ConsumerState<WindowManager>
@override @override
void onWindowFocus() { void onWindowFocus() {
super.onWindowFocus(); super.onWindowFocus();
commonPrint.log("focus"); commonPrint.log('focus');
render?.resume(); render?.resume();
} }
@@ -96,14 +94,14 @@ class _WindowContainerState extends ConsumerState<WindowManager>
@override @override
void onWindowMinimize() async { void onWindowMinimize() async {
globalState.appController.savePreferencesDebounce(); globalState.appController.savePreferencesDebounce();
commonPrint.log("minimize"); commonPrint.log('minimize');
render?.pause(); render?.pause();
super.onWindowMinimize(); super.onWindowMinimize();
} }
@override @override
void onWindowRestore() { void onWindowRestore() {
commonPrint.log("restore"); commonPrint.log('restore');
render?.resume(); render?.resume();
super.onWindowRestore(); super.onWindowRestore();
} }
@@ -128,8 +126,9 @@ class WindowHeaderContainer extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer( return Consumer(
builder: (_, ref, child) { builder: (_, ref, child) {
final isMobileView = ref.watch(isMobileViewProvider);
final version = ref.watch(versionProvider); final version = ref.watch(versionProvider);
if (version <= 10 && Platform.isMacOS) { if ((version <= 10 || !isMobileView) && system.isMacOS) {
return child!; return child!;
} }
return Stack( return Stack(
@@ -171,7 +170,7 @@ class _WindowHeaderState extends State<WindowHeader> {
_initNotifier(); _initNotifier();
} }
_initNotifier() async { Future<void> _initNotifier() async {
isMaximizedNotifier.value = await windowManager.isMaximized(); isMaximizedNotifier.value = await windowManager.isMaximized();
isPinNotifier.value = await windowManager.isAlwaysOnTop(); isPinNotifier.value = await windowManager.isAlwaysOnTop();
} }
@@ -183,7 +182,7 @@ class _WindowHeaderState extends State<WindowHeader> {
super.dispose(); super.dispose();
} }
_updateMaximized() async { Future<void> _updateMaximized() async {
final isMaximized = await windowManager.isMaximized(); final isMaximized = await windowManager.isMaximized();
switch (isMaximized) { switch (isMaximized) {
case true: case true:
@@ -196,13 +195,13 @@ class _WindowHeaderState extends State<WindowHeader> {
isMaximizedNotifier.value = await windowManager.isMaximized(); isMaximizedNotifier.value = await windowManager.isMaximized();
} }
_updatePin() async { Future<void> _updatePin() async {
final isAlwaysOnTop = await windowManager.isAlwaysOnTop(); final isAlwaysOnTop = await windowManager.isAlwaysOnTop();
await windowManager.setAlwaysOnTop(!isAlwaysOnTop); await windowManager.setAlwaysOnTop(!isAlwaysOnTop);
isPinNotifier.value = await windowManager.isAlwaysOnTop(); isPinNotifier.value = await windowManager.isAlwaysOnTop();
} }
_buildActions() { Widget _buildActions() {
return Row( return Row(
children: [ children: [
IconButton( IconButton(
@@ -280,15 +279,11 @@ class _WindowHeaderState extends State<WindowHeader> {
), ),
), ),
), ),
if (Platform.isMacOS) if (system.isMacOS)
const Text( const Text(
appName, appName,
) )
else ...[ else ...[
const Positioned(
left: 0,
child: AppIcon(),
),
Positioned( Positioned(
right: 0, right: 0,
child: _buildActions(), child: _buildActions(),
@@ -306,24 +301,18 @@ class AppIcon extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
margin: const EdgeInsets.only(left: 8), decoration: BoxDecoration(
child: const Row( color: context.colorScheme.primaryContainer,
children: [ borderRadius: BorderRadius.circular(12),
SizedBox( ),
width: 24, padding: EdgeInsets.all(6),
height: 24, child: SizedBox(
child: CircleAvatar( width: 28,
foregroundImage: AssetImage("assets/images/icon.png"), height: 28,
backgroundColor: Colors.transparent, child: CircleAvatar(
), foregroundImage: AssetImage('assets/images/icon.png'),
), backgroundColor: Colors.transparent,
SizedBox( ),
width: 8,
),
Text(
appName,
),
],
), ),
); );
} }

View File

@@ -1,6 +1,6 @@
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:flutter/material.dart'; import 'package:flutter/services.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'common.dart'; import 'common.dart';
@@ -22,17 +22,18 @@ class AppState with _$AppState {
@Default({}) DelayMap delayMap, @Default({}) DelayMap delayMap,
@Default([]) List<Group> groups, @Default([]) List<Group> groups,
@Default(0) int checkIpNum, @Default(0) int checkIpNum,
Brightness? brightness, required Brightness brightness,
int? runTime, int? runTime,
@Default([]) List<ExternalProvider> providers, @Default([]) List<ExternalProvider> providers,
String? localIp, String? localIp,
required FixedList<Connection> requests, required FixedList<TrackerInfo> requests,
required int version, required int version,
required FixedList<Log> logs, required FixedList<Log> logs,
required FixedList<Traffic> traffics, required FixedList<Traffic> traffics,
required Traffic totalTraffic, required Traffic totalTraffic,
@Default("") String proxiesQuery,
@Default(false) bool realTunEnable, @Default(false) bool realTunEnable,
@Default(false) bool loading,
required SystemUiOverlayStyle systemUiOverlayStyle,
}) = _AppState; }) = _AppState;
} }

View File

@@ -19,88 +19,88 @@ const defaultMixedPort = 7890;
const defaultKeepAliveInterval = 30; const defaultKeepAliveInterval = 30;
const defaultBypassPrivateRouteAddress = [ const defaultBypassPrivateRouteAddress = [
"1.0.0.0/8", '1.0.0.0/8',
"2.0.0.0/7", '2.0.0.0/7',
"4.0.0.0/6", '4.0.0.0/6',
"8.0.0.0/7", '8.0.0.0/7',
"11.0.0.0/8", '11.0.0.0/8',
"12.0.0.0/6", '12.0.0.0/6',
"16.0.0.0/4", '16.0.0.0/4',
"32.0.0.0/3", '32.0.0.0/3',
"64.0.0.0/3", '64.0.0.0/3',
"96.0.0.0/4", '96.0.0.0/4',
"112.0.0.0/5", '112.0.0.0/5',
"120.0.0.0/6", '120.0.0.0/6',
"124.0.0.0/7", '124.0.0.0/7',
"126.0.0.0/8", '126.0.0.0/8',
"128.0.0.0/3", '128.0.0.0/3',
"160.0.0.0/5", '160.0.0.0/5',
"168.0.0.0/8", '168.0.0.0/8',
"169.0.0.0/9", '169.0.0.0/9',
"169.128.0.0/10", '169.128.0.0/10',
"169.192.0.0/11", '169.192.0.0/11',
"169.224.0.0/12", '169.224.0.0/12',
"169.240.0.0/13", '169.240.0.0/13',
"169.248.0.0/14", '169.248.0.0/14',
"169.252.0.0/15", '169.252.0.0/15',
"169.255.0.0/16", '169.255.0.0/16',
"170.0.0.0/7", '170.0.0.0/7',
"172.0.0.0/12", '172.0.0.0/12',
"172.32.0.0/11", '172.32.0.0/11',
"172.64.0.0/10", '172.64.0.0/10',
"172.128.0.0/9", '172.128.0.0/9',
"173.0.0.0/8", '173.0.0.0/8',
"174.0.0.0/7", '174.0.0.0/7',
"176.0.0.0/4", '176.0.0.0/4',
"192.0.0.0/9", '192.0.0.0/9',
"192.128.0.0/11", '192.128.0.0/11',
"192.160.0.0/13", '192.160.0.0/13',
"192.169.0.0/16", '192.169.0.0/16',
"192.170.0.0/15", '192.170.0.0/15',
"192.172.0.0/14", '192.172.0.0/14',
"192.176.0.0/12", '192.176.0.0/12',
"192.192.0.0/10", '192.192.0.0/10',
"193.0.0.0/8", '193.0.0.0/8',
"194.0.0.0/7", '194.0.0.0/7',
"196.0.0.0/6", '196.0.0.0/6',
"200.0.0.0/5", '200.0.0.0/5',
"208.0.0.0/4", '208.0.0.0/4',
"240.0.0.0/5", '240.0.0.0/5',
"248.0.0.0/6", '248.0.0.0/6',
"252.0.0.0/7", '252.0.0.0/7',
"254.0.0.0/8", '254.0.0.0/8',
"255.0.0.0/9", '255.0.0.0/9',
"255.128.0.0/10", '255.128.0.0/10',
"255.192.0.0/11", '255.192.0.0/11',
"255.224.0.0/12", '255.224.0.0/12',
"255.240.0.0/13", '255.240.0.0/13',
"255.248.0.0/14", '255.248.0.0/14',
"255.252.0.0/15", '255.252.0.0/15',
"255.254.0.0/16", '255.254.0.0/16',
"255.255.0.0/17", '255.255.0.0/17',
"255.255.128.0/18", '255.255.128.0/18',
"255.255.192.0/19", '255.255.192.0/19',
"255.255.224.0/20", '255.255.224.0/20',
"255.255.240.0/21", '255.255.240.0/21',
"255.255.248.0/22", '255.255.248.0/22',
"255.255.252.0/23", '255.255.252.0/23',
"255.255.254.0/24", '255.255.254.0/24',
"255.255.255.0/25", '255.255.255.0/25',
"255.255.255.128/26", '255.255.255.128/26',
"255.255.255.192/27", '255.255.255.192/27',
"255.255.255.224/28", '255.255.255.224/28',
"255.255.255.240/29", '255.255.255.240/29',
"255.255.255.248/30", '255.255.255.248/30',
"255.255.255.252/31", '255.255.255.252/31',
"255.255.255.254/32", '255.255.255.254/32',
"::/1", '::/1',
"8000::/2", '8000::/2',
"c000::/3", 'c000::/3',
"e000::/4", 'e000::/4',
"f000::/5", 'f000::/5',
"f800::/6", 'f800::/6',
"fe00::/9", 'fe00::/9',
"fec0::/10" 'fec0::/10'
]; ];
@freezed @freezed
@@ -117,11 +117,11 @@ class ProxyGroup with _$ProxyGroup {
bool? lazy, bool? lazy,
String? url, String? url,
int? timeout, int? timeout,
@JsonKey(name: "max-failed-times") int? maxFailedTimes, @JsonKey(name: 'max-failed-times') int? maxFailedTimes,
String? filter, String? filter,
@JsonKey(name: "expected-filter") String? excludeFilter, @JsonKey(name: 'expected-filter') String? excludeFilter,
@JsonKey(name: "exclude-type") String? excludeType, @JsonKey(name: 'exclude-type') String? excludeType,
@JsonKey(name: "expected-status") dynamic expectedStatus, @JsonKey(name: 'expected-status') dynamic expectedStatus,
bool? hidden, bool? hidden,
String? icon, String? icon,
}) = _ProxyGroup; }) = _ProxyGroup;
@@ -144,15 +144,15 @@ class RuleProvider with _$RuleProvider {
class Sniffer with _$Sniffer { class Sniffer with _$Sniffer {
const factory Sniffer({ const factory Sniffer({
@Default(false) bool enable, @Default(false) bool enable,
@Default(true) @JsonKey(name: "override-destination") bool overrideDest, @Default(true) @JsonKey(name: 'override-destination') bool overrideDest,
@Default([]) List<String> sniffing, @Default([]) List<String> sniffing,
@Default([]) @JsonKey(name: "force-domain") List<String> forceDomain, @Default([]) @JsonKey(name: 'force-domain') List<String> forceDomain,
@Default([]) @JsonKey(name: "skip-src-address") List<String> skipSrcAddress, @Default([]) @JsonKey(name: 'skip-src-address') List<String> skipSrcAddress,
@Default([]) @JsonKey(name: "skip-dst-address") List<String> skipDstAddress, @Default([]) @JsonKey(name: 'skip-dst-address') List<String> skipDstAddress,
@Default([]) @JsonKey(name: "skip-domain") List<String> skipDomain, @Default([]) @JsonKey(name: 'skip-domain') List<String> skipDomain,
@Default([]) @JsonKey(name: "port-whitelist") List<String> port, @Default([]) @JsonKey(name: 'port-whitelist') List<String> port,
@Default(true) @JsonKey(name: "force-dns-mapping") bool forceDnsMapping, @Default(true) @JsonKey(name: 'force-dns-mapping') bool forceDnsMapping,
@Default(true) @JsonKey(name: "parse-pure-ip") bool parsePureIp, @Default(true) @JsonKey(name: 'parse-pure-ip') bool parsePureIp,
@Default({}) Map<String, SnifferConfig> sniff, @Default({}) Map<String, SnifferConfig> sniff,
}) = _Sniffer; }) = _Sniffer;
@@ -168,7 +168,7 @@ List<String> _formJsonPorts(List? ports) {
class SnifferConfig with _$SnifferConfig { class SnifferConfig with _$SnifferConfig {
const factory SnifferConfig({ const factory SnifferConfig({
@Default([]) @JsonKey(fromJson: _formJsonPorts) List<String> ports, @Default([]) @JsonKey(fromJson: _formJsonPorts) List<String> ports,
@JsonKey(name: "override-destination") bool? overrideDest, @JsonKey(name: 'override-destination') bool? overrideDest,
}) = _SnifferConfig; }) = _SnifferConfig;
factory SnifferConfig.fromJson(Map<String, Object?> json) => factory SnifferConfig.fromJson(Map<String, Object?> json) =>
@@ -180,10 +180,10 @@ class Tun with _$Tun {
const factory Tun({ const factory Tun({
@Default(false) bool enable, @Default(false) bool enable,
@Default(appName) String device, @Default(appName) String device,
@JsonKey(name: "auto-route") @Default(false) bool autoRoute, @JsonKey(name: 'auto-route') @Default(false) bool autoRoute,
@Default(TunStack.mixed) TunStack stack, @Default(TunStack.mixed) TunStack stack,
@JsonKey(name: "dns-hijack") @Default(["any:53"]) List<String> dnsHijack, @JsonKey(name: 'dns-hijack') @Default(['any:53']) List<String> dnsHijack,
@JsonKey(name: "route-address") @Default([]) List<String> routeAddress, @JsonKey(name: 'route-address') @Default([]) List<String> routeAddress,
}) = _Tun; }) = _Tun;
factory Tun.fromJson(Map<String, Object?> json) => _$TunFromJson(json); factory Tun.fromJson(Map<String, Object?> json) => _$TunFromJson(json);
@@ -222,13 +222,13 @@ extension TunExt on Tun {
class FallbackFilter with _$FallbackFilter { class FallbackFilter with _$FallbackFilter {
const factory FallbackFilter({ const factory FallbackFilter({
@Default(true) bool geoip, @Default(true) bool geoip,
@Default("CN") @JsonKey(name: "geoip-code") String geoipCode, @Default('CN') @JsonKey(name: 'geoip-code') String geoipCode,
@Default(["gfw"]) List<String> geosite, @Default(['gfw']) List<String> geosite,
@Default(["240.0.0.0/4"]) List<String> ipcidr, @Default(['240.0.0.0/4']) List<String> ipcidr,
@Default([ @Default([
"+.google.com", '+.google.com',
"+.facebook.com", '+.facebook.com',
"+.youtube.com", '+.youtube.com',
]) ])
List<String> domain, List<String> domain,
}) = _FallbackFilter; }) = _FallbackFilter;
@@ -241,51 +241,51 @@ class FallbackFilter with _$FallbackFilter {
class Dns with _$Dns { class Dns with _$Dns {
const factory Dns({ const factory Dns({
@Default(true) bool enable, @Default(true) bool enable,
@Default("0.0.0.0:1053") String listen, @Default('0.0.0.0:1053') String listen,
@Default(false) @JsonKey(name: "prefer-h3") bool preferH3, @Default(false) @JsonKey(name: 'prefer-h3') bool preferH3,
@Default(true) @JsonKey(name: "use-hosts") bool useHosts, @Default(true) @JsonKey(name: 'use-hosts') bool useHosts,
@Default(true) @JsonKey(name: "use-system-hosts") bool useSystemHosts, @Default(true) @JsonKey(name: 'use-system-hosts') bool useSystemHosts,
@Default(false) @JsonKey(name: "respect-rules") bool respectRules, @Default(false) @JsonKey(name: 'respect-rules') bool respectRules,
@Default(false) bool ipv6, @Default(false) bool ipv6,
@Default(["223.5.5.5"]) @Default(['223.5.5.5'])
@JsonKey(name: "default-nameserver") @JsonKey(name: 'default-nameserver')
List<String> defaultNameserver, List<String> defaultNameserver,
@Default(DnsMode.fakeIp) @Default(DnsMode.fakeIp)
@JsonKey(name: "enhanced-mode") @JsonKey(name: 'enhanced-mode')
DnsMode enhancedMode, DnsMode enhancedMode,
@Default("198.18.0.1/16") @Default('198.18.0.1/16')
@JsonKey(name: "fake-ip-range") @JsonKey(name: 'fake-ip-range')
String fakeIpRange, String fakeIpRange,
@Default([ @Default([
"*.lan", '*.lan',
"localhost.ptlogin2.qq.com", 'localhost.ptlogin2.qq.com',
]) ])
@JsonKey(name: "fake-ip-filter") @JsonKey(name: 'fake-ip-filter')
List<String> fakeIpFilter, List<String> fakeIpFilter,
@Default({ @Default({
"www.baidu.com": "114.114.114.114", 'www.baidu.com': '114.114.114.114',
"+.internal.crop.com": "10.0.0.1", '+.internal.crop.com': '10.0.0.1',
"geosite:cn": "https://doh.pub/dns-query" 'geosite:cn': 'https://doh.pub/dns-query'
}) })
@JsonKey(name: "nameserver-policy") @JsonKey(name: 'nameserver-policy')
Map<String, String> nameserverPolicy, Map<String, String> nameserverPolicy,
@Default([ @Default([
"https://doh.pub/dns-query", 'https://doh.pub/dns-query',
"https://dns.alidns.com/dns-query", 'https://dns.alidns.com/dns-query',
]) ])
List<String> nameserver, List<String> nameserver,
@Default([ @Default([
"tls://8.8.4.4", 'tls://8.8.4.4',
"tls://1.1.1.1", 'tls://1.1.1.1',
]) ])
List<String> fallback, List<String> fallback,
@Default([ @Default([
"https://doh.pub/dns-query", 'https://doh.pub/dns-query',
]) ])
@JsonKey(name: "proxy-server-nameserver") @JsonKey(name: 'proxy-server-nameserver')
List<String> proxyServerNameserver, List<String> proxyServerNameserver,
@Default(FallbackFilter()) @Default(FallbackFilter())
@JsonKey(name: "fallback-filter") @JsonKey(name: 'fallback-filter')
FallbackFilter fallbackFilter, FallbackFilter fallbackFilter,
}) = _Dns; }) = _Dns;
@@ -304,19 +304,19 @@ class Dns with _$Dns {
class GeoXUrl with _$GeoXUrl { class GeoXUrl with _$GeoXUrl {
const factory GeoXUrl({ const factory GeoXUrl({
@Default( @Default(
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb", 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb',
) )
String mmdb, String mmdb,
@Default( @Default(
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb", 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb',
) )
String asn, String asn,
@Default( @Default(
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat", 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat',
) )
String geoip, String geoip,
@Default( @Default(
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat", 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat',
) )
String geosite, String geosite,
}) = _GeoXUrl; }) = _GeoXUrl;
@@ -349,10 +349,10 @@ class ParsedRule with _$ParsedRule {
}) = _ParsedRule; }) = _ParsedRule;
factory ParsedRule.parseString(String value) { factory ParsedRule.parseString(String value) {
final splits = value.split(","); final splits = value.split(',');
final shortSplits = splits final shortSplits = splits
.where( .where(
(item) => !item.contains("src") && !item.contains("no-resolve"), (item) => !item.contains('src') && !item.contains('no-resolve'),
) )
.toList(); .toList();
final ruleAction = RuleAction.values.firstWhere( final ruleAction = RuleAction.values.firstWhere(
@@ -372,17 +372,17 @@ class ParsedRule with _$ParsedRule {
String? ruleProvider; String? ruleProvider;
if (ruleAction == RuleAction.RULE_SET) { if (ruleAction == RuleAction.RULE_SET) {
ruleProvider = shortSplits.sublist(1, shortSplits.length - 1).join(","); ruleProvider = shortSplits.sublist(1, shortSplits.length - 1).join(',');
} else { } else {
content = shortSplits.sublist(1, shortSplits.length - 1).join(","); content = shortSplits.sublist(1, shortSplits.length - 1).join(',');
} }
return ParsedRule( return ParsedRule(
ruleAction: ruleAction, ruleAction: ruleAction,
content: content, content: content,
src: splits.contains("src"), src: splits.contains('src'),
ruleProvider: ruleProvider, ruleProvider: ruleProvider,
noResolve: splits.contains("no-resolve"), noResolve: splits.contains('no-resolve'),
subRule: subRule, subRule: subRule,
ruleTarget: ruleTarget, ruleTarget: ruleTarget,
); );
@@ -396,10 +396,10 @@ extension ParsedRuleExt on ParsedRule {
ruleAction == RuleAction.RULE_SET ? ruleProvider : content, ruleAction == RuleAction.RULE_SET ? ruleProvider : content,
ruleAction == RuleAction.SUB_RULE ? subRule : ruleTarget, ruleAction == RuleAction.SUB_RULE ? subRule : ruleTarget,
if (ruleAction.hasParams) ...[ if (ruleAction.hasParams) ...[
if (src) "src", if (src) 'src',
if (noResolve) "no-resolve", if (noResolve) 'no-resolve',
] ]
].join(","); ].join(',');
} }
} }
@@ -430,7 +430,7 @@ class SubRule with _$SubRule {
_$SubRuleFromJson(json); _$SubRuleFromJson(json);
} }
_genRule(List<dynamic>? rules) { List<Rule> _genRule(List<dynamic>? rules) {
if (rules == null) { if (rules == null) {
return []; return [];
} }
@@ -458,12 +458,12 @@ List<SubRule> _genSubRules(Map<String, dynamic> json) {
@freezed @freezed
class ClashConfigSnippet with _$ClashConfigSnippet { class ClashConfigSnippet with _$ClashConfigSnippet {
const factory ClashConfigSnippet({ const factory ClashConfigSnippet({
@Default([]) @JsonKey(name: "proxy-groups") List<ProxyGroup> proxyGroups, @Default([]) @JsonKey(name: 'proxy-groups') List<ProxyGroup> proxyGroups,
@JsonKey(fromJson: _genRule, name: "rules") @Default([]) List<Rule> rule, @JsonKey(fromJson: _genRule, name: 'rules') @Default([]) List<Rule> rule,
@JsonKey(name: "rule-providers", fromJson: _genRuleProviders) @JsonKey(name: 'rule-providers', fromJson: _genRuleProviders)
@Default([]) @Default([])
List<RuleProvider> ruleProvider, List<RuleProvider> ruleProvider,
@JsonKey(name: "sub-rules", fromJson: _genSubRules) @JsonKey(name: 'sub-rules', fromJson: _genSubRules)
@Default([]) @Default([])
List<SubRule> subRules, List<SubRule> subRules,
}) = _ClashConfigSnippet; }) = _ClashConfigSnippet;
@@ -475,39 +475,39 @@ class ClashConfigSnippet with _$ClashConfigSnippet {
@freezed @freezed
class ClashConfig with _$ClashConfig { class ClashConfig with _$ClashConfig {
const factory ClashConfig({ const factory ClashConfig({
@Default(defaultMixedPort) @JsonKey(name: "mixed-port") int mixedPort, @Default(defaultMixedPort) @JsonKey(name: 'mixed-port') int mixedPort,
@Default(0) @JsonKey(name: "socks-port") int socksPort, @Default(0) @JsonKey(name: 'socks-port') int socksPort,
@Default(0) @JsonKey(name: "port") int port, @Default(0) @JsonKey(name: 'port') int port,
@Default(0) @JsonKey(name: "redir-port") int redirPort, @Default(0) @JsonKey(name: 'redir-port') int redirPort,
@Default(0) @JsonKey(name: "tproxy-port") int tproxyPort, @Default(0) @JsonKey(name: 'tproxy-port') int tproxyPort,
@Default(Mode.rule) Mode mode, @Default(Mode.rule) Mode mode,
@Default(false) @JsonKey(name: "allow-lan") bool allowLan, @Default(false) @JsonKey(name: 'allow-lan') bool allowLan,
@Default(LogLevel.error) @JsonKey(name: "log-level") LogLevel logLevel, @Default(LogLevel.error) @JsonKey(name: 'log-level') LogLevel logLevel,
@Default(false) bool ipv6, @Default(false) bool ipv6,
@Default(FindProcessMode.off) @Default(FindProcessMode.off)
@JsonKey( @JsonKey(
name: "find-process-mode", name: 'find-process-mode',
unknownEnumValue: FindProcessMode.always, unknownEnumValue: FindProcessMode.always,
) )
FindProcessMode findProcessMode, FindProcessMode findProcessMode,
@Default(defaultKeepAliveInterval) @Default(defaultKeepAliveInterval)
@JsonKey(name: "keep-alive-interval") @JsonKey(name: 'keep-alive-interval')
int keepAliveInterval, int keepAliveInterval,
@Default(true) @JsonKey(name: "unified-delay") bool unifiedDelay, @Default(true) @JsonKey(name: 'unified-delay') bool unifiedDelay,
@Default(true) @JsonKey(name: "tcp-concurrent") bool tcpConcurrent, @Default(true) @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,
@Default(defaultTun) @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @Default(defaultTun) @JsonKey(fromJson: Tun.safeFormJson) Tun tun,
@Default(defaultDns) @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @Default(defaultDns) @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,
@Default(defaultGeoXUrl) @Default(defaultGeoXUrl)
@JsonKey(name: "geox-url", fromJson: GeoXUrl.safeFormJson) @JsonKey(name: 'geox-url', fromJson: GeoXUrl.safeFormJson)
GeoXUrl geoXUrl, GeoXUrl geoXUrl,
@Default(GeodataLoader.memconservative) @Default(GeodataLoader.memconservative)
@JsonKey(name: "geodata-loader") @JsonKey(name: 'geodata-loader')
GeodataLoader geodataLoader, GeodataLoader geodataLoader,
@Default([]) @JsonKey(name: "proxy-groups") List<ProxyGroup> proxyGroups, @Default([]) @JsonKey(name: 'proxy-groups') List<ProxyGroup> proxyGroups,
@Default([]) List<String> rule, @Default([]) List<String> rule,
@JsonKey(name: "global-ua") String? globalUa, @JsonKey(name: 'global-ua') String? globalUa,
@Default(ExternalControllerStatus.close) @Default(ExternalControllerStatus.close)
@JsonKey(name: "external-controller") @JsonKey(name: 'external-controller')
ExternalControllerStatus externalController, ExternalControllerStatus externalController,
@Default({}) HostsMap hosts, @Default({}) HostsMap hosts,
}) = _ClashConfig; }) = _ClashConfig;

View File

@@ -16,7 +16,7 @@ class NavigationItem with _$NavigationItem {
required Icon icon, required Icon icon,
required PageLabel label, required PageLabel label,
final String? description, final String? description,
required Widget view, required WidgetBuilder builder,
@Default(true) bool keep, @Default(true) bool keep,
String? path, String? path,
@Default([NavigationItemMode.mobile, NavigationItemMode.desktop]) @Default([NavigationItemMode.mobile, NavigationItemMode.desktop])
@@ -41,15 +41,23 @@ class Package with _$Package {
@freezed @freezed
class Metadata with _$Metadata { class Metadata with _$Metadata {
const factory Metadata({ const factory Metadata({
required int uid, @Default(0) int uid,
required String network, @Default('') String network,
required String sourceIP, @Default('') String sourceIP,
required String sourcePort, @Default('') String sourcePort,
required String destinationIP, @Default('') String destinationIP,
required String destinationPort, @Default('') String destinationPort,
required String host, @Default('') String host,
required String process, DnsMode? dnsMode,
required String remoteDestination, @Default('') String process,
@Default('') String processPath,
@Default('') String remoteDestination,
@Default([]) List<String> sourceGeoIP,
@Default([]) List<String> destinationGeoIP,
@Default('') String destinationIPASN,
@Default('') String sourceIPASN,
@Default('') String specialRules,
@Default('') String specialProxy,
}) = _Metadata; }) = _Metadata;
factory Metadata.fromJson(Map<String, Object?> json) => factory Metadata.fromJson(Map<String, Object?> json) =>
@@ -57,35 +65,48 @@ class Metadata with _$Metadata {
} }
@freezed @freezed
class Connection with _$Connection { class TrackerInfo with _$TrackerInfo {
const factory Connection({ const factory TrackerInfo({
required String id, required String id,
num? upload, @Default(0) int upload,
num? download, @Default(0) int download,
required DateTime start, required DateTime start,
required Metadata metadata, required Metadata metadata,
required List<String> chains, required List<String> chains,
}) = _Connection; required String rule,
required String rulePayload,
int? downloadSpeed,
int? uploadSpeed,
}) = _TrackerInfo;
factory Connection.fromJson(Map<String, Object?> json) => factory TrackerInfo.fromJson(Map<String, Object?> json) =>
_$ConnectionFromJson(json); _$TrackerInfoFromJson(json);
} }
extension ConnectionExt on Connection { extension TrackerInfoExt on TrackerInfo {
String get desc { String get desc {
var text = "${metadata.network}://"; var text = '${metadata.network}://';
final ips = [ final ips = [
metadata.host, metadata.host,
metadata.destinationIP, metadata.destinationIP,
].where((ip) => ip.isNotEmpty); ].where((ip) => ip.isNotEmpty);
text += ips.join("/"); text += ips.join('/');
text += ":${metadata.destinationPort}"; text += ':${metadata.destinationPort}';
return text; return text;
} }
String get progressText {
final process = metadata.process;
final uid = metadata.uid;
if (uid != 0) {
return '$process($uid)';
}
return process;
}
} }
String _logDateTime(_) { String _logDateTime(dynamic _) {
return DateTime.now().toString(); return DateTime.now().showFull;
} }
// String _logId(_) { // String _logId(_) {
@@ -95,8 +116,9 @@ String _logDateTime(_) {
@freezed @freezed
class Log with _$Log { class Log with _$Log {
const factory Log({ const factory Log({
@JsonKey(name: "LogLevel") @Default(LogLevel.app) LogLevel logLevel, // @JsonKey(fromJson: _logId) required String id,
@JsonKey(name: "Payload") @Default("") String payload, @JsonKey(name: 'LogLevel') @Default(LogLevel.info) LogLevel logLevel,
@JsonKey(name: 'Payload') @Default('') String payload,
@JsonKey(fromJson: _logDateTime) required String dateTime, @JsonKey(fromJson: _logDateTime) required String dateTime,
}) = _Log; }) = _Log;
@@ -118,8 +140,8 @@ class LogsState with _$LogsState {
const factory LogsState({ const factory LogsState({
@Default([]) List<Log> logs, @Default([]) List<Log> logs,
@Default([]) List<String> keywords, @Default([]) List<String> keywords,
@Default("") String query, @Default('') String query,
@Default(false) bool loading, @Default(true) bool autoScrollToEnd,
}) = _LogsState; }) = _LogsState;
} }
@@ -138,27 +160,28 @@ extension LogsStateExt on LogsState {
} }
@freezed @freezed
class ConnectionsState with _$ConnectionsState { class TrackerInfosState with _$TrackerInfosState {
const factory ConnectionsState({ const factory TrackerInfosState({
@Default([]) List<Connection> connections, @Default([]) List<TrackerInfo> trackerInfos,
@Default([]) List<String> keywords, @Default([]) List<String> keywords,
@Default("") String query, @Default('') String query,
@Default(false) bool loading, @Default(true) bool autoScrollToEnd,
}) = _ConnectionsState; }) = _TrackerInfosState;
} }
extension ConnectionsStateExt on ConnectionsState { extension TrackerInfosStateExt on TrackerInfosState {
List<Connection> get list { List<TrackerInfo> get list {
final lowerQuery = query.toLowerCase().trim(); final lowerQuery = query.toLowerCase().trim();
final lowQuery = query.toLowerCase(); final lowQuery = query.toLowerCase();
return connections.where((connection) { return trackerInfos.where((trackerInfo) {
final chains = connection.chains; final chains = trackerInfo.chains;
final process = connection.metadata.process; final process = trackerInfo.metadata.process;
final networkText = connection.metadata.network.toLowerCase(); final networkText = trackerInfo.metadata.network.toLowerCase();
final hostText = connection.metadata.host.toLowerCase(); final hostText = trackerInfo.metadata.host.toLowerCase();
final destinationIPText = connection.metadata.destinationIP.toLowerCase(); final destinationIPText =
final processText = connection.metadata.process.toLowerCase(); trackerInfo.metadata.destinationIP.toLowerCase();
final chainsText = chains.join("").toLowerCase(); final processText = trackerInfo.metadata.process.toLowerCase();
final chainsText = chains.join('').toLowerCase();
return {...chains, process}.containsAll(keywords) && return {...chains, process}.containsAll(keywords) &&
(networkText.contains(lowerQuery) || (networkText.contains(lowerQuery) ||
hostText.contains(lowerQuery) || hostText.contains(lowerQuery) ||
@@ -169,7 +192,7 @@ extension ConnectionsStateExt on ConnectionsState {
} }
} }
const defaultDavFileName = "backup.zip"; const defaultDavFileName = 'backup.zip';
@freezed @freezed
class DAV with _$DAV { class DAV with _$DAV {
@@ -193,14 +216,14 @@ class FileInfo with _$FileInfo {
extension FileInfoExt on FileInfo { extension FileInfoExt on FileInfo {
String get desc => String get desc =>
"${TrafficValue(value: size).show} · ${lastModified.lastUpdateTimeDesc}"; '${TrafficValue(value: size).show} · ${lastModified.lastUpdateTimeDesc}';
} }
@freezed @freezed
class VersionInfo with _$VersionInfo { class VersionInfo with _$VersionInfo {
const factory VersionInfo({ const factory VersionInfo({
@Default("") String clashName, @Default('') String clashName,
@Default("") String version, @Default('') String version,
}) = _VersionInfo; }) = _VersionInfo;
factory VersionInfo.fromJson(Map<String, Object?> json) => factory VersionInfo.fromJson(Map<String, Object?> json) =>
@@ -226,6 +249,10 @@ class Traffic {
); );
} }
String toSpeedText() {
return '$up/s ↓ $down/s';
}
@override @override
String toString() { String toString() {
return '$up$down'; return '$up$down';
@@ -274,7 +301,7 @@ class Group with _$Group {
String? now, String? now,
bool? hidden, bool? hidden,
String? testUrl, String? testUrl,
@Default("") String icon, @Default('') String icon,
required String name, required String name,
}) = _Group; }) = _Group;
@@ -289,7 +316,7 @@ extension GroupsExt on List<Group> {
} }
extension GroupExt on Group { extension GroupExt on Group {
String get realNow => now ?? ""; String get realNow => now ?? '';
String getCurrentSelectedName(String proxyName) { String getCurrentSelectedName(String proxyName) {
if (type.isComputedSelected) { if (type.isComputedSelected) {
@@ -307,10 +334,10 @@ class TrafficValue {
int get value => _value; int get value => _value;
String get show => "$showValue $showUnit"; String get show => '$showValue $showUnit';
String get shortShow => String get shortShow =>
"${trafficValueShow.value.fixed(decimals: 1)} $showUnit"; '${trafficValueShow.value.fixed(decimals: 1)} $showUnit';
String get showValue => trafficValueShow.value.fixed(); String get showValue => trafficValueShow.value.fixed();
@@ -347,7 +374,7 @@ class TrafficValue {
@override @override
String toString() { String toString() {
return "$showValue$showUnit"; return '$showValue$showUnit';
} }
@override @override
@@ -411,56 +438,56 @@ class IpInfo {
static IpInfo fromIpInfoIoJson(Map<String, dynamic> json) { static IpInfo fromIpInfoIoJson(Map<String, dynamic> json) {
return switch (json) { return switch (json) {
{ {
"ip": final String ip, 'ip': final String ip,
"country": final String country, 'country': final String country,
} => } =>
IpInfo( IpInfo(
ip: ip, ip: ip,
countryCode: country, countryCode: country,
), ),
_ => throw const FormatException("invalid json"), _ => throw const FormatException('invalid json'),
}; };
} }
static IpInfo fromIpApiCoJson(Map<String, dynamic> json) { static IpInfo fromIpApiCoJson(Map<String, dynamic> json) {
return switch (json) { return switch (json) {
{ {
"ip": final String ip, 'ip': final String ip,
"country_code": final String countryCode, 'country_code': final String countryCode,
} => } =>
IpInfo( IpInfo(
ip: ip, ip: ip,
countryCode: countryCode, countryCode: countryCode,
), ),
_ => throw const FormatException("invalid json"), _ => throw const FormatException('invalid json'),
}; };
} }
static IpInfo fromIpSbJson(Map<String, dynamic> json) { static IpInfo fromIpSbJson(Map<String, dynamic> json) {
return switch (json) { return switch (json) {
{ {
"ip": final String ip, 'ip': final String ip,
"country_code": final String countryCode, 'country_code': final String countryCode,
} => } =>
IpInfo( IpInfo(
ip: ip, ip: ip,
countryCode: countryCode, countryCode: countryCode,
), ),
_ => throw const FormatException("invalid json"), _ => throw const FormatException('invalid json'),
}; };
} }
static IpInfo fromIpwhoIsJson(Map<String, dynamic> json) { static IpInfo fromIpwhoIsJson(Map<String, dynamic> json) {
return switch (json) { return switch (json) {
{ {
"ip": final String ip, 'ip': final String ip,
"country_code": final String countryCode, 'country_code': final String countryCode,
} => } =>
IpInfo( IpInfo(
ip: ip, ip: ip,
countryCode: countryCode, countryCode: countryCode,
), ),
_ => throw const FormatException("invalid json"), _ => throw const FormatException('invalid json'),
}; };
} }
@@ -539,7 +566,7 @@ class Result<T> with _$Result<T> {
factory Result.success(T data) => Result( factory Result.success(T data) => Result(
data: data, data: data,
type: ResultType.success, type: ResultType.success,
message: "", message: '',
); );
factory Result.error(String message) => Result( factory Result.error(String message) => Result(

View File

@@ -11,23 +11,23 @@ part 'generated/config.freezed.dart';
part 'generated/config.g.dart'; part 'generated/config.g.dart';
const defaultBypassDomain = [ const defaultBypassDomain = [
"*zhihu.com", '*zhihu.com',
"*zhimg.com", '*zhimg.com',
"*jd.com", '*jd.com',
"100ime-iat-api.xfyun.cn", '100ime-iat-api.xfyun.cn',
"*360buyimg.com", '*360buyimg.com',
"localhost", 'localhost',
"*.local", '*.local',
"127.*", '127.*',
"10.*", '10.*',
"172.16.*", '172.16.*',
"172.17.*", '172.17.*',
"172.18.*", '172.18.*',
"172.19.*", '172.19.*',
"172.2*", '172.2*',
"172.30.*", '172.30.*',
"172.31.*", '172.31.*',
"192.168.*" '192.168.*'
]; ];
const defaultAppSettingProps = AppSettingProps(); const defaultAppSettingProps = AppSettingProps();
@@ -178,8 +178,8 @@ class ProxiesStyle with _$ProxiesStyle {
@freezed @freezed
class TextScale with _$TextScale { class TextScale with _$TextScale {
const factory TextScale({ const factory TextScale({
@Default(false) enable, @Default(false) bool enable,
@Default(1.0) scale, @Default(1.0) double scale,
}) = _TextScale; }) = _TextScale;
factory TextScale.fromJson(Map<String, Object?> json) => factory TextScale.fromJson(Map<String, Object?> json) =>
@@ -265,12 +265,12 @@ class Config with _$Config {
factory Config.compatibleFromJson(Map<String, Object?> json) { factory Config.compatibleFromJson(Map<String, Object?> json) {
try { try {
final accessControlMap = json["accessControl"]; final accessControlMap = json['accessControl'];
final isAccessControl = json["isAccessControl"]; final isAccessControl = json['isAccessControl'];
if (accessControlMap != null) { if (accessControlMap != null) {
(accessControlMap as Map)["enable"] = isAccessControl; (accessControlMap as Map)['enable'] = isAccessControl;
if (json["vpnProps"] != null) { if (json['vpnProps'] != null) {
(json["vpnProps"] as Map)["accessControl"] = accessControlMap; (json['vpnProps'] as Map)['accessControl'] = accessControlMap;
} }
} }
} catch (_) {} } catch (_) {}

View File

@@ -12,7 +12,7 @@ abstract mixin class AppMessageListener {
void onDelay(Delay delay) {} void onDelay(Delay delay) {}
void onRequest(Connection connection) {} void onRequest(TrackerInfo connection) {}
void onLoaded(String providerName) {} void onLoaded(String providerName) {}
} }
@@ -26,9 +26,9 @@ abstract mixin class AppMessageListener {
@freezed @freezed
class SetupParams with _$SetupParams { class SetupParams with _$SetupParams {
const factory SetupParams({ const factory SetupParams({
@JsonKey(name: "config") required Map<String, dynamic> config, @JsonKey(name: 'config') required Map<String, dynamic> config,
@JsonKey(name: "selected-map") required Map<String, String> selectedMap, @JsonKey(name: 'selected-map') required Map<String, String> selectedMap,
@JsonKey(name: "test-url") required String testUrl, @JsonKey(name: 'test-url') required String testUrl,
}) = _SetupParams; }) = _SetupParams;
factory SetupParams.fromJson(Map<String, dynamic> json) => factory SetupParams.fromJson(Map<String, dynamic> json) =>
@@ -68,10 +68,10 @@ class UpdateParams with _$UpdateParams {
@freezed @freezed
class CoreState with _$CoreState { class CoreState with _$CoreState {
const factory CoreState({ const factory CoreState({
@JsonKey(name: "vpn-props") required VpnProps vpnProps, @JsonKey(name: 'vpn-props') required VpnProps vpnProps,
@JsonKey(name: "only-statistics-proxy") required bool onlyStatisticsProxy, @JsonKey(name: 'only-statistics-proxy') required bool onlyStatisticsProxy,
@JsonKey(name: "current-profile-name") required String currentProfileName, @JsonKey(name: 'current-profile-name') required String currentProfileName,
@JsonKey(name: "bypass-domain") @Default([]) List<String> bypassDomain, @JsonKey(name: 'bypass-domain') @Default([]) List<String> bypassDomain,
}) = _CoreState; }) = _CoreState;
factory CoreState.fromJson(Map<String, Object?> json) => factory CoreState.fromJson(Map<String, Object?> json) =>
@@ -100,7 +100,7 @@ class AndroidVpnOptions with _$AndroidVpnOptions {
@freezed @freezed
class InitParams with _$InitParams { class InitParams with _$InitParams {
const factory InitParams({ const factory InitParams({
@JsonKey(name: "home-dir") required String homeDir, @JsonKey(name: 'home-dir') required String homeDir,
required int version, required int version,
}) = _InitParams; }) = _InitParams;
@@ -111,8 +111,8 @@ class InitParams with _$InitParams {
@freezed @freezed
class ChangeProxyParams with _$ChangeProxyParams { class ChangeProxyParams with _$ChangeProxyParams {
const factory ChangeProxyParams({ const factory ChangeProxyParams({
@JsonKey(name: "group-name") required String groupName, @JsonKey(name: 'group-name') required String groupName,
@JsonKey(name: "proxy-name") required String proxyName, @JsonKey(name: 'proxy-name') required String proxyName,
}) = _ChangeProxyParams; }) = _ChangeProxyParams;
factory ChangeProxyParams.fromJson(Map<String, Object?> json) => factory ChangeProxyParams.fromJson(Map<String, Object?> json) =>
@@ -122,8 +122,8 @@ class ChangeProxyParams with _$ChangeProxyParams {
@freezed @freezed
class UpdateGeoDataParams with _$UpdateGeoDataParams { class UpdateGeoDataParams with _$UpdateGeoDataParams {
const factory UpdateGeoDataParams({ const factory UpdateGeoDataParams({
@JsonKey(name: "geo-type") required String geoType, @JsonKey(name: 'geo-type') required String geoType,
@JsonKey(name: "geo-name") required String geoName, @JsonKey(name: 'geo-name') required String geoName,
}) = _UpdateGeoDataParams; }) = _UpdateGeoDataParams;
factory UpdateGeoDataParams.fromJson(Map<String, Object?> json) => factory UpdateGeoDataParams.fromJson(Map<String, Object?> json) =>
@@ -197,10 +197,10 @@ class Now with _$Now {
@freezed @freezed
class ProviderSubscriptionInfo with _$ProviderSubscriptionInfo { class ProviderSubscriptionInfo with _$ProviderSubscriptionInfo {
const factory ProviderSubscriptionInfo({ const factory ProviderSubscriptionInfo({
@JsonKey(name: "UPLOAD") @Default(0) int upload, @JsonKey(name: 'UPLOAD') @Default(0) int upload,
@JsonKey(name: "DOWNLOAD") @Default(0) int download, @JsonKey(name: 'DOWNLOAD') @Default(0) int download,
@JsonKey(name: "TOTAL") @Default(0) int total, @JsonKey(name: 'TOTAL') @Default(0) int total,
@JsonKey(name: "EXPIRE") @Default(0) int expire, @JsonKey(name: 'EXPIRE') @Default(0) int expire,
}) = _ProviderSubscriptionInfo; }) = _ProviderSubscriptionInfo;
factory ProviderSubscriptionInfo.fromJson(Map<String, Object?> json) => factory ProviderSubscriptionInfo.fromJson(Map<String, Object?> json) =>
@@ -224,11 +224,11 @@ class ExternalProvider with _$ExternalProvider {
required String type, required String type,
String? path, String? path,
required int count, required int count,
@JsonKey(name: "subscription-info", fromJson: subscriptionInfoFormCore) @JsonKey(name: 'subscription-info', fromJson: subscriptionInfoFormCore)
SubscriptionInfo? subscriptionInfo, SubscriptionInfo? subscriptionInfo,
@Default(false) bool isUpdating, @Default(false) bool isUpdating,
@JsonKey(name: "vehicle-type") required String vehicleType, @JsonKey(name: 'vehicle-type') required String vehicleType,
@JsonKey(name: "update-at") required DateTime updateAt, @JsonKey(name: 'update-at') required DateTime updateAt,
}) = _ExternalProvider; }) = _ExternalProvider;
factory ExternalProvider.fromJson(Map<String, Object?> json) => factory ExternalProvider.fromJson(Map<String, Object?> json) =>

View File

@@ -26,17 +26,19 @@ mixin _$AppState {
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
List<Group> get groups => throw _privateConstructorUsedError; List<Group> get groups => throw _privateConstructorUsedError;
int get checkIpNum => throw _privateConstructorUsedError; int get checkIpNum => throw _privateConstructorUsedError;
Brightness? get brightness => throw _privateConstructorUsedError; Brightness get brightness => throw _privateConstructorUsedError;
int? get runTime => throw _privateConstructorUsedError; int? get runTime => throw _privateConstructorUsedError;
List<ExternalProvider> get providers => throw _privateConstructorUsedError; List<ExternalProvider> get providers => throw _privateConstructorUsedError;
String? get localIp => throw _privateConstructorUsedError; String? get localIp => throw _privateConstructorUsedError;
FixedList<Connection> get requests => throw _privateConstructorUsedError; FixedList<TrackerInfo> get requests => throw _privateConstructorUsedError;
int get version => throw _privateConstructorUsedError; int get version => throw _privateConstructorUsedError;
FixedList<Log> get logs => throw _privateConstructorUsedError; FixedList<Log> get logs => throw _privateConstructorUsedError;
FixedList<Traffic> get traffics => throw _privateConstructorUsedError; FixedList<Traffic> get traffics => throw _privateConstructorUsedError;
Traffic get totalTraffic => throw _privateConstructorUsedError; Traffic get totalTraffic => throw _privateConstructorUsedError;
String get proxiesQuery => throw _privateConstructorUsedError;
bool get realTunEnable => throw _privateConstructorUsedError; bool get realTunEnable => throw _privateConstructorUsedError;
bool get loading => throw _privateConstructorUsedError;
SystemUiOverlayStyle get systemUiOverlayStyle =>
throw _privateConstructorUsedError;
/// Create a copy of AppState /// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -60,17 +62,18 @@ abstract class $AppStateCopyWith<$Res> {
Map<String, Map<String, int?>> delayMap, Map<String, Map<String, int?>> delayMap,
List<Group> groups, List<Group> groups,
int checkIpNum, int checkIpNum,
Brightness? brightness, Brightness brightness,
int? runTime, int? runTime,
List<ExternalProvider> providers, List<ExternalProvider> providers,
String? localIp, String? localIp,
FixedList<Connection> requests, FixedList<TrackerInfo> requests,
int version, int version,
FixedList<Log> logs, FixedList<Log> logs,
FixedList<Traffic> traffics, FixedList<Traffic> traffics,
Traffic totalTraffic, Traffic totalTraffic,
String proxiesQuery, bool realTunEnable,
bool realTunEnable}); bool loading,
SystemUiOverlayStyle systemUiOverlayStyle});
} }
/// @nodoc /// @nodoc
@@ -97,7 +100,7 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
Object? delayMap = null, Object? delayMap = null,
Object? groups = null, Object? groups = null,
Object? checkIpNum = null, Object? checkIpNum = null,
Object? brightness = freezed, Object? brightness = null,
Object? runTime = freezed, Object? runTime = freezed,
Object? providers = null, Object? providers = null,
Object? localIp = freezed, Object? localIp = freezed,
@@ -106,8 +109,9 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
Object? logs = null, Object? logs = null,
Object? traffics = null, Object? traffics = null,
Object? totalTraffic = null, Object? totalTraffic = null,
Object? proxiesQuery = null,
Object? realTunEnable = null, Object? realTunEnable = null,
Object? loading = null,
Object? systemUiOverlayStyle = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
isInit: null == isInit isInit: null == isInit
@@ -146,10 +150,10 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
? _value.checkIpNum ? _value.checkIpNum
: checkIpNum // ignore: cast_nullable_to_non_nullable : checkIpNum // ignore: cast_nullable_to_non_nullable
as int, as int,
brightness: freezed == brightness brightness: null == brightness
? _value.brightness ? _value.brightness
: brightness // ignore: cast_nullable_to_non_nullable : brightness // ignore: cast_nullable_to_non_nullable
as Brightness?, as Brightness,
runTime: freezed == runTime runTime: freezed == runTime
? _value.runTime ? _value.runTime
: runTime // ignore: cast_nullable_to_non_nullable : runTime // ignore: cast_nullable_to_non_nullable
@@ -165,7 +169,7 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
requests: null == requests requests: null == requests
? _value.requests ? _value.requests
: requests // ignore: cast_nullable_to_non_nullable : requests // ignore: cast_nullable_to_non_nullable
as FixedList<Connection>, as FixedList<TrackerInfo>,
version: null == version version: null == version
? _value.version ? _value.version
: version // ignore: cast_nullable_to_non_nullable : version // ignore: cast_nullable_to_non_nullable
@@ -182,14 +186,18 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
? _value.totalTraffic ? _value.totalTraffic
: totalTraffic // ignore: cast_nullable_to_non_nullable : totalTraffic // ignore: cast_nullable_to_non_nullable
as Traffic, as Traffic,
proxiesQuery: null == proxiesQuery
? _value.proxiesQuery
: proxiesQuery // ignore: cast_nullable_to_non_nullable
as String,
realTunEnable: null == realTunEnable realTunEnable: null == realTunEnable
? _value.realTunEnable ? _value.realTunEnable
: realTunEnable // ignore: cast_nullable_to_non_nullable : realTunEnable // ignore: cast_nullable_to_non_nullable
as bool, as bool,
loading: null == loading
? _value.loading
: loading // ignore: cast_nullable_to_non_nullable
as bool,
systemUiOverlayStyle: null == systemUiOverlayStyle
? _value.systemUiOverlayStyle
: systemUiOverlayStyle // ignore: cast_nullable_to_non_nullable
as SystemUiOverlayStyle,
) as $Val); ) as $Val);
} }
} }
@@ -212,17 +220,18 @@ abstract class _$$AppStateImplCopyWith<$Res>
Map<String, Map<String, int?>> delayMap, Map<String, Map<String, int?>> delayMap,
List<Group> groups, List<Group> groups,
int checkIpNum, int checkIpNum,
Brightness? brightness, Brightness brightness,
int? runTime, int? runTime,
List<ExternalProvider> providers, List<ExternalProvider> providers,
String? localIp, String? localIp,
FixedList<Connection> requests, FixedList<TrackerInfo> requests,
int version, int version,
FixedList<Log> logs, FixedList<Log> logs,
FixedList<Traffic> traffics, FixedList<Traffic> traffics,
Traffic totalTraffic, Traffic totalTraffic,
String proxiesQuery, bool realTunEnable,
bool realTunEnable}); bool loading,
SystemUiOverlayStyle systemUiOverlayStyle});
} }
/// @nodoc /// @nodoc
@@ -247,7 +256,7 @@ class __$$AppStateImplCopyWithImpl<$Res>
Object? delayMap = null, Object? delayMap = null,
Object? groups = null, Object? groups = null,
Object? checkIpNum = null, Object? checkIpNum = null,
Object? brightness = freezed, Object? brightness = null,
Object? runTime = freezed, Object? runTime = freezed,
Object? providers = null, Object? providers = null,
Object? localIp = freezed, Object? localIp = freezed,
@@ -256,8 +265,9 @@ class __$$AppStateImplCopyWithImpl<$Res>
Object? logs = null, Object? logs = null,
Object? traffics = null, Object? traffics = null,
Object? totalTraffic = null, Object? totalTraffic = null,
Object? proxiesQuery = null,
Object? realTunEnable = null, Object? realTunEnable = null,
Object? loading = null,
Object? systemUiOverlayStyle = null,
}) { }) {
return _then(_$AppStateImpl( return _then(_$AppStateImpl(
isInit: null == isInit isInit: null == isInit
@@ -296,10 +306,10 @@ class __$$AppStateImplCopyWithImpl<$Res>
? _value.checkIpNum ? _value.checkIpNum
: checkIpNum // ignore: cast_nullable_to_non_nullable : checkIpNum // ignore: cast_nullable_to_non_nullable
as int, as int,
brightness: freezed == brightness brightness: null == brightness
? _value.brightness ? _value.brightness
: brightness // ignore: cast_nullable_to_non_nullable : brightness // ignore: cast_nullable_to_non_nullable
as Brightness?, as Brightness,
runTime: freezed == runTime runTime: freezed == runTime
? _value.runTime ? _value.runTime
: runTime // ignore: cast_nullable_to_non_nullable : runTime // ignore: cast_nullable_to_non_nullable
@@ -315,7 +325,7 @@ class __$$AppStateImplCopyWithImpl<$Res>
requests: null == requests requests: null == requests
? _value.requests ? _value.requests
: requests // ignore: cast_nullable_to_non_nullable : requests // ignore: cast_nullable_to_non_nullable
as FixedList<Connection>, as FixedList<TrackerInfo>,
version: null == version version: null == version
? _value.version ? _value.version
: version // ignore: cast_nullable_to_non_nullable : version // ignore: cast_nullable_to_non_nullable
@@ -332,14 +342,18 @@ class __$$AppStateImplCopyWithImpl<$Res>
? _value.totalTraffic ? _value.totalTraffic
: totalTraffic // ignore: cast_nullable_to_non_nullable : totalTraffic // ignore: cast_nullable_to_non_nullable
as Traffic, as Traffic,
proxiesQuery: null == proxiesQuery
? _value.proxiesQuery
: proxiesQuery // ignore: cast_nullable_to_non_nullable
as String,
realTunEnable: null == realTunEnable realTunEnable: null == realTunEnable
? _value.realTunEnable ? _value.realTunEnable
: realTunEnable // ignore: cast_nullable_to_non_nullable : realTunEnable // ignore: cast_nullable_to_non_nullable
as bool, as bool,
loading: null == loading
? _value.loading
: loading // ignore: cast_nullable_to_non_nullable
as bool,
systemUiOverlayStyle: null == systemUiOverlayStyle
? _value.systemUiOverlayStyle
: systemUiOverlayStyle // ignore: cast_nullable_to_non_nullable
as SystemUiOverlayStyle,
)); ));
} }
} }
@@ -357,7 +371,7 @@ class _$AppStateImpl implements _AppState {
final Map<String, Map<String, int?>> delayMap = const {}, final Map<String, Map<String, int?>> delayMap = const {},
final List<Group> groups = const [], final List<Group> groups = const [],
this.checkIpNum = 0, this.checkIpNum = 0,
this.brightness, required this.brightness,
this.runTime, this.runTime,
final List<ExternalProvider> providers = const [], final List<ExternalProvider> providers = const [],
this.localIp, this.localIp,
@@ -366,8 +380,9 @@ class _$AppStateImpl implements _AppState {
required this.logs, required this.logs,
required this.traffics, required this.traffics,
required this.totalTraffic, required this.totalTraffic,
this.proxiesQuery = "", this.realTunEnable = false,
this.realTunEnable = false}) this.loading = false,
required this.systemUiOverlayStyle})
: _packages = packages, : _packages = packages,
_delayMap = delayMap, _delayMap = delayMap,
_groups = groups, _groups = groups,
@@ -418,7 +433,7 @@ class _$AppStateImpl implements _AppState {
@JsonKey() @JsonKey()
final int checkIpNum; final int checkIpNum;
@override @override
final Brightness? brightness; final Brightness brightness;
@override @override
final int? runTime; final int? runTime;
final List<ExternalProvider> _providers; final List<ExternalProvider> _providers;
@@ -433,7 +448,7 @@ class _$AppStateImpl implements _AppState {
@override @override
final String? localIp; final String? localIp;
@override @override
final FixedList<Connection> requests; final FixedList<TrackerInfo> requests;
@override @override
final int version; final int version;
@override @override
@@ -444,14 +459,16 @@ class _$AppStateImpl implements _AppState {
final Traffic totalTraffic; final Traffic totalTraffic;
@override @override
@JsonKey() @JsonKey()
final String proxiesQuery; final bool realTunEnable;
@override @override
@JsonKey() @JsonKey()
final bool realTunEnable; final bool loading;
@override
final SystemUiOverlayStyle systemUiOverlayStyle;
@override @override
String toString() { String toString() {
return 'AppState(isInit: $isInit, backBlock: $backBlock, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, proxiesQuery: $proxiesQuery, realTunEnable: $realTunEnable)'; return 'AppState(isInit: $isInit, backBlock: $backBlock, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, realTunEnable: $realTunEnable, loading: $loading, systemUiOverlayStyle: $systemUiOverlayStyle)';
} }
@override @override
@@ -486,10 +503,11 @@ class _$AppStateImpl implements _AppState {
other.traffics == traffics) && other.traffics == traffics) &&
(identical(other.totalTraffic, totalTraffic) || (identical(other.totalTraffic, totalTraffic) ||
other.totalTraffic == totalTraffic) && other.totalTraffic == totalTraffic) &&
(identical(other.proxiesQuery, proxiesQuery) ||
other.proxiesQuery == proxiesQuery) &&
(identical(other.realTunEnable, realTunEnable) || (identical(other.realTunEnable, realTunEnable) ||
other.realTunEnable == realTunEnable)); other.realTunEnable == realTunEnable) &&
(identical(other.loading, loading) || other.loading == loading) &&
(identical(other.systemUiOverlayStyle, systemUiOverlayStyle) ||
other.systemUiOverlayStyle == systemUiOverlayStyle));
} }
@override @override
@@ -513,8 +531,9 @@ class _$AppStateImpl implements _AppState {
logs, logs,
traffics, traffics,
totalTraffic, totalTraffic,
proxiesQuery, realTunEnable,
realTunEnable loading,
systemUiOverlayStyle
]); ]);
/// Create a copy of AppState /// Create a copy of AppState
@@ -528,26 +547,28 @@ class _$AppStateImpl implements _AppState {
abstract class _AppState implements AppState { abstract class _AppState implements AppState {
const factory _AppState( const factory _AppState(
{final bool isInit, {final bool isInit,
final bool backBlock, final bool backBlock,
final PageLabel pageLabel, final PageLabel pageLabel,
final List<Package> packages, final List<Package> packages,
final int sortNum, final int sortNum,
required final Size viewSize, required final Size viewSize,
final Map<String, Map<String, int?>> delayMap, final Map<String, Map<String, int?>> delayMap,
final List<Group> groups, final List<Group> groups,
final int checkIpNum, final int checkIpNum,
final Brightness? brightness, required final Brightness brightness,
final int? runTime, final int? runTime,
final List<ExternalProvider> providers, final List<ExternalProvider> providers,
final String? localIp, final String? localIp,
required final FixedList<Connection> requests, required final FixedList<TrackerInfo> requests,
required final int version, required final int version,
required final FixedList<Log> logs, required final FixedList<Log> logs,
required final FixedList<Traffic> traffics, required final FixedList<Traffic> traffics,
required final Traffic totalTraffic, required final Traffic totalTraffic,
final String proxiesQuery, final bool realTunEnable,
final bool realTunEnable}) = _$AppStateImpl; final bool loading,
required final SystemUiOverlayStyle systemUiOverlayStyle}) =
_$AppStateImpl;
@override @override
bool get isInit; bool get isInit;
@@ -568,7 +589,7 @@ abstract class _AppState implements AppState {
@override @override
int get checkIpNum; int get checkIpNum;
@override @override
Brightness? get brightness; Brightness get brightness;
@override @override
int? get runTime; int? get runTime;
@override @override
@@ -576,7 +597,7 @@ abstract class _AppState implements AppState {
@override @override
String? get localIp; String? get localIp;
@override @override
FixedList<Connection> get requests; FixedList<TrackerInfo> get requests;
@override @override
int get version; int get version;
@override @override
@@ -586,9 +607,11 @@ abstract class _AppState implements AppState {
@override @override
Traffic get totalTraffic; Traffic get totalTraffic;
@override @override
String get proxiesQuery;
@override
bool get realTunEnable; bool get realTunEnable;
@override
bool get loading;
@override
SystemUiOverlayStyle get systemUiOverlayStyle;
/// Create a copy of AppState /// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.

File diff suppressed because it is too large Load Diff

View File

@@ -138,7 +138,7 @@ _$TunImpl _$$TunImplFromJson(Map<String, dynamic> json) => _$TunImpl(
dnsHijack: (json['dns-hijack'] as List<dynamic>?) dnsHijack: (json['dns-hijack'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
const ["any:53"], const ['any:53'],
routeAddress: (json['route-address'] as List<dynamic>?) routeAddress: (json['route-address'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
@@ -163,19 +163,19 @@ const _$TunStackEnumMap = {
_$FallbackFilterImpl _$$FallbackFilterImplFromJson(Map<String, dynamic> json) => _$FallbackFilterImpl _$$FallbackFilterImplFromJson(Map<String, dynamic> json) =>
_$FallbackFilterImpl( _$FallbackFilterImpl(
geoip: json['geoip'] as bool? ?? true, geoip: json['geoip'] as bool? ?? true,
geoipCode: json['geoip-code'] as String? ?? "CN", geoipCode: json['geoip-code'] as String? ?? 'CN',
geosite: (json['geosite'] as List<dynamic>?) geosite: (json['geosite'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
const ["gfw"], const ['gfw'],
ipcidr: (json['ipcidr'] as List<dynamic>?) ipcidr: (json['ipcidr'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
const ["240.0.0.0/4"], const ['240.0.0.0/4'],
domain: (json['domain'] as List<dynamic>?) domain: (json['domain'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
const ["+.google.com", "+.facebook.com", "+.youtube.com"], const ['+.google.com', '+.facebook.com', '+.youtube.com'],
); );
Map<String, dynamic> _$$FallbackFilterImplToJson( Map<String, dynamic> _$$FallbackFilterImplToJson(
@@ -190,7 +190,7 @@ Map<String, dynamic> _$$FallbackFilterImplToJson(
_$DnsImpl _$$DnsImplFromJson(Map<String, dynamic> json) => _$DnsImpl( _$DnsImpl _$$DnsImplFromJson(Map<String, dynamic> json) => _$DnsImpl(
enable: json['enable'] as bool? ?? true, enable: json['enable'] as bool? ?? true,
listen: json['listen'] as String? ?? "0.0.0.0:1053", listen: json['listen'] as String? ?? '0.0.0.0:1053',
preferH3: json['prefer-h3'] as bool? ?? false, preferH3: json['prefer-h3'] as bool? ?? false,
useHosts: json['use-hosts'] as bool? ?? true, useHosts: json['use-hosts'] as bool? ?? true,
useSystemHosts: json['use-system-hosts'] as bool? ?? true, useSystemHosts: json['use-system-hosts'] as bool? ?? true,
@@ -199,39 +199,39 @@ _$DnsImpl _$$DnsImplFromJson(Map<String, dynamic> json) => _$DnsImpl(
defaultNameserver: (json['default-nameserver'] as List<dynamic>?) defaultNameserver: (json['default-nameserver'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
const ["223.5.5.5"], const ['223.5.5.5'],
enhancedMode: enhancedMode:
$enumDecodeNullable(_$DnsModeEnumMap, json['enhanced-mode']) ?? $enumDecodeNullable(_$DnsModeEnumMap, json['enhanced-mode']) ??
DnsMode.fakeIp, DnsMode.fakeIp,
fakeIpRange: json['fake-ip-range'] as String? ?? "198.18.0.1/16", fakeIpRange: json['fake-ip-range'] as String? ?? '198.18.0.1/16',
fakeIpFilter: (json['fake-ip-filter'] as List<dynamic>?) fakeIpFilter: (json['fake-ip-filter'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
const ["*.lan", "localhost.ptlogin2.qq.com"], const ['*.lan', 'localhost.ptlogin2.qq.com'],
nameserverPolicy: nameserverPolicy:
(json['nameserver-policy'] as Map<String, dynamic>?)?.map( (json['nameserver-policy'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(k, e as String), (k, e) => MapEntry(k, e as String),
) ?? ) ??
const { const {
"www.baidu.com": "114.114.114.114", 'www.baidu.com': '114.114.114.114',
"+.internal.crop.com": "10.0.0.1", '+.internal.crop.com': '10.0.0.1',
"geosite:cn": "https://doh.pub/dns-query" 'geosite:cn': 'https://doh.pub/dns-query'
}, },
nameserver: (json['nameserver'] as List<dynamic>?) nameserver: (json['nameserver'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
const [ const [
"https://doh.pub/dns-query", 'https://doh.pub/dns-query',
"https://dns.alidns.com/dns-query" 'https://dns.alidns.com/dns-query'
], ],
fallback: (json['fallback'] as List<dynamic>?) fallback: (json['fallback'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
const ["tls://8.8.4.4", "tls://1.1.1.1"], const ['tls://8.8.4.4', 'tls://1.1.1.1'],
proxyServerNameserver: (json['proxy-server-nameserver'] as List<dynamic>?) proxyServerNameserver: (json['proxy-server-nameserver'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??
const ["https://doh.pub/dns-query"], const ['https://doh.pub/dns-query'],
fallbackFilter: json['fallback-filter'] == null fallbackFilter: json['fallback-filter'] == null
? const FallbackFilter() ? const FallbackFilter()
: FallbackFilter.fromJson( : FallbackFilter.fromJson(
@@ -267,13 +267,13 @@ const _$DnsModeEnumMap = {
_$GeoXUrlImpl _$$GeoXUrlImplFromJson(Map<String, dynamic> json) => _$GeoXUrlImpl _$$GeoXUrlImplFromJson(Map<String, dynamic> json) =>
_$GeoXUrlImpl( _$GeoXUrlImpl(
mmdb: json['mmdb'] as String? ?? mmdb: json['mmdb'] as String? ??
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb", 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb',
asn: json['asn'] as String? ?? asn: json['asn'] as String? ??
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb", 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb',
geoip: json['geoip'] as String? ?? geoip: json['geoip'] as String? ??
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat", 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat',
geosite: json['geosite'] as String? ?? geosite: json['geosite'] as String? ??
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat", 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat',
); );
Map<String, dynamic> _$$GeoXUrlImplToJson(_$GeoXUrlImpl instance) => Map<String, dynamic> _$$GeoXUrlImplToJson(_$GeoXUrlImpl instance) =>
@@ -418,7 +418,6 @@ const _$LogLevelEnumMap = {
LogLevel.warning: 'warning', LogLevel.warning: 'warning',
LogLevel.error: 'error', LogLevel.error: 'error',
LogLevel.silent: 'silent', LogLevel.silent: 'silent',
LogLevel.app: 'app',
}; };
const _$FindProcessModeEnumMap = { const _$FindProcessModeEnumMap = {

File diff suppressed because it is too large Load Diff

View File

@@ -26,15 +26,29 @@ Map<String, dynamic> _$$PackageImplToJson(_$PackageImpl instance) =>
_$MetadataImpl _$$MetadataImplFromJson(Map<String, dynamic> json) => _$MetadataImpl _$$MetadataImplFromJson(Map<String, dynamic> json) =>
_$MetadataImpl( _$MetadataImpl(
uid: (json['uid'] as num).toInt(), uid: (json['uid'] as num?)?.toInt() ?? 0,
network: json['network'] as String, network: json['network'] as String? ?? '',
sourceIP: json['sourceIP'] as String, sourceIP: json['sourceIP'] as String? ?? '',
sourcePort: json['sourcePort'] as String, sourcePort: json['sourcePort'] as String? ?? '',
destinationIP: json['destinationIP'] as String, destinationIP: json['destinationIP'] as String? ?? '',
destinationPort: json['destinationPort'] as String, destinationPort: json['destinationPort'] as String? ?? '',
host: json['host'] as String, host: json['host'] as String? ?? '',
process: json['process'] as String, dnsMode: $enumDecodeNullable(_$DnsModeEnumMap, json['dnsMode']),
remoteDestination: json['remoteDestination'] as String, process: json['process'] as String? ?? '',
processPath: json['processPath'] as String? ?? '',
remoteDestination: json['remoteDestination'] as String? ?? '',
sourceGeoIP: (json['sourceGeoIP'] as List<dynamic>?)
?.map((e) => e as String)
.toList() ??
const [],
destinationGeoIP: (json['destinationGeoIP'] as List<dynamic>?)
?.map((e) => e as String)
.toList() ??
const [],
destinationIPASN: json['destinationIPASN'] as String? ?? '',
sourceIPASN: json['sourceIPASN'] as String? ?? '',
specialRules: json['specialRules'] as String? ?? '',
specialProxy: json['specialProxy'] as String? ?? '',
); );
Map<String, dynamic> _$$MetadataImplToJson(_$MetadataImpl instance) => Map<String, dynamic> _$$MetadataImplToJson(_$MetadataImpl instance) =>
@@ -46,22 +60,41 @@ Map<String, dynamic> _$$MetadataImplToJson(_$MetadataImpl instance) =>
'destinationIP': instance.destinationIP, 'destinationIP': instance.destinationIP,
'destinationPort': instance.destinationPort, 'destinationPort': instance.destinationPort,
'host': instance.host, 'host': instance.host,
'dnsMode': _$DnsModeEnumMap[instance.dnsMode],
'process': instance.process, 'process': instance.process,
'processPath': instance.processPath,
'remoteDestination': instance.remoteDestination, 'remoteDestination': instance.remoteDestination,
'sourceGeoIP': instance.sourceGeoIP,
'destinationGeoIP': instance.destinationGeoIP,
'destinationIPASN': instance.destinationIPASN,
'sourceIPASN': instance.sourceIPASN,
'specialRules': instance.specialRules,
'specialProxy': instance.specialProxy,
}; };
_$ConnectionImpl _$$ConnectionImplFromJson(Map<String, dynamic> json) => const _$DnsModeEnumMap = {
_$ConnectionImpl( DnsMode.normal: 'normal',
DnsMode.fakeIp: 'fake-ip',
DnsMode.redirHost: 'redir-host',
DnsMode.hosts: 'hosts',
};
_$TrackerInfoImpl _$$TrackerInfoImplFromJson(Map<String, dynamic> json) =>
_$TrackerInfoImpl(
id: json['id'] as String, id: json['id'] as String,
upload: json['upload'] as num?, upload: (json['upload'] as num?)?.toInt() ?? 0,
download: json['download'] as num?, download: (json['download'] as num?)?.toInt() ?? 0,
start: DateTime.parse(json['start'] as String), start: DateTime.parse(json['start'] as String),
metadata: Metadata.fromJson(json['metadata'] as Map<String, dynamic>), metadata: Metadata.fromJson(json['metadata'] as Map<String, dynamic>),
chains: chains:
(json['chains'] as List<dynamic>).map((e) => e as String).toList(), (json['chains'] as List<dynamic>).map((e) => e as String).toList(),
rule: json['rule'] as String,
rulePayload: json['rulePayload'] as String,
downloadSpeed: (json['downloadSpeed'] as num?)?.toInt(),
uploadSpeed: (json['uploadSpeed'] as num?)?.toInt(),
); );
Map<String, dynamic> _$$ConnectionImplToJson(_$ConnectionImpl instance) => Map<String, dynamic> _$$TrackerInfoImplToJson(_$TrackerInfoImpl instance) =>
<String, dynamic>{ <String, dynamic>{
'id': instance.id, 'id': instance.id,
'upload': instance.upload, 'upload': instance.upload,
@@ -69,12 +102,16 @@ Map<String, dynamic> _$$ConnectionImplToJson(_$ConnectionImpl instance) =>
'start': instance.start.toIso8601String(), 'start': instance.start.toIso8601String(),
'metadata': instance.metadata, 'metadata': instance.metadata,
'chains': instance.chains, 'chains': instance.chains,
'rule': instance.rule,
'rulePayload': instance.rulePayload,
'downloadSpeed': instance.downloadSpeed,
'uploadSpeed': instance.uploadSpeed,
}; };
_$LogImpl _$$LogImplFromJson(Map<String, dynamic> json) => _$LogImpl( _$LogImpl _$$LogImplFromJson(Map<String, dynamic> json) => _$LogImpl(
logLevel: $enumDecodeNullable(_$LogLevelEnumMap, json['LogLevel']) ?? logLevel: $enumDecodeNullable(_$LogLevelEnumMap, json['LogLevel']) ??
LogLevel.app, LogLevel.info,
payload: json['Payload'] as String? ?? "", payload: json['Payload'] as String? ?? '',
dateTime: _logDateTime(json['dateTime']), dateTime: _logDateTime(json['dateTime']),
); );
@@ -90,7 +127,6 @@ const _$LogLevelEnumMap = {
LogLevel.warning: 'warning', LogLevel.warning: 'warning',
LogLevel.error: 'error', LogLevel.error: 'error',
LogLevel.silent: 'silent', LogLevel.silent: 'silent',
LogLevel.app: 'app',
}; };
_$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl( _$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl(
@@ -109,8 +145,8 @@ Map<String, dynamic> _$$DAVImplToJson(_$DAVImpl instance) => <String, dynamic>{
_$VersionInfoImpl _$$VersionInfoImplFromJson(Map<String, dynamic> json) => _$VersionInfoImpl _$$VersionInfoImplFromJson(Map<String, dynamic> json) =>
_$VersionInfoImpl( _$VersionInfoImpl(
clashName: json['clashName'] as String? ?? "", clashName: json['clashName'] as String? ?? '',
version: json['version'] as String? ?? "", version: json['version'] as String? ?? '',
); );
Map<String, dynamic> _$$VersionInfoImplToJson(_$VersionInfoImpl instance) => Map<String, dynamic> _$$VersionInfoImplToJson(_$VersionInfoImpl instance) =>
@@ -141,7 +177,7 @@ _$GroupImpl _$$GroupImplFromJson(Map<String, dynamic> json) => _$GroupImpl(
now: json['now'] as String?, now: json['now'] as String?,
hidden: json['hidden'] as bool?, hidden: json['hidden'] as bool?,
testUrl: json['testUrl'] as String?, testUrl: json['testUrl'] as String?,
icon: json['icon'] as String? ?? "", icon: json['icon'] as String? ?? '',
name: json['name'] as String, name: json['name'] as String,
); );

View File

@@ -1824,8 +1824,8 @@ TextScale _$TextScaleFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$TextScale { mixin _$TextScale {
dynamic get enable => throw _privateConstructorUsedError; bool get enable => throw _privateConstructorUsedError;
dynamic get scale => throw _privateConstructorUsedError; double get scale => throw _privateConstructorUsedError;
/// Serializes this TextScale to a JSON map. /// Serializes this TextScale to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@@ -1842,7 +1842,7 @@ abstract class $TextScaleCopyWith<$Res> {
factory $TextScaleCopyWith(TextScale value, $Res Function(TextScale) then) = factory $TextScaleCopyWith(TextScale value, $Res Function(TextScale) then) =
_$TextScaleCopyWithImpl<$Res, TextScale>; _$TextScaleCopyWithImpl<$Res, TextScale>;
@useResult @useResult
$Res call({dynamic enable, dynamic scale}); $Res call({bool enable, double scale});
} }
/// @nodoc /// @nodoc
@@ -1860,18 +1860,18 @@ class _$TextScaleCopyWithImpl<$Res, $Val extends TextScale>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? enable = freezed, Object? enable = null,
Object? scale = freezed, Object? scale = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
enable: freezed == enable enable: null == enable
? _value.enable ? _value.enable
: enable // ignore: cast_nullable_to_non_nullable : enable // ignore: cast_nullable_to_non_nullable
as dynamic, as bool,
scale: freezed == scale scale: null == scale
? _value.scale ? _value.scale
: scale // ignore: cast_nullable_to_non_nullable : scale // ignore: cast_nullable_to_non_nullable
as dynamic, as double,
) as $Val); ) as $Val);
} }
} }
@@ -1884,7 +1884,7 @@ abstract class _$$TextScaleImplCopyWith<$Res>
__$$TextScaleImplCopyWithImpl<$Res>; __$$TextScaleImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({dynamic enable, dynamic scale}); $Res call({bool enable, double scale});
} }
/// @nodoc /// @nodoc
@@ -1900,12 +1900,18 @@ class __$$TextScaleImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? enable = freezed, Object? enable = null,
Object? scale = freezed, Object? scale = null,
}) { }) {
return _then(_$TextScaleImpl( return _then(_$TextScaleImpl(
enable: freezed == enable ? _value.enable! : enable, enable: null == enable
scale: freezed == scale ? _value.scale! : scale, ? _value.enable
: enable // ignore: cast_nullable_to_non_nullable
as bool,
scale: null == scale
? _value.scale
: scale // ignore: cast_nullable_to_non_nullable
as double,
)); ));
} }
} }
@@ -1920,10 +1926,10 @@ class _$TextScaleImpl implements _TextScale {
@override @override
@JsonKey() @JsonKey()
final dynamic enable; final bool enable;
@override @override
@JsonKey() @JsonKey()
final dynamic scale; final double scale;
@override @override
String toString() { String toString() {
@@ -1935,16 +1941,13 @@ class _$TextScaleImpl implements _TextScale {
return identical(this, other) || return identical(this, other) ||
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$TextScaleImpl && other is _$TextScaleImpl &&
const DeepCollectionEquality().equals(other.enable, enable) && (identical(other.enable, enable) || other.enable == enable) &&
const DeepCollectionEquality().equals(other.scale, scale)); (identical(other.scale, scale) || other.scale == scale));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash( int get hashCode => Object.hash(runtimeType, enable, scale);
runtimeType,
const DeepCollectionEquality().hash(enable),
const DeepCollectionEquality().hash(scale));
/// Create a copy of TextScale /// Create a copy of TextScale
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -1963,16 +1966,16 @@ class _$TextScaleImpl implements _TextScale {
} }
abstract class _TextScale implements TextScale { abstract class _TextScale implements TextScale {
const factory _TextScale({final dynamic enable, final dynamic scale}) = const factory _TextScale({final bool enable, final double scale}) =
_$TextScaleImpl; _$TextScaleImpl;
factory _TextScale.fromJson(Map<String, dynamic> json) = factory _TextScale.fromJson(Map<String, dynamic> json) =
_$TextScaleImpl.fromJson; _$TextScaleImpl.fromJson;
@override @override
dynamic get enable; bool get enable;
@override @override
dynamic get scale; double get scale;
/// Create a copy of TextScale /// Create a copy of TextScale
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.

View File

@@ -238,8 +238,8 @@ const _$ProxyCardTypeEnumMap = {
_$TextScaleImpl _$$TextScaleImplFromJson(Map<String, dynamic> json) => _$TextScaleImpl _$$TextScaleImplFromJson(Map<String, dynamic> json) =>
_$TextScaleImpl( _$TextScaleImpl(
enable: json['enable'] ?? false, enable: json['enable'] as bool? ?? false,
scale: json['scale'] ?? 1.0, scale: (json['scale'] as num?)?.toDouble() ?? 1.0,
); );
Map<String, dynamic> _$$TextScaleImplToJson(_$TextScaleImpl instance) => Map<String, dynamic> _$$TextScaleImplToJson(_$TextScaleImpl instance) =>

View File

@@ -20,11 +20,11 @@ SetupParams _$SetupParamsFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$SetupParams { mixin _$SetupParams {
@JsonKey(name: "config") @JsonKey(name: 'config')
Map<String, dynamic> get config => throw _privateConstructorUsedError; Map<String, dynamic> get config => throw _privateConstructorUsedError;
@JsonKey(name: "selected-map") @JsonKey(name: 'selected-map')
Map<String, String> get selectedMap => throw _privateConstructorUsedError; Map<String, String> get selectedMap => throw _privateConstructorUsedError;
@JsonKey(name: "test-url") @JsonKey(name: 'test-url')
String get testUrl => throw _privateConstructorUsedError; String get testUrl => throw _privateConstructorUsedError;
/// Serializes this SetupParams to a JSON map. /// Serializes this SetupParams to a JSON map.
@@ -44,9 +44,9 @@ abstract class $SetupParamsCopyWith<$Res> {
_$SetupParamsCopyWithImpl<$Res, SetupParams>; _$SetupParamsCopyWithImpl<$Res, SetupParams>;
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "config") Map<String, dynamic> config, {@JsonKey(name: 'config') Map<String, dynamic> config,
@JsonKey(name: "selected-map") Map<String, String> selectedMap, @JsonKey(name: 'selected-map') Map<String, String> selectedMap,
@JsonKey(name: "test-url") String testUrl}); @JsonKey(name: 'test-url') String testUrl});
} }
/// @nodoc /// @nodoc
@@ -94,9 +94,9 @@ abstract class _$$SetupParamsImplCopyWith<$Res>
@override @override
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "config") Map<String, dynamic> config, {@JsonKey(name: 'config') Map<String, dynamic> config,
@JsonKey(name: "selected-map") Map<String, String> selectedMap, @JsonKey(name: 'selected-map') Map<String, String> selectedMap,
@JsonKey(name: "test-url") String testUrl}); @JsonKey(name: 'test-url') String testUrl});
} }
/// @nodoc /// @nodoc
@@ -137,10 +137,10 @@ class __$$SetupParamsImplCopyWithImpl<$Res>
@JsonSerializable() @JsonSerializable()
class _$SetupParamsImpl implements _SetupParams { class _$SetupParamsImpl implements _SetupParams {
const _$SetupParamsImpl( const _$SetupParamsImpl(
{@JsonKey(name: "config") required final Map<String, dynamic> config, {@JsonKey(name: 'config') required final Map<String, dynamic> config,
@JsonKey(name: "selected-map") @JsonKey(name: 'selected-map')
required final Map<String, String> selectedMap, required final Map<String, String> selectedMap,
@JsonKey(name: "test-url") required this.testUrl}) @JsonKey(name: 'test-url') required this.testUrl})
: _config = config, : _config = config,
_selectedMap = selectedMap; _selectedMap = selectedMap;
@@ -149,7 +149,7 @@ class _$SetupParamsImpl implements _SetupParams {
final Map<String, dynamic> _config; final Map<String, dynamic> _config;
@override @override
@JsonKey(name: "config") @JsonKey(name: 'config')
Map<String, dynamic> get config { Map<String, dynamic> get config {
if (_config is EqualUnmodifiableMapView) return _config; if (_config is EqualUnmodifiableMapView) return _config;
// ignore: implicit_dynamic_type // ignore: implicit_dynamic_type
@@ -158,7 +158,7 @@ class _$SetupParamsImpl implements _SetupParams {
final Map<String, String> _selectedMap; final Map<String, String> _selectedMap;
@override @override
@JsonKey(name: "selected-map") @JsonKey(name: 'selected-map')
Map<String, String> get selectedMap { Map<String, String> get selectedMap {
if (_selectedMap is EqualUnmodifiableMapView) return _selectedMap; if (_selectedMap is EqualUnmodifiableMapView) return _selectedMap;
// ignore: implicit_dynamic_type // ignore: implicit_dynamic_type
@@ -166,7 +166,7 @@ class _$SetupParamsImpl implements _SetupParams {
} }
@override @override
@JsonKey(name: "test-url") @JsonKey(name: 'test-url')
final String testUrl; final String testUrl;
@override @override
@@ -211,23 +211,23 @@ class _$SetupParamsImpl implements _SetupParams {
abstract class _SetupParams implements SetupParams { abstract class _SetupParams implements SetupParams {
const factory _SetupParams( const factory _SetupParams(
{@JsonKey(name: "config") required final Map<String, dynamic> config, {@JsonKey(name: 'config') required final Map<String, dynamic> config,
@JsonKey(name: "selected-map") @JsonKey(name: 'selected-map')
required final Map<String, String> selectedMap, required final Map<String, String> selectedMap,
@JsonKey(name: "test-url") required final String testUrl}) = @JsonKey(name: 'test-url') required final String testUrl}) =
_$SetupParamsImpl; _$SetupParamsImpl;
factory _SetupParams.fromJson(Map<String, dynamic> json) = factory _SetupParams.fromJson(Map<String, dynamic> json) =
_$SetupParamsImpl.fromJson; _$SetupParamsImpl.fromJson;
@override @override
@JsonKey(name: "config") @JsonKey(name: 'config')
Map<String, dynamic> get config; Map<String, dynamic> get config;
@override @override
@JsonKey(name: "selected-map") @JsonKey(name: 'selected-map')
Map<String, String> get selectedMap; Map<String, String> get selectedMap;
@override @override
@JsonKey(name: "test-url") @JsonKey(name: 'test-url')
String get testUrl; String get testUrl;
/// Create a copy of SetupParams /// Create a copy of SetupParams
@@ -637,13 +637,13 @@ CoreState _$CoreStateFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$CoreState { mixin _$CoreState {
@JsonKey(name: "vpn-props") @JsonKey(name: 'vpn-props')
VpnProps get vpnProps => throw _privateConstructorUsedError; VpnProps get vpnProps => throw _privateConstructorUsedError;
@JsonKey(name: "only-statistics-proxy") @JsonKey(name: 'only-statistics-proxy')
bool get onlyStatisticsProxy => throw _privateConstructorUsedError; bool get onlyStatisticsProxy => throw _privateConstructorUsedError;
@JsonKey(name: "current-profile-name") @JsonKey(name: 'current-profile-name')
String get currentProfileName => throw _privateConstructorUsedError; String get currentProfileName => throw _privateConstructorUsedError;
@JsonKey(name: "bypass-domain") @JsonKey(name: 'bypass-domain')
List<String> get bypassDomain => throw _privateConstructorUsedError; List<String> get bypassDomain => throw _privateConstructorUsedError;
/// Serializes this CoreState to a JSON map. /// Serializes this CoreState to a JSON map.
@@ -662,10 +662,10 @@ abstract class $CoreStateCopyWith<$Res> {
_$CoreStateCopyWithImpl<$Res, CoreState>; _$CoreStateCopyWithImpl<$Res, CoreState>;
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "vpn-props") VpnProps vpnProps, {@JsonKey(name: 'vpn-props') VpnProps vpnProps,
@JsonKey(name: "only-statistics-proxy") bool onlyStatisticsProxy, @JsonKey(name: 'only-statistics-proxy') bool onlyStatisticsProxy,
@JsonKey(name: "current-profile-name") String currentProfileName, @JsonKey(name: 'current-profile-name') String currentProfileName,
@JsonKey(name: "bypass-domain") List<String> bypassDomain}); @JsonKey(name: 'bypass-domain') List<String> bypassDomain});
$VpnPropsCopyWith<$Res> get vpnProps; $VpnPropsCopyWith<$Res> get vpnProps;
} }
@@ -730,10 +730,10 @@ abstract class _$$CoreStateImplCopyWith<$Res>
@override @override
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "vpn-props") VpnProps vpnProps, {@JsonKey(name: 'vpn-props') VpnProps vpnProps,
@JsonKey(name: "only-statistics-proxy") bool onlyStatisticsProxy, @JsonKey(name: 'only-statistics-proxy') bool onlyStatisticsProxy,
@JsonKey(name: "current-profile-name") String currentProfileName, @JsonKey(name: 'current-profile-name') String currentProfileName,
@JsonKey(name: "bypass-domain") List<String> bypassDomain}); @JsonKey(name: 'bypass-domain') List<String> bypassDomain});
@override @override
$VpnPropsCopyWith<$Res> get vpnProps; $VpnPropsCopyWith<$Res> get vpnProps;
@@ -782,10 +782,10 @@ class __$$CoreStateImplCopyWithImpl<$Res>
@JsonSerializable() @JsonSerializable()
class _$CoreStateImpl implements _CoreState { class _$CoreStateImpl implements _CoreState {
const _$CoreStateImpl( const _$CoreStateImpl(
{@JsonKey(name: "vpn-props") required this.vpnProps, {@JsonKey(name: 'vpn-props') required this.vpnProps,
@JsonKey(name: "only-statistics-proxy") required this.onlyStatisticsProxy, @JsonKey(name: 'only-statistics-proxy') required this.onlyStatisticsProxy,
@JsonKey(name: "current-profile-name") required this.currentProfileName, @JsonKey(name: 'current-profile-name') required this.currentProfileName,
@JsonKey(name: "bypass-domain") @JsonKey(name: 'bypass-domain')
final List<String> bypassDomain = const []}) final List<String> bypassDomain = const []})
: _bypassDomain = bypassDomain; : _bypassDomain = bypassDomain;
@@ -793,17 +793,17 @@ class _$CoreStateImpl implements _CoreState {
_$$CoreStateImplFromJson(json); _$$CoreStateImplFromJson(json);
@override @override
@JsonKey(name: "vpn-props") @JsonKey(name: 'vpn-props')
final VpnProps vpnProps; final VpnProps vpnProps;
@override @override
@JsonKey(name: "only-statistics-proxy") @JsonKey(name: 'only-statistics-proxy')
final bool onlyStatisticsProxy; final bool onlyStatisticsProxy;
@override @override
@JsonKey(name: "current-profile-name") @JsonKey(name: 'current-profile-name')
final String currentProfileName; final String currentProfileName;
final List<String> _bypassDomain; final List<String> _bypassDomain;
@override @override
@JsonKey(name: "bypass-domain") @JsonKey(name: 'bypass-domain')
List<String> get bypassDomain { List<String> get bypassDomain {
if (_bypassDomain is EqualUnmodifiableListView) return _bypassDomain; if (_bypassDomain is EqualUnmodifiableListView) return _bypassDomain;
// ignore: implicit_dynamic_type // ignore: implicit_dynamic_type
@@ -853,28 +853,28 @@ class _$CoreStateImpl implements _CoreState {
abstract class _CoreState implements CoreState { abstract class _CoreState implements CoreState {
const factory _CoreState( const factory _CoreState(
{@JsonKey(name: "vpn-props") required final VpnProps vpnProps, {@JsonKey(name: 'vpn-props') required final VpnProps vpnProps,
@JsonKey(name: "only-statistics-proxy") @JsonKey(name: 'only-statistics-proxy')
required final bool onlyStatisticsProxy, required final bool onlyStatisticsProxy,
@JsonKey(name: "current-profile-name") @JsonKey(name: 'current-profile-name')
required final String currentProfileName, required final String currentProfileName,
@JsonKey(name: "bypass-domain") final List<String> bypassDomain}) = @JsonKey(name: 'bypass-domain') final List<String> bypassDomain}) =
_$CoreStateImpl; _$CoreStateImpl;
factory _CoreState.fromJson(Map<String, dynamic> json) = factory _CoreState.fromJson(Map<String, dynamic> json) =
_$CoreStateImpl.fromJson; _$CoreStateImpl.fromJson;
@override @override
@JsonKey(name: "vpn-props") @JsonKey(name: 'vpn-props')
VpnProps get vpnProps; VpnProps get vpnProps;
@override @override
@JsonKey(name: "only-statistics-proxy") @JsonKey(name: 'only-statistics-proxy')
bool get onlyStatisticsProxy; bool get onlyStatisticsProxy;
@override @override
@JsonKey(name: "current-profile-name") @JsonKey(name: 'current-profile-name')
String get currentProfileName; String get currentProfileName;
@override @override
@JsonKey(name: "bypass-domain") @JsonKey(name: 'bypass-domain')
List<String> get bypassDomain; List<String> get bypassDomain;
/// Create a copy of CoreState /// Create a copy of CoreState
@@ -1278,7 +1278,7 @@ InitParams _$InitParamsFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$InitParams { mixin _$InitParams {
@JsonKey(name: "home-dir") @JsonKey(name: 'home-dir')
String get homeDir => throw _privateConstructorUsedError; String get homeDir => throw _privateConstructorUsedError;
int get version => throw _privateConstructorUsedError; int get version => throw _privateConstructorUsedError;
@@ -1298,7 +1298,7 @@ abstract class $InitParamsCopyWith<$Res> {
InitParams value, $Res Function(InitParams) then) = InitParams value, $Res Function(InitParams) then) =
_$InitParamsCopyWithImpl<$Res, InitParams>; _$InitParamsCopyWithImpl<$Res, InitParams>;
@useResult @useResult
$Res call({@JsonKey(name: "home-dir") String homeDir, int version}); $Res call({@JsonKey(name: 'home-dir') String homeDir, int version});
} }
/// @nodoc /// @nodoc
@@ -1340,7 +1340,7 @@ abstract class _$$InitParamsImplCopyWith<$Res>
__$$InitParamsImplCopyWithImpl<$Res>; __$$InitParamsImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({@JsonKey(name: "home-dir") String homeDir, int version}); $Res call({@JsonKey(name: 'home-dir') String homeDir, int version});
} }
/// @nodoc /// @nodoc
@@ -1376,14 +1376,14 @@ class __$$InitParamsImplCopyWithImpl<$Res>
@JsonSerializable() @JsonSerializable()
class _$InitParamsImpl implements _InitParams { class _$InitParamsImpl implements _InitParams {
const _$InitParamsImpl( const _$InitParamsImpl(
{@JsonKey(name: "home-dir") required this.homeDir, {@JsonKey(name: 'home-dir') required this.homeDir,
required this.version}); required this.version});
factory _$InitParamsImpl.fromJson(Map<String, dynamic> json) => factory _$InitParamsImpl.fromJson(Map<String, dynamic> json) =>
_$$InitParamsImplFromJson(json); _$$InitParamsImplFromJson(json);
@override @override
@JsonKey(name: "home-dir") @JsonKey(name: 'home-dir')
final String homeDir; final String homeDir;
@override @override
final int version; final int version;
@@ -1424,14 +1424,14 @@ class _$InitParamsImpl implements _InitParams {
abstract class _InitParams implements InitParams { abstract class _InitParams implements InitParams {
const factory _InitParams( const factory _InitParams(
{@JsonKey(name: "home-dir") required final String homeDir, {@JsonKey(name: 'home-dir') required final String homeDir,
required final int version}) = _$InitParamsImpl; required final int version}) = _$InitParamsImpl;
factory _InitParams.fromJson(Map<String, dynamic> json) = factory _InitParams.fromJson(Map<String, dynamic> json) =
_$InitParamsImpl.fromJson; _$InitParamsImpl.fromJson;
@override @override
@JsonKey(name: "home-dir") @JsonKey(name: 'home-dir')
String get homeDir; String get homeDir;
@override @override
int get version; int get version;
@@ -1450,9 +1450,9 @@ ChangeProxyParams _$ChangeProxyParamsFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$ChangeProxyParams { mixin _$ChangeProxyParams {
@JsonKey(name: "group-name") @JsonKey(name: 'group-name')
String get groupName => throw _privateConstructorUsedError; String get groupName => throw _privateConstructorUsedError;
@JsonKey(name: "proxy-name") @JsonKey(name: 'proxy-name')
String get proxyName => throw _privateConstructorUsedError; String get proxyName => throw _privateConstructorUsedError;
/// Serializes this ChangeProxyParams to a JSON map. /// Serializes this ChangeProxyParams to a JSON map.
@@ -1472,8 +1472,8 @@ abstract class $ChangeProxyParamsCopyWith<$Res> {
_$ChangeProxyParamsCopyWithImpl<$Res, ChangeProxyParams>; _$ChangeProxyParamsCopyWithImpl<$Res, ChangeProxyParams>;
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "group-name") String groupName, {@JsonKey(name: 'group-name') String groupName,
@JsonKey(name: "proxy-name") String proxyName}); @JsonKey(name: 'proxy-name') String proxyName});
} }
/// @nodoc /// @nodoc
@@ -1516,8 +1516,8 @@ abstract class _$$ChangeProxyParamsImplCopyWith<$Res>
@override @override
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "group-name") String groupName, {@JsonKey(name: 'group-name') String groupName,
@JsonKey(name: "proxy-name") String proxyName}); @JsonKey(name: 'proxy-name') String proxyName});
} }
/// @nodoc /// @nodoc
@@ -1553,17 +1553,17 @@ class __$$ChangeProxyParamsImplCopyWithImpl<$Res>
@JsonSerializable() @JsonSerializable()
class _$ChangeProxyParamsImpl implements _ChangeProxyParams { class _$ChangeProxyParamsImpl implements _ChangeProxyParams {
const _$ChangeProxyParamsImpl( const _$ChangeProxyParamsImpl(
{@JsonKey(name: "group-name") required this.groupName, {@JsonKey(name: 'group-name') required this.groupName,
@JsonKey(name: "proxy-name") required this.proxyName}); @JsonKey(name: 'proxy-name') required this.proxyName});
factory _$ChangeProxyParamsImpl.fromJson(Map<String, dynamic> json) => factory _$ChangeProxyParamsImpl.fromJson(Map<String, dynamic> json) =>
_$$ChangeProxyParamsImplFromJson(json); _$$ChangeProxyParamsImplFromJson(json);
@override @override
@JsonKey(name: "group-name") @JsonKey(name: 'group-name')
final String groupName; final String groupName;
@override @override
@JsonKey(name: "proxy-name") @JsonKey(name: 'proxy-name')
final String proxyName; final String proxyName;
@override @override
@@ -1605,18 +1605,18 @@ class _$ChangeProxyParamsImpl implements _ChangeProxyParams {
abstract class _ChangeProxyParams implements ChangeProxyParams { abstract class _ChangeProxyParams implements ChangeProxyParams {
const factory _ChangeProxyParams( const factory _ChangeProxyParams(
{@JsonKey(name: "group-name") required final String groupName, {@JsonKey(name: 'group-name') required final String groupName,
@JsonKey(name: "proxy-name") required final String proxyName}) = @JsonKey(name: 'proxy-name') required final String proxyName}) =
_$ChangeProxyParamsImpl; _$ChangeProxyParamsImpl;
factory _ChangeProxyParams.fromJson(Map<String, dynamic> json) = factory _ChangeProxyParams.fromJson(Map<String, dynamic> json) =
_$ChangeProxyParamsImpl.fromJson; _$ChangeProxyParamsImpl.fromJson;
@override @override
@JsonKey(name: "group-name") @JsonKey(name: 'group-name')
String get groupName; String get groupName;
@override @override
@JsonKey(name: "proxy-name") @JsonKey(name: 'proxy-name')
String get proxyName; String get proxyName;
/// Create a copy of ChangeProxyParams /// Create a copy of ChangeProxyParams
@@ -1633,9 +1633,9 @@ UpdateGeoDataParams _$UpdateGeoDataParamsFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$UpdateGeoDataParams { mixin _$UpdateGeoDataParams {
@JsonKey(name: "geo-type") @JsonKey(name: 'geo-type')
String get geoType => throw _privateConstructorUsedError; String get geoType => throw _privateConstructorUsedError;
@JsonKey(name: "geo-name") @JsonKey(name: 'geo-name')
String get geoName => throw _privateConstructorUsedError; String get geoName => throw _privateConstructorUsedError;
/// Serializes this UpdateGeoDataParams to a JSON map. /// Serializes this UpdateGeoDataParams to a JSON map.
@@ -1655,8 +1655,8 @@ abstract class $UpdateGeoDataParamsCopyWith<$Res> {
_$UpdateGeoDataParamsCopyWithImpl<$Res, UpdateGeoDataParams>; _$UpdateGeoDataParamsCopyWithImpl<$Res, UpdateGeoDataParams>;
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "geo-type") String geoType, {@JsonKey(name: 'geo-type') String geoType,
@JsonKey(name: "geo-name") String geoName}); @JsonKey(name: 'geo-name') String geoName});
} }
/// @nodoc /// @nodoc
@@ -1699,8 +1699,8 @@ abstract class _$$UpdateGeoDataParamsImplCopyWith<$Res>
@override @override
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "geo-type") String geoType, {@JsonKey(name: 'geo-type') String geoType,
@JsonKey(name: "geo-name") String geoName}); @JsonKey(name: 'geo-name') String geoName});
} }
/// @nodoc /// @nodoc
@@ -1736,17 +1736,17 @@ class __$$UpdateGeoDataParamsImplCopyWithImpl<$Res>
@JsonSerializable() @JsonSerializable()
class _$UpdateGeoDataParamsImpl implements _UpdateGeoDataParams { class _$UpdateGeoDataParamsImpl implements _UpdateGeoDataParams {
const _$UpdateGeoDataParamsImpl( const _$UpdateGeoDataParamsImpl(
{@JsonKey(name: "geo-type") required this.geoType, {@JsonKey(name: 'geo-type') required this.geoType,
@JsonKey(name: "geo-name") required this.geoName}); @JsonKey(name: 'geo-name') required this.geoName});
factory _$UpdateGeoDataParamsImpl.fromJson(Map<String, dynamic> json) => factory _$UpdateGeoDataParamsImpl.fromJson(Map<String, dynamic> json) =>
_$$UpdateGeoDataParamsImplFromJson(json); _$$UpdateGeoDataParamsImplFromJson(json);
@override @override
@JsonKey(name: "geo-type") @JsonKey(name: 'geo-type')
final String geoType; final String geoType;
@override @override
@JsonKey(name: "geo-name") @JsonKey(name: 'geo-name')
final String geoName; final String geoName;
@override @override
@@ -1786,18 +1786,18 @@ class _$UpdateGeoDataParamsImpl implements _UpdateGeoDataParams {
abstract class _UpdateGeoDataParams implements UpdateGeoDataParams { abstract class _UpdateGeoDataParams implements UpdateGeoDataParams {
const factory _UpdateGeoDataParams( const factory _UpdateGeoDataParams(
{@JsonKey(name: "geo-type") required final String geoType, {@JsonKey(name: 'geo-type') required final String geoType,
@JsonKey(name: "geo-name") required final String geoName}) = @JsonKey(name: 'geo-name') required final String geoName}) =
_$UpdateGeoDataParamsImpl; _$UpdateGeoDataParamsImpl;
factory _UpdateGeoDataParams.fromJson(Map<String, dynamic> json) = factory _UpdateGeoDataParams.fromJson(Map<String, dynamic> json) =
_$UpdateGeoDataParamsImpl.fromJson; _$UpdateGeoDataParamsImpl.fromJson;
@override @override
@JsonKey(name: "geo-type") @JsonKey(name: 'geo-type')
String get geoType; String get geoType;
@override @override
@JsonKey(name: "geo-name") @JsonKey(name: 'geo-name')
String get geoName; String get geoName;
/// Create a copy of UpdateGeoDataParams /// Create a copy of UpdateGeoDataParams
@@ -2489,13 +2489,13 @@ ProviderSubscriptionInfo _$ProviderSubscriptionInfoFromJson(
/// @nodoc /// @nodoc
mixin _$ProviderSubscriptionInfo { mixin _$ProviderSubscriptionInfo {
@JsonKey(name: "UPLOAD") @JsonKey(name: 'UPLOAD')
int get upload => throw _privateConstructorUsedError; int get upload => throw _privateConstructorUsedError;
@JsonKey(name: "DOWNLOAD") @JsonKey(name: 'DOWNLOAD')
int get download => throw _privateConstructorUsedError; int get download => throw _privateConstructorUsedError;
@JsonKey(name: "TOTAL") @JsonKey(name: 'TOTAL')
int get total => throw _privateConstructorUsedError; int get total => throw _privateConstructorUsedError;
@JsonKey(name: "EXPIRE") @JsonKey(name: 'EXPIRE')
int get expire => throw _privateConstructorUsedError; int get expire => throw _privateConstructorUsedError;
/// Serializes this ProviderSubscriptionInfo to a JSON map. /// Serializes this ProviderSubscriptionInfo to a JSON map.
@@ -2515,10 +2515,10 @@ abstract class $ProviderSubscriptionInfoCopyWith<$Res> {
_$ProviderSubscriptionInfoCopyWithImpl<$Res, ProviderSubscriptionInfo>; _$ProviderSubscriptionInfoCopyWithImpl<$Res, ProviderSubscriptionInfo>;
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "UPLOAD") int upload, {@JsonKey(name: 'UPLOAD') int upload,
@JsonKey(name: "DOWNLOAD") int download, @JsonKey(name: 'DOWNLOAD') int download,
@JsonKey(name: "TOTAL") int total, @JsonKey(name: 'TOTAL') int total,
@JsonKey(name: "EXPIRE") int expire}); @JsonKey(name: 'EXPIRE') int expire});
} }
/// @nodoc /// @nodoc
@@ -2573,10 +2573,10 @@ abstract class _$$ProviderSubscriptionInfoImplCopyWith<$Res>
@override @override
@useResult @useResult
$Res call( $Res call(
{@JsonKey(name: "UPLOAD") int upload, {@JsonKey(name: 'UPLOAD') int upload,
@JsonKey(name: "DOWNLOAD") int download, @JsonKey(name: 'DOWNLOAD') int download,
@JsonKey(name: "TOTAL") int total, @JsonKey(name: 'TOTAL') int total,
@JsonKey(name: "EXPIRE") int expire}); @JsonKey(name: 'EXPIRE') int expire});
} }
/// @nodoc /// @nodoc
@@ -2624,25 +2624,25 @@ class __$$ProviderSubscriptionInfoImplCopyWithImpl<$Res>
@JsonSerializable() @JsonSerializable()
class _$ProviderSubscriptionInfoImpl implements _ProviderSubscriptionInfo { class _$ProviderSubscriptionInfoImpl implements _ProviderSubscriptionInfo {
const _$ProviderSubscriptionInfoImpl( const _$ProviderSubscriptionInfoImpl(
{@JsonKey(name: "UPLOAD") this.upload = 0, {@JsonKey(name: 'UPLOAD') this.upload = 0,
@JsonKey(name: "DOWNLOAD") this.download = 0, @JsonKey(name: 'DOWNLOAD') this.download = 0,
@JsonKey(name: "TOTAL") this.total = 0, @JsonKey(name: 'TOTAL') this.total = 0,
@JsonKey(name: "EXPIRE") this.expire = 0}); @JsonKey(name: 'EXPIRE') this.expire = 0});
factory _$ProviderSubscriptionInfoImpl.fromJson(Map<String, dynamic> json) => factory _$ProviderSubscriptionInfoImpl.fromJson(Map<String, dynamic> json) =>
_$$ProviderSubscriptionInfoImplFromJson(json); _$$ProviderSubscriptionInfoImplFromJson(json);
@override @override
@JsonKey(name: "UPLOAD") @JsonKey(name: 'UPLOAD')
final int upload; final int upload;
@override @override
@JsonKey(name: "DOWNLOAD") @JsonKey(name: 'DOWNLOAD')
final int download; final int download;
@override @override
@JsonKey(name: "TOTAL") @JsonKey(name: 'TOTAL')
final int total; final int total;
@override @override
@JsonKey(name: "EXPIRE") @JsonKey(name: 'EXPIRE')
final int expire; final int expire;
@override @override
@@ -2685,26 +2685,26 @@ class _$ProviderSubscriptionInfoImpl implements _ProviderSubscriptionInfo {
abstract class _ProviderSubscriptionInfo implements ProviderSubscriptionInfo { abstract class _ProviderSubscriptionInfo implements ProviderSubscriptionInfo {
const factory _ProviderSubscriptionInfo( const factory _ProviderSubscriptionInfo(
{@JsonKey(name: "UPLOAD") final int upload, {@JsonKey(name: 'UPLOAD') final int upload,
@JsonKey(name: "DOWNLOAD") final int download, @JsonKey(name: 'DOWNLOAD') final int download,
@JsonKey(name: "TOTAL") final int total, @JsonKey(name: 'TOTAL') final int total,
@JsonKey(name: "EXPIRE") final int expire}) = @JsonKey(name: 'EXPIRE') final int expire}) =
_$ProviderSubscriptionInfoImpl; _$ProviderSubscriptionInfoImpl;
factory _ProviderSubscriptionInfo.fromJson(Map<String, dynamic> json) = factory _ProviderSubscriptionInfo.fromJson(Map<String, dynamic> json) =
_$ProviderSubscriptionInfoImpl.fromJson; _$ProviderSubscriptionInfoImpl.fromJson;
@override @override
@JsonKey(name: "UPLOAD") @JsonKey(name: 'UPLOAD')
int get upload; int get upload;
@override @override
@JsonKey(name: "DOWNLOAD") @JsonKey(name: 'DOWNLOAD')
int get download; int get download;
@override @override
@JsonKey(name: "TOTAL") @JsonKey(name: 'TOTAL')
int get total; int get total;
@override @override
@JsonKey(name: "EXPIRE") @JsonKey(name: 'EXPIRE')
int get expire; int get expire;
/// Create a copy of ProviderSubscriptionInfo /// Create a copy of ProviderSubscriptionInfo
@@ -2725,12 +2725,12 @@ mixin _$ExternalProvider {
String get type => throw _privateConstructorUsedError; String get type => throw _privateConstructorUsedError;
String? get path => throw _privateConstructorUsedError; String? get path => throw _privateConstructorUsedError;
int get count => throw _privateConstructorUsedError; int get count => throw _privateConstructorUsedError;
@JsonKey(name: "subscription-info", fromJson: subscriptionInfoFormCore) @JsonKey(name: 'subscription-info', fromJson: subscriptionInfoFormCore)
SubscriptionInfo? get subscriptionInfo => throw _privateConstructorUsedError; SubscriptionInfo? get subscriptionInfo => throw _privateConstructorUsedError;
bool get isUpdating => throw _privateConstructorUsedError; bool get isUpdating => throw _privateConstructorUsedError;
@JsonKey(name: "vehicle-type") @JsonKey(name: 'vehicle-type')
String get vehicleType => throw _privateConstructorUsedError; String get vehicleType => throw _privateConstructorUsedError;
@JsonKey(name: "update-at") @JsonKey(name: 'update-at')
DateTime get updateAt => throw _privateConstructorUsedError; DateTime get updateAt => throw _privateConstructorUsedError;
/// Serializes this ExternalProvider to a JSON map. /// Serializes this ExternalProvider to a JSON map.
@@ -2754,11 +2754,11 @@ abstract class $ExternalProviderCopyWith<$Res> {
String type, String type,
String? path, String? path,
int count, int count,
@JsonKey(name: "subscription-info", fromJson: subscriptionInfoFormCore) @JsonKey(name: 'subscription-info', fromJson: subscriptionInfoFormCore)
SubscriptionInfo? subscriptionInfo, SubscriptionInfo? subscriptionInfo,
bool isUpdating, bool isUpdating,
@JsonKey(name: "vehicle-type") String vehicleType, @JsonKey(name: 'vehicle-type') String vehicleType,
@JsonKey(name: "update-at") DateTime updateAt}); @JsonKey(name: 'update-at') DateTime updateAt});
$SubscriptionInfoCopyWith<$Res>? get subscriptionInfo; $SubscriptionInfoCopyWith<$Res>? get subscriptionInfo;
} }
@@ -2851,11 +2851,11 @@ abstract class _$$ExternalProviderImplCopyWith<$Res>
String type, String type,
String? path, String? path,
int count, int count,
@JsonKey(name: "subscription-info", fromJson: subscriptionInfoFormCore) @JsonKey(name: 'subscription-info', fromJson: subscriptionInfoFormCore)
SubscriptionInfo? subscriptionInfo, SubscriptionInfo? subscriptionInfo,
bool isUpdating, bool isUpdating,
@JsonKey(name: "vehicle-type") String vehicleType, @JsonKey(name: 'vehicle-type') String vehicleType,
@JsonKey(name: "update-at") DateTime updateAt}); @JsonKey(name: 'update-at') DateTime updateAt});
@override @override
$SubscriptionInfoCopyWith<$Res>? get subscriptionInfo; $SubscriptionInfoCopyWith<$Res>? get subscriptionInfo;
@@ -2928,11 +2928,11 @@ class _$ExternalProviderImpl implements _ExternalProvider {
required this.type, required this.type,
this.path, this.path,
required this.count, required this.count,
@JsonKey(name: "subscription-info", fromJson: subscriptionInfoFormCore) @JsonKey(name: 'subscription-info', fromJson: subscriptionInfoFormCore)
this.subscriptionInfo, this.subscriptionInfo,
this.isUpdating = false, this.isUpdating = false,
@JsonKey(name: "vehicle-type") required this.vehicleType, @JsonKey(name: 'vehicle-type') required this.vehicleType,
@JsonKey(name: "update-at") required this.updateAt}); @JsonKey(name: 'update-at') required this.updateAt});
factory _$ExternalProviderImpl.fromJson(Map<String, dynamic> json) => factory _$ExternalProviderImpl.fromJson(Map<String, dynamic> json) =>
_$$ExternalProviderImplFromJson(json); _$$ExternalProviderImplFromJson(json);
@@ -2946,16 +2946,16 @@ class _$ExternalProviderImpl implements _ExternalProvider {
@override @override
final int count; final int count;
@override @override
@JsonKey(name: "subscription-info", fromJson: subscriptionInfoFormCore) @JsonKey(name: 'subscription-info', fromJson: subscriptionInfoFormCore)
final SubscriptionInfo? subscriptionInfo; final SubscriptionInfo? subscriptionInfo;
@override @override
@JsonKey() @JsonKey()
final bool isUpdating; final bool isUpdating;
@override @override
@JsonKey(name: "vehicle-type") @JsonKey(name: 'vehicle-type')
final String vehicleType; final String vehicleType;
@override @override
@JsonKey(name: "update-at") @JsonKey(name: 'update-at')
final DateTime updateAt; final DateTime updateAt;
@override @override
@@ -3010,11 +3010,11 @@ abstract class _ExternalProvider implements ExternalProvider {
required final String type, required final String type,
final String? path, final String? path,
required final int count, required final int count,
@JsonKey(name: "subscription-info", fromJson: subscriptionInfoFormCore) @JsonKey(name: 'subscription-info', fromJson: subscriptionInfoFormCore)
final SubscriptionInfo? subscriptionInfo, final SubscriptionInfo? subscriptionInfo,
final bool isUpdating, final bool isUpdating,
@JsonKey(name: "vehicle-type") required final String vehicleType, @JsonKey(name: 'vehicle-type') required final String vehicleType,
@JsonKey(name: "update-at") @JsonKey(name: 'update-at')
required final DateTime updateAt}) = _$ExternalProviderImpl; required final DateTime updateAt}) = _$ExternalProviderImpl;
factory _ExternalProvider.fromJson(Map<String, dynamic> json) = factory _ExternalProvider.fromJson(Map<String, dynamic> json) =
@@ -3029,15 +3029,15 @@ abstract class _ExternalProvider implements ExternalProvider {
@override @override
int get count; int get count;
@override @override
@JsonKey(name: "subscription-info", fromJson: subscriptionInfoFormCore) @JsonKey(name: 'subscription-info', fromJson: subscriptionInfoFormCore)
SubscriptionInfo? get subscriptionInfo; SubscriptionInfo? get subscriptionInfo;
@override @override
bool get isUpdating; bool get isUpdating;
@override @override
@JsonKey(name: "vehicle-type") @JsonKey(name: 'vehicle-type')
String get vehicleType; String get vehicleType;
@override @override
@JsonKey(name: "update-at") @JsonKey(name: 'update-at')
DateTime get updateAt; DateTime get updateAt;
/// Create a copy of ExternalProvider /// Create a copy of ExternalProvider

View File

@@ -68,7 +68,6 @@ const _$LogLevelEnumMap = {
LogLevel.warning: 'warning', LogLevel.warning: 'warning',
LogLevel.error: 'error', LogLevel.error: 'error',
LogLevel.silent: 'silent', LogLevel.silent: 'silent',
LogLevel.app: 'app',
}; };
const _$ExternalControllerStatusEnumMap = { const _$ExternalControllerStatusEnumMap = {

View File

@@ -492,7 +492,7 @@ class _$ProfileImpl implements _Profile {
{required this.id, {required this.id,
this.label, this.label,
this.currentGroupName, this.currentGroupName,
this.url = "", this.url = '',
this.lastUpdateDate, this.lastUpdateDate,
required this.autoUpdateDuration, required this.autoUpdateDuration,
this.subscriptionInfo, this.subscriptionInfo,

View File

@@ -29,7 +29,7 @@ _$ProfileImpl _$$ProfileImplFromJson(Map<String, dynamic> json) =>
id: json['id'] as String, id: json['id'] as String,
label: json['label'] as String?, label: json['label'] as String?,
currentGroupName: json['currentGroupName'] as String?, currentGroupName: json['currentGroupName'] as String?,
url: json['url'] as String? ?? "", url: json['url'] as String? ?? '',
lastUpdateDate: json['lastUpdateDate'] == null lastUpdateDate: json['lastUpdateDate'] == null
? null ? null
: DateTime.parse(json['lastUpdateDate'] as String), : DateTime.parse(json['lastUpdateDate'] as String),

File diff suppressed because it is too large Load Diff

View File

@@ -531,7 +531,7 @@ abstract class _AppBarState implements AppBarState {
/// @nodoc /// @nodoc
mixin _$AppBarSearchState { mixin _$AppBarSearchState {
dynamic Function(String) get onSearch => throw _privateConstructorUsedError; dynamic Function(String) get onSearch => throw _privateConstructorUsedError;
bool get isSearch => throw _privateConstructorUsedError; String? get query => throw _privateConstructorUsedError;
/// Create a copy of AppBarSearchState /// Create a copy of AppBarSearchState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -546,7 +546,7 @@ abstract class $AppBarSearchStateCopyWith<$Res> {
AppBarSearchState value, $Res Function(AppBarSearchState) then) = AppBarSearchState value, $Res Function(AppBarSearchState) then) =
_$AppBarSearchStateCopyWithImpl<$Res, AppBarSearchState>; _$AppBarSearchStateCopyWithImpl<$Res, AppBarSearchState>;
@useResult @useResult
$Res call({dynamic Function(String) onSearch, bool isSearch}); $Res call({dynamic Function(String) onSearch, String? query});
} }
/// @nodoc /// @nodoc
@@ -565,17 +565,17 @@ class _$AppBarSearchStateCopyWithImpl<$Res, $Val extends AppBarSearchState>
@override @override
$Res call({ $Res call({
Object? onSearch = null, Object? onSearch = null,
Object? isSearch = null, Object? query = freezed,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
onSearch: null == onSearch onSearch: null == onSearch
? _value.onSearch ? _value.onSearch
: onSearch // ignore: cast_nullable_to_non_nullable : onSearch // ignore: cast_nullable_to_non_nullable
as dynamic Function(String), as dynamic Function(String),
isSearch: null == isSearch query: freezed == query
? _value.isSearch ? _value.query
: isSearch // ignore: cast_nullable_to_non_nullable : query // ignore: cast_nullable_to_non_nullable
as bool, as String?,
) as $Val); ) as $Val);
} }
} }
@@ -588,7 +588,7 @@ abstract class _$$AppBarSearchStateImplCopyWith<$Res>
__$$AppBarSearchStateImplCopyWithImpl<$Res>; __$$AppBarSearchStateImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({dynamic Function(String) onSearch, bool isSearch}); $Res call({dynamic Function(String) onSearch, String? query});
} }
/// @nodoc /// @nodoc
@@ -605,17 +605,17 @@ class __$$AppBarSearchStateImplCopyWithImpl<$Res>
@override @override
$Res call({ $Res call({
Object? onSearch = null, Object? onSearch = null,
Object? isSearch = null, Object? query = freezed,
}) { }) {
return _then(_$AppBarSearchStateImpl( return _then(_$AppBarSearchStateImpl(
onSearch: null == onSearch onSearch: null == onSearch
? _value.onSearch ? _value.onSearch
: onSearch // ignore: cast_nullable_to_non_nullable : onSearch // ignore: cast_nullable_to_non_nullable
as dynamic Function(String), as dynamic Function(String),
isSearch: null == isSearch query: freezed == query
? _value.isSearch ? _value.query
: isSearch // ignore: cast_nullable_to_non_nullable : query // ignore: cast_nullable_to_non_nullable
as bool, as String?,
)); ));
} }
} }
@@ -623,18 +623,17 @@ class __$$AppBarSearchStateImplCopyWithImpl<$Res>
/// @nodoc /// @nodoc
class _$AppBarSearchStateImpl implements _AppBarSearchState { class _$AppBarSearchStateImpl implements _AppBarSearchState {
const _$AppBarSearchStateImpl( const _$AppBarSearchStateImpl({required this.onSearch, this.query = null});
{required this.onSearch, this.isSearch = false});
@override @override
final dynamic Function(String) onSearch; final dynamic Function(String) onSearch;
@override @override
@JsonKey() @JsonKey()
final bool isSearch; final String? query;
@override @override
String toString() { String toString() {
return 'AppBarSearchState(onSearch: $onSearch, isSearch: $isSearch)'; return 'AppBarSearchState(onSearch: $onSearch, query: $query)';
} }
@override @override
@@ -644,12 +643,11 @@ class _$AppBarSearchStateImpl implements _AppBarSearchState {
other is _$AppBarSearchStateImpl && other is _$AppBarSearchStateImpl &&
(identical(other.onSearch, onSearch) || (identical(other.onSearch, onSearch) ||
other.onSearch == onSearch) && other.onSearch == onSearch) &&
(identical(other.isSearch, isSearch) || (identical(other.query, query) || other.query == query));
other.isSearch == isSearch));
} }
@override @override
int get hashCode => Object.hash(runtimeType, onSearch, isSearch); int get hashCode => Object.hash(runtimeType, onSearch, query);
/// Create a copy of AppBarSearchState /// Create a copy of AppBarSearchState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -664,12 +662,12 @@ class _$AppBarSearchStateImpl implements _AppBarSearchState {
abstract class _AppBarSearchState implements AppBarSearchState { abstract class _AppBarSearchState implements AppBarSearchState {
const factory _AppBarSearchState( const factory _AppBarSearchState(
{required final dynamic Function(String) onSearch, {required final dynamic Function(String) onSearch,
final bool isSearch}) = _$AppBarSearchStateImpl; final String? query}) = _$AppBarSearchStateImpl;
@override @override
dynamic Function(String) get onSearch; dynamic Function(String) get onSearch;
@override @override
bool get isSearch; String? get query;
/// Create a copy of AppBarSearchState /// Create a copy of AppBarSearchState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -681,8 +679,7 @@ abstract class _AppBarSearchState implements AppBarSearchState {
/// @nodoc /// @nodoc
mixin _$AppBarEditState { mixin _$AppBarEditState {
dynamic get editCount => throw _privateConstructorUsedError; int get editCount => throw _privateConstructorUsedError;
bool get isEdit => throw _privateConstructorUsedError;
dynamic Function() get onExit => throw _privateConstructorUsedError; dynamic Function() get onExit => throw _privateConstructorUsedError;
/// Create a copy of AppBarEditState /// Create a copy of AppBarEditState
@@ -698,7 +695,7 @@ abstract class $AppBarEditStateCopyWith<$Res> {
AppBarEditState value, $Res Function(AppBarEditState) then) = AppBarEditState value, $Res Function(AppBarEditState) then) =
_$AppBarEditStateCopyWithImpl<$Res, AppBarEditState>; _$AppBarEditStateCopyWithImpl<$Res, AppBarEditState>;
@useResult @useResult
$Res call({dynamic editCount, bool isEdit, dynamic Function() onExit}); $Res call({int editCount, dynamic Function() onExit});
} }
/// @nodoc /// @nodoc
@@ -716,19 +713,14 @@ class _$AppBarEditStateCopyWithImpl<$Res, $Val extends AppBarEditState>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? editCount = freezed, Object? editCount = null,
Object? isEdit = null,
Object? onExit = null, Object? onExit = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
editCount: freezed == editCount editCount: null == editCount
? _value.editCount ? _value.editCount
: editCount // ignore: cast_nullable_to_non_nullable : editCount // ignore: cast_nullable_to_non_nullable
as dynamic, as int,
isEdit: null == isEdit
? _value.isEdit
: isEdit // ignore: cast_nullable_to_non_nullable
as bool,
onExit: null == onExit onExit: null == onExit
? _value.onExit ? _value.onExit
: onExit // ignore: cast_nullable_to_non_nullable : onExit // ignore: cast_nullable_to_non_nullable
@@ -745,7 +737,7 @@ abstract class _$$AppBarEditStateImplCopyWith<$Res>
__$$AppBarEditStateImplCopyWithImpl<$Res>; __$$AppBarEditStateImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({dynamic editCount, bool isEdit, dynamic Function() onExit}); $Res call({int editCount, dynamic Function() onExit});
} }
/// @nodoc /// @nodoc
@@ -761,16 +753,14 @@ class __$$AppBarEditStateImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? editCount = freezed, Object? editCount = null,
Object? isEdit = null,
Object? onExit = null, Object? onExit = null,
}) { }) {
return _then(_$AppBarEditStateImpl( return _then(_$AppBarEditStateImpl(
editCount: freezed == editCount ? _value.editCount! : editCount, editCount: null == editCount
isEdit: null == isEdit ? _value.editCount
? _value.isEdit : editCount // ignore: cast_nullable_to_non_nullable
: isEdit // ignore: cast_nullable_to_non_nullable as int,
as bool,
onExit: null == onExit onExit: null == onExit
? _value.onExit ? _value.onExit
: onExit // ignore: cast_nullable_to_non_nullable : onExit // ignore: cast_nullable_to_non_nullable
@@ -782,21 +772,17 @@ class __$$AppBarEditStateImplCopyWithImpl<$Res>
/// @nodoc /// @nodoc
class _$AppBarEditStateImpl implements _AppBarEditState { class _$AppBarEditStateImpl implements _AppBarEditState {
const _$AppBarEditStateImpl( const _$AppBarEditStateImpl({this.editCount = 0, required this.onExit});
{this.editCount = 0, this.isEdit = false, required this.onExit});
@override @override
@JsonKey() @JsonKey()
final dynamic editCount; final int editCount;
@override
@JsonKey()
final bool isEdit;
@override @override
final dynamic Function() onExit; final dynamic Function() onExit;
@override @override
String toString() { String toString() {
return 'AppBarEditState(editCount: $editCount, isEdit: $isEdit, onExit: $onExit)'; return 'AppBarEditState(editCount: $editCount, onExit: $onExit)';
} }
@override @override
@@ -804,14 +790,13 @@ class _$AppBarEditStateImpl implements _AppBarEditState {
return identical(this, other) || return identical(this, other) ||
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$AppBarEditStateImpl && other is _$AppBarEditStateImpl &&
const DeepCollectionEquality().equals(other.editCount, editCount) && (identical(other.editCount, editCount) ||
(identical(other.isEdit, isEdit) || other.isEdit == isEdit) && other.editCount == editCount) &&
(identical(other.onExit, onExit) || other.onExit == onExit)); (identical(other.onExit, onExit) || other.onExit == onExit));
} }
@override @override
int get hashCode => Object.hash(runtimeType, int get hashCode => Object.hash(runtimeType, editCount, onExit);
const DeepCollectionEquality().hash(editCount), isEdit, onExit);
/// Create a copy of AppBarEditState /// Create a copy of AppBarEditState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -825,14 +810,11 @@ class _$AppBarEditStateImpl implements _AppBarEditState {
abstract class _AppBarEditState implements AppBarEditState { abstract class _AppBarEditState implements AppBarEditState {
const factory _AppBarEditState( const factory _AppBarEditState(
{final dynamic editCount, {final int editCount,
final bool isEdit,
required final dynamic Function() onExit}) = _$AppBarEditStateImpl; required final dynamic Function() onExit}) = _$AppBarEditStateImpl;
@override @override
dynamic get editCount; int get editCount;
@override
bool get isEdit;
@override @override
dynamic Function() get onExit; dynamic Function() get onExit;

View File

@@ -29,17 +29,17 @@ class SubscriptionInfo with _$SubscriptionInfo {
factory SubscriptionInfo.formHString(String? info) { factory SubscriptionInfo.formHString(String? info) {
if (info == null) return const SubscriptionInfo(); if (info == null) return const SubscriptionInfo();
final list = info.split(";"); final list = info.split(';');
Map<String, int?> map = {}; Map<String, int?> map = {};
for (final i in list) { for (final i in list) {
final keyValue = i.trim().split("="); final keyValue = i.trim().split('=');
map[keyValue[0]] = int.tryParse(keyValue[1]); map[keyValue[0]] = int.tryParse(keyValue[1]);
} }
return SubscriptionInfo( return SubscriptionInfo(
upload: map["upload"] ?? 0, upload: map['upload'] ?? 0,
download: map["download"] ?? 0, download: map['download'] ?? 0,
total: map["total"] ?? 0, total: map['total'] ?? 0,
expire: map["expire"] ?? 0, expire: map['expire'] ?? 0,
); );
} }
} }
@@ -50,7 +50,7 @@ class Profile with _$Profile {
required String id, required String id,
String? label, String? label,
String? currentGroupName, String? currentGroupName,
@Default("") String url, @Default('') String url,
DateTime? lastUpdateDate, DateTime? lastUpdateDate,
required Duration autoUpdateDuration, required Duration autoUpdateDuration,
SubscriptionInfo? subscriptionInfo, SubscriptionInfo? subscriptionInfo,
@@ -169,7 +169,7 @@ extension ProfileExtension on Profile {
Future<Profile> update() async { Future<Profile> update() async {
final response = await request.getFileResponseForUrl(url); final response = await request.getFileResponseForUrl(url);
final disposition = response.headers.value("content-disposition"); final disposition = response.headers.value('content-disposition');
final userinfo = response.headers.value('subscription-userinfo'); final userinfo = response.headers.value('subscription-userinfo');
return await copyWith( return await copyWith(
label: label ?? utils.getFileNameForDisposition(disposition) ?? id, label: label ?? utils.getFileNameForDisposition(disposition) ?? id,

View File

@@ -66,7 +66,6 @@ class ProfilesSelectorState with _$ProfilesSelectorState {
class NetworkDetectionState with _$NetworkDetectionState { class NetworkDetectionState with _$NetworkDetectionState {
const factory NetworkDetectionState({ const factory NetworkDetectionState({
required bool isLoading, required bool isLoading,
required bool isTesting,
required IpInfo? ipInfo, required IpInfo? ipInfo,
}) = _NetworkDetectionState; }) = _NetworkDetectionState;
} }
@@ -88,28 +87,14 @@ class TrayState with _$TrayState {
} }
@freezed @freezed
class HomeState with _$HomeState { class NavigationState with _$NavigationState {
const factory HomeState({ const factory NavigationState({
required PageLabel pageLabel, required PageLabel pageLabel,
required List<NavigationItem> navigationItems, required List<NavigationItem> navigationItems,
required ViewMode viewMode, required ViewMode viewMode,
required String? locale, required String? locale,
}) = _HomeState; required int currentIndex,
} }) = _NavigationState;
@freezed
class ProxiesSelectorState with _$ProxiesSelectorState {
const factory ProxiesSelectorState({
required List<String> groupNames,
required String? currentGroupName,
}) = _ProxiesSelectorState;
}
@freezed
class GroupNamesState with _$GroupNamesState {
const factory GroupNamesState({
required List<String> groupNames,
}) = _GroupNamesState;
} }
@freezed @freezed
@@ -127,16 +112,27 @@ class NavigationItemsState with _$NavigationItemsState {
} }
@freezed @freezed
class ProxiesListSelectorState with _$ProxiesListSelectorState { class ProxiesListState with _$ProxiesListState {
const factory ProxiesListSelectorState({ const factory ProxiesListState({
required List<String> groupNames, required List<Group> groups,
required Set<String> currentUnfoldSet, required Set<String> currentUnfoldSet,
required ProxiesSortType proxiesSortType, required ProxiesSortType proxiesSortType,
required ProxyCardType proxyCardType, required ProxyCardType proxyCardType,
required num sortNum, required num sortNum,
required int columns, required int columns,
required String query, }) = _ProxiesListState;
}) = _ProxiesListSelectorState; }
@freezed
class ProxiesTabState with _$ProxiesTabState {
const factory ProxiesTabState({
required List<Group> groups,
required String? currentGroupName,
required ProxiesSortType proxiesSortType,
required ProxyCardType proxyCardType,
required num sortNum,
required int columns,
}) = _ProxiesTabState;
} }
@freezed @freezed

View File

@@ -32,15 +32,14 @@ class AppBarState with _$AppBarState {
class AppBarSearchState with _$AppBarSearchState { class AppBarSearchState with _$AppBarSearchState {
const factory AppBarSearchState({ const factory AppBarSearchState({
required Function(String) onSearch, required Function(String) onSearch,
@Default(false) bool isSearch, @Default(null) String? query,
}) = _AppBarSearchState; }) = _AppBarSearchState;
} }
@freezed @freezed
class AppBarEditState with _$AppBarEditState { class AppBarEditState with _$AppBarEditState {
const factory AppBarEditState({ const factory AppBarEditState({
@Default(0) editCount, @Default(0) int editCount,
@Default(false) bool isEdit,
required Function() onExit, required Function() onExit,
}) = _AppBarEditState; }) = _AppBarEditState;
} }

View File

@@ -107,11 +107,11 @@ class _EditorPageState extends ConsumerState<EditorPage> {
); );
} }
_handleSearch() { void _handleSearch() {
_findController.findMode(); _findController.findMode();
} }
_handleImport() async { Future<void> _handleImport() async {
final option = await globalState.showCommonDialog<ImportOption>( final option = await globalState.showCommonDialog<ImportOption>(
child: _ImportOptionsDialog(), child: _ImportOptionsDialog(),
); );
@@ -129,8 +129,8 @@ class _EditorPageState extends ConsumerState<EditorPage> {
} }
final url = await globalState.showCommonDialog( final url = await globalState.showCommonDialog(
child: InputDialog( child: InputDialog(
title: "导入", title: '导入',
value: "", value: '',
labelText: appLocalizations.url, labelText: appLocalizations.url,
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -292,7 +292,7 @@ class _EditorPageState extends ConsumerState<EditorPage> {
mode: langYaml, mode: langYaml,
), ),
if (widget.languages.contains(Language.javaScript)) if (widget.languages.contains(Language.javaScript))
"javascript": CodeHighlightThemeMode( 'javascript': CodeHighlightThemeMode(
mode: langJavascript, mode: langJavascript,
), ),
}, },
@@ -433,7 +433,7 @@ class FindPanel extends StatelessWidget implements PreferredSizeWidget {
return bar; return bar;
} }
_buildFindInput(BuildContext context, CodeFindValue value) { Stack _buildFindInput(BuildContext context, CodeFindValue value) {
return Stack( return Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
@@ -550,7 +550,7 @@ class ContextMenuControllerImpl implements SelectionToolbarController {
OverlayEntry? _overlayEntry; OverlayEntry? _overlayEntry;
bool _isFirstRender = true; bool _isFirstRender = true;
_removeOverLayEntry() { void _removeOverLayEntry() {
_overlayEntry?.remove(); _overlayEntry?.remove();
_overlayEntry = null; _overlayEntry = null;
_isFirstRender = true; _isFirstRender = true;
@@ -689,7 +689,7 @@ class _ImportOptionsDialog extends StatefulWidget {
} }
class _ImportOptionsDialogState extends State<_ImportOptionsDialog> { class _ImportOptionsDialogState extends State<_ImportOptionsDialog> {
_handleOnTab(ImportOption value) { void _handleOnTab(ImportOption value) {
Navigator.of(context).pop(value); Navigator.of(context).pop(value);
} }

View File

@@ -1,12 +1,10 @@
import 'dart:io';
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/providers/providers.dart'; import 'package:fl_clash/providers/providers.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:fl_clash/widgets/widgets.dart'; import 'package:fl_clash/widgets/widgets.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
@@ -18,43 +16,99 @@ class HomePage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return HomeBackScope( return HomeBackScope(
child: Consumer( child: Material(
builder: (_, ref, child) { color: context.colorScheme.surface,
final state = ref.watch(homeStateProvider); child: Consumer(
final viewMode = state.viewMode; builder: (context, ref, __) {
final navigationItems = state.navigationItems; final state = ref.watch(navigationStateProvider);
final pageLabel = state.pageLabel; final isMobile = state.viewMode == ViewMode.mobile;
final index = navigationItems.lastIndexWhere( final navigationItems = state.navigationItems;
(element) => element.label == pageLabel, final pageView = _HomePageView(pageBuilder: (_, index) {
); final navigationItem = state.navigationItems[index];
final currentIndex = index == -1 ? 0 : index; final navigationView = navigationItem.builder(context);
final navigationBar = CommonNavigationBar( final view = isMobile
viewMode: viewMode, ? KeepScope(
navigationItems: navigationItems, keep: navigationItem.keep,
currentIndex: currentIndex, child: navigationView,
); )
final bottomNavigationBar = : KeepScope(
viewMode == ViewMode.mobile ? navigationBar : null; keep: navigationItem.keep,
final sideNavigationBar = child: Navigator(
viewMode != ViewMode.mobile ? navigationBar : null; onGenerateRoute: (_) {
return CommonScaffold( return CommonRoute(
key: globalState.homeScaffoldKey, builder: (_) => navigationView,
title: Intl.message( );
pageLabel.name, },
), ),
sideNavigationBar: sideNavigationBar, );
body: child!, return view;
bottomNavigationBar: bottomNavigationBar, });
); final currentIndex = state.currentIndex;
}, final bottomNavigationBar = NavigationBarTheme(
child: _HomePageView(), data: _NavigationBarDefaultsM3(context),
child: NavigationBar(
destinations: navigationItems
.map(
(e) => NavigationDestination(
icon: e.icon,
label: Intl.message(e.label.name),
),
)
.toList(),
onDestinationSelected: (index) {
globalState.appController.toPage(
navigationItems[index].label,
);
},
selectedIndex: currentIndex,
),
);
if (isMobile) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: globalState.appState.systemUiOverlayStyle.copyWith(
systemNavigationBarColor:
context.colorScheme.surfaceContainer,
),
child: Column(
children: [
Flexible(
flex: 1,
child: MediaQuery.removePadding(
removeTop: false,
removeBottom: true,
removeLeft: true,
removeRight: true,
context: context,
child: pageView,
),
),
MediaQuery.removePadding(
removeTop: true,
removeBottom: false,
removeLeft: true,
removeRight: true,
context: context,
child: bottomNavigationBar,
),
],
),
);
} else {
return pageView;
}
},
),
), ),
); );
} }
} }
class _HomePageView extends ConsumerStatefulWidget { class _HomePageView extends ConsumerStatefulWidget {
const _HomePageView(); final IndexedWidgetBuilder pageBuilder;
const _HomePageView({
required this.pageBuilder,
});
@override @override
ConsumerState createState() => _HomePageViewState(); ConsumerState createState() => _HomePageViewState();
@@ -64,18 +118,17 @@ class _HomePageViewState extends ConsumerState<_HomePageView> {
late PageController _pageController; late PageController _pageController;
@override @override
void initState() { initState() {
super.initState(); super.initState();
_pageController = PageController( _pageController = PageController(
initialPage: _pageIndex, initialPage: _pageIndex,
keepPage: true,
); );
ref.listenManual(currentPageLabelProvider, (prev, next) { ref.listenManual(currentPageLabelProvider, (prev, next) {
if (prev != next) { if (prev != next) {
_toPage(next); _toPage(next);
} }
}); });
ref.listenManual(currentNavigationsStateProvider, (prev, next) { ref.listenManual(currentNavigationItemsStateProvider, (prev, next) {
if (prev?.value.length != next.value.length) { if (prev?.value.length != next.value.length) {
_updatePageController(); _updatePageController();
} }
@@ -83,17 +136,18 @@ class _HomePageViewState extends ConsumerState<_HomePageView> {
} }
int get _pageIndex { int get _pageIndex {
final navigationItems = ref.read(currentNavigationsStateProvider).value; final navigationItems = ref.read(currentNavigationItemsStateProvider).value;
return navigationItems.indexWhere( return navigationItems.indexWhere(
(item) => item.label == globalState.appState.pageLabel, (item) => item.label == globalState.appState.pageLabel,
); );
} }
_toPage(PageLabel pageLabel, [bool ignoreAnimateTo = false]) async { Future<void> _toPage(PageLabel pageLabel,
[bool ignoreAnimateTo = false]) async {
if (!mounted) { if (!mounted) {
return; return;
} }
final navigationItems = ref.read(currentNavigationsStateProvider).value; final navigationItems = ref.read(currentNavigationItemsStateProvider).value;
final index = navigationItems.indexWhere((item) => item.label == pageLabel); final index = navigationItems.indexWhere((item) => item.label == pageLabel);
if (index == -1) { if (index == -1) {
return; return;
@@ -111,7 +165,7 @@ class _HomePageViewState extends ConsumerState<_HomePageView> {
} }
} }
_updatePageController() { void _updatePageController() {
final pageLabel = globalState.appState.pageLabel; final pageLabel = globalState.appState.pageLabel;
_toPage(pageLabel, true); _toPage(pageLabel, true);
} }
@@ -124,138 +178,19 @@ class _HomePageViewState extends ConsumerState<_HomePageView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final navigationItems = ref.watch(currentNavigationsStateProvider).value; final itemCount = ref.watch(currentNavigationItemsStateProvider
.select((state) => state.value.length));
return PageView.builder( return PageView.builder(
controller: _pageController, controller: _pageController,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
itemCount: navigationItems.length, itemCount: itemCount,
// onPageChanged: (index) { itemBuilder: (context, index) {
// debouncer.call(DebounceTag.pageChange, () { return widget.pageBuilder(context, index);
// WidgetsBinding.instance.addPostFrameCallback((_) {
// if (_pageIndex != index) {
// final pageLabel = navigationItems[index].label;
// _toPage(pageLabel, true);
// }
// });
// });
// },
itemBuilder: (_, index) {
final navigationItem = navigationItems[index];
return KeepScope(
keep: navigationItem.keep,
key: Key(navigationItem.label.name),
child: navigationItem.view,
);
}, },
); );
} }
} }
class CommonNavigationBar extends ConsumerWidget {
final ViewMode viewMode;
final List<NavigationItem> navigationItems;
final int currentIndex;
const CommonNavigationBar({
super.key,
required this.viewMode,
required this.navigationItems,
required this.currentIndex,
});
@override
Widget build(BuildContext context, ref) {
if (viewMode == ViewMode.mobile) {
return NavigationBarTheme(
data: _NavigationBarDefaultsM3(context),
child: NavigationBar(
destinations: navigationItems
.map(
(e) => NavigationDestination(
icon: e.icon,
label: Intl.message(e.label.name),
),
)
.toList(),
onDestinationSelected: (index) {
globalState.appController.toPage(navigationItems[index].label);
},
selectedIndex: currentIndex,
),
);
}
final showLabel = ref.watch(appSettingProvider).showLabel;
return Material(
color: context.colorScheme.surfaceContainer,
child: Column(
children: [
Expanded(
child: ScrollConfiguration(
behavior: HiddenBarScrollBehavior(),
child: SingleChildScrollView(
child: IntrinsicHeight(
child: NavigationRail(
backgroundColor: context.colorScheme.surfaceContainer,
selectedIconTheme: IconThemeData(
color: context.colorScheme.onSurfaceVariant,
),
unselectedIconTheme: IconThemeData(
color: context.colorScheme.onSurfaceVariant,
),
selectedLabelTextStyle:
context.textTheme.labelLarge!.copyWith(
color: context.colorScheme.onSurface,
),
unselectedLabelTextStyle:
context.textTheme.labelLarge!.copyWith(
color: context.colorScheme.onSurface,
),
destinations: navigationItems
.map(
(e) => NavigationRailDestination(
icon: e.icon,
label: Text(
Intl.message(e.label.name),
),
),
)
.toList(),
onDestinationSelected: (index) {
globalState.appController
.toPage(navigationItems[index].label);
},
extended: false,
selectedIndex: currentIndex,
labelType: showLabel
? NavigationRailLabelType.all
: NavigationRailLabelType.none,
),
),
),
),
),
const SizedBox(
height: 16,
),
IconButton(
onPressed: () {
ref.read(appSettingProvider.notifier).updateState(
(state) => state.copyWith(
showLabel: !state.showLabel,
),
);
},
icon: const Icon(Icons.menu),
),
const SizedBox(
height: 16,
),
],
),
);
}
}
class _NavigationBarDefaultsM3 extends NavigationBarThemeData { class _NavigationBarDefaultsM3 extends NavigationBarThemeData {
_NavigationBarDefaultsM3(this.context) _NavigationBarDefaultsM3(this.context)
: super( : super(
@@ -319,7 +254,7 @@ class HomeBackScope extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (Platform.isAndroid) { if (system.isAndroid) {
return CommonPopScope( return CommonPopScope(
onPop: () async { onPop: () async {
final canPop = Navigator.canPop(context); final canPop = Navigator.canPop(context);

View File

@@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:fl_clash/common/color.dart'; import 'package:fl_clash/common/color.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:fl_clash/widgets/activate_box.dart'; import 'package:fl_clash/widgets/activate_box.dart';
@@ -29,7 +30,7 @@ class _ScanPageState extends State<ScanPage> with WidgetsBindingObserver {
unawaited(controller.start()); unawaited(controller.start());
} }
_handleBarcode(BarcodeCapture barcodeCapture) { void _handleBarcode(BarcodeCapture barcodeCapture) {
final barcode = barcodeCapture.barcodes.first; final barcode = barcodeCapture.barcodes.first;
if (barcode.type == BarcodeType.url) { if (barcode.type == BarcodeType.url) {
Navigator.pop<String>( Navigator.pop<String>(

View File

@@ -1,9 +1,9 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'dart:isolate'; import 'dart:isolate';
import 'package:fl_clash/common/app_localizations.dart'; import 'package:fl_clash/common/app_localizations.dart';
import 'package:fl_clash/common/system.dart';
import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@@ -15,18 +15,18 @@ class App {
Function()? onExit; Function()? onExit;
App._internal() { App._internal() {
methodChannel = const MethodChannel("app"); methodChannel = const MethodChannel('app');
methodChannel.setMethodCallHandler((call) async { methodChannel.setMethodCallHandler((call) async {
switch (call.method) { switch (call.method) {
case "exit": case 'exit':
if (onExit != null) { if (onExit != null) {
await onExit!(); await onExit!();
} }
case "getText": case 'getText':
try { try {
return Intl.message(call.arguments as String); return Intl.message(call.arguments as String);
} catch (_) { } catch (_) {
return ""; return '';
} }
default: default:
throw MissingPluginException(); throw MissingPluginException();
@@ -40,12 +40,12 @@ class App {
} }
Future<bool?> moveTaskToBack() async { Future<bool?> moveTaskToBack() async {
return await methodChannel.invokeMethod<bool>("moveTaskToBack"); return await methodChannel.invokeMethod<bool>('moveTaskToBack');
} }
Future<List<Package>> getPackages() async { Future<List<Package>> getPackages() async {
final packagesString = final packagesString =
await methodChannel.invokeMethod<String>("getPackages"); await methodChannel.invokeMethod<String>('getPackages');
return Isolate.run<List<Package>>(() { return Isolate.run<List<Package>>(() {
final List<dynamic> packagesRaw = final List<dynamic> packagesRaw =
packagesString != null ? json.decode(packagesString) : []; packagesString != null ? json.decode(packagesString) : [];
@@ -55,7 +55,7 @@ class App {
Future<List<String>> getChinaPackageNames() async { Future<List<String>> getChinaPackageNames() async {
final packageNamesString = final packageNamesString =
await methodChannel.invokeMethod<String>("getChinaPackageNames"); await methodChannel.invokeMethod<String>('getChinaPackageNames');
return Isolate.run<List<String>>(() { return Isolate.run<List<String>>(() {
final List<dynamic> packageNamesRaw = final List<dynamic> packageNamesRaw =
packageNamesString != null ? json.decode(packageNamesString) : []; packageNamesString != null ? json.decode(packageNamesString) : [];
@@ -64,15 +64,15 @@ class App {
} }
Future<bool> openFile(String path) async { Future<bool> openFile(String path) async {
return await methodChannel.invokeMethod<bool>("openFile", { return await methodChannel.invokeMethod<bool>('openFile', {
"path": path, 'path': path,
}) ?? }) ??
false; false;
} }
Future<ImageProvider?> getPackageIcon(String packageName) async { Future<ImageProvider?> getPackageIcon(String packageName) async {
final base64 = await methodChannel.invokeMethod<String>("getPackageIcon", { final base64 = await methodChannel.invokeMethod<String>('getPackageIcon', {
"packageName": packageName, 'packageName': packageName,
}); });
if (base64 == null) { if (base64 == null) {
return null; return null;
@@ -81,23 +81,23 @@ class App {
} }
Future<bool?> tip(String? message) async { Future<bool?> tip(String? message) async {
return await methodChannel.invokeMethod<bool>("tip", { return await methodChannel.invokeMethod<bool>('tip', {
"message": "$message", 'message': '$message',
}); });
} }
Future<bool?> initShortcuts() async { Future<bool?> initShortcuts() async {
return await methodChannel.invokeMethod<bool>( return await methodChannel.invokeMethod<bool>(
"initShortcuts", 'initShortcuts',
appLocalizations.toggle, appLocalizations.toggle,
); );
} }
Future<bool?> updateExcludeFromRecents(bool value) async { Future<bool?> updateExcludeFromRecents(bool value) async {
return await methodChannel.invokeMethod<bool>("updateExcludeFromRecents", { return await methodChannel.invokeMethod<bool>('updateExcludeFromRecents', {
"value": value, 'value': value,
}); });
} }
} }
final app = Platform.isAndroid ? App() : null; final app = system.isAndroid ? App() : null;

View File

@@ -1,7 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'dart:isolate'; import 'dart:isolate';
import 'package:fl_clash/common/system.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@@ -13,7 +14,7 @@ class Service {
ReceivePort? receiver; ReceivePort? receiver;
Service._internal() { Service._internal() {
methodChannel = const MethodChannel("service"); methodChannel = const MethodChannel('service');
} }
factory Service() { factory Service() {
@@ -22,23 +23,24 @@ class Service {
} }
Future<bool?> init() async { Future<bool?> init() async {
return await methodChannel.invokeMethod<bool>("init"); return await methodChannel.invokeMethod<bool>('init');
} }
Future<bool?> destroy() async { Future<bool?> destroy() async {
return await methodChannel.invokeMethod<bool>("destroy"); return await methodChannel.invokeMethod<bool>('destroy');
} }
Future<bool?> startVpn() async { Future<bool?> startVpn() async {
final options = await clashLib?.getAndroidVpnOptions(); final options = await clashLib?.getAndroidVpnOptions();
return await methodChannel.invokeMethod<bool>("startVpn", { return await methodChannel.invokeMethod<bool>('startVpn', {
'data': json.encode(options), 'data': json.encode(options),
}); });
} }
Future<bool?> stopVpn() async { Future<bool?> stopVpn() async {
return await methodChannel.invokeMethod<bool>("stopVpn"); return await methodChannel.invokeMethod<bool>('stopVpn');
} }
} }
Service? get service => Platform.isAndroid && !globalState.isService ? Service() : null; Service? get service =>
system.isAndroid && !globalState.isService ? Service() : null;

View File

@@ -1,6 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:fl_clash/common/system.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@@ -9,13 +9,10 @@ abstract mixin class TileListener {
void onStop() {} void onStop() {}
void onDetached(){ void onDetached() {}
}
} }
class Tile { class Tile {
final MethodChannel _channel = const MethodChannel('tile'); final MethodChannel _channel = const MethodChannel('tile');
Tile._() { Tile._() {
@@ -29,13 +26,13 @@ class Tile {
Future<void> _methodCallHandler(MethodCall call) async { Future<void> _methodCallHandler(MethodCall call) async {
for (final TileListener listener in _listeners) { for (final TileListener listener in _listeners) {
switch (call.method) { switch (call.method) {
case "start": case 'start':
listener.onStart(); listener.onStart();
break; break;
case "stop": case 'stop':
listener.onStop(); listener.onStop();
break; break;
case "detached": case 'detached':
listener.onDetached(); listener.onDetached();
break; break;
} }
@@ -55,4 +52,4 @@ class Tile {
} }
} }
final tile = Platform.isAndroid ? Tile.instance : null; final tile = system.isAndroid ? Tile.instance : null;

View File

@@ -17,22 +17,22 @@ class Vpn {
FutureOr<String> Function()? handleGetStartForegroundParams; FutureOr<String> Function()? handleGetStartForegroundParams;
Vpn._internal() { Vpn._internal() {
methodChannel = const MethodChannel("vpn"); methodChannel = const MethodChannel('vpn');
methodChannel.setMethodCallHandler((call) async { methodChannel.setMethodCallHandler((call) async {
switch (call.method) { switch (call.method) {
case "gc": case 'gc':
clashCore.requestGc(); clashCore.requestGc();
case "getStartForegroundParams": case 'getStartForegroundParams':
if (handleGetStartForegroundParams != null) { if (handleGetStartForegroundParams != null) {
return await handleGetStartForegroundParams!(); return await handleGetStartForegroundParams!();
} }
return ""; return '';
case "status": case 'status':
return clashLibHandler?.getRunTime() != null; return clashLibHandler?.getRunTime() != null;
default: default:
for (final VpnListener listener in _listeners) { for (final VpnListener listener in _listeners) {
switch (call.method) { switch (call.method) {
case "dnsChanged": case 'dnsChanged':
final dns = call.arguments as String; final dns = call.arguments as String;
listener.onDnsChanged(dns); listener.onDnsChanged(dns);
} }
@@ -49,13 +49,13 @@ class Vpn {
final ObserverList<VpnListener> _listeners = ObserverList<VpnListener>(); final ObserverList<VpnListener> _listeners = ObserverList<VpnListener>();
Future<bool?> start(AndroidVpnOptions options) async { Future<bool?> start(AndroidVpnOptions options) async {
return await methodChannel.invokeMethod<bool>("start", { return await methodChannel.invokeMethod<bool>('start', {
'data': json.encode(options), 'data': json.encode(options),
}); });
} }
Future<bool?> stop() async { Future<bool?> stop() async {
return await methodChannel.invokeMethod<bool>("stop"); return await methodChannel.invokeMethod<bool>('stop');
} }
void addListener(VpnListener listener) { void addListener(VpnListener listener) {

View File

@@ -2,7 +2,7 @@ import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart'; import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -30,7 +30,7 @@ class Logs extends _$Logs with AutoDisposeNotifierMixin {
return globalState.appState.logs; return globalState.appState.logs;
} }
addLog(Log value) { void addLog(Log value) {
state = state.copyWith()..add(value); state = state.copyWith()..add(value);
} }
@@ -45,7 +45,7 @@ class Logs extends _$Logs with AutoDisposeNotifierMixin {
@riverpod @riverpod
class Requests extends _$Requests with AutoDisposeNotifierMixin { class Requests extends _$Requests with AutoDisposeNotifierMixin {
@override @override
FixedList<Connection> build() { FixedList<TrackerInfo> build() {
return globalState.appState.requests; return globalState.appState.requests;
} }
@@ -56,7 +56,7 @@ class Requests extends _$Requests with AutoDisposeNotifierMixin {
); );
} }
addRequest(Connection value) { void addRequest(TrackerInfo value) {
state = state.copyWith()..add(value); state = state.copyWith()..add(value);
} }
} }
@@ -75,7 +75,7 @@ class Providers extends _$Providers with AutoDisposeNotifierMixin {
); );
} }
setProvider(ExternalProvider? provider) { void setProvider(ExternalProvider? provider) {
if (provider == null) return; if (provider == null) return;
final index = state.indexWhere((item) => item.name == provider.name); final index = state.indexWhere((item) => item.name == provider.name);
if (index == -1) return; if (index == -1) return;
@@ -99,9 +99,10 @@ class Packages extends _$Packages with AutoDisposeNotifierMixin {
} }
@riverpod @riverpod
class AppBrightness extends _$AppBrightness with AutoDisposeNotifierMixin { class SystemBrightness extends _$SystemBrightness
with AutoDisposeNotifierMixin {
@override @override
Brightness? build() { Brightness build() {
return globalState.appState.brightness; return globalState.appState.brightness;
} }
@@ -112,7 +113,7 @@ class AppBrightness extends _$AppBrightness with AutoDisposeNotifierMixin {
); );
} }
setState(Brightness? value) { void setState(Brightness value) {
state = value; state = value;
} }
} }
@@ -131,11 +132,11 @@ class Traffics extends _$Traffics with AutoDisposeNotifierMixin {
); );
} }
addTraffic(Traffic value) { void addTraffic(Traffic value) {
state = state.copyWith()..add(value); state = state.copyWith()..add(value);
} }
clear() { void clear() {
state = state.copyWith()..clear(); state = state.copyWith()..clear();
} }
} }
@@ -281,7 +282,7 @@ class SortNum extends _$SortNum with AutoDisposeNotifierMixin {
); );
} }
add() => state++; int add() => state++;
} }
@riverpod @riverpod
@@ -298,7 +299,7 @@ class CheckIpNum extends _$CheckIpNum with AutoDisposeNotifierMixin {
); );
} }
add() => state++; int add() => state++;
} }
@riverpod @riverpod
@@ -316,6 +317,21 @@ class BackBlock extends _$BackBlock with AutoDisposeNotifierMixin {
} }
} }
@riverpod
class Loading extends _$Loading with AutoDisposeNotifierMixin {
@override
bool build() {
return globalState.appState.loading;
}
@override
onUpdate(value) {
globalState.appState = globalState.appState.copyWith(
loading: value,
);
}
}
@riverpod @riverpod
class Version extends _$Version with AutoDisposeNotifierMixin { class Version extends _$Version with AutoDisposeNotifierMixin {
@override @override
@@ -360,7 +376,7 @@ class DelayDataSource extends _$DelayDataSource with AutoDisposeNotifierMixin {
); );
} }
setDelay(Delay delay) { void setDelay(Delay delay) {
if (state[delay.url]?[delay.name] != delay.value) { if (state[delay.url]?[delay.name] != delay.value) {
final DelayMap newDelayMap = Map.from(state); final DelayMap newDelayMap = Map.from(state);
if (newDelayMap[delay.url] == null) { if (newDelayMap[delay.url] == null) {
@@ -373,16 +389,17 @@ class DelayDataSource extends _$DelayDataSource with AutoDisposeNotifierMixin {
} }
@riverpod @riverpod
class ProxiesQuery extends _$ProxiesQuery with AutoDisposeNotifierMixin { class SystemUiOverlayStyleState extends _$SystemUiOverlayStyleState
with AutoDisposeNotifierMixin {
@override @override
String build() { SystemUiOverlayStyle build() {
return globalState.appState.proxiesQuery; return globalState.appState.systemUiOverlayStyle;
} }
@override @override
onUpdate(value) { onUpdate(value) {
globalState.appState = globalState.appState.copyWith( globalState.appState = globalState.appState.copyWith(
proxiesQuery: value, systemUiOverlayStyle: value,
); );
} }
} }

Some files were not shown because too many files have changed in this diff Show More