From b45c7e3a5baa2fefbedf251ef13cb4e5ccb2dcd4 Mon Sep 17 00:00:00 2001 From: stonegate Date: Wed, 3 Jun 2020 20:39:15 +0800 Subject: [PATCH] :sparkles: Layout setting, supprt one raw view --- lib/home/addpodcast.dart | 33 +-- lib/home/home.dart | 252 +++++++++++------- lib/home/home_groups.dart | 74 +++--- lib/intro_slider/firstpage.dart | 7 +- lib/intro_slider/fourthpage.dart | 3 +- lib/intro_slider/secondpage.dart | 6 +- lib/intro_slider/thirdpage.dart | 11 +- lib/local_storage/key_value_storage.dart | 6 + lib/podcasts/podcastdetail.dart | 83 ++++-- lib/settings/layouts.dart | 165 ++++++++++++ lib/settings/settting.dart | 14 + lib/settings/theme.dart | 320 +++++++++++------------ lib/state/subscribe_podcast.dart | 5 +- lib/util/custompaint.dart | 15 +- lib/util/episodegrid.dart | 320 ++++++++++++----------- lib/util/pageroute.dart | 17 +- 16 files changed, 818 insertions(+), 513 deletions(-) create mode 100644 lib/settings/layouts.dart diff --git a/lib/home/addpodcast.dart b/lib/home/addpodcast.dart index d8c82b7..2d41f88 100644 --- a/lib/home/addpodcast.dart +++ b/lib/home/addpodcast.dart @@ -9,6 +9,7 @@ import 'package:dio/dio.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:cached_network_image/cached_network_image.dart'; import '../type/searchpodcast.dart'; import '../state/subscribe_podcast.dart'; @@ -391,26 +392,26 @@ class _SearchResultState extends State }, leading: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(20.0)), - child: Image.network( - widget.onlinePodcast.image, + child: CachedNetworkImage( height: 40.0, width: 40.0, fit: BoxFit.fitWidth, alignment: Alignment.center, - loadingBuilder: (context, child, loadingProgress) { - if (loadingProgress == null) return child; - return Container( - alignment: Alignment.center, - height: 40, - width: 40, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: context.primaryColorDark), - child: SizedBox( - width: 20, height: 2, child: LinearProgressIndicator()), - ); - }, - errorBuilder: (context, error, stackTrace) => Container( + imageUrl: widget.onlinePodcast.image, + progressIndicatorBuilder: (context, url, downloadProgress) => + Container( + height: 40, + width: 40, + alignment: Alignment.center, + color: context.primaryColorDark, + child: SizedBox( + width: 20, + height: 2, + child: LinearProgressIndicator( + value: downloadProgress.progress), + ), + ), + errorWidget: (context, url, error) => Container( width: 40, height: 40, alignment: Alignment.center, diff --git a/lib/home/home.dart b/lib/home/home.dart index 977546f..c478788 100644 --- a/lib/home/home.dart +++ b/lib/home/home.dart @@ -12,6 +12,7 @@ import 'package:fluttertoast/fluttertoast.dart'; import '../state/audiostate.dart'; import '../type/episodebrief.dart'; import '../local_storage/sqflite_localpodcast.dart'; +import '../local_storage/key_value_storage.dart'; import '../util/episodegrid.dart'; import '../util/mypopupmenu.dart'; import '../util/context_extension.dart'; @@ -401,6 +402,10 @@ class _RecentUpdate extends StatefulWidget { class _RecentUpdateState extends State<_RecentUpdate> with AutomaticKeepAliveClientMixin, SingleTickerProviderStateMixin { Future> _getRssItem(int top, List group) async { + KeyValueStorage storage = KeyValueStorage(recentLayoutKey); + int index = await storage.getInt(); + if (_layout == null) _layout = Layout.values[index]; + var dbHelper = DBHelper(); List episodes; if (group.first == 'All') @@ -441,7 +446,6 @@ class _RecentUpdateState extends State<_RecentUpdate> _loadMore = false; _groupName = 'All'; _group = ['All']; - _layout = Layout.three; } @override @@ -641,11 +645,16 @@ class _RecentUpdateState extends State<_RecentUpdate> onPressed: () { if (_layout == Layout.three) setState(() { - _layout = Layout.two; + _layout = Layout.one; + }); + else if (_layout == + Layout.two) + setState(() { + _layout = Layout.three; }); else setState(() { - _layout = Layout.three; + _layout = Layout.two; }); }, icon: _layout == Layout.three @@ -661,18 +670,33 @@ class _RecentUpdateState extends State<_RecentUpdate> .color), ), ) - : SizedBox( - height: 10, - width: 30, - child: CustomPaint( - painter: LayoutPainter( - 1, - context - .textTheme - .bodyText1 - .color), - ), - ), + : _layout == Layout.two + ? SizedBox( + height: 10, + width: 30, + child: + CustomPaint( + painter: LayoutPainter( + 1, + context + .textTheme + .bodyText1 + .color), + ), + ) + : SizedBox( + height: 10, + width: 30, + child: + CustomPaint( + painter: LayoutPainter( + 4, + context + .textTheme + .bodyText1 + .color), + ), + ), )), ], ), @@ -714,6 +738,9 @@ class _MyFavorite extends StatefulWidget { class _MyFavoriteState extends State<_MyFavorite> with AutomaticKeepAliveClientMixin { Future> _getLikedRssItem(int top, int sortBy) async { + KeyValueStorage storage = KeyValueStorage(favLayoutKey); + int index = await storage.getInt(); + if (_layout == null) _layout = Layout.values[index]; var dbHelper = DBHelper(); List episodes = await dbHelper.getLikedRssItem(top, sortBy); return episodes; @@ -737,7 +764,6 @@ class _MyFavoriteState extends State<_MyFavorite> void initState() { super.initState(); _loadMore = false; - _layout = Layout.three; _sortBy = 0; } @@ -832,39 +858,53 @@ class _MyFavoriteState extends State<_MyFavorite> Material( color: Colors.transparent, child: IconButton( - padding: EdgeInsets.zero, - onPressed: () { - if (_layout == Layout.three) - setState(() { - _layout = Layout.two; - }); - else - setState(() { - _layout = Layout.three; - }); - }, - icon: _layout == Layout.three - ? SizedBox( - height: 10, - width: 30, - child: CustomPaint( - painter: LayoutPainter( - 0, - context.textTheme.bodyText1 - .color), - ), - ) - : SizedBox( - height: 10, - width: 30, - child: CustomPaint( - painter: LayoutPainter( - 1, - context.textTheme.bodyText1 - .color), - ), - ), - ), + padding: EdgeInsets.zero, + onPressed: () { + if (_layout == Layout.three) + setState(() { + _layout = Layout.one; + }); + else if (_layout == Layout.two) + setState(() { + _layout = Layout.three; + }); + else + setState(() { + _layout = Layout.two; + }); + }, + icon: _layout == Layout.three + ? SizedBox( + height: 10, + width: 30, + child: CustomPaint( + painter: LayoutPainter( + 0, + context.textTheme + .bodyText1.color), + ), + ) + : _layout == Layout.two + ? SizedBox( + height: 10, + width: 30, + child: CustomPaint( + painter: LayoutPainter( + 1, + context.textTheme + .bodyText1.color), + ), + ) + : SizedBox( + height: 10, + width: 30, + child: CustomPaint( + painter: LayoutPainter( + 4, + context.textTheme + .bodyText1.color), + ), + )), ), ], )), @@ -906,10 +946,19 @@ class _MyDownload extends StatefulWidget { class _MyDownloadState extends State<_MyDownload> with AutomaticKeepAliveClientMixin { Layout _layout; + _getLayout() async { + KeyValueStorage keyValueStorage = KeyValueStorage(downloadLayoutKey); + int layout = await keyValueStorage.getInt(); + if (_layout == null) + setState(() { + _layout = Layout.values[layout]; + }); + } + @override void initState() { super.initState(); - _layout = Layout.three; + _getLayout(); } @override @@ -920,50 +969,65 @@ class _MyDownloadState extends State<_MyDownload> slivers: [ DownloadList(), SliverToBoxAdapter( - child: Container( - height: 40, - color: context.primaryColor, - child: Row( - children: [ - Container( - padding: EdgeInsets.symmetric(horizontal: 20), - child: Text('Downloaded')), - Spacer(), - Material( - color: Colors.transparent, - child: IconButton( - padding: EdgeInsets.zero, - onPressed: () { - if (_layout == Layout.three) - setState(() { - _layout = Layout.two; - }); - else - setState(() { - _layout = Layout.three; - }); - }, - icon: _layout == Layout.three - ? SizedBox( - height: 10, - width: 30, - child: CustomPaint( - painter: LayoutPainter( - 0, context.textTheme.bodyText1.color), - ), - ) - : SizedBox( - height: 10, - width: 30, - child: CustomPaint( - painter: LayoutPainter( - 1, context.textTheme.bodyText1.color), - ), - ), - ), - ), - ], - )), + child: _layout == null + ? Center() + : Container( + height: 40, + color: context.primaryColor, + child: Row( + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 20), + child: Text('Downloaded')), + Spacer(), + Material( + color: Colors.transparent, + child: IconButton( + padding: EdgeInsets.zero, + onPressed: () { + if (_layout == Layout.three) + setState(() { + _layout = Layout.one; + }); + else if (_layout == Layout.two) + setState(() { + _layout = Layout.three; + }); + else + setState(() { + _layout = Layout.two; + }); + }, + icon: _layout == Layout.three + ? SizedBox( + height: 10, + width: 30, + child: CustomPaint( + painter: LayoutPainter( + 0, context.textTheme.bodyText1.color), + ), + ) + : _layout == Layout.two + ? SizedBox( + height: 10, + width: 30, + child: CustomPaint( + painter: LayoutPainter(1, + context.textTheme.bodyText1.color), + ), + ) + : SizedBox( + height: 10, + width: 30, + child: CustomPaint( + painter: LayoutPainter(4, + context.textTheme.bodyText1.color), + ), + ), + ), + ), + ], + )), ), Consumer( builder: (_, downloader, __) { diff --git a/lib/home/home_groups.dart b/lib/home/home_groups.dart index 4b19440..9619fc2 100644 --- a/lib/home/home_groups.dart +++ b/lib/home/home_groups.dart @@ -10,6 +10,7 @@ import 'package:line_icons/line_icons.dart'; import '../type/episodebrief.dart'; import '../state/podcast_group.dart'; +import '../state/subscribe_podcast.dart'; import '../type/podcastlocal.dart'; import '../state/audiostate.dart'; import '../util/custompaint.dart'; @@ -394,29 +395,31 @@ class _PodcastPreviewState extends State { return Column( children: [ Expanded( - child: Container( - child: FutureBuilder>( - future: _getRssItemTop(widget.podcastLocal), - builder: (context, snapshot) { - if (snapshot.hasError) { - print(snapshot.error); - Center(); - } - return (snapshot.hasData) - ? ShowEpisode( - episodes: snapshot.data, - podcastLocal: widget.podcastLocal, - ) - : Container( - padding: EdgeInsets.all(5.0), - ); - }, - ), - ), + child: Selector( + selector: (_, worker) => worker.created, + builder: (context, created, child) { + return FutureBuilder>( + future: _getRssItemTop(widget.podcastLocal), + builder: (context, snapshot) { + if (snapshot.hasError) { + print(snapshot.error); + Center(); + } + return (snapshot.hasData) + ? ShowEpisode( + episodes: snapshot.data, + podcastLocal: widget.podcastLocal, + ) + : Container( + padding: EdgeInsets.all(5.0), + ); + }, + ); + }), ), Container( height: 40, - padding: EdgeInsets.symmetric(horizontal: 10.0), + padding: EdgeInsets.only(left: 10.0), alignment: Alignment.center, child: Row( mainAxisAlignment: MainAxisAlignment.start, @@ -434,18 +437,25 @@ class _PodcastPreviewState extends State { alignment: Alignment.centerRight, child: Material( color: Colors.transparent, - child: IconButton( - icon: Icon(Icons.arrow_forward), - tooltip: 'See All', - onPressed: () { - Navigator.push( - context, - SlideLeftHideRoute( - page: PodcastDetail( - podcastLocal: widget.podcastLocal, - )), - ); - }, + child: Selector( + selector: (_, audio) => audio.playerRunning, + builder: (_, playerRunning, __) => IconButton( + icon: Icon(Icons.arrow_forward), + tooltip: 'See All', + onPressed: () { + Navigator.push( + context, + SlideLeftHideRoute( + transitionPage: PodcastDetail( + podcastLocal: widget.podcastLocal, + hide: playerRunning, + ), + page: PodcastDetail( + podcastLocal: widget.podcastLocal, + )), + ); + }, + ), ), ), ), diff --git a/lib/intro_slider/firstpage.dart b/lib/intro_slider/firstpage.dart index ffd113d..af790b3 100644 --- a/lib/intro_slider/firstpage.dart +++ b/lib/intro_slider/firstpage.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flare_flutter/flare_actor.dart'; +import '../util/context_extension.dart'; class FirstPage extends StatefulWidget { FirstPage({Key key}) : super(key: key); @@ -12,7 +13,7 @@ class _FirstPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: Container( + body: Container( color: Color.fromRGBO(35, 204, 198, 1), child: Center( child: Column( @@ -20,10 +21,10 @@ class _FirstPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( - padding: EdgeInsets.all(100), + padding: EdgeInsets.symmetric(vertical: 100), ), Container( - height: 400, + height: context.width * 3 / 4, // color: Colors.red, child: FlareActor( 'assets/splash.flr', diff --git a/lib/intro_slider/fourthpage.dart b/lib/intro_slider/fourthpage.dart index f610c03..36d4929 100644 --- a/lib/intro_slider/fourthpage.dart +++ b/lib/intro_slider/fourthpage.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flare_flutter/flare_actor.dart'; +import '../util/context_extension.dart'; class FourthPage extends StatefulWidget { FourthPage({Key key}) : super(key: key); @@ -28,7 +29,7 @@ class _FourthPageState extends State { ),), ), Container( - height: 400, + height: context.width*3/4, // color: Colors.red, child: FlareActor( 'assets/longtap.flr', diff --git a/lib/intro_slider/secondpage.dart b/lib/intro_slider/secondpage.dart index aa2909d..72ab1a7 100644 --- a/lib/intro_slider/secondpage.dart +++ b/lib/intro_slider/secondpage.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flare_flutter/flare_actor.dart'; +import '../util/context_extension.dart'; class SecondPage extends StatefulWidget { SecondPage({Key key}) : super(key: key); @@ -21,14 +22,15 @@ class _SecondPageState extends State { Container( height: 200, alignment: Alignment.center, - padding: EdgeInsets.all(40), + padding: + EdgeInsets.only(top: 20, bottom: 20, left: 40, right: 40), child: Text( 'Subscribe podcast via search or import OMPL file.', style: TextStyle(fontSize: 30, color: Colors.white), ), ), Container( - height: 400, + height: context.width * 3 / 4, // color: Colors.red, child: FlareActor( 'assets/add.flr', diff --git a/lib/intro_slider/thirdpage.dart b/lib/intro_slider/thirdpage.dart index 58a7f9e..0e31710 100644 --- a/lib/intro_slider/thirdpage.dart +++ b/lib/intro_slider/thirdpage.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flare_flutter/flare_actor.dart'; +import '../util/context_extension.dart'; class ThirdPage extends StatefulWidget { ThirdPage({Key key}) : super(key: key); @@ -22,13 +23,13 @@ class _ThirdPageState extends State { height: 200, alignment: Alignment.center, padding: EdgeInsets.all(40), - child: Text('Swipe on podcast list to change group.', style: TextStyle( - fontSize: 30, - color: Colors.white - ),), + child: Text( + 'Swipe on podcast list to change group.', + style: TextStyle(fontSize: 30, color: Colors.white), + ), ), Container( - height: 400, + height: context.width * 3 / 4, // color: Colors.red, child: FlareActor( 'assets/swipe.flr', diff --git a/lib/local_storage/key_value_storage.dart b/lib/local_storage/key_value_storage.dart index 2c9cb76..be68e20 100644 --- a/lib/local_storage/key_value_storage.dart +++ b/lib/local_storage/key_value_storage.dart @@ -1,8 +1,10 @@ import 'dart:async'; import 'dart:convert'; + import 'package:shared_preferences/shared_preferences.dart'; import '../state/podcast_group.dart'; +import '../util/episodegrid.dart'; const String autoPlayKey = 'autoPlay'; const String autoAddKey = 'autoAdd'; @@ -17,6 +19,10 @@ const String downloadUsingDataKey = 'downloadUsingData'; const String introKey = 'intro'; const String realDarkKey = 'realDark'; const String cacheMaxKey = 'cacheMax'; +const String podcastLayoutKey = 'podcastLayoutKey'; +const String recentLayoutKey = 'recentLayoutKey'; +const String favLayoutKey = 'favLayoutKey'; +const String downloadLayoutKey = 'downloadLayoutKey'; class KeyValueStorage { final String key; diff --git a/lib/podcasts/podcastdetail.dart b/lib/podcasts/podcastdetail.dart index 6a56e86..1a27d29 100644 --- a/lib/podcasts/podcastdetail.dart +++ b/lib/podcasts/podcastdetail.dart @@ -15,6 +15,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import '../type/podcastlocal.dart'; import '../type/episodebrief.dart'; import '../local_storage/sqflite_localpodcast.dart'; +import '../local_storage/key_value_storage.dart'; import '../util/episodegrid.dart'; import '../home/audioplayer.dart'; import '../type/fireside_data.dart'; @@ -25,8 +26,10 @@ import '../state/audiostate.dart'; import '../state/podcast_group.dart'; class PodcastDetail extends StatefulWidget { - PodcastDetail({Key key, this.podcastLocal}) : super(key: key); + PodcastDetail({Key key, @required this.podcastLocal, this.hide = false}) + : super(key: key); final PodcastLocal podcastLocal; + final bool hide; @override _PodcastDetailState createState() => _PodcastDetailState(); } @@ -34,8 +37,10 @@ class PodcastDetail extends StatefulWidget { class _PodcastDetailState extends State { final GlobalKey _refreshIndicatorKey = GlobalKey(); - String backgroundImage; - List hosts; + String _backgroundImage; + List _hosts; + int _episodeCount; + Layout _layout; Future _updateRssItem(PodcastLocal podcastLocal) async { var dbHelper = DBHelper(); @@ -50,8 +55,8 @@ class _PodcastDetailState extends State { msg: 'Updated $result Episodes', gravity: ToastGravity.TOP, ); - Provider.of(context, listen: false) - .updatePodcast(podcastLocal.id); + // Provider.of(context, listen: false) + // .updatePodcast(podcastLocal.id); } else { Fluttertoast.showToast( msg: 'Update failed, network error', @@ -64,13 +69,17 @@ class _PodcastDetailState extends State { Future> _getRssItem( PodcastLocal podcastLocal, int i, bool reverse) async { var dbHelper = DBHelper(); + _episodeCount = await dbHelper.getPodcastCounts(podcastLocal.id); + KeyValueStorage storage = KeyValueStorage(podcastLayoutKey); + int index = await storage.getInt(); + if (_layout == null) _layout = Layout.values[index]; List episodes = await dbHelper.getRssItem(podcastLocal.id, i, reverse); if (podcastLocal.provider.contains('fireside')) { FiresideData data = FiresideData(podcastLocal.id, podcastLocal.link); await data.getData(); - backgroundImage = data.background; - hosts = data.hosts; + _backgroundImage = data.background; + _hosts = data.hosts; } return episodes; } @@ -114,7 +123,7 @@ class _PodcastDetailState extends State { image: DecorationImage( // colorFilter: ColorFilter.mode(_color, BlendMode.color), image: CachedNetworkImageProvider( - backgroundImage, + _backgroundImage, ), fit: BoxFit.cover)), alignment: Alignment.centerRight, @@ -179,14 +188,12 @@ class _PodcastDetailState extends State { ScrollController _controller; int _top; bool _loadMore; - Layout _layout; bool _reverse; @override void initState() { super.initState(); _loadMore = false; _top = 99; - _layout = Layout.three; _reverse = false; _controller = ScrollController(); } @@ -211,6 +218,7 @@ class _PodcastDetailState extends State { child: Scaffold( body: SafeArea( top: false, + minimum: widget.hide ? EdgeInsets.only(bottom: 50) : EdgeInsets.zero, child: RefreshIndicator( key: _refreshIndicatorKey, color: Theme.of(context).accentColor, @@ -412,7 +420,7 @@ class _PodcastDetailState extends State { }), ), SliverToBoxAdapter( - child: hostsList(context, hosts), + child: hostsList(context, _hosts), ), SliverToBoxAdapter( child: Container( @@ -485,11 +493,16 @@ class _PodcastDetailState extends State { onPressed: () { if (_layout == Layout.three) setState(() { - _layout = Layout.two; + _layout = Layout.one; + }); + else if (_layout == + Layout.two) + setState(() { + _layout = Layout.three; }); else setState(() { - _layout = Layout.three; + _layout = Layout.two; }); }, icon: _layout == Layout.three @@ -505,18 +518,33 @@ class _PodcastDetailState extends State { .color), ), ) - : SizedBox( - height: 10, - width: 30, - child: CustomPaint( - painter: LayoutPainter( - 1, - context - .textTheme - .bodyText1 - .color), - ), - ), + : _layout == Layout.two + ? SizedBox( + height: 10, + width: 30, + child: + CustomPaint( + painter: LayoutPainter( + 1, + context + .textTheme + .bodyText1 + .color), + ), + ) + : SizedBox( + height: 10, + width: 30, + child: + CustomPaint( + painter: LayoutPainter( + 4, + context + .textTheme + .bodyText1 + .color), + ), + ), ), ), ], @@ -528,8 +556,7 @@ class _PodcastDetailState extends State { showNumber: true, layout: _layout, reverse: _reverse, - episodeCount: - widget.podcastLocal.episodeCount, + episodeCount: _episodeCount, ), SliverList( delegate: SliverChildBuilderDelegate( @@ -590,7 +617,7 @@ class _AboutPodcastState extends State { var doc = parse(description); _description = parse(doc.body.text).documentElement.text; } - if(mounted) setState(() => _load = true); + if (mounted) setState(() => _load = true); } _launchUrl(String url) async { diff --git a/lib/settings/layouts.dart b/lib/settings/layouts.dart new file mode 100644 index 0000000..de51e5e --- /dev/null +++ b/lib/settings/layouts.dart @@ -0,0 +1,165 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import '../util/context_extension.dart'; +import '../util/episodegrid.dart'; +import '../util/custompaint.dart'; +import '../local_storage/key_value_storage.dart'; + +class LayoutSetting extends StatefulWidget { + const LayoutSetting({Key key}) : super(key: key); + + @override + _LayoutSettingState createState() => _LayoutSettingState(); +} + +class _LayoutSettingState extends State { + Future _getLayout(String key) async { + KeyValueStorage keyValueStorage = KeyValueStorage(key); + int layout = await keyValueStorage.getInt(); + return Layout.values[layout]; + } + + Widget _gridOptions(BuildContext context, + {String key, Layout layout, Layout option, double scale}) => + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0, left: 20.0), + child: InkWell( + onTap: () async { + KeyValueStorage storage = KeyValueStorage(key); + await storage.saveInt(option.index); + print(option.index); + setState(() {}); + }, + child: Container( + height: 30, + width: 50, + color: layout == option ? context.accentColor : Colors.transparent, + alignment: Alignment.center, + child: SizedBox( + height: 10, + width: 30, + child: CustomPaint( + painter: LayoutPainter( + scale, + layout == option + ? Colors.white + : context.textTheme.bodyText1.color), + ), + ), + ), + ), + ); + + Widget _setDefaultGrid(BuildContext context, {String key}) { + return FutureBuilder( + future: _getLayout(key), + builder: (context, snapshot) { + return snapshot.hasData + ? Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + _gridOptions(context, + key: key, + layout: snapshot.data, + option: Layout.one, + scale: 4), + _gridOptions(context, + key: key, + layout: snapshot.data, + option: Layout.two, + scale: 1), + _gridOptions(context, + key: key, + layout: snapshot.data, + option: Layout.three, + scale: 0), + ], + ) + : Center(); + }); + } + + @override + Widget build(BuildContext context) { + return AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarIconBrightness: Theme.of(context).accentColorBrightness, + systemNavigationBarColor: context.primaryColor, + systemNavigationBarIconBrightness: + Theme.of(context).accentColorBrightness, + ), + child: Scaffold( + appBar: AppBar( + title: Text('Layout'), + elevation: 0, + backgroundColor: context.primaryColor, + ), + body: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(10.0), + ), + Container( + height: 30.0, + padding: EdgeInsets.symmetric(horizontal: 80), + alignment: Alignment.centerLeft, + child: Text('Default grid view', + style: Theme.of(context) + .textTheme + .bodyText1 + .copyWith(color: Theme.of(context).accentColor)), + ), + ListView( + physics: const BouncingScrollPhysics(), + shrinkWrap: true, + scrollDirection: Axis.vertical, + children: [ + ListTile( + contentPadding: + EdgeInsets.only(left: 80.0, right: 20, bottom: 10), + // leading: Icon(Icons.colorize), + title: Text( + 'Podcast page', + ), + subtitle: + _setDefaultGrid(context, key: podcastLayoutKey), + ), + ListTile( + contentPadding: + EdgeInsets.only(left: 80.0, right: 20, bottom: 10), + // leading: Icon(Icons.colorize), + title: Text( + 'Recent tab in homepage', + ), + subtitle: + _setDefaultGrid(context, key: recentLayoutKey), + ), + ListTile( + contentPadding: + EdgeInsets.only(left: 80.0, right: 20, bottom: 10), + // leading: Icon(Icons.colorize), + title: Text( + 'Favorite tab in homepage', + ), + subtitle: _setDefaultGrid(context, key: favLayoutKey), + ), + ListTile( + contentPadding: + EdgeInsets.only(left: 80.0, right: 20, bottom: 10), + // leading: Icon(Icons.colorize), + title: Text( + 'Download tab in homepage', + ), + subtitle: _setDefaultGrid(context, key: downloadLayoutKey), + ), + Divider(height: 2), + ]), + ], + ), + )), + ); + } +} diff --git a/lib/settings/settting.dart b/lib/settings/settting.dart index 2e0e675..966dbc1 100644 --- a/lib/settings/settting.dart +++ b/lib/settings/settting.dart @@ -15,6 +15,7 @@ import '../intro_slider/app_intro.dart'; import '../type/podcastlocal.dart'; import '../local_storage/sqflite_localpodcast.dart'; import 'theme.dart'; +import 'layouts.dart'; import 'storage.dart'; import 'history.dart'; import 'syncing.dart'; @@ -152,6 +153,18 @@ class _SettingsState extends State subtitle: Text('Colors and themes'), ), Divider(height: 2), + ListTile( + onTap: () => Navigator.push( + context, + MaterialPageRoute( + builder: (context) => LayoutSetting())), + contentPadding: + EdgeInsets.symmetric(horizontal: 25.0), + leading: Icon(LineIcons.stop_circle_solid), + title: Text('Layout'), + subtitle: Text('App layout'), + ), + Divider(height: 2), ListTile( onTap: () => Navigator.push( context, @@ -294,6 +307,7 @@ class _SettingsState extends State MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ + SizedBox(width: 75), _feedbackItem( LineIcons.github, 'Submit issue', diff --git a/lib/settings/theme.dart b/lib/settings/theme.dart index d6d418e..c0dfc1e 100644 --- a/lib/settings/theme.dart +++ b/lib/settings/theme.dart @@ -26,175 +26,169 @@ class ThemeSetting extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - Column( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + Padding( + padding: EdgeInsets.all(10.0), + ), + Container( + height: 30.0, + padding: EdgeInsets.symmetric(horizontal: 80), + alignment: Alignment.centerLeft, + child: Text('Interface', + style: Theme.of(context) + .textTheme + .bodyText1 + .copyWith(color: Theme.of(context).accentColor)), + ), + ListView( + physics: const BouncingScrollPhysics(), + shrinkWrap: true, + scrollDirection: Axis.vertical, children: [ - Padding( - padding: EdgeInsets.all(10.0), - ), - Container( - height: 30.0, - padding: EdgeInsets.symmetric(horizontal: 80), - alignment: Alignment.centerLeft, - child: Text('Interface', - style: Theme.of(context) - .textTheme - .bodyText1 - .copyWith(color: Theme.of(context).accentColor)), - ), - ListView( - physics: const BouncingScrollPhysics(), - shrinkWrap: true, - scrollDirection: Axis.vertical, - children: [ - ListTile( - onTap: () => showGeneralDialog( - context: context, - barrierDismissible: true, - barrierLabel: MaterialLocalizations.of(context) - .modalBarrierDismissLabel, - barrierColor: Colors.black54, - transitionDuration: const Duration(milliseconds: 200), - pageBuilder: (BuildContext context, - Animation animaiton, - Animation secondaryAnimation) => - AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarIconBrightness: Brightness.light, - systemNavigationBarColor: - Theme.of(context).brightness == - Brightness.light - ? Color.fromRGBO(113, 113, 113, 1) - : Color.fromRGBO(15, 15, 15, 1), + ListTile( + onTap: () => showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: MaterialLocalizations.of(context) + .modalBarrierDismissLabel, + barrierColor: Colors.black54, + transitionDuration: const Duration(milliseconds: 200), + pageBuilder: (BuildContext context, + Animation animaiton, + Animation secondaryAnimation) => + AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarIconBrightness: Brightness.light, + systemNavigationBarColor: + Theme.of(context).brightness == + Brightness.light + ? Color.fromRGBO(113, 113, 113, 1) + : Color.fromRGBO(15, 15, 15, 1), + ), + child: AlertDialog( + titlePadding: EdgeInsets.only( + top: 20, + left: 40, + right: context.width / 3, + ), + elevation: 1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(10.0))), + title: Text('Theme'), + content: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + RadioListTile( + title: Text('System default'), + value: ThemeMode.system, + groupValue: settings.theme, + onChanged: (value) { + settings.setTheme = value; + Navigator.of(context).pop(); + }), + RadioListTile( + title: Text('Dark mode'), + value: ThemeMode.dark, + groupValue: settings.theme, + onChanged: (value) { + settings.setTheme = value; + Navigator.of(context).pop(); + }), + RadioListTile( + title: Text('Light mode'), + value: ThemeMode.light, + groupValue: settings.theme, + onChanged: (value) { + settings.setTheme = value; + Navigator.of(context).pop(); + }), + ], ), - child: AlertDialog( - titlePadding: EdgeInsets.only( + ), + ), + )), + contentPadding: EdgeInsets.symmetric(horizontal: 80.0), + // leading: Icon(Icons.colorize), + title: Text('Theme'), + subtitle: Text('System default'), + ), + ListTile( + contentPadding: + EdgeInsets.only(left: 80.0, right: 20, bottom: 10), + // leading: Icon(Icons.colorize), + title: Text( + 'Real Dark', + ), + subtitle: Text( + 'Turn on if you think the night is not dark enough'), + trailing: Selector( + selector: (_, setting) => setting.realDark, + builder: (_, data, __) => Switch( + value: data, + onChanged: (boo) async { + settings.setRealDark = boo; + }), + ), + ), + Divider(height: 2), + ListTile( + onTap: () => showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: MaterialLocalizations.of(context) + .modalBarrierDismissLabel, + barrierColor: Colors.black54, + transitionDuration: const Duration(milliseconds: 200), + pageBuilder: (BuildContext context, + Animation animaiton, + Animation secondaryAnimation) => + AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarIconBrightness: Brightness.light, + systemNavigationBarColor: + Theme.of(context).brightness == + Brightness.light + ? Color.fromRGBO(113, 113, 113, 1) + : Color.fromRGBO(15, 15, 15, 1), + ), + child: AlertDialog( + elevation: 1, + titlePadding: EdgeInsets.only( top: 20, left: 40, - right: context.width / 3, - ), - elevation: 1, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(10.0))), - title: Text('Theme'), - content: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - RadioListTile( - title: Text('System default'), - value: ThemeMode.system, - groupValue: settings.theme, - onChanged: (value) { - settings.setTheme = value; - Navigator.of(context).pop(); - }), - RadioListTile( - title: Text('Dark mode'), - value: ThemeMode.dark, - groupValue: settings.theme, - onChanged: (value) { - settings.setTheme = value; - Navigator.of(context).pop(); - }), - RadioListTile( - title: Text('Light mode'), - value: ThemeMode.light, - groupValue: settings.theme, - onChanged: (value) { - settings.setTheme = value; - Navigator.of(context).pop(); - }), - ], - ), - ), + right: 200, + bottom: 0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(10.0))), + title: Text.rich( + TextSpan(text: 'Choose a ', children: [ + TextSpan( + text: 'color', + style: TextStyle( + fontWeight: FontWeight.bold, + color: context.accentColor)) + ])), + content: ColorPicker( + onColorChanged: (value) => + settings.setAccentColor = value, ), - )), - contentPadding: EdgeInsets.symmetric(horizontal: 80.0), - // leading: Icon(Icons.colorize), - title: Text('Theme'), - subtitle: Text('System default'), - ), - ListTile( - contentPadding: - EdgeInsets.only(left: 80.0, right: 20, bottom: 10), - // leading: Icon(Icons.colorize), - title: Text( - 'Real Dark', - ), - subtitle: Text( - 'Turn on if you think the night is not dark enough'), - trailing: Selector( - selector: (_, setting) => setting.realDark, - builder: (_, data, __) => Switch( - value: data, - onChanged: (boo) async { - settings.setRealDark = boo; - }), - ), - ), - Divider(height: 2), - ListTile( - onTap: () => showGeneralDialog( - context: context, - barrierDismissible: true, - barrierLabel: MaterialLocalizations.of(context) - .modalBarrierDismissLabel, - barrierColor: Colors.black54, - transitionDuration: const Duration(milliseconds: 200), - pageBuilder: (BuildContext context, - Animation animaiton, - Animation secondaryAnimation) => - AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarIconBrightness: Brightness.light, - systemNavigationBarColor: - Theme.of(context).brightness == - Brightness.light - ? Color.fromRGBO(113, 113, 113, 1) - : Color.fromRGBO(15, 15, 15, 1), - ), - child: AlertDialog( - elevation: 1, - titlePadding: EdgeInsets.only( - top: 20, - left: 40, - right: 200, - bottom: 0), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(10.0))), - title: Text.rich( - TextSpan(text: 'Choose a ', children: [ - TextSpan( - text: 'color', - style: TextStyle( - fontWeight: FontWeight.bold, - color: context.accentColor)) - ])), - content: ColorPicker( - onColorChanged: (value) => - settings.setAccentColor = value, - ), - ))), - contentPadding: EdgeInsets.only(left: 80.0, right: 25), - title: Text('Accent color'), - subtitle: Text('Include the overlay color'), - trailing: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, color: context.accentColor), - ), - ), - Divider(height: 2), - ], + ))), + contentPadding: EdgeInsets.only(left: 80.0, right: 25), + title: Text('Accent color'), + subtitle: Text('Include the overlay color'), + trailing: Container( + height: 25, + width: 25, + decoration: BoxDecoration( + shape: BoxShape.circle, color: context.accentColor), + ), ), + Divider(height: 2), ], ), ], diff --git a/lib/state/subscribe_podcast.dart b/lib/state/subscribe_podcast.dart index 7759096..a19f555 100644 --- a/lib/state/subscribe_podcast.dart +++ b/lib/state/subscribe_podcast.dart @@ -140,11 +140,11 @@ Future subIsolateEntryPoint(SendPort sendPort) async { String realUrl = response.redirects.isEmpty ? rss : response.realUri.toString(); - print(realUrl); bool checkUrl = await dbHelper.checkPodcast(realUrl); - String imageUrl; + if (checkUrl) { img.Image thumbnail; + String imageUrl; try { Response> imageResponse = await Dio().get>( p.itunes.image.href, @@ -153,7 +153,6 @@ Future subIsolateEntryPoint(SendPort sendPort) async { img.Image image = img.decodeImage(imageResponse.data); thumbnail = img.copyResize(image, width: 300); } catch (e) { - print(e); try { Response> imageResponse = await Dio().get>( item.imgUrl, diff --git a/lib/util/custompaint.dart b/lib/util/custompaint.dart index e55f99c..6d05d97 100644 --- a/lib/util/custompaint.dart +++ b/lib/util/custompaint.dart @@ -17,10 +17,12 @@ class LayoutPainter extends CustomPainter { ..strokeCap = StrokeCap.round; canvas.drawRect(Rect.fromLTRB(0, 0, 10 + 5 * scale, 10), _paint); - canvas.drawRect( - Rect.fromLTRB(10 + 5 * scale, 0, 20 + 10 * scale, 10), _paint); - canvas.drawRect( - Rect.fromLTRB(20 + 5 * scale, 0, 30, 10 - 10 * scale), _paint); + if (scale < 4) { + canvas.drawRect( + Rect.fromLTRB(10 + 5 * scale, 0, 20 + 10 * scale, 10), _paint); + canvas.drawRect( + Rect.fromLTRB(20 + 5 * scale, 0, 30, 10 - 10 * scale), _paint); + } } @override @@ -664,7 +666,10 @@ class _HeartOpenState extends State left: widget.width * position, bottom: widget.height * _value * scale, child: Icon(Icons.favorite, - color: _value > 0.5 ? Colors.red.withOpacity(2 - _value*2) : Colors.red, size: 20 * _value * scale), + color: _value > 0.5 + ? Colors.red.withOpacity(2 - _value * 2) + : Colors.red, + size: 20 * _value * scale), ); } diff --git a/lib/util/episodegrid.dart b/lib/util/episodegrid.dart index 6358ec6..db5834e 100644 --- a/lib/util/episodegrid.dart +++ b/lib/util/episodegrid.dart @@ -18,7 +18,7 @@ import 'colorize.dart'; import 'context_extension.dart'; import 'custompaint.dart'; -enum Layout { two, three } +enum Layout { three, two, one } class EpisodeGrid extends StatelessWidget { final List episodes; @@ -56,6 +56,117 @@ class EpisodeGrid extends StatelessWidget { this.reverse, }) : super(key: key); + Widget _title(EpisodeBrief episode) => Container( + alignment: + layout == Layout.one ? Alignment.centerLeft : Alignment.topLeft, + padding: EdgeInsets.only(top: 2.0), + child: Text( + episode.title, + maxLines: layout == Layout.one ? 1 : 4, + overflow: + layout == Layout.one ? TextOverflow.ellipsis : TextOverflow.fade, + ), + ); + Widget _circleImage(BuildContext context, + {EpisodeBrief episode, Color color, bool boo}) => + Container( + height: context.width / 16, + width: context.width / 16, + child: boo + ? Center() + : CircleAvatar( + backgroundColor: color.withOpacity(0.5), + backgroundImage: FileImage(File("${episode.imagePath}")), + ), + ); + Widget _listenIndicater(BuildContext context, + {EpisodeBrief episode, int isListened}) => + Selector>( + selector: (_, audio) => Tuple2(audio.episode, audio.playerRunning), + builder: (_, data, __) { + return (episode.enclosureUrl == data.item1?.enclosureUrl && + data.item2) + ? Container( + height: 20, + width: 20, + margin: EdgeInsets.symmetric(horizontal: 2), + decoration: BoxDecoration( + shape: BoxShape.circle, + ), + child: WaveLoader(color: context.accentColor)) + : layout == Layout.two && isListened > 0 + ? Container( + height: 20, + width: 20, + margin: EdgeInsets.symmetric(horizontal: 2), + decoration: BoxDecoration( + color: context.accentColor, + shape: BoxShape.circle, + ), + child: CustomPaint( + painter: ListenedAllPainter( + Colors.white, + )), + ) + : Center(); + }); + + Widget _downloadIndicater(BuildContext context, {EpisodeBrief episode}) => + showDownload || layout != Layout.three + ? Container( + child: (episode.enclosureUrl != episode.mediaId) + ? Container( + height: 20, + width: 20, + margin: EdgeInsets.symmetric(horizontal: 5), + padding: EdgeInsets.symmetric(horizontal: 2), + decoration: BoxDecoration( + color: context.accentColor, + shape: BoxShape.circle, + ), + child: Icon( + Icons.done_all, + size: 15, + color: Colors.white, + ), + ) + : Center(), + ) + : Center(); + Widget _isNewIndicator(EpisodeBrief episode) => episode.isNew == 1 + ? Container( + padding: EdgeInsets.symmetric(horizontal: 2), + child: Text('New', + style: TextStyle(color: Colors.red, fontStyle: FontStyle.italic)), + ) + : Center(); + + Widget _numberIndicater(BuildContext context, {int index, Color color}) => + showNumber + ? Container( + alignment: Alignment.topRight, + child: Text( + reverse + ? (index + 1).toString() + : (episodeCount - index).toString(), + style: GoogleFonts.teko( + textStyle: TextStyle( + fontSize: context.width / 24, + color: color, + ), + ), + ), + ) + : Center(); + Widget _pubDate(BuildContext context, {EpisodeBrief episode, Color color}) => + Text( + episode.dateToString(), + style: TextStyle( + fontSize: context.width / 35, + color: color, + fontStyle: FontStyle.italic), + ); + @override Widget build(BuildContext context) { double _width = MediaQuery.of(context).size.width; @@ -139,8 +250,10 @@ class EpisodeGrid extends StatelessWidget { options: options, itemCount: episodes.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - childAspectRatio: layout == Layout.three ? 1 : 1.5, - crossAxisCount: layout == Layout.three ? 3 : 2, + childAspectRatio: + layout == Layout.three ? 1 : layout == Layout.two ? 1.5 : 4, + crossAxisCount: + layout == Layout.three ? 3 : layout == Layout.two ? 2 : 1, mainAxisSpacing: 6.0, crossAxisSpacing: 6.0, ), @@ -211,166 +324,71 @@ class EpisodeGrid extends StatelessWidget { ), ), child: Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( - flex: 2, + flex: layout == Layout.one ? 1 : 2, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - Container( - height: _width / 16, - width: _width / 16, - child: boo - ? Center() - : CircleAvatar( - backgroundColor: - _c.withOpacity(0.5), - backgroundImage: FileImage(File( - "${episodes[index].imagePath}")), - ), - ), + layout != Layout.one + ? _circleImage(context, + episode: episodes[index], + color: _c, + boo: boo) + : _pubDate(context, + episode: episodes[index], + color: _c), Spacer(), - Selector>( - selector: (_, audio) => Tuple2( - audio.episode, - audio.playerRunning), - builder: (_, data, __) { - return (episodes[index] - .enclosureUrl == - data.item1 - ?.enclosureUrl && - data.item2) - ? Container( - height: 20, - width: 20, - margin: - EdgeInsets.symmetric( - horizontal: 2), - decoration: BoxDecoration( - shape: BoxShape.circle, - ), - child: WaveLoader( - color: context - .accentColor)) - : layout == Layout.two && - snapshot.data > 0 - ? Container( - height: 20, - width: 20, - margin: EdgeInsets - .symmetric( - horizontal: - 2), - decoration: - BoxDecoration( - color: context - .accentColor, - shape: - BoxShape.circle, - ), - child: CustomPaint( - painter: - ListenedAllPainter( - Colors.white, - )), - ) - : Center(); - }), - showDownload || layout == Layout.two - ? Container( - child: (episodes[index] - .enclosureUrl != - episodes[index].mediaId) - ? Container( - height: 20, - width: 20, - margin: EdgeInsets - .symmetric( - horizontal: 5), - padding: EdgeInsets - .symmetric( - horizontal: 2), - decoration: - BoxDecoration( - color: context - .accentColor, - shape: - BoxShape.circle, - ), - child: Icon( - Icons.done_all, - size: 15, - color: Colors.white, - ), - ) - : Center(), - ) - : Center(), - episodes[index].isNew == 1 - ? Container( - padding: EdgeInsets.symmetric( - horizontal: 2), - child: Text('New', - style: TextStyle( - color: Colors.red, - fontStyle: - FontStyle.italic)), - ) - : Center(), - showNumber - ? Container( - alignment: Alignment.topRight, - child: Text( - reverse - ? (index + 1).toString() - : (episodeCount - index) - .toString(), - style: GoogleFonts.teko( - textStyle: TextStyle( - fontSize: _width / 24, - color: _c, - ), - ), - ), - ) - : Center(), + _listenIndicater(context, + episode: episodes[index], + isListened: snapshot.data), + _downloadIndicater(context, + episode: episodes[index]), + _isNewIndicator(episodes[index]), + _numberIndicater(context, + index: index, color: _c) ], ), ), Expanded( - flex: 5, - child: Container( - alignment: Alignment.topLeft, - padding: EdgeInsets.only(top: 2.0), - child: Text( - episodes[index].title, - style: TextStyle( - // fontSize: _width / 32, - ), - maxLines: 4, - overflow: TextOverflow.fade, - ), - ), + flex: layout == Layout.one ? 3 : 5, + child: layout != Layout.one + ? _title(episodes[index]) + : Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + _circleImage(context, + episode: episodes[index], + color: _c, + boo: boo), + SizedBox( + width: 5, + ), + Expanded( + child: + _title(episodes[index])) + ], + ), ), Expanded( flex: 1, child: Row( + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - Align( - alignment: Alignment.bottomLeft, - child: Text( - episodes[index].dateToString(), - style: TextStyle( - fontSize: _width / 35, - color: _c, - fontStyle: FontStyle.italic), - ), - ), + layout != Layout.one + ? Align( + alignment: Alignment.bottomLeft, + child: _pubDate(context, + episode: episodes[index], + color: _c), + ) + : SizedBox(width: 1), Spacer(), - layout == Layout.two && + layout != Layout.three && episodes[index].duration != 0 ? Container( alignment: Alignment.center, @@ -401,7 +419,7 @@ class EpisodeGrid extends StatelessWidget { // fontStyle: FontStyle.italic, ), ), - layout == Layout.two && + layout != Layout.three && episodes[index] .enclosureLength != null && @@ -424,19 +442,19 @@ class EpisodeGrid extends StatelessWidget { Padding( padding: EdgeInsets.all(1), ), - showFavorite || layout == Layout.two + showFavorite || layout != Layout.three ? FutureBuilder( future: _isLiked(episodes[index]), initialData: false, builder: (context, snapshot) => Container( - alignment: - Alignment.bottomRight, + alignment: Alignment.center, child: (snapshot.data) ? IconTheme( data: IconThemeData( - size: 15), + size: + _width / 35), child: Icon( Icons.favorite, color: Colors.red, diff --git a/lib/util/pageroute.dart b/lib/util/pageroute.dart index 7129650..8446498 100644 --- a/lib/util/pageroute.dart +++ b/lib/util/pageroute.dart @@ -39,22 +39,19 @@ class SlideLeftHideRoute extends PageRouteBuilder { Animation secondaryAnimation, ) => page, - transitionDuration: Duration(seconds: 2), + transitionDuration: Duration(milliseconds: 500), transitionsBuilder: ( BuildContext context, Animation animation, Animation secondaryAnimation, Widget child, ) { - if (animation.isCompleted) - return child; - else - return SlideTransition( - position: Tween( - begin: const Offset(1, 0), - end: Offset.zero, - ).animate(animation), - child: transitionPage); + return SlideTransition( + position: Tween( + begin: const Offset(1, 0), + end: Offset.zero, + ).animate(animation), + child: child); }, ); }