import 'dart:async'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/extensions/string_extensions.dart'; import 'package:diplomaticquarterapp/models/course/education_journey_list_model.dart' as model; import 'package:diplomaticquarterapp/pages/learning/scroll_widget.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/course_service/course_service.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class CourseList extends StatefulWidget { @override State createState() => _CourseListState(); } class _CourseListState extends State { CourseServiceProvider? _courseServiceProvider; GlobalKey _cardKey = GlobalKey(); @override void initState() { super.initState(); _courseServiceProvider = context.read(); _courseServiceProvider!.getCourses(context); } @override void dispose() { _clearData(); super.dispose(); } Future _clearData() async { await _courseServiceProvider!.postNabedJourneyData(); await _courseServiceProvider!.clearData(); } @override Widget build(BuildContext context) { return AppScaffold( isShowAppBar: false, isShowDecPage: false, showNewAppBarTitle: true, showNewAppBar: true, appBarTitle: "Learning", backgroundColor: Color(0xFFF7F7F7), onTap: () {}, body: Consumer(builder: (context, provider, child) { if (provider.nabedJourneyResponse != null) { return ListViewSeparatedExtension.separatedWithScrollListener( itemCount: provider.data!.length, itemBuilder: (context, index) { List conClass = provider.data![index].contentClasses!; model.Datum data = provider.data![index]; return Card( key: index == 0 ? _cardKey : null, margin: EdgeInsets.only(left: 20, right: 20, top: 20), shape: RoundedRectangleBorder( side: BorderSide(width: 1, color: Color(0xFFEFEFEF)), borderRadius: BorderRadius.circular(10.0), // Set your desired radius here ), child: Padding( padding: EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(10), child: CachedNetworkImage( imageUrl: conClass.first.image!.thumbUrl!, width: double.infinity, height: MediaQuery.of(context).size.height * .25, imageBuilder: (context, imageProvider) => Container( decoration: BoxDecoration( image: DecorationImage( image: imageProvider, fit: BoxFit.cover, //colorFilter: ColorFilter.mode(Colors.red, BlendMode.colorBurn), ), ), ), placeholder: (context, url) => Center(child: CircularProgressIndicator()), errorWidget: (context, url, error) => Icon(Icons.error), ), ), SizedBox(height: 20.0), Text( conClass.first.title ?? "", // "Basics of Heart", style: TextStyle( fontSize: 16.0, height: 24 / 16, color: Color(0xFF2E303A), fontWeight: FontWeight.w600, ), ), SizedBox(height: 2.0), Text( //data.date!.toIso8601String(), "Heart diseases include conditions like coronary and heart failure, often caused by factors ", style: TextStyle(fontSize: 10.0, height: 15 / 10, color: Color(0xFF575757)), ), SizedBox(height: 6.0), Text( "${data.stats!.videosReadCount} of ${data.stats!.videosCount} Watched", // conClass.first.readPercentage.toString() + "% Watched", // "2 Hours", style: TextStyle( fontSize: 10.0, height: 15 / 10, color: Color(0xFF2E303A), fontWeight: FontWeight.w600, ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Icon( Icons.play_arrow, ), Text( "${data.stats!.videosCount} Videos", // conClass.first.readPercentage.toString() + "% Watched", // "2 Hours", style: TextStyle( fontSize: 10.0, height: 15 / 10, color: Color(0xFF2E303A), fontWeight: FontWeight.w600, ), ), ], ), SizedBox( width: 8, ), Icon( Icons.arrow_right_alt, size: 18.0, color: Color(0xFF2B353E), ), ], ), ], ), ), ).onTap(() { provider.insertJourneyListData(index, true); provider.navigate(context, data.id!, conClass.first.title!, onBack: (val) { // provider.uploadStats(); provider.clear(); }); }); }, separatorBuilder: (context, index) { return SizedBox(); }, onScroll: onScroll, ); } else { return SizedBox(); } }), ); } final Set _visibleCardIds = {}; void onScroll(ScrollNotification notification, ScrollController controller, int itemCount) { double _cardHeight = _getCardSize(); if (_cardHeight > 0) { final double offset = controller.offset; final double screenHeight = MediaQuery.of(context).size.height; int firstVisibleIndex = (offset / _cardHeight).floor(); int lastVisibleIndex = ((offset + screenHeight) / _cardHeight).ceil(); Set newlyVisibleCards = {}; for (int index = firstVisibleIndex; index <= lastVisibleIndex && index < itemCount; index++) { final double cardStartOffset = index * _cardHeight; final double cardEndOffset = cardStartOffset + _cardHeight; if (cardStartOffset >= offset && cardEndOffset <= offset + screenHeight) { if (!_visibleCardIds.contains(index)) { newlyVisibleCards.add(index); _courseServiceProvider!.insertJourneyListData(index, false); } } } _visibleCardIds.addAll(newlyVisibleCards); } } double _getCardSize() { final RenderBox renderBox = _cardKey.currentContext?.findRenderObject() as RenderBox; final cardHeight = renderBox.size.height; return cardHeight; } }