Compare commits

..

45 Commits

Author SHA1 Message Date
chen08209
bd5470b863 Fix Workflow 2024-05-31 22:34:46 +08:00
chen08209
83fafa4b68 Fix Linux unable to open 2024-05-31 22:12:41 +08:00
chen08209
b7fb969301 Update README.md 3 2024-05-31 15:41:08 +08:00
chen08209
3ef3190785 Create LICENSE 2024-05-31 15:11:15 +08:00
chen08209
b1c763fcfa Update README.md 2 2024-05-31 15:08:51 +08:00
chen08209
9452ffa514 Update README.md 2024-05-31 15:02:18 +08:00
chen08209
c9291e5027 Optimize workFlow 2024-05-31 14:25:15 +08:00
chen08209
3ba86dc9c2 optimize checkUpdate 2024-05-31 10:07:51 +08:00
chen08209
fd3040283c Fix submit error 2024-05-30 17:22:23 +08:00
chen08209
91d30c0f0e add WebDAV
add Auto check updates

Optimize more details
2024-05-30 17:11:15 +08:00
chen08209
c4b470ffaf optimize delayTest 2024-05-17 19:54:57 +08:00
chen08209
9a07c785f2 upgrade flutter version 2024-05-15 20:34:59 +08:00
chen08209
a134c32493 Update kernel
Add import profile via QR code image
2024-05-15 20:21:02 +08:00
chen08209
472cea9037 Add compatibility mode and adapt clash scheme. 2024-05-11 14:10:06 +08:00
chen08209
08d07498b9 update Version 2024-05-07 18:32:21 +08:00
chen08209
d5aa09949a Reconstruction application proxy logic 2024-05-07 18:31:14 +08:00
chen08209
fd1dfe5c60 Fix Tab destroy error 2024-05-06 19:05:27 +08:00
chen08209
9f89fe8b29 Optimize repeat healthcheck 2024-05-06 17:17:26 +08:00
chen08209
78081a12e8 Optimize Direct mode ui 2024-05-06 15:27:37 +08:00
chen08209
6896837f28 Optimize Healthcheck 2024-05-06 14:32:23 +08:00
chen08209
85eb903402 Remove proxies position animation, improve performance
Add Telegram Link
2024-05-06 14:32:22 +08:00
chen08209
9aa9180f1f Update healthcheck policy 2024-05-06 14:32:21 +08:00
chen08209
feb9688a29 New Check URLTest 2024-05-06 14:32:21 +08:00
chen08209
5c71992174 Fix the problem of invalid auto-selection 2024-05-05 16:14:34 +08:00
chen08209
74c3d0ae25 New Async UpdateConfig 2024-05-05 03:13:52 +08:00
chen08209
ecd1bcafd5 add changeProfileDebounce 2024-05-05 03:13:51 +08:00
chen08209
184d2d117a Update Workflow 2024-05-05 03:13:50 +08:00
chen08209
89e6f17794 Fix ChangeProfile block 2024-05-05 03:13:49 +08:00
chen08209
aef50fe0e3 Fix Release Message Error 2024-05-04 16:14:03 +08:00
chen08209
fc0767ed25 Update Selector 2 2024-05-04 01:14:56 +08:00
chen08209
dbf1724cca Update Version 2024-05-04 00:14:34 +08:00
chen08209
909aa4038e Fix Proxies Select Error 2024-05-04 00:14:07 +08:00
chen08209
2d0a7d8d46 Fix the problem that the proxy group is empty in global mode. 2024-05-03 23:08:06 +08:00
chen08209
ca96cd1d82 Fix the problem that the proxy group is empty in global mode. 2024-05-03 23:07:38 +08:00
chen08209
91ab1e5dac Add ProxyProvider2 2024-05-03 21:48:22 +08:00
chen08209
b3a5f74df8 Add ProxyProvider 2024-05-03 21:28:22 +08:00
chen08209
1f98be8ad8 Update Version 2024-05-03 15:33:46 +08:00
chen08209
453c7c98d0 Update ProxyGroup Sort 2024-05-03 15:33:45 +08:00
chen08209
91faed35c0 Fix Android quickStart VpnService some problems 2024-05-02 00:32:11 +08:00
chen08209
07bbaf6b6f Update version 2024-05-01 23:40:04 +08:00
chen08209
e8feb7c431 Set Android notification low importance 2024-05-01 23:40:03 +08:00
chen08209
4d16820526 Fix the issue that VpnService can't be closed correctly in special cases 2024-05-01 23:40:00 +08:00
chen08209
92294b49c6 Fix the problem that TileService is not destroyed correctly in some cases
Adjust tab animation defaults
2024-05-01 23:39:59 +08:00
chen08209
8a188a37c9 Add Telegram in README_zh_CN.md 2024-05-01 21:52:07 +08:00
chen08209
48af16c265 Add Telegram 2024-05-01 21:50:26 +08:00
11 changed files with 319 additions and 559 deletions

