Untitled
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