🐛 Bugs fixed
This commit is contained in:
parent
137fe58183
commit
ab6910d9c6
25
README.md
25
README.md
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/android/app/src/main/res/mipmap-xhdpi/ic_notification.png" art = "Logo"/>
|
<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/android/app/src/main/res/mipmap-xhdpi/ic_notification.png" art = "Logo"/>
|
||||||
</br>
|
</br>
|
||||||
|
@ -6,11 +5,13 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
![CircleCI](https://img.shields.io/circleci/build/github/stonega/tsacdop?token=efe1331861e017144f2abb363acd95197e436dad)
|
![CircleCI](https://img.shields.io/circleci/build/github/stonega/tsacdop?token=efe1331861e017144f2abb363acd95197e436dad)
|
||||||
|
|
||||||
![GitHub release (latest by date)](https://img.shields.io/github/v/release/stonega/tsacdop)
|
![GitHub release (latest by date)](https://img.shields.io/github/v/release/stonega/tsacdop)
|
||||||
|
|
||||||
[![GooglePlay](https://img.shields.io/badge/Google-PlayStore-%2323CCC6)](https://play.google.com/store/apps/details?id=com.stonegate.tsacdop)
|
[![GooglePlay](https://img.shields.io/badge/Google-PlayStore-%2323CCC6)](https://play.google.com/store/apps/details?id=com.stonegate.tsacdop)
|
||||||
|
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
Enjoy podcasts with Tsacdop.
|
Enjoy podcasts with Tsacdop.
|
||||||
|
|
||||||
Tsacdop is a podcast player developed with flutter, a clean, simply beautiful and friendly app, only support Android right now.
|
Tsacdop is a podcast player developed with flutter, a clean, simply beautiful and friendly app, only support Android right now.
|
||||||
|
@ -20,6 +21,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
|
||||||
|
|
||||||
* Podcasts group management
|
* Podcasts group management
|
||||||
* Playlist support
|
* Playlist support
|
||||||
* Sleep timer / Speed setting
|
* Sleep timer / Speed setting
|
||||||
|
@ -33,9 +35,10 @@ The podcasts search engine is powered by [ListenNotes](https://listennotes.com).
|
||||||
More to come...
|
More to come...
|
||||||
|
|
||||||
## Preview
|
## Preview
|
||||||
HomePage | Group | Podcast | Episode |DarkMode
|
|
||||||
-------|--------|--------|------| ----
|
| HomePage | Group | Podcast | Episode | DarkMode |
|
||||||
<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893838840.png" art = "HomePage"/>|<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585894051734.png" art = "Groups"/>|<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893877702.png" art = "Podcast"/>|<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585896237809.png" art = "Episode"/>|<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893920721.png" art = "DarkMode"/>|
|
|------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893838840.png" art = "HomePage"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585894051734.png" art = "Groups"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893877702.png" art = "Podcast"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585896237809.png" art = "Episode"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893920721.png" art = "DarkMode"/> |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -46,11 +49,11 @@ Tsacdop is licensed under the [GPL V3.0](https://github.com/stonega/tsacdop/blob
|
||||||
Tsacdop is using ListenNotes api 1.0 pro to search podcast, which is not free. So I can not expose the api key in the repo.
|
Tsacdop is using ListenNotes api 1.0 pro to search podcast, which is not free. So I can not expose the api key in the repo.
|
||||||
If you want to build the app, you need to create a new file named .env.dart in lib folder. Add below code in .env.dart.
|
If you want to build the app, you need to create a new file named .env.dart in lib folder. Add below code in .env.dart.
|
||||||
|
|
||||||
```
|
``llkk
|
||||||
final environment = {"apiKey":"APIKEY", "shareKey":"SHAREKEY"};
|
final environment = {"apiKey":"APIKEY", "shareKey":"SHAREKEY"};
|
||||||
```
|
```
|
||||||
|
|
||||||
You can get own api key on [RapidApi](https://rapidapi.com/listennotes/api/listennotes), basic plan is free to all, and replace "APIKEY" with it.
|
You can get own api key on [ListenNotes](https://www.listennotes.com/api/), basic plan is free to all, and replace "APIKEY" with it.
|
||||||
If no api key added, the search function in the app won't work. But you can still add podcasts by serach rss link or import ompl file.
|
If no api key added, the search function in the app won't work. But you can still add podcasts by serach rss link or import ompl file.
|
||||||
|
|
||||||
Share_key is used for generate clip.
|
Share_key is used for generate clip.
|
||||||
|
@ -61,9 +64,9 @@ This project is a starting point for a Flutter application.
|
||||||
|
|
||||||
A few resources to get you started if this is your first Flutter project:
|
A few resources to get you started if this is your first Flutter project:
|
||||||
|
|
||||||
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
|
* [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
|
||||||
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
|
* [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
|
||||||
|
|
||||||
For help getting started with Flutter, view our
|
For help getting started with Flutter, view our
|
||||||
[online documentation](https://flutter.dev/docs), which offers tutorials,
|
[online documentation](https://flutter.dev/docs), which offers tutorials,
|
||||||
samples, guidance on mobile development, and a full API reference.
|
samples, guidance on mobile development, and a full API reference.
|
||||||
|
|
|
@ -48,8 +48,8 @@ android {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "com.stonegate.tsacdop"
|
applicationId "com.stonegate.tsacdop"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 28
|
targetSdkVersion 29
|
||||||
versionCode 15
|
versionCode 16
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.2';
|
const String version = '0.3.3';
|
||||||
|
|
||||||
class AboutApp extends StatelessWidget {
|
class AboutApp extends StatelessWidget {
|
||||||
_launchUrl(String url) async {
|
_launchUrl(String url) async {
|
||||||
|
|
|
@ -440,12 +440,14 @@ class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
String _groupName;
|
String _groupName;
|
||||||
List<String> _group;
|
List<String> _group;
|
||||||
Layout _layout;
|
Layout _layout;
|
||||||
|
bool _scroll;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_loadMore = false;
|
_loadMore = false;
|
||||||
_groupName = 'All';
|
_groupName = 'All';
|
||||||
_group = ['All'];
|
_group = ['All'];
|
||||||
|
_scroll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -479,6 +481,11 @@ class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
)
|
)
|
||||||
: NotificationListener<ScrollNotification>(
|
: NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification scrollInfo) {
|
onNotification: (ScrollNotification scrollInfo) {
|
||||||
|
if (scrollInfo is ScrollStartNotification &&
|
||||||
|
mounted &&
|
||||||
|
!_scroll) {
|
||||||
|
setState(() => _scroll = true);
|
||||||
|
}
|
||||||
if (scrollInfo.metrics.pixels ==
|
if (scrollInfo.metrics.pixels ==
|
||||||
scrollInfo.metrics.maxScrollExtent &&
|
scrollInfo.metrics.maxScrollExtent &&
|
||||||
snapshot.data.length == _top)
|
snapshot.data.length == _top)
|
||||||
|
@ -705,7 +712,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
EpisodeGrid(
|
EpisodeGrid(
|
||||||
episodes: snapshot.data,
|
episodes: snapshot.data,
|
||||||
layout: _layout,
|
layout: _layout,
|
||||||
initNum: 9,
|
initNum: _scroll ? 0 : 12,
|
||||||
),
|
),
|
||||||
SliverList(
|
SliverList(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
|
|
@ -4,7 +4,6 @@ import 'dart:convert';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
import '../state/podcast_group.dart';
|
import '../state/podcast_group.dart';
|
||||||
import '../util/episodegrid.dart';
|
|
||||||
|
|
||||||
const String autoPlayKey = 'autoPlay';
|
const String autoPlayKey = 'autoPlay';
|
||||||
const String autoAddKey = 'autoAdd';
|
const String autoAddKey = 'autoAdd';
|
||||||
|
|
|
@ -23,7 +23,6 @@ import '../util/colorize.dart';
|
||||||
import '../util/context_extension.dart';
|
import '../util/context_extension.dart';
|
||||||
import '../util/custompaint.dart';
|
import '../util/custompaint.dart';
|
||||||
import '../state/audiostate.dart';
|
import '../state/audiostate.dart';
|
||||||
import '../state/podcast_group.dart';
|
|
||||||
|
|
||||||
class PodcastDetail extends StatefulWidget {
|
class PodcastDetail extends StatefulWidget {
|
||||||
PodcastDetail({Key key, @required this.podcastLocal, this.hide = false})
|
PodcastDetail({Key key, @required this.podcastLocal, this.hide = false})
|
||||||
|
@ -41,6 +40,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
List<PodcastHost> _hosts;
|
List<PodcastHost> _hosts;
|
||||||
int _episodeCount;
|
int _episodeCount;
|
||||||
Layout _layout;
|
Layout _layout;
|
||||||
|
bool _scroll;
|
||||||
Future _updateRssItem(PodcastLocal podcastLocal) async {
|
Future _updateRssItem(PodcastLocal podcastLocal) async {
|
||||||
var dbHelper = DBHelper();
|
var dbHelper = DBHelper();
|
||||||
|
|
||||||
|
@ -196,6 +196,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
_top = 99;
|
_top = 99;
|
||||||
_reverse = false;
|
_reverse = false;
|
||||||
_controller = ScrollController();
|
_controller = ScrollController();
|
||||||
|
_scroll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -257,6 +258,10 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
_loadMore = false;
|
_loadMore = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (_controller.offset > 0 && mounted && !_scroll )
|
||||||
|
setState(() {
|
||||||
|
_scroll = true;
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
physics:
|
physics:
|
||||||
const AlwaysScrollableScrollPhysics(),
|
const AlwaysScrollableScrollPhysics(),
|
||||||
|
@ -557,6 +562,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
layout: _layout,
|
layout: _layout,
|
||||||
reverse: _reverse,
|
reverse: _reverse,
|
||||||
episodeCount: _episodeCount,
|
episodeCount: _episodeCount,
|
||||||
|
initNum: _scroll ? 0 : 12,
|
||||||
),
|
),
|
||||||
SliverList(
|
SliverList(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
|
|
@ -15,7 +15,6 @@ import '../util/pageroute.dart';
|
||||||
import '../util/colorize.dart';
|
import '../util/colorize.dart';
|
||||||
import '../util/duraiton_picker.dart';
|
import '../util/duraiton_picker.dart';
|
||||||
import '../util/context_extension.dart';
|
import '../util/context_extension.dart';
|
||||||
import '../state/audiostate.dart';
|
|
||||||
|
|
||||||
class PodcastGroupList extends StatefulWidget {
|
class PodcastGroupList extends StatefulWidget {
|
||||||
final PodcastGroup group;
|
final PodcastGroup group;
|
||||||
|
|
|
@ -52,8 +52,7 @@ class ThemeSetting extends StatelessWidget {
|
||||||
.modalBarrierDismissLabel,
|
.modalBarrierDismissLabel,
|
||||||
barrierColor: Colors.black54,
|
barrierColor: Colors.black54,
|
||||||
transitionDuration: const Duration(milliseconds: 200),
|
transitionDuration: const Duration(milliseconds: 200),
|
||||||
pageBuilder: (BuildContext context,
|
pageBuilder: (BuildContext context, Animation animaiton,
|
||||||
Animation animaiton,
|
|
||||||
Animation secondaryAnimation) =>
|
Animation secondaryAnimation) =>
|
||||||
AnnotatedRegion<SystemUiOverlayStyle>(
|
AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
|
@ -72,15 +71,14 @@ class ThemeSetting extends StatelessWidget {
|
||||||
),
|
),
|
||||||
elevation: 1,
|
elevation: 1,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius:
|
||||||
Radius.circular(10.0))),
|
BorderRadius.all(Radius.circular(10.0))),
|
||||||
title: Text('Theme'),
|
title: Text('Theme'),
|
||||||
content: SingleChildScrollView(
|
content: SingleChildScrollView(
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment:
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
MainAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
RadioListTile(
|
RadioListTile(
|
||||||
title: Text('System default'),
|
title: Text('System default'),
|
||||||
|
@ -123,8 +121,8 @@ class ThemeSetting extends StatelessWidget {
|
||||||
title: Text(
|
title: Text(
|
||||||
'Real Dark',
|
'Real Dark',
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle:
|
||||||
'Turn on if you think the night is not dark enough'),
|
Text('Turn on if you think the night is not dark enough'),
|
||||||
trailing: Selector<SettingState, bool>(
|
trailing: Selector<SettingState, bool>(
|
||||||
selector: (_, setting) => setting.realDark,
|
selector: (_, setting) => setting.realDark,
|
||||||
builder: (_, data, __) => Switch(
|
builder: (_, data, __) => Switch(
|
||||||
|
@ -143,8 +141,7 @@ class ThemeSetting extends StatelessWidget {
|
||||||
.modalBarrierDismissLabel,
|
.modalBarrierDismissLabel,
|
||||||
barrierColor: Colors.black54,
|
barrierColor: Colors.black54,
|
||||||
transitionDuration: const Duration(milliseconds: 200),
|
transitionDuration: const Duration(milliseconds: 200),
|
||||||
pageBuilder: (BuildContext context,
|
pageBuilder: (BuildContext context, Animation animaiton,
|
||||||
Animation animaiton,
|
|
||||||
Animation secondaryAnimation) =>
|
Animation secondaryAnimation) =>
|
||||||
AnnotatedRegion<SystemUiOverlayStyle>(
|
AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
|
@ -160,7 +157,7 @@ class ThemeSetting extends StatelessWidget {
|
||||||
titlePadding: EdgeInsets.only(
|
titlePadding: EdgeInsets.only(
|
||||||
top: 20,
|
top: 20,
|
||||||
left: 40,
|
left: 40,
|
||||||
right: 200,
|
right: context.width / 3,
|
||||||
bottom: 0),
|
bottom: 0),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
|
|
|
@ -96,9 +96,11 @@ class Playlist {
|
||||||
}
|
}
|
||||||
|
|
||||||
addToPlayList(EpisodeBrief episodeBrief) async {
|
addToPlayList(EpisodeBrief episodeBrief) async {
|
||||||
_playlist.add(episodeBrief);
|
if (!_playlist.contains(episodeBrief)) {
|
||||||
await savePlaylist();
|
_playlist.add(episodeBrief);
|
||||||
dbHelper.removeEpisodeNewMark(episodeBrief.enclosureUrl);
|
await savePlaylist();
|
||||||
|
dbHelper.removeEpisodeNewMark(episodeBrief.enclosureUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addToPlayListAt(EpisodeBrief episodeBrief, int index) async {
|
addToPlayListAt(EpisodeBrief episodeBrief, int index) async {
|
||||||
|
|
|
@ -34,7 +34,7 @@ class EpisodeBrief {
|
||||||
this.skipSeconds);
|
this.skipSeconds);
|
||||||
|
|
||||||
String dateToString() {
|
String dateToString() {
|
||||||
DateTime date = DateTime.fromMillisecondsSinceEpoch(pubDate,isUtc: true);
|
DateTime date = DateTime.fromMillisecondsSinceEpoch(pubDate, isUtc: true);
|
||||||
var diffrence = DateTime.now().toUtc().difference(date);
|
var diffrence = DateTime.now().toUtc().difference(date);
|
||||||
if (diffrence.inHours < 1) {
|
if (diffrence.inHours < 1) {
|
||||||
return '1 hour ago';
|
return '1 hour ago';
|
||||||
|
@ -56,9 +56,17 @@ class EpisodeBrief {
|
||||||
title: title,
|
title: title,
|
||||||
artist: feedTitle,
|
artist: feedTitle,
|
||||||
album: feedTitle,
|
album: feedTitle,
|
||||||
// duration: 0,
|
// duration: 0,
|
||||||
artUri: 'file://$imagePath',
|
artUri: 'file://$imagePath',
|
||||||
extras: {'skip': skipSeconds});
|
extras: {'skip': skipSeconds});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object episode) =>
|
||||||
|
episode is EpisodeBrief &&
|
||||||
|
episode.title == title &&
|
||||||
|
episode.enclosureUrl == enclosureUrl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => enclosureUrl.hashCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,18 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
final Layout layout;
|
final Layout layout;
|
||||||
final bool reverse;
|
final bool reverse;
|
||||||
final int initNum;
|
final int initNum;
|
||||||
|
EpisodeGrid({
|
||||||
|
Key key,
|
||||||
|
@required this.episodes,
|
||||||
|
this.initNum = 12,
|
||||||
|
this.showDownload = false,
|
||||||
|
this.showFavorite = false,
|
||||||
|
this.showNumber = false,
|
||||||
|
this.episodeCount = 0,
|
||||||
|
this.layout = Layout.three,
|
||||||
|
this.reverse,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
Future<int> _isListened(EpisodeBrief episode) async {
|
Future<int> _isListened(EpisodeBrief episode) async {
|
||||||
DBHelper dbHelper = DBHelper();
|
DBHelper dbHelper = DBHelper();
|
||||||
return await dbHelper.isListened(episode.enclosureUrl);
|
return await dbHelper.isListened(episode.enclosureUrl);
|
||||||
|
@ -44,18 +56,6 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
return '${(seconds ~/ 60)}:${(seconds.truncate() % 60).toString().padLeft(2, '0')}';
|
return '${(seconds ~/ 60)}:${(seconds.truncate() % 60).toString().padLeft(2, '0')}';
|
||||||
}
|
}
|
||||||
|
|
||||||
EpisodeGrid({
|
|
||||||
Key key,
|
|
||||||
@required this.episodes,
|
|
||||||
this.initNum = 12,
|
|
||||||
this.showDownload = false,
|
|
||||||
this.showFavorite = false,
|
|
||||||
this.showNumber = false,
|
|
||||||
this.episodeCount = 0,
|
|
||||||
this.layout = Layout.three,
|
|
||||||
this.reverse,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
Widget _title(EpisodeBrief episode) => Container(
|
Widget _title(EpisodeBrief episode) => Container(
|
||||||
alignment:
|
alignment:
|
||||||
layout == Layout.one ? Alignment.centerLeft : Alignment.topLeft,
|
layout == Layout.one ? Alignment.centerLeft : Alignment.topLeft,
|
||||||
|
@ -67,6 +67,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
layout == Layout.one ? TextOverflow.ellipsis : TextOverflow.fade,
|
layout == Layout.one ? TextOverflow.ellipsis : TextOverflow.fade,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _circleImage(BuildContext context,
|
Widget _circleImage(BuildContext context,
|
||||||
{EpisodeBrief episode, Color color, bool boo}) =>
|
{EpisodeBrief episode, Color color, bool boo}) =>
|
||||||
Container(
|
Container(
|
||||||
|
@ -79,6 +80,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
backgroundImage: FileImage(File("${episode.imagePath}")),
|
backgroundImage: FileImage(File("${episode.imagePath}")),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _listenIndicater(BuildContext context,
|
Widget _listenIndicater(BuildContext context,
|
||||||
{EpisodeBrief episode, int isListened}) =>
|
{EpisodeBrief episode, int isListened}) =>
|
||||||
Selector<AudioPlayerNotifier, Tuple2<EpisodeBrief, bool>>(
|
Selector<AudioPlayerNotifier, Tuple2<EpisodeBrief, bool>>(
|
||||||
|
@ -133,6 +135,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
: Center(),
|
: Center(),
|
||||||
)
|
)
|
||||||
: Center();
|
: Center();
|
||||||
|
|
||||||
Widget _isNewIndicator(EpisodeBrief episode) => episode.isNew == 1
|
Widget _isNewIndicator(EpisodeBrief episode) => episode.isNew == 1
|
||||||
? Container(
|
? Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 2),
|
padding: EdgeInsets.symmetric(horizontal: 2),
|
||||||
|
@ -158,6 +161,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Center();
|
: Center();
|
||||||
|
|
||||||
Widget _pubDate(BuildContext context, {EpisodeBrief episode, Color color}) =>
|
Widget _pubDate(BuildContext context, {EpisodeBrief episode, Color color}) =>
|
||||||
Text(
|
Text(
|
||||||
episode.dateToString(),
|
episode.dateToString(),
|
||||||
|
@ -166,7 +170,6 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
color: color,
|
color: color,
|
||||||
fontStyle: FontStyle.italic),
|
fontStyle: FontStyle.italic),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
double _width = MediaQuery.of(context).size.width;
|
double _width = MediaQuery.of(context).size.width;
|
||||||
|
@ -242,6 +245,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
showItemDuration: Duration(milliseconds: 50),
|
showItemDuration: Duration(milliseconds: 50),
|
||||||
);
|
);
|
||||||
final scrollController = ScrollController();
|
final scrollController = ScrollController();
|
||||||
|
|
||||||
return SliverPadding(
|
return SliverPadding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
top: 10.0, bottom: 5.0, left: 15.0, right: 15.0),
|
top: 10.0, bottom: 5.0, left: 15.0, right: 15.0),
|
||||||
|
@ -261,11 +265,12 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
Color _c = (Theme.of(context).brightness == Brightness.light)
|
Color _c = (Theme.of(context).brightness == Brightness.light)
|
||||||
? episodes[index].primaryColor.colorizedark()
|
? episodes[index].primaryColor.colorizedark()
|
||||||
: episodes[index].primaryColor.colorizeLight();
|
: episodes[index].primaryColor.colorizeLight();
|
||||||
|
scrollController.addListener(() {
|
||||||
|
print(scrollController.offset);
|
||||||
|
});
|
||||||
return FadeTransition(
|
return FadeTransition(
|
||||||
opacity: Tween<double>(
|
opacity: Tween<double>(begin: index < initNum ? 0 : 1, end: 1)
|
||||||
begin: index < initNum ? 0 : 1,
|
.animate(animation),
|
||||||
end: 1,
|
|
||||||
).animate(animation),
|
|
||||||
child: Selector<AudioPlayerNotifier,
|
child: Selector<AudioPlayerNotifier,
|
||||||
Tuple2<EpisodeBrief, List<String>>>(
|
Tuple2<EpisodeBrief, List<String>>>(
|
||||||
selector: (_, audio) => Tuple2(audio?.episode,
|
selector: (_, audio) => Tuple2(audio?.episode,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'context_extension.dart';
|
|
||||||
|
|
||||||
//Slide Transition
|
//Slide Transition
|
||||||
class SlideLeftRoute extends PageRouteBuilder {
|
class SlideLeftRoute extends PageRouteBuilder {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: tsacdop
|
name: tsacdop
|
||||||
description: An easy-use podacasts player.
|
description: An easy-use podacasts player.
|
||||||
|
|
||||||
version: 0.3.2
|
version: 0.3.3
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.6.0 <3.0.0"
|
sdk: ">=2.6.0 <3.0.0"
|
||||||
|
@ -41,9 +41,9 @@ dependencies:
|
||||||
connectivity: ^0.4.8+2
|
connectivity: ^0.4.8+2
|
||||||
flare_flutter: ^2.0.3
|
flare_flutter: ^2.0.3
|
||||||
rxdart: ^0.24.0
|
rxdart: ^0.24.0
|
||||||
auto_animated: ^2.1.0
|
|
||||||
wc_flutter_share: ^0.2.1
|
wc_flutter_share: ^0.2.1
|
||||||
video_player: ^0.10.11
|
video_player: ^0.10.11
|
||||||
|
auto_animated: ^2.1.0
|
||||||
just_audio:
|
just_audio:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/stonega/just_audio.git
|
url: https://github.com/stonega/just_audio.git
|
||||||
|
|
Loading…
Reference in New Issue