diff --git a/lib/bloc/podcast/audio_bloc.dart b/lib/bloc/podcast/audio_bloc.dart index 44c48deb..791b2cc3 100644 --- a/lib/bloc/podcast/audio_bloc.dart +++ b/lib/bloc/podcast/audio_bloc.dart @@ -89,7 +89,7 @@ class AudioBloc extends Bloc { await audioPlayerService.pause(); break; case TransitionState.fastforward: - await audioPlayerService.fastforward(); + await audioPlayerService.fastForward(); break; case TransitionState.rewind: await audioPlayerService.rewind(); diff --git a/lib/services/audio/audio_player_service.dart b/lib/services/audio/audio_player_service.dart index bb5df387..79b1f940 100644 --- a/lib/services/audio/audio_player_service.dart +++ b/lib/services/audio/audio_player_service.dart @@ -51,7 +51,7 @@ abstract class AudioPlayerService { Future rewind(); /// Fast forward the current episode by pre-set number of seconds. - Future fastforward(); + Future fastForward(); /// Seek to the specified position within the current episode. Future seek({@required int position}); diff --git a/lib/services/audio/mobile_audio_player_service.dart b/lib/services/audio/mobile_audio_player_service.dart index 609371b2..fb6a92d7 100644 --- a/lib/services/audio/mobile_audio_player_service.dart +++ b/lib/services/audio/mobile_audio_player_service.dart @@ -179,7 +179,7 @@ class MobileAudioPlayerService extends AudioPlayerService { } @override - Future fastforward() => AudioService.fastForward(); + Future fastForward() => AudioService.fastForward(); @override Future rewind() => AudioService.rewind(); @@ -490,22 +490,21 @@ class MobileAudioPlayerService extends AudioPlayerService { } } + /// Calculate our current chapter based on playback position, and if it's different to + /// the currently stored chapter - update. void _updateChapter(int seconds, int duration) { if (_episode == null) { log.fine('Warning. Attempting to update chapter information on a null _episode'); } else if (_episode.hasChapters && _episode.chaptersAreLoaded) { final chapters = _episode.chapters; - // What is our current chapter? - _episode.currentChapter = null; - - for (var x = 0; x < _episode.chapters.length; x++) { - final startTime = chapters[x].startTime; - final endTime = x == (_episode.chapters.length - 1) ? duration : chapters[x + 1].startTime; + for (var chapterPtr = 0; chapterPtr < _episode.chapters.length; chapterPtr++) { + final startTime = chapters[chapterPtr].startTime; + final endTime = chapterPtr == (_episode.chapters.length - 1) ? duration : chapters[chapterPtr + 1].startTime; if (seconds >= startTime && seconds < endTime) { - if (chapters[x] != _episode.currentChapter) { - _episode.currentChapter = chapters[x]; + if (chapters[chapterPtr] != _episode.currentChapter) { + _episode.currentChapter = chapters[chapterPtr]; _episodeEvent.sink.add(_episode); break; } diff --git a/lib/ui/podcast/now_playing.dart b/lib/ui/podcast/now_playing.dart index 53499b39..8ad9583e 100644 --- a/lib/ui/podcast/now_playing.dart +++ b/lib/ui/podcast/now_playing.dart @@ -46,9 +46,8 @@ class _NowPlayingState extends State with WidgetsBindingObserver { var popped = false; // If the episode finishes we can close. - playingStateSubscription = audioBloc.playingState - .where((state) => state == AudioState.stopped) - .listen((playingState) async { + playingStateSubscription = + audioBloc.playingState.where((state) => state == AudioState.stopped).listen((playingState) async { // Prevent responding to multiple stop events after we've popped and lost context. if (!popped) { Navigator.pop(context); @@ -215,8 +214,7 @@ class EpisodeTabBarView extends StatelessWidget { description: episode.description, textGroup: textGroup, ), - NowPlayingDetails( - title: episode.title, description: episode.description), + NowPlayingDetails(title: episode.title, description: episode.description), ], ); } @@ -261,8 +259,7 @@ class EpisodeTabBarViewWithChapters extends StatelessWidget { textGroup: textGroup, ); }), - NowPlayingDetails( - title: episode.title, description: episode.description), + NowPlayingDetails(title: episode.title, description: episode.description), ], ); } @@ -283,70 +280,63 @@ class NowPlayingHeader extends StatelessWidget { @override Widget build(BuildContext context) { - final audioBloc = Provider.of(context, listen: false); final placeholderBuilder = PlaceholderBuilder.of(context); - return StreamBuilder( - stream: audioBloc.nowPlaying, - builder: (context, statesnap) { - return Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 7, - child: PodcastImage( - key: Key('nowplaying$imageUrl'), - url: imageUrl, - height: 360, - width: 360, - fit: BoxFit.contain, - placeholder: placeholderBuilder != null - ? placeholderBuilder?.builder()(context) - : DelayedCircularProgressIndicator(), - errorPlaceholder: placeholderBuilder != null - ? placeholderBuilder?.errorBuilder()(context) - : Image( - image: AssetImage( - 'assets/images/anytime-placeholder-logo.png')), - ), - ), - Expanded( - flex: 3, - child: Padding( - padding: const EdgeInsets.only( - top: 16.0, - bottom: 0.0, - left: 16.0, - right: 16.0, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - flex: 3, - child: AutoSizeText( - title ?? '', - group: textGroup, - textAlign: TextAlign.center, - minFontSize: 12.0, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 20.0, - ), - maxLines: 4, - ), - ), - ], + return Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 7, + child: PodcastImage( + key: Key('nowplaying$imageUrl'), + url: imageUrl, + height: 360, + width: 360, + fit: BoxFit.contain, + placeholder: placeholderBuilder != null + ? placeholderBuilder?.builder()(context) + : DelayedCircularProgressIndicator(), + errorPlaceholder: placeholderBuilder != null + ? placeholderBuilder?.errorBuilder()(context) + : Image(image: AssetImage('assets/images/anytime-placeholder-logo.png')), + ), + ), + Expanded( + flex: 3, + child: Padding( + padding: const EdgeInsets.only( + top: 16.0, + bottom: 0.0, + left: 16.0, + right: 16.0, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 3, + child: AutoSizeText( + title ?? '', + group: textGroup, + textAlign: TextAlign.center, + minFontSize: 12.0, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20.0, + ), + maxLines: 4, ), ), - ), - ], + ], + ), ), - ); - }); + ), + ], + ), + ); } } @@ -367,113 +357,103 @@ class NowPlayingHeaderWithChapters extends StatelessWidget { @override Widget build(BuildContext context) { - final audioBloc = Provider.of(context, listen: false); final placeholderBuilder = PlaceholderBuilder.of(context); final chapterTitle = chapter?.title ?? ''; final chapterUrl = chapter?.url ?? ''; - return StreamBuilder( - stream: audioBloc.nowPlaying, - builder: (context, statesnap) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 7, - child: PodcastImage( - key: Key('nowplaying$imageUrl'), - url: imageUrl, - height: 360, - width: 360, - fit: BoxFit.contain, - placeholder: placeholderBuilder != null - ? placeholderBuilder?.builder()(context) - : DelayedCircularProgressIndicator(), - errorPlaceholder: placeholderBuilder != null - ? placeholderBuilder?.errorBuilder()(context) - : Image( - image: AssetImage( - 'assets/images/anytime-placeholder-logo.png')), - ), - ), - Expanded( - flex: 3, - child: Padding( - padding: const EdgeInsets.only( - top: 16.0, - bottom: 0.0, - left: 16.0, - right: 16.0, + return Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 7, + child: PodcastImage( + key: Key('nowplaying$imageUrl'), + url: imageUrl, + height: 360, + width: 360, + fit: BoxFit.contain, + placeholder: placeholderBuilder != null + ? placeholderBuilder?.builder()(context) + : DelayedCircularProgressIndicator(), + errorPlaceholder: placeholderBuilder != null + ? placeholderBuilder?.errorBuilder()(context) + : Image(image: AssetImage('assets/images/anytime-placeholder-logo.png')), + ), + ), + Expanded( + flex: 3, + child: Padding( + padding: const EdgeInsets.only( + top: 16.0, + bottom: 0.0, + left: 16.0, + right: 16.0, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 2, + child: AutoSizeText( + title ?? '', + group: textGroup, + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + minFontSize: 12.0, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20.0, + ), + maxLines: 3, ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - flex: 2, - child: AutoSizeText( - title ?? '', - group: textGroup, - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, - minFontSize: 12.0, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 20.0, - ), - maxLines: 3, - ), - ), - Expanded( - flex: 3, - child: Padding( - padding: - const EdgeInsets.fromLTRB(0.0, 4.0, 0.0, 0.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Flexible( - child: AutoSizeText( - chapterTitle ?? '', - group: textGroup, - minFontSize: 12.0, - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontWeight: FontWeight.normal, - fontSize: 14.0, - ), - maxLines: 3, - ), - ), - chapterUrl.isEmpty - ? const SizedBox( - height: 0, - width: 0, - ) - : IconButton( - icon: Icon(Icons.link), - color: Theme.of(context) - .primaryIconTheme - .color, - onPressed: () { - _chapterLink(chapterUrl); - }), - ], + ), + Expanded( + flex: 3, + child: Padding( + padding: const EdgeInsets.fromLTRB(0.0, 4.0, 0.0, 0.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Flexible( + child: AutoSizeText( + chapterTitle ?? '', + group: textGroup, + minFontSize: 12.0, + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: FontWeight.normal, + fontSize: 14.0, + ), + maxLines: 3, ), ), - ), - ], + chapterUrl.isEmpty + ? const SizedBox( + height: 0, + width: 0, + ) + : IconButton( + icon: Icon(Icons.link), + color: Theme.of(context).primaryIconTheme.color, + onPressed: () { + _chapterLink(chapterUrl); + }), + ], + ), ), ), - ), - ], + ], + ), ), - ); - }); + ), + ], + ), + ); } void _chapterLink(String url) async { diff --git a/lib/ui/widgets/episode_tile.dart b/lib/ui/widgets/episode_tile.dart index 58631b31..b69b0a70 100644 --- a/lib/ui/widgets/episode_tile.dart +++ b/lib/ui/widgets/episode_tile.dart @@ -58,10 +58,17 @@ class EpisodeTile extends StatelessWidget { highlight: episode.highlight, ), ), - Container( - height: 4.0, - width: 56.0 * (episode.percentagePlayed / 100), - color: Theme.of(context).primaryColor, + Padding( + padding: const EdgeInsets.only( + left: 1.0, + right: 1.0, + bottom: 1.0, + ), + child: Container( + height: 4.0, + width: 56.0 * (episode.percentagePlayed / 100), + color: Theme.of(context).primaryColor, + ), ), ], ),