mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-08-28 05:40:29 +02:00
perf(library): stream scans and optimize queue queries
This commit is contained in:
+76
-36
@@ -481,7 +481,7 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
_QueueLibraryPageData? nonEmptyFallback,
|
||||
}) {
|
||||
void storePage(_QueueLibraryPageData data) {
|
||||
final cached = _queueLibraryPageDataCache[request];
|
||||
final cached = _cachedQueueLibraryPageAt(request, request.offset);
|
||||
if (shouldRetainQueueLibraryPageSnapshot(
|
||||
currentIsEmpty: data.isEmpty,
|
||||
cachedHasContent: cached != null && !cached.isEmpty,
|
||||
@@ -489,6 +489,17 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
final staleRequests = _queueLibraryPageDataCache.keys
|
||||
.where(
|
||||
(cachedRequest) =>
|
||||
cachedRequest.offset == request.offset &&
|
||||
cachedRequest != request &&
|
||||
_sameQueueLibraryPageScope(cachedRequest, request),
|
||||
)
|
||||
.toList(growable: false);
|
||||
for (final staleRequest in staleRequests) {
|
||||
_queueLibraryPageDataCache.remove(staleRequest);
|
||||
}
|
||||
_queueLibraryPageDataCache[request] = data;
|
||||
_trimQueueLibraryPageDataCache(protectedRequest: request);
|
||||
}
|
||||
@@ -503,19 +514,7 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
|
||||
final pages = <_QueueLibraryPageData>[];
|
||||
for (var offset = 0; offset <= request.offset; offset += _libraryPageSize) {
|
||||
final page =
|
||||
_queueLibraryPageDataCache[_QueueLibraryPageRequest(
|
||||
filterMode: request.filterMode,
|
||||
limit: request.limit,
|
||||
offset: offset,
|
||||
searchQuery: request.searchQuery,
|
||||
filterSource: request.filterSource,
|
||||
filterQuality: request.filterQuality,
|
||||
filterFormat: request.filterFormat,
|
||||
filterMetadata: request.filterMetadata,
|
||||
sortMode: request.sortMode,
|
||||
localLibraryEnabled: request.localLibraryEnabled,
|
||||
)];
|
||||
final page = _cachedQueueLibraryPageAt(request, offset);
|
||||
if (page != null) pages.add(page);
|
||||
}
|
||||
|
||||
@@ -569,16 +568,37 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
_QueueLibraryPageRequest request,
|
||||
_QueueLibraryPageRequest protectedRequest,
|
||||
) {
|
||||
return request.filterMode == protectedRequest.filterMode &&
|
||||
return _sameQueueLibraryPageScope(request, protectedRequest) &&
|
||||
request.limit == protectedRequest.limit &&
|
||||
request.offset <= protectedRequest.offset &&
|
||||
request.searchQuery == protectedRequest.searchQuery &&
|
||||
request.filterSource == protectedRequest.filterSource &&
|
||||
request.filterQuality == protectedRequest.filterQuality &&
|
||||
request.filterFormat == protectedRequest.filterFormat &&
|
||||
request.filterMetadata == protectedRequest.filterMetadata &&
|
||||
request.sortMode == protectedRequest.sortMode &&
|
||||
request.localLibraryEnabled == protectedRequest.localLibraryEnabled;
|
||||
request.offset <= protectedRequest.offset;
|
||||
}
|
||||
|
||||
bool _sameQueueLibraryPageScope(
|
||||
_QueueLibraryPageRequest a,
|
||||
_QueueLibraryPageRequest b,
|
||||
) {
|
||||
return a.filterMode == b.filterMode &&
|
||||
a.limit == b.limit &&
|
||||
a.searchQuery == b.searchQuery &&
|
||||
a.filterSource == b.filterSource &&
|
||||
a.filterQuality == b.filterQuality &&
|
||||
a.filterFormat == b.filterFormat &&
|
||||
a.filterMetadata == b.filterMetadata &&
|
||||
a.sortMode == b.sortMode &&
|
||||
a.localLibraryEnabled == b.localLibraryEnabled;
|
||||
}
|
||||
|
||||
_QueueLibraryPageData? _cachedQueueLibraryPageAt(
|
||||
_QueueLibraryPageRequest request,
|
||||
int offset,
|
||||
) {
|
||||
for (final entry in _queueLibraryPageDataCache.entries) {
|
||||
if (entry.key.offset == offset &&
|
||||
_sameQueueLibraryPageScope(entry.key, request)) {
|
||||
return entry.value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _trimQueueLibraryPageDataCache({
|
||||
@@ -1292,19 +1312,39 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
nonEmptyFallback: historySnapshotCounts,
|
||||
);
|
||||
|
||||
_QueueLibraryPageRequest pageRequest(String filterMode) =>
|
||||
_QueueLibraryPageRequest(
|
||||
filterMode: filterMode,
|
||||
limit: _libraryPageSize,
|
||||
offset: _libraryPageOffsetFor(filterMode),
|
||||
searchQuery: _searchQuery,
|
||||
filterSource: _filterSource,
|
||||
filterQuality: _filterQuality,
|
||||
filterFormat: _filterFormat,
|
||||
filterMetadata: _filterMetadata,
|
||||
sortMode: _sortMode,
|
||||
localLibraryEnabled: localLibraryEnabled,
|
||||
);
|
||||
_QueueLibraryPageRequest pageRequest(String filterMode) {
|
||||
final offset = _libraryPageOffsetFor(filterMode);
|
||||
final baseRequest = _QueueLibraryPageRequest(
|
||||
filterMode: filterMode,
|
||||
limit: _libraryPageSize,
|
||||
offset: offset,
|
||||
searchQuery: _searchQuery,
|
||||
filterSource: _filterSource,
|
||||
filterQuality: _filterQuality,
|
||||
filterFormat: _filterFormat,
|
||||
filterMetadata: _filterMetadata,
|
||||
sortMode: _sortMode,
|
||||
localLibraryEnabled: localLibraryEnabled,
|
||||
);
|
||||
if (offset == 0) return baseRequest;
|
||||
final previousPage = _cachedQueueLibraryPageAt(
|
||||
baseRequest,
|
||||
offset - _libraryPageSize,
|
||||
);
|
||||
return _QueueLibraryPageRequest(
|
||||
filterMode: baseRequest.filterMode,
|
||||
limit: baseRequest.limit,
|
||||
offset: baseRequest.offset,
|
||||
searchQuery: baseRequest.searchQuery,
|
||||
filterSource: baseRequest.filterSource,
|
||||
filterQuality: baseRequest.filterQuality,
|
||||
filterFormat: baseRequest.filterFormat,
|
||||
filterMetadata: baseRequest.filterMetadata,
|
||||
sortMode: baseRequest.sortMode,
|
||||
localLibraryEnabled: baseRequest.localLibraryEnabled,
|
||||
cursor: previousPage?.nextCursor,
|
||||
);
|
||||
}
|
||||
|
||||
final activePageRequest = pageRequest(historyFilterMode);
|
||||
final activePageValue = ref.watch(
|
||||
|
||||
@@ -89,6 +89,7 @@ class _QueueLibraryPageRequest {
|
||||
final String? filterMetadata;
|
||||
final String sortMode;
|
||||
final bool localLibraryEnabled;
|
||||
final QueueLibraryDbCursor? cursor;
|
||||
|
||||
const _QueueLibraryPageRequest({
|
||||
required this.filterMode,
|
||||
@@ -101,6 +102,7 @@ class _QueueLibraryPageRequest {
|
||||
required this.filterMetadata,
|
||||
required this.sortMode,
|
||||
required this.localLibraryEnabled,
|
||||
this.cursor,
|
||||
});
|
||||
|
||||
QueueLibraryDbQuery toDbQuery() => QueueLibraryDbQuery(
|
||||
@@ -114,6 +116,7 @@ class _QueueLibraryPageRequest {
|
||||
metadata: filterMetadata,
|
||||
sortMode: sortMode,
|
||||
includeLocal: localLibraryEnabled,
|
||||
cursor: cursor,
|
||||
);
|
||||
|
||||
bool get allowsInMemoryHistoryFallback =>
|
||||
@@ -141,7 +144,8 @@ class _QueueLibraryPageRequest {
|
||||
filterFormat == other.filterFormat &&
|
||||
filterMetadata == other.filterMetadata &&
|
||||
sortMode == other.sortMode &&
|
||||
localLibraryEnabled == other.localLibraryEnabled;
|
||||
localLibraryEnabled == other.localLibraryEnabled &&
|
||||
cursor == other.cursor;
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
@@ -155,6 +159,7 @@ class _QueueLibraryPageRequest {
|
||||
filterMetadata,
|
||||
sortMode,
|
||||
localLibraryEnabled,
|
||||
cursor,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -219,6 +224,7 @@ class _QueueLibraryPageData {
|
||||
final List<LocalLibraryItem> localItems;
|
||||
final List<_GroupedAlbum> groupedAlbums;
|
||||
final List<_GroupedLocalAlbum> groupedLocalAlbums;
|
||||
final QueueLibraryDbCursor? nextCursor;
|
||||
|
||||
const _QueueLibraryPageData({
|
||||
this.items = const [],
|
||||
@@ -226,6 +232,7 @@ class _QueueLibraryPageData {
|
||||
this.localItems = const [],
|
||||
this.groupedAlbums = const [],
|
||||
this.groupedLocalAlbums = const [],
|
||||
this.nextCursor,
|
||||
});
|
||||
|
||||
bool get isEmpty =>
|
||||
@@ -331,6 +338,7 @@ class _QueueLibraryPageData {
|
||||
localItems: localItems,
|
||||
groupedAlbums: groupedAlbums,
|
||||
groupedLocalAlbums: groupedLocalAlbums,
|
||||
nextCursor: pages.last.nextCursor,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -403,7 +411,10 @@ final _queueLibraryPageProvider = FutureProvider.autoDispose
|
||||
}
|
||||
final dbQuery = request.toDbQuery();
|
||||
if (request.filterMode == 'albums') {
|
||||
final rows = await LibraryDatabase.instance.getQueueAlbumPage(dbQuery);
|
||||
final page = await LibraryDatabase.instance.getQueueAlbumPageResult(
|
||||
dbQuery,
|
||||
);
|
||||
final rows = page.rows;
|
||||
final groupedAlbums = <_GroupedAlbum>[];
|
||||
final groupedLocalAlbums = <_GroupedLocalAlbum>[];
|
||||
for (final row in rows) {
|
||||
@@ -439,10 +450,14 @@ final _queueLibraryPageProvider = FutureProvider.autoDispose
|
||||
return _QueueLibraryPageData(
|
||||
groupedAlbums: groupedAlbums,
|
||||
groupedLocalAlbums: groupedLocalAlbums,
|
||||
nextCursor: page.nextCursor,
|
||||
);
|
||||
}
|
||||
|
||||
final rows = await LibraryDatabase.instance.getQueueTrackPage(dbQuery);
|
||||
final page = await LibraryDatabase.instance.getQueueTrackPageResult(
|
||||
dbQuery,
|
||||
);
|
||||
final rows = page.rows;
|
||||
final items = <UnifiedLibraryItem>[];
|
||||
final historyItems = <DownloadHistoryItem>[];
|
||||
final localItems = <LocalLibraryItem>[];
|
||||
@@ -463,6 +478,7 @@ final _queueLibraryPageProvider = FutureProvider.autoDispose
|
||||
items: items,
|
||||
historyItems: historyItems,
|
||||
localItems: localItems,
|
||||
nextCursor: page.nextCursor,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -105,6 +105,9 @@ class _MetadataCandidateArtworkState extends State<_MetadataCandidateArtwork> {
|
||||
width: 56,
|
||||
height: 56,
|
||||
fit: BoxFit.cover,
|
||||
cacheWidth: (56 * MediaQuery.devicePixelRatioOf(context)).round(),
|
||||
cacheHeight: (56 * MediaQuery.devicePixelRatioOf(context)).round(),
|
||||
filterQuality: FilterQuality.low,
|
||||
)
|
||||
: coverUrl != null
|
||||
? CachedCoverImage(
|
||||
@@ -2434,6 +2437,11 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> {
|
||||
width: 112,
|
||||
height: 112,
|
||||
fit: BoxFit.cover,
|
||||
cacheWidth: (112 * MediaQuery.devicePixelRatioOf(context))
|
||||
.round(),
|
||||
cacheHeight: (112 * MediaQuery.devicePixelRatioOf(context))
|
||||
.round(),
|
||||
filterQuality: FilterQuality.low,
|
||||
semanticLabel:
|
||||
context.l10n.editMetadataAutoFillCoverAvailable,
|
||||
errorBuilder: (_, _, _) => const SizedBox.shrink(),
|
||||
@@ -2710,6 +2718,11 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> {
|
||||
height: 160,
|
||||
width: 160,
|
||||
fit: BoxFit.cover,
|
||||
cacheWidth: (160 * MediaQuery.devicePixelRatioOf(context))
|
||||
.round(),
|
||||
cacheHeight: (160 * MediaQuery.devicePixelRatioOf(context))
|
||||
.round(),
|
||||
filterQuality: FilterQuality.low,
|
||||
errorBuilder: (_, _, _) => Container(
|
||||
width: 160,
|
||||
height: 160,
|
||||
|
||||
Reference in New Issue
Block a user