Update file_picker
Add resources page Optimize more detail
This commit is contained in:
@@ -32,7 +32,6 @@ class AppState with ChangeNotifier {
|
||||
|
||||
AppState({
|
||||
required Mode mode,
|
||||
double? viewWidth,
|
||||
required bool isCompatible,
|
||||
required SelectedMap selectedMap,
|
||||
}) : _navigationItems = [],
|
||||
@@ -40,7 +39,7 @@ class AppState with ChangeNotifier {
|
||||
_currentLabel = "dashboard",
|
||||
_traffics = [],
|
||||
_logs = [],
|
||||
_viewWidth = viewWidth ?? 0,
|
||||
_viewWidth = 0,
|
||||
_selectedMap = selectedMap,
|
||||
_sortNum = 0,
|
||||
_mode = mode,
|
||||
@@ -167,6 +166,9 @@ class AppState with ChangeNotifier {
|
||||
|
||||
addLog(Log log) {
|
||||
_logs.add(log);
|
||||
if(_logs.length > 60){
|
||||
_logs = _logs.sublist(_logs.length - 60);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -179,7 +181,6 @@ class AppState with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<Group> get groups => _groups;
|
||||
|
||||
set groups(List<Group> value) {
|
||||
@@ -253,11 +254,7 @@ class AppState with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
ViewMode get viewMode {
|
||||
if (_viewWidth <= maxMobileWidth) return ViewMode.mobile;
|
||||
if (_viewWidth <= maxLaptopWidth) return ViewMode.laptop;
|
||||
return ViewMode.desktop;
|
||||
}
|
||||
ViewMode get viewMode => other.getViewMode(_viewWidth);
|
||||
|
||||
DelayMap get delayMap {
|
||||
return _delayMap;
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
|
||||
class Result<T> {
|
||||
String? message;
|
||||
ResultType type;
|
||||
T? data;
|
||||
|
||||
Result({
|
||||
this.message,
|
||||
required this.type,
|
||||
this.data,
|
||||
});
|
||||
|
||||
Result.success([this.data]) : type = ResultType.success,
|
||||
message = null;
|
||||
|
||||
Result.error([this.message]) : type = ResultType.error,
|
||||
data = null;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Result{message: $message, type: $type, data: $data}';
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ class Config extends ChangeNotifier {
|
||||
_autoRun = false,
|
||||
_themeMode = ThemeMode.system,
|
||||
_openLog = false,
|
||||
_isCompatible = false,
|
||||
_isCompatible = true,
|
||||
_primaryColor = defaultPrimaryColor.value,
|
||||
_proxiesSortType = ProxiesSortType.none,
|
||||
_isMinimizeOnExit = true,
|
||||
@@ -281,7 +281,7 @@ class Config extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
@JsonKey(defaultValue: false)
|
||||
@JsonKey(defaultValue: true)
|
||||
bool get isCompatible {
|
||||
return _isCompatible;
|
||||
}
|
||||
|
||||
@@ -75,3 +75,16 @@ class Process with _$Process {
|
||||
factory Process.fromJson(Map<String, Object?> json) =>
|
||||
_$ProcessFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ExternalProvider with _$ExternalProvider {
|
||||
const factory ExternalProvider({
|
||||
required String name,
|
||||
required String type,
|
||||
@JsonKey(name: "vehicle-type") required String vehicleType,
|
||||
@JsonKey(name: "update-at") required DateTime updateAt,
|
||||
}) = _ExternalProvider;
|
||||
|
||||
factory ExternalProvider.fromJson(Map<String, Object?> json) =>
|
||||
_$ExternalProviderFromJson(json);
|
||||
}
|
||||
|
||||
@@ -1029,3 +1029,214 @@ abstract class _Process implements Process {
|
||||
_$$ProcessImplCopyWith<_$ProcessImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
ExternalProvider _$ExternalProviderFromJson(Map<String, dynamic> json) {
|
||||
return _ExternalProvider.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ExternalProvider {
|
||||
String get name => throw _privateConstructorUsedError;
|
||||
String get type => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "vehicle-type")
|
||||
String get vehicleType => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "update-at")
|
||||
DateTime get updateAt => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$ExternalProviderCopyWith<ExternalProvider> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ExternalProviderCopyWith<$Res> {
|
||||
factory $ExternalProviderCopyWith(
|
||||
ExternalProvider value, $Res Function(ExternalProvider) then) =
|
||||
_$ExternalProviderCopyWithImpl<$Res, ExternalProvider>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String name,
|
||||
String type,
|
||||
@JsonKey(name: "vehicle-type") String vehicleType,
|
||||
@JsonKey(name: "update-at") DateTime updateAt});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ExternalProviderCopyWithImpl<$Res, $Val extends ExternalProvider>
|
||||
implements $ExternalProviderCopyWith<$Res> {
|
||||
_$ExternalProviderCopyWithImpl(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? name = null,
|
||||
Object? type = null,
|
||||
Object? vehicleType = null,
|
||||
Object? updateAt = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
name: null == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
type: null == type
|
||||
? _value.type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
vehicleType: null == vehicleType
|
||||
? _value.vehicleType
|
||||
: vehicleType // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
updateAt: null == updateAt
|
||||
? _value.updateAt
|
||||
: updateAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ExternalProviderImplCopyWith<$Res>
|
||||
implements $ExternalProviderCopyWith<$Res> {
|
||||
factory _$$ExternalProviderImplCopyWith(_$ExternalProviderImpl value,
|
||||
$Res Function(_$ExternalProviderImpl) then) =
|
||||
__$$ExternalProviderImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String name,
|
||||
String type,
|
||||
@JsonKey(name: "vehicle-type") String vehicleType,
|
||||
@JsonKey(name: "update-at") DateTime updateAt});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ExternalProviderImplCopyWithImpl<$Res>
|
||||
extends _$ExternalProviderCopyWithImpl<$Res, _$ExternalProviderImpl>
|
||||
implements _$$ExternalProviderImplCopyWith<$Res> {
|
||||
__$$ExternalProviderImplCopyWithImpl(_$ExternalProviderImpl _value,
|
||||
$Res Function(_$ExternalProviderImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? name = null,
|
||||
Object? type = null,
|
||||
Object? vehicleType = null,
|
||||
Object? updateAt = null,
|
||||
}) {
|
||||
return _then(_$ExternalProviderImpl(
|
||||
name: null == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
type: null == type
|
||||
? _value.type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
vehicleType: null == vehicleType
|
||||
? _value.vehicleType
|
||||
: vehicleType // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
updateAt: null == updateAt
|
||||
? _value.updateAt
|
||||
: updateAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$ExternalProviderImpl implements _ExternalProvider {
|
||||
const _$ExternalProviderImpl(
|
||||
{required this.name,
|
||||
required this.type,
|
||||
@JsonKey(name: "vehicle-type") required this.vehicleType,
|
||||
@JsonKey(name: "update-at") required this.updateAt});
|
||||
|
||||
factory _$ExternalProviderImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ExternalProviderImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String name;
|
||||
@override
|
||||
final String type;
|
||||
@override
|
||||
@JsonKey(name: "vehicle-type")
|
||||
final String vehicleType;
|
||||
@override
|
||||
@JsonKey(name: "update-at")
|
||||
final DateTime updateAt;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ExternalProvider(name: $name, type: $type, vehicleType: $vehicleType, updateAt: $updateAt)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ExternalProviderImpl &&
|
||||
(identical(other.name, name) || other.name == name) &&
|
||||
(identical(other.type, type) || other.type == type) &&
|
||||
(identical(other.vehicleType, vehicleType) ||
|
||||
other.vehicleType == vehicleType) &&
|
||||
(identical(other.updateAt, updateAt) ||
|
||||
other.updateAt == updateAt));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, name, type, vehicleType, updateAt);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ExternalProviderImplCopyWith<_$ExternalProviderImpl> get copyWith =>
|
||||
__$$ExternalProviderImplCopyWithImpl<_$ExternalProviderImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$ExternalProviderImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _ExternalProvider implements ExternalProvider {
|
||||
const factory _ExternalProvider(
|
||||
{required final String name,
|
||||
required final String type,
|
||||
@JsonKey(name: "vehicle-type") required final String vehicleType,
|
||||
@JsonKey(name: "update-at") required final DateTime updateAt}) =
|
||||
_$ExternalProviderImpl;
|
||||
|
||||
factory _ExternalProvider.fromJson(Map<String, dynamic> json) =
|
||||
_$ExternalProviderImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get name;
|
||||
@override
|
||||
String get type;
|
||||
@override
|
||||
@JsonKey(name: "vehicle-type")
|
||||
String get vehicleType;
|
||||
@override
|
||||
@JsonKey(name: "update-at")
|
||||
DateTime get updateAt;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$ExternalProviderImplCopyWith<_$ExternalProviderImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
@@ -94,3 +94,21 @@ Map<String, dynamic> _$$ProcessImplToJson(_$ProcessImpl instance) =>
|
||||
'source': instance.source,
|
||||
'target': instance.target,
|
||||
};
|
||||
|
||||
_$ExternalProviderImpl _$$ExternalProviderImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$ExternalProviderImpl(
|
||||
name: json['name'] as String,
|
||||
type: json['type'] as String,
|
||||
vehicleType: json['vehicle-type'] as String,
|
||||
updateAt: DateTime.parse(json['update-at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ExternalProviderImplToJson(
|
||||
_$ExternalProviderImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
'type': instance.type,
|
||||
'vehicle-type': instance.vehicleType,
|
||||
'update-at': instance.updateAt.toIso8601String(),
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ mixin _$NavigationItem {
|
||||
String get label => throw _privateConstructorUsedError;
|
||||
String? get description => throw _privateConstructorUsedError;
|
||||
Widget get fragment => throw _privateConstructorUsedError;
|
||||
bool get keep => throw _privateConstructorUsedError;
|
||||
String? get path => throw _privateConstructorUsedError;
|
||||
List<NavigationItemMode> get modes => throw _privateConstructorUsedError;
|
||||
|
||||
@@ -39,6 +40,7 @@ abstract class $NavigationItemCopyWith<$Res> {
|
||||
String label,
|
||||
String? description,
|
||||
Widget fragment,
|
||||
bool keep,
|
||||
String? path,
|
||||
List<NavigationItemMode> modes});
|
||||
}
|
||||
@@ -60,6 +62,7 @@ class _$NavigationItemCopyWithImpl<$Res, $Val extends NavigationItem>
|
||||
Object? label = null,
|
||||
Object? description = freezed,
|
||||
Object? fragment = null,
|
||||
Object? keep = null,
|
||||
Object? path = freezed,
|
||||
Object? modes = null,
|
||||
}) {
|
||||
@@ -80,6 +83,10 @@ class _$NavigationItemCopyWithImpl<$Res, $Val extends NavigationItem>
|
||||
? _value.fragment
|
||||
: fragment // ignore: cast_nullable_to_non_nullable
|
||||
as Widget,
|
||||
keep: null == keep
|
||||
? _value.keep
|
||||
: keep // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
path: freezed == path
|
||||
? _value.path
|
||||
: path // ignore: cast_nullable_to_non_nullable
|
||||
@@ -105,6 +112,7 @@ abstract class _$$NavigationItemImplCopyWith<$Res>
|
||||
String label,
|
||||
String? description,
|
||||
Widget fragment,
|
||||
bool keep,
|
||||
String? path,
|
||||
List<NavigationItemMode> modes});
|
||||
}
|
||||
@@ -124,6 +132,7 @@ class __$$NavigationItemImplCopyWithImpl<$Res>
|
||||
Object? label = null,
|
||||
Object? description = freezed,
|
||||
Object? fragment = null,
|
||||
Object? keep = null,
|
||||
Object? path = freezed,
|
||||
Object? modes = null,
|
||||
}) {
|
||||
@@ -144,6 +153,10 @@ class __$$NavigationItemImplCopyWithImpl<$Res>
|
||||
? _value.fragment
|
||||
: fragment // ignore: cast_nullable_to_non_nullable
|
||||
as Widget,
|
||||
keep: null == keep
|
||||
? _value.keep
|
||||
: keep // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
path: freezed == path
|
||||
? _value.path
|
||||
: path // ignore: cast_nullable_to_non_nullable
|
||||
@@ -164,6 +177,7 @@ class _$NavigationItemImpl implements _NavigationItem {
|
||||
required this.label,
|
||||
this.description,
|
||||
required this.fragment,
|
||||
this.keep = true,
|
||||
this.path,
|
||||
final List<NavigationItemMode> modes = const [
|
||||
NavigationItemMode.mobile,
|
||||
@@ -180,6 +194,9 @@ class _$NavigationItemImpl implements _NavigationItem {
|
||||
@override
|
||||
final Widget fragment;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool keep;
|
||||
@override
|
||||
final String? path;
|
||||
final List<NavigationItemMode> _modes;
|
||||
@override
|
||||
@@ -192,7 +209,7 @@ class _$NavigationItemImpl implements _NavigationItem {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'NavigationItem(icon: $icon, label: $label, description: $description, fragment: $fragment, path: $path, modes: $modes)';
|
||||
return 'NavigationItem(icon: $icon, label: $label, description: $description, fragment: $fragment, keep: $keep, path: $path, modes: $modes)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -206,13 +223,14 @@ class _$NavigationItemImpl implements _NavigationItem {
|
||||
other.description == description) &&
|
||||
(identical(other.fragment, fragment) ||
|
||||
other.fragment == fragment) &&
|
||||
(identical(other.keep, keep) || other.keep == keep) &&
|
||||
(identical(other.path, path) || other.path == path) &&
|
||||
const DeepCollectionEquality().equals(other._modes, _modes));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, icon, label, description,
|
||||
fragment, path, const DeepCollectionEquality().hash(_modes));
|
||||
fragment, keep, path, const DeepCollectionEquality().hash(_modes));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@@ -228,6 +246,7 @@ abstract class _NavigationItem implements NavigationItem {
|
||||
required final String label,
|
||||
final String? description,
|
||||
required final Widget fragment,
|
||||
final bool keep,
|
||||
final String? path,
|
||||
final List<NavigationItemMode> modes}) = _$NavigationItemImpl;
|
||||
|
||||
@@ -240,6 +259,8 @@ abstract class _NavigationItem implements NavigationItem {
|
||||
@override
|
||||
Widget get fragment;
|
||||
@override
|
||||
bool get keep;
|
||||
@override
|
||||
String? get path;
|
||||
@override
|
||||
List<NavigationItemMode> get modes;
|
||||
|
||||
@@ -9,7 +9,6 @@ export 'log.dart';
|
||||
export 'system_color_scheme.dart';
|
||||
export 'connection.dart';
|
||||
export 'package.dart';
|
||||
export 'common.dart';
|
||||
export 'ffi.dart';
|
||||
export 'selector.dart';
|
||||
export 'navigation.dart';
|
||||
|
||||
@@ -11,6 +11,7 @@ class NavigationItem with _$NavigationItem {
|
||||
required String label,
|
||||
final String? description,
|
||||
required Widget fragment,
|
||||
@Default(true) bool keep,
|
||||
String? path,
|
||||
@Default([NavigationItemMode.mobile, NavigationItemMode.desktop])
|
||||
List<NavigationItemMode> modes,
|
||||
|
||||
@@ -5,11 +5,8 @@ import 'dart:typed_data';
|
||||
import 'package:fl_clash/clash/core.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/models/models.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
import 'common.dart';
|
||||
|
||||
part 'generated/profile.g.dart';
|
||||
|
||||
typedef SelectedMap = Map<String, String>;
|
||||
@@ -83,44 +80,31 @@ class Profile {
|
||||
Duration? autoUpdateDuration,
|
||||
this.autoUpdate = true,
|
||||
}) : id = id ?? DateTime.now().millisecondsSinceEpoch.toString(),
|
||||
autoUpdateDuration =
|
||||
autoUpdateDuration ?? defaultUpdateDuration,
|
||||
autoUpdateDuration = autoUpdateDuration ?? defaultUpdateDuration,
|
||||
selectedMap = selectedMap ?? {};
|
||||
|
||||
ProfileType get type => url == null ? ProfileType.file : ProfileType.url;
|
||||
|
||||
Future<Result<bool>> checkAndUpdate() async {
|
||||
Future<void> checkAndUpdate() async {
|
||||
final isExists = await check();
|
||||
if(!isExists){
|
||||
if(url != null){
|
||||
if (!isExists) {
|
||||
if (url != null) {
|
||||
return await update();
|
||||
}
|
||||
return Result.error();
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
Future<Result<bool>> update() async {
|
||||
Future<void> update() async {
|
||||
if (url == null) {
|
||||
return Result.error(
|
||||
appLocalizations.unableToUpdateCurrentProfileDesc,
|
||||
);
|
||||
throw appLocalizations.unableToUpdateCurrentProfileDesc;
|
||||
}
|
||||
final responseResult = await Request.getFileResponseForUrl(url!);
|
||||
final response = responseResult.data;
|
||||
if (responseResult.type != ResultType.success || response == null) {
|
||||
return Result.error(responseResult.message);
|
||||
}
|
||||
final disposition = response.headers['content-disposition'];
|
||||
final response = await request.getFileResponseForUrl(url!);
|
||||
final disposition = response.headers.value("content-disposition");
|
||||
label ??= other.getFileNameForDisposition(disposition) ?? id;
|
||||
final userinfo = response.headers['subscription-userinfo'];
|
||||
final userinfo = response.headers.value('subscription-userinfo');
|
||||
userInfo = UserInfo.formHString(userinfo);
|
||||
final saveResult = await saveFile(response.bodyBytes);
|
||||
if (saveResult.type == ResultType.error) {
|
||||
return Result.error(saveResult.message);
|
||||
}
|
||||
await saveFile(response.data);
|
||||
lastUpdateDate = DateTime.now();
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
Future<bool> check() async {
|
||||
@@ -128,10 +112,10 @@ class Profile {
|
||||
return await File(profilePath!).exists();
|
||||
}
|
||||
|
||||
Future<Result<void>> saveFile(Uint8List bytes) async {
|
||||
final isValidate = clashCore.validateConfig(utf8.decode(bytes));
|
||||
if (!isValidate) {
|
||||
return Result.error(appLocalizations.profileParseErrorDesc);
|
||||
Future<void> saveFile(Uint8List bytes) async {
|
||||
final message = await clashCore.validateConfig(utf8.decode(bytes));
|
||||
if (message.isNotEmpty) {
|
||||
throw message;
|
||||
}
|
||||
final path = await appPath.getProfilePath(id);
|
||||
final file = File(path!);
|
||||
@@ -141,7 +125,6 @@ class Profile {
|
||||
}
|
||||
await file.writeAsBytes(bytes);
|
||||
lastUpdateDate = DateTime.now();
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
||||
Reference in New Issue
Block a user