From 3ba86dc9c264031fd0050e34bd7a057ef6b65338 Mon Sep 17 00:00:00 2001 From: chen08209 Date: Fri, 31 May 2024 09:59:18 +0800 Subject: [PATCH] optimize checkUpdate --- lib/common/other.dart | 13 +++++- lib/common/request.dart | 6 +-- lib/controller.dart | 64 +++++++++++++++++++++++------ lib/fragments/about.dart | 25 ++++-------- lib/l10n/arb/intl_en.arb | 4 +- lib/l10n/arb/intl_zh_CN.arb | 4 +- lib/l10n/intl/messages_en.dart | 3 ++ lib/l10n/intl/messages_zh_CN.dart | 2 + lib/l10n/l10n.dart | 20 +++++++++ lib/state.dart | 20 ++++++--- pubspec.yaml | 2 +- test/command_test.dart | 68 ++++++++++++++++++++++++++++--- 12 files changed, 182 insertions(+), 49 deletions(-) diff --git a/lib/common/other.dart b/lib/common/other.dart index abec888..fe93d0b 100644 --- a/lib/common/other.dart +++ b/lib/common/other.dart @@ -162,11 +162,22 @@ class Other { } } - double getViewWidth(){ + double getViewWidth() { final view = WidgetsBinding.instance.platformDispatcher.views.first; final size = view.physicalSize / view.devicePixelRatio; return size.width; } + + List parseReleaseBody(String? body) { + if(body == null) return []; + const pattern = r'- (.+?)\. \[.+?\]'; + final regex = RegExp(pattern); + return regex + .allMatches(body) + .map((match) => match.group(1) ?? '') + .where((item) => item.isNotEmpty) + .toList(); + } } final other = Other(); diff --git a/lib/common/request.dart b/lib/common/request.dart index 918ac4e..c70a8fc 100644 --- a/lib/common/request.dart +++ b/lib/common/request.dart @@ -17,20 +17,20 @@ class Request { } } - static Future> checkForUpdate() async { + static Future>> checkForUpdate() async { final response = await get( Uri.parse( "https://api.github.com/repos/$repository/releases/latest", ), ); if (response.statusCode != 200) return Result.error(); - final body = json.decode(response.body); + final body = json.decode(response.body) as Map; final remoteVersion = body['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['body']); + return Result.success(body); } } diff --git a/lib/controller.dart b/lib/controller.dart index 1d632b1..71afdd9 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:fl_clash/state.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; import 'clash/core.dart'; import 'enum/enum.dart'; @@ -209,14 +210,52 @@ class AppController { } autoCheckUpdate() async { + if (!config.autoCheckUpdate) return; final res = await Request.checkForUpdate(); - if(res.type != ResultType.success) return; - globalState.showMessage( - title: appLocalizations.checkUpdate, - message: TextSpan( - text: res.data, - ), - ); + checkUpdateResultHandle(result: res); + } + + checkUpdateResultHandle({ + Result>? result, + bool handleError = false +}) async { + if (result == null) return; + if (result.type == ResultType.success) { + final tagName = result.data?['tag_name']; + final body = result.data?['body']; + final submits = other.parseReleaseBody(body); + globalState.showMessage( + title: appLocalizations.discoverNewVersion, + message: TextSpan( + text: "$tagName \n", + style: context.textTheme.headlineSmall, + children: [ + TextSpan( + text: "\n", + style: context.textTheme.bodyMedium, + ), + for (final submit in submits) + TextSpan( + text: "- $submit \n", + style: context.textTheme.bodyMedium, + ), + ], + ), + onTab: () { + launchUrl( + Uri.parse("https://github.com/$repository/releases/latest"), + ); + }, + confirmText: appLocalizations.goDownload, + ); + } else if(handleError){ + globalState.showMessage( + title: appLocalizations.checkUpdate, + message: TextSpan( + text: appLocalizations.checkUpdateError, + ), + ); + } } afterInit() async { @@ -235,7 +274,7 @@ class AppController { } healthcheck() { - if(globalState.healthcheckLock) return; + if (globalState.healthcheckLock) return; for (final delay in appState.delayMap.entries) { setDelay( Delay( @@ -268,7 +307,6 @@ class AppController { } } - toProfiles() { final index = appState.currentNavigationItems.indexWhere( (element) => element.label == "profiles", @@ -365,7 +403,7 @@ class AppController { addProfileFormQrCode() async { final result = await picker.pickerConfigQRCode(); if (result.type == ResultType.error) { - if(result.message != null){ + if (result.message != null) { globalState.showMessage( title: appLocalizations.tip, message: TextSpan( @@ -394,10 +432,10 @@ class AppController { } } - updateViewWidth(){ + updateViewWidth() { appState.viewWidth = context.width; - if(appState.viewWidth == 0){ - Future.delayed(moreDuration,(){ + if (appState.viewWidth == 0) { + Future.delayed(moreDuration, () { updateViewWidth(); }); } diff --git a/lib/fragments/about.dart b/lib/fragments/about.dart index 2cacfcb..6f54e89 100644 --- a/lib/fragments/about.dart +++ b/lib/fragments/about.dart @@ -12,26 +12,15 @@ class AboutFragment extends StatelessWidget { _checkUpdate(BuildContext context) async { final commonScaffoldState = context.commonScaffoldState; if (commonScaffoldState?.mounted != true) return; - final res = await commonScaffoldState?.loadingRun>( + final res = + await commonScaffoldState?.loadingRun>>( Request.checkForUpdate, title: appLocalizations.checkUpdate, ); - if (res == null) return; - if (res.type == ResultType.success) { - globalState.showMessage( - title: appLocalizations.checkUpdate, - message: TextSpan( - text: res.data, - ), - ); - } else { - globalState.showMessage( - title: appLocalizations.checkUpdate, - message: TextSpan( - text: appLocalizations.checkUpdateError, - ), - ); - } + globalState.appController.checkUpdateResultHandle( + result: res, + handleError: true, + ); } @override @@ -92,7 +81,7 @@ class AboutFragment extends StatelessWidget { ), ListTile( title: Text(appLocalizations.checkUpdate), - onTap: (){ + onTap: () { _checkUpdate(context); }, ), diff --git a/lib/l10n/arb/intl_en.arb b/lib/l10n/arb/intl_en.arb index fc24448..fae49d9 100644 --- a/lib/l10n/arb/intl_en.arb +++ b/lib/l10n/arb/intl_en.arb @@ -149,5 +149,7 @@ "passwordTip": "Password cannot be empty", "accountTip": "Account cannot be empty", "checkUpdate": "Check for updates", - "checkUpdateError": "The current application is already the latest version" + "discoverNewVersion": "Discover the new version", + "checkUpdateError": "The current application is already the latest version", + "goDownload": "Go to download" } \ No newline at end of file diff --git a/lib/l10n/arb/intl_zh_CN.arb b/lib/l10n/arb/intl_zh_CN.arb index d0084fe..1028d85 100644 --- a/lib/l10n/arb/intl_zh_CN.arb +++ b/lib/l10n/arb/intl_zh_CN.arb @@ -149,5 +149,7 @@ "passwordTip": "密码不能为空", "accountTip": "账号不能为空", "checkUpdate": "检查更新", - "checkUpdateError": "当前应用已经是最新版了" + "discoverNewVersion": "发现新版本", + "checkUpdateError": "当前应用已经是最新版了", + "goDownload": "前往下载" } \ No newline at end of file diff --git a/lib/l10n/intl/messages_en.dart b/lib/l10n/intl/messages_en.dart index f9a358b..be7594a 100644 --- a/lib/l10n/intl/messages_en.dart +++ b/lib/l10n/intl/messages_en.dart @@ -99,6 +99,8 @@ class MessageLookup extends MessageLookupByLibrary { "desc": MessageLookupByLibrary.simpleMessage( "A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free."), "direct": MessageLookupByLibrary.simpleMessage("Direct"), + "discoverNewVersion": + MessageLookupByLibrary.simpleMessage("Discover the new version"), "discovery": MessageLookupByLibrary.simpleMessage("Discovery a new version"), "doYouWantToPass": @@ -113,6 +115,7 @@ class MessageLookup extends MessageLookupByLibrary { "filterSystemApp": MessageLookupByLibrary.simpleMessage("Filter system app"), "global": MessageLookupByLibrary.simpleMessage("Global"), + "goDownload": MessageLookupByLibrary.simpleMessage("Go to download"), "hours": MessageLookupByLibrary.simpleMessage("Hours"), "importFromURL": MessageLookupByLibrary.simpleMessage("Import from URL"), diff --git a/lib/l10n/intl/messages_zh_CN.dart b/lib/l10n/intl/messages_zh_CN.dart index 3a70eee..bfce1dd 100644 --- a/lib/l10n/intl/messages_zh_CN.dart +++ b/lib/l10n/intl/messages_zh_CN.dart @@ -83,6 +83,7 @@ class MessageLookup extends MessageLookupByLibrary { "desc": MessageLookupByLibrary.simpleMessage( "基于ClashMeta的多平台代理客户端,简单易用,开源无广告。"), "direct": MessageLookupByLibrary.simpleMessage("直连"), + "discoverNewVersion": MessageLookupByLibrary.simpleMessage("发现新版本"), "discovery": MessageLookupByLibrary.simpleMessage("发现新版本"), "doYouWantToPass": MessageLookupByLibrary.simpleMessage("是否要通过"), "download": MessageLookupByLibrary.simpleMessage("下载"), @@ -93,6 +94,7 @@ class MessageLookup extends MessageLookupByLibrary { "fileDesc": MessageLookupByLibrary.simpleMessage("直接上传配置文件"), "filterSystemApp": MessageLookupByLibrary.simpleMessage("过滤系统应用"), "global": MessageLookupByLibrary.simpleMessage("全局"), + "goDownload": MessageLookupByLibrary.simpleMessage("前往下载"), "hours": MessageLookupByLibrary.simpleMessage("小时"), "importFromURL": MessageLookupByLibrary.simpleMessage("从URL导入"), "just": MessageLookupByLibrary.simpleMessage("刚刚"), diff --git a/lib/l10n/l10n.dart b/lib/l10n/l10n.dart index 1ae8b1a..53020de 100644 --- a/lib/l10n/l10n.dart +++ b/lib/l10n/l10n.dart @@ -1550,6 +1550,16 @@ class AppLocalizations { ); } + /// `Discover the new version` + String get discoverNewVersion { + return Intl.message( + 'Discover the new version', + name: 'discoverNewVersion', + desc: '', + args: [], + ); + } + /// `The current application is already the latest version` String get checkUpdateError { return Intl.message( @@ -1559,6 +1569,16 @@ class AppLocalizations { args: [], ); } + + /// `Go to download` + String get goDownload { + return Intl.message( + 'Go to download', + name: 'goDownload', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/state.dart b/lib/state.dart index 4d5898d..fa518ce 100644 --- a/lib/state.dart +++ b/lib/state.dart @@ -158,18 +158,25 @@ class GlobalState { required String title, required InlineSpan message, Function()? onTab, + String? confirmText, }) { showCommonDialog( child: Builder( builder: (context) { return AlertDialog( title: Text(title), - content: SizedBox( + content: Container( width: 300, - child: RichText( - text: TextSpan( - style: Theme.of(context).textTheme.labelLarge, - children: [message], + constraints: const BoxConstraints( + maxHeight: 200 + ), + child: SingleChildScrollView( + child: RichText( + overflow: TextOverflow.visible, + text: TextSpan( + style: Theme.of(context).textTheme.labelLarge, + children: [message], + ), ), ), ), @@ -179,7 +186,7 @@ class GlobalState { () { Navigator.of(context).pop(); }, - child: Text(appLocalizations.confirm), + child: Text(confirmText ?? appLocalizations.confirm), ) ], ); @@ -200,6 +207,7 @@ class GlobalState { filter: filter, ); } + updateTraffic({ AppState? appState, required Config config, diff --git a/pubspec.yaml b/pubspec.yaml index e5bb9bf..dedddad 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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.5 +version: 0.8.6 environment: sdk: '>=3.1.0 <4.0.0' diff --git a/test/command_test.dart b/test/command_test.dart index a86603a..c42d6ea 100644 --- a/test/command_test.dart +++ b/test/command_test.dart @@ -4,10 +4,68 @@ import 'package:http/io_client.dart'; import 'dart:io'; void main() async { - HttpClient httpClient = HttpClient(); - httpClient.findProxy = HttpClient.findProxyFromEnvironment; + String input = """ +您 +
All changes from v0.8.5 to the latest commit: - IOClient ioClient = IOClient(httpClient); - var response = await ioClient.get(Uri.parse('https://mirror.ghproxy.com/https://raw.githubusercontent.com/Ruk1ng001/freeSub/main/clash_top30.yaml')); - print(response.body); + +(unreleased) +------------ +- Fix submit error. [chen08209] +- Add WebDAV. [chen08209] + + add Auto check updates + + Optimize more details +- Optimize delayTest. [chen08209] +- Upgrade flutter version. [chen08209] +- Update kernel Add import profile via QR code image. [chen08209] +- Add compatibility mode and adapt clash scheme. [chen08209] +- Update Version. [chen08209] +- Reconstruction application proxy logic. [chen08209] +- Fix Tab destroy error. [chen08209] +- Optimize repeat healthcheck. [chen08209] +- Optimize Direct mode ui. [chen08209] +- Optimize Healthcheck. [chen08209] +- Remove proxies position animation, improve performance Add Telegram + Link. [chen08209] +- Update healthcheck policy. [chen08209] +- New Check URLTest. [chen08209] +- Fix the problem of invalid auto-selection. [chen08209] +- New Async UpdateConfig. [chen08209] +- Add changeProfileDebounce. [chen08209] +- Update Workflow. [chen08209] +- Fix ChangeProfile block. [chen08209] +- Fix Release Message Error. [chen08209] +- Update Selector 2. [chen08209] +- Update Version. [chen08209] +- Fix Proxies Select Error. [chen08209] +- Fix the problem that the proxy group is empty in global mode. + [chen08209] +- Fix the problem that the proxy group is empty in global mode. + [chen08209] +- Add ProxyProvider2. [chen08209] +- Add ProxyProvider. [chen08209] +- Update Version. [chen08209] +- Update ProxyGroup Sort. [chen08209] +- Fix Android quickStart VpnService some problems. [chen08209] +- Update version. [chen08209] +- Set Android notification low importance. [chen08209] +- Fix the issue that VpnService can't be closed correctly in special + cases. [chen08209] +- Fix the problem that TileService is not destroyed correctly in some + cases. [chen08209] + + Adjust tab animation defaults +- Add Telegram in README_zh_CN.md. [chen08209] +- Add Telegram. [chen08209] +"""; + const pattern = r'- (.+?)\. \[.+?\]'; + final regex = RegExp(pattern); + + for (final match in regex.allMatches(input)) { + final change = match.group(1); + print(change); + } } +