Bug fixes

Change home group preview grid to 2
This commit is contained in:
stonegate 2020-04-02 17:52:26 +08:00
parent 0a0e0a45f5
commit 5dc490f83f
18 changed files with 394 additions and 300 deletions

BIN
assets/shownote.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -126,7 +126,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
bool _stopOnComplete = false; bool _stopOnComplete = false;
Timer _stopTimer; Timer _stopTimer;
int _timeLeft = 0; int _timeLeft = 0;
bool _showStopWatch = false; bool _startSleepTimer = false;
double _switchValue = 0; double _switchValue = 0;
bool _autoPlay = true; bool _autoPlay = true;
DateTime _current; DateTime _current;
@ -144,7 +144,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
bool get queueUpdate => _queueUpdate; bool get queueUpdate => _queueUpdate;
EpisodeBrief get episode => _episode; EpisodeBrief get episode => _episode;
bool get stopOnComplete => _stopOnComplete; bool get stopOnComplete => _stopOnComplete;
bool get showStopWatch => _showStopWatch; bool get startSleepTimer => _startSleepTimer;
bool get autoPlay => _autoPlay; bool get autoPlay => _autoPlay;
int get timeLeft => _timeLeft; int get timeLeft => _timeLeft;
double get switchValue => _switchValue; double get switchValue => _switchValue;
@ -165,8 +165,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
_queueUpdate = false; _queueUpdate = false;
await AudioService.connect(); await AudioService.connect();
bool running = await AudioService.running; bool running = await AudioService.running;
if (running) { if (running) {}
}
} }
loadPlaylist() async { loadPlaylist() async {
@ -217,13 +216,13 @@ class AudioPlayerNotifier extends ChangeNotifier {
await AudioService.connect(); await AudioService.connect();
} }
await AudioService.start( await AudioService.start(
backgroundTaskEntrypoint: _audioPlayerTaskEntrypoint, backgroundTaskEntrypoint: _audioPlayerTaskEntrypoint,
androidNotificationChannelName: 'Tsacdop', androidNotificationChannelName: 'Tsacdop',
notificationColor: 0xFF4d91be, notificationColor: 0xFF4d91be,
androidNotificationIcon: 'drawable/ic_notification', androidNotificationIcon: 'drawable/ic_notification',
enableQueue: true, enableQueue: true,
androidStopOnRemoveTask: true, androidStopOnRemoveTask: true,
androidStopForegroundOnPause: true); );
_playerRunning = true; _playerRunning = true;
if (_autoPlay) { if (_autoPlay) {
await Future.forEach(_queue.playlist, (episode) async { await Future.forEach(_queue.playlist, (episode) async {
@ -312,7 +311,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
} }
notifyListeners(); notifyListeners();
} }
if (_audioState == BasicPlaybackState.stopped) { if (_audioState == BasicPlaybackState.stopped || _playerRunning == false) {
timer.cancel(); timer.cancel();
} }
}); });
@ -325,6 +324,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
_seekSliderValue = 0; _seekSliderValue = 0;
_episode = _queue.playlist.first; _episode = _queue.playlist.first;
_playerRunning = true; _playerRunning = true;
_queueUpdate = !_queueUpdate;
notifyListeners(); notifyListeners();
_startAudioService(_lastPostion ?? 0); _startAudioService(_lastPostion ?? 0);
} }
@ -397,9 +397,9 @@ class AudioPlayerNotifier extends ChangeNotifier {
int pos = _backgroundAudioPosition + s * 1000; int pos = _backgroundAudioPosition + s * 1000;
AudioService.seekTo(pos); AudioService.seekTo(pos);
} }
seekTo(int position) async{ seekTo(int position) async {
if (_audioState != BasicPlaybackState.connecting && if (_audioState != BasicPlaybackState.connecting &&
_audioState != BasicPlaybackState.none) _audioState != BasicPlaybackState.none)
await AudioService.seekTo(position); await AudioService.seekTo(position);
} }
@ -417,9 +417,9 @@ class AudioPlayerNotifier extends ChangeNotifier {
} }
} }
//Set sleep time //Set sleep timer
sleepTimer(int mins) { sleepTimer(int mins) {
_showStopWatch = true; _startSleepTimer= true;
_switchValue = 1; _switchValue = 1;
notifyListeners(); notifyListeners();
_timeLeft = mins * 60; _timeLeft = mins * 60;
@ -432,12 +432,14 @@ class AudioPlayerNotifier extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
}); });
_stopTimer = Timer(Duration(minutes: mins), () { _stopTimer = Timer(Duration(minutes: mins), () {
_stopOnComplete = false; _stopOnComplete = false;
_showStopWatch = false; _startSleepTimer= false;
_switchValue = 0; _switchValue = 0;
_playerRunning = false;
notifyListeners();
AudioService.stop(); AudioService.stop();
notifyListeners(); AudioService.disconnect();
}); });
} }
@ -445,7 +447,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
cancelTimer() { cancelTimer() {
_stopTimer.cancel(); _stopTimer.cancel();
_timeLeft = 0; _timeLeft = 0;
_showStopWatch = false; _startSleepTimer= false;
_switchValue = 0; _switchValue = 0;
notifyListeners(); notifyListeners();
} }

