Untitled

 avatar
unknown
plain_text
a month ago
60 kB
4
Indexable
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'dart:ui';

import 'package:animated_read_more_text/animated_read_more_text.dart';
import 'package:bccm_player/bccm_player.dart';
import '../extensions/common.dart';
import '../extensions/extension_util/bool_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';

import '/../extensions/extension_util/context_extensions.dart';
import '/../extensions/extension_util/list_extensions.dart';
import '/../extensions/extension_util/string_extensions.dart';
import '/../extensions/loader_widget.dart';
import '/../screens/pdf_view_screen.dart';
import '/../utils/app_colors.dart';
import '../components/video_list_component.dart';
import '../extensions/LiveStream.dart';
import '../extensions/animatedList/animated_list_view.dart';
import '../extensions/app_button.dart';
import '../extensions/constants.dart';
import '../extensions/decorations.dart';
import '../extensions/extension_util/device_extensions.dart';
import '../extensions/extension_util/int_extensions.dart';
import '../extensions/extension_util/widget_extensions.dart';
import '../extensions/read_more_text.dart';
import '../extensions/shimmer/TopicShimmer.dart';
import '../extensions/system_utils.dart';
import '../extensions/text_styles.dart';
import '../main.dart';
import '../model/downloaded_book.dart';
import '../model/video_file_response.dart';
import '../model/video_list_model.dart';
import '../model/workout_list_model.dart';
import '../network/rest_api.dart';
import '../utils/app_common.dart';
import '../utils/app_constants.dart';
import '../utils/database_helper.dart';
import '../utils/responsive_widget.dart';
import 'BccmPlayerScreen.dart';
import 'choose_plan_screen.dart';

class VideoDetailScreen extends StatefulWidget {
  final int? id;
  final int? categoryId;
  final int? offset;
  final String? orderBy;
  final String? slug;
  final bool? isProgram;
  final bool? isUpNext;
  final int? programId;
  final bool? isTagShow;
  Map? param;
  int? upNextFlag;
  bool? isPurchase = false;
  bool? isFromInstructor = false;
  int? instructorId;
  int? day;
  bool? isFromWatchHistory = false;
  bool? isFromProgram = false;
  Map? paramForVideoDetail;
  int? dayForVideoProgress;

  VideoDetailScreen(
      {this.id,
      this.offset,
      this.isUpNext = true,
      this.orderBy,
      this.categoryId,
      this.isProgram = false,
      this.programId,
      this.slug,
      this.isTagShow = false,
      this.param,
      this.upNextFlag,
      this.isPurchase,
      this.isFromInstructor,
      this.instructorId = 0,
      this.day,
      this.isFromWatchHistory,
      this.isFromProgram,
      required this.paramForVideoDetail,
      this.dayForVideoProgress});

  @override
  State<VideoDetailScreen> createState() => _VideoDetailScreenState();
}

class _VideoDetailScreenState extends State<VideoDetailScreen> {
  ScrollController scrollController = ScrollController();

  VideoListModel? mVideoData;

  int? bufferDelay;
  int offset = 1;

  List<VideoFileModel>? mVideoFileList = [];
  List<VideoListModel>? upcomingVideo = [];
  List<ProgramVideo>? dayWiseProgramList = [];
  List<DownloadedBook> books = [];
  List<DownloadedBook> offlineBooks = [];

  String? mVideoUrl, quality, format, mDownloandURL;
  bool? mDownloadCheck = false;
  String time = "";
  String minutes = "";
  String path = "";
  bool? dowloading = false;
  int? progress = 0;
  bool isShimmerLoading = true;
  bool isLastPage = false;
  bool? isFirstTime;
  final dbHelper = DatabaseHelper.instance;
  DownloadedBook? mSampleDownloadTask;
  bool isToCallAPiOnScroll = true;

  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  ReceivePort port = ReceivePort();
  late GlobalKey<SimplePlayerState> playerKey = GlobalKey<SimplePlayerState>();
  late ValueNotifier<String> videoUrlNotifier;

  @override
  void initState() {
    appStore.mDownloadTaskStatus = DownloadTaskStatus.undefined;
    log("app store download" + appStore.isDownloadingList.toString() + "${widget!.day}");
    urlPlaying = "";
    init();
    _bindBackgroundIsolate();

    scrollController.addListener(() {
      if (scrollController.position.pixels == scrollController.position.maxScrollExtent && !appStore.isLoading) {
        isLastPage = true;
        offset = upcomingVideo!.length + widget.offset!.toInt();
        print("----------offset${widget.upNextFlag}-----------${offset}");
        appStore.setLoading(true);
        print("getupnextData called ${offset}");
        if (isToCallAPiOnScroll == true) {
          print("----------isToCallAPiOnScroll ${isToCallAPiOnScroll}");

          if (widget!.instructorId == 0) {
            getUpNextData(isFromScroll: true);
          } else {
            getFilterInstructionVideoListNextData(isPassOffset: true);
          }
        }
      }
    });
    super.initState();
  }

  Future<void> getFilterInstructionVideoListNextData({isPassOffset = false}) async {
    print("-------------------KBinstructor id${widget.instructorId}");
    appStore.setLoading(true);
    await getFilterInstructionVideoList(id: widget.instructorId, offset: offset, isPassOffset: isPassOffset).then((value) {
      if (value.data != null && (value.data!.isNotEmpty && value.data!.length > 0)) {
        print("--------------------------getFilterInstructionVideoList${widget.instructorId}---${offset}");
        Iterable it = value.data!;
        it.map((e) {
          upcomingVideo!.add(e);
        }).toList();
        offset = upcomingVideo!.length + 1;
        if (value.data!.isEmpty) {
          isLastPage = true;
        }
      } else {
        isToCallAPiOnScroll = false;
      }
      appStore.setLoading(false);
      if (mounted) {
        setState(() {});
      }
    });
  }

