Minor change.

This commit is contained in:
stonegate 2020-08-23 17:42:13 +08:00
parent be00383966
commit 5a32511ac9
8 changed files with 381 additions and 358 deletions

View File

@ -422,19 +422,19 @@ class __MenuBarState extends State<_MenuBar> {
return await dbHelper.isListened(episode.enclosureUrl);
}
_saveLiked(String url) async {
Future<void> _saveLiked(String url) async {
var dbHelper = DBHelper();
await dbHelper.setLiked(url);
if (mounted) setState(() {});
}
_setUnliked(String url) async {
Future<void> _setUnliked(String url) async {
var dbHelper = DBHelper();
await dbHelper.setUniked(url);
if (mounted) setState(() {});
}
_markListened(EpisodeBrief episode) async {
Future<void> _markListened(EpisodeBrief episode) async {
var dbHelper = DBHelper();
//var marked = await dbHelper.checkMarked(episode);
//if (!marked) {
@ -444,7 +444,7 @@ class __MenuBarState extends State<_MenuBar> {
if (mounted) setState(() {});
}
_markNotListened(String url) async {
Future<void> _markNotListened(String url) async {
var dbHelper = DBHelper();
await dbHelper.markNotListened(url);
if (mounted) setState(() {});
@ -554,8 +554,9 @@ class __MenuBarState extends State<_MenuBar> {
selector: (_, audio) =>
Tuple2(audio.queue.playlist, audio.queueUpdate),
builder: (_, data, __) {
return (data.item1.contains(widget.episodeItem) &&
!widget.hide)
final inPlaylist =
data.item1.contains(widget.episodeItem);
return inPlaylist
? _buttonOnMenu(
child: Icon(Icons.playlist_add_check,
color: context.accentColor),
@ -673,7 +674,7 @@ class _ShowNote extends StatelessWidget {
const _ShowNote({this.episode, Key key}) : super(key: key);
int _getTimeStamp(String url) {
final time = url.substring(7);
final time = url.substring(3).trim();
final data = time.split(':');
var seconds;
if (data.length == 3) {
@ -726,7 +727,7 @@ class _ShowNote extends StatelessWidget {
? Selector<AudioPlayerNotifier, EpisodeBrief>(
selector: (_, audio) => audio.episode,
builder: (_, data, __) {
if (data == episode) {
if (data == episode && !description.contains('#t=')) {
final linkList = linkify(description,
options: LinkifyOptions(humanize: false),
linkifiers: [TimeStampLinkifier()]);
@ -734,7 +735,7 @@ class _ShowNote extends StatelessWidget {
if (element is TimeStampElement) {
final time = element.timeStamp;
description = description.replaceFirst(time,
'<a rel="nofollow" href = "skipto:$time">$time</a>');
'<a rel="nofollow" href = "#t=$time">$time</a>');
}
}
}
@ -751,9 +752,11 @@ class _ShowNote extends StatelessWidget {
color: context.accentColor,
textBaseline: TextBaseline.ideographic),
onLinkTap: (url) {
if (url.substring(0, 6) == 'skipto') {
if (url.substring(0, 3) == '#t=') {
final seconds = _getTimeStamp(url);
audio.seekTo(seconds * 1000);
if (data == episode) {
audio.seekTo(seconds * 1000);
}
} else {
url.launchUrl;
}

View File

@ -15,6 +15,7 @@ import '../local_storage/sqflite_localpodcast.dart';
import '../state/audio_state.dart';
import '../state/download_state.dart';
import '../state/podcast_group.dart';
import '../state/refresh_podcast.dart';
import '../state/setting_state.dart';
import '../type/episodebrief.dart';
import '../type/playlist.dart';
@ -790,253 +791,259 @@ class _RecentUpdateState extends State<_RecentUpdate>
super.build(context);
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
final s = context.s;
return Selector<GroupList, bool>(
selector: (_, worker) => worker.created,
builder: (context, created, child) {
return FutureBuilder<List<EpisodeBrief>>(
future: _getRssItem(_top, _group),
builder: (context, snapshot) {
return (snapshot.hasData)
? snapshot.data.length == 0
? Padding(
padding: EdgeInsets.only(top: 150),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(LineIcons.cloud_download_alt_solid,
size: 80, color: Colors.grey[500]),
Padding(
padding: EdgeInsets.symmetric(vertical: 10)),
Text(
s.noEpisodeRecent,
style: TextStyle(color: Colors.grey[500]),
)
],
),
)
: NotificationListener<ScrollNotification>(
onNotification: (scrollInfo) {
if (scrollInfo is ScrollStartNotification &&
mounted &&
!_scroll) {
setState(() => _scroll = true);
}
if (scrollInfo.metrics.pixels ==
scrollInfo.metrics.maxScrollExtent &&
snapshot.data.length == _top) {
if (!_loadMore) {
_loadMoreEpisode();
return Selector<RefreshWorker, bool>(
selector: (_, worker) => worker.complete,
builder: (_, complete, __) => Selector<GroupList, bool>(
selector: (_, worker) => worker.created,
builder: (context, created, child) {
return FutureBuilder<List<EpisodeBrief>>(
future: _getRssItem(_top, _group),
builder: (context, snapshot) {
return (snapshot.hasData)
? snapshot.data.length == 0
? Padding(
padding: EdgeInsets.only(top: 150),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(LineIcons.cloud_download_alt_solid,
size: 80, color: Colors.grey[500]),
Padding(
padding:
EdgeInsets.symmetric(vertical: 10)),
Text(
s.noEpisodeRecent,
style: TextStyle(color: Colors.grey[500]),
)
],
),
)
: NotificationListener<ScrollNotification>(
onNotification: (scrollInfo) {
if (scrollInfo is ScrollStartNotification &&
mounted &&
!_scroll) {
setState(() => _scroll = true);
}
}
return true;
},
child: CustomScrollView(
key: PageStorageKey<String>('update'),
physics: const AlwaysScrollableScrollPhysics(),
slivers: <Widget>[
SliverToBoxAdapter(
child: Container(
height: 40,
color: context.primaryColor,
child: Material(
color: Colors.transparent,
child: Row(
children: <Widget>[
Consumer<GroupList>(
builder:
(context, groupList, child) =>
Material(
color: Colors.transparent,
child: PopupMenuButton<String>(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(
Radius.circular(
10))),
elevation: 1,
tooltip: s.groupFilter,
child: Container(
padding:
EdgeInsets.symmetric(
horizontal: 20),
height: 50,
child: Row(
mainAxisSize:
MainAxisSize.min,
children: <Widget>[
Text(_groupName ==
'All'
? s.all
: _groupName),
Padding(
padding: EdgeInsets
.symmetric(
horizontal:
5),
),
Icon(
LineIcons
.filter_solid,
size: 18,
)
],
)),
itemBuilder: (context) => [
PopupMenuItem(
child: Row(children: [
Text(s.all),
Spacer(),
if (_groupName ==
'All')
DotIndicator()
]),
value: 'All')
]..addAll(groupList.groups
.map<
PopupMenuEntry<
String>>(
(e) => PopupMenuItem(
value: e.name,
child: Row(
children: [
Text(e.name),
Spacer(),
if (e.name ==
_groupName)
DotIndicator()
],
)))
.toList()),
onSelected: (value) {
if (value == 'All') {
setState(() {
_groupName = 'All';
_group = ['All'];
});
} else {
for (var group
in groupList.groups) {
if (group.name ==
value) {
setState(() {
_groupName = value;
_group = group
.podcastList;
});
if (scrollInfo.metrics.pixels ==
scrollInfo.metrics.maxScrollExtent &&
snapshot.data.length == _top) {
if (!_loadMore) {
_loadMoreEpisode();
}
}
return true;
},
child: CustomScrollView(
key: PageStorageKey<String>('update'),
physics: const AlwaysScrollableScrollPhysics(),
slivers: <Widget>[
SliverToBoxAdapter(
child: Container(
height: 40,
color: context.primaryColor,
child: Material(
color: Colors.transparent,
child: Row(
children: <Widget>[
Consumer<GroupList>(
builder: (context, groupList,
child) =>
Material(
color: Colors.transparent,
child:
PopupMenuButton<String>(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(
Radius.circular(
10))),
elevation: 1,
tooltip: s.groupFilter,
child: Container(
padding: EdgeInsets
.symmetric(
horizontal: 20),
height: 50,
child: Row(
mainAxisSize:
MainAxisSize.min,
children: <Widget>[
Text(_groupName ==
'All'
? s.all
: _groupName),
Padding(
padding: EdgeInsets
.symmetric(
horizontal:
5),
),
Icon(
LineIcons
.filter_solid,
size: 18,
)
],
)),
itemBuilder: (context) => [
PopupMenuItem(
child: Row(children: [
Text(s.all),
Spacer(),
if (_groupName ==
'All')
DotIndicator()
]),
value: 'All')
]..addAll(groupList.groups
.map<
PopupMenuEntry<
String>>((e) =>
PopupMenuItem(
value: e.name,
child: Row(
children: [
Text(
e.name),
Spacer(),
if (e.name ==
_groupName)
DotIndicator()
],
)))
.toList()),
onSelected: (value) {
if (value == 'All') {
setState(() {
_groupName = 'All';
_group = ['All'];
});
} else {
for (var group
in groupList
.groups) {
if (group.name ==
value) {
setState(() {
_groupName =
value;
_group = group
.podcastList;
});
}
}
}
}
},
},
),
),
),
),
Spacer(),
FutureBuilder<int>(
future:
_getUpdateCounts(_group),
initialData: 0,
builder: (context, snapshot) {
return snapshot.data != 0
? Material(
color: Colors
.transparent,
child: IconButton(
tooltip: s
.addNewEpisodeTooltip,
icon: SizedBox(
height: 16,
width: 21,
child: CustomPaint(
painter: AddToPlaylistPainter(
context
.textTheme
.bodyText1
.color,
Colors
.red))),
onPressed:
() async {
await audio
.addNewEpisode(
_group);
if (mounted) {
setState(
() {});
}
Fluttertoast
.showToast(
msg: _groupName ==
'All'
? s.addNewEpisodeAll(
snapshot
.data)
: s.addEpisodeGroup(
_groupName,
snapshot
.data),
gravity:
ToastGravity
.BOTTOM,
);
}),
)
: Material(
color: Colors
.transparent,
child: IconButton(
tooltip: s
.addNewEpisodeTooltip,
icon: SizedBox(
height: 16,
width: 21,
child:
CustomPaint(
painter:
AddToPlaylistPainter(
context
.textColor,
context
.textColor,
))),
onPressed: () {}),
);
}),
Material(
color: Colors.transparent,
child: LayoutButton(
layout: _layout,
onPressed: (layout) =>
setState(() {
_layout = layout;
}),
Spacer(),
FutureBuilder<int>(
future:
_getUpdateCounts(_group),
initialData: 0,
builder: (context, snapshot) {
return snapshot.data != 0
? Material(
color: Colors
.transparent,
child: IconButton(
tooltip: s
.addNewEpisodeTooltip,
icon: SizedBox(
height: 16,
width: 21,
child: CustomPaint(
painter: AddToPlaylistPainter(
context
.textTheme.bodyText1.color,
Colors
.red))),
onPressed:
() async {
await audio
.addNewEpisode(
_group);
if (mounted) {
setState(
() {});
}
Fluttertoast
.showToast(
msg: _groupName ==
'All'
? s.addNewEpisodeAll(snapshot
.data)
: s.addEpisodeGroup(
_groupName,
snapshot.data),
gravity:
ToastGravity
.BOTTOM,
);
}),
)
: Material(
color: Colors
.transparent,
child: IconButton(
tooltip: s
.addNewEpisodeTooltip,
icon: SizedBox(
height: 16,
width: 21,
child:
CustomPaint(
painter:
AddToPlaylistPainter(
context
.textColor,
context
.textColor,
))),
onPressed:
() {}),
);
}),
Material(
color: Colors.transparent,
child: LayoutButton(
layout: _layout,
onPressed: (layout) =>
setState(() {
_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,
],
),
)),
),
),
]))
: Center();
},
);
});
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();
},
);
}),
);
}
@override

View File

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:math' as math;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@ -48,7 +49,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
super.initState();
_groupIndex = 0;
_controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 125))
AnimationController(vsync: this, duration: Duration(milliseconds: 150))
..addListener(() {
if (mounted) setState(() {});
})
@ -64,7 +65,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
super.dispose();
}
Future<int> getPodcastUpdateCounts(String id) async {
Future<int> _getPodcastUpdateCounts(String id) async {
var dbHelper = DBHelper();
return await dbHelper.getPodcastUpdateCounts(id);
}
@ -79,7 +80,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
@override
Widget build(BuildContext context) {
var _width = MediaQuery.of(context).size.width;
var width = MediaQuery.of(context).size.width;
final s = context.s;
return Selector<GroupList, Tuple3<List<PodcastGroup>, bool, bool>>(
selector: (_, groupList) =>
@ -90,11 +91,11 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
var isLoading = data.item3;
return isLoading
? Container(
height: (_width - 20) / 3 + 140,
height: (width - 20) / 3 + 140,
)
: groups[_groupIndex].podcastList.length == 0
? Container(
height: (_width - 20) / 3 + 140,
height: (width - 20) / 3 + 140,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
@ -195,7 +196,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
],
)),
Container(
height: (_width - 20) / 3 + 40,
height: (width - 20) / 3 + 40,
color: context.primaryColor,
margin: EdgeInsets.symmetric(horizontal: 15),
child: Center(
@ -334,7 +335,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
),
Container(
height: 70,
width: _width,
width: width,
alignment: Alignment.centerLeft,
color: context.scaffoldBackgroundColor,
child: TabBar(
@ -358,49 +359,41 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
_slideTween
.animate(_controller)
.value),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(25.0)),
child: LimitedBox(
maxHeight: 50,
maxWidth: 50,
child: CircleAvatar(
backgroundColor:
color.withOpacity(0.5),
backgroundImage:
podcastLocal.avatarImage,
child: FutureBuilder<int>(
future:
getPodcastUpdateCounts(
podcastLocal.id),
initialData: 0,
builder: (context, snapshot) {
return snapshot.data > 0
? Align(
child: LimitedBox(
maxHeight: 50,
maxWidth: 50,
child: CircleAvatar(
backgroundColor:
color.withOpacity(0.5),
backgroundImage:
podcastLocal.avatarImage,
child: FutureBuilder<int>(
future: _getPodcastUpdateCounts(
podcastLocal.id),
initialData: 0,
builder: (context, snapshot) {
return snapshot.data > 0
? Align(
alignment: Alignment
.bottomRight,
child: Container(
alignment: Alignment
.bottomCenter,
child: Container(
alignment:
Alignment
.center,
height: 10,
width: 40,
color: Colors
.black54,
child: Text('New',
style: TextStyle(
color: Colors
.red,
fontSize:
8,
fontStyle:
FontStyle
.italic)),
),
)
: Center();
}),
),
.center,
height: 10,
width: 10,
decoration: BoxDecoration(
color:
Colors.red,
border: Border.all(
color: context
.primaryColor,
width: 2),
shape: BoxShape
.circle),
),
)
: Center();
}),
),
),
),
@ -412,10 +405,10 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
),
),
Container(
height: (_width - 20) / 3 + 40,
margin: EdgeInsets.only(left: 10, right: 10),
height: (width - 20) / 3 + 40,
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
color: context.scaffoldBackgroundColor,
),
child: ScrollConfiguration(
behavior: NoGrowBehavior(),
@ -474,8 +467,8 @@ class PodcastPreview extends StatelessWidget {
episodes: snapshot.data,
podcastLocal: podcastLocal,
)
: Container(
padding: EdgeInsets.all(5.0),
: Padding(
padding: const EdgeInsets.all(5.0),
);
},
);
@ -492,12 +485,12 @@ class PodcastPreview extends StatelessWidget {
flex: 4,
child: Text(podcastLocal.title,
maxLines: 1,
overflow: TextOverflow.visible,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold, color: c)),
),
Expanded(
flex: 1,
child: Container(
child: Align(
alignment: Alignment.centerRight,
child: Material(
color: Colors.transparent,
@ -510,10 +503,6 @@ class PodcastPreview extends StatelessWidget {
Navigator.push(
context,
SlideLeftRoute(
// transitionPage: PodcastDetail(
// podcastLocal: podcastLocal,
// hide: playerRunning,
// ),
page: PodcastDetail(
podcastLocal: podcastLocal,
)),
@ -536,7 +525,7 @@ class ShowEpisode extends StatelessWidget {
final List<EpisodeBrief> episodes;
final PodcastLocal podcastLocal;
ShowEpisode({Key key, this.episodes, this.podcastLocal}) : super(key: key);
String _stringForSeconds(double seconds) {
String stringForSeconds(double seconds) {
if (seconds == null) return null;
return '${(seconds ~/ 60)}:${(seconds.truncate() % 60).toString().padLeft(2, '0')}';
}
@ -928,11 +917,9 @@ class ShowEpisode extends StatelessWidget {
? Container(
alignment: Alignment.center,
child: Text(
_stringForSeconds(
episodes[index]
.duration
.toDouble())
.toString(),
episodes[index]
.duration
.toTime,
style: TextStyle(
fontSize: _width / 35,
// color: _c,
@ -981,7 +968,7 @@ class ShowEpisode extends StatelessWidget {
);
}));
},
childCount: (episodes.length > 2) ? 2 : episodes.length,
childCount: math.min(episodes.length, 2),
),
),
),

View File

@ -538,12 +538,14 @@ class AudioPlayerNotifier extends ChangeNotifier {
}
updateMediaItem(EpisodeBrief episode) async {
var index = _queue.playlist
.indexWhere((item) => item.enclosureUrl == episode.enclosureUrl);
if (index > 0) {
var episodeNew = await dbHelper.getRssItemWithUrl(episode.enclosureUrl);
await delFromPlaylist(episode);
await addToPlaylistAt(episodeNew, index);
if (episode.enclosureUrl == episode.mediaId) {
var index = _queue.playlist
.indexWhere((item) => item.enclosureUrl == episode.enclosureUrl);
if (index > 0) {
var episodeNew = await dbHelper.getRssItemWithUrl(episode.enclosureUrl);
await delFromPlaylist(episode);
await addToPlaylistAt(episodeNew, index);
}
}
}
@ -818,7 +820,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
// Resume playback if we were playing
// if (_playing) {
//onPlay();
playFromStart();
_playFromStart();
// } else {
// _setState(state: BasicPlaybackState.paused);
// }
@ -842,7 +844,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
await AudioServiceBackground.setMediaItem(
mediaItem.copyWith(duration: duration));
}
playFromStart();
_playFromStart();
} else {
_playing = true;
if (_audioPlayer.playbackEvent.state != AudioPlaybackState.connecting ||
@ -853,7 +855,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
}
}
playFromStart() async {
_playFromStart() async {
_playing = true;
if (_audioPlayer.playbackEvent.state != AudioPlaybackState.connecting ||
_audioPlayer.playbackEvent.state != AudioPlaybackState.none) {
@ -940,7 +942,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
var duration = await _audioPlayer.durationFuture ?? Duration.zero;
AudioServiceBackground.setMediaItem(
mediaItem.copyWith(duration: duration));
playFromStart();
_playFromStart();
//onPlay();
} else {
_queue.insert(index, mediaItem);

View File

@ -7,26 +7,14 @@ import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import '../local_storage/key_value_storage.dart';
import '../local_storage/sqflite_localpodcast.dart';
import '../type/episode_task.dart';
import '../type/episodebrief.dart';
class EpisodeTask {
final String taskId;
int progress;
DownloadTaskStatus status;
final EpisodeBrief episode;
EpisodeTask(
this.episode,
this.taskId, {
this.progress = 0,
this.status = DownloadTaskStatus.undefined,
});
}
void downloadCallback(String id, DownloadTaskStatus status, int progress) {
developer.log('Homepage callback task in $id status ($status) $progress');
final send = IsolateNameServer.lookupPortByName('downloader_send_port');
@ -170,6 +158,14 @@ class DownloadState extends ChangeNotifier {
taskId: task.taskId, shouldDeleteContent: true);
await dbHelper.delDownloaded(episode.enclosureUrl);
} else {
if (episode.enclosureUrl == episode.mediaId) {
var filePath =
'file://${path.join(task.savedDir, Uri.encodeComponent(task.filename))}';
var fileStat =
await File(path.join(task.savedDir, task.filename)).stat();
await dbHelper.saveMediaId(
episode.enclosureUrl, filePath, task.taskId, fileStat.size);
}
_episodeTasks.add(EpisodeTask(episode, task.taskId,
progress: task.progress, status: task.status));
}
@ -286,17 +282,19 @@ class DownloadState extends ChangeNotifier {
Future pauseTask(EpisodeBrief episode) async {
var task = episodeToTask(episode);
await FlutterDownloader.pause(taskId: task.taskId);
if (task.progress > 0) {
await FlutterDownloader.pause(taskId: task.taskId);
}
notifyListeners();
}
Future resumeTask(EpisodeBrief episode) async {
var task = episodeToTask(episode);
var newTaskId = await FlutterDownloader.resume(taskId: task.taskId);
await FlutterDownloader.remove(taskId: task.taskId);
var index = _episodeTasks.indexOf(task);
_removeTask(episode);
FlutterDownloader.remove(taskId: task.taskId);
var dbHelper = DBHelper();
_episodeTasks.insert(index, EpisodeTask(episode, newTaskId));
_episodeTasks[index] = task.copyWith(taskId: newTaskId);
notifyListeners();
await dbHelper.saveDownloaded(episode.enclosureUrl, newTaskId);
}
@ -305,9 +303,8 @@ class DownloadState extends ChangeNotifier {
var newTaskId = await FlutterDownloader.retry(taskId: task.taskId);
await FlutterDownloader.remove(taskId: task.taskId);
var index = _episodeTasks.indexOf(task);
_removeTask(episode);
var dbHelper = DBHelper();
_episodeTasks.insert(index, EpisodeTask(episode, newTaskId));
_episodeTasks[index] = task.copyWith(taskId: newTaskId);
notifyListeners();
await dbHelper.saveDownloaded(episode.enclosureUrl, newTaskId);
}

View File

@ -0,0 +1,25 @@
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:equatable/equatable.dart';
import 'episodebrief.dart';
class EpisodeTask extends Equatable {
final String taskId;
final EpisodeBrief episode;
int progress;
DownloadTaskStatus status;
EpisodeTask(
this.episode,
this.taskId, {
this.progress = 0,
this.status = DownloadTaskStatus.undefined,
});
EpisodeTask copyWith({String taskId}) {
return EpisodeTask(episode, taskId ?? this.taskId,
progress: progress, status: status);
}
@override
List<Object> get props => [taskId];
}

View File

@ -947,10 +947,10 @@ class DownloadPainter extends CustomPainter {
var center = Offset(size.width / 2, size.height / 2);
if (pauseProgress == 0) {
canvas.drawLine(
Offset(width / 2, 2), Offset(width / 2, height * 4 / 5), _paint);
canvas.drawLine(Offset(width / 5, height / 2),
Offset(width / 2, 4), Offset(width / 2, height * 4 / 5), _paint);
canvas.drawLine(Offset(width / 4, height / 2),
Offset(width / 2, height * 4 / 5), _paint);
canvas.drawLine(Offset(width * 4 / 5, height / 2),
canvas.drawLine(Offset(width * 3 / 4, height / 2),
Offset(width / 2, height * 4 / 5), _paint);
}
@ -972,13 +972,15 @@ class DownloadPainter extends CustomPainter {
if (pauseProgress > 0) {
canvas.drawLine(
Offset(width / 5 + height * 3 * pauseProgress / 20,
height / 2 - height * 3 * pauseProgress / 10),
Offset(width / 2 - height * 3 * pauseProgress / 20, height * 4 / 5),
height / 2 - height * pauseProgress / 5),
Offset(width / 2 - height * 3 * pauseProgress / 20,
height * 4 / 5 - height * pauseProgress / 10),
_paint);
canvas.drawLine(
Offset(width * 4 / 5 - height * 3 * pauseProgress / 20,
height / 2 - height * 3 * pauseProgress / 10),
Offset(width / 2 + height * 3 * pauseProgress / 20, height * 4 / 5),
height / 2 - height * pauseProgress / 5),
Offset(width / 2 + height * 3 * pauseProgress / 20,
height * 4 / 5 - height * pauseProgress / 10),
_paint);
}
}

View File

@ -150,7 +150,7 @@ class EpisodeGrid extends StatelessWidget {
shape: BoxShape.circle,
),
child: Icon(
Icons.done_all,
Icons.arrow_downward,
size: 15,
color: Colors.white,
),