View File

@@ -34,6 +34,8 @@ on Mobile:
💡 Based on Material You Design, [Surfboard](https://github.com/getsurfboard/surfboard)-like UI 💡 Based on Material You Design, [Surfboard](https://github.com/getsurfboard/surfboard)-like UI
☁️ Supports data sync via WebDAV
✨ Support subscription link, Dark mode ✨ Support subscription link, Dark mode
## Contact ## Contact

View File

@@ -34,6 +34,8 @@ on Mobile:
💡 基本 Material You 设计, 类[Surfboard](https://github.com/getsurfboard/surfboard)用户界面 💡 基本 Material You 设计, 类[Surfboard](https://github.com/getsurfboard/surfboard)用户界面
☁️ 支持通过WebDAV同步数据
✨ 支持一键导入订阅, 深色模式 ✨ 支持一键导入订阅, 深色模式
## Contact ## Contact

View File

@@ -13,7 +13,6 @@ import android.os.Binder
import android.os.Build import android.os.Build
import android.os.IBinder import android.os.IBinder
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE
import androidx.core.graphics.drawable.IconCompat import androidx.core.graphics.drawable.IconCompat
import com.follow.clash.GlobalState import com.follow.clash.GlobalState
import com.follow.clash.MainActivity import com.follow.clash.MainActivity
@@ -21,7 +20,6 @@ import com.follow.clash.models.AccessControl
import com.follow.clash.models.AccessControlMode import com.follow.clash.models.AccessControlMode
@SuppressLint("WrongConstant")
class FlClashVpnService : VpnService() { class FlClashVpnService : VpnService() {
@@ -99,43 +97,6 @@ class FlClashVpnService : VpnService() {
stopForeground() stopForeground()
} }
private val notificationBuilder by lazy {
val intent = Intent(this, MainActivity::class.java)
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
} else {
PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
val icon = IconCompat.createWithResource(this, this.applicationInfo.icon)
with(NotificationCompat.Builder(this, CHANNEL)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setSmallIcon(icon)
}
setContentTitle("FlClash")
foregroundServiceBehavior = FOREGROUND_SERVICE_IMMEDIATE
setContentIntent(pendingIntent)
setCategory(NotificationCompat.CATEGORY_SERVICE)
priority = NotificationCompat.PRIORITY_LOW
setOngoing(true)
setShowWhen(false)
setOnlyAlertOnce(true)
}
}
@SuppressLint("ForegroundServiceType", "WrongConstant") @SuppressLint("ForegroundServiceType", "WrongConstant")
fun startForeground(title: String, content: String) { fun startForeground(title: String, content: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -143,13 +104,42 @@ class FlClashVpnService : VpnService() {
NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW) NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW)
val manager = getSystemService(NotificationManager::class.java) val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel) manager.createNotificationChannel(channel)
}
val notification = val intent = Intent(this, MainActivity::class.java)
notificationBuilder.setContentTitle(title).setContentText(content).build()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_SPECIAL_USE) PendingIntent.getActivity(
} else { this,
startForeground(notificationId, notification) 0,
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
} else {
PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
val icon = IconCompat.createWithResource(this, this.applicationInfo.icon)
val notification = with(NotificationCompat.Builder(this, CHANNEL)) {
setSmallIcon(icon)
setContentTitle(title)
setContentText(content)
foregroundServiceBehavior = NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE
setContentIntent(pendingIntent)
setOngoing(true)
setShowWhen(false)
build()
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_SPECIAL_USE)
} else {
startForeground(notificationId, notification)
}
} }
} }

View File

