🐛 Beter support for small screen.
This commit is contained in:
parent
8ec1793843
commit
e9ba82d5db
|
@ -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).
|
The podcasts search engine is powered by [ListenNotes](https://listennotes.com).
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* Subscriptoin group management
|
* Podcasts group management
|
||||||
* Playlist support
|
* Playlist support
|
||||||
* Sleep timer / Speed setting
|
* Sleep timer / Speed setting
|
||||||
* OMPL file export and import
|
* 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
|
* Listen and subscribe history record
|
||||||
* Dark mode / Accent color
|
* Dark mode / Accent color
|
||||||
* Download for offline playing
|
* Download for offline playing
|
||||||
* Share clip on twitter
|
* Share clip(video format) on twitter
|
||||||
|
|
||||||
More to come...
|
More to come...
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ android {
|
||||||
applicationId "com.stonegate.tsacdop"
|
applicationId "com.stonegate.tsacdop"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 14
|
versionCode 15
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
|
@ -580,7 +580,7 @@ class _MenuBarState extends State<MenuBar> {
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20.0),
|
padding: EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text('Play Now',
|
Text('Play',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).accentColor,
|
color: Theme.of(context).accentColor,
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:tsacdop/util/custompaint.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:line_icons/line_icons.dart';
|
import 'package:line_icons/line_icons.dart';
|
||||||
|
|
||||||
const String version = '0.3.1';
|
const String version = '0.3.2';
|
||||||
|
|
||||||
class AboutApp extends StatelessWidget {
|
class AboutApp extends StatelessWidget {
|
||||||
_launchUrl(String url) async {
|
_launchUrl(String url) async {
|
||||||
|
@ -74,105 +74,110 @@ class AboutApp extends StatelessWidget {
|
||||||
title: Text('About'),
|
title: Text('About'),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Container(
|
child: SingleChildScrollView(
|
||||||
padding: EdgeInsets.all(20),
|
scrollDirection: Axis.vertical,
|
||||||
alignment: Alignment.topLeft,
|
child: Padding(
|
||||||
child: Column(
|
padding: const EdgeInsets.all(20.0),
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: <Widget>[
|
mainAxisSize: MainAxisSize.min,
|
||||||
Container(
|
children: <Widget>[
|
||||||
height: 200.0,
|
Container(
|
||||||
alignment: Alignment.center,
|
height: 200.0,
|
||||||
child: Column(
|
alignment: Alignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Column(
|
||||||
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,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Image.asset(
|
Image(
|
||||||
'assets/text.png',
|
image: AssetImage('assets/logo.png'),
|
||||||
height: 25,
|
height: 80,
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 5),
|
|
||||||
),
|
|
||||||
Icon(
|
|
||||||
Icons.favorite,
|
|
||||||
color: Colors.blue,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 5),
|
|
||||||
),
|
|
||||||
FlutterLogo(
|
|
||||||
size: 18,
|
|
||||||
),
|
),
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -18,24 +18,26 @@ import '../.env.dart';
|
||||||
|
|
||||||
class MyHomePageDelegate extends SearchDelegate<int> {
|
class MyHomePageDelegate extends SearchDelegate<int> {
|
||||||
final String searchFieldLabel;
|
final String searchFieldLabel;
|
||||||
|
|
||||||
MyHomePageDelegate({this.searchFieldLabel})
|
MyHomePageDelegate({this.searchFieldLabel})
|
||||||
: super(
|
: super(
|
||||||
searchFieldLabel: searchFieldLabel,
|
searchFieldLabel: searchFieldLabel,
|
||||||
);
|
);
|
||||||
static Future<List> getList(String searchText) async {
|
|
||||||
String apiKey = environment['apiKey'];
|
//static Future<List> getList(String searchText) async {
|
||||||
String url =
|
// String apiKey = environment['apiKey'];
|
||||||
"https://listennotes.p.rapidapi.com/api/v1/search?only_in=title%2Cdescription&q=" +
|
// String url =
|
||||||
"$searchText&type=podcast";
|
// "https://listennotes.p.rapidapi.com/api/v1/search?only_in=title%2Cdescription&q=" +
|
||||||
Response response = await Dio().get(url,
|
// "$searchText&type=podcast";
|
||||||
options: Options(headers: {
|
// Response response = await Dio().get(url,
|
||||||
'X-RapidAPI-Key': "$apiKey",
|
// options: Options(headers: {
|
||||||
'Accept': "application/json"
|
// 'X-RapidAPI-Key': "$apiKey",
|
||||||
}));
|
// 'Accept': "application/json"
|
||||||
Map searchResultMap = jsonDecode(response.toString());
|
// }));
|
||||||
var searchResult = SearchPodcast.fromJson(searchResultMap);
|
// Map searchResultMap = jsonDecode(response.toString());
|
||||||
return searchResult.results;
|
// var searchResult = SearchPodcast.fromJson(searchResultMap);
|
||||||
}
|
// return searchResult.results;
|
||||||
|
//}
|
||||||
|
|
||||||
static Future getRss(String url) async {
|
static Future getRss(String url) async {
|
||||||
try {
|
try {
|
||||||
|
@ -185,27 +187,130 @@ class MyHomePageDelegate extends SearchDelegate<int> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
return FutureBuilder(
|
return SearchList(
|
||||||
future: getList(query),
|
query: 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 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,
|
width: 40.0,
|
||||||
fit: BoxFit.fitWidth,
|
fit: BoxFit.fitWidth,
|
||||||
alignment: Alignment.center,
|
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),
|
title: Text(widget.onlinePodcast.title),
|
||||||
|
|
|
@ -460,15 +460,10 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).accentColor),
|
color: Theme.of(context).accentColor),
|
||||||
)
|
)
|
||||||
: Row(
|
: Text(
|
||||||
children: <Widget>[
|
(_stringForSeconds(data.item2) ?? '') +
|
||||||
Text(
|
' Left',
|
||||||
_stringForSeconds(data.item2) ?? '',
|
maxLines: 2,
|
||||||
),
|
|
||||||
Text(
|
|
||||||
' Left',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -480,10 +475,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
||||||
selector: (_, audio) => audio.audioState,
|
selector: (_, audio) => audio.audioState,
|
||||||
builder: (_, audioplay, __) {
|
builder: (_, audioplay, __) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Spacer(),
|
//Spacer(),
|
||||||
audioplay == BasicPlaybackState.playing
|
audioplay == BasicPlaybackState.playing
|
||||||
? InkWell(
|
? InkWell(
|
||||||
onTap:
|
onTap:
|
||||||
|
@ -518,7 +512,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
height: 50.0,
|
height: 40.0,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: Colors.black),
|
color: Colors.black),
|
||||||
|
@ -531,8 +525,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
onPressed: () => audio.playNext(),
|
onPressed: () => audio.playNext(),
|
||||||
iconSize: 25.0,
|
iconSize: 20.0,
|
||||||
icon: Icon(Icons.skip_next),
|
icon: Icon(Icons.skip_next),
|
||||||
color:
|
color:
|
||||||
Theme.of(context).tabBarTheme.labelColor),
|
Theme.of(context).tabBarTheme.labelColor),
|
||||||
|
@ -1251,7 +1246,7 @@ class _ControlPanelState extends State<ControlPanel>
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 30.0),
|
padding: EdgeInsets.symmetric(horizontal: 25.0),
|
||||||
onPressed:
|
onPressed:
|
||||||
backplay == BasicPlaybackState.playing
|
backplay == BasicPlaybackState.playing
|
||||||
? () => audio.forwardAudio(-10)
|
? () => audio.forwardAudio(-10)
|
||||||
|
@ -1323,7 +1318,7 @@ class _ControlPanelState extends State<ControlPanel>
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 30.0),
|
padding: EdgeInsets.symmetric(horizontal: 25.0),
|
||||||
onPressed:
|
onPressed:
|
||||||
backplay == BasicPlaybackState.playing
|
backplay == BasicPlaybackState.playing
|
||||||
? () => audio.forwardAudio(30)
|
? () => audio.forwardAudio(30)
|
||||||
|
|
|
@ -158,7 +158,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
tabs: <Widget>[
|
tabs: <Widget>[
|
||||||
Tab(
|
Tab(
|
||||||
child: Text('Recent Update'),
|
child: Text('Recent'),
|
||||||
),
|
),
|
||||||
Tab(
|
Tab(
|
||||||
child: Text('Favorite'),
|
child: Text('Favorite'),
|
||||||
|
|
|
@ -440,7 +440,7 @@ class _PodcastPreviewState extends State<PodcastPreview> {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
SlideLeftRoute(
|
SlideLeftHideRoute(
|
||||||
page: PodcastDetail(
|
page: PodcastDetail(
|
||||||
podcastLocal: widget.podcastLocal,
|
podcastLocal: widget.podcastLocal,
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Import extends StatelessWidget {
|
||||||
groupList.subscribeNewPodcast(item.id);
|
groupList.subscribeNewPodcast(item.id);
|
||||||
return importColumn("Fetch data ${item.title}", context);
|
return importColumn("Fetch data ${item.title}", context);
|
||||||
case SubscribeState.fetch:
|
case SubscribeState.fetch:
|
||||||
groupList.updatePodcast(item.id);
|
// groupList.updatePodcast(item.id);
|
||||||
return importColumn("Subscribe success ${item.title}", context);
|
return importColumn("Subscribe success ${item.title}", context);
|
||||||
case SubscribeState.exist:
|
case SubscribeState.exist:
|
||||||
return importColumn(
|
return importColumn(
|
||||||
|
|
|
@ -253,10 +253,8 @@ class _PodcastCardState extends State<PodcastCard>
|
||||||
child: _addGroup
|
child: _addGroup
|
||||||
? Row(
|
? Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 4,
|
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -284,9 +282,10 @@ class _PodcastCardState extends State<PodcastCard>
|
||||||
}).toList()),
|
}).toList()),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
SizedBox(
|
||||||
flex: 1,
|
width: 100,
|
||||||
child: Row(
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.clear),
|
icon: Icon(Icons.clear),
|
||||||
|
@ -374,7 +373,7 @@ class _PodcastCardState extends State<PodcastCard>
|
||||||
titlePadding: EdgeInsets.only(
|
titlePadding: EdgeInsets.only(
|
||||||
top: 20,
|
top: 20,
|
||||||
left: 20,
|
left: 20,
|
||||||
right: 100,
|
right: context.width / 3,
|
||||||
bottom: 20),
|
bottom: 20),
|
||||||
title:
|
title:
|
||||||
Text('Skip seconds at the beginning'),
|
Text('Skip seconds at the beginning'),
|
||||||
|
@ -452,7 +451,7 @@ class _PodcastCardState extends State<PodcastCard>
|
||||||
titlePadding: EdgeInsets.only(
|
titlePadding: EdgeInsets.only(
|
||||||
top: 20,
|
top: 20,
|
||||||
left: 20,
|
left: 20,
|
||||||
right: 200,
|
right: context.width / 3,
|
||||||
bottom: 20),
|
bottom: 20),
|
||||||
title: Text('Remove confirm'),
|
title: Text('Remove confirm'),
|
||||||
content: Text(
|
content: Text(
|
||||||
|
@ -535,8 +534,8 @@ class _RenameGroupState extends State<RenameGroup> {
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10))),
|
borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||||
elevation: 1,
|
elevation: 1,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
||||||
titlePadding:
|
titlePadding: EdgeInsets.only(
|
||||||
EdgeInsets.only(top: 20, left: 20, right: 200, bottom: 20),
|
top: 20, left: 20, right: context.width / 3, bottom: 20),
|
||||||
actionsPadding: EdgeInsets.all(0),
|
actionsPadding: EdgeInsets.all(0),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
FlatButton(
|
||||||
|
|
|
@ -13,6 +13,7 @@ import '../type/podcastlocal.dart';
|
||||||
import '../local_storage/sqflite_localpodcast.dart';
|
import '../local_storage/sqflite_localpodcast.dart';
|
||||||
import '../podcasts/podcastdetail.dart';
|
import '../podcasts/podcastdetail.dart';
|
||||||
import '../util/pageroute.dart';
|
import '../util/pageroute.dart';
|
||||||
|
import '../util/context_extension.dart';
|
||||||
|
|
||||||
class AboutPodcast extends StatefulWidget {
|
class AboutPodcast extends StatefulWidget {
|
||||||
final PodcastLocal podcastLocal;
|
final PodcastLocal podcastLocal;
|
||||||
|
@ -48,7 +49,8 @@ class _AboutPodcastState extends State<AboutPodcast> {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10.0))),
|
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>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
FlatButton(
|
||||||
padding: EdgeInsets.all(10.0),
|
padding: EdgeInsets.all(10.0),
|
||||||
|
@ -63,18 +65,21 @@ class _AboutPodcastState extends State<AboutPodcast> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
title: Text(widget.podcastLocal.title),
|
title: Text(widget.podcastLocal.title),
|
||||||
content: Column(
|
content: SingleChildScrollView(
|
||||||
mainAxisSize: MainAxisSize.min,
|
scrollDirection: Axis.vertical,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Column(
|
||||||
children: <Widget>[
|
mainAxisSize: MainAxisSize.min,
|
||||||
!_load
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
? Center()
|
children: <Widget>[
|
||||||
: _description != null ? Html(data: _description) : Center(),
|
!_load
|
||||||
(widget.podcastLocal.author != null)
|
? Center()
|
||||||
? Text(widget.podcastLocal.author,
|
: _description != null ? Html(data: _description) : Center(),
|
||||||
style: TextStyle(color: Colors.blue))
|
(widget.podcastLocal.author != null)
|
||||||
: Center(),
|
? Text(widget.podcastLocal.author,
|
||||||
],
|
style: TextStyle(color: Colors.blue))
|
||||||
|
: Center(),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,11 +49,11 @@ class _PodcastManageState extends State<PodcastManage>
|
||||||
_fraction = _animation.value;
|
_fraction = _animation.value;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
_menuAnimation = Tween(begin: 0.0, end: 1.0).animate(
|
_menuAnimation = Tween(begin: 0.0, end: 1.0)
|
||||||
CurvedAnimation(parent: _menuController, curve: Curves.easeIn))
|
.animate(CurvedAnimation(parent: _menuController, curve: Curves.easeIn))
|
||||||
..addListener(() {
|
..addListener(() {
|
||||||
if (mounted) setState(() => _menuValue = _menuAnimation.value);
|
if (mounted) setState(() => _menuValue = _menuAnimation.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
_controller.addStatusListener((status) {
|
_controller.addStatusListener((status) {
|
||||||
if (status == AnimationStatus.completed) {
|
if (status == AnimationStatus.completed) {
|
||||||
|
@ -361,7 +361,9 @@ class _PodcastManageState extends State<PodcastManage>
|
||||||
EdgeInsets.only(
|
EdgeInsets.only(
|
||||||
top: 20,
|
top: 20,
|
||||||
left: 20,
|
left: 20,
|
||||||
right: 200,
|
right: context
|
||||||
|
.width /
|
||||||
|
3,
|
||||||
bottom: 20),
|
bottom: 20),
|
||||||
title: Text(
|
title: Text(
|
||||||
'Delete confirm'),
|
'Delete confirm'),
|
||||||
|
@ -531,8 +533,8 @@ class _AddGroupState extends State<AddGroup> {
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10))),
|
borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||||
elevation: 1,
|
elevation: 1,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
||||||
titlePadding:
|
titlePadding: EdgeInsets.only(
|
||||||
EdgeInsets.only(top: 20, left: 20, right: 200, bottom: 20),
|
top: 20, left: 20, right: context.width / 3, bottom: 20),
|
||||||
actionsPadding: EdgeInsets.all(0),
|
actionsPadding: EdgeInsets.all(0),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
FlatButton(
|
||||||
|
|
|
@ -85,7 +85,10 @@ class _SettingsState extends State<Settings>
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 5),
|
padding: EdgeInsets.symmetric(vertical: 5),
|
||||||
),
|
),
|
||||||
Text(name)
|
Text(
|
||||||
|
name,
|
||||||
|
maxLines: 2,
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -284,28 +287,31 @@ class _SettingsState extends State<Settings>
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_showFeedback
|
_showFeedback
|
||||||
? Row(
|
? SingleChildScrollView(
|
||||||
mainAxisAlignment:
|
scrollDirection: Axis.horizontal,
|
||||||
MainAxisAlignment.spaceEvenly,
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
mainAxisAlignment:
|
||||||
children: <Widget>[
|
MainAxisAlignment.spaceEvenly,
|
||||||
_feedbackItem(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
LineIcons.github,
|
children: <Widget>[
|
||||||
'Submit issue',
|
_feedbackItem(
|
||||||
'https://github.com/stonega/tsacdop/issues'),
|
LineIcons.github,
|
||||||
_feedbackItem(
|
'Submit issue',
|
||||||
LineIcons.telegram,
|
'https://github.com/stonega/tsacdop/issues'),
|
||||||
'Join group',
|
_feedbackItem(
|
||||||
'https://t.me/joinchat/Bk3LkRpTHy40QYC78PK7Qg'),
|
LineIcons.telegram,
|
||||||
_feedbackItem(
|
'Join group',
|
||||||
LineIcons.envelope_open_text_solid,
|
'https://t.me/joinchat/Bk3LkRpTHy40QYC78PK7Qg'),
|
||||||
'Write to me',
|
_feedbackItem(
|
||||||
'mailto:<tsacdop.app@gmail.com>?subject=Tsacdop Feedback'),
|
LineIcons.envelope_open_text_solid,
|
||||||
_feedbackItem(
|
'Write to me',
|
||||||
LineIcons.google_play,
|
'mailto:<tsacdop.app@gmail.com>?subject=Tsacdop Feedback'),
|
||||||
'Rate on Play',
|
_feedbackItem(
|
||||||
'https://play.google.com/store/apps/details?id=com.stonegate.tsacdop')
|
LineIcons.google_play,
|
||||||
],
|
'Rate on Play',
|
||||||
|
'https://play.google.com/store/apps/details?id=com.stonegate.tsacdop')
|
||||||
|
],
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: Center(),
|
: Center(),
|
||||||
Divider(
|
Divider(
|
||||||
|
|
|
@ -72,45 +72,46 @@ class ThemeSetting extends StatelessWidget {
|
||||||
titlePadding: EdgeInsets.only(
|
titlePadding: EdgeInsets.only(
|
||||||
top: 20,
|
top: 20,
|
||||||
left: 40,
|
left: 40,
|
||||||
right: 200,
|
right: context.width / 3,
|
||||||
),
|
),
|
||||||
elevation: 1,
|
elevation: 1,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(10.0))),
|
Radius.circular(10.0))),
|
||||||
title: Text('Theme'),
|
title: Text('Theme'),
|
||||||
content: Column(
|
content: SingleChildScrollView(
|
||||||
mainAxisSize: MainAxisSize.min,
|
scrollDirection: Axis.vertical,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
child: Column(
|
||||||
children: <Widget>[
|
mainAxisSize: MainAxisSize.min,
|
||||||
RadioListTile(
|
mainAxisAlignment:
|
||||||
title: Container(
|
MainAxisAlignment.start,
|
||||||
padding:
|
children: <Widget>[
|
||||||
EdgeInsets.only(right: 80),
|
RadioListTile(
|
||||||
child: Text('System default')),
|
title: Text('System default'),
|
||||||
value: ThemeMode.system,
|
value: ThemeMode.system,
|
||||||
groupValue: settings.theme,
|
groupValue: settings.theme,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
settings.setTheme = value;
|
settings.setTheme = value;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}),
|
}),
|
||||||
RadioListTile(
|
RadioListTile(
|
||||||
title: Text('Dark mode'),
|
title: Text('Dark mode'),
|
||||||
value: ThemeMode.dark,
|
value: ThemeMode.dark,
|
||||||
groupValue: settings.theme,
|
groupValue: settings.theme,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
settings.setTheme = value;
|
settings.setTheme = value;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}),
|
}),
|
||||||
RadioListTile(
|
RadioListTile(
|
||||||
title: Text('Light mode'),
|
title: Text('Light mode'),
|
||||||
value: ThemeMode.light,
|
value: ThemeMode.light,
|
||||||
groupValue: settings.theme,
|
groupValue: settings.theme,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
settings.setTheme = value;
|
settings.setTheme = value;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
@ -357,4 +358,4 @@ class _ColorPickerState extends State<ColorPicker>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ class SubscribeWorker extends ChangeNotifier {
|
||||||
SubscribeItem _subscribeItem;
|
SubscribeItem _subscribeItem;
|
||||||
SubscribeItem _currentSubscribeItem = SubscribeItem('', '');
|
SubscribeItem _currentSubscribeItem = SubscribeItem('', '');
|
||||||
bool _created = false;
|
bool _created = false;
|
||||||
bool get created=> _created;
|
bool get created => _created;
|
||||||
|
|
||||||
setSubscribeItem(SubscribeItem item) async {
|
setSubscribeItem(SubscribeItem item) async {
|
||||||
_subscribeItem = item;
|
_subscribeItem = item;
|
||||||
|
@ -117,9 +117,23 @@ Future<void> subIsolateEntryPoint(SendPort sendPort) async {
|
||||||
receiveTimeout: 20000,
|
receiveTimeout: 20000,
|
||||||
);
|
);
|
||||||
print(rss);
|
print(rss);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Response response = await Dio(options).get(rss);
|
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();
|
var dir = await getApplicationDocumentsDirectory();
|
||||||
|
|
||||||
|
@ -128,31 +142,35 @@ Future<void> subIsolateEntryPoint(SendPort sendPort) async {
|
||||||
|
|
||||||
print(realUrl);
|
print(realUrl);
|
||||||
bool checkUrl = await dbHelper.checkPodcast(realUrl);
|
bool checkUrl = await dbHelper.checkPodcast(realUrl);
|
||||||
|
String imageUrl;
|
||||||
if (checkUrl) {
|
if (checkUrl) {
|
||||||
img.Image thumbnail;
|
img.Image thumbnail;
|
||||||
try {
|
try {
|
||||||
Response<List<int>> imageResponse = await Dio().get<List<int>>(
|
Response<List<int>> imageResponse = await Dio().get<List<int>>(
|
||||||
p.itunes.image.href,
|
p.itunes.image.href,
|
||||||
options: Options(responseType: ResponseType.bytes));
|
options: Options(responseType: ResponseType.bytes));
|
||||||
|
imageUrl = p.itunes.image.href;
|
||||||
img.Image image = img.decodeImage(imageResponse.data);
|
img.Image image = img.decodeImage(imageResponse.data);
|
||||||
thumbnail = img.copyResize(image, width: 300);
|
thumbnail = img.copyResize(image, width: 300);
|
||||||
} on DioError catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
try {
|
try {
|
||||||
Response<List<int>> imageResponse = await Dio().get<List<int>>(
|
Response<List<int>> imageResponse = await Dio().get<List<int>>(
|
||||||
item.imgUrl,
|
item.imgUrl,
|
||||||
options: Options(responseType: ResponseType.bytes));
|
options: Options(responseType: ResponseType.bytes));
|
||||||
|
imageUrl = item.imgUrl;
|
||||||
img.Image image = img.decodeImage(imageResponse.data);
|
img.Image image = img.decodeImage(imageResponse.data);
|
||||||
thumbnail = img.copyResize(image, width: 300);
|
thumbnail = img.copyResize(image, width: 300);
|
||||||
} on DioError catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
try {
|
try {
|
||||||
Response<List<int>> imageResponse = await Dio().get<List<int>>(
|
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",
|
"https://ui-avatars.com/api/?size=300&background=4D91BE&color=fff&name=${item.title}&length=2&bold=true",
|
||||||
options: Options(responseType: ResponseType.bytes));
|
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);
|
thumbnail = img.decodeImage(imageResponse.data);
|
||||||
} on DioError catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
sendPort.send([item.title, item.url, 6]);
|
sendPort.send([item.title, item.url, 6]);
|
||||||
await Future.delayed(Duration(seconds: 2));
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
@ -174,8 +192,8 @@ Future<void> subIsolateEntryPoint(SendPort sendPort) async {
|
||||||
String author = p.itunes.author ?? p.author ?? '';
|
String author = p.itunes.author ?? p.author ?? '';
|
||||||
String provider = p.generator ?? '';
|
String provider = p.generator ?? '';
|
||||||
String link = p.link ?? '';
|
String link = p.link ?? '';
|
||||||
PodcastLocal podcastLocal = PodcastLocal(p.title, p.itunes.image.href,
|
PodcastLocal podcastLocal = PodcastLocal(p.title, imageUrl, realUrl,
|
||||||
realUrl, primaryColor, author, uuid, imagePath, provider, link,
|
primaryColor, author, uuid, imagePath, provider, link,
|
||||||
description: p.description);
|
description: p.description);
|
||||||
|
|
||||||
// await groupList.subscribe(podcastLocal);
|
// await groupList.subscribe(podcastLocal);
|
||||||
|
|
|
@ -30,7 +30,8 @@ class SlideLeftRoute extends PageRouteBuilder {
|
||||||
|
|
||||||
class SlideLeftHideRoute extends PageRouteBuilder {
|
class SlideLeftHideRoute extends PageRouteBuilder {
|
||||||
final Widget page;
|
final Widget page;
|
||||||
SlideLeftHideRoute({this.page})
|
final Widget transitionPage;
|
||||||
|
SlideLeftHideRoute({this.page, this.transitionPage})
|
||||||
: super(
|
: super(
|
||||||
pageBuilder: (
|
pageBuilder: (
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
@ -38,25 +39,23 @@ class SlideLeftHideRoute extends PageRouteBuilder {
|
||||||
Animation<double> secondaryAnimation,
|
Animation<double> secondaryAnimation,
|
||||||
) =>
|
) =>
|
||||||
page,
|
page,
|
||||||
|
transitionDuration: Duration(seconds: 2),
|
||||||
transitionsBuilder: (
|
transitionsBuilder: (
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
Animation<double> animation,
|
Animation<double> animation,
|
||||||
Animation<double> secondaryAnimation,
|
Animation<double> secondaryAnimation,
|
||||||
Widget child,
|
Widget child,
|
||||||
) =>
|
) {
|
||||||
SlideTransition(
|
if (animation.isCompleted)
|
||||||
position: Tween<Offset>(
|
return child;
|
||||||
begin: const Offset(1, 0),
|
else
|
||||||
end: Offset.zero,
|
return SlideTransition(
|
||||||
).animate(animation),
|
position: Tween<Offset>(
|
||||||
child: Container(
|
begin: const Offset(1, 0),
|
||||||
alignment: Alignment.topLeft,
|
end: Offset.zero,
|
||||||
child: SizedBox(
|
).animate(animation),
|
||||||
width: context.width,
|
child: transitionPage);
|
||||||
height: context.height,
|
},
|
||||||
child: child),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: tsacdop
|
name: tsacdop
|
||||||
description: An easy-use podacasts player.
|
description: An easy-use podacasts player.
|
||||||
|
|
||||||
version: 0.3.1
|
version: 0.3.2
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.6.0 <3.0.0"
|
sdk: ">=2.6.0 <3.0.0"
|
||||||
|
|
Loading…
Reference in New Issue