mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-29 21:02:09 +02:00
perf(search): reduce list rendering and provider rebuilds
This commit is contained in:
+26
-22
@@ -765,22 +765,25 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
),
|
||||
);
|
||||
|
||||
final hasExploreContent = ref.watch(
|
||||
exploreProvider.select((s) => s.sections.isNotEmpty),
|
||||
);
|
||||
final exploreLoading = ref.watch(
|
||||
exploreProvider.select((s) => s.isLoading),
|
||||
);
|
||||
final hasHomeFeedExtension = ref.watch(
|
||||
extensionProvider.select(
|
||||
(s) => s.extensions.any((e) => e.enabled && e.hasHomeFeed),
|
||||
),
|
||||
);
|
||||
final homeFeedDisabled = ref.watch(
|
||||
settingsProvider.select(
|
||||
(s) => s.homeFeedProvider == AppSettings.homeFeedProviderOff,
|
||||
),
|
||||
);
|
||||
final hasExploreContent =
|
||||
_showsHome &&
|
||||
ref.watch(exploreProvider.select((s) => s.sections.isNotEmpty));
|
||||
final exploreLoading =
|
||||
_showsHome && ref.watch(exploreProvider.select((s) => s.isLoading));
|
||||
final hasHomeFeedExtension =
|
||||
_showsHome &&
|
||||
ref.watch(
|
||||
extensionProvider.select(
|
||||
(s) => s.extensions.any((e) => e.enabled && e.hasHomeFeed),
|
||||
),
|
||||
);
|
||||
final homeFeedDisabled =
|
||||
_showsHome &&
|
||||
ref.watch(
|
||||
settingsProvider.select(
|
||||
(s) => s.homeFeedProvider == AppSettings.homeFeedProviderOff,
|
||||
),
|
||||
);
|
||||
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final searchText = _showsSearch ? _urlController.text.trim() : '';
|
||||
@@ -804,9 +807,11 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
_showsSearch &&
|
||||
ref.watch(trackProvider.select((s) => s.isShowingRecentAccess));
|
||||
final screenHeight = MediaQuery.sizeOf(context).height;
|
||||
final hasHistoryItems = ref.watch(
|
||||
_homeHistoryPreviewProvider.select((items) => items.isNotEmpty),
|
||||
);
|
||||
final hasHistoryItems =
|
||||
_showsHome &&
|
||||
ref.watch(
|
||||
_homeHistoryPreviewProvider.select((items) => items.isNotEmpty),
|
||||
);
|
||||
|
||||
final recentModeRequested =
|
||||
widget.mode == HomeTabMode.search ||
|
||||
@@ -982,9 +987,7 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
final recentAccessView = ref.watch(
|
||||
recentAccessViewProvider,
|
||||
);
|
||||
return SliverToBoxAdapter(
|
||||
child: _buildRecentAccess(recentAccessView, colorScheme),
|
||||
);
|
||||
return _buildRecentAccess(recentAccessView, colorScheme);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1113,6 +1116,7 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
|
||||
return SliverMainAxisGroup(
|
||||
slivers: _buildSearchResults(
|
||||
resultsRef: ref,
|
||||
tracks: tracks,
|
||||
isLoading: isLoading,
|
||||
error: error,
|
||||
|
||||
@@ -2,12 +2,43 @@ part of 'home_tab.dart';
|
||||
|
||||
extension _HomeTabRecentUI on _HomeTabState {
|
||||
Widget _buildRecentAccess(_RecentAccessView view, ColorScheme colorScheme) {
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
SliverToBoxAdapter(child: _buildRecentAccessHeader(view, colorScheme)),
|
||||
if (view.uniqueItems.isNotEmpty)
|
||||
SliverPadding(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(16, 0, 16, 8) +
|
||||
EdgeInsets.symmetric(horizontal: wideListInset(context)),
|
||||
sliver: SliverList.builder(
|
||||
itemCount: view.uniqueItems.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = view.uniqueItems[index];
|
||||
return KeyedSubtree(
|
||||
key: ValueKey('${item.type.name}:${item.id}'),
|
||||
child: _buildRecentAccessItem(
|
||||
item,
|
||||
colorScheme,
|
||||
view.downloadFilePathByRecentKey,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRecentAccessHeader(
|
||||
_RecentAccessView view,
|
||||
ColorScheme colorScheme,
|
||||
) {
|
||||
final uniqueItems = view.uniqueItems;
|
||||
final hasHiddenDownloads = view.hasHiddenDownloads;
|
||||
|
||||
return Padding(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(16, 8, 16, 8) +
|
||||
EdgeInsets.fromLTRB(16, 8, 16, uniqueItems.isEmpty ? 8 : 0) +
|
||||
EdgeInsets.symmetric(horizontal: wideListInset(context)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -99,14 +130,6 @@ extension _HomeTabRecentUI on _HomeTabState {
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
...uniqueItems.map(
|
||||
(item) => _buildRecentAccessItem(
|
||||
item,
|
||||
colorScheme,
|
||||
view.downloadFilePathByRecentKey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -299,6 +299,7 @@ extension _HomeTabSearchResultsUI on _HomeTabState {
|
||||
}
|
||||
|
||||
List<Widget> _buildSearchResults({
|
||||
required WidgetRef resultsRef,
|
||||
required List<Track> tracks,
|
||||
required bool isLoading,
|
||||
required String? error,
|
||||
@@ -418,7 +419,7 @@ extension _HomeTabSearchResultsUI on _HomeTabState {
|
||||
if (sortedTracks.isNotEmpty) {
|
||||
_historySnapshot.update(sortedTracks);
|
||||
final historyLookups = _historySnapshot.lookups;
|
||||
final existingHistoryKeys = ref.watch(
|
||||
final existingHistoryKeys = resultsRef.watch(
|
||||
downloadHistoryVisibleBatchExistsProvider(_historySnapshot.request),
|
||||
);
|
||||
slivers.addAll(
|
||||
@@ -540,6 +541,7 @@ extension _HomeTabSearchResultsUI on _HomeTabState {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: MornyeGlassPanel.overlay(
|
||||
blurEnabled: false,
|
||||
radius: 24,
|
||||
firstInGroup: isFirst,
|
||||
lastInGroup: isLast,
|
||||
|
||||
@@ -219,9 +219,9 @@ class _TrackItemWithStatus extends ConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
final queueItem = ref.watch(
|
||||
final isQueued = ref.watch(
|
||||
downloadQueueLookupProvider.select(
|
||||
(lookup) => lookup.byTrackId[track.id],
|
||||
(lookup) => lookup.byTrackId.containsKey(track.id),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -249,7 +249,6 @@ class _TrackItemWithStatus extends ConsumerWidget {
|
||||
thumbHeight = thumbSize.$2;
|
||||
}
|
||||
|
||||
final isQueued = queueItem != null;
|
||||
final hasCover = track.coverUrl?.isNotEmpty == true;
|
||||
|
||||
return Column(
|
||||
|
||||
@@ -131,6 +131,7 @@ class MornyeGlassPanel extends ConsumerWidget {
|
||||
this.strongTint = false,
|
||||
this.tintOpacity,
|
||||
this.liquidGlass = false,
|
||||
this.blurEnabled = true,
|
||||
});
|
||||
|
||||
/// Shared glass material for confirmation dialogs and floating sheets.
|
||||
@@ -142,6 +143,7 @@ class MornyeGlassPanel extends ConsumerWidget {
|
||||
this.lastInGroup = true,
|
||||
this.tintOpacity = 0.78,
|
||||
this.liquidGlass = false,
|
||||
this.blurEnabled = true,
|
||||
}) : strongTint = false;
|
||||
|
||||
final Widget child;
|
||||
@@ -152,9 +154,13 @@ class MornyeGlassPanel extends ConsumerWidget {
|
||||
final double? tintOpacity;
|
||||
final bool liquidGlass;
|
||||
|
||||
/// Disable backdrop sampling for surfaces that scroll over a plain page.
|
||||
final bool blurEnabled;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final blur =
|
||||
blurEnabled &&
|
||||
!MediaQuery.highContrastOf(context) &&
|
||||
(!ref.watch(lowEndDeviceProvider) ||
|
||||
ref.watch(backdropBlurEnabledProvider));
|
||||
|
||||
Reference in New Issue
Block a user