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
35 changes: 20 additions & 15 deletions lib/services/api/nexusphp_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import 'package:pt_mate/services/site_config_service.dart';
import '../../utils/format.dart';
import 'nexusphp_helper.dart';

// ⚡ Bolt: Cache RegExp to avoid recompiling it in list parsing loops,
// minimizing object allocations and improving performance when iterating
// over search categories.
final RegExp _whitespaceRegExp = RegExp(r'[\s\u200B-\u200D\uFEFF]');

/// NexusPHP 站点适配器
/// 实现 NexusPHP (1.9+) 站点的 API 调用
class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter {
Expand Down Expand Up @@ -39,7 +44,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(
Expand Down Expand Up @@ -75,7 +82,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) {
Expand All @@ -91,9 +100,7 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter {
SiteType.nexusphp,
);
if (template?.discountMapping != null) {
_discountMapping = Map<String, String>.from(
template!.discountMapping,
);
_discountMapping = Map<String, String>.from(template!.discountMapping);
}
final specialMapping = await SiteConfigService.getDiscountMapping(
_siteConfig.baseUrl,
Expand Down Expand Up @@ -283,8 +290,6 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter {
}
}



final name = item['name'] as String;
final smallDescr = item['small_descr'] as String? ?? '';

Expand All @@ -311,8 +316,6 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter {
}
}



return TorrentItem(
id: (item['id'] as int).toString(),
name: name,
Expand Down Expand Up @@ -369,7 +372,11 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter {
}

@override
Future<TorrentCommentList> fetchComments(String id, {int pageNumber = 1, int pageSize = 20}) async {
Future<TorrentCommentList> fetchComments(
String id, {
int pageNumber = 1,
int pageSize = 20,
}) async {
try {
final response = await _dio.get(
'/api/v1/comments',
Expand Down Expand Up @@ -506,9 +513,7 @@ class NexusPHPAdapter with NexusPHPHelper implements SiteAdapter {
Future<List<SearchCategoryConfig>> getSearchCategories() async {
// 通过baseUrl匹配预设配置
final defaultCategories =
await SiteConfigService.getDefaultSearchCategories(
_siteConfig.baseUrl,
);
await SiteConfigService.getDefaultSearchCategories(_siteConfig.baseUrl);

// 如果获取到默认分类配置,则直接返回
if (defaultCategories.isNotEmpty) {
Expand Down Expand Up @@ -536,13 +541,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(
Expand Down
16 changes: 11 additions & 5 deletions lib/services/api/nexusphp_web_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ Future<ParsedTorrentResult> _parseSearchResponseInIsolate(
);
}

// ⚡ Bolt: Cache RegExp objects used in background isolates as top-level final
// variables. Caching these objects outside of the static class methods prevents
// recompilation on hot paths (e.g., list rendering and HTML parsing).
final RegExp _sizeRegExp = RegExp(r'([\d.]+)\s*(\w+)');
final RegExp _htmlUrlRegExp = RegExp(
r'(src|href)="((?!https?://|//|data:|javascript:|#)[^"]+)"',
caseSensitive: false,
);

/// NexusPHP Web站点适配器
/// 用于处理基于Web接口的NexusPHP站点
class NexusPHPWebAdapter extends SiteAdapter
Expand Down Expand Up @@ -1147,7 +1156,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';
Expand Down Expand Up @@ -1303,10 +1312,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)!;
Expand Down