♻️ Improve progress display
This commit is contained in:
parent
2134500089
commit
249c8fbf80
@ -11,6 +11,10 @@ import 'package:spotify/spotify.dart' hide Playlist;
|
||||
import 'package:rhythm_box/services/audio_player/audio_player.dart';
|
||||
|
||||
class AudioPlayerProvider extends GetxController {
|
||||
Rx<Duration> durationTotal = Rx(Duration.zero);
|
||||
Rx<Duration> durationCurrent = Rx(Duration.zero);
|
||||
Rx<Duration> durationBuffered = Rx(Duration.zero);
|
||||
|
||||
RxBool isPlaying = false.obs;
|
||||
|
||||
Rx<AudioPlayerState> state = Rx(AudioPlayerState(
|
||||
@ -54,6 +58,11 @@ class AudioPlayerProvider extends GetxController {
|
||||
state.value = state.value.copyWith(playlist: playlist);
|
||||
await _updatePlaylist(playlist);
|
||||
}),
|
||||
audioPlayer.durationStream.listen((value) => durationTotal.value = value),
|
||||
audioPlayer.positionStream
|
||||
.listen((value) => durationCurrent.value = value),
|
||||
audioPlayer.bufferedPositionStream
|
||||
.listen((value) => durationBuffered.value = value),
|
||||
];
|
||||
|
||||
_readSavedState();
|
||||
|
@ -39,13 +39,6 @@ class _PlayerScreenState extends State<PlayerScreen> {
|
||||
bool get _isFetchingActiveTrack => _query.isQueryingTrackInfo.value;
|
||||
PlaylistMode get _loopMode => _playback.state.value.loopMode;
|
||||
|
||||
double _bufferProgress = 0;
|
||||
|
||||
Duration _durationCurrent = Duration.zero;
|
||||
Duration _durationTotal = Duration.zero;
|
||||
|
||||
List<StreamSubscription>? _subscriptions;
|
||||
|
||||
Future<void> _togglePlayState() async {
|
||||
if (!audioPlayer.isPlaying) {
|
||||
await audioPlayer.resume();
|
||||
@ -57,32 +50,6 @@ class _PlayerScreenState extends State<PlayerScreen> {
|
||||
|
||||
double? _draggingValue;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_durationCurrent = audioPlayer.position;
|
||||
_durationTotal = audioPlayer.duration;
|
||||
_bufferProgress = audioPlayer.bufferedPosition.inMilliseconds.toDouble();
|
||||
_subscriptions = [
|
||||
audioPlayer.durationStream
|
||||
.listen((dur) => setState(() => _durationTotal = dur)),
|
||||
audioPlayer.positionStream
|
||||
.listen((dur) => setState(() => _durationCurrent = dur)),
|
||||
audioPlayer.bufferedPositionStream.listen((dur) =>
|
||||
setState(() => _bufferProgress = dur.inMilliseconds.toDouble())),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_subscriptions != null) {
|
||||
for (final subscription in _subscriptions!) {
|
||||
subscription.cancel();
|
||||
}
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final size = MediaQuery.of(context).size;
|
||||
@ -134,7 +101,8 @@ class _PlayerScreenState extends State<PlayerScreen> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const Gap(24),
|
||||
Column(
|
||||
Obx(
|
||||
() => Column(
|
||||
children: [
|
||||
SliderTheme(
|
||||
data: SliderThemeData(
|
||||
@ -146,20 +114,25 @@ class _PlayerScreenState extends State<PlayerScreen> {
|
||||
overlayShape: SliderComponentShape.noOverlay,
|
||||
),
|
||||
child: Slider(
|
||||
secondaryTrackValue: _bufferProgress.abs(),
|
||||
secondaryTrackValue: _playback
|
||||
.durationBuffered.value.inMilliseconds
|
||||
.abs()
|
||||
.toDouble(),
|
||||
value: _draggingValue?.abs() ??
|
||||
_durationCurrent.inMilliseconds.toDouble().abs(),
|
||||
_playback.durationCurrent.value.inMilliseconds
|
||||
.toDouble()
|
||||
.abs(),
|
||||
min: 0,
|
||||
max: max(
|
||||
_durationTotal.inMilliseconds.abs(),
|
||||
_durationTotal.inMilliseconds.abs(),
|
||||
_playback.durationCurrent.value.inMilliseconds.abs(),
|
||||
_playback.durationTotal.value.inMilliseconds.abs(),
|
||||
).toDouble(),
|
||||
onChanged: (value) {
|
||||
setState(() => _draggingValue = value);
|
||||
},
|
||||
onChangeEnd: (value) {
|
||||
print('Seek to $value ms');
|
||||
audioPlayer.seek(Duration(milliseconds: value.toInt()));
|
||||
audioPlayer
|
||||
.seek(Duration(milliseconds: value.toInt()));
|
||||
},
|
||||
),
|
||||
),
|
||||
@ -167,17 +140,19 @@ class _PlayerScreenState extends State<PlayerScreen> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
_durationCurrent.toHumanReadableString(),
|
||||
_playback.durationCurrent.value
|
||||
.toHumanReadableString(),
|
||||
style: GoogleFonts.robotoMono(fontSize: 12),
|
||||
),
|
||||
Text(
|
||||
_durationTotal.toHumanReadableString(),
|
||||
_playback.durationTotal.value.toHumanReadableString(),
|
||||
style: GoogleFonts.robotoMono(fontSize: 12),
|
||||
),
|
||||
],
|
||||
).paddingSymmetric(horizontal: 8, vertical: 4),
|
||||
],
|
||||
).paddingSymmetric(horizontal: 24),
|
||||
),
|
||||
const Gap(24),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
@ -107,7 +107,7 @@ class _SyncedLyricsState extends State<SyncedLyrics> {
|
||||
)
|
||||
: Padding(
|
||||
padding: idx == _lyric!.lyrics.length - 1
|
||||
? const EdgeInsets.all(8.0).copyWith(bottom: 100)
|
||||
? const EdgeInsets.all(8.0).copyWith(bottom: 80)
|
||||
: const EdgeInsets.all(8.0),
|
||||
child: AnimatedDefaultTextStyle(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
@ -141,8 +141,9 @@ class _SyncedLyricsState extends State<SyncedLyrics> {
|
||||
),
|
||||
).animate(target: isActive ? 1 : 0).scale(
|
||||
duration: 300.ms,
|
||||
begin: const Offset(0.9, 0.9),
|
||||
end: const Offset(1.3, 1.3),
|
||||
begin: const Offset(1, 1),
|
||||
end: const Offset(1.25, 1.25),
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
}).paddingSymmetric(horizontal: 12),
|
||||
),
|
||||
|
@ -44,9 +44,6 @@ class _BottomPlayerState extends State<BottomPlayer>
|
||||
bool get _isPlaying => _playback.isPlaying.value;
|
||||
bool get _isFetchingActiveTrack => _query.isQueryingTrackInfo.value;
|
||||
|
||||
Duration _durationCurrent = Duration.zero;
|
||||
Duration _durationTotal = Duration.zero;
|
||||
|
||||
List<StreamSubscription>? _subscriptions;
|
||||
|
||||
Future<void> _togglePlayState() async {
|
||||
@ -63,10 +60,6 @@ class _BottomPlayerState extends State<BottomPlayer>
|
||||
void initState() {
|
||||
super.initState();
|
||||
_subscriptions = [
|
||||
audioPlayer.durationStream
|
||||
.listen((dur) => setState(() => _durationTotal = dur)),
|
||||
audioPlayer.positionStream
|
||||
.listen((dur) => setState(() => _durationCurrent = dur)),
|
||||
_playback.state.listen((state) {
|
||||
if (state.playlist.medias.isNotEmpty && !_isLifted) {
|
||||
_animationController.animateTo(1);
|
||||
@ -109,12 +102,12 @@ class _BottomPlayerState extends State<BottomPlayer>
|
||||
behavior: HitTestBehavior.translucent,
|
||||
child: Column(
|
||||
children: [
|
||||
if (_durationCurrent != Duration.zero)
|
||||
if (_playback.durationCurrent.value != Duration.zero)
|
||||
TweenAnimationBuilder<double>(
|
||||
tween: Tween(
|
||||
begin: 0,
|
||||
end: _durationCurrent.inMilliseconds /
|
||||
max(_durationTotal.inMilliseconds, 1),
|
||||
end: _playback.durationCurrent.value.inMilliseconds /
|
||||
max(_playback.durationTotal.value.inMilliseconds, 1),
|
||||
),
|
||||
duration: const Duration(milliseconds: 1000),
|
||||
builder: (context, value, _) => LinearProgressIndicator(
|
||||
|
Loading…
Reference in New Issue
Block a user