Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions lib/services/api/nexusphp_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import 'nexusphp_helper.dart';
/// NexusPHP 站点适配器
/// 实现 NexusPHP (1.9+) 站点的 API 调用
class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter {
// ⚡ Bolt: Cache RegExp to avoid recompiling on every match during loops
static final RegExp _invisibleCharsRegExp = RegExp(r'[\s\u200B-\u200D\uFEFF]');

late SiteConfig _siteConfig;
late Dio _dio;
Map<String, String>? _discountMapping;
Expand Down Expand Up @@ -536,13 +539,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(_invisibleCharsRegExp, '');
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]'),
_invisibleCharsRegExp,
'',
);
categories.add(
Expand Down
17 changes: 11 additions & 6 deletions lib/services/api/nexusphp_web_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,15 @@ class ParsedTorrentResult {
}

/// Helper class for Isolate usage
class _AdapterHelper with BaseWebAdapterMixin {}
class _AdapterHelper with BaseWebAdapterMixin {
// ⚡ Bolt: Cache RegExp to avoid recompiling on every match during loops
static final RegExp sizeRegExp = RegExp(r'([\d.]+)\s*(\w+)');
// ⚡ Bolt: Cache RegExp to avoid recompiling for every torrent list item
static final RegExp relativeUrlRegExp = RegExp(
r'(src|href)="((?!https?://|//|data:|javascript:|#)[^"]+)"',
caseSensitive: false,
);
}

/// Isolate entry point for parsing search results
Future<ParsedTorrentResult> _parseSearchResponseInIsolate(
Expand Down Expand Up @@ -1147,7 +1155,7 @@ class NexusPHPWebAdapter extends SiteAdapter
// 解析文件大小为字节数
int sizeInBytes = 0;
if (sizeText.isNotEmpty) {
final sizeMatch = RegExp(r'([\d.]+)\s*(\w+)').firstMatch(sizeText);
final sizeMatch = _AdapterHelper.sizeRegExp.firstMatch(sizeText);
if (sizeMatch != null) {
final sizeValue = double.tryParse(sizeMatch.group(1) ?? '0') ?? 0;
final unit = sizeMatch.group(2)?.toUpperCase() ?? 'B';
Expand Down Expand Up @@ -1303,10 +1311,7 @@ class NexusPHPWebAdapter extends SiteAdapter
} else {
// HTML 模式:处理相对URL
extractedContent = extractedContent.replaceAllMapped(
RegExp(
r'(src|href)="((?!https?://|//|data:|javascript:|#)[^"]+)"',
caseSensitive: false,
),
_AdapterHelper.relativeUrlRegExp,
(match) {
final attr = match.group(1);
final path = match.group(2)!;
Expand Down
5 changes: 4 additions & 1 deletion lib/services/app_update_downloader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class AppUpdateProgress {
}

class AppUpdateDownloader {
// ⚡ Bolt: Cache RegExp to avoid recompiling on every call
static final RegExp _invalidCharsRegExp = RegExp(r'[^0-9A-Za-z._-]');

AppUpdateDownloader._();

static final AppUpdateDownloader instance = AppUpdateDownloader._();
Expand Down Expand Up @@ -204,7 +207,7 @@ class AppUpdateDownloader {
final completer = Completer<void>();

final filenameVersion = (version ?? 'latest').replaceAll(
RegExp(r'[^0-9A-Za-z._-]'),
_invalidCharsRegExp,
'_',
);
final destinationFilename = 'pt_mate-$filenameVersion-arm64-v8a.apk';
Expand Down
8 changes: 6 additions & 2 deletions lib/services/downloader/qbittorrent_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import 'torrent_file_downloader_mixin.dart';
class QbittorrentClient
with TorrentFileDownloaderMixin
implements DownloaderClient {
// ⚡ Bolt: Cache RegExp to avoid recompiling on every call
static final RegExp _httpProtocolRegExp = RegExp(r'https?://');
static final RegExp _sidRegExp = RegExp(r'SID=([^;]+)');

final QbittorrentConfig config;
final String password;

Expand Down Expand Up @@ -65,7 +69,7 @@ class QbittorrentClient
String _buildBase(QbittorrentConfig c) {
var urlStr = c.host.trim();
// 补全协议
if (!urlStr.startsWith(RegExp(r'https?://'))) {
if (!urlStr.startsWith(_httpProtocolRegExp)) {
urlStr = 'http://$urlStr';
}

Expand Down Expand Up @@ -223,7 +227,7 @@ class QbittorrentClient
// 从响应头中提取会话ID
final cookies = response.headers['set-cookie'];
if (cookies != null && cookies.isNotEmpty) {
final sidMatch = RegExp(r'SID=([^;]+)').firstMatch(cookies.first);
final sidMatch = _sidRegExp.firstMatch(cookies.first);
if (sidMatch != null) {
_sessionId = sidMatch.group(1);
return;
Expand Down
5 changes: 4 additions & 1 deletion lib/services/downloader/rutorrent_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import 'torrent_file_downloader_mixin.dart';
class RuTorrentClient
with TorrentFileDownloaderMixin
implements DownloaderClient {
// ⚡ Bolt: Cache RegExp to avoid recompiling on every call
static final RegExp _httpProtocolRegExp = RegExp(r'https?://');

final RuTorrentConfig config;
final String password;

Expand Down Expand Up @@ -66,7 +69,7 @@ class RuTorrentClient
String _buildBase(RuTorrentConfig c) {
var urlStr = c.host.trim();
// 补全协议
if (!urlStr.startsWith(RegExp(r'https?://'))) {
if (!urlStr.startsWith(_httpProtocolRegExp)) {
urlStr = 'http://$urlStr';
}

Expand Down
5 changes: 4 additions & 1 deletion lib/services/downloader/transmission_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import 'torrent_file_downloader_mixin.dart';
class TransmissionClient
with TorrentFileDownloaderMixin
implements DownloaderClient {
// ⚡ Bolt: Cache RegExp to avoid recompiling on every call
static final RegExp _httpProtocolRegExp = RegExp(r'https?://');

final TransmissionConfig config;
final String password;

Expand Down Expand Up @@ -52,7 +55,7 @@ class TransmissionClient
String _buildBase(TransmissionConfig c) {
var urlStr = c.host.trim();
// 补全协议
if (!urlStr.startsWith(RegExp(r'https?://'))) {
if (!urlStr.startsWith(_httpProtocolRegExp)) {
urlStr = 'http://$urlStr';
}

Expand Down
4 changes: 3 additions & 1 deletion lib/utils/format.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class FormatUtil {

class Formatters {
static final NumberFormat _num2 = NumberFormat('#,##0.00');
// ⚡ Bolt: Cache RegExp to avoid recompiling on every call
static final RegExp _timezoneRegExp = RegExp(r'Z|[+-]\d{2}:?\d{2}$');

// 输入单位为 B(字节),格式化为 GB 或 TB(保留两位小数)
static String dataFromBytes(num bytes) {
Expand Down Expand Up @@ -193,7 +195,7 @@ class Formatters {
normalizedDate = normalizedDate.replaceRange(10, 11, 'T');
}

if (normalizedDate.contains(RegExp(r'Z|[+-]\d{2}:?\d{2}$'))) {
if (normalizedDate.contains(_timezoneRegExp)) {
return DateTime.parse(normalizedDate).toLocal();
} else {
return DateTime.parse("$normalizedDate$actualZone").toLocal();
Expand Down
16 changes: 8 additions & 8 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down