mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
Fix player position performance issue (#606)
This commit is contained in:
parent
affdb57ecd
commit
3e0834f83c
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -5,6 +5,7 @@
|
|||||||
"danceability",
|
"danceability",
|
||||||
"instrumentalness",
|
"instrumentalness",
|
||||||
"Mpris",
|
"Mpris",
|
||||||
|
"riverpod",
|
||||||
"speechiness",
|
"speechiness",
|
||||||
"Spotube",
|
"Spotube",
|
||||||
"winget"
|
"winget"
|
||||||
|
@ -48,7 +48,6 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
|
|
||||||
final playing =
|
final playing =
|
||||||
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
|
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
|
||||||
final buffering = useStream(audioPlayer.bufferingStream).data ?? true;
|
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
final isDominantColorDark = ThemeData.estimateBrightnessForColor(
|
final isDominantColorDark = ThemeData.estimateBrightnessForColor(
|
||||||
@ -89,215 +88,208 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
iconSize: compact ? 18 : 24,
|
iconSize: compact ? 18 : 24,
|
||||||
);
|
);
|
||||||
|
|
||||||
return RepaintBoundary(
|
return GestureDetector(
|
||||||
child: GestureDetector(
|
behavior: HitTestBehavior.translucent,
|
||||||
behavior: HitTestBehavior.translucent,
|
onTap: () {
|
||||||
onTap: () {
|
if (focusNode.canRequestFocus) {
|
||||||
if (focusNode.canRequestFocus) {
|
focusNode.requestFocus();
|
||||||
focusNode.requestFocus();
|
}
|
||||||
}
|
},
|
||||||
},
|
child: FocusableActionDetector(
|
||||||
child: FocusableActionDetector(
|
focusNode: focusNode,
|
||||||
focusNode: focusNode,
|
shortcuts: shortcuts,
|
||||||
shortcuts: shortcuts,
|
actions: actions,
|
||||||
actions: actions,
|
child: Container(
|
||||||
child: Container(
|
constraints: const BoxConstraints(maxWidth: 600),
|
||||||
constraints: const BoxConstraints(maxWidth: 600),
|
child: Column(
|
||||||
child: Column(
|
children: [
|
||||||
children: [
|
if (!compact)
|
||||||
if (!compact)
|
HookBuilder(
|
||||||
HookBuilder(
|
builder: (context) {
|
||||||
builder: (context) {
|
final (
|
||||||
final (
|
:bufferProgress,
|
||||||
:bufferProgress,
|
:duration,
|
||||||
:duration,
|
:position,
|
||||||
:position,
|
:progressStatic
|
||||||
:progressStatic
|
) = useProgress(ref);
|
||||||
) = useProgress(ref);
|
|
||||||
|
|
||||||
final totalMinutes = PrimitiveUtils.zeroPadNumStr(
|
final totalMinutes = PrimitiveUtils.zeroPadNumStr(
|
||||||
duration.inMinutes.remainder(60),
|
duration.inMinutes.remainder(60),
|
||||||
);
|
);
|
||||||
final totalSeconds = PrimitiveUtils.zeroPadNumStr(
|
final totalSeconds = PrimitiveUtils.zeroPadNumStr(
|
||||||
duration.inSeconds.remainder(60),
|
duration.inSeconds.remainder(60),
|
||||||
);
|
);
|
||||||
final currentMinutes = PrimitiveUtils.zeroPadNumStr(
|
final currentMinutes = PrimitiveUtils.zeroPadNumStr(
|
||||||
position.inMinutes.remainder(60),
|
position.inMinutes.remainder(60),
|
||||||
);
|
);
|
||||||
final currentSeconds = PrimitiveUtils.zeroPadNumStr(
|
final currentSeconds = PrimitiveUtils.zeroPadNumStr(
|
||||||
position.inSeconds.remainder(60),
|
position.inSeconds.remainder(60),
|
||||||
);
|
);
|
||||||
|
|
||||||
final progress = useState<num>(
|
final progress = useState<num>(
|
||||||
useMemoized(() => progressStatic, []),
|
useMemoized(() => progressStatic, []),
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
progress.value = progressStatic;
|
progress.value = progressStatic;
|
||||||
return null;
|
return null;
|
||||||
}, [progressStatic]);
|
}, [progressStatic]);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: context.l10n.slide_to_seek,
|
message: context.l10n.slide_to_seek,
|
||||||
child: Slider(
|
child: Slider(
|
||||||
// cannot divide by zero
|
// cannot divide by zero
|
||||||
// there's an edge case for value being bigger
|
// there's an edge case for value being bigger
|
||||||
// than total duration. Keeping it resolved
|
// than total duration. Keeping it resolved
|
||||||
value: progress.value.toDouble(),
|
value: progress.value.toDouble(),
|
||||||
secondaryTrackValue: bufferProgress,
|
secondaryTrackValue: bufferProgress,
|
||||||
onChanged:
|
onChanged: playlist.isFetching == true
|
||||||
playlist.isFetching == true || buffering
|
? null
|
||||||
? null
|
: (v) {
|
||||||
: (v) {
|
progress.value = v;
|
||||||
progress.value = v;
|
},
|
||||||
},
|
onChangeEnd: (value) async {
|
||||||
onChangeEnd: (value) async {
|
await audioPlayer.seek(
|
||||||
await audioPlayer.seek(
|
Duration(
|
||||||
Duration(
|
seconds: (value * duration.inSeconds).toInt(),
|
||||||
seconds:
|
),
|
||||||
(value * duration.inSeconds).toInt(),
|
);
|
||||||
),
|
},
|
||||||
);
|
activeColor: sliderColor,
|
||||||
},
|
secondaryActiveColor: sliderColor.withOpacity(0.2),
|
||||||
activeColor: sliderColor,
|
inactiveColor: sliderColor.withOpacity(0.15),
|
||||||
secondaryActiveColor:
|
),
|
||||||
sliderColor.withOpacity(0.2),
|
),
|
||||||
inactiveColor: sliderColor.withOpacity(0.15),
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0,
|
||||||
|
),
|
||||||
|
child: DefaultTextStyle(
|
||||||
|
style: theme.textTheme.bodySmall!.copyWith(
|
||||||
|
color: palette?.dominantColor?.bodyTextColor,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text("$currentMinutes:$currentSeconds"),
|
||||||
|
Text("$totalMinutes:$totalSeconds"),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.symmetric(
|
],
|
||||||
horizontal: 8.0,
|
);
|
||||||
),
|
},
|
||||||
child: DefaultTextStyle(
|
|
||||||
style: theme.textTheme.bodySmall!.copyWith(
|
|
||||||
color: palette?.dominantColor?.bodyTextColor,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text("$currentMinutes:$currentSeconds"),
|
|
||||||
Text("$totalMinutes:$totalSeconds"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
StreamBuilder<bool>(
|
|
||||||
stream: audioPlayer.shuffledStream,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
final shuffled = snapshot.data ?? false;
|
|
||||||
return IconButton(
|
|
||||||
tooltip: shuffled
|
|
||||||
? context.l10n.unshuffle_playlist
|
|
||||||
: context.l10n.shuffle_playlist,
|
|
||||||
icon: const Icon(SpotubeIcons.shuffle),
|
|
||||||
style: shuffled ? activeButtonStyle : buttonStyle,
|
|
||||||
onPressed: playlist.isFetching == true || buffering
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
if (shuffled) {
|
|
||||||
audioPlayer.setShuffle(false);
|
|
||||||
} else {
|
|
||||||
audioPlayer.setShuffle(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
IconButton(
|
|
||||||
tooltip: context.l10n.previous_track,
|
|
||||||
icon: const Icon(SpotubeIcons.skipBack),
|
|
||||||
style: buttonStyle,
|
|
||||||
onPressed: playlist.isFetching == true || buffering
|
|
||||||
? null
|
|
||||||
: playlistNotifier.previous,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
tooltip: playing
|
|
||||||
? context.l10n.pause_playback
|
|
||||||
: context.l10n.resume_playback,
|
|
||||||
icon: playlist.isFetching == true
|
|
||||||
? SizedBox(
|
|
||||||
height: 20,
|
|
||||||
width: 20,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
color: accentColor?.titleTextColor ??
|
|
||||||
theme.colorScheme.onPrimary,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Icon(
|
|
||||||
playing ? SpotubeIcons.pause : SpotubeIcons.play,
|
|
||||||
),
|
|
||||||
style: resumePauseStyle,
|
|
||||||
onPressed: playlist.isFetching == true
|
|
||||||
? null
|
|
||||||
: Actions.handler<PlayPauseIntent>(
|
|
||||||
context,
|
|
||||||
PlayPauseIntent(ref),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
tooltip: context.l10n.next_track,
|
|
||||||
icon: const Icon(SpotubeIcons.skipForward),
|
|
||||||
style: buttonStyle,
|
|
||||||
onPressed: playlist.isFetching == true || buffering
|
|
||||||
? null
|
|
||||||
: playlistNotifier.next,
|
|
||||||
),
|
|
||||||
StreamBuilder<PlaybackLoopMode>(
|
|
||||||
stream: audioPlayer.loopModeStream,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
final loopMode =
|
|
||||||
snapshot.data ?? PlaybackLoopMode.none;
|
|
||||||
return IconButton(
|
|
||||||
tooltip: loopMode == PlaybackLoopMode.one
|
|
||||||
? context.l10n.loop_track
|
|
||||||
: loopMode == PlaybackLoopMode.all
|
|
||||||
? context.l10n.repeat_playlist
|
|
||||||
: null,
|
|
||||||
icon: Icon(
|
|
||||||
loopMode == PlaybackLoopMode.one
|
|
||||||
? SpotubeIcons.repeatOne
|
|
||||||
: SpotubeIcons.repeat,
|
|
||||||
),
|
|
||||||
style: loopMode == PlaybackLoopMode.one ||
|
|
||||||
loopMode == PlaybackLoopMode.all
|
|
||||||
? activeButtonStyle
|
|
||||||
: buttonStyle,
|
|
||||||
onPressed: playlist.isFetching == true || buffering
|
|
||||||
? null
|
|
||||||
: () async {
|
|
||||||
switch (await audioPlayer.loopMode) {
|
|
||||||
case PlaybackLoopMode.all:
|
|
||||||
audioPlayer
|
|
||||||
.setLoopMode(PlaybackLoopMode.one);
|
|
||||||
break;
|
|
||||||
case PlaybackLoopMode.one:
|
|
||||||
audioPlayer
|
|
||||||
.setLoopMode(PlaybackLoopMode.none);
|
|
||||||
break;
|
|
||||||
case PlaybackLoopMode.none:
|
|
||||||
audioPlayer
|
|
||||||
.setLoopMode(PlaybackLoopMode.all);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 5)
|
Row(
|
||||||
],
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
),
|
children: [
|
||||||
|
StreamBuilder<bool>(
|
||||||
|
stream: audioPlayer.shuffledStream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final shuffled = snapshot.data ?? false;
|
||||||
|
return IconButton(
|
||||||
|
tooltip: shuffled
|
||||||
|
? context.l10n.unshuffle_playlist
|
||||||
|
: context.l10n.shuffle_playlist,
|
||||||
|
icon: const Icon(SpotubeIcons.shuffle),
|
||||||
|
style: shuffled ? activeButtonStyle : buttonStyle,
|
||||||
|
onPressed: playlist.isFetching == true
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
if (shuffled) {
|
||||||
|
audioPlayer.setShuffle(false);
|
||||||
|
} else {
|
||||||
|
audioPlayer.setShuffle(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
IconButton(
|
||||||
|
tooltip: context.l10n.previous_track,
|
||||||
|
icon: const Icon(SpotubeIcons.skipBack),
|
||||||
|
style: buttonStyle,
|
||||||
|
onPressed: playlist.isFetching == true
|
||||||
|
? null
|
||||||
|
: playlistNotifier.previous,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
tooltip: playing
|
||||||
|
? context.l10n.pause_playback
|
||||||
|
: context.l10n.resume_playback,
|
||||||
|
icon: playlist.isFetching == true
|
||||||
|
? SizedBox(
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: accentColor?.titleTextColor ??
|
||||||
|
theme.colorScheme.onPrimary,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Icon(
|
||||||
|
playing ? SpotubeIcons.pause : SpotubeIcons.play,
|
||||||
|
),
|
||||||
|
style: resumePauseStyle,
|
||||||
|
onPressed: playlist.isFetching == true
|
||||||
|
? null
|
||||||
|
: Actions.handler<PlayPauseIntent>(
|
||||||
|
context,
|
||||||
|
PlayPauseIntent(ref),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
tooltip: context.l10n.next_track,
|
||||||
|
icon: const Icon(SpotubeIcons.skipForward),
|
||||||
|
style: buttonStyle,
|
||||||
|
onPressed: playlist.isFetching == true
|
||||||
|
? null
|
||||||
|
: playlistNotifier.next,
|
||||||
|
),
|
||||||
|
StreamBuilder<PlaybackLoopMode>(
|
||||||
|
stream: audioPlayer.loopModeStream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final loopMode = snapshot.data ?? PlaybackLoopMode.none;
|
||||||
|
return IconButton(
|
||||||
|
tooltip: loopMode == PlaybackLoopMode.one
|
||||||
|
? context.l10n.loop_track
|
||||||
|
: loopMode == PlaybackLoopMode.all
|
||||||
|
? context.l10n.repeat_playlist
|
||||||
|
: null,
|
||||||
|
icon: Icon(
|
||||||
|
loopMode == PlaybackLoopMode.one
|
||||||
|
? SpotubeIcons.repeatOne
|
||||||
|
: SpotubeIcons.repeat,
|
||||||
|
),
|
||||||
|
style: loopMode == PlaybackLoopMode.one ||
|
||||||
|
loopMode == PlaybackLoopMode.all
|
||||||
|
? activeButtonStyle
|
||||||
|
: buttonStyle,
|
||||||
|
onPressed: playlist.isFetching == true
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
switch (await audioPlayer.loopMode) {
|
||||||
|
case PlaybackLoopMode.all:
|
||||||
|
audioPlayer
|
||||||
|
.setLoopMode(PlaybackLoopMode.one);
|
||||||
|
break;
|
||||||
|
case PlaybackLoopMode.one:
|
||||||
|
audioPlayer
|
||||||
|
.setLoopMode(PlaybackLoopMode.none);
|
||||||
|
break;
|
||||||
|
case PlaybackLoopMode.none:
|
||||||
|
audioPlayer
|
||||||
|
.setLoopMode(PlaybackLoopMode.all);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 5)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -62,99 +62,95 @@ class PlayerOverlay extends HookConsumerWidget {
|
|||||||
child: AnimatedOpacity(
|
child: AnimatedOpacity(
|
||||||
duration: const Duration(milliseconds: 250),
|
duration: const Duration(milliseconds: 250),
|
||||||
opacity: canShow ? 1 : 0,
|
opacity: canShow ? 1 : 0,
|
||||||
child: RepaintBoundary(
|
child: Material(
|
||||||
child: Material(
|
type: MaterialType.transparency,
|
||||||
type: MaterialType.transparency,
|
child: Column(
|
||||||
child: Column(
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisSize: MainAxisSize.min,
|
children: [
|
||||||
children: [
|
HookBuilder(
|
||||||
HookBuilder(
|
builder: (context) {
|
||||||
builder: (context) {
|
final progress = useProgress(ref);
|
||||||
final progress = useProgress(ref);
|
// animated
|
||||||
// animated
|
return TweenAnimationBuilder<double>(
|
||||||
return TweenAnimationBuilder<double>(
|
duration: const Duration(milliseconds: 250),
|
||||||
duration: const Duration(milliseconds: 250),
|
tween: Tween<double>(
|
||||||
tween: Tween<double>(
|
begin: 0,
|
||||||
begin: 0,
|
end: progress.progressStatic,
|
||||||
end: progress.progressStatic,
|
),
|
||||||
),
|
builder: (context, value, child) {
|
||||||
builder: (context, value, child) {
|
return LinearProgressIndicator(
|
||||||
return LinearProgressIndicator(
|
value: value,
|
||||||
value: value,
|
minHeight: 2,
|
||||||
minHeight: 2,
|
backgroundColor: Colors.transparent,
|
||||||
backgroundColor: Colors.transparent,
|
valueColor: AlwaysStoppedAnimation(
|
||||||
valueColor: AlwaysStoppedAnimation(
|
theme.colorScheme.primary,
|
||||||
theme.colorScheme.primary,
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
Expanded(
|
||||||
Expanded(
|
child: Row(
|
||||||
child: Row(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
children: [
|
||||||
children: [
|
Expanded(
|
||||||
Expanded(
|
child: MouseRegion(
|
||||||
child: MouseRegion(
|
cursor: SystemMouseCursors.click,
|
||||||
cursor: SystemMouseCursors.click,
|
child: GestureDetector(
|
||||||
child: GestureDetector(
|
onTap: () =>
|
||||||
onTap: () =>
|
GoRouter.of(context).push("/player"),
|
||||||
GoRouter.of(context).push("/player"),
|
child: PlayerTrackDetails(
|
||||||
child: PlayerTrackDetails(
|
albumArt: albumArt,
|
||||||
albumArt: albumArt,
|
color: textColor,
|
||||||
color: textColor,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
),
|
||||||
children: [
|
Row(
|
||||||
IconButton(
|
children: [
|
||||||
icon: Icon(
|
IconButton(
|
||||||
SpotubeIcons.skipBack,
|
icon: Icon(
|
||||||
color: textColor,
|
SpotubeIcons.skipBack,
|
||||||
),
|
color: textColor,
|
||||||
onPressed: playlistNotifier.previous,
|
|
||||||
),
|
),
|
||||||
Consumer(
|
onPressed: playlistNotifier.previous,
|
||||||
builder: (context, ref, _) {
|
),
|
||||||
return IconButton(
|
Consumer(
|
||||||
icon: playlist.isFetching
|
builder: (context, ref, _) {
|
||||||
? const SizedBox(
|
return IconButton(
|
||||||
height: 20,
|
icon: playlist.isFetching
|
||||||
width: 20,
|
? const SizedBox(
|
||||||
child:
|
height: 20,
|
||||||
CircularProgressIndicator(),
|
width: 20,
|
||||||
)
|
child: CircularProgressIndicator(),
|
||||||
: Icon(
|
)
|
||||||
playing
|
: Icon(
|
||||||
? SpotubeIcons.pause
|
playing
|
||||||
: SpotubeIcons.play,
|
? SpotubeIcons.pause
|
||||||
color: textColor,
|
: SpotubeIcons.play,
|
||||||
),
|
color: textColor,
|
||||||
onPressed:
|
),
|
||||||
Actions.handler<PlayPauseIntent>(
|
onPressed: Actions.handler<PlayPauseIntent>(
|
||||||
context,
|
context,
|
||||||
PlayPauseIntent(ref),
|
PlayPauseIntent(ref),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
SpotubeIcons.skipForward,
|
||||||
|
color: textColor,
|
||||||
),
|
),
|
||||||
IconButton(
|
onPressed: playlistNotifier.next,
|
||||||
icon: Icon(
|
),
|
||||||
SpotubeIcons.skipForward,
|
],
|
||||||
color: textColor,
|
),
|
||||||
),
|
],
|
||||||
onPressed: playlistNotifier.next,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
|
||||||
import 'package:spotube/services/audio_player/audio_player.dart';
|
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||||
|
|
||||||
({
|
({
|
||||||
@ -9,21 +8,29 @@ import 'package:spotube/services/audio_player/audio_player.dart';
|
|||||||
Duration duration,
|
Duration duration,
|
||||||
double bufferProgress
|
double bufferProgress
|
||||||
}) useProgress(WidgetRef ref) {
|
}) useProgress(WidgetRef ref) {
|
||||||
final playlist = ref.watch(ProxyPlaylistNotifier.provider);
|
|
||||||
|
|
||||||
final bufferProgress =
|
final bufferProgress =
|
||||||
useStream(audioPlayer.bufferedPositionStream).data?.inSeconds ?? 0;
|
useStream(audioPlayer.bufferedPositionStream).data?.inSeconds ?? 0;
|
||||||
|
|
||||||
|
Duration audioPlayerDuration = Duration.zero;
|
||||||
|
Duration audioPlayerPosition = Duration.zero;
|
||||||
|
|
||||||
// Duration future is needed for getting the duration of the song
|
// Duration future is needed for getting the duration of the song
|
||||||
// as stream can be null when no event occurs (Mostly needed for android)
|
// as stream can be null when no event occurs (Mostly needed for android)
|
||||||
final durationFuture = useFuture(audioPlayer.duration);
|
audioPlayer.duration.then((value) {
|
||||||
final duration = useStream(audioPlayer.durationStream).data ??
|
if (value != null) {
|
||||||
durationFuture.data ??
|
audioPlayerDuration = value;
|
||||||
Duration.zero;
|
}
|
||||||
|
});
|
||||||
|
|
||||||
final positionFuture = useFuture(audioPlayer.position);
|
audioPlayer.position.then((value) {
|
||||||
final position = useState<Duration>(positionFuture.data ?? Duration.zero);
|
if (value != null) {
|
||||||
|
audioPlayerPosition = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final position = useState<Duration>(audioPlayerPosition);
|
||||||
|
final duration =
|
||||||
|
useStream(audioPlayer.durationStream).data ?? audioPlayerDuration;
|
||||||
final sliderMax = duration.inSeconds;
|
final sliderMax = duration.inSeconds;
|
||||||
final sliderValue = position.value.inSeconds;
|
final sliderValue = position.value.inSeconds;
|
||||||
|
|
||||||
@ -38,7 +45,7 @@ import 'package:spotube/services/audio_player/audio_player.dart';
|
|||||||
lastPosition = event;
|
lastPosition = event;
|
||||||
position.value = event;
|
position.value = event;
|
||||||
}).cancel;
|
}).cancel;
|
||||||
}, []);
|
}, [audioPlayerPosition, audioPlayerDuration]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
progressStatic:
|
progressStatic:
|
||||||
|
Loading…
Reference in New Issue
Block a user