Compare commits
1 Commits
v0.8.83-pr
...
v0.8.83-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cb5d40969 |
@@ -3,7 +3,6 @@ package com.follow.clash.models
|
||||
data class Package(
|
||||
val packageName: String,
|
||||
val label: String,
|
||||
val system: Boolean,
|
||||
val internet: Boolean,
|
||||
val isSystem: Boolean,
|
||||
val lastUpdateTime: Long,
|
||||
)
|
||||
|
||||
@@ -293,17 +293,19 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
|
||||
if (packages.isNotEmpty()) return packages
|
||||
packageManager?.getInstalledPackages(PackageManager.GET_META_DATA or PackageManager.GET_PERMISSIONS)
|
||||
?.filter {
|
||||
it.packageName != FlClashApplication.getAppContext().packageName || it.packageName == "android"
|
||||
it.packageName != FlClashApplication.getAppContext().packageName && (
|
||||
it.requestedPermissions?.contains(Manifest.permission.INTERNET) == true
|
||||
|| it.packageName == "android"
|
||||
)
|
||||
|
||||
}?.map {
|
||||
Package(
|
||||
packageName = it.packageName,
|
||||
label = it.applicationInfo?.loadLabel(packageManager).toString(),
|
||||
system = (it.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM)) == 1,
|
||||
lastUpdateTime = it.lastUpdateTime,
|
||||
internet = it.requestedPermissions?.contains(Manifest.permission.INTERNET) == true
|
||||
)
|
||||
}?.let { packages.addAll(it) }
|
||||
Package(
|
||||
packageName = it.packageName,
|
||||
label = it.applicationInfo?.loadLabel(packageManager).toString(),
|
||||
isSystem = (it.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM)) == 1,
|
||||
lastUpdateTime = it.lastUpdateTime
|
||||
)
|
||||
}?.let { packages.addAll(it) }
|
||||
return packages
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ fun Service.startForeground(notification: Notification) {
|
||||
}
|
||||
}
|
||||
|
||||
Log.d("[FlClash]","startForeground===>")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
try {
|
||||
startForeground(
|
||||
|
||||
@@ -34,10 +34,6 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
if (options.ipv4Address.isNotEmpty()) {
|
||||
val cidr = options.ipv4Address.toCIDR()
|
||||
addAddress(cidr.address, cidr.prefixLength)
|
||||
Log.d(
|
||||
"addAddress",
|
||||
"address: ${cidr.address} prefixLength:${cidr.prefixLength}"
|
||||
)
|
||||
val routeAddress = options.getIpv4RouteAddress()
|
||||
if (routeAddress.isNotEmpty()) {
|
||||
try {
|
||||
@@ -54,39 +50,26 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
} else {
|
||||
addRoute("0.0.0.0", 0)
|
||||
}
|
||||
} else {
|
||||
addRoute("0.0.0.0", 0)
|
||||
}
|
||||
try {
|
||||
if (options.ipv6Address.isNotEmpty()) {
|
||||
val cidr = options.ipv6Address.toCIDR()
|
||||
Log.d(
|
||||
"addAddress6",
|
||||
"address: ${cidr.address} prefixLength:${cidr.prefixLength}"
|
||||
)
|
||||
addAddress(cidr.address, cidr.prefixLength)
|
||||
val routeAddress = options.getIpv6RouteAddress()
|
||||
if (routeAddress.isNotEmpty()) {
|
||||
try {
|
||||
routeAddress.forEach { i ->
|
||||
Log.d(
|
||||
"addRoute6",
|
||||
"address: ${i.address} prefixLength:${i.prefixLength}"
|
||||
)
|
||||
addRoute(i.address, i.prefixLength)
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
addRoute("::", 0)
|
||||
if (options.ipv6Address.isNotEmpty()) {
|
||||
val cidr = options.ipv6Address.toCIDR()
|
||||
addAddress(cidr.address, cidr.prefixLength)
|
||||
val routeAddress = options.getIpv6RouteAddress()
|
||||
if (routeAddress.isNotEmpty()) {
|
||||
try {
|
||||
routeAddress.forEach { i ->
|
||||
Log.d(
|
||||
"addRoute6",
|
||||
"address: ${i.address} prefixLength:${i.prefixLength}"
|
||||
)
|
||||
addRoute(i.address, i.prefixLength)
|
||||
}
|
||||
} else {
|
||||
} catch (_: Exception) {
|
||||
addRoute("::", 0)
|
||||
}
|
||||
} else {
|
||||
addRoute("::", 0)
|
||||
}
|
||||
}catch (_:Exception){
|
||||
Log.d(
|
||||
"addAddress6",
|
||||
"IPv6 is not supported."
|
||||
)
|
||||
}
|
||||
addDnsServer(options.dnsServerAddress)
|
||||
setMtu(9000)
|
||||
|
||||
@@ -392,8 +392,5 @@
|
||||
"messageTestTip": "This is a message.",
|
||||
"crashTest": "Crash test",
|
||||
"clearData": "Clear Data",
|
||||
"textScale": "Text Scaling",
|
||||
"internet": "Internet",
|
||||
"systemApp": "System APP",
|
||||
"noNetworkApp": "No network App"
|
||||
"textScale": "Text Scaling"
|
||||
}
|
||||
@@ -393,8 +393,5 @@
|
||||
"crashTest": "クラッシュテスト",
|
||||
"clearData": "データを消去",
|
||||
"zoom": "ズーム",
|
||||
"textScale": "テキストスケーリング",
|
||||
"internet": "インターネット",
|
||||
"systemApp": "システムアプリ",
|
||||
"noNetworkApp": "ネットワークなしアプリ"
|
||||
"textScale": "テキストスケーリング"
|
||||
}
|
||||
@@ -393,8 +393,5 @@
|
||||
"crashTest": "Тест на сбои",
|
||||
"clearData": "Очистить данные",
|
||||
"zoom": "Масштаб",
|
||||
"textScale": "Масштабирование текста",
|
||||
"internet": "Интернет",
|
||||
"systemApp": "Системное приложение",
|
||||
"noNetworkApp": "Приложение без сети"
|
||||
"textScale": "Масштабирование текста"
|
||||
}
|
||||
@@ -393,8 +393,5 @@
|
||||
"crashTest": "崩溃测试",
|
||||
"clearData": "清除数据",
|
||||
"zoom": "缩放",
|
||||
"textScale": "文本缩放",
|
||||
"internet": "互联网",
|
||||
"systemApp": "系统应用",
|
||||
"noNetworkApp": "无网络应用"
|
||||
"textScale": "文本缩放"
|
||||
}
|
||||
|
||||
@@ -98,13 +98,13 @@ func handleStopTun() {
|
||||
}
|
||||
}
|
||||
|
||||
func handleStartTun(fd int, callback unsafe.Pointer) {
|
||||
func handleStartTun(fd int, callback unsafe.Pointer) bool {
|
||||
handleStopTun()
|
||||
tunLock.Lock()
|
||||
defer tunLock.Unlock()
|
||||
now := time.Now()
|
||||
runTime = &now
|
||||
if fd != 0 {
|
||||
tunLock.Lock()
|
||||
defer tunLock.Unlock()
|
||||
tunHandler = &TunHandler{
|
||||
callback: callback,
|
||||
limit: semaphore.NewWeighted(4),
|
||||
@@ -113,11 +113,13 @@ func handleStartTun(fd int, callback unsafe.Pointer) {
|
||||
tunListener, _ := t.Start(fd, currentConfig.General.Tun.Device, currentConfig.General.Tun.Stack)
|
||||
if tunListener != nil {
|
||||
log.Infoln("TUN address: %v", tunListener.Address())
|
||||
tunHandler.listener = tunListener
|
||||
} else {
|
||||
removeTunHook()
|
||||
return false
|
||||
}
|
||||
tunHandler.listener = tunListener
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func handleGetRunTime() string {
|
||||
@@ -226,10 +228,7 @@ func quickStart(initParamsChar *C.char, paramsChar *C.char, stateParamsChar *C.c
|
||||
|
||||
//export startTUN
|
||||
func startTUN(fd C.int, callback unsafe.Pointer) bool {
|
||||
go func() {
|
||||
handleStartTun(int(fd), callback)
|
||||
}()
|
||||
return true
|
||||
return handleStartTun(int(fd), callback)
|
||||
}
|
||||
|
||||
//export getRunTime
|
||||
@@ -239,9 +238,7 @@ func getRunTime() *C.char {
|
||||
|
||||
//export stopTun
|
||||
func stopTun() {
|
||||
go func() {
|
||||
handleStopTun()
|
||||
}()
|
||||
handleStopTun()
|
||||
}
|
||||
|
||||
//export getCurrentProfileName
|
||||
|
||||
@@ -24,6 +24,7 @@ type AccessControl struct {
|
||||
Mode string `json:"mode"`
|
||||
AcceptList []string `json:"acceptList"`
|
||||
RejectList []string `json:"rejectList"`
|
||||
IsFilterSystemApp bool `json:"isFilterSystemApp"`
|
||||
}
|
||||
|
||||
type AndroidVpnRawOptions struct {
|
||||
|
||||
@@ -245,6 +245,7 @@ abstract class ClashHandlerInterface with ClashInterface {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<bool> crash() {
|
||||
return invoke<bool>(
|
||||
|
||||
@@ -71,9 +71,9 @@ class ClashService extends ClashHandlerInterface {
|
||||
}
|
||||
}, (error, stack) {
|
||||
commonPrint.log(error.toString());
|
||||
if (error is SocketException) {
|
||||
if(error is SocketException){
|
||||
globalState.showNotifier(error.toString());
|
||||
// globalState.appController.restartCore();
|
||||
globalState.appController.restartCore();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,8 +16,7 @@ const browserUa =
|
||||
const packageName = "com.follow.clash";
|
||||
final unixSocketPath = "/tmp/FlClashSocket_${Random().nextInt(10000)}.sock";
|
||||
const helperPort = 47890;
|
||||
const maxTextScale = 1.4;
|
||||
const minTextScale = 0.8;
|
||||
const helperTag = "2024125";
|
||||
final baseInfoEdgeInsets = EdgeInsets.symmetric(
|
||||
vertical: 16.ap,
|
||||
horizontal: 16.ap,
|
||||
@@ -57,7 +56,6 @@ final commonFilter = ImageFilter.blur(
|
||||
const navigationItemListEquality = ListEquality<NavigationItem>();
|
||||
const connectionListEquality = ListEquality<Connection>();
|
||||
const stringListEquality = ListEquality<String>();
|
||||
const intListEquality = ListEquality<int>();
|
||||
const logListEquality = ListEquality<Log>();
|
||||
const groupListEquality = ListEquality<Group>();
|
||||
const externalProviderListEquality = ListEquality<ExternalProvider>();
|
||||
|
||||
@@ -130,7 +130,7 @@ class Request {
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
return false;
|
||||
}
|
||||
return (response.data as String) == globalState.helperToken;
|
||||
return (response.data as String) == helperTag;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -396,9 +396,9 @@ class AppController {
|
||||
handleExit() async {
|
||||
try {
|
||||
await updateStatus(false);
|
||||
await proxy?.stopProxy();
|
||||
await clashCore.shutdown();
|
||||
await clashService?.destroy();
|
||||
await proxy?.stopProxy();
|
||||
await savePreferences();
|
||||
} finally {
|
||||
system.exit();
|
||||
@@ -487,10 +487,10 @@ class AppController {
|
||||
Future<void> _initCore() async {
|
||||
final isInit = await clashCore.isInit;
|
||||
if (!isInit) {
|
||||
await clashCore.init();
|
||||
await clashCore.setState(
|
||||
globalState.getCoreState(),
|
||||
);
|
||||
await clashCore.init();
|
||||
}
|
||||
await applyProfile();
|
||||
}
|
||||
@@ -941,34 +941,29 @@ class AppController {
|
||||
|
||||
_recovery(Config config, RecoveryOption recoveryOption) {
|
||||
final profiles = config.profiles;
|
||||
final oldProfiles = List.from(globalState.config.profiles);
|
||||
_ref.read(profilesProvider.notifier).value = profiles;
|
||||
for (final profile in oldProfiles) {
|
||||
_ref.read(profilesProvider.notifier).setProfile(
|
||||
profile,
|
||||
force: false,
|
||||
);
|
||||
for (final profile in profiles) {
|
||||
_ref.read(profilesProvider.notifier).setProfile(profile);
|
||||
}
|
||||
final onlyProfiles = recoveryOption == RecoveryOption.onlyProfiles;
|
||||
if (!onlyProfiles) {
|
||||
_ref.read(patchClashConfigProvider.notifier).value =
|
||||
config.patchClashConfig;
|
||||
_ref.read(appSettingProvider.notifier).value = config.appSetting;
|
||||
_ref.read(currentProfileIdProvider.notifier).value =
|
||||
config.currentProfileId;
|
||||
_ref.read(appDAVSettingProvider.notifier).value = config.dav;
|
||||
_ref.read(themeSettingProvider.notifier).value = config.themeProps;
|
||||
_ref.read(windowSettingProvider.notifier).value = config.windowProps;
|
||||
_ref.read(vpnSettingProvider.notifier).value = config.vpnProps;
|
||||
_ref.read(proxiesStyleSettingProvider.notifier).value =
|
||||
config.proxiesStyle;
|
||||
_ref.read(overrideDnsProvider.notifier).value = config.overrideDns;
|
||||
_ref.read(networkSettingProvider.notifier).value = config.networkProps;
|
||||
_ref.read(hotKeyActionsProvider.notifier).value = config.hotKeyActions;
|
||||
}
|
||||
final currentProfile = _ref.read(currentProfileProvider);
|
||||
if (currentProfile == null) {
|
||||
_ref.read(currentProfileIdProvider.notifier).value = profiles.first.id;
|
||||
if (onlyProfiles) {
|
||||
final currentProfile = _ref.read(currentProfileProvider);
|
||||
if (currentProfile != null) {
|
||||
_ref.read(currentProfileIdProvider.notifier).value = profiles.first.id;
|
||||
}
|
||||
return;
|
||||
}
|
||||
_ref.read(patchClashConfigProvider.notifier).value =
|
||||
config.patchClashConfig;
|
||||
_ref.read(appSettingProvider.notifier).value = config.appSetting;
|
||||
_ref.read(currentProfileIdProvider.notifier).value =
|
||||
config.currentProfileId;
|
||||
_ref.read(appDAVSettingProvider.notifier).value = config.dav;
|
||||
_ref.read(themeSettingProvider.notifier).value = config.themeProps;
|
||||
_ref.read(windowSettingProvider.notifier).value = config.windowProps;
|
||||
_ref.read(vpnSettingProvider.notifier).value = config.vpnProps;
|
||||
_ref.read(proxiesStyleSettingProvider.notifier).value = config.proxiesStyle;
|
||||
_ref.read(overrideDnsProvider.notifier).value = config.overrideDns;
|
||||
_ref.read(networkSettingProvider.notifier).value = config.networkProps;
|
||||
_ref.read(hotKeyActionsProvider.notifier).value = config.hotKeyActions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +293,6 @@ enum WindowsHelperServiceStatus {
|
||||
|
||||
enum DebounceTag {
|
||||
updateClashConfig,
|
||||
updateStatus,
|
||||
updateGroups,
|
||||
addCheckIpNum,
|
||||
applyProfile,
|
||||
@@ -348,15 +347,6 @@ enum DashboardWidget {
|
||||
),
|
||||
platforms: desktopPlatforms,
|
||||
),
|
||||
vpnButton(
|
||||
GridItem(
|
||||
crossAxisCellCount: 4,
|
||||
child: VpnButton(),
|
||||
),
|
||||
platforms: [
|
||||
SupportPlatform.Android,
|
||||
],
|
||||
),
|
||||
systemProxyButton(
|
||||
GridItem(
|
||||
crossAxisCellCount: 4,
|
||||
|
||||
@@ -113,11 +113,15 @@ class _AccessFragmentState extends ConsumerState<AccessFragment> {
|
||||
}
|
||||
|
||||
_intelligentSelected() async {
|
||||
final packageNames = ref.read(
|
||||
packageListSelectorStateProvider.select(
|
||||
(state) => state.list.map((item) => item.packageName),
|
||||
),
|
||||
);
|
||||
final appState = globalState.appState;
|
||||
final config = globalState.config;
|
||||
final accessControl = config.vpnProps.accessControl;
|
||||
final packageNames = appState.packages
|
||||
.where(
|
||||
(item) =>
|
||||
accessControl.isFilterSystemApp ? item.isSystem == false : true,
|
||||
)
|
||||
.map((item) => item.packageName);
|
||||
final commonScaffoldState = context.commonScaffoldState;
|
||||
if (commonScaffoldState?.mounted != true) return;
|
||||
final selectedPackageNames =
|
||||
@@ -190,7 +194,7 @@ class _AccessFragmentState extends ConsumerState<AccessFragment> {
|
||||
final state = ref.watch(packageListSelectorStateProvider);
|
||||
final accessControl = state.accessControl;
|
||||
final accessControlMode = accessControl.mode;
|
||||
final packages = state.getSortList(
|
||||
final packages = state.getList(
|
||||
accessControlMode == AccessControlMode.acceptSelected
|
||||
? acceptList
|
||||
: rejectList,
|
||||
@@ -478,20 +482,14 @@ class AccessControlSearchDelegate extends SearchDelegate {
|
||||
final lowQuery = query.toLowerCase();
|
||||
return Consumer(
|
||||
builder: (context, ref, __) {
|
||||
final vm3 = ref.watch(
|
||||
packageListSelectorStateProvider.select(
|
||||
(state) => VM3(
|
||||
a: state.getSortList(
|
||||
state.accessControl.mode == AccessControlMode.acceptSelected
|
||||
? acceptList
|
||||
: rejectList,
|
||||
),
|
||||
b: state.accessControl.enable,
|
||||
c: state.accessControl.currentList,
|
||||
),
|
||||
),
|
||||
final state = ref.watch(packageListSelectorStateProvider);
|
||||
final accessControl = state.accessControl;
|
||||
final accessControlMode = accessControl.mode;
|
||||
final packages = state.getList(
|
||||
accessControlMode == AccessControlMode.acceptSelected
|
||||
? acceptList
|
||||
: rejectList,
|
||||
);
|
||||
final packages = vm3.a;
|
||||
final queryPackages = packages
|
||||
.where(
|
||||
(package) =>
|
||||
@@ -499,8 +497,8 @@ class AccessControlSearchDelegate extends SearchDelegate {
|
||||
package.packageName.contains(lowQuery),
|
||||
)
|
||||
.toList();
|
||||
final isAccessControl = vm3.b;
|
||||
final currentList = vm3.c;
|
||||
final isAccessControl = state.accessControl.enable;
|
||||
final currentList = accessControl.currentList;
|
||||
final packageNameList = packages.map((e) => e.packageName).toList();
|
||||
final valueList = currentList.intersection(packageNameList);
|
||||
return DisabledMask(
|
||||
@@ -581,6 +579,13 @@ class _AccessControlPanelState extends ConsumerState<AccessControlPanel> {
|
||||
};
|
||||
}
|
||||
|
||||
String _getTextWithIsFilterSystemApp(bool isFilterSystemApp) {
|
||||
return switch (isFilterSystemApp) {
|
||||
true => appLocalizations.onlyOtherApps,
|
||||
false => appLocalizations.allApps,
|
||||
};
|
||||
}
|
||||
|
||||
List<Widget> _buildModeSetting() {
|
||||
return generateSection(
|
||||
title: appLocalizations.mode,
|
||||
@@ -668,39 +673,25 @@ class _AccessControlPanelState extends ConsumerState<AccessControlPanel> {
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final vm2 = ref.watch(
|
||||
vpnSettingProvider.select(
|
||||
(state) => VM2(
|
||||
a: state.accessControl.isFilterSystemApp,
|
||||
b: state.accessControl.isFilterNonInternetApp,
|
||||
),
|
||||
),
|
||||
final isFilterSystemApp = ref.watch(
|
||||
vpnSettingProvider
|
||||
.select((state) => state.accessControl.isFilterSystemApp),
|
||||
);
|
||||
return Wrap(
|
||||
spacing: 16,
|
||||
children: [
|
||||
SettingTextCard(
|
||||
appLocalizations.systemApp,
|
||||
isSelected: vm2.a == false,
|
||||
onPressed: () {
|
||||
ref.read(vpnSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith.accessControl(
|
||||
isFilterSystemApp: !vm2.a,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
SettingTextCard(
|
||||
appLocalizations.noNetworkApp,
|
||||
isSelected: vm2.b == false,
|
||||
onPressed: () {
|
||||
ref.read(vpnSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith.accessControl(
|
||||
isFilterNonInternetApp: !vm2.b,
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
for (final item in [false, true])
|
||||
SettingTextCard(
|
||||
_getTextWithIsFilterSystemApp(item),
|
||||
isSelected: isFilterSystemApp == item,
|
||||
onPressed: () {
|
||||
ref.read(vpnSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith.accessControl(
|
||||
isFilterSystemApp: item,
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
|
||||
@@ -301,11 +301,8 @@ class RouteAddressItem extends ConsumerWidget {
|
||||
title: appLocalizations.routeAddress,
|
||||
widget: Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final routeAddress = ref.watch(
|
||||
patchClashConfigProvider.select(
|
||||
(state) => state.tun.routeAddress,
|
||||
),
|
||||
);
|
||||
final routeAddress = ref.watch(patchClashConfigProvider
|
||||
.select((state) => state.tun.routeAddress));
|
||||
return ListInputPage(
|
||||
title: appLocalizations.routeAddress,
|
||||
items: routeAddress,
|
||||
@@ -374,9 +371,7 @@ class NetworkListView extends ConsumerWidget {
|
||||
return;
|
||||
}
|
||||
ref.read(vpnSettingProvider.notifier).updateState(
|
||||
(state) => defaultVpnProps.copyWith(
|
||||
accessControl: state.accessControl,
|
||||
),
|
||||
(state) => defaultVpnProps,
|
||||
);
|
||||
ref.read(patchClashConfigProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
|
||||
@@ -24,9 +24,10 @@ class OutboundMode extends StatelessWidget {
|
||||
);
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
hoverColor: Colors.transparent),
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
hoverColor: Colors.transparent
|
||||
),
|
||||
child: CommonCard(
|
||||
onPressed: () {},
|
||||
info: Info(
|
||||
@@ -131,12 +132,10 @@ class OutboundModeV2 extends StatelessWidget {
|
||||
.titleSmall
|
||||
?.adjustSize(1)
|
||||
.copyWith(
|
||||
color: item == mode
|
||||
? _getTextColor(
|
||||
context,
|
||||
item,
|
||||
)
|
||||
: null,
|
||||
color: _getTextColor(
|
||||
context,
|
||||
mode,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -165,87 +165,3 @@ class SystemProxyButton extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class VpnButton extends StatelessWidget {
|
||||
const VpnButton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: getWidgetHeight(1),
|
||||
child: CommonCard(
|
||||
onPressed: () {
|
||||
showSheet(
|
||||
context: context,
|
||||
builder: (_, type) {
|
||||
return AdaptiveSheetScaffold(
|
||||
type: type,
|
||||
body: generateListView(
|
||||
generateSection(
|
||||
items: [
|
||||
const VPNItem(),
|
||||
const VpnSystemProxyItem(),
|
||||
const TunStackItem(),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: "VPN",
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
info: Info(
|
||||
label: "VPN",
|
||||
iconData: Icons.stacked_line_chart,
|
||||
),
|
||||
child: Container(
|
||||
padding: baseInfoEdgeInsets.copyWith(
|
||||
top: 4,
|
||||
bottom: 8,
|
||||
right: 8,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: TooltipText(
|
||||
text: Text(
|
||||
appLocalizations.options,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall
|
||||
?.adjustSize(-2)
|
||||
.toLight,
|
||||
),
|
||||
),
|
||||
),
|
||||
Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final enable = ref.watch(
|
||||
vpnSettingProvider.select(
|
||||
(state) => state.enable,
|
||||
),
|
||||
);
|
||||
return Switch(
|
||||
value: enable,
|
||||
onChanged: (value) {
|
||||
ref.read(vpnSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
enable: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/models/models.dart';
|
||||
import 'package:fl_clash/providers/providers.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
@@ -36,15 +35,11 @@ class _StartButtonState extends State<StartButton>
|
||||
}
|
||||
|
||||
handleSwitchStart() {
|
||||
isStart = !isStart;
|
||||
updateController();
|
||||
debouncer.call(
|
||||
DebounceTag.updateStatus,
|
||||
() {
|
||||
globalState.appController.updateStatus(isStart);
|
||||
},
|
||||
duration: moreDuration,
|
||||
);
|
||||
if (isStart == globalState.appState.isStart) {
|
||||
isStart = !isStart;
|
||||
updateController();
|
||||
globalState.appController.updateStatus(isStart);
|
||||
}
|
||||
}
|
||||
|
||||
updateController() {
|
||||
@@ -131,11 +126,9 @@ class _StartButtonState extends State<StartButton>
|
||||
final text = utils.getTimeText(runTime);
|
||||
return Text(
|
||||
text,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium
|
||||
?.toSoftBold
|
||||
.copyWith(color: context.colorScheme.onPrimaryContainer),
|
||||
style: Theme.of(context).textTheme.titleMedium?.toSoftBold.copyWith(
|
||||
color: context.colorScheme.onPrimaryContainer
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:fl_clash/state.dart';
|
||||
|
||||
double get listHeaderHeight {
|
||||
final measure = globalState.measure;
|
||||
return 28 + measure.titleMediumHeight + 4 + measure.bodyMediumHeight;
|
||||
return 24 + measure.titleMediumHeight + 4 + measure.bodyMediumHeight;
|
||||
}
|
||||
|
||||
double getItemHeight(ProxyCardType proxyCardType) {
|
||||
|
||||
@@ -414,10 +414,7 @@ class _ListHeaderState extends State<ListHeader>
|
||||
return Consumer(
|
||||
builder: (_, ref, child) {
|
||||
final iconStyle = ref.watch(
|
||||
proxiesStyleSettingProvider.select(
|
||||
(state) => state.iconStyle,
|
||||
),
|
||||
);
|
||||
proxiesStyleSettingProvider.select((state) => state.iconStyle));
|
||||
final icon = ref.watch(proxiesStyleSettingProvider.select((state) {
|
||||
final iconMapEntryList = state.iconMap.entries.toList();
|
||||
final index = iconMapEntryList.indexWhere((item) {
|
||||
@@ -433,44 +430,30 @@ class _ListHeaderState extends State<ListHeader>
|
||||
return this.icon;
|
||||
}));
|
||||
return switch (iconStyle) {
|
||||
ProxiesIconStyle.standard => LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(
|
||||
right: 16,
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: Container(
|
||||
height: constraints.maxHeight,
|
||||
width: constraints.maxWidth,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.all(6.ap),
|
||||
decoration: BoxDecoration(
|
||||
color: context.colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: CommonTargetIcon(
|
||||
src: icon,
|
||||
size: constraints.maxHeight - 12.ap,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
ProxiesIconStyle.standard => Container(
|
||||
height: 48,
|
||||
width: 48,
|
||||
margin: const EdgeInsets.only(
|
||||
right: 16,
|
||||
),
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: context.colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: CommonTargetIcon(
|
||||
src: icon,
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
ProxiesIconStyle.icon => Container(
|
||||
margin: const EdgeInsets.only(
|
||||
right: 16,
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
return CommonTargetIcon(
|
||||
src: icon,
|
||||
size: constraints.maxHeight - 8,
|
||||
);
|
||||
},
|
||||
child: CommonTargetIcon(
|
||||
src: icon,
|
||||
size: 42,
|
||||
),
|
||||
),
|
||||
ProxiesIconStyle.none => Container(),
|
||||
|
||||
@@ -78,7 +78,7 @@ class _ProxiesFragmentState extends ConsumerState<ProxiesFragment>
|
||||
return AdaptiveSheetScaffold(
|
||||
type: type,
|
||||
body: const ProxiesSetting(),
|
||||
title: appLocalizations.settings,
|
||||
title: appLocalizations.proxiesSetting,
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -123,13 +123,8 @@ class _ProxiesFragmentState extends ConsumerState<ProxiesFragment>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final proxiesType = ref.watch(
|
||||
proxiesStyleSettingProvider.select(
|
||||
(state) => state.type,
|
||||
),
|
||||
);
|
||||
|
||||
ref.watch(themeSettingProvider.select((state) => state.textScale));
|
||||
final proxiesType =
|
||||
ref.watch(proxiesStyleSettingProvider.select((state) => state.type));
|
||||
return switch (proxiesType) {
|
||||
ProxiesType.tab => ProxiesTabFragment(
|
||||
key: _proxiesTabKey,
|
||||
|
||||
@@ -147,21 +147,22 @@ class _GeoDataListItemState extends State<GeoDataListItem> {
|
||||
FutureBuilder<FileInfo>(
|
||||
future: _getGeoFileLastModified(geoItem.fileName),
|
||||
builder: (_, snapshot) {
|
||||
final height = globalState.measure.bodyMediumHeight;
|
||||
return SizedBox(
|
||||
height: height,
|
||||
child: snapshot.data == null
|
||||
? SizedBox(
|
||||
width: height,
|
||||
height: height,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
height: 24,
|
||||
child: FadeThroughBox(
|
||||
key: Key("fade_box_${geoItem.label}"),
|
||||
child: snapshot.data == null
|
||||
? const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
snapshot.data!.desc,
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
snapshot.data!.desc,
|
||||
style: context.textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// ignore_for_file: deprecated_member_use
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'dart:ui' as ui;
|
||||
@@ -43,7 +41,6 @@ class ThemeFragment extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
_ThemeModeItem(),
|
||||
_PrimaryColorItem(),
|
||||
@@ -72,15 +69,20 @@ class ItemCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Wrap(
|
||||
runSpacing: 16,
|
||||
children: [
|
||||
InfoHeader(
|
||||
info: info,
|
||||
actions: actions,
|
||||
),
|
||||
child,
|
||||
],
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 16,
|
||||
),
|
||||
child: Wrap(
|
||||
runSpacing: 16,
|
||||
children: [
|
||||
InfoHeader(
|
||||
info: info,
|
||||
actions: actions,
|
||||
),
|
||||
child,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -283,21 +285,18 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final vm4 = ref.watch(
|
||||
final vm3 = ref.watch(
|
||||
themeSettingProvider.select(
|
||||
(state) => VM4(
|
||||
(state) => VM3(
|
||||
a: state.primaryColor,
|
||||
b: state.primaryColors,
|
||||
c: state.schemeVariant,
|
||||
d: state.primaryColor == defaultPrimaryColor &&
|
||||
intListEquality.equals(state.primaryColors, defaultPrimaryColors),
|
||||
),
|
||||
),
|
||||
);
|
||||
final primaryColor = vm4.a;
|
||||
final primaryColors = [null, ...vm4.b];
|
||||
final schemeVariant = vm4.c;
|
||||
final isEquals = vm4.d;
|
||||
final primaryColor = vm3.a;
|
||||
final primaryColors = [null, ...vm3.b];
|
||||
final schemeVariant = vm3.c;
|
||||
|
||||
return CommonPopScope(
|
||||
onPop: () {
|
||||
@@ -324,32 +323,33 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
||||
onPressed: _handleChangeSchemeVariant,
|
||||
child: Text(Intl.message("${schemeVariant.name}Scheme")),
|
||||
),
|
||||
if (_removablePrimaryColor != null)
|
||||
FilledButton(
|
||||
style: ButtonStyle(
|
||||
visualDensity: VisualDensity.compact,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_removablePrimaryColor = null;
|
||||
});
|
||||
},
|
||||
child: Text(appLocalizations.cancel),
|
||||
),
|
||||
if (_removablePrimaryColor == null && !isEquals)
|
||||
IconButton.filledTonal(
|
||||
iconSize: 20,
|
||||
padding: EdgeInsets.all(4),
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: _handleReset,
|
||||
icon: Icon(Icons.replay),
|
||||
)
|
||||
_removablePrimaryColor != null
|
||||
? FilledButton(
|
||||
style: ButtonStyle(
|
||||
visualDensity: VisualDensity.compact,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_removablePrimaryColor = null;
|
||||
});
|
||||
},
|
||||
child: Text(appLocalizations.cancel),
|
||||
)
|
||||
: IconButton.filledTonal(
|
||||
iconSize: 20,
|
||||
padding: EdgeInsets.all(4),
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: _handleReset,
|
||||
icon: Icon(Icons.replay),
|
||||
)
|
||||
],
|
||||
space: 8,
|
||||
),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
margin: const EdgeInsets.only(
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 16,
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
@@ -441,31 +441,31 @@ class _PrueBlackItem extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final prueBlack = ref.watch(
|
||||
themeSettingProvider.select(
|
||||
(state) => state.pureBlack,
|
||||
),
|
||||
);
|
||||
return ListItem.switchItem(
|
||||
leading: Icon(
|
||||
Icons.contrast,
|
||||
),
|
||||
horizontalTitleGap: 12,
|
||||
title: Text(
|
||||
appLocalizations.pureBlackMode,
|
||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||
color: context.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
delegate: SwitchDelegate(
|
||||
value: prueBlack,
|
||||
onChanged: (value) {
|
||||
ref.read(themeSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
pureBlack: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
final prueBlack =
|
||||
ref.watch(themeSettingProvider.select((state) => state.pureBlack));
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: ListItem.switchItem(
|
||||
leading: Icon(
|
||||
Icons.contrast,
|
||||
),
|
||||
horizontalTitleGap: 12,
|
||||
title: Text(
|
||||
appLocalizations.pureBlackMode,
|
||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||
color: context.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
delegate: SwitchDelegate(
|
||||
value: prueBlack,
|
||||
onChanged: (value) {
|
||||
ref.read(themeSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
pureBlack: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -481,12 +481,13 @@ class _TextScaleFactorItem extends ConsumerWidget {
|
||||
(state) => state.textScale,
|
||||
),
|
||||
);
|
||||
final String process = "${((textScale.scale * 100) as double).round()}%";
|
||||
final String process =
|
||||
"${((textScale.scale * 100) as double).round()}%";
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(bottom: 8),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: ListItem.switchItem(
|
||||
leading: Icon(
|
||||
Icons.text_fields,
|
||||
@@ -510,45 +511,30 @@ class _TextScaleFactorItem extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
spacing: 32,
|
||||
children: [
|
||||
Expanded(
|
||||
child: DisabledMask(
|
||||
status: !textScale.enable,
|
||||
child: ActivateBox(
|
||||
active: textScale.enable,
|
||||
child: SliderTheme(
|
||||
data: _SliderDefaultsM3(context),
|
||||
child: Slider(
|
||||
padding: EdgeInsets.zero,
|
||||
min: minTextScale,
|
||||
max: maxTextScale,
|
||||
value: textScale.scale,
|
||||
onChanged: (value) {
|
||||
ref.read(themeSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith.textScale(
|
||||
scale: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
DisabledMask(
|
||||
status: !textScale.enable,
|
||||
child: ActivateBox(
|
||||
active: textScale.enable,
|
||||
child: SliderTheme(
|
||||
data: _SliderDefaultsM3(context),
|
||||
child: Slider(
|
||||
min: 0.8,
|
||||
divisions: 8,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
),
|
||||
max: 1.2,
|
||||
label: process,
|
||||
value: textScale.scale,
|
||||
onChanged: (value) {
|
||||
ref.read(themeSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith.textScale(
|
||||
scale: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 4),
|
||||
child: Text(
|
||||
process,
|
||||
style: context.textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -310,7 +310,7 @@ class _DeveloperItem extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListItem.open(
|
||||
leading: const Icon(Icons.developer_board),
|
||||
leading: const Icon(Icons.developer_mode),
|
||||
title: Text(appLocalizations.developerMode),
|
||||
delegate: OpenDelegate(
|
||||
title: appLocalizations.developerMode,
|
||||
|
||||
@@ -326,7 +326,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"intelligentSelected": MessageLookupByLibrary.simpleMessage(
|
||||
"Intelligent selection",
|
||||
),
|
||||
"internet": MessageLookupByLibrary.simpleMessage("Internet"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("Intranet IP"),
|
||||
"ipcidr": MessageLookupByLibrary.simpleMessage("Ipcidr"),
|
||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -410,7 +409,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"noInfo": MessageLookupByLibrary.simpleMessage("No info"),
|
||||
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("No more info"),
|
||||
"noNetwork": MessageLookupByLibrary.simpleMessage("No network"),
|
||||
"noNetworkApp": MessageLookupByLibrary.simpleMessage("No network App"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("No proxy"),
|
||||
"noProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Please create a profile or add a valid profile",
|
||||
@@ -624,7 +622,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"submit": MessageLookupByLibrary.simpleMessage("Submit"),
|
||||
"sync": MessageLookupByLibrary.simpleMessage("Sync"),
|
||||
"system": MessageLookupByLibrary.simpleMessage("System"),
|
||||
"systemApp": MessageLookupByLibrary.simpleMessage("System APP"),
|
||||
"systemFont": MessageLookupByLibrary.simpleMessage("System font"),
|
||||
"systemProxy": MessageLookupByLibrary.simpleMessage("System proxy"),
|
||||
"systemProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
|
||||
@@ -236,7 +236,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"init": MessageLookupByLibrary.simpleMessage("初期化"),
|
||||
"inputCorrectHotkey": MessageLookupByLibrary.simpleMessage("正しいホットキーを入力"),
|
||||
"intelligentSelected": MessageLookupByLibrary.simpleMessage("インテリジェント選択"),
|
||||
"internet": MessageLookupByLibrary.simpleMessage("インターネット"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("イントラネットIP"),
|
||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IPCIDR"),
|
||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage("有効化するとIPv6トラフィックを受信可能"),
|
||||
@@ -296,7 +295,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"noInfo": MessageLookupByLibrary.simpleMessage("情報なし"),
|
||||
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("追加情報なし"),
|
||||
"noNetwork": MessageLookupByLibrary.simpleMessage("ネットワークなし"),
|
||||
"noNetworkApp": MessageLookupByLibrary.simpleMessage("ネットワークなしアプリ"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("プロキシなし"),
|
||||
"noProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"プロファイルを作成するか、有効なプロファイルを追加してください",
|
||||
@@ -462,7 +460,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"submit": MessageLookupByLibrary.simpleMessage("送信"),
|
||||
"sync": MessageLookupByLibrary.simpleMessage("同期"),
|
||||
"system": MessageLookupByLibrary.simpleMessage("システム"),
|
||||
"systemApp": MessageLookupByLibrary.simpleMessage("システムアプリ"),
|
||||
"systemFont": MessageLookupByLibrary.simpleMessage("システムフォント"),
|
||||
"systemProxy": MessageLookupByLibrary.simpleMessage("システムプロキシ"),
|
||||
"systemProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
|
||||
@@ -348,7 +348,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"intelligentSelected": MessageLookupByLibrary.simpleMessage(
|
||||
"Интеллектуальный выбор",
|
||||
),
|
||||
"internet": MessageLookupByLibrary.simpleMessage("Интернет"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("Внутренний IP"),
|
||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IPCIDR"),
|
||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -438,7 +437,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Нет дополнительной информации",
|
||||
),
|
||||
"noNetwork": MessageLookupByLibrary.simpleMessage("Нет сети"),
|
||||
"noNetworkApp": MessageLookupByLibrary.simpleMessage("Приложение без сети"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("Нет прокси"),
|
||||
"noProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Пожалуйста, создайте профиль или добавьте действительный профиль",
|
||||
@@ -662,7 +660,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"submit": MessageLookupByLibrary.simpleMessage("Отправить"),
|
||||
"sync": MessageLookupByLibrary.simpleMessage("Синхронизация"),
|
||||
"system": MessageLookupByLibrary.simpleMessage("Система"),
|
||||
"systemApp": MessageLookupByLibrary.simpleMessage("Системное приложение"),
|
||||
"systemFont": MessageLookupByLibrary.simpleMessage("Системный шрифт"),
|
||||
"systemProxy": MessageLookupByLibrary.simpleMessage("Системный прокси"),
|
||||
"systemProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
|
||||
@@ -210,7 +210,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"init": MessageLookupByLibrary.simpleMessage("初始化"),
|
||||
"inputCorrectHotkey": MessageLookupByLibrary.simpleMessage("请输入正确的快捷键"),
|
||||
"intelligentSelected": MessageLookupByLibrary.simpleMessage("智能选择"),
|
||||
"internet": MessageLookupByLibrary.simpleMessage("互联网"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("内网 IP"),
|
||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IP/掩码"),
|
||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage("开启后将可以接收IPv6流量"),
|
||||
@@ -264,7 +263,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"noInfo": MessageLookupByLibrary.simpleMessage("暂无信息"),
|
||||
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("暂无更多信息"),
|
||||
"noNetwork": MessageLookupByLibrary.simpleMessage("无网络"),
|
||||
"noNetworkApp": MessageLookupByLibrary.simpleMessage("无网络应用"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("暂无代理"),
|
||||
"noProxyDesc": MessageLookupByLibrary.simpleMessage("请创建配置文件或者添加有效配置文件"),
|
||||
"noResolve": MessageLookupByLibrary.simpleMessage("不解析IP"),
|
||||
@@ -406,7 +404,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"submit": MessageLookupByLibrary.simpleMessage("提交"),
|
||||
"sync": MessageLookupByLibrary.simpleMessage("同步"),
|
||||
"system": MessageLookupByLibrary.simpleMessage("系统"),
|
||||
"systemApp": MessageLookupByLibrary.simpleMessage("系统应用"),
|
||||
"systemFont": MessageLookupByLibrary.simpleMessage("系统字体"),
|
||||
"systemProxy": MessageLookupByLibrary.simpleMessage("系统代理"),
|
||||
"systemProxyDesc": MessageLookupByLibrary.simpleMessage("设置系统代理"),
|
||||
|
||||
@@ -3059,26 +3059,6 @@ class AppLocalizations {
|
||||
String get textScale {
|
||||
return Intl.message('Text Scaling', name: 'textScale', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `Internet`
|
||||
String get internet {
|
||||
return Intl.message('Internet', name: 'internet', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `System APP`
|
||||
String get systemApp {
|
||||
return Intl.message('System APP', name: 'systemApp', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `No network App`
|
||||
String get noNetworkApp {
|
||||
return Intl.message(
|
||||
'No network App',
|
||||
name: 'noNetworkApp',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
|
||||
@@ -27,7 +27,6 @@ Future<void> main() async {
|
||||
await android?.init();
|
||||
await window?.init(version);
|
||||
globalState.isPre = const String.fromEnvironment("APP_ENV") != 'stable';
|
||||
globalState.helperToken = const String.fromEnvironment("HELPER_TOKEN");
|
||||
HttpOverrides.global = FlClashHttpOverrides();
|
||||
runApp(ProviderScope(
|
||||
child: const Application(),
|
||||
|
||||
@@ -23,9 +23,9 @@ class ThemeManager extends ConsumerWidget {
|
||||
final double textScaleFactor = max(
|
||||
min(
|
||||
textScale.enable ? textScale.scale : defaultTextScaleFactor,
|
||||
maxTextScale,
|
||||
1.2,
|
||||
),
|
||||
minTextScale,
|
||||
0.8,
|
||||
);
|
||||
|
||||
globalState.measure = Measure.of(context, textScaleFactor);
|
||||
|
||||
@@ -25,6 +25,7 @@ class WindowManager extends ConsumerStatefulWidget {
|
||||
|
||||
class _WindowContainerState extends ConsumerState<WindowManager>
|
||||
with WindowListener, WindowExtListener {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return widget.child;
|
||||
@@ -182,23 +183,19 @@ class _WindowHeaderState extends State<WindowHeader> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
_updateMaximized() async {
|
||||
final isMaximized = await windowManager.isMaximized();
|
||||
switch (isMaximized) {
|
||||
_updateMaximized() {
|
||||
isMaximizedNotifier.value = !isMaximizedNotifier.value;
|
||||
switch (isMaximizedNotifier.value) {
|
||||
case true:
|
||||
await windowManager.unmaximize();
|
||||
break;
|
||||
windowManager.maximize();
|
||||
case false:
|
||||
await windowManager.maximize();
|
||||
break;
|
||||
windowManager.unmaximize();
|
||||
}
|
||||
isMaximizedNotifier.value = await windowManager.isMaximized();
|
||||
}
|
||||
|
||||
_updatePin() async {
|
||||
final isAlwaysOnTop = await windowManager.isAlwaysOnTop();
|
||||
await windowManager.setAlwaysOnTop(!isAlwaysOnTop);
|
||||
isPinNotifier.value = await windowManager.isAlwaysOnTop();
|
||||
_updatePin() {
|
||||
isPinNotifier.value = !isPinNotifier.value;
|
||||
windowManager.setAlwaysOnTop(isPinNotifier.value);
|
||||
}
|
||||
|
||||
_buildActions() {
|
||||
|
||||
@@ -147,7 +147,6 @@ class Tun with _$Tun {
|
||||
const factory Tun({
|
||||
@Default(false) bool enable,
|
||||
@Default(appName) String device,
|
||||
@JsonKey(name: "auto-route") @Default(false) bool autoRoute,
|
||||
@Default(TunStack.gvisor) TunStack stack,
|
||||
@JsonKey(name: "dns-hijack") @Default(["any:53"]) List<String> dnsHijack,
|
||||
@JsonKey(name: "route-address") @Default([]) List<String> routeAddress,
|
||||
|
||||
@@ -30,8 +30,7 @@ class Package with _$Package {
|
||||
const factory Package({
|
||||
required String packageName,
|
||||
required String label,
|
||||
required bool system,
|
||||
required bool internet,
|
||||
required bool isSystem,
|
||||
required int lastUpdateTime,
|
||||
}) = _Package;
|
||||
|
||||
|
||||
@@ -106,7 +106,6 @@ class AccessControl with _$AccessControl {
|
||||
@Default([]) List<String> rejectList,
|
||||
@Default(AccessSortType.none) AccessSortType sort,
|
||||
@Default(true) bool isFilterSystemApp,
|
||||
@Default(true) bool isFilterNonInternetApp,
|
||||
}) = _AccessControl;
|
||||
|
||||
factory AccessControl.fromJson(Map<String, Object?> json) =>
|
||||
|
||||
@@ -660,8 +660,6 @@ Tun _$TunFromJson(Map<String, dynamic> json) {
|
||||
mixin _$Tun {
|
||||
bool get enable => throw _privateConstructorUsedError;
|
||||
String get device => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "auto-route")
|
||||
bool get autoRoute => throw _privateConstructorUsedError;
|
||||
TunStack get stack => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "dns-hijack")
|
||||
List<String> get dnsHijack => throw _privateConstructorUsedError;
|
||||
@@ -685,7 +683,6 @@ abstract class $TunCopyWith<$Res> {
|
||||
$Res call(
|
||||
{bool enable,
|
||||
String device,
|
||||
@JsonKey(name: "auto-route") bool autoRoute,
|
||||
TunStack stack,
|
||||
@JsonKey(name: "dns-hijack") List<String> dnsHijack,
|
||||
@JsonKey(name: "route-address") List<String> routeAddress});
|
||||
@@ -707,7 +704,6 @@ class _$TunCopyWithImpl<$Res, $Val extends Tun> implements $TunCopyWith<$Res> {
|
||||
$Res call({
|
||||
Object? enable = null,
|
||||
Object? device = null,
|
||||
Object? autoRoute = null,
|
||||
Object? stack = null,
|
||||
Object? dnsHijack = null,
|
||||
Object? routeAddress = null,
|
||||
@@ -721,10 +717,6 @@ class _$TunCopyWithImpl<$Res, $Val extends Tun> implements $TunCopyWith<$Res> {
|
||||
? _value.device
|
||||
: device // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
autoRoute: null == autoRoute
|
||||
? _value.autoRoute
|
||||
: autoRoute // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
stack: null == stack
|
||||
? _value.stack
|
||||
: stack // ignore: cast_nullable_to_non_nullable
|
||||
@@ -750,7 +742,6 @@ abstract class _$$TunImplCopyWith<$Res> implements $TunCopyWith<$Res> {
|
||||
$Res call(
|
||||
{bool enable,
|
||||
String device,
|
||||
@JsonKey(name: "auto-route") bool autoRoute,
|
||||
TunStack stack,
|
||||
@JsonKey(name: "dns-hijack") List<String> dnsHijack,
|
||||
@JsonKey(name: "route-address") List<String> routeAddress});
|
||||
@@ -769,7 +760,6 @@ class __$$TunImplCopyWithImpl<$Res> extends _$TunCopyWithImpl<$Res, _$TunImpl>
|
||||
$Res call({
|
||||
Object? enable = null,
|
||||
Object? device = null,
|
||||
Object? autoRoute = null,
|
||||
Object? stack = null,
|
||||
Object? dnsHijack = null,
|
||||
Object? routeAddress = null,
|
||||
@@ -783,10 +773,6 @@ class __$$TunImplCopyWithImpl<$Res> extends _$TunCopyWithImpl<$Res, _$TunImpl>
|
||||
? _value.device
|
||||
: device // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
autoRoute: null == autoRoute
|
||||
? _value.autoRoute
|
||||
: autoRoute // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
stack: null == stack
|
||||
? _value.stack
|
||||
: stack // ignore: cast_nullable_to_non_nullable
|
||||
@@ -809,7 +795,6 @@ class _$TunImpl implements _Tun {
|
||||
const _$TunImpl(
|
||||
{this.enable = false,
|
||||
this.device = appName,
|
||||
@JsonKey(name: "auto-route") this.autoRoute = false,
|
||||
this.stack = TunStack.gvisor,
|
||||
@JsonKey(name: "dns-hijack")
|
||||
final List<String> dnsHijack = const ["any:53"],
|
||||
@@ -828,9 +813,6 @@ class _$TunImpl implements _Tun {
|
||||
@JsonKey()
|
||||
final String device;
|
||||
@override
|
||||
@JsonKey(name: "auto-route")
|
||||
final bool autoRoute;
|
||||
@override
|
||||
@JsonKey()
|
||||
final TunStack stack;
|
||||
final List<String> _dnsHijack;
|
||||
@@ -853,7 +835,7 @@ class _$TunImpl implements _Tun {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Tun(enable: $enable, device: $device, autoRoute: $autoRoute, stack: $stack, dnsHijack: $dnsHijack, routeAddress: $routeAddress)';
|
||||
return 'Tun(enable: $enable, device: $device, stack: $stack, dnsHijack: $dnsHijack, routeAddress: $routeAddress)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -863,8 +845,6 @@ class _$TunImpl implements _Tun {
|
||||
other is _$TunImpl &&
|
||||
(identical(other.enable, enable) || other.enable == enable) &&
|
||||
(identical(other.device, device) || other.device == device) &&
|
||||
(identical(other.autoRoute, autoRoute) ||
|
||||
other.autoRoute == autoRoute) &&
|
||||
(identical(other.stack, stack) || other.stack == stack) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._dnsHijack, _dnsHijack) &&
|
||||
@@ -878,7 +858,6 @@ class _$TunImpl implements _Tun {
|
||||
runtimeType,
|
||||
enable,
|
||||
device,
|
||||
autoRoute,
|
||||
stack,
|
||||
const DeepCollectionEquality().hash(_dnsHijack),
|
||||
const DeepCollectionEquality().hash(_routeAddress));
|
||||
@@ -903,7 +882,6 @@ abstract class _Tun implements Tun {
|
||||
const factory _Tun(
|
||||
{final bool enable,
|
||||
final String device,
|
||||
@JsonKey(name: "auto-route") final bool autoRoute,
|
||||
final TunStack stack,
|
||||
@JsonKey(name: "dns-hijack") final List<String> dnsHijack,
|
||||
@JsonKey(name: "route-address") final List<String> routeAddress}) =
|
||||
@@ -916,9 +894,6 @@ abstract class _Tun implements Tun {
|
||||
@override
|
||||
String get device;
|
||||
@override
|
||||
@JsonKey(name: "auto-route")
|
||||
bool get autoRoute;
|
||||
@override
|
||||
TunStack get stack;
|
||||
@override
|
||||
@JsonKey(name: "dns-hijack")
|
||||
|
||||
@@ -66,7 +66,6 @@ Map<String, dynamic> _$$RuleProviderImplToJson(_$RuleProviderImpl instance) =>
|
||||
_$TunImpl _$$TunImplFromJson(Map<String, dynamic> json) => _$TunImpl(
|
||||
enable: json['enable'] as bool? ?? false,
|
||||
device: json['device'] as String? ?? appName,
|
||||
autoRoute: json['auto-route'] as bool? ?? false,
|
||||
stack: $enumDecodeNullable(_$TunStackEnumMap, json['stack']) ??
|
||||
TunStack.gvisor,
|
||||
dnsHijack: (json['dns-hijack'] as List<dynamic>?)
|
||||
@@ -82,7 +81,6 @@ _$TunImpl _$$TunImplFromJson(Map<String, dynamic> json) => _$TunImpl(
|
||||
Map<String, dynamic> _$$TunImplToJson(_$TunImpl instance) => <String, dynamic>{
|
||||
'enable': instance.enable,
|
||||
'device': instance.device,
|
||||
'auto-route': instance.autoRoute,
|
||||
'stack': _$TunStackEnumMap[instance.stack]!,
|
||||
'dns-hijack': instance.dnsHijack,
|
||||
'route-address': instance.routeAddress,
|
||||
|
||||
@@ -289,8 +289,7 @@ Package _$PackageFromJson(Map<String, dynamic> json) {
|
||||
mixin _$Package {
|
||||
String get packageName => throw _privateConstructorUsedError;
|
||||
String get label => throw _privateConstructorUsedError;
|
||||
bool get system => throw _privateConstructorUsedError;
|
||||
bool get internet => throw _privateConstructorUsedError;
|
||||
bool get isSystem => throw _privateConstructorUsedError;
|
||||
int get lastUpdateTime => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this Package to a JSON map.
|
||||
@@ -308,11 +307,7 @@ abstract class $PackageCopyWith<$Res> {
|
||||
_$PackageCopyWithImpl<$Res, Package>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String packageName,
|
||||
String label,
|
||||
bool system,
|
||||
bool internet,
|
||||
int lastUpdateTime});
|
||||
{String packageName, String label, bool isSystem, int lastUpdateTime});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -332,8 +327,7 @@ class _$PackageCopyWithImpl<$Res, $Val extends Package>
|
||||
$Res call({
|
||||
Object? packageName = null,
|
||||
Object? label = null,
|
||||
Object? system = null,
|
||||
Object? internet = null,
|
||||
Object? isSystem = null,
|
||||
Object? lastUpdateTime = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
@@ -345,13 +339,9 @@ class _$PackageCopyWithImpl<$Res, $Val extends Package>
|
||||
? _value.label
|
||||
: label // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
system: null == system
|
||||
? _value.system
|
||||
: system // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
internet: null == internet
|
||||
? _value.internet
|
||||
: internet // ignore: cast_nullable_to_non_nullable
|
||||
isSystem: null == isSystem
|
||||
? _value.isSystem
|
||||
: isSystem // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
lastUpdateTime: null == lastUpdateTime
|
||||
? _value.lastUpdateTime
|
||||
@@ -369,11 +359,7 @@ abstract class _$$PackageImplCopyWith<$Res> implements $PackageCopyWith<$Res> {
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String packageName,
|
||||
String label,
|
||||
bool system,
|
||||
bool internet,
|
||||
int lastUpdateTime});
|
||||
{String packageName, String label, bool isSystem, int lastUpdateTime});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -391,8 +377,7 @@ class __$$PackageImplCopyWithImpl<$Res>
|
||||
$Res call({
|
||||
Object? packageName = null,
|
||||
Object? label = null,
|
||||
Object? system = null,
|
||||
Object? internet = null,
|
||||
Object? isSystem = null,
|
||||
Object? lastUpdateTime = null,
|
||||
}) {
|
||||
return _then(_$PackageImpl(
|
||||
@@ -404,13 +389,9 @@ class __$$PackageImplCopyWithImpl<$Res>
|
||||
? _value.label
|
||||
: label // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
system: null == system
|
||||
? _value.system
|
||||
: system // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
internet: null == internet
|
||||
? _value.internet
|
||||
: internet // ignore: cast_nullable_to_non_nullable
|
||||
isSystem: null == isSystem
|
||||
? _value.isSystem
|
||||
: isSystem // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
lastUpdateTime: null == lastUpdateTime
|
||||
? _value.lastUpdateTime
|
||||
@@ -426,8 +407,7 @@ class _$PackageImpl implements _Package {
|
||||
const _$PackageImpl(
|
||||
{required this.packageName,
|
||||
required this.label,
|
||||
required this.system,
|
||||
required this.internet,
|
||||
required this.isSystem,
|
||||
required this.lastUpdateTime});
|
||||
|
||||
factory _$PackageImpl.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -438,15 +418,13 @@ class _$PackageImpl implements _Package {
|
||||
@override
|
||||
final String label;
|
||||
@override
|
||||
final bool system;
|
||||
@override
|
||||
final bool internet;
|
||||
final bool isSystem;
|
||||
@override
|
||||
final int lastUpdateTime;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Package(packageName: $packageName, label: $label, system: $system, internet: $internet, lastUpdateTime: $lastUpdateTime)';
|
||||
return 'Package(packageName: $packageName, label: $label, isSystem: $isSystem, lastUpdateTime: $lastUpdateTime)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -457,17 +435,16 @@ class _$PackageImpl implements _Package {
|
||||
(identical(other.packageName, packageName) ||
|
||||
other.packageName == packageName) &&
|
||||
(identical(other.label, label) || other.label == label) &&
|
||||
(identical(other.system, system) || other.system == system) &&
|
||||
(identical(other.internet, internet) ||
|
||||
other.internet == internet) &&
|
||||
(identical(other.isSystem, isSystem) ||
|
||||
other.isSystem == isSystem) &&
|
||||
(identical(other.lastUpdateTime, lastUpdateTime) ||
|
||||
other.lastUpdateTime == lastUpdateTime));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, packageName, label, system, internet, lastUpdateTime);
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, packageName, label, isSystem, lastUpdateTime);
|
||||
|
||||
/// Create a copy of Package
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -489,8 +466,7 @@ abstract class _Package implements Package {
|
||||
const factory _Package(
|
||||
{required final String packageName,
|
||||
required final String label,
|
||||
required final bool system,
|
||||
required final bool internet,
|
||||
required final bool isSystem,
|
||||
required final int lastUpdateTime}) = _$PackageImpl;
|
||||
|
||||
factory _Package.fromJson(Map<String, dynamic> json) = _$PackageImpl.fromJson;
|
||||
@@ -500,9 +476,7 @@ abstract class _Package implements Package {
|
||||
@override
|
||||
String get label;
|
||||
@override
|
||||
bool get system;
|
||||
@override
|
||||
bool get internet;
|
||||
bool get isSystem;
|
||||
@override
|
||||
int get lastUpdateTime;
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ _$PackageImpl _$$PackageImplFromJson(Map<String, dynamic> json) =>
|
||||
_$PackageImpl(
|
||||
packageName: json['packageName'] as String,
|
||||
label: json['label'] as String,
|
||||
system: json['system'] as bool,
|
||||
internet: json['internet'] as bool,
|
||||
isSystem: json['isSystem'] as bool,
|
||||
lastUpdateTime: (json['lastUpdateTime'] as num).toInt(),
|
||||
);
|
||||
|
||||
@@ -19,8 +18,7 @@ Map<String, dynamic> _$$PackageImplToJson(_$PackageImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'packageName': instance.packageName,
|
||||
'label': instance.label,
|
||||
'system': instance.system,
|
||||
'internet': instance.internet,
|
||||
'isSystem': instance.isSystem,
|
||||
'lastUpdateTime': instance.lastUpdateTime,
|
||||
};
|
||||
|
||||
|
||||
@@ -539,7 +539,6 @@ mixin _$AccessControl {
|
||||
List<String> get rejectList => throw _privateConstructorUsedError;
|
||||
AccessSortType get sort => throw _privateConstructorUsedError;
|
||||
bool get isFilterSystemApp => throw _privateConstructorUsedError;
|
||||
bool get isFilterNonInternetApp => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this AccessControl to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@@ -563,8 +562,7 @@ abstract class $AccessControlCopyWith<$Res> {
|
||||
List<String> acceptList,
|
||||
List<String> rejectList,
|
||||
AccessSortType sort,
|
||||
bool isFilterSystemApp,
|
||||
bool isFilterNonInternetApp});
|
||||
bool isFilterSystemApp});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -588,7 +586,6 @@ class _$AccessControlCopyWithImpl<$Res, $Val extends AccessControl>
|
||||
Object? rejectList = null,
|
||||
Object? sort = null,
|
||||
Object? isFilterSystemApp = null,
|
||||
Object? isFilterNonInternetApp = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
enable: null == enable
|
||||
@@ -615,10 +612,6 @@ class _$AccessControlCopyWithImpl<$Res, $Val extends AccessControl>
|
||||
? _value.isFilterSystemApp
|
||||
: isFilterSystemApp // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
isFilterNonInternetApp: null == isFilterNonInternetApp
|
||||
? _value.isFilterNonInternetApp
|
||||
: isFilterNonInternetApp // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@@ -637,8 +630,7 @@ abstract class _$$AccessControlImplCopyWith<$Res>
|
||||
List<String> acceptList,
|
||||
List<String> rejectList,
|
||||
AccessSortType sort,
|
||||
bool isFilterSystemApp,
|
||||
bool isFilterNonInternetApp});
|
||||
bool isFilterSystemApp});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -660,7 +652,6 @@ class __$$AccessControlImplCopyWithImpl<$Res>
|
||||
Object? rejectList = null,
|
||||
Object? sort = null,
|
||||
Object? isFilterSystemApp = null,
|
||||
Object? isFilterNonInternetApp = null,
|
||||
}) {
|
||||
return _then(_$AccessControlImpl(
|
||||
enable: null == enable
|
||||
@@ -687,10 +678,6 @@ class __$$AccessControlImplCopyWithImpl<$Res>
|
||||
? _value.isFilterSystemApp
|
||||
: isFilterSystemApp // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
isFilterNonInternetApp: null == isFilterNonInternetApp
|
||||
? _value.isFilterNonInternetApp
|
||||
: isFilterNonInternetApp // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -704,8 +691,7 @@ class _$AccessControlImpl implements _AccessControl {
|
||||
final List<String> acceptList = const [],
|
||||
final List<String> rejectList = const [],
|
||||
this.sort = AccessSortType.none,
|
||||
this.isFilterSystemApp = true,
|
||||
this.isFilterNonInternetApp = true})
|
||||
this.isFilterSystemApp = true})
|
||||
: _acceptList = acceptList,
|
||||
_rejectList = rejectList;
|
||||
|
||||
@@ -742,13 +728,10 @@ class _$AccessControlImpl implements _AccessControl {
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool isFilterSystemApp;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool isFilterNonInternetApp;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AccessControl(enable: $enable, mode: $mode, acceptList: $acceptList, rejectList: $rejectList, sort: $sort, isFilterSystemApp: $isFilterSystemApp, isFilterNonInternetApp: $isFilterNonInternetApp)';
|
||||
return 'AccessControl(enable: $enable, mode: $mode, acceptList: $acceptList, rejectList: $rejectList, sort: $sort, isFilterSystemApp: $isFilterSystemApp)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -764,9 +747,7 @@ class _$AccessControlImpl implements _AccessControl {
|
||||
.equals(other._rejectList, _rejectList) &&
|
||||
(identical(other.sort, sort) || other.sort == sort) &&
|
||||
(identical(other.isFilterSystemApp, isFilterSystemApp) ||
|
||||
other.isFilterSystemApp == isFilterSystemApp) &&
|
||||
(identical(other.isFilterNonInternetApp, isFilterNonInternetApp) ||
|
||||
other.isFilterNonInternetApp == isFilterNonInternetApp));
|
||||
other.isFilterSystemApp == isFilterSystemApp));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -778,8 +759,7 @@ class _$AccessControlImpl implements _AccessControl {
|
||||
const DeepCollectionEquality().hash(_acceptList),
|
||||
const DeepCollectionEquality().hash(_rejectList),
|
||||
sort,
|
||||
isFilterSystemApp,
|
||||
isFilterNonInternetApp);
|
||||
isFilterSystemApp);
|
||||
|
||||
/// Create a copy of AccessControl
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -804,8 +784,7 @@ abstract class _AccessControl implements AccessControl {
|
||||
final List<String> acceptList,
|
||||
final List<String> rejectList,
|
||||
final AccessSortType sort,
|
||||
final bool isFilterSystemApp,
|
||||
final bool isFilterNonInternetApp}) = _$AccessControlImpl;
|
||||
final bool isFilterSystemApp}) = _$AccessControlImpl;
|
||||
|
||||
factory _AccessControl.fromJson(Map<String, dynamic> json) =
|
||||
_$AccessControlImpl.fromJson;
|
||||
@@ -822,8 +801,6 @@ abstract class _AccessControl implements AccessControl {
|
||||
AccessSortType get sort;
|
||||
@override
|
||||
bool get isFilterSystemApp;
|
||||
@override
|
||||
bool get isFilterNonInternetApp;
|
||||
|
||||
/// Create a copy of AccessControl
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
|
||||
@@ -59,7 +59,6 @@ const _$DashboardWidgetEnumMap = {
|
||||
DashboardWidget.trafficUsage: 'trafficUsage',
|
||||
DashboardWidget.networkDetection: 'networkDetection',
|
||||
DashboardWidget.tunButton: 'tunButton',
|
||||
DashboardWidget.vpnButton: 'vpnButton',
|
||||
DashboardWidget.systemProxyButton: 'systemProxyButton',
|
||||
DashboardWidget.intranetIp: 'intranetIp',
|
||||
DashboardWidget.memoryInfo: 'memoryInfo',
|
||||
@@ -81,7 +80,6 @@ _$AccessControlImpl _$$AccessControlImplFromJson(Map<String, dynamic> json) =>
|
||||
sort: $enumDecodeNullable(_$AccessSortTypeEnumMap, json['sort']) ??
|
||||
AccessSortType.none,
|
||||
isFilterSystemApp: json['isFilterSystemApp'] as bool? ?? true,
|
||||
isFilterNonInternetApp: json['isFilterNonInternetApp'] as bool? ?? true,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$AccessControlImplToJson(_$AccessControlImpl instance) =>
|
||||
@@ -92,7 +90,6 @@ Map<String, dynamic> _$$AccessControlImplToJson(_$AccessControlImpl instance) =>
|
||||
'rejectList': instance.rejectList,
|
||||
'sort': _$AccessSortTypeEnumMap[instance.sort]!,
|
||||
'isFilterSystemApp': instance.isFilterSystemApp,
|
||||
'isFilterNonInternetApp': instance.isFilterNonInternetApp,
|
||||
};
|
||||
|
||||
const _$AccessControlModeEnumMap = {
|
||||
|
||||
@@ -327,193 +327,6 @@ abstract class _VM3<A, B, C> implements VM3<A, B, C> {
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$VM4<A, B, C, D> {
|
||||
A get a => throw _privateConstructorUsedError;
|
||||
B get b => throw _privateConstructorUsedError;
|
||||
C get c => throw _privateConstructorUsedError;
|
||||
D get d => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$VM4CopyWith<A, B, C, D, VM4<A, B, C, D>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $VM4CopyWith<A, B, C, D, $Res> {
|
||||
factory $VM4CopyWith(
|
||||
VM4<A, B, C, D> value, $Res Function(VM4<A, B, C, D>) then) =
|
||||
_$VM4CopyWithImpl<A, B, C, D, $Res, VM4<A, B, C, D>>;
|
||||
@useResult
|
||||
$Res call({A a, B b, C c, D d});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$VM4CopyWithImpl<A, B, C, D, $Res, $Val extends VM4<A, B, C, D>>
|
||||
implements $VM4CopyWith<A, B, C, D, $Res> {
|
||||
_$VM4CopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? a = freezed,
|
||||
Object? b = freezed,
|
||||
Object? c = freezed,
|
||||
Object? d = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
a: freezed == a
|
||||
? _value.a
|
||||
: a // ignore: cast_nullable_to_non_nullable
|
||||
as A,
|
||||
b: freezed == b
|
||||
? _value.b
|
||||
: b // ignore: cast_nullable_to_non_nullable
|
||||
as B,
|
||||
c: freezed == c
|
||||
? _value.c
|
||||
: c // ignore: cast_nullable_to_non_nullable
|
||||
as C,
|
||||
d: freezed == d
|
||||
? _value.d
|
||||
: d // ignore: cast_nullable_to_non_nullable
|
||||
as D,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$VM4ImplCopyWith<A, B, C, D, $Res>
|
||||
implements $VM4CopyWith<A, B, C, D, $Res> {
|
||||
factory _$$VM4ImplCopyWith(_$VM4Impl<A, B, C, D> value,
|
||||
$Res Function(_$VM4Impl<A, B, C, D>) then) =
|
||||
__$$VM4ImplCopyWithImpl<A, B, C, D, $Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({A a, B b, C c, D d});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$VM4ImplCopyWithImpl<A, B, C, D, $Res>
|
||||
extends _$VM4CopyWithImpl<A, B, C, D, $Res, _$VM4Impl<A, B, C, D>>
|
||||
implements _$$VM4ImplCopyWith<A, B, C, D, $Res> {
|
||||
__$$VM4ImplCopyWithImpl(
|
||||
_$VM4Impl<A, B, C, D> _value, $Res Function(_$VM4Impl<A, B, C, D>) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? a = freezed,
|
||||
Object? b = freezed,
|
||||
Object? c = freezed,
|
||||
Object? d = freezed,
|
||||
}) {
|
||||
return _then(_$VM4Impl<A, B, C, D>(
|
||||
a: freezed == a
|
||||
? _value.a
|
||||
: a // ignore: cast_nullable_to_non_nullable
|
||||
as A,
|
||||
b: freezed == b
|
||||
? _value.b
|
||||
: b // ignore: cast_nullable_to_non_nullable
|
||||
as B,
|
||||
c: freezed == c
|
||||
? _value.c
|
||||
: c // ignore: cast_nullable_to_non_nullable
|
||||
as C,
|
||||
d: freezed == d
|
||||
? _value.d
|
||||
: d // ignore: cast_nullable_to_non_nullable
|
||||
as D,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$VM4Impl<A, B, C, D> implements _VM4<A, B, C, D> {
|
||||
const _$VM4Impl(
|
||||
{required this.a, required this.b, required this.c, required this.d});
|
||||
|
||||
@override
|
||||
final A a;
|
||||
@override
|
||||
final B b;
|
||||
@override
|
||||
final C c;
|
||||
@override
|
||||
final D d;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'VM4<$A, $B, $C, $D>(a: $a, b: $b, c: $c, d: $d)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$VM4Impl<A, B, C, D> &&
|
||||
const DeepCollectionEquality().equals(other.a, a) &&
|
||||
const DeepCollectionEquality().equals(other.b, b) &&
|
||||
const DeepCollectionEquality().equals(other.c, c) &&
|
||||
const DeepCollectionEquality().equals(other.d, d));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(a),
|
||||
const DeepCollectionEquality().hash(b),
|
||||
const DeepCollectionEquality().hash(c),
|
||||
const DeepCollectionEquality().hash(d));
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$VM4ImplCopyWith<A, B, C, D, _$VM4Impl<A, B, C, D>> get copyWith =>
|
||||
__$$VM4ImplCopyWithImpl<A, B, C, D, _$VM4Impl<A, B, C, D>>(
|
||||
this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _VM4<A, B, C, D> implements VM4<A, B, C, D> {
|
||||
const factory _VM4(
|
||||
{required final A a,
|
||||
required final B b,
|
||||
required final C c,
|
||||
required final D d}) = _$VM4Impl<A, B, C, D>;
|
||||
|
||||
@override
|
||||
A get a;
|
||||
@override
|
||||
B get b;
|
||||
@override
|
||||
C get c;
|
||||
@override
|
||||
D get d;
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$VM4ImplCopyWith<A, B, C, D, _$VM4Impl<A, B, C, D>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$StartButtonSelectorState {
|
||||
bool get isInit => throw _privateConstructorUsedError;
|
||||
@@ -3522,7 +3335,6 @@ mixin _$ClashConfigState {
|
||||
bool get overrideDns => throw _privateConstructorUsedError;
|
||||
ClashConfig get clashConfig => throw _privateConstructorUsedError;
|
||||
OverrideData get overrideData => throw _privateConstructorUsedError;
|
||||
RouteMode get routeMode => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ClashConfigState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -3538,10 +3350,7 @@ abstract class $ClashConfigStateCopyWith<$Res> {
|
||||
_$ClashConfigStateCopyWithImpl<$Res, ClashConfigState>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{bool overrideDns,
|
||||
ClashConfig clashConfig,
|
||||
OverrideData overrideData,
|
||||
RouteMode routeMode});
|
||||
{bool overrideDns, ClashConfig clashConfig, OverrideData overrideData});
|
||||
|
||||
$ClashConfigCopyWith<$Res> get clashConfig;
|
||||
$OverrideDataCopyWith<$Res> get overrideData;
|
||||
@@ -3565,7 +3374,6 @@ class _$ClashConfigStateCopyWithImpl<$Res, $Val extends ClashConfigState>
|
||||
Object? overrideDns = null,
|
||||
Object? clashConfig = null,
|
||||
Object? overrideData = null,
|
||||
Object? routeMode = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
overrideDns: null == overrideDns
|
||||
@@ -3580,10 +3388,6 @@ class _$ClashConfigStateCopyWithImpl<$Res, $Val extends ClashConfigState>
|
||||
? _value.overrideData
|
||||
: overrideData // ignore: cast_nullable_to_non_nullable
|
||||
as OverrideData,
|
||||
routeMode: null == routeMode
|
||||
? _value.routeMode
|
||||
: routeMode // ignore: cast_nullable_to_non_nullable
|
||||
as RouteMode,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
@@ -3617,10 +3421,7 @@ abstract class _$$ClashConfigStateImplCopyWith<$Res>
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{bool overrideDns,
|
||||
ClashConfig clashConfig,
|
||||
OverrideData overrideData,
|
||||
RouteMode routeMode});
|
||||
{bool overrideDns, ClashConfig clashConfig, OverrideData overrideData});
|
||||
|
||||
@override
|
||||
$ClashConfigCopyWith<$Res> get clashConfig;
|
||||
@@ -3644,7 +3445,6 @@ class __$$ClashConfigStateImplCopyWithImpl<$Res>
|
||||
Object? overrideDns = null,
|
||||
Object? clashConfig = null,
|
||||
Object? overrideData = null,
|
||||
Object? routeMode = null,
|
||||
}) {
|
||||
return _then(_$ClashConfigStateImpl(
|
||||
overrideDns: null == overrideDns
|
||||
@@ -3659,10 +3459,6 @@ class __$$ClashConfigStateImplCopyWithImpl<$Res>
|
||||
? _value.overrideData
|
||||
: overrideData // ignore: cast_nullable_to_non_nullable
|
||||
as OverrideData,
|
||||
routeMode: null == routeMode
|
||||
? _value.routeMode
|
||||
: routeMode // ignore: cast_nullable_to_non_nullable
|
||||
as RouteMode,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -3673,8 +3469,7 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
const _$ClashConfigStateImpl(
|
||||
{required this.overrideDns,
|
||||
required this.clashConfig,
|
||||
required this.overrideData,
|
||||
required this.routeMode});
|
||||
required this.overrideData});
|
||||
|
||||
@override
|
||||
final bool overrideDns;
|
||||
@@ -3682,12 +3477,10 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
final ClashConfig clashConfig;
|
||||
@override
|
||||
final OverrideData overrideData;
|
||||
@override
|
||||
final RouteMode routeMode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ClashConfigState(overrideDns: $overrideDns, clashConfig: $clashConfig, overrideData: $overrideData, routeMode: $routeMode)';
|
||||
return 'ClashConfigState(overrideDns: $overrideDns, clashConfig: $clashConfig, overrideData: $overrideData)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -3700,14 +3493,12 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
(identical(other.clashConfig, clashConfig) ||
|
||||
other.clashConfig == clashConfig) &&
|
||||
(identical(other.overrideData, overrideData) ||
|
||||
other.overrideData == overrideData) &&
|
||||
(identical(other.routeMode, routeMode) ||
|
||||
other.routeMode == routeMode));
|
||||
other.overrideData == overrideData));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, overrideDns, clashConfig, overrideData, routeMode);
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, overrideDns, clashConfig, overrideData);
|
||||
|
||||
/// Create a copy of ClashConfigState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -3723,8 +3514,7 @@ abstract class _ClashConfigState implements ClashConfigState {
|
||||
const factory _ClashConfigState(
|
||||
{required final bool overrideDns,
|
||||
required final ClashConfig clashConfig,
|
||||
required final OverrideData overrideData,
|
||||
required final RouteMode routeMode}) = _$ClashConfigStateImpl;
|
||||
required final OverrideData overrideData}) = _$ClashConfigStateImpl;
|
||||
|
||||
@override
|
||||
bool get overrideDns;
|
||||
@@ -3732,8 +3522,6 @@ abstract class _ClashConfigState implements ClashConfigState {
|
||||
ClashConfig get clashConfig;
|
||||
@override
|
||||
OverrideData get overrideData;
|
||||
@override
|
||||
RouteMode get routeMode;
|
||||
|
||||
/// Create a copy of ClashConfigState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
|
||||
@@ -24,17 +24,6 @@ class VM3<A, B, C> with _$VM3<A, B, C> {
|
||||
}) = _VM3;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class VM4<A, B, C,D> with _$VM4<A, B, C,D> {
|
||||
const factory VM4({
|
||||
required A a,
|
||||
required B b,
|
||||
required C c,
|
||||
required D d,
|
||||
}) = _VM4;
|
||||
}
|
||||
|
||||
|
||||
@freezed
|
||||
class StartButtonSelectorState with _$StartButtonSelectorState {
|
||||
const factory StartButtonSelectorState({
|
||||
@@ -157,21 +146,12 @@ class PackageListSelectorState with _$PackageListSelectorState {
|
||||
}
|
||||
|
||||
extension PackageListSelectorStateExt on PackageListSelectorState {
|
||||
List<Package> get list {
|
||||
List<Package> getList(List<String> selectedList) {
|
||||
final isFilterSystemApp = accessControl.isFilterSystemApp;
|
||||
final isFilterNonInternetApp = accessControl.isFilterNonInternetApp;
|
||||
return packages
|
||||
.where(
|
||||
(item) =>
|
||||
(isFilterSystemApp ? item.system == false : true) &&
|
||||
(isFilterNonInternetApp ? item.internet == true : true),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<Package> getSortList(List<String> selectedList) {
|
||||
final sort = accessControl.sort;
|
||||
return list.sorted(
|
||||
return packages
|
||||
.where((item) => isFilterSystemApp ? item.isSystem == false : true)
|
||||
.sorted(
|
||||
(a, b) {
|
||||
return switch (sort) {
|
||||
AccessSortType.none => 0,
|
||||
@@ -228,7 +208,6 @@ class ClashConfigState with _$ClashConfigState {
|
||||
required bool overrideDns,
|
||||
required ClashConfig clashConfig,
|
||||
required OverrideData overrideData,
|
||||
required RouteMode routeMode,
|
||||
}) = _ClashConfigState;
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,6 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
||||
);
|
||||
},
|
||||
popup: CommonPopupMenu(
|
||||
minWidth: 180,
|
||||
items: [
|
||||
PopupMenuItemData(
|
||||
icon: Icons.search,
|
||||
@@ -190,7 +189,7 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
||||
shortcutsActivatorsBuilder: DefaultCodeShortcutsActivatorsBuilder(),
|
||||
controller: _controller,
|
||||
style: CodeEditorStyle(
|
||||
fontSize: 14.ap,
|
||||
fontSize: 14,
|
||||
fontFamily: FontFamily.jetBrainsMono.value,
|
||||
codeTheme: CodeHighlightTheme(
|
||||
languages: {
|
||||
|
||||
@@ -190,46 +190,43 @@ class CommonNavigationBar extends ConsumerWidget {
|
||||
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,
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -126,7 +126,7 @@ class Profiles extends _$Profiles with AutoDisposeNotifierMixin {
|
||||
}
|
||||
}
|
||||
|
||||
setProfile(Profile profile, {bool force = true}) {
|
||||
setProfile(Profile profile) {
|
||||
final List<Profile> profilesTemp = List.from(state);
|
||||
final index =
|
||||
profilesTemp.indexWhere((element) => element.id == profile.id);
|
||||
@@ -135,7 +135,7 @@ class Profiles extends _$Profiles with AutoDisposeNotifierMixin {
|
||||
);
|
||||
if (index == -1) {
|
||||
profilesTemp.add(updateProfile);
|
||||
} else if (force == true) {
|
||||
} else {
|
||||
profilesTemp[index] = updateProfile;
|
||||
}
|
||||
state = profilesTemp;
|
||||
|
||||
@@ -83,7 +83,7 @@ final themeSettingProvider =
|
||||
);
|
||||
|
||||
typedef _$ThemeSetting = AutoDisposeNotifier<ThemeProps>;
|
||||
String _$profilesHash() => r'c416fda0f8deded24a715a8234efa0bcd0445449';
|
||||
String _$profilesHash() => r'a6514c89064e4f42fc31fe7d525088fd26c51016';
|
||||
|
||||
/// See also [Profiles].
|
||||
@ProviderFor(Profiles)
|
||||
|
||||
@@ -78,7 +78,7 @@ final coreStateProvider = AutoDisposeProvider<CoreState>.internal(
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
typedef CoreStateRef = AutoDisposeProviderRef<CoreState>;
|
||||
String _$clashConfigStateHash() => r'fbbcd7221b0b9b18db523e59c9021e8e56e119ca';
|
||||
String _$clashConfigStateHash() => r'848f6b2f734d99fb11ec05f73d614be415e9658f';
|
||||
|
||||
/// See also [clashConfigState].
|
||||
@ProviderFor(clashConfigState)
|
||||
|
||||
@@ -75,15 +75,13 @@ CoreState coreState(Ref ref) {
|
||||
ClashConfigState clashConfigState(Ref ref) {
|
||||
final clashConfig = ref.watch(patchClashConfigProvider);
|
||||
final overrideDns = ref.watch(overrideDnsProvider);
|
||||
final overrideData =
|
||||
ref.watch(currentProfileProvider.select((state) => state?.overrideData));
|
||||
final routeMode =
|
||||
ref.watch(networkSettingProvider.select((state) => state.routeMode));
|
||||
final overrideData = ref.watch(currentProfileProvider.select(
|
||||
(state) => state?.overrideData,
|
||||
));
|
||||
return ClashConfigState(
|
||||
overrideDns: overrideDns,
|
||||
clashConfig: clashConfig,
|
||||
overrideData: overrideData ?? OverrideData(),
|
||||
routeMode: routeMode,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ class GlobalState {
|
||||
late Config config;
|
||||
late AppState appState;
|
||||
bool isPre = true;
|
||||
String? helperToken;
|
||||
late PackageInfo packageInfo;
|
||||
Function? updateCurrentDelayDebounce;
|
||||
late Measure measure;
|
||||
@@ -259,17 +258,14 @@ class GlobalState {
|
||||
getUpdateConfigParams([bool? isPatch]) {
|
||||
final currentProfile = config.currentProfile;
|
||||
final clashConfig = config.patchClashConfig;
|
||||
final routeAddress =
|
||||
config.networkProps.routeMode == RouteMode.bypassPrivate
|
||||
? defaultBypassPrivateRouteAddress
|
||||
: clashConfig.tun.routeAddress;
|
||||
return UpdateConfigParams(
|
||||
profileId: config.currentProfileId ?? "",
|
||||
config: clashConfig.copyWith(
|
||||
globalUa: ua,
|
||||
tun: clashConfig.tun.copyWith(
|
||||
autoRoute: routeAddress.isEmpty ? true : false,
|
||||
routeAddress: routeAddress,
|
||||
routeAddress: config.networkProps.routeMode == RouteMode.bypassPrivate
|
||||
? defaultBypassPrivateRouteAddress
|
||||
: clashConfig.tun.routeAddress,
|
||||
),
|
||||
rule: currentProfile?.overrideData.runningRule ?? [],
|
||||
),
|
||||
|
||||
@@ -10,7 +10,7 @@ import 'package:flutter/services.dart';
|
||||
import 'chip.dart';
|
||||
|
||||
class CommonScaffold extends StatefulWidget {
|
||||
final AppBar? appBar;
|
||||
final PreferredSizeWidget? appBar;
|
||||
final Widget body;
|
||||
final Widget? bottomNavigationBar;
|
||||
final Widget? sideNavigationBar;
|
||||
@@ -344,10 +344,10 @@ class CommonScaffoldState extends State<CommonScaffold> {
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
widget.appBar ??
|
||||
child: widget.appBar ??
|
||||
Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
ValueListenableBuilder<AppBarState>(
|
||||
valueListenable: _appBarState,
|
||||
builder: (_, state, __) {
|
||||
@@ -368,16 +368,16 @@ class CommonScaffoldState extends State<CommonScaffold> {
|
||||
);
|
||||
},
|
||||
),
|
||||
ValueListenableBuilder(
|
||||
valueListenable: _loading,
|
||||
builder: (_, value, __) {
|
||||
return value == true
|
||||
? const LinearProgressIndicator()
|
||||
: Container();
|
||||
},
|
||||
ValueListenableBuilder(
|
||||
valueListenable: _loading,
|
||||
builder: (_, value, __) {
|
||||
return value == true
|
||||
? const LinearProgressIndicator()
|
||||
: Container();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ packages:
|
||||
source: hosted
|
||||
version: "0.3.4+2"
|
||||
crypto:
|
||||
dependency: "direct dev"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: fl_clash
|
||||
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
||||
publish_to: 'none'
|
||||
version: 0.8.83+202504254
|
||||
version: 0.8.83+202504231
|
||||
environment:
|
||||
sdk: '>=3.1.0 <4.0.0'
|
||||
|
||||
@@ -66,7 +66,6 @@ dev_dependencies:
|
||||
riverpod_generator: ^2.6.3
|
||||
custom_lint: ^0.7.0
|
||||
riverpod_lint: ^2.6.3
|
||||
crypto: ^3.0.3
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
14
services/helper/Cargo.lock
generated
14
services/helper/Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
@@ -284,7 +284,6 @@ dependencies = [
|
||||
"anyhow",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"sha2",
|
||||
"tokio",
|
||||
"warp",
|
||||
"windows-service",
|
||||
@@ -823,17 +822,6 @@ dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
|
||||
@@ -14,11 +14,10 @@ anyhow = "1.0.93"
|
||||
warp = "0.3.7"
|
||||
serde = { version = "1.0.215", features = ["derive"] }
|
||||
once_cell = "1.20.2"
|
||||
sha2 = "0.10.8"
|
||||
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = "s"
|
||||
opt-level = "s"
|
||||
@@ -1,4 +0,0 @@
|
||||
fn main() {
|
||||
let version = std::env::var("TOKEN").unwrap_or_default();
|
||||
println!("cargo:rustc-env=TOKEN={}", version);
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, Error, Read};
|
||||
use std::{io, thread};
|
||||
use std::io::BufRead;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{io, thread};
|
||||
use warp::{Filter, Reply};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
const LISTEN_PORT: u16 = 47890;
|
||||
|
||||
@@ -17,31 +15,10 @@ pub struct StartParams {
|
||||
pub arg: String,
|
||||
}
|
||||
|
||||
fn sha256_file(path: &str) -> Result<String, Error> {
|
||||
let mut file = File::open(path)?;
|
||||
let mut hasher = Sha256::new();
|
||||
let mut buffer = [0; 4096];
|
||||
|
||||
loop {
|
||||
let bytes_read = file.read(&mut buffer)?;
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
hasher.update(&buffer[..bytes_read]);
|
||||
}
|
||||
|
||||
Ok(format!("{:x}", hasher.finalize()))
|
||||
}
|
||||
|
||||
static LOGS: Lazy<Arc<Mutex<VecDeque<String>>>> =
|
||||
Lazy::new(|| Arc::new(Mutex::new(VecDeque::with_capacity(100))));
|
||||
static PROCESS: Lazy<Arc<Mutex<Option<std::process::Child>>>> =
|
||||
Lazy::new(|| Arc::new(Mutex::new(None)));
|
||||
static LOGS: Lazy<Arc<Mutex<VecDeque<String>>>> = Lazy::new(|| Arc::new(Mutex::new(VecDeque::with_capacity(100))));
|
||||
static PROCESS: Lazy<Arc<Mutex<Option<std::process::Child>>>> = Lazy::new(|| Arc::new(Mutex::new(None)));
|
||||
|
||||
fn start(start_params: StartParams) -> impl Reply {
|
||||
if sha256_file(start_params.path.as_str()).unwrap_or("".to_string()) != env!("TOKEN") {
|
||||
return "Only FlClashCore is allowed to run.".to_string();
|
||||
}
|
||||
stop();
|
||||
let mut process = PROCESS.lock().unwrap();
|
||||
match Command::new(&start_params.path)
|
||||
@@ -96,29 +73,38 @@ fn log_message(message: String) {
|
||||
|
||||
fn get_logs() -> impl Reply {
|
||||
let log_buffer = LOGS.lock().unwrap();
|
||||
let value = log_buffer
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
let value = log_buffer.iter().cloned().collect::<Vec<String>>().join("\n");
|
||||
warp::reply::with_header(value, "Content-Type", "text/plain")
|
||||
}
|
||||
|
||||
pub async fn run_service() -> anyhow::Result<()> {
|
||||
let api_ping = warp::get().and(warp::path("ping")).map(|| env!("TOKEN"));
|
||||
let api_ping = warp::get()
|
||||
.and(warp::path("ping"))
|
||||
.map(|| "2024125");
|
||||
|
||||
let api_start = warp::post()
|
||||
.and(warp::path("start"))
|
||||
.and(warp::body::json())
|
||||
.map(|start_params: StartParams| start(start_params));
|
||||
.map(|start_params: StartParams| {
|
||||
start(start_params)
|
||||
});
|
||||
|
||||
let api_stop = warp::post().and(warp::path("stop")).map(|| stop());
|
||||
let api_stop = warp::post()
|
||||
.and(warp::path("stop"))
|
||||
.map(|| stop());
|
||||
|
||||
let api_logs = warp::get().and(warp::path("logs")).map(|| get_logs());
|
||||
let api_logs = warp::get()
|
||||
.and(warp::path("logs"))
|
||||
.map(|| get_logs());
|
||||
|
||||
warp::serve(api_ping.or(api_start).or(api_stop).or(api_logs))
|
||||
warp::serve(
|
||||
api_ping
|
||||
.or(api_start)
|
||||
.or(api_stop)
|
||||
.or(api_logs)
|
||||
)
|
||||
.run(([127, 0, 0, 1], LISTEN_PORT))
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
44
setup.dart
44
setup.dart
@@ -5,7 +5,6 @@ import 'dart:io';
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
|
||||
enum Target {
|
||||
windows,
|
||||
@@ -196,16 +195,7 @@ class Build {
|
||||
if (exitCode != 0 && name != null) throw "$name error";
|
||||
}
|
||||
|
||||
static Future<String?> calcSha256(String filePath) async {
|
||||
final file = File(filePath);
|
||||
if (!await file.exists()) {
|
||||
return null;
|
||||
}
|
||||
final stream = file.openRead();
|
||||
return sha256.convert(await stream.reduce((a, b) => a + b)).toString();
|
||||
}
|
||||
|
||||
static Future<List<String>> buildCore({
|
||||
static buildCore({
|
||||
required Mode mode,
|
||||
required Target target,
|
||||
Arch? arch,
|
||||
@@ -219,8 +209,6 @@ class Build {
|
||||
},
|
||||
).toList();
|
||||
|
||||
final List<String> corePaths = [];
|
||||
|
||||
for (final item in items) {
|
||||
final outFileDir = join(
|
||||
outDir,
|
||||
@@ -240,7 +228,6 @@ class Build {
|
||||
outFileDir,
|
||||
fileName,
|
||||
);
|
||||
corePaths.add(outPath);
|
||||
|
||||
final Map<String, String> env = {};
|
||||
env["GOOS"] = item.target.os;
|
||||
@@ -271,11 +258,9 @@ class Build {
|
||||
workingDirectory: _coreDir,
|
||||
);
|
||||
}
|
||||
|
||||
return corePaths;
|
||||
}
|
||||
|
||||
static buildHelper(Target target, String token) async {
|
||||
static buildHelper(Target target) async {
|
||||
await exec(
|
||||
[
|
||||
"cargo",
|
||||
@@ -284,9 +269,6 @@ class Build {
|
||||
"--features",
|
||||
"windows-service",
|
||||
],
|
||||
environment: {
|
||||
"TOKEN": token,
|
||||
},
|
||||
name: "build helper",
|
||||
workingDirectory: _servicesDir,
|
||||
);
|
||||
@@ -296,15 +278,13 @@ class Build {
|
||||
"release",
|
||||
"helper${target.executableExtensionName}",
|
||||
);
|
||||
final targetPath = join(
|
||||
outDir,
|
||||
target.name,
|
||||
"FlClashHelperService${target.executableExtensionName}",
|
||||
);
|
||||
final targetPath = join(outDir, target.name,
|
||||
"FlClashHelperService${target.executableExtensionName}");
|
||||
await File(outPath).copy(targetPath);
|
||||
}
|
||||
|
||||
static List<String> getExecutable(String command) {
|
||||
print(command);
|
||||
return command.split(" ");
|
||||
}
|
||||
|
||||
@@ -486,28 +466,26 @@ class BuildCommand extends Command {
|
||||
throw "Invalid arch parameter";
|
||||
}
|
||||
|
||||
final corePaths = await Build.buildCore(
|
||||
await Build.buildCore(
|
||||
target: target,
|
||||
arch: arch,
|
||||
mode: mode,
|
||||
);
|
||||
|
||||
if (target == Target.windows) {
|
||||
await Build.buildHelper(target);
|
||||
}
|
||||
|
||||
if (out != "app") {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (target) {
|
||||
case Target.windows:
|
||||
final token = await Build.calcSha256(corePaths.first);
|
||||
if (token == null) {
|
||||
throw "Core not exists";
|
||||
}
|
||||
Build.buildHelper(target, token);
|
||||
_buildDistributor(
|
||||
target: target,
|
||||
targets: "exe,zip",
|
||||
args:
|
||||
" --description $archName --build-dart-define=HELPER_TOKEN=$token",
|
||||
args: " --description $archName",
|
||||
env: env,
|
||||
);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user