View File

@ -16,13 +16,16 @@ import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:tsacdop/class/audiostate.dart'; import 'package:tsacdop/class/audiostate.dart';
import 'package:tsacdop/class/episodebrief.dart'; import 'package:tsacdop/class/episodebrief.dart';
import 'package:tsacdop/local_storage/sqflite_localpodcast.dart'; import 'package:tsacdop/local_storage/sqflite_localpodcast.dart';
import 'package:tsacdop/util/context_extension.dart';
import 'episodedownload.dart'; import 'episodedownload.dart';
class EpisodeDetail extends StatefulWidget { class EpisodeDetail extends StatefulWidget {
final EpisodeBrief episodeItem; final EpisodeBrief episodeItem;
final String heroTag; final String heroTag;
final bool hide; final bool hide;
EpisodeDetail({this.episodeItem, this.heroTag = '',this.hide = false, Key key}) : super(key: key); EpisodeDetail(
{this.episodeItem, this.heroTag = '', this.hide = false, Key key})
: super(key: key);
@override @override
_EpisodeDetailState createState() => _EpisodeDetailState(); _EpisodeDetailState createState() => _EpisodeDetailState();
@ -38,7 +41,8 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
Future getSDescription(String url) async { Future getSDescription(String url) async {
var dbHelper = DBHelper(); var dbHelper = DBHelper();
_description = (await dbHelper.getDescription(url)) _description = (await dbHelper.getDescription(url))
.replaceAll(RegExp(r'\s?<p>(<br>)?</p>\s?'), '').replaceAll('\r', ''); .replaceAll(RegExp(r'\s?<p>(<br>)?</p>\s?'), '')
.replaceAll('\r', '');
if (mounted) if (mounted)
setState(() { setState(() {
_loaddes = true; _loaddes = true;
@ -93,7 +97,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
child: Scaffold( child: Scaffold(
backgroundColor: Theme.of(context).primaryColor, backgroundColor: Theme.of(context).primaryColor,
appBar: AppBar( appBar: AppBar(
// title: Text(widget.episodeItem.feedTitle), // title: Text(widget.episodeItem.feedTitle),
centerTitle: true, centerTitle: true,
), ),
body: Stack( body: Stack(
@ -197,13 +201,12 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
padding: EdgeInsets.only(top: 5.0), padding: EdgeInsets.only(top: 5.0),
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
//physics: AlwaysScrollableScrollPhysics(),
controller: _controller, controller: _controller,
child: _loaddes child: _loaddes
? (_description.contains('<')) ? (_description.contains('<'))
? Html( ? Html(
padding: padding: EdgeInsets.only(
EdgeInsets.only(left: 20.0, right: 20, bottom: 10), left: 20.0, right: 20, bottom: 10),
defaultTextStyle: TextStyle(height: 1.8), defaultTextStyle: TextStyle(height: 1.8),
data: _description, data: _description,
linkStyle: TextStyle( linkStyle: TextStyle(
@ -215,24 +218,48 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
}, },
useRichText: true, useRichText: true,
) )
: Container( : _description.length > 0
padding: ? Container(
EdgeInsets.only(left: 20.0, right: 20.0, bottom: 10.0), padding: EdgeInsets.only(
alignment: Alignment.topLeft, left: 20.0,
child: SelectableLinkify( right: 20.0,
onOpen: (link) { bottom: 10.0),
_launchUrl(link.url); alignment: Alignment.topLeft,
}, child: SelectableLinkify(
text: _description, onOpen: (link) {
style: TextStyle( _launchUrl(link.url);
height: 1.8, },
), text: _description,
linkStyle: TextStyle( style: TextStyle(
color: Theme.of(context).accentColor, height: 1.8,
decoration: TextDecoration.underline, ),
), linkStyle: TextStyle(
), color:
) Theme.of(context).accentColor,
decoration:
TextDecoration.underline,
),
),
)
: Container(
height: context.width,
alignment: Alignment.center,
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: <Widget>[
Image(
image: AssetImage(
'assets/shownote.png'),
height: 100.0,
),
Padding(padding: EdgeInsets.all(5.0)),
Text(
'Still no shownote received\n for this episode.', textAlign: TextAlign.center,
style: TextStyle(color: context.textTheme.bodyText1.color.withOpacity(0.5))),
],
),
)
: Center(), : Center(),
), ),
), ),
@ -259,10 +286,9 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: MenuBar( child: MenuBar(
episodeItem: widget.episodeItem, episodeItem: widget.episodeItem,
heroTag: widget.heroTag, heroTag: widget.heroTag,
hide: widget.hide hide: widget.hide),
),
), ),
), ),
); );
@ -279,7 +305,8 @@ class MenuBar extends StatefulWidget {
final EpisodeBrief episodeItem; final EpisodeBrief episodeItem;
final String heroTag; final String heroTag;
final bool hide; final bool hide;
MenuBar({this.episodeItem, this.heroTag, this.hide, Key key}) : super(key: key); MenuBar({this.episodeItem, this.heroTag, this.hide, Key key})
: super(key: key);
@override @override
_MenuBarState createState() => _MenuBarState(); _MenuBarState createState() => _MenuBarState();
} }
@ -349,10 +376,11 @@ class _MenuBarState extends State<MenuBar> {
height: 30.0, height: 30.0,
width: 30.0, width: 30.0,
color: Theme.of(context).scaffoldBackgroundColor, color: Theme.of(context).scaffoldBackgroundColor,
child: widget.hide ? Center() : child: widget.hide
CircleAvatar( ? Center()
backgroundImage: : CircleAvatar(
FileImage(File("${widget.episodeItem.imagePath}"))), backgroundImage:
FileImage(File("${widget.episodeItem.imagePath}"))),
), ),
), ),
), ),