  _bindBackgroundIsolate() async {
    log('DownloadsController - _bindBackgroundIsolate called');
    final isSuccess = IsolateNameServer.registerPortWithName(
      port.sendPort,
      'downloader_send_port',
    );

    log('_bindBackgroundIsolate - isSuccess = $isSuccess');

    if (!isSuccess) {
      _unbindBackgroundIsolate();
      _bindBackgroundIsolate();
      return;
    } else {
      port.listen((message) {
        if (message[1] == 2 || message[1] == 6) {
          print("progress");
          LiveStream().emit(DOWNLOAD_PROGRESS, message);
          progress = message[2];

          if (mounted) {
            setState(() {});
          }
        }
        if (message[1] == 3) {
          LiveStream().emit(DOWNLOAD_PROGRESS, message);
          checkDownload();
        }
      });
      await FlutterDownloader.registerCallback(downloadCallback);
    }
  }

  void _unbindBackgroundIsolate() {
    log('DownloadsController - _unbindBackgroundIsolate called');
    IsolateNameServer.removePortNameMapping('downloader_send_port');
  }

  @pragma('vm:entry-point')
  static downloadCallback(String id, int status, int percent) {
    log("DownloadsControllerr - registerCallback - task id = $id, status = $status, progress = $percent");

    final SendPort? send = IsolateNameServer.lookupPortByName('downloader_send_port');
    send!.send([id, status, percent]);
  }

  Future<void> checkDownload() async {
    if (mVideoData != null) {
      progress = 0;

      books = await dbHelper.queryRowBook(mVideoData!.id.toString());
      String? mTask;

      for (int i = 0; i < books.length; i++) {
        if (mVideoData!.id == books[i].video_id) {
          mTask = books[i].taskId;
          break;
        }
      }

      List<DownloadTask>? getTasks = await FlutterDownloader.loadTasks();
      getTasks!.forEach((element) {
        if (element.taskId == mTask) {
          print(" _task.status------" + element.status.toString());
          appStore.mDownloadTaskStatus = element.status;
        }
      });

      if (mounted) {
        setState(() {});
      }
    }
  }

  void loadBookFromOffline() async {
    if (mVideoData != null) {
      DownloadedBook? sampleBook;
      var sampleTask;
      List<DownloadedBook> list = await dbHelper.queryRowBook(mVideoData!.id.toString());

      List<DownloadTask>? tasks = await FlutterDownloader.loadTasks();
      if (list != null && list.isNotEmpty) {
        list.forEach((book) {
          sampleBook = book;
          sampleTask = tasks!.firstWhere((task) => task.taskId == book.taskId);
        });
      }
      if (sampleTask == null) {
        sampleTask = defaultTask(mDownloandURL.validate());
      }
      if (sampleBook == null) {
        String path1 = (isAndroid ? (await getTemporaryDirectory()).path : (await getApplicationDocumentsDirectory()).path) +
            "/" +
            mVideoData!.title.validate() +
            ".mp4";
        sampleBook = defaultBook(mVideoData!, minutes, path1, mDownloandURL);
      }
      sampleBook!.mDownloadTask = sampleTask;
      sampleBook!.status = sampleTask.status;
      mSampleDownloadTask = sampleBook;
    }
  }

  readBook(context) async {
    print("video type=========================" + format.toString());
    String type = format != "pdf" ? ".mp4" : ".pdf";
    log(mDownloandURL);
    final String? taskId = await FlutterDownloader.enqueue(
      url: mDownloandURL.validate(),
      savedDir: isAndroid ? (await getTemporaryDirectory()).path : (await getApplicationDocumentsDirectory()).path,
      fileName: mVideoData!.title.toString().validate() + type,
      showNotification: false,
      openFileFromNotification: true,
    );
    String path1 =
        (isAndroid ? (await getTemporaryDirectory()).path : (await getApplicationDocumentsDirectory()).path) + "/" + mVideoData!.title! + type;

    mSampleDownloadTask!.taskId = taskId;
    mSampleDownloadTask!.status = DownloadTaskStatus.running;
    mSampleDownloadTask!.download_status = 0;
    mSampleDownloadTask!.progress = 0;
    mSampleDownloadTask!.video_id = mVideoData!.id;
    mSampleDownloadTask!.video_path = path1;
    mSampleDownloadTask!.pdf_url = path1;
    mSampleDownloadTask!.video_url = mDownloandURL;
    mSampleDownloadTask!.name = mVideoData!.title;
    mSampleDownloadTask!.description = mVideoData!.description;

    appStore.setDownloadList(mVideoData!.id.validate());
    await dbHelper.insert(mSampleDownloadTask);
    appStore.mDownloadTaskStatus = DownloadTaskStatus.running;
    setState(() {});
  }

  @override
  void dispose() {
    print("-------------KB DISPOSE CALLED");
    super.dispose();
  }