@@ -1,9 +1,7 @@
import 'package:collection/collection.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/plugins/app.dart'; import 'package:fl_clash/plugins/app.dart';
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/state.dart';
import 'package:fl_clash/widgets/widgets.dart'; import 'package:fl_clash/widgets/widgets.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -21,10 +19,8 @@ class _AccessFragmentState extends State<AccessFragment> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) async {
Future.delayed(const Duration(milliseconds: 300), () async { packagesListenable.value = await app?.getPackages() ?? [];
packagesListenable.value = await app?.getPackages() ?? [];
});
}); });
} }
@@ -95,28 +91,13 @@ class _AccessFragmentState extends State<AccessFragment> {
return IconButton( return IconButton(
tooltip: tooltip, tooltip: tooltip,
onPressed: () { onPressed: () {
final config = globalState.appController.config; final config = context.read<Config>();
final isAccept =
config.accessControl.mode == AccessControlMode.acceptSelected;
if (isSelectedAll) { if (isSelectedAll) {
config.accessControl = switch (isAccept) { config.accessControl.currentList = [];
true => config.accessControl.copyWith( config.accessControl = config.accessControl.copyWith();
acceptList: [],
),
false => config.accessControl.copyWith(
rejectList: [],
),
};
} else { } else {
config.accessControl = switch (isAccept) { config.accessControl.currentList = allValueList;
true => config.accessControl.copyWith( config.accessControl = config.accessControl.copyWith();
acceptList: allValueList,
),
false => config.accessControl.copyWith(
rejectList: allValueList,
),
};
} }
}, },
icon: isSelectedAll icon: isSelectedAll
@@ -200,8 +181,7 @@ class _AccessFragmentState extends State<AccessFragment> {
children: [ children: [
Flexible( Flexible(
child: _buildSelectedAllButton( child: _buildSelectedAllButton(
isSelectedAll: const ListEquality<String>() isSelectedAll: valueList.length == packageNameList.length,
.equals(valueList, packageNameList),
allValueList: packageNameList, allValueList: packageNameList,
), ),
), ),
@@ -215,18 +195,13 @@ class _AccessFragmentState extends State<AccessFragment> {
); );
} }
Widget _buildPackageList() { Widget _buildPackageList(bool isAccessControl) {
return ValueListenableBuilder( return ValueListenableBuilder(
valueListenable: packagesListenable, valueListenable: packagesListenable,
builder: (_, packages, ___) { builder: (_, packages, ___) {
return Selector<Config, PackageListSelectorState>( return Selector<Config, AccessControl>(
selector: (_, config) => PackageListSelectorState( selector: (_, config) => config.accessControl,
accessControl: config.accessControl, builder: (context, accessControl, __) {
isAccessControl: config.isAccessControl,
),
builder: (context, state, __) {
final accessControl = state.accessControl;
final isAccessControl = state.isAccessControl;
final isFilterSystemApp = accessControl.isFilterSystemApp; final isFilterSystemApp = accessControl.isFilterSystemApp;
final currentPackages = isFilterSystemApp final currentPackages = isFilterSystemApp
? packages ? packages
@@ -236,15 +211,13 @@ class _AccessFragmentState extends State<AccessFragment> {
final packageNameList = final packageNameList =
currentPackages.map((e) => e.packageName).toList(); currentPackages.map((e) => e.packageName).toList();
final accessControlMode = accessControl.mode; final accessControlMode = accessControl.mode;
final currentList = final valueList =
accessControlMode == AccessControlMode.acceptSelected accessControl.currentList.intersection(packageNameList);
? accessControl.acceptList
: accessControl.rejectList;
final valueList = currentList.intersection(packageNameList);
final describe = final describe =
accessControlMode == AccessControlMode.acceptSelected accessControlMode == AccessControlMode.acceptSelected
? appLocalizations.accessControlAllowDesc ? appLocalizations.accessControlAllowDesc
: appLocalizations.accessControlNotAllowDesc; : appLocalizations.accessControlNotAllowDesc;
return DisabledMask( return DisabledMask(
status: !isAccessControl, status: !isAccessControl,
child: Column( child: Column(
@@ -268,7 +241,7 @@ class _AccessFragmentState extends State<AccessFragment> {
itemBuilder: (_, index) { itemBuilder: (_, index) {
final package = currentPackages[index]; final package = currentPackages[index];
return PackageListItem( return PackageListItem(
key: Key(package.packageName), key: Key(package.label),
package: package, package: package,
value: value:
valueList.contains(package.packageName), valueList.contains(package.packageName),
@@ -279,20 +252,11 @@ class _AccessFragmentState extends State<AccessFragment> {
} else { } else {
valueList.remove(package.packageName); valueList.remove(package.packageName);
} }
final config = final config = context.read<Config>();
globalState.appController.config; config.accessControl.currentList =
if (accessControlMode == valueList;
AccessControlMode.acceptSelected) { config.accessControl =
config.accessControl = config.accessControl.copyWith();
config.accessControl.copyWith(
acceptList: valueList,
);
} else {
config.accessControl =
config.accessControl.copyWith(
rejectList: valueList,
);
}
}, },
); );
}, },
@@ -312,7 +276,7 @@ class _AccessFragmentState extends State<AccessFragment> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Selector<Config, bool>( return Selector<Config, bool>(
selector: (_, config) => config.isAccessControl, selector: (_, config) => config.isAccessControl,
builder: (_, isAccessControl, child) { builder: (_, isAccessControl, __) {
return Column( return Column(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: [ children: [
@@ -336,12 +300,11 @@ class _AccessFragmentState extends State<AccessFragment> {
), ),
), ),
Flexible( Flexible(
child: child!, child: _buildPackageList(isAccessControl),
), ),
], ],
); );
}, },
child: _buildPackageList(),
); );
} }
} }

View File

@@ -1,26 +1,78 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import '../enum/enum.dart'; import '../enum/enum.dart';
import '../common/common.dart'; import '../common/common.dart';
import 'models.dart'; import 'models.dart';
part 'generated/config.g.dart'; part 'generated/config.g.dart';
part 'generated/config.freezed.dart';
@freezed @JsonSerializable()
class AccessControl with _$AccessControl { class AccessControl {
const factory AccessControl({ AccessControlMode mode;
@Default(AccessControlMode.rejectSelected) AccessControlMode mode, List<String> acceptList;
@Default([]) List<String> acceptList, List<String> rejectList;
@Default([]) List<String> rejectList, bool isFilterSystemApp;
@Default(true) bool isFilterSystemApp,
}) = _AccessControl;
factory AccessControl.fromJson(Map<String, Object?> json) => AccessControl({
_$AccessControlFromJson(json); this.isFilterSystemApp = true,
this.mode = AccessControlMode.rejectSelected,
this.acceptList = const [],
this.rejectList = const [],
});
@JsonKey(includeFromJson: false, includeToJson: false)
List<String> get currentList =>
mode == AccessControlMode.acceptSelected ? acceptList : rejectList;
set currentList(List<String> currentList) {
if (mode == AccessControlMode.acceptSelected) {
acceptList = currentList;
} else {
rejectList = currentList;
}
}
AccessControl copyWith({
AccessControlMode? mode,
List<String>? acceptList,
List<String>? rejectList,
bool? isFilterSystemApp,
}) {
return AccessControl(
mode: mode ?? this.mode,
acceptList: acceptList ?? this.acceptList,
rejectList: rejectList ?? this.rejectList,
isFilterSystemApp: isFilterSystemApp ?? this.isFilterSystemApp,
);
}
Map<String, dynamic> toJson() {
return _$AccessControlToJson(this);
}
factory AccessControl.fromJson(Map<String, dynamic> json) {
return _$AccessControlFromJson(json);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AccessControl &&
runtimeType == other.runtimeType &&
mode == other.mode &&
acceptList == other.acceptList &&
rejectList == other.rejectList &&
isFilterSystemApp == other.isFilterSystemApp;
@override
int get hashCode =>
mode.hashCode ^
acceptList.hashCode ^
rejectList.hashCode ^
isFilterSystemApp.hashCode;
} }
@JsonSerializable() @JsonSerializable()
@@ -56,7 +108,7 @@ class Config extends ChangeNotifier {
_isMinimizeOnExit = true, _isMinimizeOnExit = true,
_isAccessControl = false, _isAccessControl = false,
_autoCheckUpdate = true, _autoCheckUpdate = true,
_accessControl = const AccessControl(), _accessControl = AccessControl(),
_isAnimateToPage = true; _isAnimateToPage = true;
deleteProfileById(String id) { deleteProfileById(String id) {
@@ -90,7 +142,7 @@ class Config extends ChangeNotifier {
_setProfile(Profile profile) { _setProfile(Profile profile) {
final List<Profile> profilesTemp = List.from(_profiles); final List<Profile> profilesTemp = List.from(_profiles);
final index = final index =
profilesTemp.indexWhere((element) => element.id == profile.id); profilesTemp.indexWhere((element) => element.id == profile.id);
final updateProfile = profile.copyWith( final updateProfile = profile.copyWith(
label: _getLabel(profile.label, profile.id), label: _getLabel(profile.label, profile.id),
); );
@@ -305,18 +357,17 @@ class Config extends ChangeNotifier {
} }
} }
update( update([Config? config, RecoveryOption recoveryOptions = RecoveryOption.all]) {
[Config? config, RecoveryOption recoveryOptions = RecoveryOption.all]) {
if (config != null) { if (config != null) {
_profiles = config._profiles; _profiles = config._profiles;
for (final profile in config._profiles) { for (final profile in config._profiles) {
_setProfile(profile); _setProfile(profile);
} }
final onlyProfiles = recoveryOptions == RecoveryOption.onlyProfiles; final onlyProfiles = recoveryOptions == RecoveryOption.onlyProfiles;
if (_currentProfileId == null && onlyProfiles && profiles.isNotEmpty) { if(_currentProfileId == null && onlyProfiles && profiles.isNotEmpty){
_currentProfileId = _profiles.first.id; _currentProfileId = _profiles.first.id;
} }
if (onlyProfiles) return; if(onlyProfiles) return;
_currentProfileId = config._currentProfileId; _currentProfileId = config._currentProfileId;
_isCompatible = config._isCompatible; _isCompatible = config._isCompatible;
_autoLaunch = config._autoLaunch; _autoLaunch = config._autoLaunch;

View File

@@ -1,241 +0,0 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of '../config.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
AccessControl _$AccessControlFromJson(Map<String, dynamic> json) {
return _AccessControl.fromJson(json);
}
/// @nodoc
mixin _$AccessControl {
AccessControlMode get mode => throw _privateConstructorUsedError;
List<String> get acceptList => throw _privateConstructorUsedError;
List<String> get rejectList => throw _privateConstructorUsedError;
bool get isFilterSystemApp => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$AccessControlCopyWith<AccessControl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $AccessControlCopyWith<$Res> {
factory $AccessControlCopyWith(
AccessControl value, $Res Function(AccessControl) then) =
_$AccessControlCopyWithImpl<$Res, AccessControl>;
@useResult
$Res call(
{AccessControlMode mode,
List<String> acceptList,
List<String> rejectList,
bool isFilterSystemApp});
}
/// @nodoc
class _$AccessControlCopyWithImpl<$Res, $Val extends AccessControl>
implements $AccessControlCopyWith<$Res> {
_$AccessControlCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? mode = null,
Object? acceptList = null,
Object? rejectList = null,
Object? isFilterSystemApp = null,
}) {
return _then(_value.copyWith(
mode: null == mode
? _value.mode
: mode // ignore: cast_nullable_to_non_nullable
as AccessControlMode,
acceptList: null == acceptList
? _value.acceptList
: acceptList // ignore: cast_nullable_to_non_nullable
as List<String>,
rejectList: null == rejectList
? _value.rejectList
: rejectList // ignore: cast_nullable_to_non_nullable
as List<String>,
isFilterSystemApp: null == isFilterSystemApp
? _value.isFilterSystemApp
: isFilterSystemApp // ignore: cast_nullable_to_non_nullable
as bool,
) as $Val);
}
}
/// @nodoc
abstract class _$$AccessControlImplCopyWith<$Res>
implements $AccessControlCopyWith<$Res> {
factory _$$AccessControlImplCopyWith(
_$AccessControlImpl value, $Res Function(_$AccessControlImpl) then) =
__$$AccessControlImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{AccessControlMode mode,
List<String> acceptList,
List<String> rejectList,
bool isFilterSystemApp});
}
/// @nodoc
class __$$AccessControlImplCopyWithImpl<$Res>
extends _$AccessControlCopyWithImpl<$Res, _$AccessControlImpl>
implements _$$AccessControlImplCopyWith<$Res> {
__$$AccessControlImplCopyWithImpl(
_$AccessControlImpl _value, $Res Function(_$AccessControlImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? mode = null,
Object? acceptList = null,
Object? rejectList = null,
Object? isFilterSystemApp = null,
}) {
return _then(_$AccessControlImpl(
mode: null == mode
? _value.mode
: mode // ignore: cast_nullable_to_non_nullable
as AccessControlMode,
acceptList: null == acceptList
? _value._acceptList
: acceptList // ignore: cast_nullable_to_non_nullable
as List<String>,
rejectList: null == rejectList
? _value._rejectList
: rejectList // ignore: cast_nullable_to_non_nullable
as List<String>,
isFilterSystemApp: null == isFilterSystemApp
? _value.isFilterSystemApp
: isFilterSystemApp // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
/// @nodoc
@JsonSerializable()
class _$AccessControlImpl implements _AccessControl {
const _$AccessControlImpl(
{this.mode = AccessControlMode.rejectSelected,
final List<String> acceptList = const [],
final List<String> rejectList = const [],
this.isFilterSystemApp = true})
: _acceptList = acceptList,
_rejectList = rejectList;
factory _$AccessControlImpl.fromJson(Map<String, dynamic> json) =>
_$$AccessControlImplFromJson(json);
@override
@JsonKey()
final AccessControlMode mode;
final List<String> _acceptList;
@override
@JsonKey()
List<String> get acceptList {
if (_acceptList is EqualUnmodifiableListView) return _acceptList;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_acceptList);
}
final List<String> _rejectList;
@override
@JsonKey()
List<String> get rejectList {
if (_rejectList is EqualUnmodifiableListView) return _rejectList;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_rejectList);
}
@override
@JsonKey()
final bool isFilterSystemApp;
@override
String toString() {
return 'AccessControl(mode: $mode, acceptList: $acceptList, rejectList: $rejectList, isFilterSystemApp: $isFilterSystemApp)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$AccessControlImpl &&
(identical(other.mode, mode) || other.mode == mode) &&
const DeepCollectionEquality()
.equals(other._acceptList, _acceptList) &&
const DeepCollectionEquality()
.equals(other._rejectList, _rejectList) &&
(identical(other.isFilterSystemApp, isFilterSystemApp) ||
other.isFilterSystemApp == isFilterSystemApp));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType,
mode,
const DeepCollectionEquality().hash(_acceptList),
const DeepCollectionEquality().hash(_rejectList),
isFilterSystemApp);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$AccessControlImplCopyWith<_$AccessControlImpl> get copyWith =>
__$$AccessControlImplCopyWithImpl<_$AccessControlImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$AccessControlImplToJson(
this,
);
}
}
abstract class _AccessControl implements AccessControl {
const factory _AccessControl(
{final AccessControlMode mode,
final List<String> acceptList,
final List<String> rejectList,
final bool isFilterSystemApp}) = _$AccessControlImpl;
factory _AccessControl.fromJson(Map<String, dynamic> json) =
_$AccessControlImpl.fromJson;
@override
AccessControlMode get mode;
@override
List<String> get acceptList;
@override
List<String> get rejectList;
@override
bool get isFilterSystemApp;
@override
@JsonKey(ignore: true)
_$$AccessControlImplCopyWith<_$AccessControlImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -6,6 +6,34 @@ part of '../config.dart';
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
AccessControl _$AccessControlFromJson(Map<String, dynamic> json) =>
AccessControl(
isFilterSystemApp: json['isFilterSystemApp'] as bool? ?? true,
mode: $enumDecodeNullable(_$AccessControlModeEnumMap, json['mode']) ??
AccessControlMode.rejectSelected,
acceptList: (json['acceptList'] as List<dynamic>?)
?.map((e) => e as String)
.toList() ??
const [],
rejectList: (json['rejectList'] as List<dynamic>?)
?.map((e) => e as String)
.toList() ??
const [],
);
Map<String, dynamic> _$AccessControlToJson(AccessControl instance) =>
<String, dynamic>{
'mode': _$AccessControlModeEnumMap[instance.mode]!,
'acceptList': instance.acceptList,
'rejectList': instance.rejectList,
'isFilterSystemApp': instance.isFilterSystemApp,
};
const _$AccessControlModeEnumMap = {
AccessControlMode.acceptSelected: 'acceptSelected',
AccessControlMode.rejectSelected: 'rejectSelected',
};
Config _$ConfigFromJson(Map<String, dynamic> json) => Config() Config _$ConfigFromJson(Map<String, dynamic> json) => Config()
..profiles = (json['profiles'] as List<dynamic>?) ..profiles = (json['profiles'] as List<dynamic>?)
?.map((e) => Profile.fromJson(e as Map<String, dynamic>)) ?.map((e) => Profile.fromJson(e as Map<String, dynamic>))
@@ -65,31 +93,3 @@ const _$ProxiesSortTypeEnumMap = {
ProxiesSortType.delay: 'delay', ProxiesSortType.delay: 'delay',
ProxiesSortType.name: 'name', ProxiesSortType.name: 'name',
}; };
_$AccessControlImpl _$$AccessControlImplFromJson(Map<String, dynamic> json) =>
_$AccessControlImpl(
mode: $enumDecodeNullable(_$AccessControlModeEnumMap, json['mode']) ??
AccessControlMode.rejectSelected,
acceptList: (json['acceptList'] as List<dynamic>?)
?.map((e) => e as String)
.toList() ??
const [],
rejectList: (json['rejectList'] as List<dynamic>?)
?.map((e) => e as String)
.toList() ??
const [],
isFilterSystemApp: json['isFilterSystemApp'] as bool? ?? true,
);
Map<String, dynamic> _$$AccessControlImplToJson(_$AccessControlImpl instance) =>
<String, dynamic>{
'mode': _$AccessControlModeEnumMap[instance.mode]!,
'acceptList': instance.acceptList,
'rejectList': instance.rejectList,
'isFilterSystemApp': instance.isFilterSystemApp,
};
const _$AccessControlModeEnumMap = {
AccessControlMode.acceptSelected: 'acceptSelected',
AccessControlMode.rejectSelected: 'rejectSelected',
};

View File

@@ -667,6 +667,155 @@ abstract class _ProfilesSelectorState implements ProfilesSelectorState {
get copyWith => throw _privateConstructorUsedError; get copyWith => throw _privateConstructorUsedError;
} }
/// @nodoc
mixin _$PackageListSelectorState {
AccessControl get accessControl => throw _privateConstructorUsedError;
List<Package> get packages => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$PackageListSelectorStateCopyWith<PackageListSelectorState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $PackageListSelectorStateCopyWith<$Res> {
factory $PackageListSelectorStateCopyWith(PackageListSelectorState value,
$Res Function(PackageListSelectorState) then) =
_$PackageListSelectorStateCopyWithImpl<$Res, PackageListSelectorState>;
@useResult
$Res call({AccessControl accessControl, List<Package> packages});
}
/// @nodoc
class _$PackageListSelectorStateCopyWithImpl<$Res,
$Val extends PackageListSelectorState>
implements $PackageListSelectorStateCopyWith<$Res> {
_$PackageListSelectorStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? accessControl = null,
Object? packages = null,
}) {
return _then(_value.copyWith(
accessControl: null == accessControl
? _value.accessControl
: accessControl // ignore: cast_nullable_to_non_nullable
as AccessControl,
packages: null == packages
? _value.packages
: packages // ignore: cast_nullable_to_non_nullable
as List<Package>,
) as $Val);
}
}
/// @nodoc
abstract class _$$PackageListSelectorStateImplCopyWith<$Res>
implements $PackageListSelectorStateCopyWith<$Res> {
factory _$$PackageListSelectorStateImplCopyWith(
_$PackageListSelectorStateImpl value,
$Res Function(_$PackageListSelectorStateImpl) then) =
__$$PackageListSelectorStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({AccessControl accessControl, List<Package> packages});
}
/// @nodoc
class __$$PackageListSelectorStateImplCopyWithImpl<$Res>
extends _$PackageListSelectorStateCopyWithImpl<$Res,
_$PackageListSelectorStateImpl>
implements _$$PackageListSelectorStateImplCopyWith<$Res> {
__$$PackageListSelectorStateImplCopyWithImpl(
_$PackageListSelectorStateImpl _value,
$Res Function(_$PackageListSelectorStateImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? accessControl = null,
Object? packages = null,
}) {
return _then(_$PackageListSelectorStateImpl(
accessControl: null == accessControl
? _value.accessControl
: accessControl // ignore: cast_nullable_to_non_nullable
as AccessControl,
packages: null == packages
? _value._packages
: packages // ignore: cast_nullable_to_non_nullable
as List<Package>,
));
}
}
/// @nodoc
class _$PackageListSelectorStateImpl implements _PackageListSelectorState {
const _$PackageListSelectorStateImpl(
{required this.accessControl, required final List<Package> packages})
: _packages = packages;
@override
final AccessControl accessControl;
final List<Package> _packages;
@override
List<Package> get packages {
if (_packages is EqualUnmodifiableListView) return _packages;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_packages);
}
@override
String toString() {
return 'PackageListSelectorState(accessControl: $accessControl, packages: $packages)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PackageListSelectorStateImpl &&
(identical(other.accessControl, accessControl) ||
other.accessControl == accessControl) &&
const DeepCollectionEquality().equals(other._packages, _packages));
}
@override
int get hashCode => Object.hash(runtimeType, accessControl,
const DeepCollectionEquality().hash(_packages));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$PackageListSelectorStateImplCopyWith<_$PackageListSelectorStateImpl>
get copyWith => __$$PackageListSelectorStateImplCopyWithImpl<
_$PackageListSelectorStateImpl>(this, _$identity);
}
abstract class _PackageListSelectorState implements PackageListSelectorState {
const factory _PackageListSelectorState(
{required final AccessControl accessControl,
required final List<Package> packages}) = _$PackageListSelectorStateImpl;
@override
AccessControl get accessControl;
@override
List<Package> get packages;
@override
@JsonKey(ignore: true)
_$$PackageListSelectorStateImplCopyWith<_$PackageListSelectorStateImpl>
get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc /// @nodoc
mixin _$ApplicationSelectorState { mixin _$ApplicationSelectorState {
String? get locale => throw _privateConstructorUsedError; String? get locale => throw _privateConstructorUsedError;
@@ -2070,159 +2219,3 @@ abstract class _MoreToolsSelectorState implements MoreToolsSelectorState {
_$$MoreToolsSelectorStateImplCopyWith<_$MoreToolsSelectorStateImpl> _$$MoreToolsSelectorStateImplCopyWith<_$MoreToolsSelectorStateImpl>
get copyWith => throw _privateConstructorUsedError; get copyWith => throw _privateConstructorUsedError;
} }
/// @nodoc
mixin _$PackageListSelectorState {
AccessControl get accessControl => throw _privateConstructorUsedError;
bool get isAccessControl => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$PackageListSelectorStateCopyWith<PackageListSelectorState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $PackageListSelectorStateCopyWith<$Res> {
factory $PackageListSelectorStateCopyWith(PackageListSelectorState value,
$Res Function(PackageListSelectorState) then) =
_$PackageListSelectorStateCopyWithImpl<$Res, PackageListSelectorState>;
@useResult
$Res call({AccessControl accessControl, bool isAccessControl});
$AccessControlCopyWith<$Res> get accessControl;
}
/// @nodoc
class _$PackageListSelectorStateCopyWithImpl<$Res,
$Val extends PackageListSelectorState>
implements $PackageListSelectorStateCopyWith<$Res> {
_$PackageListSelectorStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? accessControl = null,
Object? isAccessControl = null,
}) {
return _then(_value.copyWith(
accessControl: null == accessControl
? _value.accessControl
: accessControl // ignore: cast_nullable_to_non_nullable
as AccessControl,
isAccessControl: null == isAccessControl
? _value.isAccessControl
: isAccessControl // ignore: cast_nullable_to_non_nullable
as bool,
) as $Val);
}
@override
@pragma('vm:prefer-inline')
$AccessControlCopyWith<$Res> get accessControl {
return $AccessControlCopyWith<$Res>(_value.accessControl, (value) {
return _then(_value.copyWith(accessControl: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$PackageListSelectorStateImplCopyWith<$Res>
implements $PackageListSelectorStateCopyWith<$Res> {
factory _$$PackageListSelectorStateImplCopyWith(
_$PackageListSelectorStateImpl value,
$Res Function(_$PackageListSelectorStateImpl) then) =
__$$PackageListSelectorStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({AccessControl accessControl, bool isAccessControl});
@override
$AccessControlCopyWith<$Res> get accessControl;
}
/// @nodoc
class __$$PackageListSelectorStateImplCopyWithImpl<$Res>
extends _$PackageListSelectorStateCopyWithImpl<$Res,
_$PackageListSelectorStateImpl>
implements _$$PackageListSelectorStateImplCopyWith<$Res> {
__$$PackageListSelectorStateImplCopyWithImpl(
_$PackageListSelectorStateImpl _value,
$Res Function(_$PackageListSelectorStateImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? accessControl = null,
Object? isAccessControl = null,
}) {
return _then(_$PackageListSelectorStateImpl(
accessControl: null == accessControl
? _value.accessControl
: accessControl // ignore: cast_nullable_to_non_nullable
as AccessControl,
isAccessControl: null == isAccessControl
? _value.isAccessControl
: isAccessControl // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
/// @nodoc
class _$PackageListSelectorStateImpl implements _PackageListSelectorState {
const _$PackageListSelectorStateImpl(
{required this.accessControl, required this.isAccessControl});
@override
final AccessControl accessControl;
@override
final bool isAccessControl;
@override
String toString() {
return 'PackageListSelectorState(accessControl: $accessControl, isAccessControl: $isAccessControl)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PackageListSelectorStateImpl &&
(identical(other.accessControl, accessControl) ||
other.accessControl == accessControl) &&
(identical(other.isAccessControl, isAccessControl) ||
other.isAccessControl == isAccessControl));
}
@override
int get hashCode => Object.hash(runtimeType, accessControl, isAccessControl);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$PackageListSelectorStateImplCopyWith<_$PackageListSelectorStateImpl>
get copyWith => __$$PackageListSelectorStateImplCopyWithImpl<
_$PackageListSelectorStateImpl>(this, _$identity);
}
abstract class _PackageListSelectorState implements PackageListSelectorState {
const factory _PackageListSelectorState(
{required final AccessControl accessControl,
required final bool isAccessControl}) = _$PackageListSelectorStateImpl;
@override
AccessControl get accessControl;
@override
bool get isAccessControl;
@override
@JsonKey(ignore: true)
_$$PackageListSelectorStateImplCopyWith<_$PackageListSelectorStateImpl>
get copyWith => throw _privateConstructorUsedError;
}

View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'config.dart'; import 'config.dart';
import 'navigation.dart'; import 'navigation.dart';
import 'package.dart';
import 'profile.dart'; import 'profile.dart';
import 'proxy.dart'; import 'proxy.dart';
@@ -43,6 +44,14 @@ class ProfilesSelectorState with _$ProfilesSelectorState {
}) = _ProfilesSelectorState; }) = _ProfilesSelectorState;
} }
@freezed
class PackageListSelectorState with _$PackageListSelectorState {
const factory PackageListSelectorState({
required AccessControl accessControl,
required List<Package> packages,
}) = _PackageListSelectorState;
}
@freezed @freezed
class ApplicationSelectorState with _$ApplicationSelectorState { class ApplicationSelectorState with _$ApplicationSelectorState {
const factory ApplicationSelectorState({ const factory ApplicationSelectorState({
@@ -117,12 +126,4 @@ class MoreToolsSelectorState with _$MoreToolsSelectorState {
const factory MoreToolsSelectorState({ const factory MoreToolsSelectorState({
required List<NavigationItem> navigationItems, required List<NavigationItem> navigationItems,
}) = _MoreToolsSelectorState; }) = _MoreToolsSelectorState;
}
@freezed
class PackageListSelectorState with _$PackageListSelectorState {
const factory PackageListSelectorState({
required AccessControl accessControl,
required bool isAccessControl,
}) = _PackageListSelectorState;
} }

View File

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

View File

@@ -1,5 +1,4 @@
// ignore_for_file: avoid_print // ignore_for_file: avoid_print
void main() async { void main() async {
String input = """ String input = """