diff --git a/lib/providers.dart b/lib/providers.dart index 8d8f1de..e1ee9c9 100644 --- a/lib/providers.dart +++ b/lib/providers.dart @@ -65,5 +65,5 @@ final annilProvider = ChangeNotifierProvider((final ref) => AnnilService(ref)); final annivProvider = ChangeNotifierProvider((final ref) => AnnivService(ref)); final playbackProvider = ChangeNotifierProvider((final ref) => PlaybackService(ref)); -final playingProvider = ChangeNotifierProvider( - (final ref) => ref.watch(playbackProvider.select((final p) => p.playing))); +final playingProvider = + ChangeNotifierProvider((final ref) => ref.read(playbackProvider).playing); diff --git a/lib/services/playback/playback_playing.dart b/lib/services/playback/playback_playing.dart index 9ffaf81..b83f183 100644 --- a/lib/services/playback/playback_playing.dart +++ b/lib/services/playback/playback_playing.dart @@ -19,7 +19,7 @@ class PlayingTrack extends ChangeNotifier { late Debouncer progressNotifyDebouncer; PlayingTrack(this.ref) { progressNotifyDebouncer = Debouncer( - milliseconds: 300, + milliseconds: 1000, action: notifyListeners, ); } diff --git a/lib/ui/bottom_player/bottom_player_mobile.dart b/lib/ui/bottom_player/bottom_player_mobile.dart index ff86448..bafeb34 100644 --- a/lib/ui/bottom_player/bottom_player_mobile.dart +++ b/lib/ui/bottom_player/bottom_player_mobile.dart @@ -4,6 +4,7 @@ import 'package:annix/ui/widgets/cover.dart'; import 'package:annix/ui/widgets/buttons/play_pause_button.dart'; import 'package:annix/ui/widgets/swiper.dart'; import 'package:annix/utils/context_extension.dart'; +import 'package:audio_video_progress_bar/audio_video_progress_bar.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -30,7 +31,7 @@ class MobileBottomPlayer extends StatelessWidget { ), height: height, child: Stack( - alignment: Alignment.bottomCenter, + alignment: Alignment.bottomLeft, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -46,17 +47,31 @@ class MobileBottomPlayer extends StatelessWidget { const FavoriteButton(), Padding( padding: const EdgeInsets.only(right: 8.0), - child: PlayPauseButton.small(), + child: RepaintBoundary(child: PlayPauseButton.small()), ), ], ), - Consumer(builder: (context, ref, child) { - final playing = ref.watch(playingProvider); - return LinearProgressIndicator( - value: playing.progress, - minHeight: 2, - ); - }), + LayoutBuilder( + builder: (context, constraints) { + return RepaintBoundary( + child: Consumer( + builder: (context, ref, child) { + final playing = ref.watch(playingProvider); + return ProgressBar( + progress: playing.position, + total: playing.duration == Duration.zero + ? playing.position + : playing.duration, + timeLabelLocation: TimeLabelLocation.none, + thumbCanPaintOutsideBar: false, + thumbRadius: 0, + barHeight: 2, + ); + }, + ), + ); + }, + ), ], ), ); diff --git a/lib/ui/layout/layout.dart b/lib/ui/layout/layout.dart index d6b1aa8..0453649 100644 --- a/lib/ui/layout/layout.dart +++ b/lib/ui/layout/layout.dart @@ -239,18 +239,23 @@ class AnnixLayout extends HookConsumerWidget { config: { Breakpoints.small: SlotLayout.from( key: const Key('Bottom Navigation Small'), - builder: (context) => SizedBox( - height: currentHeight, - child: AnimatedOpacity( - duration: const Duration(milliseconds: 200), - opacity: opacity, - child: standardBottomNavigationBar( - currentIndex: currentIndex, - onDestinationSelected: onDestinationSelected, - destinations: destinations, - ), - ), - ), + builder: (context) { + final bar = standardBottomNavigationBar( + currentIndex: currentIndex, + onDestinationSelected: onDestinationSelected, + destinations: destinations, + ); + return SizedBox( + height: currentHeight, + child: opacity == 1 + ? bar + : AnimatedOpacity( + duration: const Duration(milliseconds: 200), + opacity: opacity, + child: bar, + ), + ); + }, ), }, ), diff --git a/lib/ui/widgets/slide_up.dart b/lib/ui/widgets/slide_up.dart index 7853b35..788a7d5 100644 --- a/lib/ui/widgets/slide_up.dart +++ b/lib/ui/widgets/slide_up.dart @@ -174,19 +174,21 @@ class _SlidingUpPanelState extends ConsumerState minHeight: widget.maxHeight, maxHeight: widget.maxHeight, alignment: Alignment.topCenter, - child: FadeTransition( - opacity: TweenSequence([ - TweenSequenceItem( - tween: Tween(begin: 0.0, end: 1.0), - weight: 10, - ), - TweenSequenceItem( - tween: Tween(begin: 1.0, end: 1.0), - weight: 90, - ), - ]).animate(_ac), - child: widget.panel, - ), + child: _ac.value == 0 + ? Container() + : FadeTransition( + opacity: TweenSequence([ + TweenSequenceItem( + tween: Tween(begin: 0.0, end: 1.0), + weight: 10, + ), + TweenSequenceItem( + tween: Tween(begin: 1.0, end: 1.0), + weight: 90, + ), + ]).animate(_ac), + child: widget.panel, + ), ), // collapsed panel diff --git a/lib/utils/debounce.dart b/lib/utils/debounce.dart index a7457b3..e3a034a 100644 --- a/lib/utils/debounce.dart +++ b/lib/utils/debounce.dart @@ -11,11 +11,13 @@ class Debouncer { Debouncer({required this.milliseconds, required this.action}); run() { - if (_timer != null && _timer!.isActive) { + if (_timer?.isActive == true) { return; } - _timer = Timer(Duration(milliseconds: milliseconds), action); - _timer = null; + _timer = Timer(Duration(milliseconds: milliseconds), () { + _timer = null; + action(); + }); } }