  Future<void> init() async {
    print("---------initcalled");
    isShimmerLoading = true;
    try {
      if (mounted) {
        setState(() {});
      }
    } on Exception catch (e) {
      // TODO
    }
    offset = widget.offset.validate();
    printBodyFXLog(message: "SK:::: Video id: ${widget.id}");

    await getVideoDetails(widget.id, param: widget.paramForVideoDetail).then((value) async {
      mVideoData = value.newData!;
      print("-------------video data" + mVideoData!.toJson().toString());

      if (!mVideoData!.duration!.formatted.isEmptyOrNull) {
        var str = mVideoData!.duration!.formatted.validate().split(":");
        String hrs = str[0];
        String min = str[1];
        String sec = str[2];
        minutes = str[1];
        if (hrs != "00") {
          time += hrs.toString() + ":" + min.toString() + ":" + sec.toString();
        } else {
          time += min.toString() + ":" + sec.toString();
        }
      }
      await getVideoFile(videoId: mVideoData!.id.validate()).then((value) {
        mVideoFileList = value.data;
        mVideoFileList.forEachIndexed((element, index) {
          if (value.data![index].format == "mp4") {
            if (value.data![index].quality == "720p") {
              if (!value.data![index].videoSourceHref.isEmptyOrNull) {
                mDownloandURL = value.data![index].videoSourceHref;
                mDownloadCheck = true;
                format = value.data![index].format.validate();
              } else {
                if (!value.data![index].url.isEmptyOrNull) {
                  mDownloandURL = value.data![index].url;
                  mDownloadCheck = true;
                  format = value.data![index].format.validate();
                }
              }
            }
          }
        });
        int index = value.data!.indexWhere((item) => item.format == 'm3u8');
        if (index >= 0) {
          if (value.data![index].format == "m3u8") {
            print("test ${index}-------${value.data![index].format}");
            if (!value.data![index].url.isEmptyOrNull) {
              mVideoUrl = value.data![index].url.validate();
              videoUrlNotifier = ValueNotifier<String>(mVideoUrl.toString());
              quality = value.data![index].quality.validate();
            }
          }
        } else {
          for (int i = 0; i < value.data!.length; i++) {
            if (value.data![i].format == "m3u8") {
              print("test ${i}-------${value.data![i].format}");
              if (!value.data![i].url.isEmptyOrNull) {
                mVideoUrl = value.data![i].url.validate();
                videoUrlNotifier = ValueNotifier<String>(mVideoUrl.toString());
                quality = value.data![i].quality.validate();
                break;
              }
            } else if (value.data![i].format == "mp4") {
              if (!value.data![i].videoSourceHref.isEmptyOrNull) {
                mVideoUrl = value.data![i].videoSourceHref.validate();
                videoUrlNotifier = ValueNotifier<String>(mVideoUrl.toString());
                print("test else if ${i}-------${value.data![i].format}----------${mVideoUrl}");
                quality = value.data![i].quality.validate();
              } else {
                mVideoUrl = value.data![i].url.validate();
                print("else ${i} ${value.data![i].format}-------mVideo url${mVideoUrl}");
                videoUrlNotifier = ValueNotifier<String>(mVideoUrl.toString());
                quality = value.data![i].quality.validate();
              }
              break;
            } else {
              print("${value.data![i]}-------${value.data![i].format}----------${mVideoUrl}");
              if (!value.data![i].videoSourceHref.isEmptyOrNull) {
                if (value.data![i].quality == "720p") {
                  mVideoUrl = value.data![i].videoSourceHref.validate();
                  videoUrlNotifier = ValueNotifier<String>(mVideoUrl.toString());
                  quality = value.data![i].quality.validate();
                } else {
                  mVideoUrl = value.data![i].videoSourceHref.validate();
                  videoUrlNotifier = ValueNotifier<String>(mVideoUrl.toString());
                  quality = value.data![i].quality.validate();
                }
              }
              break;
            }
          }
        }
        print("---------------mVideoUrl update${mVideoUrl}");
        print("mDownloandURL--->" + mDownloandURL.toString());
        log("video file -----${mVideoUrl}");
      });

      books = await dbHelper.queryRowBook(mVideoData!.id.toString());
      String? mTask;

      for (int i = 0; i < books.length; i++) {
        if (mVideoData!.id == books[i].video_id) {
          mTask = books[i].taskId;
          print("Id Match");
          break;
        }
      }

      List<DownloadTask>? getTasks = await FlutterDownloader.loadTasks();

      for (int i = 0; i < getTasks!.length; i++) {
        if (getTasks[i].taskId == mTask) {
          appStore.mDownloadTaskStatus = getTasks[i].status;
          progress = getTasks[i].progress;
          break;
        } else {
          appStore.mDownloadTaskStatus = DownloadTaskStatus.undefined;
        }
      }
      loadBookFromOffline();
      if (widget.isFromInstructor == true) {
        getFilterInstructionVideoListNextData(isPassOffset: true);
      } else {
        getUpNextData();
      }
      if (Platform.isAndroid && mVideoData!.type != "pdf" && !mVideoUrl.isEmptyOrNull) {
        // initializePlayer();
      }
      print("appStore.mDownloadTaskStatus" + appStore.mDownloadTaskStatus.toString());
      isShimmerLoading = false;
      if (mounted) {
        setState(() {});
      }
      //   print("progress---; " + mVideoUrl.toString());
    }).catchError((e, s) {
      print("Error----" + e.toString() + "STACK::::$s");
      isShimmerLoading = false;
      setState(() {});
    });
    // if (mVideoData!.isAvailable == true) {
    offlineBooks = await dbHelper.queryAllRows();
    log("----- offline ${offlineBooks.length}");

    // }
  }

