diff --git a/lib/home/home.dart b/lib/home/home.dart index b1204aa..264e835 100644 --- a/lib/home/home.dart +++ b/lib/home/home.dart @@ -24,6 +24,7 @@ import '../util/custom_popupmenu.dart'; import '../util/custom_widget.dart'; import '../util/episodegrid.dart'; import '../util/extension_helper.dart'; +import '../util/muiliselect_bar.dart'; import 'audioplayer.dart'; import 'download_list.dart'; import 'home_groups.dart'; @@ -315,9 +316,8 @@ class _HomeState extends State with SingleTickerProviderStateMixin { color: Colors.cyan[600], padding: const EdgeInsets.all(0), child: Text(s.dismiss, - style: Theme.of(context) - .textTheme - .button + style: context + .textTheme.button .copyWith( color: Colors.white)), onPressed: () => @@ -727,6 +727,13 @@ class _RecentUpdateState extends State<_RecentUpdate> Layout _layout; bool _hideListened; bool _scroll; + + ///Selected episode list. + List _selectedEpisodes; + + ///Toggle for multi-select. + bool _multiSelect; + @override void initState() { super.initState(); @@ -734,9 +741,10 @@ class _RecentUpdateState extends State<_RecentUpdate> _groupName = 'All'; _group = []; _scroll = false; + _multiSelect = false; } - Future _updateRssItem() async { + Future _updateRssItem() async { final refreshWorker = context.read(); refreshWorker.start(_group); await Future.delayed(Duration(seconds: 1)); @@ -955,77 +963,198 @@ class _RecentUpdateState extends State<_RecentUpdate> backgroundColor: context.accentColor, semanticsLabel: s.refreshStarted, onRefresh: _updateRssItem, - child: CustomScrollView( - key: PageStorageKey('update'), - physics: - const AlwaysScrollableScrollPhysics(), - slivers: [ - SliverToBoxAdapter( - child: Container( - height: 40, - color: context.primaryColor, - child: Material( - color: Colors.transparent, - child: Row( - children: [ - _switchGroupButton(), - Spacer(), - _addNewButton(), - Material( - color: Colors.transparent, - child: IconButton( - tooltip: - s.hideListenedSetting, - icon: SizedBox( - width: 30, - height: 15, - child: HideListened( - hideListened: - _hideListened ?? - false, - ), - ), - onPressed: () { - setState(() => - _hideListened = - !_hideListened); - }, - ), - ), - Material( - color: Colors.transparent, - child: LayoutButton( - layout: _layout, - onPressed: (layout) => - setState(() { - _layout = layout; - }), - ), - ), - ], + child: Stack( + children: [ + ScrollConfiguration( + behavior: NoGrowBehavior(), + child: CustomScrollView( + key: PageStorageKey('update'), + physics: + const AlwaysScrollableScrollPhysics(), + slivers: [ + SliverToBoxAdapter( + child: SizedBox( + height: 40, + // color: context.primaryColor, + // child: Material( + // color: Colors.transparent, + // child: Row( + // children: [ + // _switchGroupButton(), + // Spacer(), + // _addNewButton(), + // Material( + // color: Colors.transparent, + // child: IconButton( + // tooltip: s + // .hideListenedSetting, + // icon: SizedBox( + // width: 30, + // height: 15, + // child: HideListened( + // hideListened: + // _hideListened ?? + // false, + // ), + // ), + // onPressed: () { + // setState(() => + // _hideListened = + // !_hideListened); + // }, + // ), + // ), + // Material( + // color: Colors.transparent, + // child: LayoutButton( + // layout: _layout, + // onPressed: (layout) => + // setState(() { + // _layout = layout; + // }), + // ), + // ), + // Material( + // color: + // Colors.transparent, + // clipBehavior: + // Clip.hardEdge, + // borderRadius: + // BorderRadius + // .circular(100), + // child: IconButton( + // icon: SizedBox( + // width: 20, + // height: 10, + // child: CustomPaint( + // painter: MultiSelectPainter( + // color: context + // .accentColor)), + // ), + // onPressed: () { + // setState(() { + // _selectedEpisodes = + // []; + // _multiSelect = + // true; + // }); + // }, + // )), + // ], + // ), + // ), ), - )), - ), - EpisodeGrid( - episodes: snapshot.data, - layout: _layout, - initNum: _scroll ? 0 : 12, - ), - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - return _loadMore - ? Container( - height: 2, - child: - LinearProgressIndicator()) - : Center(); - }, - childCount: 1, - ), - ), - ]), - )) + ), + EpisodeGrid( + episodes: snapshot.data, + layout: _layout, + initNum: _scroll ? 0 : 12, + multiSelect: _multiSelect, + selectedList: + _selectedEpisodes ?? [], + onSelect: (value) => setState(() { + _selectedEpisodes = value; + }), + ), + SliverList( + delegate: + SliverChildBuilderDelegate( + (context, index) { + return _loadMore + ? Container( + height: 2, + child: + LinearProgressIndicator()) + : Center(); + }, + childCount: 1, + ), + ), + ]), + ), + Column( + children: [ + if (!_multiSelect) + Container( + height: 40, + color: context.primaryColor, + child: Material( + color: Colors.transparent, + child: Row( + children: [ + _switchGroupButton(), + Spacer(), + _addNewButton(), + Material( + color: Colors.transparent, + child: IconButton( + tooltip: + s.hideListenedSetting, + icon: SizedBox( + width: 30, + height: 15, + child: HideListened( + hideListened: + _hideListened ?? + false, + ), + ), + onPressed: () { + setState(() => + _hideListened = + !_hideListened); + }, + ), + ), + Material( + color: Colors.transparent, + child: LayoutButton( + layout: _layout, + onPressed: (layout) => + setState(() { + _layout = layout; + }), + ), + ), + Material( + color: Colors.transparent, + child: IconButton( + icon: SizedBox( + width: 20, + height: 10, + child: CustomPaint( + painter: MultiSelectPainter( + color: context + .accentColor)), + ), + onPressed: () { + setState(() { + _selectedEpisodes = + []; + _multiSelect = true; + }); + }, + )), + ], + ), + )), + if (_multiSelect) + MultiSelectMenuBar( + selectedList: _selectedEpisodes, + onClose: (value) { + setState(() { + if (value) { + _multiSelect = false; + } + }); + }, + ), + ], + ), + ], + ), + ), + ) : Center(); }, ); @@ -1122,122 +1251,127 @@ class _MyFavoriteState extends State<_MyFavorite> } return true; }, - child: CustomScrollView( - key: PageStorageKey('favorite'), - slivers: [ - SliverToBoxAdapter( - child: Container( - height: 40, - color: context.primaryColor, - child: Row( - children: [ - Material( - color: Colors.transparent, - child: PopupMenuButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(10))), - elevation: 1, - tooltip: s.homeSubMenuSortBy, - child: Container( - height: 50, - padding: EdgeInsets.symmetric( - horizontal: 20), - child: Row( - mainAxisSize: - MainAxisSize.min, - children: [ - Text(s.homeSubMenuSortBy), - Padding( - padding: - EdgeInsets.symmetric( - horizontal: 5), - ), - Icon( - LineIcons - .hourglass_start_solid, - size: 18, - ) - ], - )), - itemBuilder: (context) => [ - PopupMenuItem( - value: 0, - child: Row( - children: [ - Text(s.updateDate), - Spacer(), - if (_sortBy == 0) - DotIndicator() - ], + child: Stack( + children: [ + ScrollConfiguration( + behavior: NoGrowBehavior(), + child: CustomScrollView( + key: PageStorageKey('favorite'), + slivers: [ + SliverToBoxAdapter( + child: SizedBox(height: 40)), + EpisodeGrid( + episodes: snapshot.data, + layout: _layout, + initNum: 0, + ), + SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + return _loadMore + ? Container( + height: 2, + child: + LinearProgressIndicator()) + : Center(); + }, + childCount: 1, + ), + ), + ], + ), + ), + Container( + height: 40, + color: context.primaryColor, + child: Row( + children: [ + Material( + color: Colors.transparent, + child: PopupMenuButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(10))), + elevation: 1, + tooltip: s.homeSubMenuSortBy, + child: Container( + height: 50, + padding: EdgeInsets.symmetric( + horizontal: 20), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(s.homeSubMenuSortBy), + Padding( + padding: EdgeInsets.symmetric( + horizontal: 5), ), - ), - PopupMenuItem( - value: 1, - child: Row( - children: [ - Text(s.likeDate), - Spacer(), - if (_sortBy == 1) - DotIndicator() - ], - ), - ) - ], - onSelected: (value) { - if (value == 0) { - setState(() => _sortBy = 0); - } else if (value == 1) { - setState(() => _sortBy = 1); - } - }, - ), - ), - Spacer(), - Material( - color: Colors.transparent, - child: IconButton( - icon: SizedBox( - width: 30, - height: 15, - child: HideListened( - hideListened: - _hideListened ?? false, - ), + Icon( + LineIcons + .hourglass_start_solid, + size: 18, + ) + ], + )), + itemBuilder: (context) => [ + PopupMenuItem( + value: 0, + child: Row( + children: [ + Text(s.updateDate), + Spacer(), + if (_sortBy == 0) DotIndicator() + ], ), - onPressed: () { - setState(() => _hideListened = - !_hideListened); - }, + ), + PopupMenuItem( + value: 1, + child: Row( + children: [ + Text(s.likeDate), + Spacer(), + if (_sortBy == 1) DotIndicator() + ], + ), + ) + ], + onSelected: (value) { + if (value == 0) { + setState(() => _sortBy = 0); + } else if (value == 1) { + setState(() => _sortBy = 1); + } + }, + ), + ), + Spacer(), + Material( + color: Colors.transparent, + child: IconButton( + icon: SizedBox( + width: 30, + height: 15, + child: HideListened( + hideListened: + _hideListened ?? false, ), ), - Material( - color: Colors.transparent, - child: LayoutButton( - layout: _layout, - onPressed: (layout) => setState(() { - _layout = layout; - }), - ), - ), - ], - )), - ), - EpisodeGrid( - episodes: snapshot.data, - layout: _layout, - initNum: 0, - ), - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - return _loadMore - ? Container( - height: 2, - child: LinearProgressIndicator()) - : Center(); - }, - childCount: 1, + onPressed: () { + setState(() => + _hideListened = !_hideListened); + }, + ), + ), + Material( + color: Colors.transparent, + child: LayoutButton( + layout: _layout, + onPressed: (layout) => setState(() { + _layout = layout; + }), + ), + ), + ], ), ), ], diff --git a/lib/podcasts/podcast_detail.dart b/lib/podcasts/podcast_detail.dart index b5d729a..1f67ec0 100644 --- a/lib/podcasts/podcast_detail.dart +++ b/lib/podcasts/podcast_detail.dart @@ -10,7 +10,6 @@ import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:html/parser.dart'; import 'package:line_icons/line_icons.dart'; -import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; @@ -21,13 +20,13 @@ import '../state/audio_state.dart'; import '../state/download_state.dart'; import '../type/episodebrief.dart'; import '../type/fireside_data.dart'; -import '../type/play_histroy.dart'; import '../type/podcastlocal.dart'; import '../util/audiopanel.dart'; import '../util/custom_widget.dart'; import '../util/episodegrid.dart'; import '../util/extension_helper.dart'; import '../util/general_dialog.dart'; +import '../util/muiliselect_bar.dart'; import 'podcast_settings.dart'; class PodcastDetail extends StatefulWidget { @@ -83,11 +82,8 @@ class _PodcastDetailState extends State { ///Toggle for multi-select. bool _multiSelect; - bool _selectAll; - bool _selectBefore; - bool _selectAfter; @override @@ -994,419 +990,6 @@ class _PodcastDetailState extends State { } } -class MultiSelectMenuBar extends StatefulWidget { - MultiSelectMenuBar( - {this.selectedList, - this.selectAll, - this.onSelectAll, - this.onClose, - this.onSelectAfter, - this.onSelectBefore, - Key key}) - : super(key: key); - final List selectedList; - final bool selectAll; - final ValueChanged onSelectAll; - final ValueChanged onClose; - final ValueChanged onSelectBefore; - final ValueChanged onSelectAfter; - - @override - _MultiSelectMenuBarState createState() => _MultiSelectMenuBarState(); -} - -///Multi select menu bar. -class _MultiSelectMenuBarState extends State { - bool _liked; - bool _marked; - bool _inPlaylist; - bool _downloaded; - final _dbHelper = DBHelper(); - - @override - void initState() { - super.initState(); - _liked = false; - _marked = false; - _downloaded = false; - _inPlaylist = false; - } - - @override - void didUpdateWidget(MultiSelectMenuBar oldWidget) { - if (oldWidget.selectedList != widget.selectedList) { - setState(() { - _liked = false; - _marked = false; - _downloaded = false; - _inPlaylist = false; - }); - super.didUpdateWidget(oldWidget); - } - } - - Future _saveLiked() async { - for (var episode in widget.selectedList) { - await _dbHelper.setLiked(episode.enclosureUrl); - } - if (mounted) { - setState(() => _liked = true); - widget.onClose(false); - } - } - - Future _setUnliked() async { - for (var episode in widget.selectedList) { - await _dbHelper.setUniked(episode.enclosureUrl); - } - if (mounted) { - setState(() => _liked = false); - widget.onClose(false); - } - } - - Future _markListened() async { - for (var episode in widget.selectedList) { - final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1); - await _dbHelper.saveHistory(history); - } - if (mounted) { - setState(() => _marked = true); - widget.onClose(false); - } - } - - Future _markNotListened() async { - for (var episode in widget.selectedList) { - await _dbHelper.markNotListened(episode.enclosureUrl); - } - if (mounted) { - setState(() => _marked = false); - widget.onClose(false); - } - } - - Future _requestDownload() async { - final permissionReady = await _checkPermmison(); - final downloadUsingData = await KeyValueStorage(downloadUsingDataKey) - .getBool(defaultValue: true, reverse: true); - var dataConfirm = true; - final result = await Connectivity().checkConnectivity(); - final usingData = result == ConnectivityResult.mobile; - if (permissionReady) { - if (downloadUsingData && usingData) { - dataConfirm = await _useDataConfirm(); - } - if (dataConfirm) { - for (var episode in widget.selectedList) { - Provider.of(context, listen: false).startTask(episode); - } - if (mounted) { - setState(() { - _downloaded = true; - }); - } - } - } - } - - Future _useDataConfirm() async { - var ifUseData = false; - final s = context.s; - await generalDialog( - context, - title: Text(s.cellularConfirm), - content: Text(s.cellularConfirmDes), - actions: [ - FlatButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text( - s.cancel, - style: TextStyle(color: Colors.grey[600]), - ), - ), - FlatButton( - onPressed: () { - ifUseData = true; - Navigator.of(context).pop(); - }, - child: Text( - s.confirm, - style: TextStyle(color: Colors.red), - ), - ) - ], - ); - return ifUseData; - } - - Future _checkPermmison() async { - var permission = await Permission.storage.status; - if (permission != PermissionStatus.granted) { - var permissions = await [Permission.storage].request(); - if (permissions[Permission.storage] == PermissionStatus.granted) { - return true; - } else { - return false; - } - } else { - return true; - } - } - - Widget _buttonOnMenu({Widget child, VoidCallback onTap}) => Material( - color: Colors.transparent, - child: InkWell( - onTap: onTap, - child: SizedBox( - height: 50, - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 15.0), child: child), - ), - ), - ); - OverlayEntry _createOverlayEntry() { - RenderBox renderBox = context.findRenderObject(); - var offset = renderBox.localToGlobal(Offset.zero); - return OverlayEntry( - builder: (constext) => Positioned( - left: offset.dx + 50, - top: offset.dy - 60, - child: Container( - width: 70, - height: 100, - //color: Colors.grey[200], - child: HeartOpen(width: 50, height: 80)), - ), - ); - } - - @override - Widget build(BuildContext context) { - final s = context.s; - var audio = context.watch(); - return TweenAnimationBuilder( - tween: Tween(begin: 0, end: 1), - duration: Duration(milliseconds: 500), - builder: (context, value, child) => Container( - height: 90.0 * value, - decoration: BoxDecoration(color: context.primaryColor), - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - height: 40, - child: Center( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 20.0), - child: Text('${widget.selectedList.length} selected', - style: context.textTheme.headline6 - .copyWith(color: context.accentColor))), - ), - ), - Spacer(), - if (widget.selectedList.length == 1) - SizedBox( - height: 25, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 5), - child: OutlinedButton( - style: OutlinedButton.styleFrom( - side: BorderSide(color: context.accentColor), - primary: context.textColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(100)))), - onPressed: () { - widget.onSelectBefore(true); - }, - child: Text('Before')), - ), - ), - if (widget.selectedList.length == 1) - SizedBox( - height: 25, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 5), - child: OutlinedButton( - style: OutlinedButton.styleFrom( - side: BorderSide(color: context.accentColor), - primary: context.textColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(100)))), - onPressed: () { - widget.onSelectAfter(true); - }, - child: Text('After')), - ), - ), - SizedBox( - height: 25, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 5), - child: OutlinedButton( - style: OutlinedButton.styleFrom( - side: BorderSide(color: context.accentColor), - backgroundColor: - widget.selectAll ? context.accentColor : null, - primary: widget.selectAll - ? Colors.white - : context.textColor, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.all(Radius.circular(100)))), - onPressed: () { - widget.onSelectAll(!widget.selectAll); - }, - child: Text('All')), - ), - ) - ], - ), - Row( - children: [ - _buttonOnMenu( - child: _liked - ? Icon(Icons.favorite, color: Colors.red) - : Icon( - Icons.favorite_border, - color: Colors.grey[700], - ), - onTap: () async { - if (widget.selectedList.isNotEmpty) { - if (!_liked) { - await _saveLiked(); - Fluttertoast.showToast( - msg: s.liked, - gravity: ToastGravity.BOTTOM, - ); - } else { - await _setUnliked(); - Fluttertoast.showToast( - msg: s.unliked, - gravity: ToastGravity.BOTTOM, - ); - } - } - // OverlayEntry _overlayEntry; - // _overlayEntry = _createOverlayEntry(); - // Overlay.of(context).insert(_overlayEntry); - // await Future.delayed(Duration(seconds: 2)); - // _overlayEntry?.remove(); - }), - _buttonOnMenu( - child: _downloaded - ? Center( - child: SizedBox( - height: 20, - width: 20, - child: CustomPaint( - painter: DownloadPainter( - color: context.accentColor, - fraction: 1, - progressColor: context.accentColor, - progress: 1), - ), - ), - ) - : Center( - child: SizedBox( - height: 20, - width: 20, - child: CustomPaint( - painter: DownloadPainter( - color: Colors.grey[700], - fraction: 0, - progressColor: context.accentColor, - ), - ), - ), - ), - onTap: () { - if (widget.selectedList.isNotEmpty) { - if (!_downloaded) _requestDownload(); - } - }, - ), - _buttonOnMenu( - child: _inPlaylist - ? Icon(Icons.playlist_add_check, - color: context.accentColor) - : Icon( - Icons.playlist_add, - color: Colors.grey[700], - ), - onTap: () async { - if (widget.selectedList.isNotEmpty) { - if (!_inPlaylist) { - for (var episode in widget.selectedList) { - audio.addToPlaylist(episode); - Fluttertoast.showToast( - msg: s.toastAddPlaylist, - gravity: ToastGravity.BOTTOM, - ); - } - setState(() => _inPlaylist = true); - } else { - for (var episode in widget.selectedList) { - audio.delFromPlaylist(episode); - Fluttertoast.showToast( - msg: s.toastRemovePlaylist, - gravity: ToastGravity.BOTTOM, - ); - } - setState(() => _inPlaylist = false); - } - } - }), - _buttonOnMenu( - child: Padding( - padding: EdgeInsets.symmetric(vertical: 12), - child: CustomPaint( - size: Size(25, 20), - painter: ListenedAllPainter( - _marked ? context.accentColor : Colors.grey[700], - stroke: 2.0), - ), - ), - onTap: () async { - if (widget.selectedList.isNotEmpty) { - if (!_marked) { - await _markListened(); - Fluttertoast.showToast( - msg: s.markListened, - gravity: ToastGravity.BOTTOM, - ); - } else { - await _markNotListened(); - Fluttertoast.showToast( - msg: s.markNotListened, - gravity: ToastGravity.BOTTOM, - ); - } - } - }), - Spacer(), - _buttonOnMenu( - child: Icon(Icons.close), - onTap: () => widget.onClose(true)) - ], - ), - ], - ), - ), - ), - ); - } -} - class AboutPodcast extends StatefulWidget { final PodcastLocal podcastLocal; AboutPodcast({this.podcastLocal, Key key}) : super(key: key); diff --git a/lib/util/muiliselect_bar.dart b/lib/util/muiliselect_bar.dart new file mode 100644 index 0000000..c37fda4 --- /dev/null +++ b/lib/util/muiliselect_bar.dart @@ -0,0 +1,445 @@ +import 'package:connectivity/connectivity.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:provider/provider.dart'; + +import '../local_storage/key_value_storage.dart'; +import '../local_storage/sqflite_localpodcast.dart'; +import '../state/audio_state.dart'; +import '../state/download_state.dart'; +import '../type/episodebrief.dart'; +import '../type/play_histroy.dart'; +import 'custom_widget.dart'; +import 'extension_helper.dart'; +import 'general_dialog.dart'; + +class MultiSelectMenuBar extends StatefulWidget { + MultiSelectMenuBar( + {this.selectedList, + this.selectAll, + this.onSelectAll, + this.onClose, + this.onSelectAfter, + this.onSelectBefore, + Key key}) + : assert(onClose != null), + super(key: key); + final List selectedList; + final bool selectAll; + final ValueChanged onSelectAll; + final ValueChanged onClose; + final ValueChanged onSelectBefore; + final ValueChanged onSelectAfter; + + @override + _MultiSelectMenuBarState createState() => _MultiSelectMenuBarState(); +} + +///Multi select menu bar. +class _MultiSelectMenuBarState extends State { + bool _liked; + bool _marked; + bool _inPlaylist; + bool _downloaded; + final _dbHelper = DBHelper(); + + @override + void initState() { + super.initState(); + _liked = false; + _marked = false; + _downloaded = false; + _inPlaylist = false; + } + + @override + void didUpdateWidget(MultiSelectMenuBar oldWidget) { + if (oldWidget.selectedList != widget.selectedList) { + setState(() { + _liked = false; + _marked = false; + _downloaded = false; + _inPlaylist = false; + }); + super.didUpdateWidget(oldWidget); + } + } + + Future _saveLiked() async { + for (var episode in widget.selectedList) { + await _dbHelper.setLiked(episode.enclosureUrl); + } + if (mounted) { + setState(() => _liked = true); + widget.onClose(false); + } + } + + Future _setUnliked() async { + for (var episode in widget.selectedList) { + await _dbHelper.setUniked(episode.enclosureUrl); + } + if (mounted) { + setState(() => _liked = false); + widget.onClose(false); + } + } + + Future _markListened() async { + for (var episode in widget.selectedList) { + final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1); + await _dbHelper.saveHistory(history); + } + if (mounted) { + setState(() => _marked = true); + widget.onClose(false); + } + } + + Future _markNotListened() async { + for (var episode in widget.selectedList) { + await _dbHelper.markNotListened(episode.enclosureUrl); + } + if (mounted) { + setState(() => _marked = false); + widget.onClose(false); + } + } + + Future _requestDownload() async { + final permissionReady = await _checkPermmison(); + final downloadUsingData = await KeyValueStorage(downloadUsingDataKey) + .getBool(defaultValue: true, reverse: true); + var dataConfirm = true; + final result = await Connectivity().checkConnectivity(); + final usingData = result == ConnectivityResult.mobile; + if (permissionReady) { + if (downloadUsingData && usingData) { + dataConfirm = await _useDataConfirm(); + } + if (dataConfirm) { + for (var episode in widget.selectedList) { + Provider.of(context, listen: false).startTask(episode); + } + if (mounted) { + setState(() { + _downloaded = true; + }); + } + } + } + } + + Future _useDataConfirm() async { + var ifUseData = false; + final s = context.s; + await generalDialog( + context, + title: Text(s.cellularConfirm), + content: Text(s.cellularConfirmDes), + actions: [ + FlatButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text( + s.cancel, + style: TextStyle(color: Colors.grey[600]), + ), + ), + FlatButton( + onPressed: () { + ifUseData = true; + Navigator.of(context).pop(); + }, + child: Text( + s.confirm, + style: TextStyle(color: Colors.red), + ), + ) + ], + ); + return ifUseData; + } + + Future _checkPermmison() async { + var permission = await Permission.storage.status; + if (permission != PermissionStatus.granted) { + var permissions = await [Permission.storage].request(); + if (permissions[Permission.storage] == PermissionStatus.granted) { + return true; + } else { + return false; + } + } else { + return true; + } + } + + Widget _buttonOnMenu({Widget child, VoidCallback onTap}) => Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + child: SizedBox( + height: 40, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 12.0), child: child), + ), + ), + ); + OverlayEntry _createOverlayEntry() { + RenderBox renderBox = context.findRenderObject(); + var offset = renderBox.localToGlobal(Offset.zero); + return OverlayEntry( + builder: (constext) => Positioned( + left: offset.dx + 50, + top: offset.dy - 60, + child: Container( + width: 70, + height: 100, + //color: Colors.grey[200], + child: HeartOpen(width: 50, height: 80)), + ), + ); + } + + @override + Widget build(BuildContext context) { + final s = context.s; + var audio = context.watch(); + return TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: Duration(milliseconds: 500), + builder: (context, value, child) => Container( + height: widget.selectAll == null ? 40 : 90.0 * value, + decoration: BoxDecoration(color: context.primaryColor), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (widget.selectAll != null) + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: 40, + child: Center( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 20.0), + child: Text( + '${widget.selectedList.length} selected', + style: context.textTheme.headline6 + .copyWith(color: context.accentColor))), + ), + ), + Spacer(), + if (widget.selectedList.length == 1) + SizedBox( + height: 25, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 5), + child: OutlinedButton( + style: OutlinedButton.styleFrom( + side: BorderSide(color: context.accentColor), + primary: context.textColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(100)))), + onPressed: () { + widget.onSelectBefore(true); + }, + child: Text('Before')), + ), + ), + if (widget.selectedList.length == 1) + SizedBox( + height: 25, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 5), + child: OutlinedButton( + style: OutlinedButton.styleFrom( + side: BorderSide(color: context.accentColor), + primary: context.textColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(100)))), + onPressed: () { + widget.onSelectAfter(true); + }, + child: Text('After')), + ), + ), + SizedBox( + height: 25, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 5), + child: OutlinedButton( + style: OutlinedButton.styleFrom( + side: BorderSide(color: context.accentColor), + backgroundColor: widget.selectAll + ? context.accentColor + : null, + primary: widget.selectAll + ? Colors.white + : context.textColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(100)))), + onPressed: () { + widget.onSelectAll(!widget.selectAll); + }, + child: Text('All')), + ), + ) + ], + ), + Row( + children: [ + _buttonOnMenu( + child: _liked + ? Icon(Icons.favorite, color: Colors.red) + : Icon( + Icons.favorite_border, + color: Colors.grey[700], + ), + onTap: () async { + if (widget.selectedList.isNotEmpty) { + if (!_liked) { + await _saveLiked(); + Fluttertoast.showToast( + msg: s.liked, + gravity: ToastGravity.BOTTOM, + ); + } else { + await _setUnliked(); + Fluttertoast.showToast( + msg: s.unliked, + gravity: ToastGravity.BOTTOM, + ); + } + audio.setEpisodeState = true; + } + // OverlayEntry _overlayEntry; + // _overlayEntry = _createOverlayEntry(); + // Overlay.of(context).insert(_overlayEntry); + // await Future.delayed(Duration(seconds: 2)); + // _overlayEntry?.remove(); + }), + _buttonOnMenu( + child: _downloaded + ? Center( + child: SizedBox( + height: 20, + width: 20, + child: CustomPaint( + painter: DownloadPainter( + color: context.accentColor, + fraction: 1, + progressColor: context.accentColor, + progress: 1), + ), + ), + ) + : Center( + child: SizedBox( + height: 20, + width: 20, + child: CustomPaint( + painter: DownloadPainter( + color: Colors.grey[700], + fraction: 0, + progressColor: context.accentColor, + ), + ), + ), + ), + onTap: () { + if (widget.selectedList.isNotEmpty) { + if (!_downloaded) _requestDownload(); + } + }, + ), + _buttonOnMenu( + child: _inPlaylist + ? Icon(Icons.playlist_add_check, + color: context.accentColor) + : Icon( + Icons.playlist_add, + color: Colors.grey[700], + ), + onTap: () async { + if (widget.selectedList.isNotEmpty) { + if (!_inPlaylist) { + for (var episode in widget.selectedList) { + audio.addToPlaylist(episode); + Fluttertoast.showToast( + msg: s.toastAddPlaylist, + gravity: ToastGravity.BOTTOM, + ); + } + setState(() => _inPlaylist = true); + } else { + for (var episode in widget.selectedList) { + audio.delFromPlaylist(episode); + Fluttertoast.showToast( + msg: s.toastRemovePlaylist, + gravity: ToastGravity.BOTTOM, + ); + } + setState(() => _inPlaylist = false); + } + } + }), + _buttonOnMenu( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: CustomPaint( + size: Size(25, 25), + painter: ListenedAllPainter( + _marked ? context.accentColor : Colors.grey[700], + stroke: 2.0), + ), + ), + onTap: () async { + if (widget.selectedList.isNotEmpty) { + if (!_marked) { + await _markListened(); + Fluttertoast.showToast( + msg: s.markListened, + gravity: ToastGravity.BOTTOM, + ); + } else { + await _markNotListened(); + Fluttertoast.showToast( + msg: s.markNotListened, + gravity: ToastGravity.BOTTOM, + ); + } + } + }), + Spacer(), + if (widget.selectAll == null) + SizedBox( + height: 40, + child: Center( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10.0), + child: Text( + '${widget.selectedList.length} selected', + style: context.textTheme.headline6 + .copyWith(color: context.accentColor))), + ), + ), + _buttonOnMenu( + child: Icon(Icons.close), + onTap: () => widget.onClose(true)) + ], + ), + ], + ), + ), + ), + ); + } +}