mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-01 13:49:36 +02:00
perf(player): commit seek gestures once after scrubbing
This commit is contained in:
1 parent
a064e96c37
commit
fd777c34d9
3 files changed
+175
-15
No files matched your search
@@ -22,6 +22,7 @@ import 'package:spotiflac_android/utils/synced_lyrics_scroll.dart';
|
||||
import 'package:spotiflac_android/widgets/app_bottom_sheet.dart';
|
||||
import 'package:spotiflac_android/widgets/audio_quality_badges.dart';
|
||||
import 'package:spotiflac_android/widgets/player_artwork.dart';
|
||||
import 'package:spotiflac_android/widgets/playback_seek_slider.dart';
|
||||
import 'package:spotiflac_android/widgets/settings_group.dart';
|
||||
|
||||
final _log = AppLogger('NowPlaying');
|
||||
@@ -661,6 +662,7 @@ class _NowPlayingScreenState extends ConsumerState<NowPlayingScreen> {
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_PlaybackControls(
|
||||
key: ValueKey(mediaItem.id),
|
||||
duration: mediaItem.duration ?? Duration.zero,
|
||||
controller: controller,
|
||||
colorScheme: colorScheme,
|
||||
@@ -1195,6 +1197,7 @@ class _PlaybackControls extends ConsumerWidget {
|
||||
final String? qualityLabel;
|
||||
|
||||
const _PlaybackControls({
|
||||
super.key,
|
||||
required this.duration,
|
||||
required this.controller,
|
||||
required this.colorScheme,
|
||||
@@ -1216,13 +1219,6 @@ class _PlaybackControls extends ConsumerWidget {
|
||||
(s) => s.value?.repeatMode ?? AudioServiceRepeatMode.none,
|
||||
),
|
||||
);
|
||||
final maxMs = duration.inMilliseconds > 0
|
||||
? duration.inMilliseconds.toDouble()
|
||||
: 1.0;
|
||||
final posMs = position.inMilliseconds
|
||||
.clamp(0, duration.inMilliseconds > 0 ? duration.inMilliseconds : 0)
|
||||
.toDouble();
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
@@ -1246,14 +1242,10 @@ class _PlaybackControls extends ConsumerWidget {
|
||||
overlayRadius: 24,
|
||||
),
|
||||
),
|
||||
child: Slider(
|
||||
value: posMs.clamp(0, maxMs),
|
||||
max: maxMs,
|
||||
onChanged: duration.inMilliseconds > 0
|
||||
? (value) => controller.seek(
|
||||
Duration(milliseconds: value.round()),
|
||||
)
|
||||
: null,
|
||||
child: PlaybackSeekSlider(
|
||||
position: position,
|
||||
duration: duration,
|
||||
onSeek: controller.seek,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Previews scrubbing locally and seeks once when the gesture ends.
|
||||
class PlaybackSeekSlider extends StatefulWidget {
|
||||
final Duration position;
|
||||
final Duration duration;
|
||||
final Future<void> Function(Duration) onSeek;
|
||||
|
||||
const PlaybackSeekSlider({
|
||||
super.key,
|
||||
required this.position,
|
||||
required this.duration,
|
||||
required this.onSeek,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PlaybackSeekSlider> createState() => _PlaybackSeekSliderState();
|
||||
}
|
||||
|
||||
class _PlaybackSeekSliderState extends State<PlaybackSeekSlider> {
|
||||
double? _previewMs;
|
||||
int _gestureGeneration = 0;
|
||||
|
||||
Future<void> _commit(double value) async {
|
||||
final generation = _gestureGeneration;
|
||||
try {
|
||||
await widget.onSeek(Duration(milliseconds: value.round()));
|
||||
} finally {
|
||||
if (mounted && generation == _gestureGeneration) {
|
||||
setState(() => _previewMs = null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final durationMs = widget.duration.inMilliseconds;
|
||||
final enabled = durationMs > 0;
|
||||
final maxMs = enabled ? durationMs.toDouble() : 1.0;
|
||||
return Slider(
|
||||
value: enabled
|
||||
? (_previewMs ?? widget.position.inMilliseconds.toDouble()).clamp(
|
||||
0,
|
||||
maxMs,
|
||||
)
|
||||
: 0,
|
||||
max: maxMs,
|
||||
onChangeStart: enabled ? (_) => _gestureGeneration++ : null,
|
||||
onChanged: enabled ? (value) => setState(() => _previewMs = value) : null,
|
||||
onChangeEnd: enabled ? _commit : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user