Untitled

mail@pastecode.io avatar
unknown
plain_text
5 months ago
16 kB
1
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});
}
Leave a Comment