Minor change
This commit is contained in:
parent
93ed9d3513
commit
6086db0f8c
|
@ -173,8 +173,8 @@ For help getting started with Flutter, view our
|
||||||
[English]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=English&query=%24.languages%5B3%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
[English]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=English&query=%24.languages%5B3%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
||||||
[Chinese Simplified]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=Chinese%20Simplified&query=%24.languages%5B2%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
[Chinese Simplified]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=Chinese%20Simplified&query=%24.languages%5B2%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
||||||
[French]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=French(ppp)&query=%24.languages%5B5%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
[French]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=French(ppp)&query=%24.languages%5B5%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
||||||
[Spanish]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=Spanish(Joel)&query=%24.languages%5B8%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
[Spanish]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=Spanish(Joel)&query=%24.languages%5B7%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
||||||
[Portuguese]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=portuguese(Bruno)&query=%24.languages%5B10%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
[Portuguese]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=%2323CCC6&label=portuguese(Bruno)&query=%24.languages%5B9%5D.reviewedProgress&url=https%3A%2F%2Fapi.localizely.com%2Fv1%2Fprojects%2Fbde4e9bd-4cb2-449b-9de2-18f231ddb47d%2Fstatus&suffix=%
|
||||||
[localizely - website]: https://localizely.com/
|
[localizely - website]: https://localizely.com/
|
||||||
[google play - icon]: https://img.shields.io/badge/google-playStore-%2323CCC6
|
[google play - icon]: https://img.shields.io/badge/google-playStore-%2323CCC6
|
||||||
[google play]: https://play.google.com/store/apps/details?id=com.stonegate.tsacdop
|
[google play]: https://play.google.com/store/apps/details?id=com.stonegate.tsacdop
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'package:line_icons/line_icons.dart';
|
||||||
import '../util/custom_widget.dart';
|
import '../util/custom_widget.dart';
|
||||||
import '../util/extension_helper.dart';
|
import '../util/extension_helper.dart';
|
||||||
|
|
||||||
const String version = '0.4.17';
|
const String version = '0.4.18';
|
||||||
|
|
||||||
class AboutApp extends StatelessWidget {
|
class AboutApp extends StatelessWidget {
|
||||||
Widget _listItem(
|
Widget _listItem(
|
||||||
|
|
|
@ -526,12 +526,13 @@ class _PlaylistButton extends StatefulWidget {
|
||||||
class __PlaylistButtonState extends State<_PlaylistButton> {
|
class __PlaylistButtonState extends State<_PlaylistButton> {
|
||||||
bool _loadPlay;
|
bool _loadPlay;
|
||||||
|
|
||||||
_getPlaylist() async {
|
Future<void> _getPlaylist() async {
|
||||||
await Provider.of<AudioPlayerNotifier>(context, listen: false)
|
await context.read<AudioPlayerNotifier>().loadPlaylist();
|
||||||
.loadPlaylist();
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_loadPlay = true;
|
_loadPlay = true;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -545,157 +546,158 @@ class __PlaylistButtonState extends State<_PlaylistButton> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var audio = context.watch<AudioPlayerNotifier>();
|
var audio = context.watch<AudioPlayerNotifier>();
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
return MyPopupMenuButton<int>(
|
return Material(
|
||||||
shape: RoundedRectangleBorder(
|
child: MyPopupMenuButton<int>(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10))),
|
shape: RoundedRectangleBorder(
|
||||||
elevation: 1,
|
borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||||
icon: Icon(Icons.playlist_play),
|
elevation: 1,
|
||||||
tooltip: s.menu,
|
icon: Icon(Icons.playlist_play),
|
||||||
itemBuilder: (context) => [
|
tooltip: s.menu,
|
||||||
MyPopupMenuItem(
|
itemBuilder: (context) => [
|
||||||
height: 50,
|
MyPopupMenuItem(
|
||||||
value: 1,
|
height: 50,
|
||||||
child: Container(
|
value: 1,
|
||||||
decoration: BoxDecoration(
|
child: Container(
|
||||||
// color: Theme.of(context).accentColor,
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
topLeft: Radius.circular(10.0),
|
topLeft: Radius.circular(10.0),
|
||||||
topRight: Radius.circular(10.0)),
|
topRight: Radius.circular(10.0)),
|
||||||
),
|
),
|
||||||
child: Selector<AudioPlayerNotifier, Tuple3<bool, Playlist, int>>(
|
child: Selector<AudioPlayerNotifier, Tuple3<bool, Playlist, int>>(
|
||||||
selector: (_, audio) =>
|
selector: (_, audio) =>
|
||||||
Tuple3(audio.playerRunning, audio.queue, audio.lastPositin),
|
Tuple3(audio.playerRunning, audio.queue, audio.lastPositin),
|
||||||
builder: (_, data, __) => !_loadPlay
|
builder: (_, data, __) => !_loadPlay
|
||||||
? Container(
|
? SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
)
|
)
|
||||||
: data.item1 || data.item2.playlist.length == 0
|
: data.item1 || data.item2.playlist.length == 0
|
||||||
? Container(
|
? SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
)
|
)
|
||||||
: InkWell(
|
: InkWell(
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
topLeft: Radius.circular(10.0),
|
topLeft: Radius.circular(10.0),
|
||||||
topRight: Radius.circular(10.0)),
|
topRight: Radius.circular(10.0)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
audio.playlistLoad();
|
audio.playlistLoad();
|
||||||
Navigator.pop<int>(context);
|
Navigator.pop<int>(context);
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 5),
|
padding: EdgeInsets.symmetric(vertical: 5),
|
||||||
),
|
),
|
||||||
Stack(
|
Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: <Widget>[
|
|
||||||
CircleAvatar(
|
|
||||||
radius: 20,
|
|
||||||
backgroundImage: data
|
|
||||||
.item2.playlist.first.avatarImage),
|
|
||||||
Container(
|
|
||||||
height: 40.0,
|
|
||||||
width: 40.0,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
color: Colors.black12),
|
|
||||||
child: Icon(
|
|
||||||
Icons.play_arrow,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 2),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
height: 70,
|
|
||||||
width: 140,
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
CircleAvatar(
|
||||||
(data.item3 ~/ 1000).toTime,
|
radius: 20,
|
||||||
// style:
|
backgroundImage: data
|
||||||
// TextStyle(color: Colors.white)
|
.item2.playlist.first.avatarImage),
|
||||||
),
|
Container(
|
||||||
Text(
|
height: 40.0,
|
||||||
data.item2.playlist.first.title,
|
width: 40.0,
|
||||||
maxLines: 2,
|
decoration: BoxDecoration(
|
||||||
textAlign: TextAlign.center,
|
shape: BoxShape.circle,
|
||||||
overflow: TextOverflow.fade,
|
color: Colors.black12),
|
||||||
// style: TextStyle(color: Colors.white),
|
child: Icon(
|
||||||
|
Icons.play_arrow,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
Divider(
|
padding: EdgeInsets.symmetric(vertical: 2),
|
||||||
height: 1,
|
),
|
||||||
),
|
Container(
|
||||||
],
|
height: 70,
|
||||||
|
width: 140,
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
(data.item3 ~/ 1000).toTime,
|
||||||
|
// style:
|
||||||
|
// TextStyle(color: Colors.white)
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
data.item2.playlist.first.title,
|
||||||
|
maxLines: 2,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
// style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 0,
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.only(left: 10),
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Icon(Icons.playlist_play),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 5.0),
|
|
||||||
),
|
|
||||||
Text(s.homeMenuPlaylist),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuDivider(
|
|
||||||
height: 1,
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: 2,
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.only(left: 10),
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Icon(Icons.history),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
|
||||||
),
|
|
||||||
Text(s.settingsHistory),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuDivider(
|
|
||||||
height: 1,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
onSelected: (value) {
|
|
||||||
if (value == 0) {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => PlaylistPage(
|
|
||||||
initPage: InitPage.playlist,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
} else if (value == 2) {
|
PopupMenuItem(
|
||||||
Navigator.push(
|
value: 0,
|
||||||
context,
|
child: Container(
|
||||||
MaterialPageRoute(
|
padding: EdgeInsets.only(left: 10),
|
||||||
builder: (context) => PlaylistPage(
|
child: Row(
|
||||||
initPage: InitPage.history,
|
children: <Widget>[
|
||||||
|
Icon(Icons.playlist_play),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
|
),
|
||||||
|
Text(s.homeMenuPlaylist),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}
|
PopupMenuDivider(
|
||||||
},
|
height: 1,
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: 2,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.only(left: 10),
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(Icons.history),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
|
),
|
||||||
|
Text(s.settingsHistory),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuDivider(
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
onSelected: (value) {
|
||||||
|
if (value == 0) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => PlaylistPage(
|
||||||
|
initPage: InitPage.playlist,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (value == 2) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => PlaylistPage(
|
||||||
|
initPage: InitPage.history,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -707,6 +709,19 @@ class _RecentUpdate extends StatefulWidget {
|
||||||
|
|
||||||
class _RecentUpdateState extends State<_RecentUpdate>
|
class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
with AutomaticKeepAliveClientMixin, SingleTickerProviderStateMixin {
|
with AutomaticKeepAliveClientMixin, SingleTickerProviderStateMixin {
|
||||||
|
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
|
||||||
|
GlobalKey<RefreshIndicatorState>();
|
||||||
|
|
||||||
|
Future _updateRssItem() async {
|
||||||
|
final refreshWorker = context.read<RefreshWorker>();
|
||||||
|
refreshWorker.start(_group);
|
||||||
|
await Future.delayed(Duration(seconds: 1));
|
||||||
|
Fluttertoast.showToast(
|
||||||
|
msg: 'Refresh started',
|
||||||
|
gravity: ToastGravity.BOTTOM,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<EpisodeBrief>> _getRssItem(int top, List<String> group,
|
Future<List<EpisodeBrief>> _getRssItem(int top, List<String> group,
|
||||||
{bool hideListened}) async {
|
{bool hideListened}) async {
|
||||||
var storage = KeyValueStorage(recentLayoutKey);
|
var storage = KeyValueStorage(recentLayoutKey);
|
||||||
|
@ -718,7 +733,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
}
|
}
|
||||||
var dbHelper = DBHelper();
|
var dbHelper = DBHelper();
|
||||||
List<EpisodeBrief> episodes;
|
List<EpisodeBrief> episodes;
|
||||||
if (group.first == 'All') {
|
if (group.isEmpty) {
|
||||||
episodes =
|
episodes =
|
||||||
await dbHelper.getRecentRssItem(top, hideListened: _hideListened);
|
await dbHelper.getRecentRssItem(top, hideListened: _hideListened);
|
||||||
} else {
|
} else {
|
||||||
|
@ -731,7 +746,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
Future<int> _getUpdateCounts(List<String> group) async {
|
Future<int> _getUpdateCounts(List<String> group) async {
|
||||||
var dbHelper = DBHelper();
|
var dbHelper = DBHelper();
|
||||||
var episodes = <EpisodeBrief>[];
|
var episodes = <EpisodeBrief>[];
|
||||||
if (group.first == 'All') {
|
if (group.isEmpty) {
|
||||||
episodes = await dbHelper.getRecentNewRssItem();
|
episodes = await dbHelper.getRecentNewRssItem();
|
||||||
} else {
|
} else {
|
||||||
episodes = await dbHelper.getGroupNewRssItem(group);
|
episodes = await dbHelper.getGroupNewRssItem(group);
|
||||||
|
@ -768,7 +783,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
super.initState();
|
super.initState();
|
||||||
_loadMore = false;
|
_loadMore = false;
|
||||||
_groupName = 'All';
|
_groupName = 'All';
|
||||||
_group = ['All'];
|
_group = [];
|
||||||
_scroll = false;
|
_scroll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,24 +835,28 @@ class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
child: CustomScrollView(
|
child: RefreshIndicator(
|
||||||
key: PageStorageKey<String>('update'),
|
key: _refreshIndicatorKey,
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
color: context.accentColor,
|
||||||
slivers: <Widget>[
|
onRefresh: () async {
|
||||||
SliverToBoxAdapter(
|
await _updateRssItem();
|
||||||
child: Container(
|
},
|
||||||
height: 40,
|
child: CustomScrollView(
|
||||||
color: context.primaryColor,
|
key: PageStorageKey<String>('update'),
|
||||||
child: Material(
|
physics:
|
||||||
color: Colors.transparent,
|
const AlwaysScrollableScrollPhysics(),
|
||||||
child: Row(
|
slivers: <Widget>[
|
||||||
children: <Widget>[
|
SliverToBoxAdapter(
|
||||||
Consumer<GroupList>(
|
child: Container(
|
||||||
builder: (context, groupList,
|
height: 40,
|
||||||
child) =>
|
color: context.primaryColor,
|
||||||
Material(
|
child: Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child:
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Consumer<GroupList>(
|
||||||
|
builder: (context, groupList,
|
||||||
|
child) =>
|
||||||
PopupMenuButton<String>(
|
PopupMenuButton<String>(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius:
|
borderRadius:
|
||||||
|
@ -903,7 +922,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
if (value == 'All') {
|
if (value == 'All') {
|
||||||
setState(() {
|
setState(() {
|
||||||
_groupName = 'All';
|
_groupName = 'All';
|
||||||
_group = ['All'];
|
_group = [];
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
for (var group
|
for (var group
|
||||||
|
@ -923,129 +942,128 @@ class _RecentUpdateState extends State<_RecentUpdate>
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Spacer(),
|
||||||
Spacer(),
|
FutureBuilder<int>(
|
||||||
FutureBuilder<int>(
|
future: _getUpdateCounts(
|
||||||
future:
|
_group),
|
||||||
_getUpdateCounts(_group),
|
initialData: 0,
|
||||||
initialData: 0,
|
builder:
|
||||||
builder: (context, snapshot) {
|
(context, snapshot) {
|
||||||
return snapshot.data != 0
|
return snapshot.data != 0
|
||||||
? Material(
|
? Material(
|
||||||
color: Colors
|
color: Colors
|
||||||
.transparent,
|
.transparent,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
tooltip: s
|
tooltip: s
|
||||||
.addNewEpisodeTooltip,
|
.addNewEpisodeTooltip,
|
||||||
icon: SizedBox(
|
icon: SizedBox(
|
||||||
height: 15,
|
height:
|
||||||
width: 20,
|
15,
|
||||||
child: CustomPaint(
|
width: 20,
|
||||||
painter: AddToPlaylistPainter(
|
child: CustomPaint(
|
||||||
context
|
painter: AddToPlaylistPainter(
|
||||||
.textTheme.bodyText1.color,
|
context
|
||||||
Colors
|
.textTheme.bodyText1.color,
|
||||||
.red))),
|
Colors
|
||||||
onPressed:
|
.red))),
|
||||||
() async {
|
onPressed:
|
||||||
await audio
|
() async {
|
||||||
.addNewEpisode(
|
await audio
|
||||||
_group);
|
.addNewEpisode(
|
||||||
if (mounted) {
|
_group);
|
||||||
setState(
|
if (mounted) {
|
||||||
() {});
|
setState(
|
||||||
}
|
() {});
|
||||||
Fluttertoast
|
}
|
||||||
.showToast(
|
Fluttertoast
|
||||||
msg: _groupName ==
|
.showToast(
|
||||||
'All'
|
msg: _groupName ==
|
||||||
? s.addNewEpisodeAll(snapshot
|
'All'
|
||||||
.data)
|
? s.addNewEpisodeAll(snapshot
|
||||||
: s.addEpisodeGroup(
|
.data)
|
||||||
_groupName,
|
: s.addEpisodeGroup(
|
||||||
snapshot.data),
|
_groupName,
|
||||||
gravity:
|
snapshot.data),
|
||||||
ToastGravity
|
gravity:
|
||||||
.BOTTOM,
|
ToastGravity
|
||||||
);
|
.BOTTOM,
|
||||||
}),
|
);
|
||||||
)
|
}),
|
||||||
: Material(
|
)
|
||||||
color: Colors
|
: Material(
|
||||||
.transparent,
|
color: Colors
|
||||||
child: IconButton(
|
.transparent,
|
||||||
tooltip: s
|
child: IconButton(
|
||||||
.addNewEpisodeTooltip,
|
tooltip: s
|
||||||
icon: SizedBox(
|
.addNewEpisodeTooltip,
|
||||||
height: 15,
|
icon: SizedBox(
|
||||||
width: 20,
|
height: 15,
|
||||||
child:
|
width: 20,
|
||||||
CustomPaint(
|
child: CustomPaint(
|
||||||
painter:
|
painter: AddToPlaylistPainter(
|
||||||
AddToPlaylistPainter(
|
context
|
||||||
context
|
.textColor,
|
||||||
.textColor,
|
context
|
||||||
context
|
.textColor,
|
||||||
.textColor,
|
))),
|
||||||
))),
|
onPressed: () {}),
|
||||||
onPressed:
|
);
|
||||||
() {}),
|
}),
|
||||||
);
|
Material(
|
||||||
}),
|
color: Colors.transparent,
|
||||||
Material(
|
child: IconButton(
|
||||||
color: Colors.transparent,
|
tooltip:
|
||||||
child: IconButton(
|
s.hideListenedSetting,
|
||||||
tooltip:
|
icon: SizedBox(
|
||||||
s.hideListenedSetting,
|
width: 30,
|
||||||
icon: SizedBox(
|
height: 15,
|
||||||
width: 30,
|
child: HideListened(
|
||||||
height: 15,
|
hideListened:
|
||||||
child: HideListened(
|
_hideListened ??
|
||||||
hideListened:
|
false,
|
||||||
_hideListened ??
|
),
|
||||||
false,
|
|
||||||
),
|
),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() =>
|
||||||
|
_hideListened =
|
||||||
|
!_hideListened);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
onPressed: () {
|
|
||||||
setState(() =>
|
|
||||||
_hideListened =
|
|
||||||
!_hideListened);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
Material(
|
||||||
Material(
|
color: Colors.transparent,
|
||||||
color: Colors.transparent,
|
child: LayoutButton(
|
||||||
child: LayoutButton(
|
layout: _layout,
|
||||||
layout: _layout,
|
onPressed: (layout) =>
|
||||||
onPressed: (layout) =>
|
setState(() {
|
||||||
setState(() {
|
_layout = layout;
|
||||||
_layout = layout;
|
}),
|
||||||
}),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
)),
|
||||||
)),
|
|
||||||
),
|
|
||||||
EpisodeGrid(
|
|
||||||
episodes: snapshot.data,
|
|
||||||
layout: _layout,
|
|
||||||
initNum: _scroll ? 0 : 12,
|
|
||||||
),
|
|
||||||
SliverList(
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(context, index) {
|
|
||||||
return _loadMore
|
|
||||||
? Container(
|
|
||||||
height: 2,
|
|
||||||
child:
|
|
||||||
LinearProgressIndicator())
|
|
||||||
: Center();
|
|
||||||
},
|
|
||||||
childCount: 1,
|
|
||||||
),
|
),
|
||||||
),
|
EpisodeGrid(
|
||||||
]))
|
episodes: snapshot.data,
|
||||||
|
layout: _layout,
|
||||||
|
initNum: _scroll ? 0 : 12,
|
||||||
|
),
|
||||||
|
SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
(context, index) {
|
||||||
|
return _loadMore
|
||||||
|
? Container(
|
||||||
|
height: 2,
|
||||||
|
child:
|
||||||
|
LinearProgressIndicator())
|
||||||
|
: Center();
|
||||||
|
},
|
||||||
|
childCount: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
))
|
||||||
: Center();
|
: Center();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -361,11 +361,8 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
color: context.scaffoldBackgroundColor,
|
color: context.scaffoldBackgroundColor,
|
||||||
child: TabBar(
|
child: TabBar(
|
||||||
labelPadding: EdgeInsets.only(
|
labelPadding:
|
||||||
top: 5.0,
|
EdgeInsets.fromLTRB(6.0, 5.0, 6.0, 10.0),
|
||||||
bottom: 10.0,
|
|
||||||
left: 6.0,
|
|
||||||
right: 6.0),
|
|
||||||
indicator: CircleTabIndicator(
|
indicator: CircleTabIndicator(
|
||||||
color: context.accentColor, radius: 3),
|
color: context.accentColor, radius: 3),
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
|
@ -439,17 +436,30 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
|
||||||
.podcasts
|
.podcasts
|
||||||
.map<Widget>((podcastLocal) {
|
.map<Widget>((podcastLocal) {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).brightness ==
|
color: context.brightness ==
|
||||||
Brightness.light
|
Brightness.light
|
||||||
? Theme.of(context).primaryColor
|
? context.primaryColor
|
||||||
: Colors.black12),
|
: Colors.black12),
|
||||||
margin: EdgeInsets.symmetric(horizontal: 5.0),
|
margin:
|
||||||
key: ObjectKey(podcastLocal.title),
|
EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
child: PodcastPreview(
|
key: ObjectKey(podcastLocal.title),
|
||||||
podcastLocal: podcastLocal,
|
child: Material(
|
||||||
),
|
color: Colors.transparent,
|
||||||
);
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
SlideLeftRoute(
|
||||||
|
page: PodcastDetail(
|
||||||
|
podcastLocal: podcastLocal,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: PodcastPreview(
|
||||||
|
podcastLocal: podcastLocal,
|
||||||
|
),
|
||||||
|
)));
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -513,27 +523,11 @@ class PodcastPreview extends StatelessWidget {
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: Material(
|
child: Padding(
|
||||||
color: Colors.transparent,
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
child: Selector<AudioPlayerNotifier, bool>(
|
child: Icon(Icons.arrow_forward),
|
||||||
selector: (_, audio) => audio.playerRunning,
|
)),
|
||||||
builder: (_, playerRunning, __) => IconButton(
|
|
||||||
icon: Icon(Icons.arrow_forward),
|
|
||||||
tooltip: context.s.homeGroupsSeeAll,
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
SlideLeftRoute(
|
|
||||||
page: PodcastDetail(
|
|
||||||
podcastLocal: podcastLocal,
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -6,7 +6,6 @@ import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
import 'package:line_icons/line_icons.dart';
|
import 'package:line_icons/line_icons.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
@ -26,7 +25,6 @@ class PopupMenu extends StatefulWidget {
|
||||||
class _PopupMenuState extends State<PopupMenu> {
|
class _PopupMenuState extends State<PopupMenu> {
|
||||||
Future<String> _getRefreshDate(BuildContext context) async {
|
Future<String> _getRefreshDate(BuildContext context) async {
|
||||||
int refreshDate;
|
int refreshDate;
|
||||||
final s = context.s;
|
|
||||||
var refreshstorage = KeyValueStorage('refreshdate');
|
var refreshstorage = KeyValueStorage('refreshdate');
|
||||||
var i = await refreshstorage.getInt();
|
var i = await refreshstorage.getInt();
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
|
@ -36,20 +34,21 @@ class _PopupMenuState extends State<PopupMenu> {
|
||||||
} else {
|
} else {
|
||||||
refreshDate = i;
|
refreshDate = i;
|
||||||
}
|
}
|
||||||
var date = DateTime.fromMillisecondsSinceEpoch(refreshDate);
|
return refreshDate.toDate(context);
|
||||||
var difference = DateTime.now().difference(date);
|
// var date = DateTime.fromMillisecondsSinceEpoch(refreshDate);
|
||||||
if (difference.inSeconds < 60) {
|
// var difference = DateTime.now().difference(date);
|
||||||
return s.secondsAgo(difference.inSeconds);
|
// if (difference.inSeconds < 60) {
|
||||||
} else if (difference.inMinutes < 60) {
|
// return s.secondsAgo(difference.inSeconds);
|
||||||
return s.minsAgo(difference.inMinutes);
|
// } else if (difference.inMinutes < 60) {
|
||||||
} else if (difference.inHours < 24) {
|
// return s.minsAgo(difference.inMinutes);
|
||||||
return s.hoursAgo(difference.inHours);
|
// } else if (difference.inHours < 24) {
|
||||||
} else if (difference.inDays < 7) {
|
// return s.hoursAgo(difference.inHours);
|
||||||
return s.daysAgo(difference.inDays);
|
// } else if (difference.inDays < 7) {
|
||||||
} else {
|
// return s.daysAgo(difference.inDays);
|
||||||
return DateFormat.yMMMd()
|
// } else {
|
||||||
.format(DateTime.fromMillisecondsSinceEpoch(refreshDate));
|
// return DateFormat.yMMMd()
|
||||||
}
|
// .format(DateTime.fromMillisecondsSinceEpoch(refreshDate));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void _saveOmpl(String path) async {
|
void _saveOmpl(String path) async {
|
||||||
|
@ -198,8 +197,7 @@ class _PopupMenuState extends State<PopupMenu> {
|
||||||
} else if (value == 2) {
|
} else if (value == 2) {
|
||||||
_getFilePath();
|
_getFilePath();
|
||||||
} else if (value == 1) {
|
} else if (value == 1) {
|
||||||
//_refreshAll();
|
refreshWorker.start([]);
|
||||||
refreshWorker.start();
|
|
||||||
} else if (value == 3) {
|
} else if (value == 3) {
|
||||||
// setting.theme != 2 ? setting.setTheme(2) : setting.setTheme(1);
|
// setting.theme != 2 ? setting.setTheme(2) : setting.setTheme(1);
|
||||||
} else if (value == 4) {
|
} else if (value == 4) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ class _PlaylistPageState extends State<PlaylistPage> {
|
||||||
systemNavigationBarColor: Theme.of(context).primaryColor,
|
systemNavigationBarColor: Theme.of(context).primaryColor,
|
||||||
),
|
),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
backgroundColor: context.primaryColor,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
backgroundColor: context.accentColor.withAlpha(70),
|
backgroundColor: context.accentColor.withAlpha(70),
|
||||||
|
@ -264,9 +264,12 @@ class _PlaylistPageState extends State<PlaylistPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: AnimatedSwitcher(
|
child: Container(
|
||||||
duration: Duration(milliseconds: 300),
|
color: context.primaryColor,
|
||||||
child: _loadList)),
|
child: AnimatedSwitcher(
|
||||||
|
duration: Duration(milliseconds: 300),
|
||||||
|
child: _loadList),
|
||||||
|
)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -586,171 +589,192 @@ class __HistoryListState extends State<_HistoryList> {
|
||||||
final date = snapshot
|
final date = snapshot
|
||||||
.data[index].playdate.millisecondsSinceEpoch;
|
.data[index].playdate.millisecondsSinceEpoch;
|
||||||
final episode = snapshot.data[index].episode;
|
final episode = snapshot.data[index].episode;
|
||||||
final c = episode.backgroudColor(context);
|
final c = episode?.backgroudColor(context);
|
||||||
return SizedBox(
|
return episode == null
|
||||||
height: 90.0,
|
? Center()
|
||||||
child: Column(
|
: SizedBox(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
height: 90.0,
|
||||||
children: [
|
child: Column(
|
||||||
Expanded(
|
mainAxisAlignment:
|
||||||
child: Center(
|
MainAxisAlignment.spaceAround,
|
||||||
child: ListTile(
|
children: [
|
||||||
contentPadding:
|
Expanded(
|
||||||
EdgeInsets.fromLTRB(24, 8, 20, 8),
|
child: Center(
|
||||||
onTap: () => audio.episodeLoad(episode),
|
child: ListTile(
|
||||||
leading: CircleAvatar(
|
contentPadding: EdgeInsets.fromLTRB(
|
||||||
backgroundColor: c.withOpacity(0.5),
|
24, 8, 20, 8),
|
||||||
backgroundImage: episode.avatarImage),
|
onTap: () =>
|
||||||
title: Padding(
|
audio.episodeLoad(episode),
|
||||||
padding:
|
leading: CircleAvatar(
|
||||||
EdgeInsets.symmetric(vertical: 5.0),
|
backgroundColor:
|
||||||
child: Text(
|
c?.withOpacity(0.5),
|
||||||
snapshot.data[index].title,
|
backgroundImage:
|
||||||
maxLines: 1,
|
episode.avatarImage),
|
||||||
overflow: TextOverflow.ellipsis,
|
title: Padding(
|
||||||
),
|
padding: EdgeInsets.symmetric(
|
||||||
),
|
vertical: 5.0),
|
||||||
subtitle: Container(
|
child: Text(
|
||||||
height: 35,
|
snapshot.data[index].title,
|
||||||
child: Row(
|
maxLines: 1,
|
||||||
mainAxisAlignment:
|
overflow: TextOverflow.ellipsis,
|
||||||
MainAxisAlignment.start,
|
),
|
||||||
crossAxisAlignment:
|
),
|
||||||
CrossAxisAlignment.center,
|
subtitle: Container(
|
||||||
children: <Widget>[
|
height: 35,
|
||||||
if (seekValue < 0.9)
|
child: Row(
|
||||||
Padding(
|
mainAxisAlignment:
|
||||||
padding:
|
MainAxisAlignment.start,
|
||||||
const EdgeInsets.symmetric(
|
crossAxisAlignment:
|
||||||
vertical: 5.0),
|
CrossAxisAlignment.center,
|
||||||
child: Material(
|
children: <Widget>[
|
||||||
color: Colors.transparent,
|
if (seekValue < 0.9)
|
||||||
child: InkWell(
|
Padding(
|
||||||
onTap: () async {
|
padding: const EdgeInsets
|
||||||
audio.episodeLoad(episode,
|
|
||||||
startPosition:
|
|
||||||
(seconds * 1000)
|
|
||||||
.toInt());
|
|
||||||
},
|
|
||||||
child: Stack(children: [
|
|
||||||
ShaderMask(
|
|
||||||
shaderCallback:
|
|
||||||
(bounds) {
|
|
||||||
return LinearGradient(
|
|
||||||
begin: Alignment
|
|
||||||
.centerLeft,
|
|
||||||
colors: <Color>[
|
|
||||||
Colors.cyan[600]
|
|
||||||
.withOpacity(
|
|
||||||
0.8),
|
|
||||||
Colors.white70
|
|
||||||
],
|
|
||||||
stops: [
|
|
||||||
seekValue,
|
|
||||||
seekValue
|
|
||||||
],
|
|
||||||
tileMode:
|
|
||||||
TileMode.mirror,
|
|
||||||
).createShader(
|
|
||||||
bounds);
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 25,
|
|
||||||
alignment:
|
|
||||||
Alignment.center,
|
|
||||||
padding: EdgeInsets
|
|
||||||
.symmetric(
|
.symmetric(
|
||||||
horizontal:
|
vertical: 5.0),
|
||||||
20),
|
child: Material(
|
||||||
decoration:
|
color:
|
||||||
BoxDecoration(
|
Colors.transparent,
|
||||||
borderRadius:
|
child: InkWell(
|
||||||
BorderRadius.all(
|
onTap: () async {
|
||||||
Radius.circular(
|
audio.episodeLoad(
|
||||||
20.0)),
|
episode,
|
||||||
color: context
|
startPosition:
|
||||||
.accentColor,
|
(seconds *
|
||||||
),
|
1000)
|
||||||
child: Text(
|
.toInt());
|
||||||
seconds.toTime,
|
},
|
||||||
style: TextStyle(
|
child: Stack(
|
||||||
color: Colors
|
children: [
|
||||||
.white),
|
ShaderMask(
|
||||||
),
|
shaderCallback:
|
||||||
|
(bounds) {
|
||||||
|
return LinearGradient(
|
||||||
|
begin: Alignment
|
||||||
|
.centerLeft,
|
||||||
|
colors: <
|
||||||
|
Color>[
|
||||||
|
Colors
|
||||||
|
.cyan[600]
|
||||||
|
.withOpacity(0.8),
|
||||||
|
Colors
|
||||||
|
.white70
|
||||||
|
],
|
||||||
|
stops: [
|
||||||
|
seekValue,
|
||||||
|
seekValue
|
||||||
|
],
|
||||||
|
tileMode:
|
||||||
|
TileMode
|
||||||
|
.mirror,
|
||||||
|
).createShader(
|
||||||
|
bounds);
|
||||||
|
},
|
||||||
|
child:
|
||||||
|
Container(
|
||||||
|
height: 25,
|
||||||
|
alignment:
|
||||||
|
Alignment
|
||||||
|
.center,
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal:
|
||||||
|
20),
|
||||||
|
decoration:
|
||||||
|
BoxDecoration(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(
|
||||||
|
Radius.circular(20.0)),
|
||||||
|
color: context
|
||||||
|
.accentColor,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
seconds
|
||||||
|
.toTime,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]),
|
),
|
||||||
|
SizedBox(
|
||||||
|
child: Selector<
|
||||||
|
AudioPlayerNotifier,
|
||||||
|
Tuple2<
|
||||||
|
List<EpisodeBrief>,
|
||||||
|
bool>>(
|
||||||
|
selector: (_, audio) =>
|
||||||
|
Tuple2(
|
||||||
|
audio.queue
|
||||||
|
.playlist,
|
||||||
|
audio
|
||||||
|
.queueUpdate),
|
||||||
|
builder: (_, data, __) {
|
||||||
|
return data.item1
|
||||||
|
.contains(
|
||||||
|
episode)
|
||||||
|
? IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons
|
||||||
|
.playlist_add_check,
|
||||||
|
color: context
|
||||||
|
.accentColor),
|
||||||
|
onPressed:
|
||||||
|
() async {
|
||||||
|
audio.delFromPlaylist(
|
||||||
|
episode);
|
||||||
|
Fluttertoast
|
||||||
|
.showToast(
|
||||||
|
msg: s
|
||||||
|
.toastRemovePlaylist,
|
||||||
|
gravity:
|
||||||
|
ToastGravity
|
||||||
|
.BOTTOM,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons
|
||||||
|
.playlist_add,
|
||||||
|
color: Colors
|
||||||
|
.grey[
|
||||||
|
700]),
|
||||||
|
onPressed:
|
||||||
|
() async {
|
||||||
|
audio.addToPlaylist(
|
||||||
|
episode);
|
||||||
|
Fluttertoast
|
||||||
|
.showToast(
|
||||||
|
msg: s
|
||||||
|
.toastAddPlaylist,
|
||||||
|
gravity:
|
||||||
|
ToastGravity
|
||||||
|
.BOTTOM,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
Spacer(),
|
||||||
),
|
Text(
|
||||||
SizedBox(
|
date.toDate(context),
|
||||||
child: Selector<
|
style: TextStyle(
|
||||||
AudioPlayerNotifier,
|
fontSize: 15,
|
||||||
Tuple2<List<EpisodeBrief>,
|
),
|
||||||
bool>>(
|
),
|
||||||
selector: (_, audio) => Tuple2(
|
],
|
||||||
audio.queue.playlist,
|
|
||||||
audio.queueUpdate),
|
|
||||||
builder: (_, data, __) {
|
|
||||||
return data.item1
|
|
||||||
.contains(episode)
|
|
||||||
? IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
Icons
|
|
||||||
.playlist_add_check,
|
|
||||||
color: context
|
|
||||||
.accentColor),
|
|
||||||
onPressed: () async {
|
|
||||||
audio
|
|
||||||
.delFromPlaylist(
|
|
||||||
episode);
|
|
||||||
Fluttertoast
|
|
||||||
.showToast(
|
|
||||||
msg: s
|
|
||||||
.toastRemovePlaylist,
|
|
||||||
gravity:
|
|
||||||
ToastGravity
|
|
||||||
.BOTTOM,
|
|
||||||
);
|
|
||||||
})
|
|
||||||
: IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
Icons
|
|
||||||
.playlist_add,
|
|
||||||
color: Colors
|
|
||||||
.grey[700]),
|
|
||||||
onPressed: () async {
|
|
||||||
audio.addToPlaylist(
|
|
||||||
episode);
|
|
||||||
Fluttertoast
|
|
||||||
.showToast(
|
|
||||||
msg: s
|
|
||||||
.toastAddPlaylist,
|
|
||||||
gravity:
|
|
||||||
ToastGravity
|
|
||||||
.BOTTOM,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Spacer(),
|
),
|
||||||
Text(
|
|
||||||
date.toDate(context),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 15,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Divider(height: 1)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
Divider(height: 1)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -38,7 +38,8 @@ class DBHelper {
|
||||||
description TEXT, add_date INTEGER, imagePath TEXT, provider TEXT, link TEXT,
|
description TEXT, add_date INTEGER, imagePath TEXT, provider TEXT, link TEXT,
|
||||||
background_image TEXT DEFAULT '', hosts TEXT DEFAULT '',update_count INTEGER DEFAULT 0,
|
background_image TEXT DEFAULT '', hosts TEXT DEFAULT '',update_count INTEGER DEFAULT 0,
|
||||||
episode_count INTEGER DEFAULT 0, skip_seconds INTEGER DEFAULT 0,
|
episode_count INTEGER DEFAULT 0, skip_seconds INTEGER DEFAULT 0,
|
||||||
auto_download INTEGER DEFAULT 0, skip_seconds_end INTEGER DEFAULT 0)""");
|
auto_download INTEGER DEFAULT 0, skip_seconds_end INTEGER DEFAULT 0,
|
||||||
|
never_update INTEGER DEFAULT 0)""");
|
||||||
await db
|
await db
|
||||||
.execute("""CREATE TABLE Episodes(id INTEGER PRIMARY KEY,title TEXT,
|
.execute("""CREATE TABLE Episodes(id INTEGER PRIMARY KEY,title TEXT,
|
||||||
enclosure_url TEXT UNIQUE, enclosure_length INTEGER, pubDate TEXT,
|
enclosure_url TEXT UNIQUE, enclosure_length INTEGER, pubDate TEXT,
|
||||||
|
@ -62,27 +63,41 @@ class DBHelper {
|
||||||
"ALTER TABLE PodcastLocal ADD auto_download INTEGER DEFAULT 0");
|
"ALTER TABLE PodcastLocal ADD auto_download INTEGER DEFAULT 0");
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"ALTER TABLE PodcastLocal ADD skip_seconds_end INTEGER DEFAULT 0 ");
|
"ALTER TABLE PodcastLocal ADD skip_seconds_end INTEGER DEFAULT 0 ");
|
||||||
|
await db.execute(
|
||||||
|
"ALTER TABLE PodcastLocal ADD never_update INTEGER DEFAULT 0 ");
|
||||||
} else if (oldVersion == 2) {
|
} else if (oldVersion == 2) {
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"ALTER TABLE PodcastLocal ADD auto_download INTEGER DEFAULT 0");
|
"ALTER TABLE PodcastLocal ADD auto_download INTEGER DEFAULT 0");
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"ALTER TABLE PodcastLocal ADD skip_seconds_end INTEGER DEFAULT 0 ");
|
"ALTER TABLE PodcastLocal ADD skip_seconds_end INTEGER DEFAULT 0 ");
|
||||||
|
await db.execute(
|
||||||
|
"ALTER TABLE PodcastLocal ADD never_update INTEGER DEFAULT 0 ");
|
||||||
} else if (oldVersion == 3) {
|
} else if (oldVersion == 3) {
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"ALTER TABLE PodcastLocal ADD skip_seconds_end INTEGER DEFAULT 0 ");
|
"ALTER TABLE PodcastLocal ADD skip_seconds_end INTEGER DEFAULT 0");
|
||||||
|
await db.execute(
|
||||||
|
"ALTER TABLE PodcastLocal ADD never_update INTEGER DEFAULT 0 ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<PodcastLocal>> getPodcastLocal(List<String> podcasts) async {
|
Future<List<PodcastLocal>> getPodcastLocal(List<String> podcasts,
|
||||||
|
{bool updateOnly = false}) async {
|
||||||
var dbClient = await database;
|
var dbClient = await database;
|
||||||
var podcastLocal = <PodcastLocal>[];
|
var podcastLocal = <PodcastLocal>[];
|
||||||
|
|
||||||
for (var s in podcasts) {
|
for (var s in podcasts) {
|
||||||
List<Map> list;
|
List<Map> list;
|
||||||
list = await dbClient.rawQuery(
|
if (updateOnly) {
|
||||||
"""SELECT id, title, imageUrl, rssUrl, primaryColor, author, imagePath , provider,
|
list = await dbClient.rawQuery(
|
||||||
|
"""SELECT id, title, imageUrl, rssUrl, primaryColor, author, imagePath , provider,
|
||||||
|
link ,update_count, episode_count FROM PodcastLocal WHERE id = ? AND
|
||||||
|
never_update = 0""", [s]);
|
||||||
|
} else {
|
||||||
|
list = await dbClient.rawQuery(
|
||||||
|
"""SELECT id, title, imageUrl, rssUrl, primaryColor, author, imagePath , provider,
|
||||||
link ,update_count, episode_count FROM PodcastLocal WHERE id = ?""",
|
link ,update_count, episode_count FROM PodcastLocal WHERE id = ?""",
|
||||||
[s]);
|
[s]);
|
||||||
|
}
|
||||||
if (list.length > 0) {
|
if (list.length > 0) {
|
||||||
podcastLocal.add(PodcastLocal(
|
podcastLocal.add(PodcastLocal(
|
||||||
list.first['title'],
|
list.first['title'],
|
||||||
|
@ -101,10 +116,21 @@ class DBHelper {
|
||||||
return podcastLocal;
|
return podcastLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<PodcastLocal>> getPodcastLocalAll() async {
|
Future<List<PodcastLocal>> getPodcastLocalAll(
|
||||||
|
{bool updateOnly = false}) async {
|
||||||
var dbClient = await database;
|
var dbClient = await database;
|
||||||
List<Map> list = await dbClient.rawQuery(
|
|
||||||
'SELECT id, title, imageUrl, rssUrl, primaryColor, author, imagePath, provider, link FROM PodcastLocal ORDER BY add_date DESC');
|
List<Map> list;
|
||||||
|
if (updateOnly) {
|
||||||
|
list = await dbClient.rawQuery(
|
||||||
|
"""SELECT id, title, imageUrl, rssUrl, primaryColor, author, imagePath,
|
||||||
|
provider, link FROM PodcastLocal WHERE never_update = 0 ORDER BY
|
||||||
|
add_date DESC""");
|
||||||
|
} else {
|
||||||
|
list = await dbClient.rawQuery(
|
||||||
|
"""SELECT id, title, imageUrl, rssUrl, primaryColor, author, imagePath,
|
||||||
|
provider, link FROM PodcastLocal ORDER BY add_date DESC""");
|
||||||
|
}
|
||||||
|
|
||||||
var podcastLocal = <PodcastLocal>[];
|
var podcastLocal = <PodcastLocal>[];
|
||||||
|
|
||||||
|
@ -131,6 +157,21 @@ class DBHelper {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> getNeverUpdate(String id) async {
|
||||||
|
var dbClient = await database;
|
||||||
|
List<Map> list = await dbClient
|
||||||
|
.rawQuery('SELECT never_update FROM PodcastLocal WHERE id = ?', [id]);
|
||||||
|
if (list.isNotEmpty) return list.first['never_update'] == 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> saveNeverUpdate(String id, {bool boo}) async {
|
||||||
|
var dbClient = await database;
|
||||||
|
return await dbClient.rawUpdate(
|
||||||
|
"UPDATE PodcastLocal SET never_update = ? WHERE id = ?",
|
||||||
|
[boo ? 1 : 0, id]);
|
||||||
|
}
|
||||||
|
|
||||||
Future<int> getPodcastUpdateCounts(String id) async {
|
Future<int> getPodcastUpdateCounts(String id) async {
|
||||||
var dbClient = await database;
|
var dbClient = await database;
|
||||||
List<Map> list = await dbClient.rawQuery(
|
List<Map> list = await dbClient.rawQuery(
|
||||||
|
|
|
@ -58,6 +58,11 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
if (mounted) setState(() {});
|
if (mounted) setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _setNeverUpdate(bool boo) async {
|
||||||
|
await _dbHelper.saveNeverUpdate(widget.podcastLocal.id, boo: boo);
|
||||||
|
if (mounted) setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _saveSkipSecondsStart(int seconds) async {
|
Future<void> _saveSkipSecondsStart(int seconds) async {
|
||||||
await _dbHelper.saveSkipSecondsStart(widget.podcastLocal.id, seconds);
|
await _dbHelper.saveSkipSecondsStart(widget.podcastLocal.id, seconds);
|
||||||
}
|
}
|
||||||
|
@ -70,6 +75,10 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
return await _dbHelper.getAutoDownload(id);
|
return await _dbHelper.getAutoDownload(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> _getNeverUpdate(String id) async {
|
||||||
|
return await _dbHelper.getNeverUpdate(id);
|
||||||
|
}
|
||||||
|
|
||||||
Future<int> _getSkipSecondStart(String id) async {
|
Future<int> _getSkipSecondStart(String id) async {
|
||||||
return await _dbHelper.getSkipSecondsStart(id);
|
return await _dbHelper.getSkipSecondsStart(id);
|
||||||
}
|
}
|
||||||
|
@ -217,6 +226,21 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
FutureBuilder<bool>(
|
||||||
|
future: _getNeverUpdate(widget.podcastLocal.id),
|
||||||
|
initialData: false,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return ListTile(
|
||||||
|
onTap: () => _setNeverUpdate(!snapshot.data),
|
||||||
|
leading: Icon(Icons.lock),
|
||||||
|
title: Text('Never update'),
|
||||||
|
trailing: Transform.scale(
|
||||||
|
scale: 0.9,
|
||||||
|
child:
|
||||||
|
Switch(value: snapshot.data, onChanged: _setNeverUpdate),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
FutureBuilder<int>(
|
FutureBuilder<int>(
|
||||||
future: _getSkipSecondStart(widget.podcastLocal.id),
|
future: _getSkipSecondStart(widget.podcastLocal.id),
|
||||||
initialData: 0,
|
initialData: 0,
|
||||||
|
@ -246,42 +270,42 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
},
|
},
|
||||||
onConfirm: () async {
|
onConfirm: () async {
|
||||||
await _saveSkipSecondsStart(_secondsStart);
|
await _saveSkipSecondsStart(_secondsStart);
|
||||||
setState(() => _showStartTimePicker = false);
|
if (mounted) setState(() => _showStartTimePicker = false);
|
||||||
},
|
},
|
||||||
onChange: (value) => _secondsStart = value.inSeconds),
|
onChange: (value) => _secondsStart = value.inSeconds),
|
||||||
FutureBuilder<int>(
|
// FutureBuilder<int>(
|
||||||
future: _getSkipSecondEnd(widget.podcastLocal.id),
|
// future: _getSkipSecondEnd(widget.podcastLocal.id),
|
||||||
initialData: 0,
|
// initialData: 0,
|
||||||
builder: (context, snapshot) => ListTile(
|
// builder: (context, snapshot) => ListTile(
|
||||||
onTap: () {
|
// onTap: () {
|
||||||
_secondsEnd = 0;
|
// _secondsEnd = 0;
|
||||||
setState(() {
|
// setState(() {
|
||||||
_removeConfirm = false;
|
// _removeConfirm = false;
|
||||||
_markConfirm = false;
|
// _markConfirm = false;
|
||||||
_showStartTimePicker = false;
|
// _showStartTimePicker = false;
|
||||||
_showEndTimePicker = !_showEndTimePicker;
|
// _showEndTimePicker = !_showEndTimePicker;
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
leading: Icon(Icons.fast_rewind),
|
// leading: Icon(Icons.fast_rewind),
|
||||||
title: Text(s.skipSecondsAtEnd),
|
// title: Text(s.skipSecondsAtEnd),
|
||||||
trailing: Padding(
|
// trailing: Padding(
|
||||||
padding: const EdgeInsets.only(right: 10.0),
|
// padding: const EdgeInsets.only(right: 10.0),
|
||||||
child: Text(snapshot.data.toTime),
|
// child: Text(snapshot.data.toTime),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
if (_showEndTimePicker)
|
// if (_showEndTimePicker)
|
||||||
_TimePicker(
|
// _TimePicker(
|
||||||
onCancel: () {
|
// onCancel: () {
|
||||||
_secondsEnd = 0;
|
// _secondsEnd = 0;
|
||||||
setState(() => _showEndTimePicker = false);
|
// setState(() => _showEndTimePicker = false);
|
||||||
},
|
// },
|
||||||
onConfirm: () async {
|
// onConfirm: () async {
|
||||||
await _saveSkipSecondsEnd(_secondsEnd);
|
// await _saveSkipSecondsEnd(_secondsEnd);
|
||||||
setState(() => _showEndTimePicker = false);
|
// setState(() => _showEndTimePicker = false);
|
||||||
},
|
// },
|
||||||
onChange: (value) => _secondsEnd = value.inSeconds,
|
// onChange: (value) => _secondsEnd = value.inSeconds,
|
||||||
),
|
// ),
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (_coverStatus != RefreshCoverStatus.start) {
|
if (_coverStatus != RefreshCoverStatus.start) {
|
||||||
|
@ -419,7 +443,6 @@ class _TimePicker extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
DurationPicker(
|
DurationPicker(
|
||||||
key: key,
|
|
||||||
onChange: onChange,
|
onChange: onChange,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||||
import 'dart:developer' as developer;
|
import 'dart:developer' as developer;
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:device_info/device_info.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -9,6 +10,7 @@ import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
|
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:line_icons/line_icons.dart';
|
import 'package:line_icons/line_icons.dart';
|
||||||
|
import 'package:confetti/confetti.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -299,23 +301,37 @@ class _DataBackupState extends State<DataBackup> {
|
||||||
final loginInfo = snapshot.data;
|
final loginInfo = snapshot.data;
|
||||||
if (loginInfo.isNotEmpty) {
|
if (loginInfo.isNotEmpty) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding:
|
contentPadding: const EdgeInsets.only(
|
||||||
const EdgeInsets.only(left: 70.0, right: 20),
|
left: 70.0, right: 20, top: 10, bottom: 10),
|
||||||
onTap: _syncNow,
|
onTap: _syncNow,
|
||||||
title: Text(s.syncNow),
|
title: Text(s.syncNow),
|
||||||
|
trailing: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => _GpodderInfo()));
|
||||||
|
},
|
||||||
|
icon: Icon(LineIcons.info_circle_solid),
|
||||||
|
),
|
||||||
subtitle: FutureBuilder<List<int>>(
|
subtitle: FutureBuilder<List<int>>(
|
||||||
future: _getSyncStatus(),
|
future: _getSyncStatus(),
|
||||||
initialData: [0, 0],
|
initialData: [0, 0],
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final dateTime = snapshot.data[0];
|
final dateTime = snapshot.data[0];
|
||||||
final status = snapshot.data[1];
|
final status = snapshot.data[1];
|
||||||
return Wrap(
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'${s.lastUpdate}: ${dateTime.toDate(context)}'),
|
'${s.lastUpdate}: ${dateTime.toDate(context)}'),
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Text('${s.status}: '),
|
Row(
|
||||||
_syncStauts(status),
|
children: [
|
||||||
|
Text('${s.status}: '),
|
||||||
|
_syncStauts(status),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
@ -323,6 +339,7 @@ class _DataBackupState extends State<DataBackup> {
|
||||||
}
|
}
|
||||||
return Center();
|
return Center();
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// ListTile(
|
// ListTile(
|
||||||
// onTap: () async {
|
// onTap: () async {
|
||||||
// final subscribeWorker = context.read<GroupList>();
|
// final subscribeWorker = context.read<GroupList>();
|
||||||
|
@ -402,7 +419,7 @@ class _DataBackupState extends State<DataBackup> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Divider(),
|
Divider(height: 1),
|
||||||
Container(
|
Container(
|
||||||
height: 30.0,
|
height: 30.0,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 70),
|
padding: EdgeInsets.symmetric(horizontal: 70),
|
||||||
|
@ -568,13 +585,21 @@ class __LoginGpodderState extends State<_LoginGpodder> {
|
||||||
var _username = '';
|
var _username = '';
|
||||||
var _password = '';
|
var _password = '';
|
||||||
LoginStatus _loginStatus;
|
LoginStatus _loginStatus;
|
||||||
|
ConfettiController _controller;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_loginStatus = LoginStatus.none;
|
_loginStatus = LoginStatus.none;
|
||||||
|
_controller = ConfettiController(duration: Duration(seconds: 3));
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
final GlobalKey<FormFieldState<String>> _passwordFieldKey =
|
final GlobalKey<FormFieldState<String>> _passwordFieldKey =
|
||||||
GlobalKey<FormFieldState<String>>();
|
GlobalKey<FormFieldState<String>>();
|
||||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
@ -601,6 +626,7 @@ class __LoginGpodderState extends State<_LoginGpodder> {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_loginStatus = LoginStatus.complete;
|
_loginStatus = LoginStatus.complete;
|
||||||
|
_controller.play();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -635,9 +661,11 @@ class __LoginGpodderState extends State<_LoginGpodder> {
|
||||||
var rssLink = rssExp.stringMatch(rss.xmlUrl);
|
var rssLink = rssExp.stringMatch(rss.xmlUrl);
|
||||||
if (rssLink != null) {
|
if (rssLink != null) {
|
||||||
final dbHelper = DBHelper();
|
final dbHelper = DBHelper();
|
||||||
final exist = dbHelper.checkPodcast(rssLink);
|
final exist = await dbHelper.checkPodcast(rssLink);
|
||||||
if (exist == '') {
|
if (exist == '') {
|
||||||
var item = SubscribeItem(rssLink, rss.text, group: 'Home');
|
var item = SubscribeItem(
|
||||||
|
rssLink, rss.text == '' ? rssLink : rss.text,
|
||||||
|
group: 'Home');
|
||||||
await subscribeWorker.setSubscribeItem(item, syncGpodder: false);
|
await subscribeWorker.setSubscribeItem(item, syncGpodder: false);
|
||||||
await Future.delayed(Duration(milliseconds: 200));
|
await Future.delayed(Duration(milliseconds: 200));
|
||||||
}
|
}
|
||||||
|
@ -757,14 +785,37 @@ class __LoginGpodderState extends State<_LoginGpodder> {
|
||||||
_loginStatus == LoginStatus.complete
|
_loginStatus == LoginStatus.complete
|
||||||
? SliverList(
|
? SliverList(
|
||||||
delegate: SliverChildListDelegate([
|
delegate: SliverChildListDelegate([
|
||||||
Padding(
|
Stack(
|
||||||
padding: const EdgeInsets.fromLTRB(40.0, 50, 40, 100),
|
children: [
|
||||||
child: Text(
|
Padding(
|
||||||
s.gpodderLoginDes,
|
padding:
|
||||||
textAlign: TextAlign.center,
|
const EdgeInsets.fromLTRB(40.0, 50, 40, 100),
|
||||||
style:
|
child: Text(
|
||||||
context.textTheme.subtitle1.copyWith(height: 2),
|
s.gpodderLoginDes,
|
||||||
),
|
textAlign: TextAlign.center,
|
||||||
|
style: context.textTheme.subtitle1
|
||||||
|
.copyWith(height: 2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: ConfettiWidget(
|
||||||
|
confettiController: _controller,
|
||||||
|
blastDirectionality:
|
||||||
|
BlastDirectionality.explosive,
|
||||||
|
emissionFrequency: 0.05,
|
||||||
|
maximumSize: Size(20, 10),
|
||||||
|
shouldLoop: false,
|
||||||
|
colors: const [
|
||||||
|
Colors.green,
|
||||||
|
Colors.blue,
|
||||||
|
Colors.pink,
|
||||||
|
Colors.orange,
|
||||||
|
Colors.purple
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Center(
|
Center(
|
||||||
child: OutlineButton(
|
child: OutlineButton(
|
||||||
|
@ -773,7 +824,7 @@ class __LoginGpodderState extends State<_LoginGpodder> {
|
||||||
},
|
},
|
||||||
highlightedBorderColor: context.accentColor,
|
highlightedBorderColor: context.accentColor,
|
||||||
child: Text(s.back)),
|
child: Text(s.back)),
|
||||||
)
|
),
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
: Form(
|
: Form(
|
||||||
|
@ -922,3 +973,152 @@ class _PasswordFieldState extends State<PasswordField> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _GpodderInfo extends StatefulWidget {
|
||||||
|
_GpodderInfo({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
__GpodderInfoState createState() => __GpodderInfoState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class __GpodderInfoState extends State<_GpodderInfo> {
|
||||||
|
final _gpodder = Gpodder();
|
||||||
|
var _syncing = false;
|
||||||
|
|
||||||
|
Future<List<String>> _getLoginInfo() async {
|
||||||
|
final storage = KeyValueStorage(gpodderApiKey);
|
||||||
|
final androidInfo = await DeviceInfoPlugin().androidInfo;
|
||||||
|
final deviceInfo = await storage.getStringList();
|
||||||
|
deviceInfo.add("Tsacdop on ${androidInfo.model}");
|
||||||
|
return deviceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fullSync() async {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_syncing = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
final uploadStatus = await _gpodder.uploadSubscriptions();
|
||||||
|
if (uploadStatus == 200) {
|
||||||
|
var subscribeWorker = context.read<GroupList>();
|
||||||
|
var rssExp = RegExp(r'^(https?):\/\/(.*)');
|
||||||
|
final opml = await _gpodder.getAllPodcast();
|
||||||
|
if (opml != '') {
|
||||||
|
Map<String, List<OmplOutline>> data = PodcastsBackup.parseOMPL(opml);
|
||||||
|
for (var entry in data.entries) {
|
||||||
|
var list = entry.value.reversed;
|
||||||
|
for (var rss in list) {
|
||||||
|
var rssLink = rssExp.stringMatch(rss.xmlUrl);
|
||||||
|
if (rssLink != null) {
|
||||||
|
final dbHelper = DBHelper();
|
||||||
|
final exist = await dbHelper.checkPodcast(rssLink);
|
||||||
|
if (exist == '') {
|
||||||
|
var item = SubscribeItem(
|
||||||
|
rssLink, rss.text == '' ? rssLink : rss.text,
|
||||||
|
group: 'Home');
|
||||||
|
await subscribeWorker.setSubscribeItem(item,
|
||||||
|
syncGpodder: false);
|
||||||
|
await Future.delayed(Duration(milliseconds: 200));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//await _syncNow();
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_syncing = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = context.s;
|
||||||
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarIconBrightness: Brightness.dark,
|
||||||
|
systemNavigationBarColor: Theme.of(context).primaryColor,
|
||||||
|
systemNavigationBarIconBrightness:
|
||||||
|
Theme.of(context).accentColorBrightness,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
resizeToAvoidBottomInset: true,
|
||||||
|
body: SafeArea(
|
||||||
|
top: false,
|
||||||
|
child: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverAppBar(
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
iconTheme: IconThemeData(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
backgroundColor: context.accentColor,
|
||||||
|
expandedHeight: 200,
|
||||||
|
flexibleSpace: Container(
|
||||||
|
height: 200,
|
||||||
|
width: double.infinity,
|
||||||
|
color: context.accentColor,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
CircleAvatar(
|
||||||
|
minRadius: 50,
|
||||||
|
backgroundColor: context.primaryColor.withOpacity(0.3),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 80,
|
||||||
|
width: 80,
|
||||||
|
child: Image.asset('assets/gpodder.png')),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(s.intergateWith('gpodder.net'),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverList(
|
||||||
|
delegate: SliverChildListDelegate([
|
||||||
|
FutureBuilder<List<String>>(
|
||||||
|
future: _getLoginInfo(),
|
||||||
|
initialData: [],
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final deviceId =
|
||||||
|
snapshot.data.isNotEmpty ? snapshot.data[1] : '';
|
||||||
|
final deviceName =
|
||||||
|
snapshot.data.isNotEmpty ? snapshot.data[3] : '';
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
title: Text('Divice id'),
|
||||||
|
subtitle: Text(deviceId),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text('Divice name'),
|
||||||
|
subtitle: Text(deviceName),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
ListTile(
|
||||||
|
onTap: _fullSync,
|
||||||
|
// contentPadding:
|
||||||
|
// const EdgeInsets.only(left: 70.0, right: 20),
|
||||||
|
title: Text('Full sync'),
|
||||||
|
subtitle: Text('If sync have error')),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -218,7 +218,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
||||||
volumeGainStorage.saveInt(volumeGain);
|
volumeGainStorage.saveInt(volumeGain);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _initAudioData() async {
|
Future<void> _initAudioData() async {
|
||||||
var index = await playerHeightStorage.getInt(defaultValue: 0);
|
var index = await playerHeightStorage.getInt(defaultValue: 0);
|
||||||
_playerHeight = PlayerHeight.values[index];
|
_playerHeight = PlayerHeight.values[index];
|
||||||
_currentSpeed = await speedStorage.getDoubel(defaultValue: 1.0);
|
_currentSpeed = await speedStorage.getDoubel(defaultValue: 1.0);
|
||||||
|
@ -250,8 +250,6 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
||||||
void addListener(VoidCallback listener) {
|
void addListener(VoidCallback listener) {
|
||||||
super.addListener(listener);
|
super.addListener(listener);
|
||||||
_initAudioData();
|
_initAudioData();
|
||||||
// _queueUpdate = false;
|
|
||||||
// _getAutoSleepTimer();
|
|
||||||
AudioService.connect();
|
AudioService.connect();
|
||||||
var running = AudioService.running;
|
var running = AudioService.running;
|
||||||
if (running) {}
|
if (running) {}
|
||||||
|
@ -265,7 +263,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
||||||
if (_lastPostion > 0 && _queue.playlist.length > 0) {
|
if (_lastPostion > 0 && _queue.playlist.length > 0) {
|
||||||
final episode = _queue.playlist.first;
|
final episode = _queue.playlist.first;
|
||||||
final duration = episode.duration * 1000;
|
final duration = episode.duration * 1000;
|
||||||
final seekValue = duration != 0 ? _lastPostion / duration : 1;
|
final seekValue = duration != 0 ? _lastPostion / duration : 1.0;
|
||||||
final history = PlayHistory(
|
final history = PlayHistory(
|
||||||
episode.title, episode.enclosureUrl, _lastPostion ~/ 1000, seekValue);
|
episode.title, episode.enclosureUrl, _lastPostion ~/ 1000, seekValue);
|
||||||
await dbHelper.saveHistory(history);
|
await dbHelper.saveHistory(history);
|
||||||
|
@ -319,7 +317,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_startAudioService(int position, String url) async {
|
Future<void> _startAudioService(int position, String url) async {
|
||||||
_stopOnComplete = false;
|
_stopOnComplete = false;
|
||||||
_sleepTimerMode = SleepTimerMode.undefined;
|
_sleepTimerMode = SleepTimerMode.undefined;
|
||||||
_switchValue = 0;
|
_switchValue = 0;
|
||||||
|
@ -439,27 +437,26 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
||||||
});
|
});
|
||||||
|
|
||||||
AudioService.customEventStream.distinct().listen((event) async {
|
AudioService.customEventStream.distinct().listen((event) async {
|
||||||
if (event is String && _episode.title == event) {
|
if (event is String &&
|
||||||
|
_queue.playlist.isNotEmpty &&
|
||||||
|
_queue.playlist.first.title == event) {
|
||||||
_queue.delFromPlaylist(_episode);
|
_queue.delFromPlaylist(_episode);
|
||||||
_lastPostion = 0;
|
_lastPostion = 0;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
await positionStorage.saveInt(_lastPostion);
|
await positionStorage.saveInt(_lastPostion);
|
||||||
if (_lastPostion == 0) {
|
final history = PlayHistory(_episode.title, _episode.enclosureUrl,
|
||||||
|
_backgroundAudioPosition ~/ 1000, _seekSliderValue);
|
||||||
|
await dbHelper.saveHistory(history);
|
||||||
|
}
|
||||||
|
if (event is Map && event['playerRunning'] == false && _playerRunning) {
|
||||||
|
_playerRunning = false;
|
||||||
|
notifyListeners();
|
||||||
|
if (_lastPostion > 0) {
|
||||||
final history = PlayHistory(_episode.title, _episode.enclosureUrl,
|
final history = PlayHistory(_episode.title, _episode.enclosureUrl,
|
||||||
_backgroundAudioPosition ~/ 1000, _seekSliderValue);
|
_lastPostion ~/ 1000, _seekSliderValue);
|
||||||
await dbHelper.saveHistory(history);
|
await dbHelper.saveHistory(history);
|
||||||
}
|
}
|
||||||
}
|
_episode = null;
|
||||||
if (event is Map && event['playerRunning'] == false) {
|
|
||||||
if (_playerRunning) {
|
|
||||||
_playerRunning = false;
|
|
||||||
notifyListeners();
|
|
||||||
if (_lastPostion > 0) {
|
|
||||||
final history = PlayHistory(_episode.title, _episode.enclosureUrl,
|
|
||||||
_lastPostion ~/ 1000, _seekSliderValue);
|
|
||||||
await dbHelper.saveHistory(history);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -531,7 +528,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
||||||
|
|
||||||
Future<void> addNewEpisode(List<String> group) async {
|
Future<void> addNewEpisode(List<String> group) async {
|
||||||
var newEpisodes = <EpisodeBrief>[];
|
var newEpisodes = <EpisodeBrief>[];
|
||||||
if (group.first == 'All') {
|
if (group.isEmpty) {
|
||||||
newEpisodes = await dbHelper.getRecentNewRssItem();
|
newEpisodes = await dbHelper.getRecentNewRssItem();
|
||||||
} else {
|
} else {
|
||||||
newEpisodes = await dbHelper.getGroupNewRssItem(group);
|
newEpisodes = await dbHelper.getGroupNewRssItem(group);
|
||||||
|
@ -541,14 +538,14 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
||||||
await addToPlaylist(episode);
|
await addToPlaylist(episode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (group.first == 'All') {
|
if (group.isEmpty) {
|
||||||
await dbHelper.removeAllNewMark();
|
await dbHelper.removeAllNewMark();
|
||||||
} else {
|
} else {
|
||||||
await dbHelper.removeGroupNewMark(group);
|
await dbHelper.removeGroupNewMark(group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMediaItem(EpisodeBrief episode) async {
|
Future<void> updateMediaItem(EpisodeBrief episode) async {
|
||||||
if (episode.enclosureUrl == episode.mediaId) {
|
if (episode.enclosureUrl == episode.mediaId) {
|
||||||
var index = _queue.playlist
|
var index = _queue.playlist
|
||||||
.indexWhere((item) => item.enclosureUrl == episode.enclosureUrl);
|
.indexWhere((item) => item.enclosureUrl == episode.enclosureUrl);
|
||||||
|
@ -867,7 +864,8 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
||||||
await AudioServiceBackground.setQueue(_queue);
|
await AudioServiceBackground.setQueue(_queue);
|
||||||
if (_queue.length == 0 || _stopAtEnd) {
|
if (_queue.length == 0 || _stopAtEnd) {
|
||||||
_skipState = null;
|
_skipState = null;
|
||||||
onStop();
|
await Future.delayed(Duration(milliseconds: 200));
|
||||||
|
await onStop();
|
||||||
} else {
|
} else {
|
||||||
await AudioServiceBackground.setQueue(_queue);
|
await AudioServiceBackground.setQueue(_queue);
|
||||||
await AudioServiceBackground.setMediaItem(mediaItem);
|
await AudioServiceBackground.setMediaItem(mediaItem);
|
||||||
|
@ -878,13 +876,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
||||||
mediaItem.copyWith(duration: duration));
|
mediaItem.copyWith(duration: duration));
|
||||||
}
|
}
|
||||||
_skipState = null;
|
_skipState = null;
|
||||||
// Resume playback if we were playing
|
|
||||||
// if (_playing) {
|
|
||||||
//onPlay();
|
|
||||||
_playFromStart();
|
_playFromStart();
|
||||||
// } else {
|
|
||||||
// _setState(state: BasicPlaybackState.paused);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -922,10 +914,11 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
||||||
_session.setActive(true);
|
_session.setActive(true);
|
||||||
if (mediaItem.extras['skipSecondsStart'] > 0 ||
|
if (mediaItem.extras['skipSecondsStart'] > 0 ||
|
||||||
mediaItem.extras['skipSecondsEnd'] > 0) {
|
mediaItem.extras['skipSecondsEnd'] > 0) {
|
||||||
//_audioPlayer.seek(Duration(seconds: mediaItem.extras['skip']));
|
_audioPlayer
|
||||||
_audioPlayer.setClip(
|
.seek(Duration(seconds: mediaItem.extras['skipSecondsStart']));
|
||||||
start: Duration(seconds: mediaItem.extras['skipSecondsStart']),
|
// await _audioPlayer.setClip(
|
||||||
end: Duration(seconds: mediaItem.extras['skipSecondsEnd']));
|
// start: Duration(seconds: mediaItem.extras['skipSecondsStart']),
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
if (_audioPlayer.playbackEvent.state != AudioPlaybackState.connecting ||
|
if (_audioPlayer.playbackEvent.state != AudioPlaybackState.connecting ||
|
||||||
_audioPlayer.playbackEvent.state != AudioPlaybackState.none) {
|
_audioPlayer.playbackEvent.state != AudioPlaybackState.none) {
|
||||||
|
|
|
@ -152,14 +152,14 @@ class SubscribeItem {
|
||||||
///Podcast group, default Home.
|
///Podcast group, default Home.
|
||||||
String group;
|
String group;
|
||||||
|
|
||||||
///sync to gpodder
|
SubscribeItem(
|
||||||
bool syncWithGpodder;
|
this.url,
|
||||||
SubscribeItem(this.url, this.title,
|
this.title, {
|
||||||
{this.subscribeState = SubscribeState.none,
|
this.subscribeState = SubscribeState.none,
|
||||||
this.id = '',
|
this.id = '',
|
||||||
this.imgUrl = '',
|
this.imgUrl = '',
|
||||||
this.group = '',
|
this.group = '',
|
||||||
this.syncWithGpodder = true});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupList extends ChangeNotifier {
|
class GroupList extends ChangeNotifier {
|
||||||
|
@ -219,7 +219,7 @@ class GroupList extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _start() async {
|
Future _start() async {
|
||||||
if (_created == false) {
|
if (!_created) {
|
||||||
await _createIsolate();
|
await _createIsolate();
|
||||||
_created = true;
|
_created = true;
|
||||||
listen();
|
listen();
|
||||||
|
@ -229,7 +229,6 @@ class GroupList extends ChangeNotifier {
|
||||||
_subscribeItem.title,
|
_subscribeItem.title,
|
||||||
_subscribeItem.imgUrl,
|
_subscribeItem.imgUrl,
|
||||||
_subscribeItem.group,
|
_subscribeItem.group,
|
||||||
_subscribeItem.syncWithGpodder
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +249,6 @@ class GroupList extends ChangeNotifier {
|
||||||
_subscribeItem.title,
|
_subscribeItem.title,
|
||||||
_subscribeItem.imgUrl,
|
_subscribeItem.imgUrl,
|
||||||
_subscribeItem.group,
|
_subscribeItem.group,
|
||||||
_subscribeItem.syncWithGpodder
|
|
||||||
]);
|
]);
|
||||||
} else if (message is List) {
|
} else if (message is List) {
|
||||||
_setCurrentSubscribeItem(SubscribeItem(
|
_setCurrentSubscribeItem(SubscribeItem(
|
||||||
|
@ -717,7 +715,7 @@ Future<void> subIsolateEntryPoint(SendPort sendPort) async {
|
||||||
subReceivePort.distinct().listen((message) {
|
subReceivePort.distinct().listen((message) {
|
||||||
if (message is List<dynamic>) {
|
if (message is List<dynamic>) {
|
||||||
items.add(SubscribeItem(message[0], message[1],
|
items.add(SubscribeItem(message[0], message[1],
|
||||||
imgUrl: message[2], group: message[3], syncWithGpodder: message[4]));
|
imgUrl: message[2], group: message[3]));
|
||||||
if (!_running) {
|
if (!_running) {
|
||||||
_subscribe(items.first);
|
_subscribe(items.first);
|
||||||
_running = true;
|
_running = true;
|
||||||
|
|
|
@ -34,8 +34,12 @@ class RefreshWorker extends ChangeNotifier {
|
||||||
refreshIsolateEntryPoint, receivePort.sendPort);
|
refreshIsolateEntryPoint, receivePort.sendPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _listen() {
|
void _listen(List<String> podcasts) {
|
||||||
receivePort.distinct().listen((message) {
|
receivePort.distinct().listen((message) {
|
||||||
|
if (message is SendPort) {
|
||||||
|
refreshSendPort = message;
|
||||||
|
refreshSendPort.send(podcasts);
|
||||||
|
}
|
||||||
if (message is List) {
|
if (message is List) {
|
||||||
_currentRefreshItem =
|
_currentRefreshItem =
|
||||||
RefreshItem(message[0], RefreshState.values[message[1]]);
|
RefreshItem(message[0], RefreshState.values[message[1]]);
|
||||||
|
@ -51,11 +55,11 @@ class RefreshWorker extends ChangeNotifier {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> start() async {
|
Future<void> start(List<String> podcasts) async {
|
||||||
if (!_created) {
|
if (!_created) {
|
||||||
_complete = false;
|
_complete = false;
|
||||||
_createIsolate();
|
await _createIsolate();
|
||||||
_listen();
|
_listen(podcasts);
|
||||||
_created = true;
|
_created = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,14 +72,30 @@ class RefreshWorker extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refreshIsolateEntryPoint(SendPort sendPort) async {
|
Future<void> refreshIsolateEntryPoint(SendPort sendPort) async {
|
||||||
var refreshstorage = KeyValueStorage(refreshdateKey);
|
var refreshReceivePort = ReceivePort();
|
||||||
await refreshstorage.saveInt(DateTime.now().millisecondsSinceEpoch);
|
sendPort.send(refreshReceivePort.sendPort);
|
||||||
var dbHelper = DBHelper();
|
var _dbHelper = DBHelper();
|
||||||
var podcastList = await dbHelper.getPodcastLocalAll();
|
|
||||||
for (var podcastLocal in podcastList) {
|
Future<void> _refreshAll(List<String> podcasts) async {
|
||||||
sendPort.send([podcastLocal.title, 1]);
|
var podcastList;
|
||||||
var updateCount = await dbHelper.updatePodcastRss(podcastLocal);
|
if (podcasts.isEmpty) {
|
||||||
developer.log('Refresh ${podcastLocal.title}$updateCount');
|
var refreshstorage = KeyValueStorage(refreshdateKey);
|
||||||
|
await refreshstorage.saveInt(DateTime.now().millisecondsSinceEpoch);
|
||||||
|
podcastList = await _dbHelper.getPodcastLocalAll(updateOnly: true);
|
||||||
|
} else {
|
||||||
|
podcastList = await _dbHelper.getPodcastLocal(podcasts, updateOnly: true);
|
||||||
|
}
|
||||||
|
for (var podcastLocal in podcastList) {
|
||||||
|
sendPort.send([podcastLocal.title, 1]);
|
||||||
|
var updateCount = await _dbHelper.updatePodcastRss(podcastLocal);
|
||||||
|
developer.log('Refresh ${podcastLocal.title}$updateCount');
|
||||||
|
}
|
||||||
|
sendPort.send("done");
|
||||||
}
|
}
|
||||||
sendPort.send("done");
|
|
||||||
|
refreshReceivePort.distinct().listen((message) {
|
||||||
|
if (message is List<dynamic>) {
|
||||||
|
_refreshAll(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ void callbackDispatcher() {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
Workmanager.executeTask((task, inputData) async {
|
Workmanager.executeTask((task, inputData) async {
|
||||||
var dbHelper = DBHelper();
|
var dbHelper = DBHelper();
|
||||||
var podcastList = await dbHelper.getPodcastLocalAll();
|
var podcastList = await dbHelper.getPodcastLocalAll(updateOnly: false);
|
||||||
//lastWork is a indicator for if the app was opened since last backgroundwork
|
//lastWork is a indicator for if the app was opened since last backgroundwork
|
||||||
//if the app wes opend,then the old marked new episode would be marked not new.
|
//if the app wes opend,then the old marked new episode would be marked not new.
|
||||||
var lastWorkStorage = KeyValueStorage(lastWorkKey);
|
var lastWorkStorage = KeyValueStorage(lastWorkKey);
|
||||||
|
|
19
pubspec.yaml
19
pubspec.yaml
|
@ -1,7 +1,7 @@
|
||||||
name: tsacdop
|
name: tsacdop
|
||||||
description: An open source podacasts player.
|
description: An open source podacasts player.
|
||||||
|
|
||||||
version: 0.4.17+34
|
version: 0.4.18+35
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.6.0 <3.0.0"
|
sdk: ">=2.6.0 <3.0.0"
|
||||||
|
@ -15,7 +15,8 @@ dependencies:
|
||||||
audio_session: ^0.0.7
|
audio_session: ^0.0.7
|
||||||
cached_network_image: ^2.3.2+1
|
cached_network_image: ^2.3.2+1
|
||||||
color_thief_flutter: ^1.0.2
|
color_thief_flutter: ^1.0.2
|
||||||
cookie_jar: ^1.0.0
|
confetti: ^0.5.4+1
|
||||||
|
cookie_jar: ^1.0.1
|
||||||
cupertino_icons: ^1.0.0
|
cupertino_icons: ^1.0.0
|
||||||
connectivity: ^0.4.9
|
connectivity: ^0.4.9
|
||||||
device_info: ^0.4.2+7
|
device_info: ^0.4.2+7
|
||||||
|
@ -25,7 +26,7 @@ dependencies:
|
||||||
effective_dart: ^1.2.4
|
effective_dart: ^1.2.4
|
||||||
equatable: ^1.2.5
|
equatable: ^1.2.5
|
||||||
feature_discovery: ^0.10.0
|
feature_discovery: ^0.10.0
|
||||||
file_picker: ^2.0.0
|
file_picker: ^2.0.1+2
|
||||||
flutter_html: ^0.11.1
|
flutter_html: ^0.11.1
|
||||||
flutter_downloader: ^1.5.0
|
flutter_downloader: ^1.5.0
|
||||||
fluttertoast: ^4.0.0
|
fluttertoast: ^4.0.0
|
||||||
|
@ -36,18 +37,18 @@ dependencies:
|
||||||
fl_chart: ^0.11.1
|
fl_chart: ^0.11.1
|
||||||
marquee: ^1.3.1
|
marquee: ^1.3.1
|
||||||
google_fonts: ^1.1.0
|
google_fonts: ^1.1.0
|
||||||
image: ^2.1.14
|
image: ^2.1.17
|
||||||
intl: ^0.16.1
|
intl: ^0.16.1
|
||||||
json_serializable: ^3.4.1
|
json_serializable: ^3.5.0
|
||||||
json_annotation: ^3.0.1
|
json_annotation: ^3.1.0
|
||||||
path_provider: ^1.6.16
|
path_provider: ^1.6.18
|
||||||
permission_handler: ^5.0.1
|
permission_handler: ^5.0.1
|
||||||
provider: ^4.3.2
|
provider: ^4.3.2
|
||||||
rxdart: ^0.24.1
|
rxdart: ^0.24.1
|
||||||
sqflite: ^1.3.1
|
sqflite: ^1.3.1
|
||||||
shared_preferences: ^0.5.10
|
shared_preferences: ^0.5.12
|
||||||
tuple: ^1.0.3
|
tuple: ^1.0.3
|
||||||
url_launcher: ^5.6.0
|
url_launcher: ^5.7.1
|
||||||
uuid: ^2.2.2
|
uuid: ^2.2.2
|
||||||
xml: ^4.2.0
|
xml: ^4.2.0
|
||||||
workmanager: ^0.2.3
|
workmanager: ^0.2.3
|
||||||
|
|
Loading…
Reference in New Issue