mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-21 06:52:18 +02:00
perf(collections): reuse membership indexes for metadata changes
This commit is contained in:
1 parent
0c6ad3b96a
commit
996efb4f54
2 files changed
+76
-1
No files matched your search
@@ -171,6 +171,28 @@ class UserPlaylistCollection {
|
||||
return _trackKeys.contains(trackKey);
|
||||
}
|
||||
|
||||
bool sharesMembershipIndexWith(UserPlaylistCollection other) =>
|
||||
identical(_trackKeys, other._trackKeys);
|
||||
|
||||
/// Publishes tracks and their index built by the hydration worker. When it
|
||||
/// verified unchanged membership, keep the original index so the enclosing
|
||||
/// collections state need not rescan every other playlist's tracks.
|
||||
UserPlaylistCollection withHydratedTracks({
|
||||
required List<CollectionTrackEntry> tracks,
|
||||
required Set<String> trackKeys,
|
||||
required bool membershipUnchanged,
|
||||
}) => UserPlaylistCollection(
|
||||
id: id,
|
||||
name: name,
|
||||
coverImagePath: coverImagePath,
|
||||
createdAt: createdAt,
|
||||
updatedAt: updatedAt,
|
||||
tracks: tracks,
|
||||
previewCover: previewCover,
|
||||
tracksLoaded: true,
|
||||
trackKeys: membershipUnchanged ? _trackKeys : trackKeys,
|
||||
);
|
||||
|
||||
Set<String> get trackKeys => UnmodifiableSetView(_trackKeys);
|
||||
int get trackCount => _trackKeys.length;
|
||||
|
||||
@@ -365,10 +387,30 @@ class LibraryCollectionsState {
|
||||
lovedKeys: keepLovedIndex ? _lovedKeys : null,
|
||||
favoriteArtistKeys: keepFavoriteArtistIndex ? _favoriteArtistKeys : null,
|
||||
playlistsById: keepPlaylistIndex ? _playlistsById : null,
|
||||
allPlaylistTrackKeys: keepPlaylistIndex ? _allPlaylistTrackKeys : null,
|
||||
allPlaylistTrackKeys:
|
||||
keepPlaylistIndex || _hasSamePlaylistMembership(nextPlaylists)
|
||||
? _allPlaylistTrackKeys
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
bool _hasSamePlaylistMembership(List<UserPlaylistCollection> nextPlaylists) {
|
||||
if (nextPlaylists.length != playlists.length ||
|
||||
_playlistsById.length != playlists.length) {
|
||||
return false;
|
||||
}
|
||||
final seen = <String>{};
|
||||
for (final playlist in nextPlaylists) {
|
||||
final previous = _playlistsById[playlist.id];
|
||||
if (!seen.add(playlist.id) ||
|
||||
previous == null ||
|
||||
!identical(previous._trackKeys, playlist._trackKeys)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'wishlist': wishlist.map((e) => e.toJson()).toList(),
|
||||
'loved': loved.map((e) => e.toJson()).toList(),
|
||||
|
||||
@@ -106,4 +106,37 @@ void main() {
|
||||
expect(loaded.tracksLoaded, isTrue);
|
||||
expect(loaded.trackCount, 0);
|
||||
});
|
||||
|
||||
test(
|
||||
'membership remains correct after metadata copies and playlist changes',
|
||||
() {
|
||||
UserPlaylistCollection playlist(String id, String key) =>
|
||||
UserPlaylistCollection(
|
||||
id: id,
|
||||
name: id,
|
||||
createdAt: DateTime.utc(2026),
|
||||
updatedAt: DateTime.utc(2026),
|
||||
tracks: const [],
|
||||
tracksLoaded: false,
|
||||
trackKeys: {key},
|
||||
);
|
||||
final first = playlist('first', 'example:first');
|
||||
final second = playlist('second', 'example:second');
|
||||
final state = LibraryCollectionsState(playlists: [first, second]);
|
||||
final renamed = state.copyWith(
|
||||
playlists: [
|
||||
second.copyWith(name: 'Renamed'),
|
||||
first,
|
||||
],
|
||||
);
|
||||
expect(renamed.isTrackInAnyPlaylist('example:first'), isTrue);
|
||||
expect(renamed.isTrackInAnyPlaylist('example:second'), isTrue);
|
||||
final replaced = renamed.copyWith(playlists: [first, first]);
|
||||
expect(replaced.isTrackInAnyPlaylist('example:first'), isTrue);
|
||||
expect(replaced.isTrackInAnyPlaylist('example:second'), isFalse);
|
||||
final removed = renamed.copyWith(playlists: [second]);
|
||||
expect(removed.isTrackInAnyPlaylist('example:first'), isFalse);
|
||||
expect(removed.isTrackInAnyPlaylist('example:second'), isTrue);
|
||||
},
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user