mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-30 13:19:44 +02:00
perf(player): rebuild preview buttons only on status changes
This commit is contained in:
1 parent
abfd8df5fb
commit
7a26f3beac
2 files changed
+96
-5
No files matched your search
@@ -39,8 +39,12 @@ class PreviewButton extends ConsumerWidget {
|
|||||||
|
|
||||||
// When the built-in player is currently on this track, mirror and control
|
// When the built-in player is currently on this track, mirror and control
|
||||||
// it (consistent with the mini player) rather than the preview snippet.
|
// it (consistent with the mini player) rather than the preview snippet.
|
||||||
final mainItem = ref.watch(currentMediaItemProvider).value;
|
final isCurrentMainTrack = ref.watch(
|
||||||
if (_isCurrentMainTrack(mainItem)) {
|
currentMediaItemProvider.select(
|
||||||
|
(item) => _isCurrentMainTrack(item.value),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (isCurrentMainTrack) {
|
||||||
final isPlaying = ref.watch(playbackPlayingProvider);
|
final isPlaying = ref.watch(playbackPlayingProvider);
|
||||||
return IconButton(
|
return IconButton(
|
||||||
iconSize: size,
|
iconSize: size,
|
||||||
@@ -62,9 +66,13 @@ class PreviewButton extends ConsumerWidget {
|
|||||||
|
|
||||||
if (!track.hasPreview) return const SizedBox.shrink();
|
if (!track.hasPreview) return const SizedBox.shrink();
|
||||||
|
|
||||||
final previewState = ref.watch(previewPlayerProvider);
|
final status = ref.watch(
|
||||||
final isActive = previewState.isActiveUrl(track.previewUrl);
|
previewPlayerProvider.select(
|
||||||
final status = isActive ? previewState.status : PreviewStatus.idle;
|
(state) => state.isActiveUrl(track.previewUrl)
|
||||||
|
? state.status
|
||||||
|
: PreviewStatus.idle,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
final Widget icon;
|
final Widget icon;
|
||||||
final String tooltip;
|
final String tooltip;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:spotiflac_android/models/settings.dart';
|
|||||||
import 'package:spotiflac_android/models/track.dart';
|
import 'package:spotiflac_android/models/track.dart';
|
||||||
import 'package:spotiflac_android/providers/library_collections_provider.dart';
|
import 'package:spotiflac_android/providers/library_collections_provider.dart';
|
||||||
import 'package:spotiflac_android/providers/music_player_provider.dart';
|
import 'package:spotiflac_android/providers/music_player_provider.dart';
|
||||||
|
import 'package:spotiflac_android/providers/preview_player_provider.dart';
|
||||||
import 'package:spotiflac_android/providers/settings_provider.dart';
|
import 'package:spotiflac_android/providers/settings_provider.dart';
|
||||||
import 'package:spotiflac_android/widgets/preview_button.dart';
|
import 'package:spotiflac_android/widgets/preview_button.dart';
|
||||||
import 'package:spotiflac_android/widgets/track_collection_quick_actions.dart';
|
import 'package:spotiflac_android/widgets/track_collection_quick_actions.dart';
|
||||||
@@ -79,6 +80,69 @@ void main() {
|
|||||||
expectCenteredHitbox(tester, Icons.play_circle_fill_rounded);
|
expectCenteredHitbox(tester, Icons.play_circle_fill_rounded);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('preview progress does not rebuild track buttons', (
|
||||||
|
tester,
|
||||||
|
) async {
|
||||||
|
final player = _TestPreviewPlayer();
|
||||||
|
var builds = 0;
|
||||||
|
await tester.pumpWidget(
|
||||||
|
ProviderScope(
|
||||||
|
overrides: [
|
||||||
|
currentMediaItemProvider.overrideWith((ref) => Stream.value(null)),
|
||||||
|
previewPlayerProvider.overrideWith(() => player),
|
||||||
|
],
|
||||||
|
child: MaterialApp(
|
||||||
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
|
supportedLocales: AppLocalizations.supportedLocales,
|
||||||
|
home: Scaffold(
|
||||||
|
body: _CountingPreviewButton(track: track, onBuild: () => builds++),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
player.emit(
|
||||||
|
PreviewPlayerState(
|
||||||
|
activeUrl: track.previewUrl,
|
||||||
|
status: PreviewStatus.playing,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
expect(find.byIcon(Icons.pause_circle_filled_rounded), findsOneWidget);
|
||||||
|
final playingBuilds = builds;
|
||||||
|
for (var second = 1; second <= 3; second++) {
|
||||||
|
player.emit(
|
||||||
|
PreviewPlayerState(
|
||||||
|
activeUrl: track.previewUrl,
|
||||||
|
status: PreviewStatus.playing,
|
||||||
|
position: Duration(seconds: second),
|
||||||
|
duration: const Duration(seconds: 30),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
}
|
||||||
|
expect(builds, playingBuilds);
|
||||||
|
|
||||||
|
player.emit(
|
||||||
|
PreviewPlayerState(
|
||||||
|
activeUrl: track.previewUrl,
|
||||||
|
status: PreviewStatus.paused,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
expect(find.byIcon(Icons.play_circle_fill_rounded), findsOneWidget);
|
||||||
|
expect(builds, playingBuilds + 1);
|
||||||
|
|
||||||
|
player.emit(
|
||||||
|
const PreviewPlayerState(
|
||||||
|
activeUrl: 'https://example.com/another-preview.mp3',
|
||||||
|
status: PreviewStatus.playing,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
expect(find.byIcon(Icons.play_circle_outline_rounded), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('overflow menu icon is centered in its adjacent hitbox', (
|
testWidgets('overflow menu icon is centered in its adjacent hitbox', (
|
||||||
tester,
|
tester,
|
||||||
) async {
|
) async {
|
||||||
@@ -157,6 +221,25 @@ class _TestSettingsNotifier extends SettingsNotifier {
|
|||||||
AppSettings build() => const AppSettings();
|
AppSettings build() => const AppSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _TestPreviewPlayer extends PreviewPlayerController {
|
||||||
|
@override
|
||||||
|
PreviewPlayerState build() => const PreviewPlayerState();
|
||||||
|
|
||||||
|
void emit(PreviewPlayerState next) => state = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CountingPreviewButton extends PreviewButton {
|
||||||
|
const _CountingPreviewButton({required super.track, required this.onBuild});
|
||||||
|
|
||||||
|
final VoidCallback onBuild;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
onBuild();
|
||||||
|
return super.build(context, ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _TestLibraryCollectionsNotifier extends LibraryCollectionsNotifier {
|
class _TestLibraryCollectionsNotifier extends LibraryCollectionsNotifier {
|
||||||
@override
|
@override
|
||||||
LibraryCollectionsState build() => LibraryCollectionsState(isLoaded: true);
|
LibraryCollectionsState build() => LibraryCollectionsState(isLoaded: true);
|
||||||
|
|||||||
Reference in new issue
Block a user