import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/material.dart'; import 'package:flutter_kinetra/kt_utils/kt_string_extend.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:video_player/video_player.dart'; import 'package:visibility_detector/visibility_detector.dart'; import '../../kt_model/kt_short_video_bean.dart'; import '../../kt_widgets/kt_network_image.dart'; import '../../kt_widgets/kt_status_widget.dart'; import '../kt_routes.dart'; import 'logic.dart'; class KtExplorePage extends StatefulWidget { const KtExplorePage({super.key}); @override State createState() => _KtExplorePageState(); } class _KtExplorePageState extends State with AutomaticKeepAliveClientMixin { final logic = Get.put(KtExploreLogic()); final state = Get.find().state; @override Widget build(BuildContext context) { super.build(context); return GetBuilder( builder: (ctrl) { if (state.loadStatus == KtLoadStatusType.loadNoData || state.loadStatus == KtLoadStatusType.loadFailed) { return KtStatusWidget( type: KtErrorStatusType.nothingYet, onPressed: logic.fetchDiscoverList, ); } return Container( width: ScreenUtil().screenWidth, height: ScreenUtil().screenHeight, padding: EdgeInsets.only( top: ScreenUtil().statusBarHeight, left: 18.w, right: 18.w, ), decoration: BoxDecoration( image: DecorationImage( image: AssetImage('explore_bg.png'.ktIcon), fit: BoxFit.fill, ), ), child: Stack( clipBehavior: Clip.none, children: [ Column( children: [ SizedBox(height: 40.w), Expanded( child: EasyRefresh( controller: logic.refreshCtrl, header: MaterialHeader(), footer: MaterialFooter(), onRefresh: () => logic.fetchDiscoverList(refresh: true), child: PageView.builder( scrollDirection: Axis.vertical, itemCount: state.videoList.length, controller: logic.pageController, onPageChanged: (index) => logic.onPageChanged(index), itemBuilder: (_, index) => videoPlayerItem(index: index), ), ), ), ], ), Row( children: [ Stack( clipBehavior: Clip.none, children: [ Image.asset('ic_explore_ip.png'.ktIcon, width: 56.8.w), Positioned( top: 0.w, right: -2.w, child: Image.asset( 'ic_explore_tv.png'.ktIcon, width: 19.w, ), ), ], ), SizedBox(width: 12.w), Text( "Unlock Your Next Binge\nObsession", style: TextStyle( fontSize: 18.sp, color: Colors.black, fontStyle: FontStyle.italic, fontWeight: FontWeight.w800, ), ), ], ), ], ), ); }, ); } Widget videoPlayerItem({int index = 0}) { return GetBuilder( builder: (ctrl) { if (state.controllers.isEmpty) return Container(); final VideoPlayerController? videoPlayerController = state.controllers[index]; if (videoPlayerController == null || !videoPlayerController.value.isInitialized) { return Stack( children: [ KtNetworkImage( imageUrl: state.videoList[index].imageUrl!, width: ScreenUtil().screenWidth - 36.w, height: 540.w, fit: BoxFit.cover, borderRadius: BorderRadius.circular(16.w), ), Center(child: CircularProgressIndicator()), ], ); } KtShortVideoBean item = state.videoList[index]; return Container( margin: EdgeInsets.only(bottom: 18.w), alignment: Alignment.topCenter, child: GestureDetector( onTap: () { videoPlayerController.value.isPlaying ? videoPlayerController.pause() : videoPlayerController.play(); setState(() {}); }, child: Stack( alignment: Alignment.bottomCenter, children: [ Positioned.fill( child: VisibilityDetector( key: ValueKey( 'discover-video-${state.videoList[index].id}', ), onVisibilityChanged: (info) { if (info.visibleFraction > 0.85 && state.currentPage == index && !videoPlayerController.value.isPlaying) { videoPlayerController.play(); logic.update(); } if (info.visibleFraction < 0.09 && videoPlayerController.value.isPlaying) { videoPlayerController.pause(); logic.update(); } }, child: ClipRRect( borderRadius: BorderRadius.circular(16.w), child: SizedBox( width: ScreenUtil().screenWidth - 36.w, height: 540.w, child: VideoPlayer(videoPlayerController), ), ), ), ), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.end, children: [ Container( width: ScreenUtil().screenWidth - 56.w, margin: EdgeInsets.only(left: 12.w), child: Text( item.name ?? '', maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.w500, ), ), ), SizedBox(height: 11.w), GestureDetector( onTap: () { Get.toNamed( KtRoutes.shortVideo, arguments: { 'shortPlayId': item.shortPlayId, 'imageUrl': item.imageUrl, 'isFromDiscover': true, }, )?.then((v) { videoPlayerController.play(); setState(() {}); }); }, child: Container( width: ScreenUtil().screenWidth - 60.w, margin: EdgeInsets.symmetric(horizontal: 12.w), padding: EdgeInsets.symmetric( horizontal: 12.w, vertical: 9.w, ), decoration: BoxDecoration( color: Color(0xFF1E1E20).withValues(alpha: .3), borderRadius: BorderRadius.circular(100), ), child: Row( children: [ Image.asset('ic_ep.png'.ktIcon, width: 16.w), SizedBox(width: 6.w), Text( 'Watch the complete series', style: TextStyle( fontSize: 12.sp, color: Colors.white, fontWeight: FontWeight.w400, ), ), const Spacer(), Image.asset( 'ic_right_white.png'.ktIcon, width: 10.w, ), ], ), ), ), SizedBox(height: 16.w), // if (state.controllers[state.currentPage] != null) // DrVideoProgressBar( // controller: state.controllers[state.currentPage]!, // width: ScreenUtil().screenWidth, // ), ], ), if (!videoPlayerController.value.isPlaying) Positioned( top: 240.h, child: GestureDetector( onTap: () { videoPlayerController.value.isPlaying ? videoPlayerController.pause() : videoPlayerController.play(); setState(() {}); }, child: Image.asset('ic_play.png'.ktIcon, width: 62.w), ), ), ], ), ), ); }, ); } @override bool get wantKeepAlive => true; }