From e9ba82d5dba52027056ad5b367a1bb91e92676ad Mon Sep 17 00:00:00 2001 From: stonegate Date: Tue, 2 Jun 2020 22:05:49 +0800 Subject: [PATCH] :bug: Beter support for small screen. --- README.md | 4 +- android/app/build.gradle | 2 +- lib/episodes/episodedetail.dart | 2 +- lib/home/about.dart | 193 +++++++++++++++--------------- lib/home/addpodcast.dart | 196 +++++++++++++++++++++++++------ lib/home/audioplayer.dart | 27 ++--- lib/home/home.dart | 2 +- lib/home/home_groups.dart | 2 +- lib/home/importompl.dart | 2 +- lib/podcasts/podcastgroup.dart | 15 ++- lib/podcasts/podcastlist.dart | 31 +++-- lib/podcasts/podcastmanage.dart | 18 +-- lib/settings/settting.dart | 52 ++++---- lib/settings/theme.dart | 69 +++++------ lib/state/subscribe_podcast.dart | 34 ++++-- lib/util/pageroute.dart | 29 +++-- pubspec.yaml | 2 +- 17 files changed, 417 insertions(+), 263 deletions(-) diff --git a/README.md b/README.md index d66ba69..d08a6b9 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Credit to flutter team and all involved plugins, especially [webfeed](https://g The podcasts search engine is powered by [ListenNotes](https://listennotes.com). ## Features -* Subscriptoin group management +* Podcasts group management * Playlist support * Sleep timer / Speed setting * OMPL file export and import @@ -28,7 +28,7 @@ The podcasts search engine is powered by [ListenNotes](https://listennotes.com). * Listen and subscribe history record * Dark mode / Accent color * Download for offline playing -* Share clip on twitter +* Share clip(video format) on twitter More to come... diff --git a/android/app/build.gradle b/android/app/build.gradle index 9392a12..f071420 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -49,7 +49,7 @@ android { applicationId "com.stonegate.tsacdop" minSdkVersion 19 targetSdkVersion 28 - versionCode 14 + versionCode 15 versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/lib/episodes/episodedetail.dart b/lib/episodes/episodedetail.dart index a94e1a4..2337e32 100644 --- a/lib/episodes/episodedetail.dart +++ b/lib/episodes/episodedetail.dart @@ -580,7 +580,7 @@ class _MenuBarState extends State { padding: EdgeInsets.symmetric(horizontal: 20.0), child: Row( children: [ - Text('Play Now', + Text('Play', style: TextStyle( color: Theme.of(context).accentColor, fontSize: 15, diff --git a/lib/home/about.dart b/lib/home/about.dart index 654d761..63fce52 100644 --- a/lib/home/about.dart +++ b/lib/home/about.dart @@ -4,7 +4,7 @@ import 'package:tsacdop/util/custompaint.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:line_icons/line_icons.dart'; -const String version = '0.3.1'; +const String version = '0.3.2'; class AboutApp extends StatelessWidget { _launchUrl(String url) async { @@ -74,105 +74,110 @@ class AboutApp extends StatelessWidget { title: Text('About'), ), body: SafeArea( - child: Container( - padding: EdgeInsets.all(20), - alignment: Alignment.topLeft, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Container( - height: 200.0, - alignment: Alignment.center, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - Image( - image: AssetImage('assets/logo.png'), - height: 80, - ), - Text('Version: $version'), - ], - ), - ), - Container( - padding: EdgeInsets.symmetric(horizontal: 50), - child: Text( - 'Tsacdop is a podcast player developed in flutter, a clean, simply beautiful and friendly app.', - textAlign: TextAlign.center, - ), - ), - Padding( - padding: EdgeInsets.all(10.0), - ), - Container( - padding: EdgeInsets.only(top: 20.0, bottom: 10.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all( - color: Theme.of(context).accentColor, width: 1), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: EdgeInsets.symmetric(horizontal: 20.0), - alignment: Alignment.centerLeft, - child: Text( - 'Developer', - style: - TextStyle(color: Theme.of(context).accentColor), - ), - ), - _listItem(context, 'Twitter', LineIcons.twitter, - 'https://twitter.com/shimenmen'), - _listItem(context, 'GitHub', LineIcons.github_alt, - 'https://github.com/stonega'), - _listItem(context, 'Medium', LineIcons.medium, - 'https://medium.com/@stonegate'), - ], - ), - ), - Spacer(), - Container( - height: 50, - alignment: Alignment.center, - child: GestureDetector( - onTapDown: (detail) async { - OverlayEntry _overlayEntry; - _overlayEntry = _createOverlayEntry(detail); - Overlay.of(context).insert(_overlayEntry); - await Future.delayed(Duration(seconds: 2)); - _overlayEntry?.remove(); - }, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + height: 200.0, + alignment: Alignment.center, + child: Column( mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, children: [ - Image.asset( - 'assets/text.png', - height: 25, - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 5), - ), - Icon( - Icons.favorite, - color: Colors.blue, - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 5), - ), - FlutterLogo( - size: 18, + Image( + image: AssetImage('assets/logo.png'), + height: 80, ), + Text('Version: $version'), ], ), ), - ), - ], + Container( + padding: EdgeInsets.symmetric(horizontal: 50), + child: Text( + 'Tsacdop is a podcast player developed in flutter, a clean, simply beautiful and friendly app.', + textAlign: TextAlign.center, + ), + ), + Padding( + padding: EdgeInsets.all(10.0), + ), + Container( + padding: EdgeInsets.only(top: 20.0, bottom: 10.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all( + color: Theme.of(context).accentColor, width: 1), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 20.0), + alignment: Alignment.centerLeft, + child: Text( + 'Developer', + style: TextStyle( + color: Theme.of(context).accentColor), + ), + ), + _listItem(context, 'Twitter', LineIcons.twitter, + 'https://twitter.com/shimenmen'), + _listItem(context, 'GitHub', LineIcons.github_alt, + 'https://github.com/stonega'), + _listItem(context, 'Medium', LineIcons.medium, + 'https://medium.com/@stonegate'), + ], + ), + ), + //Spacer(), + Padding( + padding: EdgeInsets.symmetric(vertical: 50), + ), + Container( + height: 50, + alignment: Alignment.center, + child: GestureDetector( + onTapDown: (detail) async { + OverlayEntry _overlayEntry; + _overlayEntry = _createOverlayEntry(detail); + Overlay.of(context).insert(_overlayEntry); + await Future.delayed(Duration(seconds: 2)); + _overlayEntry?.remove(); + }, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/text.png', + height: 25, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 5), + ), + Icon( + Icons.favorite, + color: Colors.blue, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 5), + ), + FlutterLogo( + size: 18, + ), + ], + ), + ), + ), + ], + ), ), ), )), diff --git a/lib/home/addpodcast.dart b/lib/home/addpodcast.dart index d7f35f3..d8c82b7 100644 --- a/lib/home/addpodcast.dart +++ b/lib/home/addpodcast.dart @@ -18,24 +18,26 @@ import '../.env.dart'; class MyHomePageDelegate extends SearchDelegate { final String searchFieldLabel; + MyHomePageDelegate({this.searchFieldLabel}) : super( - searchFieldLabel: searchFieldLabel, - ); - static Future getList(String searchText) async { - String apiKey = environment['apiKey']; - String url = - "https://listennotes.p.rapidapi.com/api/v1/search?only_in=title%2Cdescription&q=" + - "$searchText&type=podcast"; - Response response = await Dio().get(url, - options: Options(headers: { - 'X-RapidAPI-Key': "$apiKey", - 'Accept': "application/json" - })); - Map searchResultMap = jsonDecode(response.toString()); - var searchResult = SearchPodcast.fromJson(searchResultMap); - return searchResult.results; - } + searchFieldLabel: searchFieldLabel, + ); + + //static Future getList(String searchText) async { + // String apiKey = environment['apiKey']; + // String url = + // "https://listennotes.p.rapidapi.com/api/v1/search?only_in=title%2Cdescription&q=" + + // "$searchText&type=podcast"; + // Response response = await Dio().get(url, + // options: Options(headers: { + // 'X-RapidAPI-Key': "$apiKey", + // 'Accept': "application/json" + // })); + // Map searchResultMap = jsonDecode(response.toString()); + // var searchResult = SearchPodcast.fromJson(searchResultMap); + // return searchResult.results; + //} static Future getRss(String url) async { try { @@ -185,27 +187,130 @@ class MyHomePageDelegate extends SearchDelegate { }, ); else - return FutureBuilder( - future: getList(query), - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (!snapshot.hasData && query != null) - return Container( - padding: EdgeInsets.only(top: 200), - alignment: Alignment.topCenter, - child: CircularProgressIndicator(), - ); - List content = snapshot.data; - return ListView.builder( - scrollDirection: Axis.vertical, - itemCount: content.length, - itemBuilder: (BuildContext context, int index) { - return SearchResult( - onlinePodcast: content[index], - ); - }, - ); - }, + return SearchList( + query: query, ); + // return FutureBuilder( + // future: getList(query), + // builder: (BuildContext context, AsyncSnapshot snapshot) { + // if (!snapshot.hasData && query != null) + // return Container( + // padding: EdgeInsets.only(top: 200), + // alignment: Alignment.topCenter, + // child: CircularProgressIndicator(), + // ); + // List content = snapshot.data; + // return ListView.builder( + // scrollDirection: Axis.vertical, + // itemCount: content.length, + // itemBuilder: (BuildContext context, int index) { + // return SearchResult( + // onlinePodcast: content[index], + // ); + // }, + // ); + // }, + // ); + } +} + +class SearchList extends StatefulWidget { + final String query; + SearchList({this.query, Key key}) : super(key: key); + + @override + _SearchListState createState() => _SearchListState(); +} + +class _SearchListState extends State { + int _nextOffset; + List _podcastList; + int _offset; + bool _loading; + @override + void initState() { + super.initState(); + _nextOffset = 0; + _podcastList = []; + } + + Future _getList(String searchText, int nextOffset) async { + String apiKey = environment['apiKey']; + String url = "https://listen-api.listennotes.com/api/v2/search?q=" + + searchText + + "&sort_by_date=0&type=podcast&offset=$nextOffset"; + Response response = await Dio().get(url, + options: Options(headers: { + 'X-ListenAPI-Key': "$apiKey", + 'Accept': "application/json" + })); + Map searchResultMap = jsonDecode(response.toString()); + var searchResult = SearchPodcast.fromJson(searchResultMap); + _offset = searchResult.nextOffset; + _podcastList.addAll(searchResult.results.cast()); + _loading = false; + return _podcastList; + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _getList(widget.query, _nextOffset), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (!snapshot.hasData && widget.query != null) + return Container( + padding: EdgeInsets.only(top: 200), + alignment: Alignment.topCenter, + child: CircularProgressIndicator(), + ); + 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: [ + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 20.0), + child: SizedBox( + height: 30, + child: OutlineButton( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.all(Radius.circular(15))), + child: _loading + ? SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + )) + : Text('Load more'), + onPressed: () => _loading + ? null + : setState(() { + _loading = true; + _nextOffset = _offset; + }))), + ) + ], + ), + ) + ], + ); + }, + ); } } @@ -292,6 +397,25 @@ class _SearchResultState extends State 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( + width: 40, + height: 40, + alignment: Alignment.center, + color: context.primaryColorDark, + child: Icon(Icons.error)), ), ), title: Text(widget.onlinePodcast.title), diff --git a/lib/home/audioplayer.dart b/lib/home/audioplayer.dart index 4e3832f..f35d527 100644 --- a/lib/home/audioplayer.dart +++ b/lib/home/audioplayer.dart @@ -460,15 +460,10 @@ class _PlayerWidgetState extends State { style: TextStyle( color: Theme.of(context).accentColor), ) - : Row( - children: [ - Text( - _stringForSeconds(data.item2) ?? '', - ), - Text( - ' Left', - ), - ], + : Text( + (_stringForSeconds(data.item2) ?? '') + + ' Left', + maxLines: 2, ), ); }, @@ -480,10 +475,9 @@ class _PlayerWidgetState extends State { selector: (_, audio) => audio.audioState, builder: (_, audioplay, __) { return Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, children: [ - Spacer(), + //Spacer(), audioplay == BasicPlaybackState.playing ? InkWell( onTap: @@ -518,7 +512,7 @@ class _PlayerWidgetState extends State { )), ), Container( - height: 50.0, + height: 40.0, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.black), @@ -531,8 +525,9 @@ class _PlayerWidgetState extends State { ), ), IconButton( + padding: EdgeInsets.zero, onPressed: () => audio.playNext(), - iconSize: 25.0, + iconSize: 20.0, icon: Icon(Icons.skip_next), color: Theme.of(context).tabBarTheme.labelColor), @@ -1251,7 +1246,7 @@ class _ControlPanelState extends State mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( - padding: EdgeInsets.symmetric(horizontal: 30.0), + padding: EdgeInsets.symmetric(horizontal: 25.0), onPressed: backplay == BasicPlaybackState.playing ? () => audio.forwardAudio(-10) @@ -1323,7 +1318,7 @@ class _ControlPanelState extends State ), ), IconButton( - padding: EdgeInsets.symmetric(horizontal: 30.0), + padding: EdgeInsets.symmetric(horizontal: 25.0), onPressed: backplay == BasicPlaybackState.playing ? () => audio.forwardAudio(30) diff --git a/lib/home/home.dart b/lib/home/home.dart index cfb1eff..977546f 100644 --- a/lib/home/home.dart +++ b/lib/home/home.dart @@ -158,7 +158,7 @@ class _HomeState extends State with SingleTickerProviderStateMixin { controller: _controller, tabs: [ Tab( - child: Text('Recent Update'), + child: Text('Recent'), ), Tab( child: Text('Favorite'), diff --git a/lib/home/home_groups.dart b/lib/home/home_groups.dart index 8cae580..4b19440 100644 --- a/lib/home/home_groups.dart +++ b/lib/home/home_groups.dart @@ -440,7 +440,7 @@ class _PodcastPreviewState extends State { onPressed: () { Navigator.push( context, - SlideLeftRoute( + SlideLeftHideRoute( page: PodcastDetail( podcastLocal: widget.podcastLocal, )), diff --git a/lib/home/importompl.dart b/lib/home/importompl.dart index e08eb1a..ff482cd 100644 --- a/lib/home/importompl.dart +++ b/lib/home/importompl.dart @@ -39,7 +39,7 @@ class Import extends StatelessWidget { groupList.subscribeNewPodcast(item.id); return importColumn("Fetch data ${item.title}", context); case SubscribeState.fetch: - groupList.updatePodcast(item.id); + // groupList.updatePodcast(item.id); return importColumn("Subscribe success ${item.title}", context); case SubscribeState.exist: return importColumn( diff --git a/lib/podcasts/podcastgroup.dart b/lib/podcasts/podcastgroup.dart index cadc18b..770c0ee 100644 --- a/lib/podcasts/podcastgroup.dart +++ b/lib/podcasts/podcastgroup.dart @@ -253,10 +253,8 @@ class _PodcastCardState extends State child: _addGroup ? Row( mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, children: [ Expanded( - flex: 4, child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( @@ -284,9 +282,10 @@ class _PodcastCardState extends State }).toList()), ), ), - Expanded( - flex: 1, + SizedBox( + width: 100, child: Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ IconButton( icon: Icon(Icons.clear), @@ -374,7 +373,7 @@ class _PodcastCardState extends State titlePadding: EdgeInsets.only( top: 20, left: 20, - right: 100, + right: context.width / 3, bottom: 20), title: Text('Skip seconds at the beginning'), @@ -452,7 +451,7 @@ class _PodcastCardState extends State titlePadding: EdgeInsets.only( top: 20, left: 20, - right: 200, + right: context.width / 3, bottom: 20), title: Text('Remove confirm'), content: Text( @@ -535,8 +534,8 @@ class _RenameGroupState extends State { borderRadius: BorderRadius.all(Radius.circular(10))), elevation: 1, contentPadding: EdgeInsets.symmetric(horizontal: 20), - titlePadding: - EdgeInsets.only(top: 20, left: 20, right: 200, bottom: 20), + titlePadding: EdgeInsets.only( + top: 20, left: 20, right: context.width / 3, bottom: 20), actionsPadding: EdgeInsets.all(0), actions: [ FlatButton( diff --git a/lib/podcasts/podcastlist.dart b/lib/podcasts/podcastlist.dart index 17071c8..cacebb0 100644 --- a/lib/podcasts/podcastlist.dart +++ b/lib/podcasts/podcastlist.dart @@ -13,6 +13,7 @@ import '../type/podcastlocal.dart'; import '../local_storage/sqflite_localpodcast.dart'; import '../podcasts/podcastdetail.dart'; import '../util/pageroute.dart'; +import '../util/context_extension.dart'; class AboutPodcast extends StatefulWidget { final PodcastLocal podcastLocal; @@ -48,7 +49,8 @@ class _AboutPodcastState extends State { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10.0))), - titlePadding: EdgeInsets.only(top: 20, left: 20, right: 200, bottom: 20), + titlePadding: EdgeInsets.only( + top: 20, left: 20, right: context.width / 3, bottom: 20), actions: [ FlatButton( padding: EdgeInsets.all(10.0), @@ -63,18 +65,21 @@ class _AboutPodcastState extends State { ), ], title: Text(widget.podcastLocal.title), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - !_load - ? Center() - : _description != null ? Html(data: _description) : Center(), - (widget.podcastLocal.author != null) - ? Text(widget.podcastLocal.author, - style: TextStyle(color: Colors.blue)) - : Center(), - ], + content: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + !_load + ? Center() + : _description != null ? Html(data: _description) : Center(), + (widget.podcastLocal.author != null) + ? Text(widget.podcastLocal.author, + style: TextStyle(color: Colors.blue)) + : Center(), + ], + ), ), ); } diff --git a/lib/podcasts/podcastmanage.dart b/lib/podcasts/podcastmanage.dart index 878afef..4ab2c8c 100644 --- a/lib/podcasts/podcastmanage.dart +++ b/lib/podcasts/podcastmanage.dart @@ -49,11 +49,11 @@ class _PodcastManageState extends State _fraction = _animation.value; }); }); - _menuAnimation = Tween(begin: 0.0, end: 1.0).animate( - CurvedAnimation(parent: _menuController, curve: Curves.easeIn)) - ..addListener(() { - if (mounted) setState(() => _menuValue = _menuAnimation.value); - }); + _menuAnimation = Tween(begin: 0.0, end: 1.0) + .animate(CurvedAnimation(parent: _menuController, curve: Curves.easeIn)) + ..addListener(() { + if (mounted) setState(() => _menuValue = _menuAnimation.value); + }); _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { @@ -361,7 +361,9 @@ class _PodcastManageState extends State EdgeInsets.only( top: 20, left: 20, - right: 200, + right: context + .width / + 3, bottom: 20), title: Text( 'Delete confirm'), @@ -531,8 +533,8 @@ class _AddGroupState extends State { borderRadius: BorderRadius.all(Radius.circular(10))), elevation: 1, contentPadding: EdgeInsets.symmetric(horizontal: 20), - titlePadding: - EdgeInsets.only(top: 20, left: 20, right: 200, bottom: 20), + titlePadding: EdgeInsets.only( + top: 20, left: 20, right: context.width / 3, bottom: 20), actionsPadding: EdgeInsets.all(0), actions: [ FlatButton( diff --git a/lib/settings/settting.dart b/lib/settings/settting.dart index 2a80a4b..2e0e675 100644 --- a/lib/settings/settting.dart +++ b/lib/settings/settting.dart @@ -85,7 +85,10 @@ class _SettingsState extends State Padding( padding: EdgeInsets.symmetric(vertical: 5), ), - Text(name) + Text( + name, + maxLines: 2, + ) ], ), ), @@ -284,28 +287,31 @@ class _SettingsState extends State ), ), _showFeedback - ? Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - _feedbackItem( - LineIcons.github, - 'Submit issue', - 'https://github.com/stonega/tsacdop/issues'), - _feedbackItem( - LineIcons.telegram, - 'Join group', - 'https://t.me/joinchat/Bk3LkRpTHy40QYC78PK7Qg'), - _feedbackItem( - LineIcons.envelope_open_text_solid, - 'Write to me', - 'mailto:?subject=Tsacdop Feedback'), - _feedbackItem( - LineIcons.google_play, - 'Rate on Play', - 'https://play.google.com/store/apps/details?id=com.stonegate.tsacdop') - ], + ? SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _feedbackItem( + LineIcons.github, + 'Submit issue', + 'https://github.com/stonega/tsacdop/issues'), + _feedbackItem( + LineIcons.telegram, + 'Join group', + 'https://t.me/joinchat/Bk3LkRpTHy40QYC78PK7Qg'), + _feedbackItem( + LineIcons.envelope_open_text_solid, + 'Write to me', + 'mailto:?subject=Tsacdop Feedback'), + _feedbackItem( + LineIcons.google_play, + 'Rate on Play', + 'https://play.google.com/store/apps/details?id=com.stonegate.tsacdop') + ], + ), ) : Center(), Divider( diff --git a/lib/settings/theme.dart b/lib/settings/theme.dart index 9571294..d6d418e 100644 --- a/lib/settings/theme.dart +++ b/lib/settings/theme.dart @@ -72,45 +72,46 @@ class ThemeSetting extends StatelessWidget { titlePadding: EdgeInsets.only( top: 20, left: 40, - right: 200, + right: context.width / 3, ), elevation: 1, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(10.0))), title: Text('Theme'), - content: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - RadioListTile( - title: Container( - padding: - EdgeInsets.only(right: 80), - child: 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(); - }), - ], + 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(); + }), + ], + ), ), ), )), @@ -357,4 +358,4 @@ class _ColorPickerState extends State ), ); } -} \ No newline at end of file +} diff --git a/lib/state/subscribe_podcast.dart b/lib/state/subscribe_podcast.dart index ef61a60..7759096 100644 --- a/lib/state/subscribe_podcast.dart +++ b/lib/state/subscribe_podcast.dart @@ -36,7 +36,7 @@ class SubscribeWorker extends ChangeNotifier { SubscribeItem _subscribeItem; SubscribeItem _currentSubscribeItem = SubscribeItem('', ''); bool _created = false; - bool get created=> _created; + bool get created => _created; setSubscribeItem(SubscribeItem item) async { _subscribeItem = item; @@ -117,9 +117,23 @@ Future subIsolateEntryPoint(SendPort sendPort) async { receiveTimeout: 20000, ); print(rss); + try { Response response = await Dio(options).get(rss); - var p = RssFeed.parse(response.data); + RssFeed p; + try { + p = RssFeed.parse(response.data); + } on ArgumentError catch (e) { + print(e); + sendPort.send([item.title, item.url, 6]); + await Future.delayed(Duration(seconds: 2)); + sendPort.send([item.title, item.url, 4]); + items.removeWhere((element) => element.url == item.url); + if (items.length > 0) { + await _subscribe(items.first); + } else + sendPort.send("done"); + } var dir = await getApplicationDocumentsDirectory(); @@ -128,31 +142,35 @@ Future subIsolateEntryPoint(SendPort sendPort) async { print(realUrl); bool checkUrl = await dbHelper.checkPodcast(realUrl); - + String imageUrl; if (checkUrl) { img.Image thumbnail; try { Response> imageResponse = await Dio().get>( p.itunes.image.href, options: Options(responseType: ResponseType.bytes)); + imageUrl = p.itunes.image.href; img.Image image = img.decodeImage(imageResponse.data); thumbnail = img.copyResize(image, width: 300); - } on DioError catch (e) { + } catch (e) { print(e); try { Response> imageResponse = await Dio().get>( item.imgUrl, options: Options(responseType: ResponseType.bytes)); + imageUrl = item.imgUrl; img.Image image = img.decodeImage(imageResponse.data); thumbnail = img.copyResize(image, width: 300); - } on DioError catch (e) { + } catch (e) { print(e); try { Response> imageResponse = await Dio().get>( "https://ui-avatars.com/api/?size=300&background=4D91BE&color=fff&name=${item.title}&length=2&bold=true", options: Options(responseType: ResponseType.bytes)); + imageUrl = + "https://ui-avatars.com/api/?size=300&background=4D91BE&color=fff&name=${item.title}&length=2&bold=true"; thumbnail = img.decodeImage(imageResponse.data); - } on DioError catch (e) { + } catch (e) { print(e); sendPort.send([item.title, item.url, 6]); await Future.delayed(Duration(seconds: 2)); @@ -174,8 +192,8 @@ Future subIsolateEntryPoint(SendPort sendPort) async { String author = p.itunes.author ?? p.author ?? ''; String provider = p.generator ?? ''; String link = p.link ?? ''; - PodcastLocal podcastLocal = PodcastLocal(p.title, p.itunes.image.href, - realUrl, primaryColor, author, uuid, imagePath, provider, link, + PodcastLocal podcastLocal = PodcastLocal(p.title, imageUrl, realUrl, + primaryColor, author, uuid, imagePath, provider, link, description: p.description); // await groupList.subscribe(podcastLocal); diff --git a/lib/util/pageroute.dart b/lib/util/pageroute.dart index ea2ee60..7129650 100644 --- a/lib/util/pageroute.dart +++ b/lib/util/pageroute.dart @@ -30,7 +30,8 @@ class SlideLeftRoute extends PageRouteBuilder { class SlideLeftHideRoute extends PageRouteBuilder { final Widget page; - SlideLeftHideRoute({this.page}) + final Widget transitionPage; + SlideLeftHideRoute({this.page, this.transitionPage}) : super( pageBuilder: ( BuildContext context, @@ -38,25 +39,23 @@ class SlideLeftHideRoute extends PageRouteBuilder { Animation secondaryAnimation, ) => page, + transitionDuration: Duration(seconds: 2), transitionsBuilder: ( BuildContext context, Animation animation, Animation secondaryAnimation, Widget child, - ) => - SlideTransition( - position: Tween( - begin: const Offset(1, 0), - end: Offset.zero, - ).animate(animation), - child: Container( - alignment: Alignment.topLeft, - child: SizedBox( - width: context.width, - height: context.height, - child: child), - ), - ), + ) { + if (animation.isCompleted) + return child; + else + return SlideTransition( + position: Tween( + begin: const Offset(1, 0), + end: Offset.zero, + ).animate(animation), + child: transitionPage); + }, ); } diff --git a/pubspec.yaml b/pubspec.yaml index 513b38f..c5b9829 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: tsacdop description: An easy-use podacasts player. -version: 0.3.1 +version: 0.3.2 environment: sdk: ">=2.6.0 <3.0.0"