diff --git a/lib/services/api/nexusphp_adapter.dart b/lib/services/api/nexusphp_adapter.dart index 2924535..370b7df 100644 --- a/lib/services/api/nexusphp_adapter.dart +++ b/lib/services/api/nexusphp_adapter.dart @@ -13,6 +13,8 @@ import 'nexusphp_helper.dart'; /// 实现 NexusPHP (1.9+) 站点的 API 调用 class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter { late SiteConfig _siteConfig; + // ⚡ Bolt: Cache RegExp instance to prevent repeated recompilation when trimming category names. + static final RegExp _whitespaceRegExp = RegExp(r'[\s\u200B-\u200D\uFEFF]'); late Dio _dio; Map? _discountMapping; Map? _tagMapping; @@ -39,7 +41,9 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter { await _loadTagMapping(); swDiscount.stop(); if (kDebugMode) { - _logger.d('NexusPHPAdapter.init: 加载优惠映射耗时=${swDiscount.elapsedMilliseconds}ms'); + _logger.d( + 'NexusPHPAdapter.init: 加载优惠映射耗时=${swDiscount.elapsedMilliseconds}ms', + ); } _dio = Dio( @@ -75,7 +79,9 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter { ); swInterceptors.stop(); if (kDebugMode) { - _logger.d('NexusPHPAdapter.init: 配置Dio与拦截器耗时=${swInterceptors.elapsedMilliseconds}ms'); + _logger.d( + 'NexusPHPAdapter.init: 配置Dio与拦截器耗时=${swInterceptors.elapsedMilliseconds}ms', + ); } swTotal.stop(); if (kDebugMode) { @@ -91,9 +97,7 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter { SiteType.nexusphp, ); if (template?.discountMapping != null) { - _discountMapping = Map.from( - template!.discountMapping, - ); + _discountMapping = Map.from(template!.discountMapping); } final specialMapping = await SiteConfigService.getDiscountMapping( _siteConfig.baseUrl, @@ -283,8 +287,6 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter { } } - - final name = item['name'] as String; final smallDescr = item['small_descr'] as String? ?? ''; @@ -311,8 +313,6 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter { } } - - return TorrentItem( id: (item['id'] as int).toString(), name: name, @@ -369,7 +369,11 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter { } @override - Future fetchComments(String id, {int pageNumber = 1, int pageSize = 20}) async { + Future fetchComments( + String id, { + int pageNumber = 1, + int pageSize = 20, + }) async { try { final response = await _dio.get( '/api/v1/comments', @@ -506,9 +510,7 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter { Future> getSearchCategories() async { // 通过baseUrl匹配预设配置 final defaultCategories = - await SiteConfigService.getDefaultSearchCategories( - _siteConfig.baseUrl, - ); + await SiteConfigService.getDefaultSearchCategories(_siteConfig.baseUrl); // 如果获取到默认分类配置,则直接返回 if (defaultCategories.isNotEmpty) { @@ -536,13 +538,13 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter { for (final section in sectionsData) { final sectionName = section['name'] as String; final sectionDisplayName = (section['display_name'] as String) - .replaceAll(RegExp(r'[\s\u200B-\u200D\uFEFF]'), ''); + .replaceAll(_whitespaceRegExp, ''); final categoriesData = section['categories'] as List; for (final category in categoriesData) { final categoryId = category['id']; final categoryName = (category['name'] as String).replaceAll( - RegExp(r'[\s\u200B-\u200D\uFEFF]'), + _whitespaceRegExp, '', ); categories.add( diff --git a/lib/services/api/nexusphp_web_adapter.dart b/lib/services/api/nexusphp_web_adapter.dart index de866d1..2f5c791 100644 --- a/lib/services/api/nexusphp_web_adapter.dart +++ b/lib/services/api/nexusphp_web_adapter.dart @@ -57,6 +57,13 @@ class ParsedTorrentResult { /// Helper class for Isolate usage class _AdapterHelper with BaseWebAdapterMixin {} +// ⚡ Bolt: Caching RegExp instances to prevent recompilation during isolate parsing loops. +final _sizeRegExp = RegExp(r'([\d.]+)\s*(\w+)'); +final _htmlUrlRegExp = RegExp( + r'(src|href)="((?!https?://|//|data:|javascript:|#)[^"]+)"', + caseSensitive: false, +); + /// Isolate entry point for parsing search results Future _parseSearchResponseInIsolate( ParseSearchParams params, @@ -1147,7 +1154,7 @@ class NexusPHPWebAdapter extends SiteAdapter // 解析文件大小为字节数 int sizeInBytes = 0; if (sizeText.isNotEmpty) { - final sizeMatch = RegExp(r'([\d.]+)\s*(\w+)').firstMatch(sizeText); + final sizeMatch = _sizeRegExp.firstMatch(sizeText); if (sizeMatch != null) { final sizeValue = double.tryParse(sizeMatch.group(1) ?? '0') ?? 0; final unit = sizeMatch.group(2)?.toUpperCase() ?? 'B'; @@ -1303,10 +1310,7 @@ class NexusPHPWebAdapter extends SiteAdapter } else { // HTML 模式:处理相对URL extractedContent = extractedContent.replaceAllMapped( - RegExp( - r'(src|href)="((?!https?://|//|data:|javascript:|#)[^"]+)"', - caseSensitive: false, - ), + _htmlUrlRegExp, (match) { final attr = match.group(1); final path = match.group(2)!; diff --git a/lib/widgets/web_login_widget.dart b/lib/widgets/web_login_widget.dart index a155474..dd5247a 100644 --- a/lib/widgets/web_login_widget.dart +++ b/lib/widgets/web_login_widget.dart @@ -23,6 +23,11 @@ class WebLoginWidget extends StatefulWidget { } class _WebLoginWidgetState extends State { + // ⚡ Bolt: Cache static RegExp instance to avoid compiling on every `_checkLoginStatus` call. + static final RegExp _titleRegExp = RegExp( + r'(.*?)<\/title>', + caseSensitive: false, + ); InAppWebViewController? _controller; bool _isLoading = true; bool _loginSuccess = false; @@ -77,10 +82,7 @@ class _WebLoginWidgetState extends State<WebLoginWidget> { if (html == null || html.isEmpty) return; // 检查页面标题 - final titleMatch = RegExp( - r'<title>(.*?)<\/title>', - caseSensitive: false, - ).firstMatch(html); + final titleMatch = _titleRegExp.firstMatch(html); final title = titleMatch?.group(1) ?? ""; // 如果标题包含登录字样,说明尚未成功 @@ -311,7 +313,11 @@ class _WebLoginWidgetState extends State<WebLoginWidget> { _logger.w('CookieManager未获取到cookie'); } if (mounted) { - NotificationHelper.showInfo(context, '无法获取cookie,请检查登录状态', duration: const Duration(seconds: 3)); + NotificationHelper.showInfo( + context, + '无法获取cookie,请检查登录状态', + duration: const Duration(seconds: 3), + ); } return false; } catch (e) { @@ -319,7 +325,7 @@ class _WebLoginWidgetState extends State<WebLoginWidget> { _logger.e('提取cookie时出错: $e'); } if (mounted) { - NotificationHelper.showError(context, 'Cookie提取失败: $e'); + NotificationHelper.showError(context, 'Cookie提取失败: $e'); } return false; } diff --git a/pubspec.lock b/pubspec.lock index 507755d..2ed0eaf 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" checked_yaml: dependency: transitive description: @@ -649,18 +649,18 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.18" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: @@ -1022,10 +1022,10 @@ packages: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.9" timezone: dependency: transitive description: