import 'dart:typed_data'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flare_flutter/flare_controls.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:page_transition/page_transition.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:teso/Classes/API%20Clasess/CouponDetails.dart'; import 'package:teso/Classes/API%20Clasess/Post.dart'; import 'package:teso/Classes/API%20Clasess/PostFav.dart'; import 'package:teso/Classes/TesoUser.dart'; import 'package:teso/Pages/Sub_Pages/Posts/comment.dart'; import 'package:teso/Pages/Sub_Pages/userProfile3P.dart'; import 'package:teso/Services/video_controller_service.dart'; import 'package:teso/blocs/video_player/video_player_bloc.dart'; import 'package:teso/blocs/video_player/video_player_event.dart'; import 'package:teso/blocs/video_player/video_player_state.dart'; import 'package:teso/providers/user_provider.dart'; import 'package:teso/util/SizeConfig.dart'; import 'package:teso/util/consts.dart'; import 'package:numeral/numeral.dart'; import 'package:teso/GeneralWidgets/widgets/video_player_widget.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; // ignore: must_be_immutable class ViewPost extends StatefulWidget { Post postedAd; TesoUser user; bool friend; final bool play; Function report; ViewPost({ Key key, this.postedAd, this.user, this.friend, @required this.play, @required this.report, // this.posts, }) : super(key: key); @override _ViewPostState createState() => _ViewPostState(); } class _ViewPostState extends State { bool favoured = false; List coupons = []; Uint8List imageBitmap; final FlareControls flareControls = FlareControls(); bool campaignAd = false; int likes = 0; int comments = 0; var userDoc; var document; bool likeShow = false; bool dark = false; void sharing(Post ad) async { await rootBundle .load("assets/images/rawLogoOverlay.png") .then((value) => setState(() { imageBitmap = value.buffer.asUint8List(); })); Provider.of(context, listen: false).downloadVideo( ad.postID, ad.playbackID, ad.rendition, imageBitmap, context); } @override void dispose() { rootBundle.evict("assets/images/rawLogoOverlay.png"); super.dispose(); } void likePost(Post ad) { setState(() { likeShow = true; }); SharedPreferences.getInstance().then((value) { String cid = value.getString("id"); PostFav liked = new PostFav(); liked.admirerId = cid; liked.countId = DateTime.now().toString() + "$cid"; liked.timestamp = DateTime.now().toIso8601String(); liked.postId = ad.postID; setState(() { // ad.likes.add(liked); likes++; favoured = true; }); flareControls.play("like"); Provider.of(context, listen: false).addLike(liked); }); } void dislikePost(Post ad) { setState(() { favoured = false; likes--; }); Provider.of(context, listen: false).deleteLike(ad.postID); } void commentsDialog(BuildContext context) { if (userDoc == null) { FirebaseFirestore.instance .collection("users") .doc(widget.postedAd.publisherID) .get() .then((value) { setState(() { userDoc = value.data(); }); }); } else { showModalBottomSheet( context: context, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)), ), builder: (BuildContext bc) { return ClipRRect( borderRadius: BorderRadius.only( topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0), ), child: CommentSection( postedAd: widget.postedAd, user: TesoUser( username: userDoc["username"], userGUID: userDoc["id"], )), ); }, ); } } Future getCampaignCoupons(String campaign) async { SharedPreferences prefs = await SharedPreferences.getInstance(); Map requestHeaders = { 'Content-type': 'application/json', 'Authorization': prefs.getString('tokensTeso') }; try { var register2 = serverLocation + 'coupons/campaign_coupons'; var client1 = await http.post( Uri.parse(register2), headers: requestHeaders, body: json.encode(campaign), ); if (client1.statusCode == 200) { var details = jsonDecode(client1.body); setState(() { coupons = List.from( details.map((model) => CouponDetails.fromJSON(model)).toList()); // coupons.removeWhere( // (element) => element.expiration.isAfter(DateTime.now())); }); } } catch (e) { print(e); } } @override void initState() { campaignAd = false; _getDocuments(); _likedListen(); _commentsListen(); FirebaseFirestore.instance .collection("users") .doc(widget.postedAd.publisherID) .get() .then((value) { if (mounted) setState(() { userDoc = value.data(); }); }); SharedPreferences.getInstance().then((value) => value.getString("theme") == "light" ? dark = false : dark = true); super.initState(); } _getDocuments() { FirebaseFirestore.instance .collection("posts") .doc(widget.postedAd.postID) .get() .then((value) { if (mounted) setState(() { document = value.data(); if (document != null) { if (document["campaignId"] != null) { campaignAd = true; getCampaignCoupons(document["campaignId"]); } } }); }); } _likedListen() { SharedPreferences.getInstance().then((value) { String cid = value.getString("id"); FirebaseFirestore.instance .collection("posts") .doc(widget.postedAd.postID) .collection("likes") .snapshots() .listen((event) { if (mounted) { setState(() { favoured = event.docs.any((element) => element.data()["admirerID"] == cid); likes = event.docs.length; }); } }); }); } _commentsListen() { FirebaseFirestore.instance .collection("posts") .doc(widget.postedAd.postID) .collection("comments") .snapshots() .listen((event) { if (mounted) { setState(() { comments = event.docs.length; }); } }); } @override Widget build(BuildContext context) { SizeConfig().init(context); return Scaffold( body: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, color: Colors.black, child: Stack( children: [ _buildVideoPlayer(widget.postedAd), Align( alignment: Alignment.bottomRight, child: Container( margin: EdgeInsets.only( right: 10, bottom: 30, ), width: 50, height: MediaQuery.of(context).size.width * 0.73, child: Column( children: [ _publisherWidget(context), SizedBox( height: 20, ), _favoriteWidget(context), SizedBox( height: 20, ), _commentWidget(context), SizedBox( height: 20, ), Container( height: 30, child: InkWell( onTap: () => moreDialog(context, widget.postedAd), child: Icon( Icons.more_horiz, size: 30, color: Colors.white, ), ), ), ], ), ), ), _nameDescription(context), ], ), ), ); } Widget _buildVideoPlayer(Post ad) { return BlocProvider( create: (context) => VideoPlayerBloc( RepositoryProvider.of(context)) ..add(VideoSelectedEvent(ad)), child: BlocBuilder( builder: (context, state) { return Container(child: _getPlayer(context, state, ad)); }, ), ); } Widget _getPlayer(BuildContext context, VideoPlayerState state, Post ad) { // final screenWidth = MediaQuery.of(context).size.width; // final containerHeight = screenWidth / ASPECT_RATIO; final containerHeight = MediaQuery.of(context).size.height; if (state is VideoPlayerStateLoaded) { return GestureDetector( onDoubleTap: () { if (campaignAd) { if (favoured) { return null; } else { likePost(ad); } } else { if (favoured) { dislikePost(ad); } else { likePost(ad); } } }, child: Stack( children: [ VideoPlayerWidget( key: Key(state.video.playbackID), controller: state.controller, ad: ad, play: widget.play, details: coupons, ), AnimatedOpacity( opacity: likeShow ? 1 : 0, duration: Duration(seconds: 2), onEnd: () { setState(() { likeShow = false; }); }, child: Container( width: double.infinity, height: MediaQuery.of(context).size.height, child: Center( child: Image.asset("assets/lovw.gif"), ), ), ), ], ), ); } if (state is VideoPlayerStateLoading) { return Container(); } if (state is VideoPlayerStateError) { return Container( height: containerHeight, color: Colors.black, child: Center( child: Text(state.message), ), ); } return Container(); } Widget _nameDescription(BuildContext context) { return Align( alignment: Alignment.bottomLeft, child: Container( margin: EdgeInsets.symmetric( horizontal: 10, vertical: MediaQuery.of(context).size.height * 0.05, ), child: new Wrap( direction: Axis.vertical, children: [ new RichText( maxLines: 5, text: TextSpan( text: userDoc != null ? "@" + userDoc["username"] : "", style: TextStyle( color: Colors.white, fontSize: SizeConfig.safeBlockHorizontal * 4.3, fontWeight: FontWeight.bold, ), ), ), SizedBox(height: 5), Container( margin: EdgeInsets.only(bottom: 20), width: MediaQuery.of(context).size.width * 0.7, child: Text( document != null ? document["title"] != null ? document["title"] : "" : "", style: TextStyle( color: Colors.white, fontSize: SizeConfig.safeBlockHorizontal * 4.3, height: 1.5, ), maxLines: 4, overflow: TextOverflow.ellipsis, textDirection: TextDirection.rtl, textAlign: TextAlign.left, ), ), ], ), ), ); } Widget _publisherWidget(BuildContext context) { return Container( width: 40, height: 40, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: Colors.black, width: 1, ), ), child: ClipRRect( borderRadius: BorderRadius.only( topLeft: Radius.circular(90.0), topRight: Radius.circular(90.0), bottomLeft: Radius.circular(90), bottomRight: Radius.circular(90), ), child: InkWell( onTap: widget.postedAd.publisherID != null ? () => Navigator.pushReplacement( context, PageTransition( child: UserProfileThirdPerson( user: new TesoUser( username: userDoc["username"], userGUID: userDoc["id"], firstname: userDoc["firstname"], lastname: userDoc["surname"], ), ), type: PageTransitionType.fade, ), ) : null, child: CachedNetworkImage( imageUrl: serverLocation + "api/pulldp/" + widget.postedAd.publisherID, imageBuilder: (context, imageProvider) => FadeInImage( height: 90, width: 90, fit: BoxFit.fill, image: imageProvider, placeholder: AssetImage("assets/images/tesoDP/dp1.png"), ), ), ), ), ); } Widget _favoriteWidget(BuildContext context) { return Container( height: 50, child: InkWell( onTap: () { if (campaignAd) { if (favoured) { return null; } else { likePost(widget.postedAd); } } else { if (favoured) { dislikePost(widget.postedAd); } else { likePost(widget.postedAd); } } }, child: new Wrap( direction: Axis.vertical, children: [ Container( width: 50, height: 30, child: Center( child: Icon( Icons.favorite, size: 30, color: favoured ? Colors.red : Colors.white, ), ), ), Container( height: 20, width: 50, child: Center( child: Text( Numeral(likes).value().toString(), style: TextStyle( fontWeight: FontWeight.bold, color: Colors.white, ), ), ), ), ], ), ), ); } Widget _commentWidget(BuildContext context) { return Container( height: 50, child: InkWell( onTap: () => commentsDialog(context), child: new Wrap( direction: Axis.vertical, children: [ Container( width: 50, height: 30, child: Center( child: Icon( Icons.comment, size: 30, color: Colors.white, ), ), ), Container( height: 20, width: 50, child: Center( child: Text( Numeral(comments).value().toString(), style: TextStyle( fontWeight: FontWeight.bold, color: Colors.white, ), ), ), ), ], ), ), ); } void moreDialog(BuildContext context, Post ad) { showModalBottomSheet( context: context, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(30.0)), ), builder: (BuildContext bc) { return Container( child: SingleChildScrollView( scrollDirection: Axis.vertical, child: new Wrap( children: [ new Container( margin: EdgeInsets.symmetric( vertical: 15.0, ), child: Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Container( width: 50, height: 4, color: Colors.grey, ), ), ), ), buildTop3(context, ad), new Container( width: MediaQuery.of(context).size.width, height: 40, margin: EdgeInsets.symmetric(vertical: 20.0, horizontal: 15), decoration: BoxDecoration( color: !dark ? Colors.grey[200] : Colors.white12, borderRadius: BorderRadius.circular(5)), child: new Center( child: Text( "Why you're seeing this post", textAlign: TextAlign.center, style: TextStyle( color: !dark ? Colors.black : Colors.white, ), ), ), ), // bottomButtons(context, friends), ], ), ), ); }, ); } buildTop3(BuildContext context, Post ad) { return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ GestureDetector( onTap: () => sharing(ad), child: Container( width: SizeConfig.blockSizeHorizontal * 30, height: SizeConfig.blockSizeHorizontal * 20, decoration: BoxDecoration( borderRadius: BorderRadius.all( Radius.circular( 10, ), ), color: !dark ? Colors.grey[200] : Colors.white12, ), alignment: Alignment.center, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Icon(Icons.share), Text( "Share", ), ], ), ), ), ), GestureDetector( onTap: () => reportDialog(context), child: Container( width: SizeConfig.blockSizeHorizontal * 30, height: SizeConfig.blockSizeHorizontal * 20, decoration: BoxDecoration( borderRadius: BorderRadius.all( Radius.circular( 10, ), ), color: !dark ? Colors.grey[200] : Colors.white12, ), alignment: Alignment.center, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Icon( Icons.report_problem, color: Colors.red[900], ), Text( "Report", ), ], ), ), ), ), ], ); } flagContent(level) { Provider.of(context, listen: false) .flagPost(widget.postedAd, level); Navigator.pop(context); widget.report(widget.postedAd); this.dispose(); } bottomButtons(BuildContext context, friends) { return new Container( width: MediaQuery.of(context).size.width, margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 15), child: Column( children: [ new Container( width: MediaQuery.of(context).size.width, child: new Center( child: ElevatedButton( style: ElevatedButton.styleFrom( primary: Colors.grey[200], shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(5.0), ), ), ), onPressed: () => Navigator.pop(context), child: Container( width: MediaQuery.of(context).size.width, child: Text( "Hide", textAlign: TextAlign.center, )), ), ), ), friends ? new Container( width: MediaQuery.of(context).size.width, child: new Center( child: ElevatedButton( style: ElevatedButton.styleFrom( primary: Colors.grey[300], shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(5.0), ), ), ), onPressed: () => Navigator.pop(context), child: Container( width: MediaQuery.of(context).size.width, child: Text( "Unfrend", textAlign: TextAlign.center, )), ), ), ) : new Container( width: MediaQuery.of(context).size.width, child: new Center( child: ElevatedButton( style: ElevatedButton.styleFrom( primary: Colors.grey[300], shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(5.0), ), ), ), onPressed: () => Navigator.pop(context), child: Container( width: MediaQuery.of(context).size.width, child: Text( "Add Friend", textAlign: TextAlign.center, )), ), ), ) ], )); } void reportDialog(BuildContext context) { showModalBottomSheet( context: context, isScrollControlled: true, enableDrag: true, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(30.0)), ), builder: (BuildContext bc) { return Container( height: MediaQuery.of(context).size.height * 0.95, child: Column( children: [ new Container( margin: EdgeInsets.symmetric( vertical: 15.0, ), child: Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Container( width: 50, height: 4, color: Colors.grey, ), ), ), ), Container( child: Center( child: Text( "Report", style: TextStyle( fontSize: SizeConfig.blockSizeHorizontal * 3.5, fontWeight: FontWeight.w800, ), ), ), ), Divider(), Container( padding: EdgeInsets.symmetric(horizontal: 10), child: Text( "Why are you reporting this post?", textAlign: TextAlign.left, style: TextStyle( fontSize: SizeConfig.blockSizeHorizontal * 3.5, fontWeight: FontWeight.w800, ), ), ), SizedBox( height: 5, ), Container( padding: EdgeInsets.symmetric(horizontal: 15), child: Center( child: Text( "Your report would be handled as soon as possible. However if someone is in immediate danger, call the local emergency services - don't wait.", style: TextStyle( fontSize: SizeConfig.blockSizeHorizontal * 3.5, fontWeight: FontWeight.w400, ), ), ), ), Divider(), Container( height: MediaQuery.of(context).size.height * 0.7, child: new ListView( scrollDirection: Axis.vertical, children: [ ListTile( title: Text("It's a spam"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(1), ), ListTile( title: Text("Nudity or sexual activity"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(2), ), ListTile( title: Text("I just don't like it"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(3), ), ListTile( title: Text("Hate speech or symbols"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(4), ), ListTile( title: Text("False information"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(5), ), ListTile( title: Text("Bullying harassment"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(6), ), ListTile( title: Text("Violence or dangerous organisations"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(7), ), ListTile( title: Text("Scam or fraud"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(8), ), ListTile( title: Text("Intellectual property violation"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(9), ), ListTile( title: Text("Sale of illegal or regulated goods"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(10), ), ListTile( title: Text("Suicide or self-injury"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(11), ), ListTile( title: Text("Eating disorders"), trailing: Icon(Icons.arrow_forward_ios), onTap: () => flagContent(12), ), ], ), ), ], ), ); }, ); } }