Untitled
unknown
plain_text
a year ago
16 kB
10
Indexable
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:abcaa/components/downloadbutton.dart';
import 'package:abcaa/components/option_button_bystatus.dart';
import 'package:abcaa/components/topic/collapsed_item.dart';
import 'package:abcaa/components/topic/expanded_item.dart';
import 'package:abcaa/models/component/topic.dart';
import 'package:al_downloader/al_downloader.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:expandable/expandable.dart';
import 'package:get_storage/get_storage.dart';
class TopicItem extends StatefulWidget {
final TopicModel? model;
final List<String> downloadLinks;
final String subject;
final bool active;
final bool showHeader;
final Duration duration;
final String? totalLesson;
final String? totalDuration;
final double? progress;
final Function? downloadOnPress;
final String? formattedDuration;
final int index;
final bool last;
final Orientation orientation;
final bool available;
final String token;
final Function onTopicPressed;
final List<String> downloadKeys;
final bool isVideoDownloadExpired;
const TopicItem(
{Key? key,
required this.model,
required this.subject,
this.last = false,
required this.onTopicPressed,
this.available = true,
required this.showHeader,
required this.duration,
required this.isVideoDownloadExpired,
this.totalDuration,
this.totalLesson,
this.downloadOnPress,
required this.downloadKeys,
this.progress,
this.orientation = Orientation.portrait,
required this.downloadLinks,
required this.token,
required this.index,
this.formattedDuration,
required this.active})
: super(key: key);
@override
State<TopicItem> createState() => _TopicItem2State();
}
class _TopicItem2State extends State<TopicItem> {
double lessonDownloadProgress = 0;
ExpandableController expandableController = ExpandableController();
BatchDownloadModel? model;
DownloadStatus dlStatus = DownloadStatus.notDownloaded;
double dlProgress = 0.0;
Timer? timer;
stopDownloadSimulation() {
timer?.cancel();
}
DownloadStatus aldownloaderEquivalentToStatus(ALDownloaderStatus status) {
switch (status) {
case ALDownloaderStatus.unstarted:
return DownloadStatus.notDownloaded;
case ALDownloaderStatus.downloading:
return DownloadStatus.downloading;
case ALDownloaderStatus.succeeded:
return DownloadStatus.downloaded;
default:
return DownloadStatus.notDownloaded;
}
}
statusEquivalentToALDownloader(DownloadStatus status) {
switch (status) {
case DownloadStatus.notDownloaded:
return ALDownloaderStatus.unstarted;
case DownloadStatus.fetchingDownload:
return ALDownloaderStatus.unstarted;
case DownloadStatus.downloading:
return ALDownloaderStatus.downloading;
case DownloadStatus.downloaded:
return ALDownloaderStatus.succeeded;
default:
return ALDownloaderStatus.unstarted;
}
}
startDownloadSimulation() {
setState(() {
dlStatus = DownloadStatus.downloading;
});
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
setState(() {
if (dlStatus == DownloadStatus.downloading) {
dlProgress += 0.1;
if (dlProgress >= 1.0) {
dlStatus = DownloadStatus.downloaded;
timer.cancel();
}
}
});
});
}
void addHandlerInterfaceForBatch() {
final urls = widget.downloadLinks;
ALDownloaderBatcher.addHandlerInterface(
ALDownloaderHandlerInterface(progressHandler: (progress) {
setState(() {
model = BatchDownloadModel(
progress: progress,
status: ALDownloaderStatus.downloading,
urls: urls);
});
log('ALDownloader[Batch] | download progress = $progress, url = $urls\n');
}, succeededHandler: () {
setState(() {
model = BatchDownloadModel(
status: ALDownloaderStatus.succeeded, progress: 1, urls: urls);
});
}, failedHandler: () {
setState(() {
model = BatchDownloadModel(
progress: model?.progress ?? 0,
status: ALDownloaderStatus.failed,
urls: urls);
});
}, pausedHandler: () {
setState(() {
model = BatchDownloadModel(
progress: model?.progress ?? 0,
status: ALDownloaderStatus.paused,
urls: urls);
});
}),
urls);
}
void cancelDownload() {
ALDownloaderBatcher.cancel(widget.downloadLinks);
setState(() {
model = BatchDownloadModel(
progress: model?.progress ?? 0,
status: ALDownloaderStatus.unstarted,
urls: widget.downloadLinks);
});
}
void removeAlldownload() {
ALDownloaderBatcher.remove(widget.downloadLinks);
setState(() {
model = BatchDownloadModel(
progress: model?.progress ?? 0,
status: ALDownloaderStatus.unstarted,
urls: widget.downloadLinks);
});
}
void batchDownload() {
log('batch download pressed');
final urls = widget.downloadLinks;
List<ALDownloaderBatcherInputVO> vo = [];
for (int i = 0; i < urls.length; i++) {
final v = ALDownloaderBatcherInputVO(urls[i]);
v.headers = {
'download': widget.downloadKeys[i],
'token': GetStorage().read('accessToken'),
};
vo.add(v);
inspect(v.headers);
}
ALDownloaderBatcher.downloadUrlsWithVOs(
vo,
// handlerInterface:
// ALDownloaderHandlerInterface(progressHandler: (progress) {
// log('ALDownloader | batch | tarogo| download progress = $progress\n');
// setState(() {
// model = BatchDownloadModel(
// progress: progress,
// status: ALDownloaderStatus.downloading,
// urls: urls);
// });
// }, succeededHandler: () {
// setState(() {
// model = BatchDownloadModel(
// status: ALDownloaderStatus.succeeded, progress: 1, urls: urls);
// });
// }, failedHandler: () {
// setState(() {
// model = BatchDownloadModel(
// progress: model?.progress ?? 0,
// status: ALDownloaderStatus.failed,
// urls: urls);
// });
// }, pausedHandler: () {
// setState(() {
// model = BatchDownloadModel(
// progress: model?.progress ?? 0,
// status: ALDownloaderStatus.paused,
// urls: urls);
// });
// }),
);
}
Future<ALDownloaderStatus> checkBatchStatus() async {
var status =
await ALDownloaderBatcher.getStatusForUrls(widget.downloadLinks);
var tasks = await ALDownloaderBatcher.getTasksForUrls(widget.downloadLinks);
bool downloaded = false;
for (var element in tasks) {
log('teck | download status = ${element.status}');
log('teck | download progress = ${element.progress}');
log('teck | download url = ${element.url}');
if (element.status == ALDownloaderStatus.succeeded &&
element.progress == 1) {
downloaded = true;
}
}
return downloaded ? ALDownloaderStatus.succeeded : status;
}
Future<ALDownloaderStatus> checkTasks() async {
var tasks = await ALDownloaderBatcher.getTasksForUrls(widget.downloadLinks);
if (tasks
.every((element) => element.status == ALDownloaderStatus.succeeded)) {
return ALDownloaderStatus.succeeded;
}
if (tasks
.any((element) => element.status == ALDownloaderStatus.downloading)) {
return ALDownloaderStatus.downloading;
}
if (tasks.every((element) => element.status == ALDownloaderStatus.failed)) {
return ALDownloaderStatus.failed;
}
if (tasks.every((element) => element.status == ALDownloaderStatus.paused)) {
return ALDownloaderStatus.paused;
}
if (tasks
.every((element) => element.status == ALDownloaderStatus.unstarted)) {
return ALDownloaderStatus.unstarted;
}
return ALDownloaderStatus.unstarted;
}
Future<double> checkBatchProgress() async {
var progress =
await ALDownloaderBatcher.getProgressForUrls(widget.downloadLinks);
return progress;
}
Future<void> initialize() async {
/// ALDownloader initilize
ALDownloader.initialize();
/// Configure print
ALDownloader.configurePrint(false, frequentEnabled: false);
addHandlerInterfaceForBatch();
var status = await checkTasks();
var progress = await checkBatchProgress();
setState(() {
model = BatchDownloadModel(
status: status, progress: progress, urls: widget.downloadLinks);
});
}
@override
void initState() {
if (widget.index == 0) {
initialize();
}
super.initState();
}
@override
void didChangeDependencies() {
ScreenUtil.init(context);
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
var item = Column(
children: [
if (widget.showHeader)
Container(
padding: EdgeInsets.fromLTRB(15.w, 8.h, 15.w, 8.h),
decoration: const BoxDecoration(color: Color(0XFF262A34)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
SvgPicture.asset('images/lesson.svg'),
Text(
widget.totalLesson ?? '',
style: const TextStyle(
fontSize: 14,
color: Colors.white,
fontFamily: 'Poppins',
fontWeight: FontWeight.w400),
),
SizedBox(
width: 4.w,
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: SvgPicture.asset('images/time.svg'),
),
Text(
'${widget.totalDuration}',
style: const TextStyle(
fontSize: 14,
color: Colors.white,
fontFamily: 'Poppins',
fontWeight: FontWeight.w400),
)
],
),
Visibility(
visible: true,
child: Row(
children: [
widget.isVideoDownloadExpired
? const Text(
'Download Unavailable',
style: TextStyle(
fontFamily: 'PlusJakartaSans',
fontSize: 14,
color: Color(0XFF5861FA)),
)
: SizedBox(
width: 120,
height: 30,
child: DownloadButton(
downloadProgress: model?.progress ?? 0,
status: aldownloaderEquivalentToStatus(
model?.status ??
ALDownloaderStatus.unstarted),
onDownload: () {
batchDownload();
},
onCancel: () {
cancelDownload();
},
onOpen: () {
removeAlldownload();
}),
)
// if (model?.status == ALDownloaderStatus.unstarted)
// const Text(
// 'Download All',
// style: TextStyle(
// fontFamily: 'PlusJakartaSans',
// fontSize: 14,
// color: Color(0XFF5861FA)),
// ),
// if (model?.status == ALDownloaderStatus.succeeded)
// const Text(
// 'Downloaded',
// style: TextStyle(
// fontFamily: 'PlusJakartaSans',
// fontSize: 14,
// color: Color(0XFF898A8D)),
// ),
// Padding(
// padding: const EdgeInsets.only(left: 8.0, right: 8),
// child: StatusDisplay(
// model: model ??
// BatchDownloadModel(
// progress: 0,
// status: ALDownloaderStatus.unstarted,
// urls: widget.downloadLinks)),
// ),
],
),
)
],
),
),
Visibility(
visible: widget.showHeader,
child: Container(
color: const Color(0xff342f36),
height: 1,
)),
InkWell(
onTap: () async {
var res = await ALDownloader.getTaskForUrl(
widget.downloadLinks[widget.index]);
log(res?.url ?? '');
log(res?.file.filePath ?? '');
log(res?.status.toString() ?? '');
log(res?.file.fileName ?? '');
log(widget.downloadKeys[widget.index]);
widget.onTopicPressed();
},
child: Container(
padding: EdgeInsets.fromLTRB(15.w, 8.h, 15.w, 8.h),
decoration: BoxDecoration(
color: widget.active
? const Color(0XFF575CAA)
: const Color(0XFF262A34)),
child: ExpandableNotifier(
controller: expandableController,
child: ExpandablePanel(
theme: const ExpandableThemeData(
animationDuration: Duration.zero),
controller: expandableController,
collapsed: CollapsedItem(
index: widget.index,
model: widget.model,
progress: widget.progress,
active: widget.active,
formattedDuration: widget.formattedDuration,
),
expanded: ExpandedItem(
index: widget.index,
model: widget.model,
progress: widget.progress,
active: widget.active,
formattedDuration: widget.formattedDuration,
downloadLinks: widget.downloadLinks)),
)),
),
if (!widget.last)
Container(
color: const Color(0xff342f36),
height: 1,
),
],
);
return Material(
color: Colors.transparent,
child: item,
);
}
}
class BatchDownloadModel {
double progress = 0.0;
List<String> urls;
ALDownloaderStatus status;
BatchDownloadModel(
{required this.progress, required this.urls, required this.status});
}
Editor is loading...
Leave a Comment