From d0329792638e13497d528ea5ba8db27f5775974a Mon Sep 17 00:00:00 2001 From: xijieyin Date: Sat, 4 Jun 2022 17:45:51 +0800 Subject: [PATCH] fix: update material you theme --- lib/episodes/episode_detail.dart | 9 +- lib/home/about.dart | 8 +- lib/home/home.dart | 9 +- lib/home/home_groups.dart | 342 +++++++------- lib/home/pocast_discovery.dart | 565 ++++++++++++------------ lib/home/search_podcast.dart | 242 +++++----- lib/main.dart | 4 + lib/podcasts/custom_tabview.dart | 3 +- lib/podcasts/podcast_detail.dart | 175 +++----- lib/podcasts/podcast_group.dart | 252 +++++------ lib/podcasts/podcast_manage.dart | 685 ++++++++++++++--------------- lib/podcasts/podcast_settings.dart | 375 ++++++++-------- lib/podcasts/podcastlist.dart | 131 ++---- lib/settings/data_backup.dart | 2 +- lib/settings/history.dart | 2 +- lib/settings/layouts.dart | 2 +- lib/settings/play_setting.dart | 2 +- lib/settings/settting.dart | 6 +- lib/settings/storage.dart | 2 +- lib/settings/theme.dart | 71 +-- lib/util/extension_helper.dart | 4 +- lib/widgets/episodegrid.dart | 538 +++++++++++----------- 22 files changed, 1673 insertions(+), 1756 deletions(-) diff --git a/lib/episodes/episode_detail.dart b/lib/episodes/episode_detail.dart index 7b9c0e6..0346135 100644 --- a/lib/episodes/episode_detail.dart +++ b/lib/episodes/episode_detail.dart @@ -104,7 +104,7 @@ class _EpisodeDetailState extends State { } }, child: Scaffold( - backgroundColor: context.onPrimary, + backgroundColor: context.background, body: SafeArea( child: Stack( children: [ @@ -120,6 +120,7 @@ class _EpisodeDetailState extends State { widget.episodeItem!.cardColor(context), floating: true, pinned: true, + scrolledUnderElevation: 0, title: _showTitle ? Text( widget.episodeItem?.title ?? '', @@ -195,8 +196,8 @@ class _EpisodeDetailState extends State { s.minsCount( widget.episodeItem!.duration! ~/ 60, ), - style: - TextStyle(color: context.onPrimary), + style: TextStyle( + color: context.background), )), if (widget.episodeItem!.enclosureLength != null && @@ -214,7 +215,7 @@ class _EpisodeDetailState extends State { child: Text( '${widget.episodeItem!.enclosureLength! ~/ 1000000}MB', style: - TextStyle(color: context.onPrimary), + TextStyle(color: context.background), ), ), FutureBuilder( diff --git a/lib/home/about.dart b/lib/home/about.dart index e9052fd..b1e3b5e 100644 --- a/lib/home/about.dart +++ b/lib/home/about.dart @@ -30,16 +30,16 @@ class AboutApp extends StatelessWidget { final s = context.s; return AnnotatedRegion( value: SystemUiOverlayStyle( - statusBarColor: context.onPrimary, + statusBarColor: context.background, statusBarIconBrightness: context.iconBrightness, - systemNavigationBarColor: context.onPrimary, + systemNavigationBarColor: context.background, systemNavigationBarIconBrightness: context.iconBrightness, ), child: SafeArea( child: Scaffold( - backgroundColor: context.onPrimary, + backgroundColor: context.background, appBar: AppBar( - backgroundColor: context.onPrimary, + backgroundColor: context.background, title: Text(s.homeToprightMenuAbout), scrolledUnderElevation: 1, leading: CustomBackButton(), diff --git a/lib/home/home.dart b/lib/home/home.dart index 4d2a4bc..60608ba 100644 --- a/lib/home/home.dart +++ b/lib/home/home.dart @@ -97,8 +97,8 @@ class _HomeState extends State with SingleTickerProviderStateMixin { value: SystemUiOverlayStyle( systemNavigationBarIconBrightness: context.brightness, statusBarIconBrightness: context.iconBrightness, - systemNavigationBarColor: context.onPrimary, - statusBarColor: context.onPrimary, + systemNavigationBarColor: context.background, + statusBarColor: context.background, ), child: WillPopScope( onWillPop: () async { @@ -115,7 +115,7 @@ class _HomeState extends State with SingleTickerProviderStateMixin { }, child: Scaffold( key: _scaffoldKey, - backgroundColor: context.onPrimary, + backgroundColor: context.background, body: Stack( children: [ SafeArea( @@ -163,8 +163,7 @@ class _HomeState extends State with SingleTickerProviderStateMixin { Theme.of(context).brightness == Brightness.light ? settings.setTheme = ThemeMode.dark - : settings.setTheme = - ThemeMode.light + : settings.setTheme = ThemeMode.light }, child: Text( 'Tsacdop', diff --git a/lib/home/home_groups.dart b/lib/home/home_groups.dart index dcbd613..d4ae812 100644 --- a/lib/home/home_groups.dart +++ b/lib/home/home_groups.dart @@ -94,113 +94,115 @@ class _ScrollPodcastsState extends State mainAxisSize: MainAxisSize.min, children: [ GestureDetector( - onVerticalDragEnd: (event) { - if (event.primaryVelocity! > 200) { - if (groups.length == 1) { - Fluttertoast.showToast( - msg: s.addSomeGroups, - gravity: ToastGravity.BOTTOM, - ); - } else { - if (mounted) { - setState(() { - (_groupIndex != 0) - ? _groupIndex-- - : _groupIndex = groups.length - 1; - }); - } - } - } else if (event.primaryVelocity! < -200) { - if (groups.length == 1) { - Fluttertoast.showToast( - msg: s.addSomeGroups, - gravity: ToastGravity.BOTTOM, - ); - } else { - if (mounted) { - setState( - () { - (_groupIndex < groups.length - 1) - ? _groupIndex++ - : _groupIndex = 0; - }, - ); - } + onVerticalDragEnd: (event) { + if (event.primaryVelocity! > 200) { + if (groups.length == 1) { + Fluttertoast.showToast( + msg: s.addSomeGroups, + gravity: ToastGravity.BOTTOM, + ); + } else { + if (mounted) { + setState(() { + (_groupIndex != 0) + ? _groupIndex-- + : _groupIndex = groups.length - 1; + }); } } - }, - child: Column( - children: [ - SizedBox( - height: 30, - child: Row( - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: 15.0), - child: Text( - groups[_groupIndex]!.name!, - style: context.textTheme.bodyText1! - .copyWith(color: context.accentColor), - ), + } else if (event.primaryVelocity! < -200) { + if (groups.length == 1) { + Fluttertoast.showToast( + msg: s.addSomeGroups, + gravity: ToastGravity.BOTTOM, + ); + } else { + if (mounted) { + setState( + () { + (_groupIndex < groups.length - 1) + ? _groupIndex++ + : _groupIndex = 0; + }, + ); + } + } + } + }, + child: Column( + children: [ + SizedBox( + height: 30, + child: Row( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 15.0), + child: Text( + groups[_groupIndex]!.name!, + style: context.textTheme.bodyText1! + .copyWith(color: context.accentColor), ), - Spacer(), - Padding( - padding: EdgeInsets.symmetric(horizontal: 15), - child: InkWell( - onTap: () { - if (!import) { - Navigator.push( - context, - SlideLeftRoute( - page: context - .read() - .openAllPodcastDefalt! - ? PodcastList() - : PodcastManage(), - ), - ); - } - }, - onLongPress: () { - if (!import) { - Navigator.push( - context, - SlideLeftRoute(page: PodcastList()), - ); - } - }, - borderRadius: BorderRadius.circular(5), - child: Padding( - padding: const EdgeInsets.all(5.0), - child: Text( - s.homeGroupsSeeAll, - style: context.textTheme.bodyText1! - .copyWith( - color: import - ? context.primaryColorDark - : context.accentColor), + ), + Spacer(), + Padding( + padding: EdgeInsets.symmetric(horizontal: 15), + child: InkWell( + borderRadius: BorderRadius.circular(15), + onTap: () { + if (!import) { + Navigator.push( + context, + SlideLeftRoute( + page: context + .read() + .openAllPodcastDefalt! + ? PodcastList() + : PodcastManage(), + ), + ); + } + }, + onLongPress: () { + if (!import) { + Navigator.push( + context, + SlideLeftRoute(page: PodcastList()), + ); + } + }, + child: Padding( + padding: const EdgeInsets.all(5.0), + child: Text( + s.homeGroupsSeeAll, + style: + context.textTheme.bodyText1!.copyWith( + color: import + ? context.primaryColorDark + : context.accentColor, ), ), ), ), - ], - ), + ), + ], ), - Container( - height: 70, - color: context.background, - child: Row( - children: [ - _circleContainer(context), - _circleContainer(context), - _circleContainer(context) - ], - )), - ], - )), + ), + Container( + height: 70, + color: context.background, + child: Row( + children: [ + _circleContainer(context), + _circleContainer(context), + _circleContainer(context) + ], + )), + ], + ), + ), Container( height: (width - 20) / 3 + 40, - color: context.onPrimary, + color: context.background, margin: EdgeInsets.symmetric(horizontal: 15), child: Center( child: _groupIndex == 0 @@ -297,39 +299,39 @@ class _ScrollPodcastsState extends State Padding( padding: const EdgeInsets.symmetric(horizontal: 15), child: InkWell( - onTap: () { - if (!import) { - Navigator.push( - context, - SlideLeftRoute( - page: context - .read() - .openAllPodcastDefalt! - ? PodcastList() - : PodcastManage()), - ); - } - }, - onLongPress: () { - if (!import) { - Navigator.push( - context, - SlideLeftRoute(page: PodcastList()), - ); - } - }, - borderRadius: BorderRadius.circular(5), - child: Padding( - padding: const EdgeInsets.all(5.0), - child: Text( - s.homeGroupsSeeAll, - style: context.textTheme.bodyText1! - .copyWith( - color: import - ? context.primaryColorDark - : context.accentColor), - ), - )), + onTap: () { + if (!import) { + Navigator.push( + context, + SlideLeftRoute( + page: context + .read() + .openAllPodcastDefalt! + ? PodcastList() + : PodcastManage()), + ); + } + }, + onLongPress: () { + if (!import) { + Navigator.push( + context, + SlideLeftRoute(page: PodcastList()), + ); + } + }, + borderRadius: BorderRadius.circular(5), + child: Padding( + padding: const EdgeInsets.all(5.0), + child: Text( + s.homeGroupsSeeAll, + style: context.textTheme.bodyText1!.copyWith( + color: import + ? context.primaryColorDark + : context.accentColor), + ), + ), + ), ) ], ), @@ -338,7 +340,7 @@ class _ScrollPodcastsState extends State height: 70, width: width, alignment: Alignment.centerLeft, - color: context.onPrimary, + color: context.background, child: TabBar( labelPadding: EdgeInsets.fromLTRB(6.0, 5.0, 6.0, 10.0), indicator: CircleTabIndicator( @@ -370,47 +372,45 @@ class _ScrollPodcastsState extends State ), Container( height: (width - 20) / 3 + 40, - margin: const EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( color: context.background, + borderRadius: BorderRadius.circular(10), ), - child: ScrollConfiguration( - behavior: NoGrowBehavior(), - child: TabBarView( - children: groups[_groupIndex]!.podcasts.map( - (podcastLocal) { - return Container( - decoration: BoxDecoration( - color: context.brightness == Brightness.light - ? context.primaryColor - : Colors.black12), - margin: EdgeInsets.symmetric(horizontal: 5.0), - key: ObjectKey(podcastLocal.title), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Navigator.push( - context, - HidePlayerRoute( - PodcastDetail( - podcastLocal: podcastLocal, - ), - PodcastDetail( - podcastLocal: podcastLocal, - hide: true), - duration: Duration(milliseconds: 300), - )); - }, - child: PodcastPreview( - podcastLocal: podcastLocal, - ), + child: TabBarView( + children: groups[_groupIndex]!.podcasts.map( + (podcastLocal) { + return Container( + decoration: BoxDecoration( + color: context.brightness == Brightness.light + ? context.primaryColor + : Colors.black12), + margin: EdgeInsets.symmetric(horizontal: 5.0), + key: ObjectKey(podcastLocal.title), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(20), + onTap: () { + Navigator.push( + context, + HidePlayerRoute( + PodcastDetail( + podcastLocal: podcastLocal, + ), + PodcastDetail( + podcastLocal: podcastLocal, hide: true), + duration: Duration(milliseconds: 300), + ), + ); + }, + child: PodcastPreview( + podcastLocal: podcastLocal, ), ), - ); - }, - ).toList(), - ), + ), + ); + }, + ).toList(), ), ), ], @@ -494,7 +494,9 @@ class _PodcastPreviewState extends State { episodes: snapshot.data, podcastLocal: widget.podcastLocal, ) - : Padding(padding: const EdgeInsets.all(5.0)); + : Padding( + padding: const EdgeInsets.all(5.0), + ); }, ); }, @@ -561,8 +563,8 @@ class ShowEpisode extends StatelessWidget { gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( childAspectRatio: 1.5, crossAxisCount: 2, - mainAxisSpacing: 8.0, - crossAxisSpacing: 6.0, + mainAxisSpacing: 20, + crossAxisSpacing: 14, ), delegate: SliverChildBuilderDelegate( (context, index) { diff --git a/lib/home/pocast_discovery.dart b/lib/home/pocast_discovery.dart index 5ea68f6..1d9bdfd 100644 --- a/lib/home/pocast_discovery.dart +++ b/lib/home/pocast_discovery.dart @@ -27,17 +27,6 @@ class DiscoveryPageState extends State { final List _podcastList = []; Future? _searchTopPodcast; Future? _getIfHideDiscovery; - Future?> _getSearchHistory() { - final storage = KeyValueStorage(searchHistoryKey); - final history = storage.getStringList(); - return history; - } - - void backToHome() { - setState(() { - _selectedGenre = null; - }); - } @override void initState() { @@ -46,95 +35,257 @@ class DiscoveryPageState extends State { _getIfHideDiscovery = _getHideDiscovery(); } - Widget _loadTopPodcasts() => Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), color: context.primaryColor), - width: 120, - margin: EdgeInsets.fromLTRB(10, 10, 0, 10), - padding: EdgeInsets.all(4), - alignment: Alignment.topCenter, - child: Column( - children: [ - Expanded( - flex: 2, - child: Center( - child: Container( - height: 50, - width: 50, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: context.primaryColorDark, - ), - alignment: Alignment.center, - child: SizedBox( - width: 20, - height: 2, - child: LinearProgressIndicator(value: 0), - ), - ), - ), - ), - Expanded( - flex: 1, + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _getIfHideDiscovery!.then((value) => value as bool), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return Center(); + } else if (snapshot.data! || environment['apiKey'] == '') { + return SingleChildScrollView( child: Column( - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - width: 80, - height: context.textTheme.bodyText1!.fontSize, - decoration: BoxDecoration( - color: context.primaryColorDark, - borderRadius: BorderRadius.circular(4)), + _historyList(), + SizedBox( + height: 150, + child: Center( + child: Icon( + Icons.search, + size: 80, + color: Colors.grey[400], + ), + ), ), - SizedBox(height: 10), - Container( - width: 40, - height: context.textTheme.bodyText1!.fontSize, - decoration: BoxDecoration( - color: context.primaryColorDark, - borderRadius: BorderRadius.circular(4)), + SizedBox( + height: 50, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + LineIcons.microphone, + size: 30, + color: Colors.lightBlue, + ), + SizedBox(width: 50), + Icon( + LineIcons.broadcastTower, + size: 30, + color: Colors.deepPurple, + ), + SizedBox(width: 50), + Icon( + LineIcons.rssSquare, + size: 30, + color: Colors.blueGrey, + ), + ], + ), + ), + Padding( + padding: EdgeInsets.fromLTRB(50, 20, 50, 20), + child: Center( + child: Text( + context.s.searchHelper, + textAlign: TextAlign.center, + style: context.textTheme.headline6! + .copyWith(color: Colors.grey[400]), + ), + ), ), ], ), - ), - Expanded( - flex: 1, - child: Center( - child: SizedBox( - height: 32, - child: OutlinedButton( - style: OutlinedButton.styleFrom( - primary: context.accentColor.withOpacity(0.5), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(100.0), - side: BorderSide(color: Colors.grey[500]!)), - // highlightedBorderColor: Colors.grey[500], - // disabledTextColor: Colors.grey[500], - // disabledBorderColor: Colors.grey[500], + ); + } else { + return PodcastSlideup( + searchEngine: SearchEngine.listenNotes, + child: Selector( + selector: (_, searchState) => searchState.genre, + builder: (_, genre, __) => IndexedStack( + index: genre == null ? 0 : 1, + children: [ + SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _historyList(), + SizedBox(height: 8), + SizedBox( + height: 200, + child: FutureBuilder>( + future: _searchTopPodcast!.then( + (value) => value as List), + builder: (context, snapshot) { + return ScrollConfiguration( + behavior: NoGrowBehavior(), + child: ListView( + addAutomaticKeepAlives: true, + scrollDirection: Axis.horizontal, + children: snapshot.hasData + ? snapshot.data! + .map((podcast) { + return _podcastCard( + podcast, + onTap: () { + context + .read() + .selectedPodcast = + podcast; + widget.onTap!(''); + }, + ); + }).toList() + : [ + _loadTopPodcasts(), + _loadTopPodcasts(), + _loadTopPodcasts(), + _loadTopPodcasts(), + ]), + ); + }), + ), + Padding( + padding: EdgeInsets.fromLTRB(20, 10, 10, 4), + child: Text('Categories', + style: context.textTheme.headline6! + .copyWith(color: context.accentColor)), + ), + ListView( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + children: genres + .map((e) => ListTile( + contentPadding: + EdgeInsets.fromLTRB(20, 0, 20, 0), + onTap: () { + widget.onTap!(''); + context.read().setGenre = e; + }, + title: Text(e.name!, + style: context.textTheme.headline6), + )) + .toList(), + ), + SizedBox( + height: 40, + child: Center( + child: Image( + image: context.brightness == Brightness.light + ? AssetImage('assets/listennotes.png') + : AssetImage('assets/listennotes_light.png'), + height: 15, + ), + ), + ) + ], ), - child: Text(context.s.subscribe), - onPressed: () {}), + ), + genre == null ? Center() : _TopPodcastList(genre: genre), + ], ), ), - ), - ], - )); + ); + } + }, + ); + } + + Widget _loadTopPodcasts() => Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: context.primaryColor), + width: 120, + margin: EdgeInsets.fromLTRB(10, 10, 0, 10), + padding: EdgeInsets.all(4), + alignment: Alignment.topCenter, + child: Column( + children: [ + Expanded( + flex: 2, + child: Center( + child: Container( + height: 50, + width: 50, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: context.primaryColorDark, + ), + alignment: Alignment.center, + child: SizedBox( + width: 20, + height: 2, + child: LinearProgressIndicator(value: 0), + ), + ), + ), + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 80, + height: context.textTheme.bodyText1!.fontSize, + decoration: BoxDecoration( + color: context.primaryColorDark, + borderRadius: BorderRadius.circular(4)), + ), + SizedBox(height: 10), + Container( + width: 40, + height: context.textTheme.bodyText1!.fontSize, + decoration: BoxDecoration( + color: context.primaryColorDark, + borderRadius: BorderRadius.circular(4)), + ), + ], + ), + ), + Expanded( + flex: 1, + child: Center( + child: SizedBox( + height: 32, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + primary: context.accentColor.withOpacity(0.5), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(100.0), + side: BorderSide(color: Colors.grey[500]!)), + // highlightedBorderColor: Colors.grey[500], + // disabledTextColor: Colors.grey[500], + // disabledBorderColor: Colors.grey[500], + ), + child: Text(context.s.subscribe), + onPressed: () {}), + ), + ), + ), + ], + ), + ); Widget _historyList() => FutureBuilder?>( - future: _getSearchHistory(), - initialData: [], - builder: (context, snapshot) { - if (snapshot.hasData && snapshot.data!.isNotEmpty) { - final history = snapshot.data!; - return Wrap( - direction: Axis.horizontal, - children: history - .map((e) => Padding( + future: _getSearchHistory(), + initialData: [], + builder: (context, snapshot) { + if (snapshot.hasData && snapshot.data!.isNotEmpty) { + final history = snapshot.data!; + return Wrap( + direction: Axis.horizontal, + children: history + .map( + (e) => Padding( padding: const EdgeInsets.fromLTRB(8, 2, 0, 0), - child: FlatButton.icon( - color: Colors.accents[history.indexOf(e)].withAlpha(70), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(100.0), + child: TextButton.icon( + style: TextButton.styleFrom( + primary: Colors.accents[history.indexOf(e)], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(100.0), + ), ), onPressed: () => widget.onTap!(e), label: Text(e!), @@ -143,32 +294,32 @@ class DiscoveryPageState extends State { size: 20, ), ), - )) - .toList(), - ); - } - return SizedBox( - height: 0, - ); - }); + ), + ) + .toList(), + ); + } + return Center(); + }, + ); Widget _podcastCard(OnlinePodcast podcast, {VoidCallback? onTap}) { return Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: context.primaryColor, + borderRadius: BorderRadius.circular(20), + color: context.background, border: Border.all(color: context.textColor.withOpacity(0.1), width: 1)), - width: 120, - margin: EdgeInsets.fromLTRB(10, 10, 0, 10), + width: 140, + margin: EdgeInsets.fromLTRB(20, 10, 0, 10), child: Material( color: Colors.transparent, - borderRadius: BorderRadius.circular(10), + borderRadius: BorderRadius.circular(20), clipBehavior: Clip.hardEdge, child: InkWell( onTap: onTap, child: Padding( - padding: EdgeInsets.all(4.0), + padding: EdgeInsets.all(8.0), child: Column( children: [ Expanded( @@ -200,6 +351,18 @@ class DiscoveryPageState extends State { ); } + Future?> _getSearchHistory() { + final storage = KeyValueStorage(searchHistoryKey); + final history = storage.getStringList(); + return history; + } + + void backToHome() { + setState(() { + _selectedGenre = null; + }); + } + Future> _getTopPodcasts({int? page}) async { if (environment['apiKey'] == '') return []; final searchEngine = ListenNotesSearch(); @@ -222,167 +385,6 @@ class DiscoveryPageState extends State { final storage = KeyValueStorage(hidePodcastDiscoveryKey); return await storage.getBool(defaultValue: false); } - - @override - Widget build(BuildContext context) { - return FutureBuilder( - future: _getIfHideDiscovery!.then((value) => value as bool), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return Center(); - } else if (snapshot.data! || environment['apiKey'] == '') { - return ScrollConfiguration( - behavior: NoGrowBehavior(), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _historyList(), - SizedBox( - height: 150, - child: Center( - child: Icon( - Icons.search, - size: 80, - color: Colors.grey[400], - ), - ), - ), - SizedBox( - height: 50, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - LineIcons.microphone, - size: 30, - color: Colors.lightBlue, - ), - SizedBox(width: 50), - Icon( - LineIcons.broadcastTower, - size: 30, - color: Colors.deepPurple, - ), - SizedBox(width: 50), - Icon( - LineIcons.rssSquare, - size: 30, - color: Colors.blueGrey, - ), - ], - ), - ), - Padding( - padding: EdgeInsets.fromLTRB(50, 20, 50, 20), - child: Center( - child: Text( - context.s.searchHelper, - textAlign: TextAlign.center, - style: context.textTheme.headline6! - .copyWith(color: Colors.grey[400]), - ), - ), - ), - ], - ), - ), - ); - } else { - return PodcastSlideup( - searchEngine: SearchEngine.listenNotes, - child: Selector( - selector: (_, searchState) => searchState.genre, - builder: (_, genre, __) => IndexedStack( - index: genre == null ? 0 : 1, - children: [ - SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _historyList(), - SizedBox(height: 8), - SizedBox( - height: 200, - child: FutureBuilder>( - future: _searchTopPodcast!.then( - (value) => value as List), - builder: (context, snapshot) { - return ScrollConfiguration( - behavior: NoGrowBehavior(), - child: ListView( - addAutomaticKeepAlives: true, - scrollDirection: Axis.horizontal, - children: snapshot.hasData - ? snapshot.data! - .map((podcast) { - return _podcastCard( - podcast, - onTap: () { - context - .read() - .selectedPodcast = - podcast; - widget.onTap!(''); - }, - ); - }).toList() - : [ - _loadTopPodcasts(), - _loadTopPodcasts(), - _loadTopPodcasts(), - _loadTopPodcasts(), - ]), - ); - }), - ), - Padding( - padding: EdgeInsets.fromLTRB(20, 10, 10, 4), - child: Text('Categories', - style: context.textTheme.headline6! - .copyWith(color: context.accentColor)), - ), - ListView( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - children: genres - .map((e) => ListTile( - contentPadding: - EdgeInsets.fromLTRB(20, 0, 20, 0), - onTap: () { - widget.onTap!(''); - context.read().setGenre = - e; - }, - title: Text(e.name!, - style: context.textTheme.headline6), - )) - .toList(), - ), - SizedBox( - height: 40, - child: Center( - child: Image( - image: context.brightness == Brightness.light - ? AssetImage('assets/listennotes.png') - : AssetImage( - 'assets/listennotes_light.png'), - height: 15, - ), - ), - ) - ], - ), - ), - genre == null ? Center() : _TopPodcastList(genre: genre), - ], - ), - ), - ); - } - }); - } } class _TopPodcastList extends StatefulWidget { @@ -398,20 +400,6 @@ class __TopPodcastListState extends State<_TopPodcastList> { Future? _searchFuture; late bool _loading; late int _page; - Future> _getTopPodcasts( - {required Genre genre, int? page}) async { - final searchEngine = ListenNotesSearch(); - var searchResult = await searchEngine.fetchBestPodcast( - genre: genre.id, - page: page, - ); - final podcastTopList = [ - for (final p in searchResult!.podcasts!) p?.toOnlinePodcast - ]; - _podcastList.addAll(podcastTopList.cast()); - _loading = false; - return _podcastList; - } @override void initState() { @@ -462,12 +450,8 @@ class __TopPodcastListState extends State<_TopPodcastList> { children: [ Padding( padding: const EdgeInsets.only(top: 10.0, bottom: 20.0), - child: OutlinedButton( - style: OutlinedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.all(Radius.circular(100))), - ), + child: TextButton( + style: TextButton.styleFrom(), // highlightedBorderColor: context.accentColor, // splashColor: context.accentColor.withOpacity(0.5), child: _loading @@ -498,4 +482,19 @@ class __TopPodcastListState extends State<_TopPodcastList> { }, ); } + + Future> _getTopPodcasts( + {required Genre genre, int? page}) async { + final searchEngine = ListenNotesSearch(); + final searchResult = await searchEngine.fetchBestPodcast( + genre: genre.id, + page: page, + ); + final podcastTopList = [ + for (final p in searchResult!.podcasts!) p?.toOnlinePodcast + ]; + _podcastList.addAll(podcastTopList.cast()); + _loading = false; + return _podcastList; + } } diff --git a/lib/home/search_podcast.dart b/lib/home/search_podcast.dart index f0cda76..e6432dc 100644 --- a/lib/home/search_podcast.dart +++ b/lib/home/search_podcast.dart @@ -40,7 +40,7 @@ class MyHomePageDelegate extends SearchDelegate { connectTimeout: 30000, receiveTimeout: 90000, ); - var response = await Dio(options).get(url); + final response = await Dio(options).get(url); return RssFeed.parse(response.data); } catch (e) { rethrow; @@ -88,7 +88,10 @@ class MyHomePageDelegate extends SearchDelegate { child: IconButton( tooltip: context.s.back, splashRadius: 20, - icon: Icon(_getIconData(Theme.of(context).platform)), + icon: Icon( + _getIconData(Theme.of(context).platform), + color: context.textColor, + ), onPressed: () { close(context, 1); }, @@ -164,12 +167,10 @@ class MyHomePageDelegate extends SearchDelegate { switch (_searchEngine) { case SearchEngine.listenNotes: return _ListenNotesSearch(query: query); - break; case SearchEngine.podcastIndex: return _PodcastIndexSearch(query: query); default: return Center(); - break; } } } @@ -217,14 +218,14 @@ class _RssResultState extends State { @override Widget build(BuildContext context) { final s = context.s; - var items = widget.rssFeed!.items!; + final items = widget.rssFeed!.items!; return DefaultTabController( length: 2, child: Column( children: [ Container( color: context.primaryColor, - height: 140, + height: 160, child: Row( children: [ Expanded( @@ -314,8 +315,12 @@ class _RssResultState extends State { url!.launchUrl; }, style: { + 'html': Style( + padding: const EdgeInsets.symmetric(horizontal: 12), + ), 'a': Style( color: context.accentColor, + textDecoration: TextDecoration.none, ) }, shrinkWrap: true, @@ -331,13 +336,9 @@ class _RssResultState extends State { return Container( padding: const EdgeInsets.only(top: 10.0, bottom: 20.0), alignment: Alignment.center, - child: OutlinedButton( - style: OutlinedButton.styleFrom( - // highlightedBorderColor: context.accentColor, + child: TextButton( + style: TextButton.styleFrom( onSurface: context.accentColor.withOpacity(0.5), - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.all(Radius.circular(100))), ), child: Text(context.s.loadMore), onPressed: () => setState( @@ -378,18 +379,12 @@ class __SearchPopupMenuState extends State<_SearchPopupMenu> { _getSearchEngine(); } - Future _getSearchEngine() async { - final storage = KeyValueStorage(searchEngineKey); - final index = await storage.getInt(); - setState(() => _searchEngine = SearchEngine.values[index]); - widget.onSelected!(_searchEngine); - } - @override Widget build(BuildContext context) { return PopupMenuButton( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), elevation: 1, + color: context.priamryContainer, icon: SizedBox( height: 25, width: 25, @@ -437,11 +432,18 @@ class __SearchPopupMenuState extends State<_SearchPopupMenu> { ], ); } + + Future _getSearchEngine() async { + final storage = KeyValueStorage(searchEngineKey); + final index = await storage.getInt(); + setState(() => _searchEngine = SearchEngine.values[index]); + widget.onSelected!(_searchEngine); + } } class _ListenNotesSearch extends StatefulWidget { - final String? query; - _ListenNotesSearch({this.query, Key? key}) : super(key: key); + final String query; + _ListenNotesSearch({required this.query, Key? key}) : super(key: key); @override __ListenNotesSearchState createState() => __ListenNotesSearchState(); @@ -461,9 +463,9 @@ class __ListenNotesSearchState extends State<_ListenNotesSearch> { _searchFuture = _getListenNotesList(widget.query, _nextOffset); } - Future _saveHistory(String? query) async { + Future _saveHistory(String query) async { final storage = KeyValueStorage(searchHistoryKey); - final history = await (storage.getStringList() as FutureOr>); + final history = await storage.getStringList(); if (!history.contains(query)) { if (history.length >= 6) { history.removeLast(); @@ -474,7 +476,7 @@ class __ListenNotesSearchState extends State<_ListenNotesSearch> { } Future> _getListenNotesList( - String? searchText, int? nextOffset) async { + String searchText, int? nextOffset) async { if (nextOffset == 0) _saveHistory(searchText); final searchEngine = ListenNotesSearch(); var searchResult; @@ -544,12 +546,13 @@ class __ListenNotesSearchState extends State<_ListenNotesSearch> { mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.min, children: [ - OutlinedButton( - style: OutlinedButton.styleFrom( + TextButton( + style: TextButton.styleFrom( side: BorderSide(color: context.accentColor), onSurface: context.accentColor.withOpacity(0.5), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(100)), + borderRadius: BorderRadius.circular(100), + ), ), child: _loading ? SizedBox( @@ -582,7 +585,9 @@ class __ListenNotesSearchState extends State<_ListenNotesSearch> { child: Text( 'Powered by ListenNotes', style: GoogleFonts.quicksand( - color: Colors.red, textStyle: TextStyle(fontSize: 15)), + color: Colors.red, + textStyle: TextStyle(fontSize: 15), + ), ), // Image( // image: context.brightness == Brightness.light @@ -662,101 +667,102 @@ class __PodcastIndexSearchState extends State<_PodcastIndexSearch> { return PodcastSlideup( searchEngine: SearchEngine.podcastIndex, child: FutureBuilder( - future: _searchFuture.then((value) => value as List), - builder: (context, snapshot) { - if (!snapshot.hasData && widget.query != null) { + future: _searchFuture.then((value) => value as List), + builder: (context, snapshot) { + if (!snapshot.hasData && widget.query != null) { + return Container( + padding: EdgeInsets.only(top: 200), + alignment: Alignment.topCenter, + child: Platform.isIOS + ? CupertinoActivityIndicator() + : CircularProgressIndicator(), + ); + } + if (snapshot.data!.isEmpty) { + if (_loadError) { return Container( padding: EdgeInsets.only(top: 200), alignment: Alignment.topCenter, - child: Platform.isIOS - ? CupertinoActivityIndicator() - : CircularProgressIndicator(), + child: Text('Network error.', + style: context.textTheme.headline6! + .copyWith(color: Colors.red)), + ); + } else { + return Container( + padding: EdgeInsets.only(top: 200), + alignment: Alignment.topCenter, + child: Text('No result found.', + style: context.textTheme.headline6! + .copyWith(color: context.accentColor)), ); } - if (snapshot.data!.isEmpty) { - if (_loadError) { - return Container( - padding: EdgeInsets.only(top: 200), - alignment: Alignment.topCenter, - child: Text('Network error.', - style: context.textTheme.headline6! - .copyWith(color: Colors.red)), - ); - } else { - return Container( - padding: EdgeInsets.only(top: 200), - alignment: Alignment.topCenter, - child: Text('No result found.', - style: context.textTheme.headline6! - .copyWith(color: context.accentColor)), - ); - } - } - var content = snapshot.data!; - return CustomScrollView( - slivers: [ - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - return SearchResult(onlinePodcast: content[index]); - }, - childCount: content.length, - ), + } + var content = snapshot.data!; + return CustomScrollView( + slivers: [ + SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + return SearchResult(onlinePodcast: content[index]); + }, + childCount: content.length, ), - SliverToBoxAdapter( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.min, - children: [ - OutlinedButton( - style: OutlinedButton.styleFrom( - side: BorderSide(color: context.accentColor), - onSurface: context.accentColor.withOpacity(0.5), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(100)), - ), - child: _loading - ? SizedBox( - height: 20, - width: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - )) - : Text(context.s.loadMore), - onPressed: () => _loading - ? null - : setState( - () { - _loading = true; - _limit += 10; - _searchFuture = _getPodcatsIndexList( - widget.query!, - limit: _limit); - }, + ), + SliverToBoxAdapter( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, + children: [ + TextButton( + style: TextButton.styleFrom( + side: BorderSide(color: context.accentColor), + onSurface: context.accentColor.withOpacity(0.5), + ), + child: _loading + ? SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + strokeWidth: 2, ), - ) - ], - ), + ) + : Text(context.s.loadMore), + onPressed: () => _loading + ? null + : setState( + () { + _loading = true; + _limit += 10; + _searchFuture = _getPodcatsIndexList( + widget.query!, + limit: _limit); + }, + ), + ) + ], ), - SliverToBoxAdapter( - child: Padding( - padding: EdgeInsets.symmetric(vertical: 10), - child: Center( - child: Text( - 'Powered by PODCASTINDEX', - style: GoogleFonts.quicksand( - color: Colors.red, - textStyle: TextStyle(fontSize: 15)), - ), - ) - // Image( - // image: AssetImage('assets/podcastindex.png'), - // height: 15, - // ), - )) - ], - ); - }), + ), + SliverToBoxAdapter( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 10), + child: Center( + child: Text( + 'Powered by PODCASTINDEX', + style: GoogleFonts.quicksand( + color: Colors.red, + textStyle: TextStyle(fontSize: 15)), + ), + ) + // Image( + // image: AssetImage('assets/podcastindex.png'), + // height: 15, + // ), + ), + ) + ], + ); + }, + ), ); } } @@ -997,12 +1003,10 @@ class _SearchResultDetailState extends State padding: const EdgeInsets.only(top: 10.0, bottom: 20.0), alignment: Alignment.center, child: SizedBox( - child: OutlinedButton( - style: OutlinedButton.styleFrom( + child: TextButton( + style: TextButton.styleFrom( side: BorderSide(color: context.accentColor), onSurface: context.accentColor.withOpacity(0.5), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(100)), ), child: _loading ? SizedBox( diff --git a/lib/main.dart b/lib/main.dart index 6b159a1..d3d3ee3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -44,6 +44,10 @@ Future main() async { ), ); await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( + systemNavigationBarColor: Colors.transparent, + statusBarColor: Colors.transparent, + )); await SystemChrome.setPreferredOrientations( [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); } diff --git a/lib/podcasts/custom_tabview.dart b/lib/podcasts/custom_tabview.dart index 307c659..bce96ce 100644 --- a/lib/podcasts/custom_tabview.dart +++ b/lib/podcasts/custom_tabview.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:tsacdop/util/extension_helper.dart'; class CustomTabView extends StatefulWidget { final int itemCount; @@ -108,7 +109,7 @@ class _CustomTabsState extends State unselectedLabelColor: Colors.grey[700], indicator: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(15)), - color: Theme.of(context).accentColor, + color: context.accentColor, ), tabs: List.generate( widget.itemCount, diff --git a/lib/podcasts/podcast_detail.dart b/lib/podcasts/podcast_detail.dart index 8fa2eef..466f0df 100644 --- a/lib/podcasts/podcast_detail.dart +++ b/lib/podcasts/podcast_detail.dart @@ -122,12 +122,12 @@ class _PodcastDetailState extends State { ); } if (result > 0) { - var autoDownload = await _dbHelper.getAutoDownload(podcastLocal.id); + final autoDownload = await _dbHelper.getAutoDownload(podcastLocal.id); if (autoDownload) { - var downloader = Provider.of(context, listen: false); - var result = await Connectivity().checkConnectivity(); - var autoDownloadStorage = KeyValueStorage(autoDownloadNetworkKey); - var autoDownloadNetwork = await autoDownloadStorage.getInt(); + final downloader = Provider.of(context, listen: false); + final result = await Connectivity().checkConnectivity(); + final autoDownloadStorage = KeyValueStorage(autoDownloadNetworkKey); + final autoDownloadNetwork = await autoDownloadStorage.getInt(); if (autoDownloadNetwork == 1) { var episodes = await _dbHelper.getNewEpisodes(podcastLocal.id); // For safety @@ -232,31 +232,32 @@ class _PodcastDetailState extends State { VoidCallback? onTap, required Color backgroundColor}) { return Container( - padding: EdgeInsets.fromLTRB(5, 10, 5, 0), - width: 60.0, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - InkWell( - borderRadius: BorderRadius.circular(20), - onTap: onTap, - child: CircleAvatar( - radius: 20, - child: child, - backgroundColor: backgroundColor.withOpacity(0.5), - ), + padding: EdgeInsets.fromLTRB(5, 10, 5, 0), + width: 60.0, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + borderRadius: BorderRadius.circular(20), + onTap: onTap, + child: CircleAvatar( + radius: 20, + child: child, + backgroundColor: backgroundColor.withOpacity(0.5), ), - SizedBox(height: 4), - Text( - title, - style: context.textTheme.subtitle2, - textAlign: TextAlign.center, - maxLines: 2, - overflow: TextOverflow.fade, - ), - ], - )); + ), + SizedBox(height: 4), + Text( + title, + style: context.textTheme.subtitle2, + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.fade, + ), + ], + ), + ); } Widget _hostsList(BuildContext context, PodcastLocal podcastLocal) { @@ -673,11 +674,7 @@ class _PodcastDetailState extends State { final s = context.s; return AnnotatedRegion( value: SystemUiOverlayStyle( - statusBarColor: color, - statusBarIconBrightness: Brightness.dark, - systemNavigationBarColor: context.primaryColor, - systemNavigationBarIconBrightness: context.iconBrightness, - ), + statusBarColor: color, statusBarIconBrightness: Brightness.light), child: WillPopScope( onWillPop: () { if (_playerKey.currentState != null && @@ -690,7 +687,6 @@ class _PodcastDetailState extends State { }, child: Scaffold( body: SafeArea( - top: false, child: RefreshIndicator( key: _refreshIndicatorKey, displacement: context.paddingTop + 40, @@ -751,6 +747,7 @@ class _PodcastDetailState extends State { ), ], elevation: 0, + scrolledUnderElevation: 0, iconTheme: IconThemeData( color: Colors.white, ), @@ -1021,17 +1018,6 @@ class AboutPodcast extends StatefulWidget { class _AboutPodcastState extends State { late String _description; late bool _load; - void getDescription(String? id) async { - var dbHelper = DBHelper(); - var description = await dbHelper.getFeedDescription(id); - if (description == null || description.isEmpty) { - _description = ''; - } else { - var doc = parse(description); - _description = parse(doc.body!.text).documentElement!.text; - } - if (mounted) setState(() => _load = true); - } @override void initState() { @@ -1042,75 +1028,30 @@ class _AboutPodcastState extends State { @override Widget build(BuildContext context) { - return !_load - ? Center() - : Linkify( - text: _description, - onOpen: (link) { - link.url!.launchUrl; - }, - linkStyle: TextStyle( - color: Theme.of(context).accentColor, - decoration: TextDecoration.underline, - textBaseline: TextBaseline.ideographic), - ); - // LayoutBuilder( - // builder: (context, size) { - // final span = TextSpan(text: _description); - // final tp = TextPainter( - // text: span, maxLines: 3, textDirection: TextDirection.ltr); - // tp.layout(maxWidth: size.maxWidth); + if (_load) + return Linkify( + text: _description, + onOpen: (link) { + link.url!.launchUrl; + }, + linkStyle: TextStyle( + color: context.accentColor, + decoration: TextDecoration.underline, + textBaseline: TextBaseline.ideographic), + ); + return Center(); + } - // if (tp.didExceedMaxLines) { - // return GestureDetector( - // onTap: () { - // setState(() => _expand = !_expand); - // }, - // child: !_expand - // ? Column( - // mainAxisAlignment: MainAxisAlignment.start, - // mainAxisSize: MainAxisSize.min, - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Linkify( - // onOpen: (link) { - // link.url.launchUrl; - // }, - // text: _description, - // linkStyle: TextStyle( - // color: Theme.of(context).accentColor, - // decoration: TextDecoration.underline, - // textBaseline: TextBaseline.ideographic), - // maxLines: 3, - // overflow: TextOverflow.ellipsis, - // ), - // ], - // ) - // : Linkify( - // onOpen: (link) { - // link.url.launchUrl; - // }, - // text: _description, - // linkStyle: TextStyle( - // color: Theme.of(context).accentColor, - // decoration: TextDecoration.underline, - // textBaseline: TextBaseline.ideographic), - // ), - // ); - // } else { - // return Linkify( - // text: _description, - // onOpen: (link) { - // link.url.launchUrl; - // }, - // linkStyle: TextStyle( - // color: Theme.of(context).accentColor, - // decoration: TextDecoration.underline, - // textBaseline: TextBaseline.ideographic), - // ); - // } - // }, - // ); + void getDescription(String? id) async { + final dbHelper = DBHelper(); + final description = await dbHelper.getFeedDescription(id); + if (description == null || description.isEmpty) { + _description = ''; + } else { + final doc = parse(description); + _description = parse(doc.body!.text).documentElement!.text; + } + if (mounted) setState(() => _load = true); } } @@ -1156,8 +1097,7 @@ class _SearchEpisodeState extends State { titlePadding: const EdgeInsets.all(20), actionsPadding: EdgeInsets.zero, actions: [ - FlatButton( - splashColor: context.accentColor.withAlpha(70), + TextButton( onPressed: () => Navigator.of(context).pop(), child: Text( s.cancel, @@ -1165,8 +1105,7 @@ class _SearchEpisodeState extends State { style: TextStyle(color: Colors.grey[600]), ), ), - FlatButton( - splashColor: context.accentColor.withAlpha(70), + TextButton( onPressed: () { if ((_query ?? '').isNotEmpty) { widget.onSearch!(_query); diff --git a/lib/podcasts/podcast_group.dart b/lib/podcasts/podcast_group.dart index b8e6414..d2ff093 100644 --- a/lib/podcasts/podcast_group.dart +++ b/lib/podcasts/podcast_group.dart @@ -85,45 +85,6 @@ class __PodcastCardState extends State<_PodcastCard> int? _seconds; int? _skipSeconds; - Future _getSkipSecond(String? id) async { - var dbHelper = DBHelper(); - var seconds = await dbHelper.getSkipSecondsStart(id); - _skipSeconds = seconds; - return seconds; - } - - _saveSkipSeconds(String? id, int? seconds) async { - var dbHelper = DBHelper(); - await dbHelper.saveSkipSecondsStart(id, seconds); - } - - _setAutoDownload(String? id, bool boo) async { - var permission = await _checkPermmison(); - if (permission) { - var dbHelper = DBHelper(); - await dbHelper.saveAutoDownload(id, boo: boo); - } - } - - Future _getAutoDownload(String? id) async { - var dbHelper = DBHelper(); - return await dbHelper.getAutoDownload(id); - } - - 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; - } - } - @override void initState() { super.initState(); @@ -134,43 +95,20 @@ class __PodcastCardState extends State<_PodcastCard> _controller = AnimationController(vsync: this, duration: Duration(milliseconds: 300)); _animation = Tween(begin: 0.0, end: 1.0).animate(_controller) - ..addListener(() { - setState(() { - _value = _animation.value; - }); - }); - } - - Widget _buttonOnMenu( - {required Widget icon, - VoidCallback? onTap, - required String tooltip}) => - Material( - color: Colors.transparent, - child: InkWell( - onTap: onTap, - child: Container( - height: 50.0, - padding: EdgeInsets.symmetric(horizontal: 5.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: icon, - ), - Text(tooltip, style: context.textTheme.subtitle2), - ], - )), - ), + ..addListener( + () { + setState(() { + _value = _animation.value; + }); + }, ); + } @override Widget build(BuildContext context) { final c = widget.podcastLocal!.backgroudColor(context); final s = context.s; - var groupList = context.watch(); + final groupList = context.watch(); _belongGroups = groupList.getPodcastGroup(widget.podcastLocal!.id); return Column( mainAxisSize: MainAxisSize.min, @@ -398,9 +336,7 @@ class __PodcastCardState extends State<_PodcastCard> _seconds = value.inSeconds, ), actions: [ - FlatButton( - splashColor: context.accentColor - .withAlpha(70), + TextButton( onPressed: () { Navigator.of(context).pop(); _seconds = 0; @@ -411,9 +347,7 @@ class __PodcastCardState extends State<_PodcastCard> color: Colors.grey[600]), ), ), - FlatButton( - splashColor: context.accentColor - .withAlpha(70), + TextButton( onPressed: () { Navigator.of(context).pop(); _saveSkipSeconds( @@ -431,44 +365,42 @@ class __PodcastCardState extends State<_PodcastCard> }); }), _buttonOnMenu( - icon: Icon( - Icons.delete, - color: Colors.red, - size: _value == 0 ? 1 : 20 * _value!, - ), - tooltip: s.remove, - onTap: () { - generalDialog( - context, - title: Text(s.removeConfirm), - content: Text(s.removePodcastDes), - actions: [ - FlatButton( - splashColor: - context.accentColor.withAlpha(70), - onPressed: () => - Navigator.of(context).pop(), - child: Text( - s.cancel, - style: TextStyle( - color: Colors.grey[600]), - ), + icon: Icon( + Icons.delete, + color: Colors.red, + size: _value == 0 ? 1 : 20 * _value!, + ), + tooltip: s.remove, + onTap: () { + generalDialog( + context, + title: Text(s.removeConfirm), + content: Text(s.removePodcastDes), + actions: [ + TextButton( + onPressed: () => + Navigator.of(context).pop(), + child: Text( + s.cancel, + style: + TextStyle(color: Colors.grey[600]), ), - FlatButton( - splashColor: Colors.red.withAlpha(70), - onPressed: () { - groupList.removePodcast( - widget.podcastLocal!); - Navigator.of(context).pop(); - }, - child: Text( - s.confirm, - style: TextStyle(color: Colors.red), - ), - ) - ], - ); - }), + ), + TextButton( + onPressed: () { + groupList.removePodcast( + widget.podcastLocal!); + Navigator.of(context).pop(); + }, + child: Text( + s.confirm, + style: TextStyle(color: Colors.red), + ), + ) + ], + ); + }, + ), ], ), ), @@ -477,6 +409,71 @@ class __PodcastCardState extends State<_PodcastCard> ], ); } + + Widget _buttonOnMenu( + {required Widget icon, + VoidCallback? onTap, + required String tooltip}) => + Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + child: Container( + height: 50.0, + padding: EdgeInsets.symmetric(horizontal: 5.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: icon, + ), + Text(tooltip, style: context.textTheme.subtitle2), + ], + ), + ), + ), + ); + + Future _getSkipSecond(String? id) async { + final dbHelper = DBHelper(); + final seconds = await dbHelper.getSkipSecondsStart(id); + _skipSeconds = seconds; + return seconds; + } + + _saveSkipSeconds(String? id, int? seconds) async { + final dbHelper = DBHelper(); + await dbHelper.saveSkipSecondsStart(id, seconds); + } + + _setAutoDownload(String? id, bool boo) async { + final permission = await _checkPermmison(); + if (permission) { + final dbHelper = DBHelper(); + await dbHelper.saveAutoDownload(id, boo: boo); + } + } + + Future _getAutoDownload(String? id) async { + final dbHelper = DBHelper(); + return await dbHelper.getAutoDownload(id); + } + + Future _checkPermmison() async { + final permission = await Permission.storage.status; + if (permission != PermissionStatus.granted) { + final permissions = await [Permission.storage].request(); + if (permissions[Permission.storage] == PermissionStatus.granted) { + return true; + } else { + return false; + } + } else { + return true; + } + } } class RenameGroup extends StatefulWidget { @@ -511,7 +508,7 @@ class _RenameGroupState extends State { final s = context.s; return AnnotatedRegion( value: SystemUiOverlayStyle( - statusBarIconBrightness: Brightness.light, + statusBarColor: Colors.transparent, systemNavigationBarColor: Theme.of(context).brightness == Brightness.light ? Color.fromRGBO(113, 113, 113, 1) @@ -519,27 +516,28 @@ class _RenameGroupState extends State { ), child: AlertDialog( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(10))), + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + ), elevation: 1, contentPadding: EdgeInsets.symmetric(horizontal: 20), titlePadding: EdgeInsets.all(20), actionsPadding: EdgeInsets.zero, actions: [ - FlatButton( - splashColor: context.accentColor.withAlpha(70), + TextButton( onPressed: () => Navigator.of(context).pop(), child: Text( s.cancel, style: TextStyle(color: Colors.grey[600]), ), ), - FlatButton( - splashColor: context.accentColor.withAlpha(70), + TextButton( onPressed: () async { if (list.contains(_newName)) { setState(() => _error = 1); } else { - var newGroup = PodcastGroup(_newName, + final newGroup = PodcastGroup(_newName, color: widget.group!.color, id: widget.group!.id, podcastList: widget.group!.podcastList); @@ -547,12 +545,16 @@ class _RenameGroupState extends State { Navigator.of(context).pop(); } }, - child: Text(s.confirm, - style: TextStyle(color: Theme.of(context).accentColor)), + child: Text( + s.confirm, + style: TextStyle(color: context.accentColor), + ), ) ], - title: - SizedBox(width: context.width - 160, child: Text(s.editGroupName)), + title: SizedBox( + width: context.width - 160, + child: Text(s.editGroupName), + ), content: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -578,7 +580,7 @@ class _RenameGroupState extends State { _newName = value; }, ), - Container( + Align( alignment: Alignment.centerLeft, child: (_error == 1) ? Text( diff --git a/lib/podcasts/podcast_manage.dart b/lib/podcasts/podcast_manage.dart index 4894f15..8a8110a 100644 --- a/lib/podcasts/podcast_manage.dart +++ b/lib/podcasts/podcast_manage.dart @@ -42,7 +42,7 @@ class _PodcastManageState extends State _menuValue = 0; _index = 0; _menuController = AnimationController( - vsync: this, duration: const Duration(milliseconds: 150)); + vsync: this, duration: const Duration(milliseconds: 300)); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 500)); _animation = Tween(begin: 0.0, end: 1.0).animate(_controller) @@ -51,8 +51,8 @@ class _PodcastManageState extends State setState(() => _fraction = _animation.value); } }); - _menuAnimation = Tween(begin: 0.0, end: 1.0).animate( - CurvedAnimation(parent: _menuController, curve: Curves.elasticInOut)) + _menuAnimation = Tween(begin: 0.0, end: 1.0) + .animate(CurvedAnimation(parent: _menuController, curve: Curves.ease)) ..addListener(() { if (mounted) setState(() => _menuValue = _menuAnimation.value); }); @@ -77,6 +77,274 @@ class _PodcastManageState extends State super.dispose(); } + @override + Widget build(BuildContext context) { + final s = context.s; + return AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarColor: context.priamryContainer, + systemNavigationBarColor: context.background, + ), + child: Scaffold( + appBar: AppBar( + backgroundColor: context.priamryContainer, + title: Text(context.s.groups(2)), + leading: CustomBackButton(), + systemOverlayStyle: SystemUiOverlayStyle( + statusBarColor: context.priamryContainer, + ), + actions: [ + featureDiscoveryOverlay( + context, + featureId: addGroupFeature, + tapTarget: Icon(Icons.add), + title: s.featureDiscoveryGroup, + backgroundColor: Colors.cyan[600], + description: s.featureDiscoveryGroupDes, + buttonColor: Colors.cyan[500], + child: IconButton( + splashRadius: 20, + onPressed: () => showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: MaterialLocalizations.of(context) + .modalBarrierDismissLabel, + barrierColor: Colors.black54, + transitionDuration: const Duration(milliseconds: 200), + pageBuilder: (context, animaiton, secondaryAnimation) => + AddGroup()), + icon: Icon(Icons.add_circle_outline)), + ), + Selector( + selector: (_, setting) => setting.openAllPodcastDefalt, + builder: (_, data, __) { + return !data! + ? IconButton( + splashRadius: 20, + onPressed: () => Navigator.push( + context, ScaleRoute(page: PodcastList())), + icon: Icon(Icons.all_out)) + : Center(); + }) + // _OrderMenu(), + ], + ), + body: SafeArea( + child: WillPopScope( + onWillPop: () async { + context.read().clearOrderChanged(); + return true; + }, + child: Consumer( + builder: (_, groupList, __) { + // var _isLoading = groupList.isLoading; + final _groups = groupList.groups; + if (_groups.isEmpty) return Center(); + return Stack( + children: [ + ColoredBox( + color: context.priamryContainer, + child: CustomTabView( + itemCount: _groups.length, + tabBuilder: (context, index) => Tab( + child: Container( + height: 50.0, + padding: EdgeInsets.symmetric(horizontal: 20.0), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + ), + child: Text( + _groups[index]!.name!, + ), + ), + ), + pageBuilder: (context, index) => + featureDiscoveryOverlay( + context, + featureId: configurePodcast, + tapTarget: Text(s.podcast(1)), + title: s.featureDiscoveryGroupPodcast, + backgroundColor: Colors.cyan[600], + buttonColor: Colors.cyan[500], + description: s.featureDiscoveryGroupPodcastDes, + child: PodcastGroupList( + group: _groups[index], + key: ValueKey(_groups[index]!.name), + ), + ), + onPositionChange: (value) => + // setState(() => + _index = value, + ), + ), + if (_showSetting) + Positioned.fill( + top: 50, + child: GestureDetector( + onTap: () async { + await _menuController.reverse(); + if (mounted) { + setState(() => _showSetting = false); + } + }, + child: Container( + color: context.background.withOpacity( + 0.8 * math.min(_menuController.value * 2, 1.0)), + ), + ), + ), + Positioned( + right: 30, + bottom: 30, + child: _saveButton(), + ), + if (_showSetting) + Positioned( + right: 100 * _menuValue - 70, + bottom: 100, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + _menuController.reverse(); + setState(() => _showSetting = false); + _index == 0 + ? Fluttertoast.showToast( + msg: s.toastHomeGroupNotSupport, + gravity: ToastGravity.BOTTOM, + ) + : showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: + MaterialLocalizations.of(context) + .modalBarrierDismissLabel, + barrierColor: Colors.black54, + transitionDuration: + const Duration(milliseconds: 300), + pageBuilder: (context, animaiton, + secondaryAnimation) => + RenameGroup( + group: _groups[_index!], + )); + }, + child: Container( + height: 30.0, + decoration: BoxDecoration( + color: Colors.grey[700], + borderRadius: + BorderRadius.circular(10.0)), + padding: EdgeInsets.symmetric(horizontal: 10), + child: Row( + children: [ + Icon( + Icons.text_fields, + color: Colors.white, + size: 15.0, + ), + Padding( + padding: EdgeInsets.symmetric( + horizontal: 5.0), + ), + Text(context.s.editGroupName, + style: + TextStyle(color: Colors.white)), + ], + ), + ), + ), + ), + SizedBox(height: 20), + Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + _menuController.reverse(); + setState(() => _showSetting = false); + _index == 0 + ? Fluttertoast.showToast( + msg: s.toastHomeGroupNotSupport, + gravity: ToastGravity.BOTTOM, + ) + : generalDialog( + context, + title: Text(s.removeConfirm), + content: Text(s.groupRemoveConfirm), + actions: [ + TextButton( + onPressed: () => + Navigator.of(context).pop(), + child: Text( + context.s.cancel, + style: TextStyle( + color: Colors.grey[600]), + ), + ), + TextButton( + onPressed: () { + if (_index == + groupList.groups.length - + 1) { + setState(() { + _index = _index! - 1; + }); + groupList.delGroup( + _groups[_index! + 1]!); + } else { + groupList.delGroup( + _groups[_index!]!); + } + Navigator.of(context).pop(); + }, + child: Text( + context.s.confirm, + style: TextStyle( + color: Colors.red), + ), + ) + ], + ); + }, + child: Container( + height: 30, + decoration: BoxDecoration( + color: Colors.grey[700], + borderRadius: + BorderRadius.circular(10.0)), + padding: EdgeInsets.symmetric(horizontal: 10), + child: Row( + children: [ + Icon( + Icons.delete, + color: Colors.red, + size: 15.0, + ), + SizedBox(width: 10), + Text(s.remove, + style: TextStyle(color: Colors.red)), + ], + ), + ), + ), + ), + ], + ), + ), + ], + ); + }, + ), + ), + ), + ), + ); + } + Widget _saveButton() { final s = context.s; return Consumer( @@ -150,288 +418,6 @@ class _PodcastManageState extends State }, ); } - - @override - Widget build(BuildContext context) { - final s = context.s; - return AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarIconBrightness: context.brightness, - systemNavigationBarColor: context.primaryColor, - systemNavigationBarIconBrightness: context.iconBrightness, - // statusBarColor: Theme.of(context).primaryColor, - ), - child: Scaffold( - appBar: AppBar( - title: Text(context.s.groups(2)), - leading: CustomBackButton(), - actions: [ - featureDiscoveryOverlay( - context, - featureId: addGroupFeature, - tapTarget: Icon(Icons.add), - title: s.featureDiscoveryGroup, - backgroundColor: Colors.cyan[600], - description: s.featureDiscoveryGroupDes, - buttonColor: Colors.cyan[500], - child: IconButton( - splashRadius: 20, - onPressed: () => showGeneralDialog( - context: context, - barrierDismissible: true, - barrierLabel: MaterialLocalizations.of(context) - .modalBarrierDismissLabel, - barrierColor: Colors.black54, - transitionDuration: const Duration(milliseconds: 200), - pageBuilder: (context, animaiton, secondaryAnimation) => - AddGroup()), - icon: Icon(Icons.add_circle_outline)), - ), - Selector( - selector: (_, setting) => setting.openAllPodcastDefalt, - builder: (_, data, __) { - return !data! - ? IconButton( - splashRadius: 20, - onPressed: () => Navigator.push( - context, ScaleRoute(page: PodcastList())), - icon: Icon(Icons.all_out)) - : Center(); - }) - // _OrderMenu(), - ], - ), - body: WillPopScope( - onWillPop: () async { - context.read().clearOrderChanged(); - return true; - }, - child: Consumer( - builder: (_, groupList, __) { - // var _isLoading = groupList.isLoading; - var _groups = groupList.groups; - return _groups.isEmpty - ? Center() - : Stack( - children: [ - Container( - color: context.background, - child: CustomTabView( - itemCount: _groups.length, - tabBuilder: (context, index) => Tab( - child: Container( - height: 30.0, - padding: - EdgeInsets.symmetric(horizontal: 10.0), - alignment: Alignment.center, - decoration: BoxDecoration( - // color: Colors.grey[600].withOpacity(0.3), - borderRadius: BorderRadius.circular(15), - ), - child: Text( - _groups[index]!.name!, - )), - ), - pageBuilder: (context, index) => - featureDiscoveryOverlay( - context, - featureId: configurePodcast, - tapTarget: Text(s.podcast(1)), - title: s.featureDiscoveryGroupPodcast, - backgroundColor: Colors.cyan[600], - buttonColor: Colors.cyan[500], - description: s.featureDiscoveryGroupPodcastDes, - child: PodcastGroupList( - group: _groups[index], - key: ValueKey(_groups[index]!.name), - ), - ), - onPositionChange: (value) => - // setState(() => - _index = value, - ), - ), - if (_showSetting) - Positioned.fill( - top: 50, - child: GestureDetector( - onTap: () async { - await _menuController.reverse(); - if (mounted) { - setState(() => _showSetting = false); - } - }, - child: Container( - color: context.background.withOpacity(0.8 * - math.min(_menuController.value * 2, 1.0)), - ), - ), - ), - Positioned( - right: 30, - bottom: 30, - child: _saveButton(), - ), - if (_showSetting) - Positioned( - right: 100 * _menuValue - 70, - bottom: 100, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - _menuController.reverse(); - setState(() => _showSetting = false); - _index == 0 - ? Fluttertoast.showToast( - msg: s.toastHomeGroupNotSupport, - gravity: ToastGravity.BOTTOM, - ) - : showGeneralDialog( - context: context, - barrierDismissible: true, - barrierLabel: - MaterialLocalizations.of( - context) - .modalBarrierDismissLabel, - barrierColor: Colors.black54, - transitionDuration: - const Duration( - milliseconds: 300), - pageBuilder: (context, animaiton, - secondaryAnimation) => - RenameGroup( - group: _groups[_index!], - )); - }, - child: Container( - height: 30.0, - decoration: BoxDecoration( - color: Colors.grey[700], - borderRadius: - BorderRadius.circular(10.0)), - padding: - EdgeInsets.symmetric(horizontal: 10), - child: Row( - children: [ - Icon( - Icons.text_fields, - color: Colors.white, - size: 15.0, - ), - Padding( - padding: EdgeInsets.symmetric( - horizontal: 5.0), - ), - Text(context.s.editGroupName, - style: TextStyle( - color: Colors.white)), - ], - ), - ), - ), - ), - SizedBox(height: 20), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - _menuController.reverse(); - setState(() => _showSetting = false); - _index == 0 - ? Fluttertoast.showToast( - msg: s.toastHomeGroupNotSupport, - gravity: ToastGravity.BOTTOM, - ) - : generalDialog( - context, - title: Text(s.removeConfirm), - content: - Text(s.groupRemoveConfirm), - actions: [ - FlatButton( - splashColor: context - .accentColor - .withAlpha(70), - onPressed: () => - Navigator.of(context) - .pop(), - child: Text( - context.s.cancel, - style: TextStyle( - color: - Colors.grey[600]), - ), - ), - FlatButton( - splashColor: context - .accentColor - .withAlpha(70), - onPressed: () { - if (_index == - groupList - .groups.length - - 1) { - setState(() { - _index = _index! - 1; - }); - groupList.delGroup( - _groups[ - _index! + 1]!); - } else { - groupList.delGroup( - _groups[_index!]!); - } - Navigator.of(context).pop(); - }, - child: Text( - context.s.confirm, - style: TextStyle( - color: Colors.red), - ), - ) - ], - ); - }, - child: Container( - height: 30, - decoration: BoxDecoration( - color: Colors.grey[700], - borderRadius: - BorderRadius.circular(10.0)), - padding: - EdgeInsets.symmetric(horizontal: 10), - child: Row( - children: [ - Icon( - Icons.delete, - color: Colors.red, - size: 15.0, - ), - SizedBox(width: 10), - Text(s.remove, - style: - TextStyle(color: Colors.red)), - ], - ), - ), - ), - ), - ], - ), - ), - ], - ); - }, - ), - ), - ), - ); - } } class _OrderMenu extends StatelessWidget { @@ -495,78 +481,81 @@ class _AddGroupState extends State { List list = groupList.groups.map((e) => e!.name).toList(); return AnnotatedRegion( value: SystemUiOverlayStyle( - statusBarIconBrightness: Brightness.light, + statusBarColor: Colors.transparent, systemNavigationBarColor: Theme.of(context).brightness == Brightness.light ? Color.fromRGBO(113, 113, 113, 1) : Color.fromRGBO(5, 5, 5, 1), ), - child: AlertDialog( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), - elevation: 1, - contentPadding: EdgeInsets.symmetric(horizontal: 20), - titlePadding: EdgeInsets.all(20), - actionsPadding: EdgeInsets.zero, - actions: [ - FlatButton( - splashColor: context.accentColor.withAlpha(70), - onPressed: () => Navigator.of(context).pop(), - child: Text( - s.cancel, - style: TextStyle(color: Colors.grey[600]), - ), + child: SafeArea( + top: false, + child: AlertDialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), ), - FlatButton( - splashColor: context.accentColor.withAlpha(70), - onPressed: () async { - if (list.contains(_newGroup)) { - setState(() => _error = 1); - } else { - groupList.addGroup(PodcastGroup(_newGroup)); - Navigator.of(context).pop(); - } - }, - child: - Text(s.confirm, style: TextStyle(color: context.accentColor)), - ) - ], - title: SizedBox(width: context.width - 160, child: Text(s.newGroup)), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextField( - decoration: InputDecoration( - contentPadding: EdgeInsets.symmetric(horizontal: 10), - hintText: s.newGroup, - hintStyle: TextStyle(fontSize: 18), - filled: true, - focusedBorder: UnderlineInputBorder( - borderSide: - BorderSide(color: context.accentColor, width: 2.0), - ), - enabledBorder: UnderlineInputBorder( - borderSide: - BorderSide(color: context.accentColor, width: 2.0), - ), + elevation: 1, + contentPadding: EdgeInsets.symmetric(horizontal: 20), + titlePadding: EdgeInsets.all(20), + actionsPadding: EdgeInsets.zero, + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text( + s.cancel, + style: TextStyle(color: Colors.grey[600]), ), - cursorRadius: Radius.circular(2), - autofocus: true, - maxLines: 1, - controller: _controller, - onChanged: (value) { - _newGroup = value; + ), + TextButton( + onPressed: () async { + if (list.contains(_newGroup)) { + setState(() => _error = 1); + } else { + groupList.addGroup(PodcastGroup(_newGroup)); + Navigator.of(context).pop(); + } }, - ), - Container( - alignment: Alignment.centerLeft, - child: (_error == 1) - ? Text( - s.groupExisted, - style: TextStyle(color: Colors.red[400]), - ) - : Center(), - ), + child: + Text(s.confirm, style: TextStyle(color: context.accentColor)), + ) ], + title: SizedBox(width: context.width - 160, child: Text(s.newGroup)), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + decoration: InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 10), + hintText: s.newGroup, + hintStyle: TextStyle(fontSize: 18), + filled: true, + focusedBorder: UnderlineInputBorder( + borderSide: + BorderSide(color: context.accentColor, width: 2.0), + ), + enabledBorder: UnderlineInputBorder( + borderSide: + BorderSide(color: context.accentColor, width: 2.0), + ), + ), + cursorRadius: Radius.circular(2), + autofocus: true, + maxLines: 1, + controller: _controller, + onChanged: (value) { + _newGroup = value; + }, + ), + Container( + alignment: Alignment.centerLeft, + child: (_error == 1) + ? Text( + s.groupExisted, + style: TextStyle(color: Colors.red[400]), + ) + : Center(), + ), + ], + ), ), ), ); diff --git a/lib/podcasts/podcast_settings.dart b/lib/podcasts/podcast_settings.dart index 79b1027..4611c82 100644 --- a/lib/podcasts/podcast_settings.dart +++ b/lib/podcasts/podcast_settings.dart @@ -52,153 +52,6 @@ class _PodcastSettingState extends State { _showEndTimePicker = false; } - Future _setAutoDownload(bool boo) async { - var permission = await _checkPermmison(); - if (permission) { - await _dbHelper.saveAutoDownload(widget.podcastLocal!.id, boo: boo); - } - if (mounted) setState(() {}); - } - - Future _setNeverUpdate(bool boo) async { - await _dbHelper.saveNeverUpdate(widget.podcastLocal!.id, boo: boo); - if (mounted) setState(() {}); - } - - Future _setHideNewMark(bool boo) async { - await _dbHelper.saveHideNewMark(widget.podcastLocal!.id, boo: boo); - if (mounted) setState(() {}); - } - - Future _saveSkipSecondsStart(int? seconds) async { - await _dbHelper.saveSkipSecondsStart(widget.podcastLocal!.id, seconds); - } - - Future _saveSkipSecondsEnd(int seconds) async { - await _dbHelper.saveSkipSecondsEnd(widget.podcastLocal!.id, seconds); - } - - Future _getAutoDownload(String? id) async { - return await _dbHelper.getAutoDownload(id); - } - - Future _getNeverUpdate(String? id) async { - return await _dbHelper.getNeverUpdate(id); - } - - Future _getHideNewMark(String? id) async { - return await _dbHelper.getHideNewMark(id); - } - - Future _getSkipSecondStart(String? id) async { - return await _dbHelper.getSkipSecondsStart(id); - } - - Future _getSkipSecondEnd(String id) async { - return await _dbHelper.getSkipSecondsEnd(id); - } - - Future _markListened(String? podcastId) async { - setState(() { - _markStatus = MarkStatus.start; - }); - final episodes = await _dbHelper.getRssItem(podcastId, -1, - reverse: true, hideListened: true); - for (var episode in episodes) { - final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1); - await _dbHelper.saveHistory(history); - } - if (mounted) { - setState(() { - _markStatus = MarkStatus.complete; - }); - } - } - - Future _refreshArtWork() async { - setState(() => _coverStatus = RefreshCoverStatus.start); - var options = BaseOptions( - connectTimeout: 30000, - receiveTimeout: 90000, - ); - var dir = await getApplicationDocumentsDirectory(); - var filePath = "${dir.path}/${widget.podcastLocal!.id}.png"; - var dio = Dio(options); - String? imageUrl; - - try { - var response = await dio.get(widget.podcastLocal!.rssUrl); - try { - var p = RssFeed.parse(response.data); - imageUrl = p.itunes!.image!.href ?? p.image!.url; - } catch (e) { - developer.log(e.toString()); - if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error); - } - } catch (e) { - developer.log(e.toString()); - if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error); - } - if (imageUrl != null && imageUrl.contains('http')) { - try { - img.Image thumbnail; - var imageResponse = await dio.get>(imageUrl, - options: Options( - responseType: ResponseType.bytes, - )); - var image = img.decodeImage(imageResponse.data!)!; - thumbnail = img.copyResize(image, width: 300); - if (thumbnail != null) { - File(filePath)..writeAsBytesSync(img.encodePng(thumbnail)); - _dbHelper.updatePodcastImage( - id: widget.podcastLocal!.id, filePath: filePath); - print('saved image'); - if (mounted) { - setState(() => _coverStatus = RefreshCoverStatus.complete); - } - } - } catch (e) { - developer.log(e.toString()); - if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error); - } - } else if (_coverStatus == RefreshCoverStatus.start && mounted) { - setState(() => _coverStatus = RefreshCoverStatus.complete); - } - } - - 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 _getRefreshStatusIcon(RefreshCoverStatus status) { - switch (status) { - case RefreshCoverStatus.none: - return Center(); - break; - case RefreshCoverStatus.start: - return CircularProgressIndicator(strokeWidth: 2); - break; - case RefreshCoverStatus.complete: - return Icon(Icons.done); - break; - case RefreshCoverStatus.error: - return Icon(Icons.refresh, color: Colors.red); - break; - default: - return Center(); - } - } - @override Widget build(BuildContext context) { final s = context.s; @@ -341,42 +194,43 @@ class _PodcastSettingState extends State { child: _getRefreshStatusIcon(_coverStatus)))), Divider(height: 1), ListTile( - onTap: () { - setState(() { - _removeConfirm = false; - _showStartTimePicker = false; - _showEndTimePicker = false; - _markConfirm = !_markConfirm; - }); - }, - dense: true, - title: Row( - children: [ - SizedBox( - height: 18, - width: 18, - child: CustomPaint( - painter: ListenedAllPainter(context.accentColor, stroke: 2), - ), + onTap: () { + setState(() { + _removeConfirm = false; + _showStartTimePicker = false; + _showEndTimePicker = false; + _markConfirm = !_markConfirm; + }); + }, + dense: true, + title: Row( + children: [ + SizedBox( + height: 18, + width: 18, + child: CustomPaint( + painter: ListenedAllPainter(context.accentColor, stroke: 2), ), - SizedBox(width: 20), - Text(s.menuMarkAllListened, - style: textStyle.copyWith( - color: context.accentColor, - fontWeight: FontWeight.bold)), - ], + ), + SizedBox(width: 20), + Text(s.menuMarkAllListened, + style: textStyle.copyWith( + color: context.accentColor, fontWeight: FontWeight.bold)), + ], + ), + trailing: Padding( + padding: const EdgeInsets.only(right: 10.0), + child: SizedBox( + height: 20, + width: 20, + child: _markStatus == MarkStatus.none + ? Center() + : _markStatus == MarkStatus.start + ? CircularProgressIndicator(strokeWidth: 2) + : Icon(Icons.done), ), - trailing: Padding( - padding: const EdgeInsets.only(right: 10.0), - child: SizedBox( - height: 20, - width: 20, - child: _markStatus == MarkStatus.none - ? Center() - : _markStatus == MarkStatus.start - ? CircularProgressIndicator(strokeWidth: 2) - : Icon(Icons.done)), - )), + ), + ), if (_markConfirm) Container( width: double.infinity, @@ -384,7 +238,7 @@ class _PodcastSettingState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - FlatButton( + TextButton( onPressed: () => setState(() { _markConfirm = false; }), @@ -392,7 +246,7 @@ class _PodcastSettingState extends State { s.cancel, style: TextStyle(color: Colors.grey[600]), )), - FlatButton( + TextButton( onPressed: () { if (_markStatus != MarkStatus.start) { _markListened(widget.podcastLocal!.id); @@ -402,7 +256,7 @@ class _PodcastSettingState extends State { }); }, child: Text(s.confirm, - style: TextStyle(color: context.accentColor))), + style: TextStyle(color: context.error))), ], ), ), @@ -433,15 +287,14 @@ class _PodcastSettingState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - FlatButton( + TextButton( onPressed: () => setState(() { _removeConfirm = false; }), child: Text(s.cancel, style: TextStyle(color: Colors.grey[600])), ), - FlatButton( - splashColor: Colors.red.withAlpha(70), + TextButton( onPressed: () async { await groupList.removePodcast(widget.podcastLocal!); Navigator.of(context).pop(); @@ -454,6 +307,147 @@ class _PodcastSettingState extends State { ], ); } + + Future _setAutoDownload(bool boo) async { + var permission = await _checkPermmison(); + if (permission) { + await _dbHelper.saveAutoDownload(widget.podcastLocal!.id, boo: boo); + } + if (mounted) setState(() {}); + } + + Future _setNeverUpdate(bool boo) async { + await _dbHelper.saveNeverUpdate(widget.podcastLocal!.id, boo: boo); + if (mounted) setState(() {}); + } + + Future _setHideNewMark(bool boo) async { + await _dbHelper.saveHideNewMark(widget.podcastLocal!.id, boo: boo); + if (mounted) setState(() {}); + } + + Future _saveSkipSecondsStart(int? seconds) async { + await _dbHelper.saveSkipSecondsStart(widget.podcastLocal!.id, seconds); + } + + Future _saveSkipSecondsEnd(int seconds) async { + await _dbHelper.saveSkipSecondsEnd(widget.podcastLocal!.id, seconds); + } + + Future _getAutoDownload(String? id) async { + return await _dbHelper.getAutoDownload(id); + } + + Future _getNeverUpdate(String? id) async { + return await _dbHelper.getNeverUpdate(id); + } + + Future _getHideNewMark(String? id) async { + return await _dbHelper.getHideNewMark(id); + } + + Future _getSkipSecondStart(String? id) async { + return await _dbHelper.getSkipSecondsStart(id); + } + + Future _getSkipSecondEnd(String id) async { + return await _dbHelper.getSkipSecondsEnd(id); + } + + Future _markListened(String? podcastId) async { + setState(() { + _markStatus = MarkStatus.start; + }); + final episodes = await _dbHelper.getRssItem(podcastId, -1, + reverse: true, hideListened: true); + for (var episode in episodes) { + final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1); + await _dbHelper.saveHistory(history); + } + if (mounted) { + setState(() { + _markStatus = MarkStatus.complete; + }); + } + } + + Future _refreshArtWork() async { + setState(() => _coverStatus = RefreshCoverStatus.start); + var options = BaseOptions( + connectTimeout: 30000, + receiveTimeout: 90000, + ); + var dir = await getApplicationDocumentsDirectory(); + var filePath = "${dir.path}/${widget.podcastLocal!.id}.png"; + var dio = Dio(options); + String? imageUrl; + + try { + var response = await dio.get(widget.podcastLocal!.rssUrl); + try { + var p = RssFeed.parse(response.data); + imageUrl = p.itunes!.image!.href ?? p.image!.url; + } catch (e) { + developer.log(e.toString()); + if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error); + } + } catch (e) { + developer.log(e.toString()); + if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error); + } + if (imageUrl != null && imageUrl.contains('http')) { + try { + img.Image thumbnail; + var imageResponse = await dio.get>(imageUrl, + options: Options( + responseType: ResponseType.bytes, + )); + var image = img.decodeImage(imageResponse.data!)!; + thumbnail = img.copyResize(image, width: 300); + File(filePath)..writeAsBytesSync(img.encodePng(thumbnail)); + _dbHelper.updatePodcastImage( + id: widget.podcastLocal!.id, filePath: filePath); + print('saved image'); + if (mounted) { + setState(() => _coverStatus = RefreshCoverStatus.complete); + } + } catch (e) { + developer.log(e.toString()); + if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error); + } + } else if (_coverStatus == RefreshCoverStatus.start && mounted) { + setState(() => _coverStatus = RefreshCoverStatus.complete); + } + } + + 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 _getRefreshStatusIcon(RefreshCoverStatus status) { + switch (status) { + case RefreshCoverStatus.none: + return Center(); + case RefreshCoverStatus.start: + return CircularProgressIndicator(strokeWidth: 2); + case RefreshCoverStatus.complete: + return Icon(Icons.done); + case RefreshCoverStatus.error: + return Icon(Icons.refresh, color: Colors.red); + default: + return Center(); + } + } } class _TimePicker extends StatelessWidget { @@ -477,15 +471,16 @@ class _TimePicker extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - FlatButton( + TextButton( onPressed: onCancel, child: Text( s.cancel, style: TextStyle(color: Colors.grey[600]), ), ), - FlatButton( - splashColor: context.accentColor.withAlpha(70), + TextButton( + style: TextButton.styleFrom( + surfaceTintColor: context.priamryContainer), onPressed: onConfirm, child: Text( s.confirm, diff --git a/lib/podcasts/podcastlist.dart b/lib/podcasts/podcastlist.dart index 043d54b..81b22c0 100644 --- a/lib/podcasts/podcastlist.dart +++ b/lib/podcasts/podcastlist.dart @@ -1,9 +1,7 @@ import 'dart:async'; import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:provider/provider.dart'; @@ -20,78 +18,6 @@ import 'podcast_detail.dart'; import 'podcast_manage.dart'; import 'podcast_settings.dart'; -class AboutPodcast extends StatefulWidget { - final PodcastLocal? podcastLocal; - AboutPodcast({this.podcastLocal, Key? key}) : super(key: key); - - @override - _AboutPodcastState createState() => _AboutPodcastState(); -} - -class _AboutPodcastState extends State { - String? _description; - late bool _load; - - void getDescription(String? id) async { - var dbHelper = DBHelper(); - var description = await dbHelper.getFeedDescription(id); - _description = description; - setState(() { - _load = true; - }); - } - - @override - void initState() { - super.initState(); - _load = false; - getDescription(widget.podcastLocal!.id); - } - - @override - Widget build(BuildContext context) { - var _groupList = Provider.of(context, listen: false); - final s = context.s; - return AlertDialog( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)), - titlePadding: EdgeInsets.only( - top: 20, left: 20, right: context.width / 3, bottom: 20), - actions: [ - FlatButton( - splashColor: context.accentColor.withAlpha(70), - padding: EdgeInsets.all(10.0), - onPressed: () { - _groupList.removePodcast(widget.podcastLocal!); - Navigator.of(context).pop(); - }, - textColor: Colors.red, - child: Text( - s.remove, - ), - ), - ], - title: Text(widget.podcastLocal!.title!), - content: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - !_load - ? Center() - : _description != null - ? Html(data: _description) - : Center(), - if (widget.podcastLocal!.author != null) - Text(widget.podcastLocal!.author!, - style: TextStyle(color: Colors.blue)) - ], - ), - ), - ); - } -} - class PodcastList extends StatefulWidget { @override _PodcastListState createState() => _PodcastListState(); @@ -108,32 +34,34 @@ class _PodcastListState extends State { Widget build(BuildContext context) { final width = context.width; return AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarIconBrightness: Theme.of(context).accentColorBrightness, - systemNavigationBarColor: context.primaryColor, - systemNavigationBarIconBrightness: - Theme.of(context).accentColorBrightness, - ), - child: Scaffold( - appBar: AppBar( - title: Text(context.s.podcast(2)), - leading: CustomBackButton(), - actions: [ - Selector( + value: context.overlay, + child: SafeArea( + child: Scaffold( + backgroundColor: context.background, + appBar: AppBar( + backgroundColor: context.background, + title: Text(context.s.podcast(2)), + leading: CustomBackButton(), + actions: [ + Selector( selector: (_, setting) => setting.openAllPodcastDefalt, builder: (_, data, __) { - return data! - ? IconButton( - splashRadius: 20, - icon: Icon(Icons.all_out), - onPressed: () => Navigator.push( - context, ScaleRoute(page: PodcastManage()))) - : Center(); - }) - ], - ), - body: SafeArea( - child: Container( + if (!data!) return Center(); + return IconButton( + splashRadius: 20, + icon: Icon(Icons.all_out), + onPressed: () => Navigator.push( + context, + ScaleRoute( + page: PodcastManage(), + ), + ), + ); + }, + ) + ], + ), + body: Container( color: context.primaryColor, child: FutureBuilder>( future: _getPodcastLocal(), @@ -212,9 +140,10 @@ class _PodcastListState extends State { } return Center( child: SizedBox( - height: 20, - width: 20, - child: CircularProgressIndicator()), + height: 20, + width: 20, + child: CircularProgressIndicator(), + ), ); }, ), diff --git a/lib/settings/data_backup.dart b/lib/settings/data_backup.dart index 86b54c5..7c0be0d 100644 --- a/lib/settings/data_backup.dart +++ b/lib/settings/data_backup.dart @@ -45,7 +45,7 @@ class _DataBackupState extends State { systemNavigationBarIconBrightness: context.brightness, ), child: Scaffold( - backgroundColor: context.onPrimary, + backgroundColor: context.background, appBar: AppBar( elevation: 0, title: Text(s.settingsBackup), diff --git a/lib/settings/history.dart b/lib/settings/history.dart index be0d0d5..437d208 100644 --- a/lib/settings/history.dart +++ b/lib/settings/history.dart @@ -44,7 +44,7 @@ class _PlayedHistoryState extends State return AnnotatedRegion( value: context.overlay, child: Scaffold( - backgroundColor: context.onPrimary, + backgroundColor: context.background, body: SafeArea( child: NestedScrollView( headerSliverBuilder: (context, innerBoxScrolled) { diff --git a/lib/settings/layouts.dart b/lib/settings/layouts.dart index bb3ea74..154b784 100644 --- a/lib/settings/layouts.dart +++ b/lib/settings/layouts.dart @@ -28,7 +28,7 @@ class _LayoutSettingState extends State { return AnnotatedRegion( value: context.overlay, child: Scaffold( - backgroundColor: context.onPrimary, + backgroundColor: context.background, appBar: AppBar( title: Text(s.settingsLayout), leading: CustomBackButton(), diff --git a/lib/settings/play_setting.dart b/lib/settings/play_setting.dart index 7339a31..adab1f8 100644 --- a/lib/settings/play_setting.dart +++ b/lib/settings/play_setting.dart @@ -46,7 +46,7 @@ class _PlaySettingState extends State { return AnnotatedRegion( value: context.overlay, child: Scaffold( - backgroundColor: context.onPrimary, + backgroundColor: context.background, appBar: AppBar( title: Text(s.play), leading: CustomBackButton(), diff --git a/lib/settings/settting.dart b/lib/settings/settting.dart index b60c9cd..aaa885b 100644 --- a/lib/settings/settting.dart +++ b/lib/settings/settting.dart @@ -72,16 +72,16 @@ class _SettingsState extends State { return AnnotatedRegion( value: SystemUiOverlayStyle( statusBarIconBrightness: context.brightness, - systemNavigationBarColor: context.onPrimary, + systemNavigationBarColor: context.background, systemNavigationBarIconBrightness: context.iconBrightness, ), child: Scaffold( - backgroundColor: context.onPrimary, + backgroundColor: context.background, appBar: AppBar( title: Text(s.settings), leading: CustomBackButton(), elevation: _showTitle ? 1 : 0, - backgroundColor: context.onPrimary, + backgroundColor: context.background, ), body: SingleChildScrollView( scrollDirection: Axis.vertical, diff --git a/lib/settings/storage.dart b/lib/settings/storage.dart index 11948d5..06af78f 100644 --- a/lib/settings/storage.dart +++ b/lib/settings/storage.dart @@ -46,7 +46,7 @@ class _StorageSettingState extends State return AnnotatedRegion( value: context.overlay, child: Scaffold( - backgroundColor: context.onPrimary, + backgroundColor: context.background, appBar: AppBar( title: Text(s.settingStorage), leading: CustomBackButton(), diff --git a/lib/settings/theme.dart b/lib/settings/theme.dart index c0a16d1..cb095aa 100644 --- a/lib/settings/theme.dart +++ b/lib/settings/theme.dart @@ -11,16 +11,16 @@ class ThemeSetting extends StatelessWidget { @override Widget build(BuildContext context) { final s = context.s; - var settings = Provider.of(context, listen: false); + final settings = Provider.of(context, listen: false); return AnnotatedRegion( value: context.overlay, child: Scaffold( - backgroundColor: context.onPrimary, + backgroundColor: context.background, appBar: AppBar( title: Text(s.settingsAppearance), leading: CustomBackButton(), elevation: 0, - backgroundColor: context.onPrimary, + backgroundColor: context.background, ), body: Column( mainAxisAlignment: MainAxisAlignment.start, @@ -52,7 +52,7 @@ class ThemeSetting extends StatelessWidget { pageBuilder: (context, animaiton, secondaryAnimation) => AnnotatedRegion( value: SystemUiOverlayStyle( - statusBarIconBrightness: Brightness.light, + statusBarColor: Colors.transparent, systemNavigationBarColor: Theme.of(context).brightness == Brightness.light ? Color.fromRGBO(113, 113, 113, 1) @@ -151,13 +151,18 @@ class ThemeSetting extends StatelessWidget { ListTile( onTap: () => generalDialog( context, - title: Text.rich(TextSpan(text: s.chooseA, children: [ + title: Text.rich( TextSpan( - text: ' ${s.color}', - style: TextStyle( - fontWeight: FontWeight.bold, - color: context.accentColor)) - ])), + text: s.chooseA, + children: [ + TextSpan( + text: ' ${s.color}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: context.accentColor)) + ], + ), + ), content: _ColorPicker( onColorChanged: (value) => settings.setAccentColor = value, ), @@ -253,29 +258,6 @@ class __ColorPickerState extends State<_ColorPicker> }); } - Widget _colorCircle(Color color) => Material( - color: Colors.transparent, - child: InkWell( - borderRadius: BorderRadius.all(Radius.circular(10)), - onTap: () => widget.onColorChanged!(color), - child: Container( - decoration: BoxDecoration( - border: color == context.accentColor - ? Border.all(color: Colors.grey[400]!, width: 4) - : null, - borderRadius: BorderRadius.all(Radius.circular(10)), - color: color), - ), - ), - ); - - List _accentList(MaterialAccentColor color) => [ - _colorCircle(color.shade100), - _colorCircle(color.shade200), - _colorCircle(color.shade400), - _colorCircle(color.shade700) - ]; - @override Widget build(BuildContext context) { return Container( @@ -397,4 +379,27 @@ class __ColorPickerState extends State<_ColorPicker> ), ); } + + Widget _colorCircle(Color color) => Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.all(Radius.circular(10)), + onTap: () => widget.onColorChanged!(color), + child: Container( + decoration: BoxDecoration( + border: color == context.accentColor + ? Border.all(color: Colors.grey[400]!, width: 4) + : null, + borderRadius: BorderRadius.all(Radius.circular(10)), + color: color), + ), + ), + ); + + List _accentList(MaterialAccentColor color) => [ + _colorCircle(color.shade100), + _colorCircle(color.shade200), + _colorCircle(color.shade400), + _colorCircle(color.shade700) + ]; } diff --git a/lib/util/extension_helper.dart b/lib/util/extension_helper.dart index c4e3aad..d15bbb2 100644 --- a/lib/util/extension_helper.dart +++ b/lib/util/extension_helper.dart @@ -32,9 +32,9 @@ extension ContextExtension on BuildContext { double get paddingTop => MediaQuery.of(this).padding.top; TextTheme get textTheme => Theme.of(this).textTheme; SystemUiOverlayStyle get overlay => SystemUiOverlayStyle( - statusBarColor: onPrimary, + statusBarColor: background, statusBarIconBrightness: iconBrightness, - systemNavigationBarColor: onPrimary, + systemNavigationBarColor: background, systemNavigationBarIconBrightness: iconBrightness, ); S get s => S.of(this)!; diff --git a/lib/widgets/episodegrid.dart b/lib/widgets/episodegrid.dart index d5f8849..332582c 100644 --- a/lib/widgets/episodegrid.dart +++ b/lib/widgets/episodegrid.dart @@ -72,11 +72,11 @@ class EpisodeGrid extends StatelessWidget { Future>> _initData( EpisodeBrief episode) async { - var menuList = await _getEpisodeMenu(); - var tapToOpen = await _getTapToOpenPopupMenu(); - var listened = await _isListened(episode); - var liked = await _isLiked(episode); - var downloaded = await _isDownloaded(episode); + final menuList = await _getEpisodeMenu(); + final tapToOpen = await _getTapToOpenPopupMenu(); + final listened = await _isListened(episode); + final liked = await _isLiked(episode); + final downloaded = await _isDownloaded(episode); return Tuple5(listened, liked, downloaded, tapToOpen, menuList); } @@ -85,8 +85,8 @@ class EpisodeGrid extends StatelessWidget { } Future> _getEpisodeMenu() async { - var popupMenuStorage = KeyValueStorage(episodePopupMenuKey); - var list = await popupMenuStorage.getMenu(); + final popupMenuStorage = KeyValueStorage(episodePopupMenuKey); + final list = await popupMenuStorage.getMenu(); return list; } @@ -95,8 +95,8 @@ class EpisodeGrid extends StatelessWidget { } Future _getTapToOpenPopupMenu() async { - var tapToOpenPopupMenuStorage = KeyValueStorage(tapToOpenPopupMenuKey); - var boo = await tapToOpenPopupMenuStorage.getBool(defaultValue: false); + final tapToOpenPopupMenuStorage = KeyValueStorage(tapToOpenPopupMenuKey); + final boo = await tapToOpenPopupMenuStorage.getBool(defaultValue: false); return boo; } @@ -307,102 +307,131 @@ class EpisodeGrid extends StatelessWidget { Color? color, bool? isLiked, bool? isDownloaded, + Color? cardColor, + required int isListened, bool? boo}) { - var width = context.width; + final width = context.width; if (layout == Layout.one) { return _layoutOneCard(context, index: index!, color: color, isLiked: isLiked!, + cardColor: cardColor, + isListened: isListened, isDownloaded: isDownloaded, boo: boo!); } - return Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: layout == Layout.one ? 1 : 2, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - layout != Layout.one - ? _circleImage(context, - episode: episodes![index!], color: color, boo: boo!) - : _pubDate(context, - episode: episodes![index!], color: color), - Spacer(), - _isNewIndicator(episodes![index]), - _downloadIndicater(context, - episode: episodes![index], isDownloaded: isDownloaded), - _numberIndicater(context, index: index, color: color) - ], + return Container( + decoration: BoxDecoration( + color: cardColor, + borderRadius: BorderRadius.circular(15.0), + ), + clipBehavior: Clip.hardEdge, + child: Stack( + alignment: AlignmentDirectional.bottomCenter, + children: [ + if (isListened > 0) + Container( + height: 4, + color: context.accentColor, ), - ), - Expanded( - flex: layout == Layout.one ? 3 : 5, - child: layout != Layout.one - ? _title(episodes![index]) - : Row( + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + flex: layout == Layout.one ? 1 : 2, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, - children: [ - _circleImage(context, - episode: episodes![index], color: color, boo: boo!), - SizedBox( - width: 5, - ), - Expanded(child: _title(episodes![index])) + children: [ + layout != Layout.one + ? _circleImage(context, + episode: episodes![index!], + color: color, + boo: boo!) + : _pubDate(context, + episode: episodes![index!], color: color), + Spacer(), + _isNewIndicator(episodes![index]), + _downloadIndicater(context, + episode: episodes![index], + isDownloaded: isDownloaded), + _numberIndicater(context, index: index, color: color) + ], + ), + ), + Expanded( + flex: layout == Layout.one ? 3 : 5, + child: layout != Layout.one + ? _title(episodes![index]) + : Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _circleImage(context, + episode: episodes![index], + color: color, + boo: boo!), + SizedBox( + width: 5, + ), + Expanded(child: _title(episodes![index])) + ], + ), + ), + Expanded( + flex: 1, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + if (layout != Layout.one) + _pubDate(context, + episode: episodes![index], color: color), + Spacer(), + if (layout != Layout.three && + episodes![index].duration != 0) + Align( + alignment: Alignment.center, + child: Text( + episodes![index].duration!.toTime, + style: TextStyle(fontSize: width / 35), + ), + ), + if (episodes![index].duration != 0 && + episodes![index].enclosureLength != null && + episodes![index].enclosureLength != 0 && + layout != Layout.three) + Text( + '|', + style: TextStyle( + fontSize: width / 35, + ), + ), + if (layout != Layout.three && + episodes![index].enclosureLength != null && + episodes![index].enclosureLength != 0) + Align( + alignment: Alignment.center, + child: Text( + '${episodes![index].enclosureLength! ~/ 1000000}MB', + style: TextStyle(fontSize: width / 35), + ), + ), + Padding( + padding: EdgeInsets.all(1), + ), + if ((showFavorite || layout != Layout.three) && isLiked!) + Icon( + Icons.favorite, + color: Colors.red, + size: width / 35, + ) ], ), - ), - Expanded( - flex: 1, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - if (layout != Layout.one) - _pubDate(context, episode: episodes![index], color: color), - Spacer(), - if (layout != Layout.three && episodes![index].duration != 0) - Align( - alignment: Alignment.center, - child: Text( - episodes![index].duration!.toTime, - style: TextStyle(fontSize: width / 35), - ), - ), - if (episodes![index].duration != 0 && - episodes![index].enclosureLength != null && - episodes![index].enclosureLength != 0 && - layout != Layout.three) - Text( - '|', - style: TextStyle( - fontSize: width / 35, - ), - ), - if (layout != Layout.three && - episodes![index].enclosureLength != null && - episodes![index].enclosureLength != 0) - Align( - alignment: Alignment.center, - child: Text( - '${episodes![index].enclosureLength! ~/ 1000000}MB', - style: TextStyle(fontSize: width / 35), - ), - ), - Padding( - padding: EdgeInsets.all(1), ), - if ((showFavorite || layout != Layout.three) && isLiked!) - Icon( - Icons.favorite, - color: Colors.red, - size: width / 35, - ) ], ), ), @@ -416,106 +445,127 @@ class EpisodeGrid extends StatelessWidget { Color? color, required bool isLiked, bool? isDownloaded, + Color? cardColor, + required int isListened, required bool boo}) { var width = context.width; - return Padding( - padding: EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, + return Container( + decoration: BoxDecoration( + color: cardColor, + borderRadius: BorderRadius.circular(15.0), + ), + clipBehavior: Clip.hardEdge, + child: Stack( + alignment: AlignmentDirectional.bottomCenter, children: [ - Expanded( - flex: 1, - child: Center( - child: _circleImage(context, - episode: episodes![index], - color: color, - boo: boo, - radius: context.width / 8), + if (isListened > 0) + Container( + height: 4, + color: context.accentColor, ), - ), - Expanded( - flex: 4, - child: Column( + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( flex: 1, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Text(episodes![index].feedTitle!, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontWeight: FontWeight.bold, color: color)), - ), - _isNewIndicator(episodes![index]), - _downloadIndicater(context, - episode: episodes![index], - isDownloaded: isDownloaded), - _numberIndicater(context, index: index, color: color) - ], + child: Center( + child: _circleImage(context, + episode: episodes![index], + color: color, + boo: boo, + radius: context.width / 8), ), ), Expanded( - flex: 2, - child: Align( - alignment: Alignment.topLeft, - child: _title(episodes![index]))), - Expanded( - flex: 1, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - if (episodes![index].duration != 0) - Align( - alignment: Alignment.center, - child: Text( - episodes![index].duration!.toTime, - style: TextStyle(fontSize: width / 35), + flex: 4, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 1, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Text(episodes![index].feedTitle!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: FontWeight.bold, + color: color)), ), - ), - if (episodes![index].duration != 0 && - episodes![index].enclosureLength != null && - episodes![index].enclosureLength != 0 && - layout != Layout.three) - Text( - '|', - style: TextStyle( - fontSize: width / 35, - ), - ), - if (episodes![index].enclosureLength != null && - episodes![index].enclosureLength != 0) - Align( - alignment: Alignment.center, - child: Text( - '${episodes![index].enclosureLength! ~/ 1000000}MB', - style: TextStyle(fontSize: width / 35), - ), - ), - SizedBox(width: 4), - if (isLiked) - Icon( - Icons.favorite, - color: Colors.red, - size: width / 35, - ), - Spacer(), - _pubDate(context, - episode: episodes![index], color: color), - ]), - ) + _isNewIndicator(episodes![index]), + _downloadIndicater(context, + episode: episodes![index], + isDownloaded: isDownloaded), + _numberIndicater(context, + index: index, color: color) + ], + ), + ), + Expanded( + flex: 2, + child: Align( + alignment: Alignment.topLeft, + child: _title(episodes![index]))), + Expanded( + flex: 1, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + if (episodes![index].duration != 0) + Align( + alignment: Alignment.center, + child: Text( + episodes![index].duration!.toTime, + style: TextStyle(fontSize: width / 35), + ), + ), + if (episodes![index].duration != 0 && + episodes![index].enclosureLength != null && + episodes![index].enclosureLength != 0 && + layout != Layout.three) + Text( + '|', + style: TextStyle( + fontSize: width / 35, + ), + ), + if (episodes![index].enclosureLength != null && + episodes![index].enclosureLength != 0) + Align( + alignment: Alignment.center, + child: Text( + '${episodes![index].enclosureLength! ~/ 1000000}MB', + style: TextStyle(fontSize: width / 35), + ), + ), + SizedBox(width: 4), + if (isLiked) + Icon( + Icons.favorite, + color: Colors.red, + size: width / 35, + ), + Spacer(), + _pubDate(context, + episode: episodes![index], color: color), + ]), + ) + ], + ), + ), + SizedBox(width: 8) ], ), ), - SizedBox(width: 8) ], ), ); @@ -533,7 +583,7 @@ class EpisodeGrid extends StatelessWidget { final s = context.s; return SliverPadding( padding: const EdgeInsets.only( - top: 10.0, bottom: 5.0, left: 15.0, right: 15.0), + top: 10.0, bottom: 5.0, left: 10.0, right: 10.0), sliver: LiveSliverGrid.options( controller: scrollController, options: options, @@ -549,8 +599,8 @@ class EpisodeGrid extends StatelessWidget { : layout == Layout.two ? 2 : 1, - mainAxisSpacing: 6.0, - crossAxisSpacing: 6.0, + mainAxisSpacing: 10.0, + crossAxisSpacing: 10.0, ), itemBuilder: (context, index, animation) { final c = episodes![index].backgroudColor(context); @@ -576,28 +626,31 @@ class EpisodeGrid extends StatelessWidget { future: _initData(episodes![index]), initialData: Tuple5(0, false, false, false, []), builder: (context, snapshot) { - var isListened = snapshot.data!.item1; - var isLiked = snapshot.data!.item2; - var isDownloaded = snapshot.data!.item3; - var tapToOpen = snapshot.data!.item4; - var menuList = snapshot.data!.item5; + final isListened = snapshot.data!.item1; + final isLiked = snapshot.data!.item2; + final isDownloaded = snapshot.data!.item3; + final tapToOpen = snapshot.data!.item4; + final menuList = snapshot.data!.item5; return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - color: isListened > 0 - ? context.brightness == Brightness.light - ? Colors.grey[200] - : Color.fromRGBO(50, 50, 50, 1) - : context.background, - boxShadow: [ - BoxShadow( - color: context.brightness == Brightness.light - ? context.primaryColor - : Color.fromRGBO(40, 40, 40, 1), - blurRadius: 0.5, - spreadRadius: 0.5, - ), - ]), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.all( + // Radius.circular(15.0), + // ), + // color: isListened > 0 + // ? context.brightness == Brightness.light + // ? Colors.grey[200] + // : Color.fromRGBO(50, 50, 50, 1) + // : context.priamryContainer, + // ), + // boxShadow: [ + // BoxShadow( + // color: context.brightness == Brightness.light + // ? context.primaryColor + // : Color.fromRGBO(40, 40, 40, 1), + // blurRadius: 0.5, + // spreadRadius: 0.5, + // ), + // ]), alignment: Alignment.center, child: multiSelect! ? Material( @@ -616,7 +669,8 @@ class EpisodeGrid extends StatelessWidget { }, child: Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(15.0), + color: episodes![index].cardColor(context), border: Border.all( color: selectedList! .contains(episodes![index]) @@ -632,6 +686,7 @@ class EpisodeGrid extends StatelessWidget { index: index, isLiked: isLiked, isDownloaded: isDownloaded, + isListened: isListened, color: c, boo: boo), ), @@ -639,7 +694,8 @@ class EpisodeGrid extends StatelessWidget { ) : Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5.0), + color: episodes![index].cardColor(context), + borderRadius: BorderRadius.circular(20.0), border: Border.all( color: context.brightness == Brightness.light ? context.primaryColor @@ -652,7 +708,7 @@ class EpisodeGrid extends StatelessWidget { menuItemExtent: 45, menuBoxDecoration: BoxDecoration( color: Colors.transparent, - borderRadius: BorderRadius.circular(15.0)), + borderRadius: BorderRadius.circular(20.0)), duration: Duration(milliseconds: 100), tapMode: tapToOpen ? TapMode.onTap @@ -666,10 +722,7 @@ class EpisodeGrid extends StatelessWidget { menuOffset: 6, menuItems: [ FocusedMenuItem( - backgroundColor: - context.brightness == Brightness.light - ? context.primaryColor - : context.dialogBackgroundColor, + backgroundColor: context.priamryContainer, title: Text( data.item1 != episodes![index] || !data.item4 @@ -687,10 +740,8 @@ class EpisodeGrid extends StatelessWidget { }), if (menuList.contains(1)) FocusedMenuItem( - backgroundColor: context.brightness == - Brightness.light - ? context.primaryColor - : context.dialogBackgroundColor, + backgroundColor: + context.priamryContainer, title: data.item2.contains( episodes![index].enclosureUrl) ? Text(s.remove) @@ -719,10 +770,8 @@ class EpisodeGrid extends StatelessWidget { }), if (menuList.contains(2)) FocusedMenuItem( - backgroundColor: context.brightness == - Brightness.light - ? context.primaryColor - : context.dialogBackgroundColor, + backgroundColor: + context.priamryContainer, title: isLiked ? Text(s.unlike) : Text(s.like), @@ -749,10 +798,8 @@ class EpisodeGrid extends StatelessWidget { }), if (menuList.contains(3)) FocusedMenuItem( - backgroundColor: context.brightness == - Brightness.light - ? context.primaryColor - : context.dialogBackgroundColor, + backgroundColor: + context.priamryContainer, title: isListened > 0 ? Text(s.markNotListened, style: TextStyle( @@ -792,10 +839,8 @@ class EpisodeGrid extends StatelessWidget { }), if (menuList.contains(4)) FocusedMenuItem( - backgroundColor: context.brightness == - Brightness.light - ? context.primaryColor - : context.dialogBackgroundColor, + backgroundColor: + context.priamryContainer, title: isDownloaded ? Text(s.downloaded, style: TextStyle( @@ -812,30 +857,33 @@ class EpisodeGrid extends StatelessWidget { }), if (menuList.contains(5)) FocusedMenuItem( - backgroundColor: context.brightness == - Brightness.light - ? context.primaryColor - : context.dialogBackgroundColor, - title: Text(s.playNext), - trailingIcon: Icon( - LineIcons.lightningBolt, - color: Colors.amber, - ), - onPressed: () { - audio.moveToTop(episodes![index]); - Fluttertoast.showToast( - msg: s.playNextDes, - gravity: ToastGravity.BOTTOM, - ); - }), + backgroundColor: context.priamryContainer, + title: Text(s.playNext), + trailingIcon: Icon( + LineIcons.lightningBolt, + color: Colors.amber, + ), + onPressed: () { + audio.moveToTop(episodes![index]); + Fluttertoast.showToast( + msg: s.playNextDes, + gravity: ToastGravity.BOTTOM, + ); + }, + ), ], onPressed: action, - child: _episodeCard(context, - index: index, - isLiked: isLiked, - isDownloaded: isDownloaded, - color: c, - boo: boo), + child: _episodeCard( + context, + index: index, + isLiked: isLiked, + isListened: isListened, + isDownloaded: isDownloaded, + cardColor: + episodes![index].cardColor(context), + color: c, + boo: boo, + ), ), ), );