perf: optimize providers, caching, and reduce rebuilds

- Cache SharedPreferences.getInstance() in providers (settings, theme, recent_access)
- Pre-compute download counts in queue provider to avoid repeated filtering
- Add identical() caching for RecentAccessView in HomeTab
- Use selective watching for exploreProvider (sections, greeting, isLoading only)
- Move isYTMusicQuickPicks computation to ExploreSection.fromJson()
- Hoist static RegExp patterns to avoid repeated compilation
- Use batch operations for iOS path migration in history_database
- Replace containsKey+lookup with single lookup in palette_service
- Pre-compute lowercase strings outside filter loops in logger
- Fix _isLoaded race condition in DownloadHistoryNotifier
This commit is contained in:
zarzet
2026-01-22 03:56:47 +07:00
parent 55b75dc48d
commit 6388f3a5b8
17 changed files with 287 additions and 155 deletions
+17 -8
View File
@@ -26,6 +26,15 @@ class _UpdateDialogState extends State<UpdateDialog> {
bool _isDownloading = false;
double _progress = 0;
String _statusText = '';
static final RegExp _whatsNewPattern =
RegExp(r"###?\s*What'?s\s*New\s*\n", caseSensitive: false);
static final RegExp _cutoffPattern =
RegExp(r'\n---|\n###?\s*Downloads', caseSensitive: false);
static final RegExp _sectionPattern = RegExp(r'^#{1,3}\s*(.+)$');
static final RegExp _listPattern = RegExp(r'^[-*]\s+(.+)$');
static final RegExp _subListPattern = RegExp(r'^\s+[-*]\s+(.+)$');
static final RegExp _boldPattern = RegExp(r'\*\*([^*]+)\*\*');
static final RegExp _codePattern = RegExp(r'`([^`]+)`');
Future<void> _downloadAndInstall() async {
final apkUrl = widget.updateInfo.apkDownloadUrl;
@@ -293,12 +302,12 @@ class _UpdateDialogState extends State<UpdateDialog> {
String _formatChangelog(String changelog) {
var content = changelog;
final whatsNewMatch = RegExp(r"###?\s*What'?s\s*New\s*\n", caseSensitive: false).firstMatch(content);
final whatsNewMatch = _whatsNewPattern.firstMatch(content);
if (whatsNewMatch != null) {
content = content.substring(whatsNewMatch.end);
}
final cutoffMatch = RegExp(r'\n---|\n###?\s*Downloads', caseSensitive: false).firstMatch(content);
final cutoffMatch = _cutoffPattern.firstMatch(content);
if (cutoffMatch != null) {
content = content.substring(0, cutoffMatch.start);
}
@@ -310,7 +319,7 @@ class _UpdateDialogState extends State<UpdateDialog> {
line = line.trim();
if (line.isEmpty) continue;
final sectionMatch = RegExp(r'^#{1,3}\s*(.+)$').firstMatch(line);
final sectionMatch = _sectionPattern.firstMatch(line);
if (sectionMatch != null) {
final section = sectionMatch.group(1)?.trim();
if (section != null && section.isNotEmpty) {
@@ -320,19 +329,19 @@ class _UpdateDialogState extends State<UpdateDialog> {
continue;
}
final listMatch = RegExp(r'^[-*]\s+(.+)$').firstMatch(line);
final listMatch = _listPattern.firstMatch(line);
if (listMatch != null) {
var itemText = listMatch.group(1) ?? '';
itemText = itemText.replaceAllMapped(RegExp(r'\*\*([^*]+)\*\*'), (m) => m.group(1) ?? '');
itemText = itemText.replaceAllMapped(RegExp(r'`([^`]+)`'), (m) => m.group(1) ?? '');
itemText = itemText.replaceAllMapped(_boldPattern, (m) => m.group(1) ?? '');
itemText = itemText.replaceAllMapped(_codePattern, (m) => m.group(1) ?? '');
formattedLines.add('• $itemText');
continue;
}
final subListMatch = RegExp(r'^\s+[-*]\s+(.+)$').firstMatch(line);
final subListMatch = _subListPattern.firstMatch(line);
if (subListMatch != null) {
var itemText = subListMatch.group(1) ?? '';
itemText = itemText.replaceAllMapped(RegExp(r'\*\*([^*]+)\*\*'), (m) => m.group(1) ?? '');
itemText = itemText.replaceAllMapped(_boldPattern, (m) => m.group(1) ?? '');
formattedLines.add(' - $itemText');
continue;
}