  Future<void> getUpNextData({bool? isFromScroll = false}) async {
    if (widget.isUpNext == true) {
      print("---------------- param ${widget.param}");
      await getUpNextVideoList(
              page: offset,
              sortItem: widget.orderBy,
              id: widget.categoryId,
              isProgram: widget.isProgram,
              programId: widget.programId,
              slug: widget.slug,
              upNextFlag: widget.upNextFlag,
              param: widget.param,
              isPurchase: widget.isPurchase)
          .then((value) {
        print("=============value showtag ${value.showDayTag}---------${offset}");
        if (value.data != null && (value.data!.isNotEmpty && value.data!.length > 0)) {
          Iterable it = value.data!;
          it.map((e) {
            upcomingVideo!.add(e);
            // widget.param!["offset"] = upcomingVideo!.length;
          }).toList();
          print("---------------------currnt offset value${widget.param!["offset"]}");
          print("-------------------------videoLenght${upcomingVideo!.length}");
          widget.param!["offset"] = upcomingVideo!.length + (widget.param?["offset"] ?? 0);
          print("---------------------new offset value${widget.param!["offset"]}");
          print("---------------${widget.param!["offset"] = upcomingVideo!.length + offset}");
        } else if (value.dayWiseVideoList != null && (value.dayWiseVideoList!.isNotEmpty && value.dayWiseVideoList!.length > 0)) {
          bool isContain = false;
          Iterable it = value.dayWiseVideoList!;
          if (!isFromScroll.validate()) {
            dayWiseProgramList!.clear();
          }

          final existingItems = dayWiseProgramList!.toSet();

          it.forEach((e) {
            if (!existingItems.contains(e)) {
              dayWiseProgramList!.add(e);
            } else {
              isContain = true;
            }
          });

          try {
            if (isFromScroll.validate()) {
              print("------------------upcoming list day wise${dayWiseProgramList!.length}");
              widget.param!["day"] = dayWiseProgramList![dayWiseProgramList!.length - 1].day;
              widget.param!["video_id"] = dayWiseProgramList![dayWiseProgramList!.length - 1]
                  .video![dayWiseProgramList![dayWiseProgramList!.length - 1].video!.length - 1]
                  .id;
              print("----------------KRUTI${widget.param!["day"]}---------${widget.param!["video_id"]}");
            }
          } catch (e) {
            print("--------------error to set pagiantion${e.toString()}");
          }
          if (isContain) {
/*
            call this because when first time reach at scroll position it get same list as shown in ui so data not added in list and loading gives no changes in ui so call it for next data.
*/
            getUpNextData(isFromScroll: isFromScroll);
          }
        } else {
          isToCallAPiOnScroll = false;
        }

        appStore.setLoading(false);
        if (mounted) {
          setState(() {});
        }
      }).catchError((error, stack) {
        print("stack trss");
        print(stack);
        print("--------------${error.toString()}");
        appStore.setLoading(false);
        if (mounted) {
          setState(() {});
        }
      });
    }
  }

  Future<void> storeData(String id, int? progress, DownloadTaskStatus status) async {
    if (status == DownloadTaskStatus.complete) {
      appStore.removeDownloadList(mVideoData!.id.validate());

      books = await dbHelper.queryRowBook(mVideoData!.id.toString());
      String? mTask;

      for (int i = 0; i < books.length; i++) {
        print("All data-------------" + books[i].toJson().toString());
        print("mVideoData!.id" + mVideoData!.id.toString());
        print("mVideoData!.id" + books[i].video_id.toString());
        if (mVideoData!.id == books[i].video_id) {
          mTask = books[i].taskId;
          print("hello");
          break;
        }
      }
      print(mVideoData!.id);
      print("task id new------" + mTask.toString());
      List<DownloadTask>? getTasks = await FlutterDownloader.loadTasks();
      for (int i = 0; i < getTasks!.length; i++)
        if (getTasks[i].taskId == mTask) {
          appStore.mDownloadTaskStatus = getTasks[i].status;
          break;
        } else {
          appStore.mDownloadTaskStatus = DownloadTaskStatus.undefined;
        }
      print(" appStore.mDownloadTaskStatus" + appStore.mDownloadTaskStatus.toString());

      loadBookFromOffline();
      appStore.setLoading(false);
      setState(() {});
    }
    if (status == DownloadTaskStatus.failed || status == DownloadTaskStatus.canceled || status == DownloadTaskStatus.paused) {
      appStore.setLoading(false);
    }
  }

  bool? isLandscape;

