Untitled
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}); }
Leave a Comment