View File

@ -72,20 +72,19 @@ class AboutApp extends StatelessWidget {
image: AssetImage('assets/logo.png'), image: AssetImage('assets/logo.png'),
height: 80, height: 80,
), ),
Text('Version: 0.1.5'), Text('Version: 0.1.6'),
], ],
), ),
), ),
Container( Container(
padding: EdgeInsets.symmetric(horizontal: 50), padding: EdgeInsets.symmetric(horizontal: 50),
height: 50,
child: Text( child: Text(
'Tsacdop is a podcast player developed in flutter, a simple, beautiful, and easy-use application.', 'Tsacdop is a podcast player developed in flutter, a simply beautiful, and friendly app.',
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
Padding( Padding(
padding: EdgeInsets.all(5.0), padding: EdgeInsets.all(10.0),
), ),
Container( Container(
padding: EdgeInsets.only(top: 20.0, bottom: 10.0), padding: EdgeInsets.only(top: 20.0, bottom: 10.0),
@ -113,7 +112,7 @@ class AboutApp extends StatelessWidget {
'https://twitter.com/shimenmen'), 'https://twitter.com/shimenmen'),
_listItem( _listItem(
context, context,
'Stone Gate', 'Medium',
LineIcons.medium, LineIcons.medium,
'https://medium.com/@stonegate'), 'https://medium.com/@stonegate'),
], ],

View File

@ -71,10 +71,10 @@ class MyRoundSliderThumpShape extends SliderComponentShape {
begin: _disabledThumbRadius, begin: _disabledThumbRadius,
end: enabledThumbRadius, end: enabledThumbRadius,
); );
final ColorTween colorTween = ColorTween( // final ColorTween colorTween = ColorTween(
begin: sliderTheme.disabledThumbColor, // begin: sliderTheme.disabledThumbColor,
end: sliderTheme.thumbColor, // end: sliderTheme.thumbColor,
); // );
canvas.drawCircle( canvas.drawCircle(
center, center,
@ -157,7 +157,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false); var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
return Selector<AudioPlayerNotifier, Tuple3<bool, int, double>>( return Selector<AudioPlayerNotifier, Tuple3<bool, int, double>>(
selector: (_, audio) => selector: (_, audio) =>
Tuple3(audio.showStopWatch, audio.timeLeft, audio.switchValue), Tuple3(audio.startSleepTimer, audio.timeLeft, audio.switchValue),
builder: (_, data, __) { builder: (_, data, __) {
return Container( return Container(
height: 300, height: 300,
@ -547,17 +547,14 @@ class _PlayerWidgetState extends State<PlayerWidget> {
Spacer(), Spacer(),
Selector<AudioPlayerNotifier, Tuple3<EpisodeBrief, bool, bool>>( Selector<AudioPlayerNotifier, Tuple3<EpisodeBrief, bool, bool>>(
selector: (_, audio) => Tuple3( selector: (_, audio) => Tuple3(
audio.episode, audio.stopOnComplete, audio.showStopWatch), audio.episode, audio.stopOnComplete, audio.startSleepTimer),
builder: (_, data, __) { builder: (_, data, __) {
return Container( return Container(
padding: EdgeInsets.all(12.0), padding: EdgeInsets.all(5.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
Padding(
padding: EdgeInsets.all(5.0),
),
Container( Container(
height: 30.0, height: 30.0,
width: 30.0, width: 30.0,
@ -568,7 +565,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
), ),
Container( Container(
padding: EdgeInsets.symmetric(horizontal: 5.0), padding: EdgeInsets.symmetric(horizontal: 5.0),
width: 200, width: 150,
child: Text( child: Text(
data.item1.feedTitle, data.item1.feedTitle,
maxLines: 1, maxLines: 1,
@ -578,6 +575,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
Spacer(), Spacer(),
LastPosition(), LastPosition(),
IconButton( IconButton(
padding: EdgeInsets.zero,
onPressed: () => Navigator.push( onPressed: () => Navigator.push(
context, context,
SlideUptRoute( SlideUptRoute(
@ -1007,8 +1005,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
builder: (_, audioplay, __) { builder: (_, audioplay, __) {
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Spacer(),
audioplay == BasicPlaybackState.playing audioplay == BasicPlaybackState.playing
? InkWell( ? InkWell(
onTap: onTap:
@ -1032,7 +1031,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
alignment: Alignment.center, alignment: Alignment.center,
children: <Widget>[ children: <Widget>[
Container( Container(
padding: EdgeInsets.all(10.0), padding: EdgeInsets.symmetric(vertical: 10.0),
child: Container( child: Container(
height: 30.0, height: 30.0,
width: 30.0, width: 30.0,
@ -1214,7 +1213,7 @@ class _ImageRotateState extends State<ImageRotate>
return Transform.rotate( return Transform.rotate(
angle: 2 * math.pi * _value, angle: 2 * math.pi * _value,
child: Container( child: Container(
padding: EdgeInsets.all(10.0), padding: EdgeInsets.symmetric(vertical: 10.0),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(15.0)), borderRadius: BorderRadius.all(Radius.circular(15.0)),
child: Container( child: Container(

View File

@ -482,8 +482,8 @@ class ShowEpisode extends StatelessWidget {
padding: const EdgeInsets.all(5.0), padding: const EdgeInsets.all(5.0),
sliver: SliverGrid( sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 1.0, childAspectRatio: 1.5,
crossAxisCount: 3, crossAxisCount: 2,
mainAxisSpacing: 6.0, mainAxisSpacing: 6.0,
crossAxisSpacing: 6.0, crossAxisSpacing: 6.0,
), ),
@ -529,15 +529,6 @@ class ShowEpisode extends StatelessWidget {
); );
}, },
child: Container( child: Container(
// decoration: BoxDecoration(
// border: Border.all(
// color: Theme.of(context).brightness ==
// Brightness.light
// ? Theme.of(context).primaryColor
// : Theme.of(context).scaffoldBackgroundColor,
// width: 0.0,
// ),
// ),
padding: EdgeInsets.all(10.0), padding: EdgeInsets.all(10.0),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -560,7 +551,7 @@ class ShowEpisode extends StatelessWidget {
), ),
), ),
Spacer(), Spacer(),
episodes[index].isNew == 1 episodes[index].isNew == 1
? Text( ? Text(
'New', 'New',
style: TextStyle( style: TextStyle(
@ -579,8 +570,8 @@ class ShowEpisode extends StatelessWidget {
child: Text( child: Text(
episodes[index].title, episodes[index].title,
style: TextStyle( style: TextStyle(
fontSize: _width / 32, //fontSize: _width / 32,
), ),
maxLines: 4, maxLines: 4,
overflow: TextOverflow.fade, overflow: TextOverflow.fade,
), ),
@ -588,17 +579,37 @@ class ShowEpisode extends StatelessWidget {
), ),
Expanded( Expanded(
flex: 1, flex: 1,
child: Container( child: Row(
alignment: Alignment.bottomLeft, children: <Widget>[
child: Text( Container(
episodes[index].dateToString(), alignment: Alignment.bottomLeft,
//podcast[index].pubDate.substring(4, 16), child: Text(
style: TextStyle( episodes[index].dateToString(),
fontSize: _width / 35, //podcast[index].pubDate.substring(4, 16),
color: _c, style: TextStyle(
fontStyle: FontStyle.italic, fontSize: _width / 35,
color: _c,
fontStyle: FontStyle.italic,
),
),
), ),
), Spacer(),
episodes[index].duration != 0
? Container(
alignment: Alignment.center,
child: Text(
(episodes[index].duration)
.toString() +
'mins',
style: TextStyle(
fontSize: _width / 35,
// color: _c,
// fontStyle: FontStyle.italic,
),
),
)
: Center(),
],
)), )),
], ],
), ),
@ -608,7 +619,7 @@ class ShowEpisode extends StatelessWidget {
), ),
); );
}, },
childCount: (episodes.length > 3) ? 3 : episodes.length, childCount: (episodes.length > 2) ? 2 : episodes.length,
), ),
), ),
), ),

View File

@ -88,121 +88,142 @@ class _PlaylistPageState extends State<PlaylistPage> {
height: _topHeight, height: _topHeight,
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Container( Expanded(
height: _topHeight, flex: 2,
padding: EdgeInsets.only( child: Container(
left: 70, height: _topHeight,
), padding: EdgeInsets.only(
alignment: Alignment.centerLeft, left: 60,
child: RichText( ),
text: TextSpan( alignment: Alignment.centerLeft,
text: _topHeight > 90 ? 'Playlist\n' : '', child: RichText(
style: TextStyle( text: TextSpan(
color: text: _topHeight > 90 ? 'Playlist\n' : '',
Theme.of(context).textTheme.bodyText1.color, style: TextStyle(
fontSize: 30, color: Theme.of(context)
), .textTheme
children: <TextSpan>[ .bodyText1
TextSpan( .color,
text: episodes.length.toString(), fontSize: 30,
style: GoogleFonts.cairo( ),
textStyle: TextStyle( children: <TextSpan>[
color: Theme.of(context).accentColor, TextSpan(
fontSize: 30, text: episodes.length.toString(),
style: GoogleFonts.cairo(
textStyle: TextStyle(
color: Theme.of(context).accentColor,
fontSize: 25,
),
), ),
), ),
), TextSpan(
TextSpan( text: episodes.length < 2
text: episodes.length < 2 ? 'episode'
? ' episode ' : 'episodes',
: ' episodes ', style: TextStyle(
style: TextStyle( color: Theme.of(context).accentColor,
fontSize: 15,
)),
TextSpan(
text:
_sumPlaylistLength(episodes).toString(),
style: GoogleFonts.cairo(
textStyle: TextStyle(
color: Theme.of(context).accentColor, color: Theme.of(context).accentColor,
fontSize: 20, fontSize: 25,
)), )),
TextSpan( ),
text: _sumPlaylistLength(episodes).toString(), TextSpan(
style: GoogleFonts.cairo( text: 'mins',
textStyle: TextStyle( style: TextStyle(
color: Theme.of(context).accentColor, color: Theme.of(context).accentColor,
fontSize: 30, fontSize: 15,
)), )),
), ],
TextSpan( ),
text: ' mins',
style: TextStyle(
color: Theme.of(context).accentColor,
fontSize: 20,
)),
],
), ),
), ),
), ),
Spacer(), Expanded(
Container( flex: 1,
padding: EdgeInsets.only( child: Container(
right: 20, padding: EdgeInsets.all(5.0),
), margin: EdgeInsets.only(right: 20.0, bottom: 5.0),
child: data.item2 decoration: data.item2 ? BoxDecoration(
? _topHeight < 90 color: context.brightness == Brightness.dark ? Colors.grey[800] : Colors.grey[200],
? Row( borderRadius:
mainAxisAlignment: BorderRadius.all(Radius.circular(10.0)),
MainAxisAlignment.center, ) :
crossAxisAlignment: BoxDecoration(
CrossAxisAlignment.center, shape: BoxShape.circle,
children: <Widget>[ color: Colors.transparent
CircleAvatar( ),
radius: 12, child: data.item2
backgroundImage: FileImage(File( ? _topHeight < 90
"${episodes.first.imagePath}")), ? Row(
), mainAxisAlignment:
Padding( MainAxisAlignment.center,
padding: EdgeInsets.symmetric( crossAxisAlignment:
horizontal: 15), CrossAxisAlignment.center,
child: SizedBox( children: <Widget>[
width: 20, CircleAvatar(
height: 15, radius: 12,
child: WaveLoader()), backgroundImage: FileImage(File(
), "${episodes.first.imagePath}")),
],
)
: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: <Widget>[
CircleAvatar(
radius: 15,
//backgroundColor: _c.withOpacity(0.5),
backgroundImage: FileImage(File(
"${episodes.first.imagePath}")),
),
Container(
width: 150,
alignment: Alignment.center,
child: Text(
episodes.first.title,
maxLines: 1,
overflow: TextOverflow.fade,
), ),
), Padding(
Padding( padding: EdgeInsets.symmetric(
padding: EdgeInsets.symmetric( horizontal: 15),
horizontal: 15), child: SizedBox(
child: SizedBox( width: 20,
width: 20, height: 15,
height: 15, child: WaveLoader()),
child: WaveLoader()), ),
), ],
], )
) : Column(
: IconButton( mainAxisAlignment:
icon: Icon(Icons.play_circle_filled, MainAxisAlignment.center,
size: 40, crossAxisAlignment:
color: Theme.of(context).accentColor), CrossAxisAlignment.center,
onPressed: () => audio.playlistLoad(), children: <Widget>[
), CircleAvatar(
radius: 15,
//backgroundColor: _c.withOpacity(0.5),
backgroundImage: FileImage(File(
"${episodes.first.imagePath}")),
),
Container(
width: 150,
alignment: Alignment.center,
child: Text(
episodes.first.title,
maxLines: 1,
overflow: TextOverflow.fade,
textAlign: TextAlign.center,
),
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 15),
child: SizedBox(
width: 20,
height: 15,
child: WaveLoader()),
),
],
)
: IconButton(
padding: EdgeInsets.all(0),
alignment: Alignment.center,
icon: Icon(Icons.play_circle_filled,
size: 40,
color: Theme.of(context).accentColor),
onPressed: () {
audio.playlistLoad();
// setState(() {});
}),
),
), ),
], ],
), ),
@ -286,6 +307,7 @@ class _DismissibleContainerState extends State<DismissibleContainer> {
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false); var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
return AnimatedContainer( return AnimatedContainer(
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
alignment: Alignment.center,
height: _delete ? 0 : 95.0, height: _delete ? 0 : 95.0,
child: _delete child: _delete
? Container( ? Container(

View File

@ -195,12 +195,12 @@ class DBHelper {
return result; return result;
} }
Future<List<PlayHistory>> getPlayHistory() async { Future<List<PlayHistory>> getPlayHistory(int top) async {
var dbClient = await database; var dbClient = await database;
List<Map> list = await dbClient.rawQuery( List<Map> list = await dbClient.rawQuery(
"""SELECT title, enclosure_url, seconds, seek_value, add_date FROM PlayHistory """SELECT title, enclosure_url, seconds, seek_value, add_date FROM PlayHistory
ORDER BY add_date DESC ORDER BY add_date DESC LIMIT ?
"""); """,[top]);
List<PlayHistory> playHistory = []; List<PlayHistory> playHistory = [];
list.forEach((record) { list.forEach((record) {
playHistory.add(PlayHistory(record['title'], record['enclosure_url'], playHistory.add(PlayHistory(record['title'], record['enclosure_url'],

View File

@ -173,7 +173,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
void initState() { void initState() {
super.initState(); super.initState();
_loadMore = false; _loadMore = false;
_top = 33; _top = 99;
_controller = ScrollController(); _controller = ScrollController();
} }

View File

@ -13,16 +13,26 @@ class PlayedHistory extends StatefulWidget {
class _PlayedHistoryState extends State<PlayedHistory> class _PlayedHistoryState extends State<PlayedHistory>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
Future<List<PlayHistory>> getPlayHistory() async { Future<List<PlayHistory>> getPlayHistory(int top) async {
DBHelper dbHelper = DBHelper(); DBHelper dbHelper = DBHelper();
List<PlayHistory> playHistory; List<PlayHistory> playHistory;
playHistory = await dbHelper.getPlayHistory(); playHistory = await dbHelper.getPlayHistory(top);
await Future.forEach(playHistory, (playHistory) async { await Future.forEach(playHistory, (playHistory) async {
await playHistory.getEpisode(); await playHistory.getEpisode();
}); });
return playHistory; return playHistory;
} }
_loadMoreData() async {
// await Future.delayed(Duration(seconds: 3));
if (mounted)
setState(() {
_top = _top + 100;
});
}
int _top = 100;
Future<List<SubHistory>> getSubHistory() async { Future<List<SubHistory>> getSubHistory() async {
DBHelper dbHelper = DBHelper(); DBHelper dbHelper = DBHelper();
return await dbHelper.getSubHistory(); return await dbHelper.getSubHistory();
@ -126,94 +136,109 @@ class _PlayedHistoryState extends State<PlayedHistory>
}, },
body: TabBarView(controller: _controller, children: <Widget>[ body: TabBarView(controller: _controller, children: <Widget>[
FutureBuilder<List<PlayHistory>>( FutureBuilder<List<PlayHistory>>(
future: getPlayHistory(), future: getPlayHistory(_top),
builder: (context, snapshot) { builder: (context, snapshot) {
double _width = MediaQuery.of(context).size.width; double _width = MediaQuery.of(context).size.width;
return snapshot.hasData return snapshot.hasData
? ListView.builder( ? NotificationListener<ScrollNotification>(
shrinkWrap: true, onNotification: (ScrollNotification scrollInfo) {
scrollDirection: Axis.vertical, if (scrollInfo.metrics.pixels ==
itemCount: snapshot.data.length, scrollInfo.metrics.maxScrollExtent &&
itemBuilder: (BuildContext context, int index) { snapshot.data.length == _top)
return Container( _loadMoreData();
color: Theme.of(context).scaffoldBackgroundColor, return true;
child: Column( },
children: <Widget>[ child: ListView.builder(
ListTile( //shrinkWrap: true,
title: Column( scrollDirection: Axis.vertical,
mainAxisAlignment: itemCount: snapshot.data.length,
MainAxisAlignment.start, itemBuilder: (BuildContext context, int index) {
crossAxisAlignment: return Container(
CrossAxisAlignment.start, color:
children: <Widget>[ Theme.of(context).scaffoldBackgroundColor,
Text( child: Column(
DateFormat.yMd().add_jm().format( children: <Widget>[
snapshot.data[index].playdate), ListTile(
style: TextStyle( title: Column(
color: const Color(0xff67727d), mainAxisAlignment:
fontSize: 15, MainAxisAlignment.start,
fontStyle: FontStyle.italic), crossAxisAlignment:
), CrossAxisAlignment.start,
Text( children: <Widget>[
snapshot.data[index].title, Text(
maxLines: 2, DateFormat.yMd().add_jm().format(
overflow: TextOverflow.ellipsis, snapshot
), .data[index].playdate),
],
),
subtitle: Container(
width: _width,
child: Row(
children: <Widget>[
Icon(
Icons.timelapse,
color: Colors.grey[400],
),
Container(
height: 2,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.grey[400],
width: 2.0))),
width: _width *
snapshot.data[index]
.seekValue <
(_width - 120)
? _width *
snapshot
.data[index].seekValue
: _width - 120,
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 2),
),
Container(
width: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Theme.of(context)
.accentColor,
borderRadius: BorderRadius.all(
Radius.circular(10))),
padding: EdgeInsets.all(2),
child: Text(
_stringForSeconds(
snapshot.data[index].seconds),
style: TextStyle( style: TextStyle(
color: Colors.white), color:
const Color(0xff67727d),
fontSize: 15,
fontStyle: FontStyle.italic),
), ),
Text(
snapshot.data[index].title,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
subtitle: Container(
width: _width,
child: Row(
children: <Widget>[
Icon(
Icons.timelapse,
color: Colors.grey[400],
),
Container(
height: 2,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors
.grey[400],
width: 2.0))),
width: _width *
snapshot.data[index]
.seekValue <
(_width - 120)
? _width *
snapshot.data[index]
.seekValue
: _width - 120,
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 2),
),
Container(
width: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Theme.of(context)
.accentColor,
borderRadius:
BorderRadius.all(
Radius.circular(
10))),
padding: EdgeInsets.all(2),
child: Text(
_stringForSeconds(snapshot
.data[index].seconds),
style: TextStyle(
color: Colors.white),
),
),
],
), ),
], ),
), ),
), // Divider(height: 2),
],
), ),
// Divider(height: 2), );
], }),
), )
);
})
: Center( : Center(
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
); );

View File

@ -41,5 +41,8 @@ List<Libries> plugins = [
Libries('audio_service', mit, 'https://pub.dev/packages/audio_service'), Libries('audio_service', mit, 'https://pub.dev/packages/audio_service'),
Libries('just_audio', apacheLicense, 'https://pub.dev/packages/just_audio'), Libries('just_audio', apacheLicense, 'https://pub.dev/packages/just_audio'),
Libries('line_icons', gpl, 'https://pub.dev/packages/line_icons'), Libries('line_icons', gpl, 'https://pub.dev/packages/line_icons'),
Libries('flutter_file_dialog', bsd, 'https://pub.dev/packages/flutter_file_dialog') Libries('flutter_file_dialog', bsd, 'https://pub.dev/packages/flutter_file_dialog'),
Libries('flutter_linkify', mit, 'https://pub.dev/packages/flutter_linkify'),
Libries('extended_nested_scroll_view', mit, 'https://pub.dev/packages/extended_nested_scroll_view'),
Libries('connectivity', bsd, 'https://pub.dev/packages/connectivity'),
]; ];

View File

@ -195,7 +195,7 @@ class Settings extends StatelessWidget {
EdgeInsets.symmetric(horizontal: 25.0), EdgeInsets.symmetric(horizontal: 25.0),
leading: Icon(LineIcons.map_signs_solid), leading: Icon(LineIcons.map_signs_solid),
title: Text('Changelog'), title: Text('Changelog'),
subtitle: Text('List of chagnes'), subtitle: Text('List of changes'),
), ),
Divider(height: 2), Divider(height: 2),
ListTile( ListTile(
@ -213,7 +213,7 @@ class Settings extends StatelessWidget {
Divider(height: 2), Divider(height: 2),
ListTile( ListTile(
onTap: () => _launchUrl( onTap: () => _launchUrl(
'mailto:<xijieyin@gmail.com>?subject=Tsacdop Feedback'), 'mailto:<tsacdop.app@gmail.com>?subject=Tsacdop Feedback'),
contentPadding: contentPadding:
EdgeInsets.symmetric(horizontal: 25.0), EdgeInsets.symmetric(horizontal: 25.0),
leading: Icon(LineIcons.bug_solid), leading: Icon(LineIcons.bug_solid),

View File

@ -58,7 +58,7 @@ class StorageSetting extends StatelessWidget {
EdgeInsets.only(left: 80.0, right: 25), EdgeInsets.only(left: 80.0, right: 25),
title: Text('Ask before using cellular data'), title: Text('Ask before using cellular data'),
subtitle: Text( subtitle: Text(
'Ask to confirem when using cellular data to download episodes.'), 'Ask to confirm when using cellular data to download episodes.'),
trailing: Selector<SettingState, bool>( trailing: Selector<SettingState, bool>(
selector: (_, settings) => selector: (_, settings) =>
settings.downloadUsingData, settings.downloadUsingData,

View File

@ -8,4 +8,5 @@ extension ContextExtension on BuildContext{
Brightness get brightness => Theme.of(this).brightness; Brightness get brightness => Theme.of(this).brightness;
double get width => MediaQuery.of(this).size.width; double get width => MediaQuery.of(this).size.width;
double get height => MediaQuery.of(this).size.width; double get height => MediaQuery.of(this).size.width;
TextTheme get textTheme => Theme.of(this).textTheme;
} }

View File

@ -1,4 +1,7 @@
//Fork from https://github.com/divyanshub024/day_night_switch //Fork from https://github.com/divyanshub024/day_night_switch
//Copyright https://github.com/divyanshub024
//Apache License 2.0 https://github.com/divyanshub024/day_night_switch/blob/master/LICENSE
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';

View File

@ -104,7 +104,7 @@ class EpisodeGrid extends StatelessWidget {
const EdgeInsets.only(top: 5.0, bottom: 5.0, left: 15.0, right: 15.0), const EdgeInsets.only(top: 5.0, bottom: 5.0, left: 15.0, right: 15.0),
sliver: SliverGrid( sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 1.0, childAspectRatio: 1,
crossAxisCount: 3, crossAxisCount: 3,
mainAxisSpacing: 6.0, mainAxisSpacing: 6.0,
crossAxisSpacing: 6.0, crossAxisSpacing: 6.0,
@ -213,7 +213,7 @@ class EpisodeGrid extends StatelessWidget {
child: Text( child: Text(
episodes[index].title, episodes[index].title,
style: TextStyle( style: TextStyle(
fontSize: _width / 32, // fontSize: _width / 32,
), ),
maxLines: 4, maxLines: 4,
overflow: TextOverflow.fade, overflow: TextOverflow.fade,

View File

@ -1 +1,3 @@
Forked from https://github.com/witochandra/webfeed Forked from https://github.com/witochandra/webfeed
Copyright https://github.com/witochandra ALL RIGHT RESERVED
Mit License https://github.com/witochandra/webfeed/blob/master/LICENSE

View File

@ -11,7 +11,7 @@ description: An easy-use podacasts player.
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.1.5 version: 0.1.6
environment: environment:
sdk: ">=2.6.0 <3.0.0" sdk: ">=2.6.0 <3.0.0"
@ -56,7 +56,6 @@ dev_dependencies:
just_audio: just_audio:
git: git:
url: https://github.com/stonega/just_audio.git url: https://github.com/stonega/just_audio.git
rxdart: ^0.23.1
line_icons: line_icons:
git: git:
url: https://github.com/galonsos/line_icons.git url: https://github.com/galonsos/line_icons.git