  Widget mBtnWidget({IconData? img, String? value}) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Icon(img),
        2.height,
        Text(value.validate(), style: primaryTextStyle(context, size: 12)),
      ],
    );
  }

  Future<void> deleteFile(File file) async {
    try {
      if (await file.exists()) {
        await file.delete();
      }
    } catch (e) {
      // Error in getting access to the file.
    }
  }

  Future<void> setBookmark(int? id) async {
    appStore.setLoading(true);
    Map req = {"video_id": id};
    await setBookmarkVideo(req).then((value) {
      if (mVideoData!.isBookmark == 1) {
        mVideoData!.isBookmark = 0;
      } else {
        mVideoData!.isBookmark = 1;
      }
      toast(value.message);
      LiveStream().emit(LIBRARY);
      appStore.setLoading(false);
      setState(() {});
    }).catchError((e) {
      appStore.setLoading(false);
      setState(() {});
    });
  }

  Future<void> setBookmark1(int? id, int index) async {
    appStore.setLoading(true);
    Map req = {"video_id": id};
    await setBookmarkVideo(req).then((value) {
      appStore.setLoading(false);
      if (upcomingVideo![index].isBookmark == 1) {
        upcomingVideo![index].isBookmark = 0;
      } else {
        upcomingVideo![index].isBookmark = 1;
      }
      LiveStream().emit(LIBRARY);
      toast(value.message);
      appStore.setLoading(false);
      setState(() {});
    }).catchError((e) {
      appStore.setLoading(false);
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    print("SCREEN_REFRESH");
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          automaticallyImplyLeading: false,
          leading: Icon(Icons.arrow_back).onTap(() {
            Navigator.pop(context, true);
          }),
          actions: [
            Padding(
              padding: EdgeInsets.only(right: 16),
              child: CastButton(color: Colors.red),
            ),
          ],
        ),
        body: Stack(
          children: [
            if (mVideoData != null && !isShimmerLoading)
              Column(
                children: [
                  mVideoData!.type == "pdf"
                      ? Stack(
                          children: [
                            AspectRatio(
                              aspectRatio: 16 / 9,
                              child: cachedImage(mVideoData!.thumbnailLarge.validate(), fit: BoxFit.fill).cornerRadiusWithClipRRect(0),
                            ),
                            Positioned(
                              bottom: 16,
                              left: 16,
                              child: Container(
                                decoration: boxDecorationWithRoundedCorners(borderRadius: radius(8), backgroundColor: Colors.black38),
                                padding: EdgeInsets.all(8),
                                child: Row(
                                  children: [
                                    const Icon(Icons.play_arrow, size: 18),
                                    4.width,
                                    Text("View PDF", style: primaryTextStyle(context, color: Colors.white)),
                                  ],
                                ),
                              ).onTap(() {
                                if (mVideoData!.is_accessiable == false) {
                                  ChoosePlanScreen().launch(context);
                                } else {
                                  PDFViewScreen(mURL: mVideoData!.pdf_url.validate()).launch(context);
                                }
                              }),
                            )
                          ],
                        )
                      : Stack(
                          children: [
                            AspectRatio(
                              aspectRatio: ResponsiveWidget.isMediumScreen(context) ? 16 / 9 : 16 / 9,
                              child: mVideoData!.is_accessiable == false
                                  ? Stack(
                                      alignment: Alignment.center,
                                      children: [
                                        cachedImage(mVideoData!.thumbnailLarge.validate(), width: context.width(), fit: BoxFit.fill)
                                            .cornerRadiusWithClipRRect(0),
                                        Icon(AntDesign.playcircleo, size: 30).center()
                                      ],
                                    )
                                  : mVideoUrl.isEmptyOrNull
                                      ? AspectRatio(
                                          aspectRatio: 16 / 9,
                                          child: cachedImage(mVideoData!.thumbnailLarge.validate(), width: context.width(), fit: BoxFit.fill)
                                              .cornerRadiusWithClipRRect(0))
                                      : ValueListenableBuilder(
                                          valueListenable: videoUrlNotifier,
                                          builder: (context, videoUrl, child) {
                                            print("------------value notifier123 day ${widget.day}-----${videoUrlNotifier.value}");
                                            return SimplePlayer(
                                                key: ValueKey(videoUrl),
                                                id: widget.id,
                                                urlString: mVideoUrl,
                                                videoListModel: mVideoData,
                                                name: mVideoData!.title.validate(),
                                                images: mVideoData!.thumbnailLarge,
                                                programId: widget.programId,
                                                upNextFlag: widget.upNextFlag,
                                                dayForVideoProgress: widget.dayForVideoProgress != null ? widget.dayForVideoProgress! : 0,
                                                day: widget.upNextFlag == 1
                                                    ? widget.day
                                                    : (widget.isFromWatchHistory == true && widget.day != 0)
                                                        ? widget.day
                                                        : -1);
                                          }),
                            ),
                          ],
                        ),
                  CustomScrollView(
                    controller: scrollController,
                    physics: BouncingScrollPhysics(),
                    slivers: <Widget>[
                      SliverList(
                        delegate: SliverChildBuilderDelegate(
                          (BuildContext context, int index) {
                            return Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                16.height,
                                Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    Text(mVideoData!.title.validate(), style: boldTextStyle(context, size: 24)),
                                    8.height,
                                    Text(minutes.validate() + ' m', style: secondaryTextStyle(context))
                                        .visible(!isShimmerLoading && !minutes.isEmptyOrNull),
                                    if (mVideoData!.is_accessiable == false)
                                      AppButton(
                                        text: "Start free trial",
                                        margin: EdgeInsets.only(bottom: 8, top: 16),
                                        width: context.width(),
                                        color: primaryColor,
                                        onTap: () {
                                          ChoosePlanScreen().launch(context);
                                        },
                                      ),
                                    8.height,
                                    ReadMoreText(
                                      parseHtmlString(mVideoData!.description.validate()),
                                      trimMode: TrimMode.Line,
                                      trimLines: 3,
                                      colorClickableText: primaryColor,
                                      trimCollapsedText: ' Show more',
                                      trimExpandedText: ' Show less',
                                      style: primaryTextStyle(context, size: 16, color: descriptionColor, height: 1.4),
                                    ),
                                    if (mVideoData != null && !mVideoData!.description.isEmptyOrNull)
                                      AnimatedReadMoreText(
                                        parseHtmlString(mVideoData!.description.validate()),
                                        animationCurve: Curves.easeInOut,
                                        readMoreText: '...Show more',
                                        expandOnTextTap: true,
                                        textStyle: primaryTextStyle(context, size: 16, color: descriptionColor, height: 1.4),
                                        readLessText: ' Show less',
                                        maxLines: 3,
                                        buttonTextStyle: primaryTextStyle(context, color: primaryColor),
                                        animationDuration: Duration(milliseconds: 500),
                                      ).paddingOnly(left: 16, right: 16, top: 8).visible(mVideoData!.description.validate().isEmptyOrNull),
                                  ],
                                ).paddingSymmetric(horizontal: 16),
                                20.height,
                                Row(
                                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                  children: [
                                    mBtnWidget(
                                      img: mVideoData!.isBookmark == 1 ? MaterialCommunityIcons.playlist_check : MaterialCommunityIcons.playlist_plus,
                                      value: mVideoData!.isBookmark == 1
                                          ? ''
                                              'Remove from list'
                                          : "Add to list",
                                    ).onTap(() {
                                      setBookmark(mVideoData!.id.validate());
                                    }),
                                    mBtnWidget(img: MaterialCommunityIcons.share, value: "Share").onTap(() {
                                      String? mShareURL =
                                          shareUrl() + "/videos/" + mVideoData!.id.validate().toString() + "/" + mVideoData!.url.toString();
                                      Share.share(
                                        'I\'m watching ${mVideoData!.title.validate()} on Body FX Home Fitness\n$mShareURL',
                                      );
                                    }),
                                    if (mDownloadCheck == true)
                                      appStore.mDownloadTaskStatus == DownloadTaskStatus.failed ||
                                              appStore.mDownloadTaskStatus == DownloadTaskStatus.canceled
                                          ? mBtnWidget(img: MaterialCommunityIcons.reload, value: "Re-download").onTap(() async {
                                              await FlutterDownloader.remove(taskId: mSampleDownloadTask!.taskId.validate());
                                              await deleteFile(File(mSampleDownloadTask!.video_path.validate()));
                                              log("app store download" + appStore.isDownloadingList.toString());
                                              await appStore.removeDownloadList(mSampleDownloadTask!.video_id.validate().toInt());
                                              await dbHelper.delete(mSampleDownloadTask!.video_id.validate()).then((value) {});

                                              if (mVideoData!.is_accessiable == false) {
                                                ChoosePlanScreen().launch(context);
                                              } else {
                                                if (offlineBooks.length >= 10) {
                                                  toast(
                                                      'You have reached your offline download limit, remove items from your offline library to download this item.');
                                                } else if (appStore.isDownloadingList!.contains(mVideoData!.id)) {
                                                  toast('Video is downloading in queue');
                                                } else {
                                                  if (mVideoData!.type == "pdf") {
                                                    if (!mVideoData!.pdf_url.validate().isEmptyOrNull) {
                                                      readBook(context);
                                                    }
                                                  } else {
                                                    if (!mDownloandURL.isEmptyOrNull) {
                                                      // _initializeNotifications();
                                                      readBook(context);
                                                    }
                                                  }
                                                }
                                              }
                                            })
                                          : ((appStore.mDownloadTaskStatus == DownloadTaskStatus.running ||
                                                      appStore.mDownloadTaskStatus == DownloadTaskStatus.enqueued) &&
                                                  progress! < 100)
                                              ? Column(
                                                  crossAxisAlignment: CrossAxisAlignment.center,
                                                  children: [
                                                    Container(
                                                      padding: EdgeInsets.all(10),
                                                      height: 30,
                                                      width: 30,
                                                      child: CircularProgressIndicator(
                                                        strokeWidth: 2,
                                                        valueColor: AlwaysStoppedAnimation(
                                                          defaultLoaderAccentColorGlobal ?? Theme.of(context).colorScheme.secondary,
                                                        ),
                                                      ),
                                                    ).center(),
                                                    Text(progress != null ? "$progress%" : "0%", style: primaryTextStyle(context, size: 12)),
                                                  ],
                                                )
                                              : mBtnWidget(
                                                      img: books.isNotEmpty ? MaterialIcons.file_download_done : Feather.download, value: "Download")
                                                  .onTap(() async {
                                                  if (mVideoData!.is_accessiable == false) {
                                                    ChoosePlanScreen().launch(context);
                                                  } else {
                                                    if (books.isNotEmpty) {
                                                      toast("Already Downloaded");
                                                    } else if (offlineBooks.length >= 10) {
                                                      toast(
                                                          'You have reached your offline download limit, remove items from your offline library to download this item.');
                                                    } else if (appStore.isDownloadingList!.contains(mVideoData!.id)) {
                                                      toast('Video is downloading in queue');
                                                    } else {
                                                      if (mVideoData!.type == "pdf") {
                                                        if (!mVideoData!.pdf_url.validate().isEmptyOrNull) {
                                                          readBook(context);
                                                        }
                                                      } else {
                                                        if (!mDownloandURL.isEmptyOrNull) {
                                                          readBook(context);
                                                        }
                                                      }
                                                    }
                                                  }
                                                }),
                                  ],
                                ),
                                12.height,
                                if (upcomingVideo != null && upcomingVideo!.isNotEmpty) Divider(endIndent: 16, thickness: 0.2, indent: 16, height: 0),
                              ],
                            );
                          },
                          childCount: 1,
                        ),
                      ),
                      if (dayWiseProgramList != null && dayWiseProgramList!.isNotEmpty)
                        SliverPersistentHeader(
                          pinned: true,
                          delegate: StickyHeaderItem(),
                        ),
                      //   if (dayWiseProgramList != null && dayWiseProgramList!.isNotEmpty)
                      SliverList(
                        delegate: SliverChildBuilderDelegate(
                          (BuildContext context, int index) {
                            return dayWiseProgramList != null && dayWiseProgramList!.isNotEmpty
                                ? AnimatedListView(
                                    padding: EdgeInsets.fromLTRB(16, 8, 8, 8),
                                    shrinkWrap: true,
                                    physics: NeverScrollableScrollPhysics(),
                                    itemCount: dayWiseProgramList!.length,
                                    itemBuilder: (BuildContext, i) {
                                      final dayData = dayWiseProgramList![i];
                                      final videos = dayData.video;
                                      return Column(
                                        children: [
                                          Column(
                                            crossAxisAlignment: CrossAxisAlignment.start,
                                            children: [
                                              Container(
                                                padding: EdgeInsets.symmetric(vertical: 6, horizontal: 10),
                                                decoration: boxDecorationWithRoundedCorners(
                                                    backgroundColor: dayWiseProgramList![i].isDayCompleted == true ? primaryColor : Colors.grey),
                                                child: Text("Day ".toUpperCase() + dayWiseProgramList![i].day.toString(),
                                                    style: secondaryTextStyle(context, color: textPrimaryColorGlobal)),
                                              ),
                                              8.height,
                                              ListView.builder(
                                                  shrinkWrap: true, // Allow nested scrolling
                                                  physics: NeverScrollableScrollPhysics(), // Disable inner scrolling
                                                  itemCount: videos!.length,
                                                  itemBuilder: (context, index) {
                                                    final videoData = videos[index];

                                                    return VideoListComponent(
                                                      mVideoData: videoData,
                                                      isFromProgram: widget.isFromProgram,
                                                      onDelete: () {
                                                        print("Day: ${dayData.day}, Video Index: $index");
                                                        setBookmark(
                                                          videoData.id,
                                                        );
                                                      },
                                                      onCall: () async {
                                                        appStore.setLoading(true);
                                                        if (mVideoUrl != null) {
                                                          var lastPosition = viewController.playerController.value.playbackPositionMs;
                                                          if ((lastPosition! / 1000) >= 30) {
                                                            var duration = minutes.isNotEmpty
                                                                ? minutes.toInt()
                                                                : ((viewController.playerController.value.currentMediaItem?.metadata!.durationMs)! /
                                                                    60000);
                                                            var watchedPercentage = (lastPosition! / 60000) / duration;
                                                            printBodyFXLog(
                                                                message:
                                                                    "lastposition ${lastPosition} duration ${duration} total duration ${watchedPercentage}");
                                                            Map req = {
                                                              "video_id": widget.id,
                                                              "last_position": (lastPosition / 1000),
                                                              "is_completed": watchedPercentage >= 0.7 ? 1 : 0,
                                                              if (widget.programId != null && widget.programId != 0) "program_id": widget.programId,
                                                              if (widget.day.validate() > 0) "day": widget.day
                                                            };
                                                            printBodyFXLog(message: "TEST request----$req");
                                                            await saveUserVideoProgressApi(req).then((v) {
                                                              appStore.setLoading(false);
                                                              printBodyFXLog(message: "TEST Response $v");
                                                            }).catchError((e) {
                                                              printBodyFXLog(message: " TEST ERROR Error $e");
                                                            });
                                                          }
                                                        }
                                                        int isShowFromVideosNoDayYes = 1;
                                                        //show from video no  DAY YES isShowFromVideosNoDayYes=1
                                                        //v1/filter-program-video-list?day=5&program_id=3&video_id=294
                                                        Map paramsIsShowFromVideosNoDayYes = {
                                                          "isProgram": true,
                                                          //  "isShowFromVideos": 0,
                                                          "endPoint": "v1/filter-program-video-list?",
                                                          // "day": "need to pass from video details screen",
                                                          "program_id": widget.programId,
                                                          "video_id": videoData.id,
                                                          "day": dayData.day,
                                                          "upNextFlag": isShowFromVideosNoDayYes,
                                                          "isPurchase": widget.isPurchase
                                                        };
                                                        print("------------------video id--------${videoData.id}----------day ${dayData.day}");
                                                        try {
                                                          await viewController.playerController.pause();
                                                        } catch (e) {}
                                                        bool res = await VideoDetailScreen(
                                                          id: videoData.id,
                                                          offset: i,
                                                          isProgram: true,
                                                          isTagShow: widget.isTagShow,
                                                          isFromProgram: widget.isFromProgram,
                                                          //isTagShow: mProgram!.programData!.showDayTag == 1,
                                                          programId: widget.programId,
                                                          upNextFlag: isShowFromVideosNoDayYes,
                                                          param: paramsIsShowFromVideosNoDayYes,
                                                          isFromInstructor: widget.isFromInstructor,
                                                          instructorId: widget.instructorId,
                                                          isPurchase: widget.isPurchase,
                                                          day: dayData.day,
                                                          dayForVideoProgress: dayData.day,
                                                          paramForVideoDetail: {"program_id": widget.programId, "day": dayData.day},
                                                        ).launch(context);
                                                        if (res = true) {
                                                          printBodyFXLog(message: "after another video play");

                                                          await Future.delayed(Duration(seconds: 1));
                                                          init();
                                                        }
                                                      },
                                                    );
                                                  })
                                            ],
                                          ),
                                        ],
                                      );
                                    })
                                : SizedBox();
                          },
                          childCount: 1,
                        ),
                      ),
                      if (upcomingVideo != null && upcomingVideo!.isNotEmpty)
                        SliverPersistentHeader(
                          pinned: true,
                          delegate: StickyHeaderItem(),
                        ),
                      // if (upcomingVideo != null && upcomingVideo!.isNotEmpty)
                      SliverList(
                        delegate: SliverChildBuilderDelegate(
                          (BuildContext context, int index) {
                            print("-----------upcoming${upcomingVideo!.length}");
                            return upcomingVideo != null && upcomingVideo!.isNotEmpty
                                ? AnimatedListView(
                                    padding: EdgeInsets.fromLTRB(16, 8, 8, 8),
                                    shrinkWrap: true,
                                    physics: NeverScrollableScrollPhysics(),
                                    itemCount: upcomingVideo!.length,
                                    itemBuilder: (BuildContext, i) {
                                      print(
                                          "-------------video detail screen ${upcomingVideo![i].id} ${upcomingVideo![i].day}-----${upcomingVideo![i].programId}");
                                      return VideoListComponent(
                                        mVideoData: upcomingVideo![i],
                                        tagIndex: widget.offset! + i + 1,
                                        isShowDayTag: widget.isTagShow,
                                        isFromProgram: widget.isFromProgram,
                                        onCall: () async {
                                          appStore.setLoading(true);
                                          if (mVideoUrl != null) {
                                            var lastPosition = viewController.playerController.value.playbackPositionMs;
                                            if ((lastPosition! / 1000) >= 30) {
                                              var duration = minutes.isNotEmpty
                                                  ? minutes.toInt()
                                                  : ((viewController.playerController.value.currentMediaItem?.metadata!.durationMs)! / 60000);
                                              var watchedPercentage = (lastPosition! / 60000) / duration;
                                              printBodyFXLog(
                                                  message: "lastposition ${lastPosition} duration ${duration} total duration ${watchedPercentage}");
                                              Map req = {
                                                "video_id": widget.id,
                                                "last_position": (lastPosition / 1000),
                                                "is_completed": watchedPercentage >= 0.7 ? 1 : 0,
                                                if (widget.programId != null && widget.programId != 0) "program_id": widget.programId,
                                                if (widget.day.validate() > 0) "day": widget.day
                                              };

                                              printBodyFXLog(message: "TEST request----$req");
                                              await saveUserVideoProgressApi(req).then((v) {
                                                appStore.setLoading(false);
                                                printBodyFXLog(message: "TEST Response $v");
                                              }).catchError((e) {
                                                printBodyFXLog(message: " TEST ERROR Error $e");
                                              });
                                            }
                                            try {
                                              viewController.playerController.pause();
                                              viewController.playerController.stop(reset: true);
                                            } on Exception catch (e) {
                                              // TODO
                                            }

                                            if (mVideoData!.is_accessiable == true && !mVideoUrl.isEmptyOrNull) {
                                              if (!viewController.playerController.isPrimary) {
                                                print("upnext video play2");
                                                viewController.dispose();
                                                viewController.playerController.dispose();
                                              }
                                            }
                                          }
                                          // finish(context);
                                          int value2 = i + widget.offset!.toInt() + 1;

                                          Map paramsShowVideoNoDayNo = {
                                            "isProgram": true,
                                            //"isShowFromVideos": 0,
                                            "endPoint": "v1/filter-program-video-list?",
                                            "program_id": widget.programId,
                                            "offset": widget.offset! + i + 1,
                                            //"offset": offset,
                                            //"upNextFlag": isShowFromVideosNoDayNO,
                                            "upNextFlag": 2,
                                            "isPurchase": widget.isPurchase,
                                          };
                                          print("------------OFFSET AT CLICk${widget.offset! + i + 1}");
                                          print(
                                              "-------------video detail screen ${upcomingVideo![i].id} ${upcomingVideo![i].day}-----${upcomingVideo![i].programId}");
                                          bool res = await VideoDetailScreen(
                                                  id: upcomingVideo![i].id,
                                                  categoryId: widget.categoryId,
                                                  orderBy: widget.orderBy,
                                                  offset: value2,
                                                  slug: widget.slug,
                                                  // programId: upcomingVideo![i].programId,
                                                  isFromProgram: widget.isFromProgram,
                                                  programId: widget.programId,
                                                  isProgram: widget.isProgram,
                                                  upNextFlag: widget.upNextFlag,
                                                  isFromInstructor: widget.isFromInstructor,
                                                  instructorId: widget.instructorId,
                                                  isPurchase: widget.isPurchase,
                                                  dayForVideoProgress: upcomingVideo![i].day,
                                                  paramForVideoDetail: {"program_id": widget.programId, "day": upcomingVideo![i].day},
                                                  param: paramsShowVideoNoDayNo)
                                              .launch(context);
                                          if (res == true) {
                                            await Future.delayed(Duration(seconds: 2));
                                            printBodyFXLog(message: "===> offset  ${widget.offset} == ${value2}");
                                            init();
                                          }
                                        },
                                        onDelete: () {
                                          setBookmark1(upcomingVideo![i].id, i);
                                        },
                                      );
                                    })
                                : SizedBox();
                          },
                          childCount: 1,
                        ),
                      )
                    ],
                  ).expand(),
                ],
              ),
            Observer(builder: (context) {
              final isLoading = appStore.isLoading;
              if (isLastPage && isToCallAPiOnScroll) {
                return Positioned(
                  bottom: 8,
                  left: 0,
                  right: 0,
                  child: Loader(color: primaryColor).visible(isLoading),
                );
              } else if (upcomingVideo == null || dayWiseProgramList == null) {
                return Loader().center().visible(isLoading);
              } else {
                return TopicShimmer().visible(isShimmerLoading);
              }
            }),
            // TopicShimmer().visible(isShimmerLoading),
          ],
        ),
      ),
    );
  }
}

class StickyHeaderItem extends SliverPersistentHeaderDelegate {
  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      width: context.width(),
      padding: EdgeInsets.fromLTRB(16, 8, 16, 16),
      color: context.scaffoldBackgroundColor,
      child: ListTile(
        contentPadding: EdgeInsets.all(0),
        title: Text("Up next", style: boldTextStyle(context)),
      ),
    );
  }

  @override
  double get maxExtent => 56.0;

  @override
  double get minExtent => 56.0;

  @override
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}
Editor is loading...
Leave a Comment