🐛 Beter support for small screen.

This commit is contained in:
stonegate 2020-06-02 22:05:49 +08:00
parent 8ec1793843
commit e9ba82d5db
17 changed files with 417 additions and 263 deletions

View File

@ -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...

View File

@ -49,7 +49,7 @@ android {
applicationId "com.stonegate.tsacdop"
minSdkVersion 19
targetSdkVersion 28
versionCode 14
versionCode 15
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

View File

@ -580,7 +580,7 @@ class _MenuBarState extends State<MenuBar> {
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
children: <Widget>[
Text('Play Now',
Text('Play',
style: TextStyle(
color: Theme.of(context).accentColor,
fontSize: 15,

View File

@ -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: <Widget>[
Container(
height: 200.0,
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
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: <Widget>[
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: <Widget>[
Container(
height: 200.0,
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
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: <Widget>[
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: <Widget>[
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,
),
],
),
),
),
],
),
),
),
)),

View File

@ -18,24 +18,26 @@ import '../.env.dart';
class MyHomePageDelegate extends SearchDelegate<int> {
final String searchFieldLabel;
MyHomePageDelegate({this.searchFieldLabel})
: super(
searchFieldLabel: searchFieldLabel,
);
static Future<List> 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<List> 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<int> {
},
);
else
return FutureBuilder(
future: getList(query),
builder: (BuildContext context, AsyncSnapshot<List> 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<List> 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<SearchList> {
int _nextOffset;
List<OnlinePodcast> _podcastList;
int _offset;
bool _loading;
@override
void initState() {
super.initState();
_nextOffset = 0;
_podcastList = [];
}
Future<List> _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<List>(
future: _getList(widget.query, _nextOffset),
builder: (BuildContext context, AsyncSnapshot<List> 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<SearchResult>
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),

View File

@ -460,15 +460,10 @@ class _PlayerWidgetState extends State<PlayerWidget> {
style: TextStyle(
color: Theme.of(context).accentColor),
)
: Row(
children: <Widget>[
Text(
_stringForSeconds(data.item2) ?? '',
),
Text(
' Left',
),
],
: Text(
(_stringForSeconds(data.item2) ?? '') +
' Left',
maxLines: 2,
),
);
},
@ -480,10 +475,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
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<PlayerWidget> {
)),
),
Container(
height: 50.0,
height: 40.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.black),
@ -531,8 +525,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
),
),
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<ControlPanel>
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<ControlPanel>
),
),
IconButton(
padding: EdgeInsets.symmetric(horizontal: 30.0),
padding: EdgeInsets.symmetric(horizontal: 25.0),
onPressed:
backplay == BasicPlaybackState.playing
? () => audio.forwardAudio(30)

View File

@ -158,7 +158,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
controller: _controller,
tabs: <Widget>[
Tab(
child: Text('Recent Update'),
child: Text('Recent'),
),
Tab(
child: Text('Favorite'),

View File

@ -440,7 +440,7 @@ class _PodcastPreviewState extends State<PodcastPreview> {
onPressed: () {
Navigator.push(
context,
SlideLeftRoute(
SlideLeftHideRoute(
page: PodcastDetail(
podcastLocal: widget.podcastLocal,
)),

View File

@ -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(

View File

@ -253,10 +253,8 @@ class _PodcastCardState extends State<PodcastCard>
child: _addGroup
? Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
flex: 4,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
@ -284,9 +282,10 @@ class _PodcastCardState extends State<PodcastCard>
}).toList()),
),
),
Expanded(
flex: 1,
SizedBox(
width: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
IconButton(
icon: Icon(Icons.clear),
@ -374,7 +373,7 @@ class _PodcastCardState extends State<PodcastCard>
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<PodcastCard>
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<RenameGroup> {
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: <Widget>[
FlatButton(

View File

@ -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<AboutPodcast> {
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: <Widget>[
FlatButton(
padding: EdgeInsets.all(10.0),
@ -63,18 +65,21 @@ class _AboutPodcastState extends State<AboutPodcast> {
),
],
title: Text(widget.podcastLocal.title),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
!_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: <Widget>[
!_load
? Center()
: _description != null ? Html(data: _description) : Center(),
(widget.podcastLocal.author != null)
? Text(widget.podcastLocal.author,
style: TextStyle(color: Colors.blue))
: Center(),
],
),
),
);
}

View File

@ -49,11 +49,11 @@ class _PodcastManageState extends State<PodcastManage>
_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<PodcastManage>
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<AddGroup> {
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: <Widget>[
FlatButton(

View File

@ -85,7 +85,10 @@ class _SettingsState extends State<Settings>
Padding(
padding: EdgeInsets.symmetric(vertical: 5),
),
Text(name)
Text(
name,
maxLines: 2,
)
],
),
),
@ -284,28 +287,31 @@ class _SettingsState extends State<Settings>
),
),
_showFeedback
? Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_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:<tsacdop.app@gmail.com>?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: <Widget>[
_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:<tsacdop.app@gmail.com>?subject=Tsacdop Feedback'),
_feedbackItem(
LineIcons.google_play,
'Rate on Play',
'https://play.google.com/store/apps/details?id=com.stonegate.tsacdop')
],
),
)
: Center(),
Divider(

View File

@ -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: <Widget>[
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: <Widget>[
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<ColorPicker>
),
);
}
}
}

View File

@ -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<void> 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<void> subIsolateEntryPoint(SendPort sendPort) async {
print(realUrl);
bool checkUrl = await dbHelper.checkPodcast(realUrl);
String imageUrl;
if (checkUrl) {
img.Image thumbnail;
try {
Response<List<int>> imageResponse = await Dio().get<List<int>>(
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<List<int>> imageResponse = await Dio().get<List<int>>(
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<List<int>> imageResponse = await Dio().get<List<int>>(
"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<void> 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);

View File

@ -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<double> secondaryAnimation,
) =>
page,
transitionDuration: Duration(seconds: 2),
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
SlideTransition(
position: Tween<Offset>(
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<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(animation),
child: transitionPage);
},
);
}

View File

@ -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"