Update file_picker

Add resources page

Optimize more detail
This commit is contained in:
chen08209
2024-06-03 18:02:05 +08:00
parent 01f1b2d72f
commit bb7e44da30
50 changed files with 32716 additions and 443 deletions

View File

@@ -9,6 +9,8 @@ const httpTimeoutDuration = Duration(milliseconds: 5000);
const moreDuration = Duration(milliseconds: 100);
const defaultUpdateDuration = Duration(days: 1);
const mmdbFileName = "geoip.metadb";
const geoSiteFileName = "GeoSite.dat";
const asnFileName = "ASN.mmdb";
const profilesDirectoryName = "profiles";
const localhost = "127.0.0.1";
const clashConfigKey = "clash_config";

View File

@@ -1,5 +1,7 @@
import 'package:fl_clash/common/app_localizations.dart';
extension DateTimeExtension on DateTime {
bool isBeforeNow() {
bool get isBeforeNow {
return isBefore(DateTime.now());
}
@@ -9,4 +11,28 @@ extension DateTimeExtension on DateTime {
}
return true;
}
String get lastUpdateTimeDesc {
final currentDateTime = DateTime.now();
final difference = currentDateTime.difference(this);
final days = difference.inDays;
if (days >= 365) {
return "${(days / 365).floor()} ${appLocalizations.years}${appLocalizations.ago}";
}
if (days >= 30) {
return "${(days / 30).floor()} ${appLocalizations.months}${appLocalizations.ago}";
}
if (days >= 1) {
return "$days ${appLocalizations.days}${appLocalizations.ago}";
}
final hours = difference.inHours;
if (hours >= 1) {
return "$hours ${appLocalizations.hours}${appLocalizations.ago}";
}
final minutes = difference.inMinutes;
if (minutes >= 1) {
return "$minutes ${appLocalizations.minutes}${appLocalizations.ago}";
}
return appLocalizations.just;
}
}

View File

@@ -29,6 +29,14 @@ class Navigation {
label: "profiles",
fragment: ProfilesFragment(),
),
const NavigationItem(
icon: Icon(Icons.swap_vert_circle),
label: "resources",
description: "resourcesDesc",
keep: false,
fragment: Resources(),
modes: [NavigationItemMode.desktop, NavigationItemMode.more],
),
NavigationItem(
icon: const Icon(Icons.adb),
label: "logs",

View File

@@ -2,6 +2,8 @@ import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';
import 'package:fl_clash/common/constant.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:flutter/material.dart';
import 'package:zxing2/qrcode.dart';
import 'package:image/image.dart' as img;
@@ -178,6 +180,12 @@ class Other {
.where((item) => item.isNotEmpty)
.toList();
}
ViewMode getViewMode(double viewWidth){
if (viewWidth <= maxMobileWidth) return ViewMode.mobile;
if (viewWidth <= maxLaptopWidth) return ViewMode.laptop;
return ViewMode.desktop;
}
}
final other = Other();

View File

@@ -36,11 +36,6 @@ class AppPath {
final directory = await getProfilesPath();
return join(directory, "$id.yaml");
}
Future<String> getMMDBPath() async {
var directory = await applicationSupportDirectoryCompleter.future;
return join(directory.path, mmdbFileName);
}
}
final appPath = AppPath();

View File

@@ -3,10 +3,9 @@ import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:fl_clash/common/common.dart';
import 'package:image_picker/image_picker.dart';
import 'package:fl_clash/models/models.dart';
class Picker {
Future<Result<PlatformFile>> pickerConfigFile() async {
Future<PlatformFile?> pickerConfigFile() async {
FilePickerResult? filePickerResult;
if (Platform.isAndroid) {
filePickerResult = await FilePicker.platform.pickFiles(
@@ -23,20 +22,20 @@ class Picker {
}
final file = filePickerResult?.files.first;
if (file == null) {
return Result.error(appLocalizations.pleaseUploadFile);
return null;
}
return Result.success(file);
return file;
}
Future<Result<String>> pickerConfigQRCode() async {
Future<String?> pickerConfigQRCode() async {
final xFile = await ImagePicker().pickImage(source: ImageSource.gallery);
final bytes = await xFile?.readAsBytes();
if (bytes == null) return Result.error();
if (bytes == null) return null;
final result = await other.parseQRCode(bytes);
if (result == null || !result.isUrl) {
return Result.error(appLocalizations.pleaseUploadValidQrcode);
throw appLocalizations.pleaseUploadValidQrcode;
}
return Result.success(result);
return result;
}
}

View File

@@ -11,7 +11,7 @@ class ProxyManager {
_proxy = proxy ?? proxy_plugin.Proxy();
}
bool get isStart => startTime != null && startTime!.isBeforeNow();
bool get isStart => startTime != null && startTime!.isBeforeNow;
DateTime? get startTime => _proxy.startTime;

View File

@@ -1,36 +1,78 @@
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:fl_clash/common/common.dart';
import 'package:http/http.dart';
import '../models/models.dart';
import 'package:fl_clash/state.dart';
class Request {
static Future<Result<Response>> getFileResponseForUrl(String url) async {
final headers = {'User-Agent': coreName};
try {
final response = await get(Uri.parse(url), headers: headers).timeout(
httpTimeoutDuration,
late final Dio _dio;
int? _port;
Request() {
_dio = Dio(
BaseOptions(
connectTimeout: httpTimeoutDuration,
sendTimeout: httpTimeoutDuration,
receiveTimeout: httpTimeoutDuration,
headers: {"User-Agent": coreName},
),
);
_dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
_syncProxy();
return handler.next(options); // 继续请求
},
));
}
_syncProxy(){
final port = globalState.appController.clashConfig.mixedPort;
if (_port != port) {
_port = port;
_dio.httpClientAdapter = IOHttpClientAdapter(
createHttpClient: () {
final client = HttpClient();
client.findProxy = (url) {
return "PROXY localhost:$_port;DIRECT";
};
return client;
},
);
return Result.success(response);
} catch (err) {
return Result.error(err.toString());
}
}
static Future<Result<Map<String,dynamic>>> checkForUpdate() async {
final response = await get(
Uri.parse(
"https://api.github.com/repos/$repository/releases/latest",
Future<Response> getFileResponseForUrl(String url) async {
final response = await _dio
.get(
url,
options: Options(
responseType: ResponseType.bytes,
),
)
.timeout(
httpTimeoutDuration,
);
return response;
}
Future<Map<String, dynamic>?> checkForUpdate() async {
final response = await _dio.get(
"https://api.github.com/repos/$repository/releases/latest",
options: Options(
responseType: ResponseType.json,
),
);
if (response.statusCode != 200) return Result.error();
final body = json.decode(response.body) as Map<String,dynamic>;
final remoteVersion = body['tag_name'];
if (response.statusCode != 200) return null;
final data = response.data as Map<String, dynamic>;
final remoteVersion = data['tag_name'];
final packageInfo = await appPackage.packageInfoCompleter.future;
final version = packageInfo.version;
final hasUpdate =
other.compareVersions(remoteVersion.replaceAll('v', ''), version) > 0;
if (!hasUpdate) return Result.error();
return Result.success(body);
if (!hasUpdate) return null;
return data;
}
}
final request = Request();