import 'dart:io'; import 'dart:ui'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:flutter_html/image_render.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/retrofit/data/memberCommentList.dart'; import 'package:huixiang/retrofit/data/activity.dart'; import 'package:huixiang/retrofit/data/article.dart'; import 'package:huixiang/retrofit/data/base_data.dart'; import 'package:huixiang/retrofit/data/page.dart'; import 'package:huixiang/retrofit/retrofit_api.dart'; import 'package:huixiang/view_widget/custom_image.dart'; import 'package:huixiang/view_widget/my_appbar.dart'; import 'package:huixiang/view_widget/share_dialog.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:sharesdk_plugin/sharesdk_defines.dart'; import 'package:sharesdk_plugin/sharesdk_interface.dart'; import 'package:sharesdk_plugin/sharesdk_map.dart'; import 'package:video_player/video_player.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:flutter_html/src/replaced_element.dart'; import 'package:flutter/cupertino.dart'; import 'package:chewie/src/chewie_progress_colors.dart' as chewie; import 'package:chewie/chewie.dart'; class StoreDetailsPage extends StatefulWidget { final Map arguments; ///富文本 文章 活动 StoreDetailsPage({this.arguments}); @override State createState() { return _StoreDetailsPage(); } } class _StoreDetailsPage extends State { ApiService apiService; RefreshController _refreshController; bool isLiked = false; int commentTotal = 0; var commentTextController = TextEditingController(); var commentFocus = FocusNode(); String hintText = "留下您精彩的评论吧"; String parenId = "0"; @override void initState() { super.initState(); _refreshController = RefreshController(); if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); SharedPreferences.getInstance().then((value) { apiService = ApiService(Dio(), context: context, token: value.getString("token")); queryHtml(); queryMemberCommentList(); }); } Activity activity; Article article; List memberList = []; queryHtml() async { BaseData baseData = await apiService.informationInfo( widget.arguments["activityId"] ?? widget.arguments["articleId"]); if (baseData != null && baseData.isSuccess) { setState(() { if (widget.arguments.containsKey("activityId")) { activity = Activity.fromJson(baseData.data); } else if (widget.arguments.containsKey("articleId")) { article = Article.fromJson(baseData.data); } }); } } share() async { SSDKMap params = SSDKMap() ..setGeneral( activity != null ? activity.mainTitle : article != null ? article.mainTitle : "", activity != null ? activity.viceTitle : article != null ? article.viceTitle : "", [ activity != null ? activity.coverImg : article != null ? article.coverImg : "", ], activity != null ? activity.coverImg : article != null ? article.coverImg : "", "", "http://hx.lotus-wallet.com/index.html?id=${widget.arguments["activityId"] ?? widget.arguments["articleId"]}", "", "", "", "", SSDKContentTypes.webpage); debugPrint(activity != null ? activity.coverImg : article != null ? article.coverImg : ""); showModalBottomSheet( context: context, backgroundColor: Colors.transparent, builder: (context) { return ShareDialog((platform) { if (platform == ShareSDKPlatforms.line) { params.map["type"] = SSDKContentTypes.text.value; params.map["text"] = "${activity != null ? activity.viceTitle : article != null ? article.viceTitle : ""} http://hx.lotus-wallet.com/index.html?id=${widget.arguments["activityId"] ?? widget.arguments["articleId"]}"; } SharesdkPlugin.share(platform, params, (state, userData, contentEntity, error) { print("share!$state"); }); }); }); } //评论列表 queryMemberCommentList() async { BaseData baseData = await apiService.memberCommentList({ "pageNum": 1, "pageSize": 100, "relationalId": widget.arguments["activityId"] ?? widget.arguments["articleId"], "relationalType": 1 }).catchError((error) { _refreshController.refreshFailed(); }); if (baseData != null && baseData.isSuccess) { PageInfo pageInfo = PageInfo.fromJson(baseData.data); _refreshController.refreshCompleted(); setState(() { commentTotal = pageInfo.size; memberList = pageInfo.list.map((e) => MemberCommentList.fromMap(e)).toList(); }); } } //评论点赞 queryCommentLike(String id) async { BaseData baseData = await apiService.commentLike(id).catchError((onError) {}); if (baseData != null && baseData.isSuccess) { setState(() { memberList.forEach((element) { if (element.id == id) { element.likes += 1; element.isFabulous = true; } }); }); } else { if (baseData.msg == "您已点过赞") { setState(() { memberList.forEach((element) { if (element.id == id) { element.isFabulous = true; } }); }); } else SmartDialog.showToast(baseData.msg, alignment: Alignment.center); } } //给文章/活动点赞 queryInformationLikes() async { BaseData baseData = await apiService .informationLikes( widget.arguments["activityId"] ?? widget.arguments["articleId"]) .catchError((onError) {}); if (baseData != null && baseData.isSuccess) { setState(() { isLiked = true; if (article != null) article.likes += 1; else if (activity != null) activity.likes += 1; }); } else { SmartDialog.showToast(baseData.msg, alignment: Alignment.center); } } //发布评论 queryMemberComment(String content) async { BaseData baseData = await apiService.memberComment({ "content": content, "parentId": parenId, "relationalId": widget.arguments["activityId"] ?? widget.arguments["articleId"], "relationalType": 1 }).catchError((error) { _refreshController.refreshFailed(); }); if (baseData != null && baseData.isSuccess) { commentTextController.text = ""; queryMemberCommentList(); } } @override Widget build(BuildContext context) { return Scaffold( appBar: MyAppBar( action: Container( margin: EdgeInsets.only(right: 10), child: GestureDetector( onTap: () { share(); }, child: Icon( Icons.share, size: 24, color: Colors.black, ), ), ), background: Color(0xFFF7F7F7), leadingColor: Colors.black, title: activity != null ? activity.mainTitle : article != null ? article.mainTitle : "", titleSize: 18.sp, titleColor: Colors.black, ), body: Container( child: GestureDetector( onTap: () { commentFocus.unfocus(); setState(() { hintText = "留下您精彩的评论吧"; }); parenId = "0"; }, child: SingleChildScrollView( physics: BouncingScrollPhysics(), child: Column( children: [ Container( color: Color(0xFFF7F7F7), padding: EdgeInsets.all(12), alignment: Alignment.centerLeft, child: Text( activity != null ? activity.mainTitle : article != null ? article.mainTitle : "", style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: Color(0xFF353535), ), ), ), Container( padding: EdgeInsets.symmetric(horizontal: 12.w), child: Row( children: [ InkWell( child: Text( "${activity != null ? activity.storeName : (article != null && article.author != null) ? article.author.name : ""}", style: TextStyle( fontWeight: FontWeight.normal, fontSize: 14.sp, color: Colors.blue, ), ), onTap: () { if (activity != null) { if (widget.arguments["source"] != null && widget.arguments["source"] == activity.storeId) { Navigator.of(context).pop(); } else { Navigator.of(context).pushNamed( '/router/union_detail_page', arguments: { "id": activity.storeId, "source": widget.arguments["activityId"] }); } } }, ), SizedBox( width: 10.w, ), Text( activity != null ? activity.createTime : article != null ? article.createTime : "", style: TextStyle( fontWeight: FontWeight.normal, fontSize: 12.sp, color: Colors.grey, ), ) ], ), ), Html( data: activity != null ? activity.content : article != null ? article.content : "", customImageRenders: { base64DataUriMatcher(): base64ImageRender(), assetUriMatcher(): assetImageRender(), networkSourceMatcher(extension: "svg"): svgNetworkImageRender(), networkSourceMatcher(): networkImageRender( loadingWidget: () { return Container(); }, // mapUrl: (url) { // print("objectUrl: $url"); // return "$url?imageMogr2/format/webp/blur/1x0/quality/75"; // }, ), }, customRender: { "video": (context, parsedChild, attributes, element) { return videoWidget( double.tryParse(attributes['width'] ?? ""), double.tryParse(element.attributes['height'] ?? ""), element.children.first.attributes["src"], element.attributes["sandbox"]); }, "iframe": (context, parsedChild, attributes, element) { return videoWidget( double.tryParse(attributes['width'] ?? ""), double.tryParse(element.attributes['height'] ?? ""), element.children.first.attributes["src"], element.attributes["sandbox"]); }, "audio": (context, parsedChild, attributes, element) { final sources = [ if (element.attributes['src'] != null) element.attributes['src'], ]; if (sources == null || sources.isEmpty || sources.first == null) { return EmptyContentElement(); } return audioWidget( attributes['controls'] != null, attributes['loop'] != null, attributes['autoplay'] != null, sources, context.style.width ?? 300.w); }, }, ), Container( decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withAlpha(12), offset: Offset(0, 2), blurRadius: 14, spreadRadius: 0) ], ), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.all(16), child: Row( children: [ Text("评论(${commentTotal.toString()})", style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: Color(0xff1A1A1A))), SizedBox( width: 16.w, ), Text( "喜欢(${article?.likes ?? activity?.likes ?? "0"})", style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: Color(0xff1A1A1A))), ], ), ), ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), itemCount: memberList != null ? memberList.length : 0, scrollDirection: Axis.vertical, itemBuilder: (context, position) { return GestureDetector( onTap: () {}, child: commentItem(memberList[position], position, memberList.length, () { FocusScope.of(context).requestFocus(commentFocus); parenId = memberList[position].id; setState(() { hintText = "回复@${memberList[position].username}:"; }); }), ); }, ), ], ), ), SizedBox( height: 12.h, ), Container( padding: EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withAlpha(12), offset: Offset(0, 2), blurRadius: 14, spreadRadius: 0) ], borderRadius: new BorderRadius.only( topLeft: Radius.circular(8.0), topRight: Radius.circular(8.0), ), ), child: Row( children: [ Expanded( flex: 1, child: Container( decoration: new BoxDecoration( color: Color(0xffF2F2F2), borderRadius: BorderRadius.circular(2.0)), child: Column( children: [ Container( margin: const EdgeInsets.fromLTRB(4, 0, 4, 0), alignment: Alignment.topLeft, child: TextField( maxLines: 8, minLines: 1, focusNode: commentFocus, controller: commentTextController, decoration: InputDecoration( border: InputBorder.none, hintText: hintText, hintStyle: TextStyle( fontSize: 14.sp, color: Color(0xffCDCCCC), ), ), ), ), ], ), ), ), Padding( padding: EdgeInsets.only(left: 20.w, right: 20.w), child: GestureDetector( onTap: () { var commentText = commentTextController.text; if (commentText == "") { return; } queryMemberComment(commentText); }, child: Text( "发送", style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: Color(0XFF1A1A1A)), ), ), ), GestureDetector( onTap: () { if (isLiked) return; queryInformationLikes(); }, child: Image.asset(isLiked ? "assets/image/icon_like.png" : "assets/image/icon_like_h.png"), ) ], ), ), ], ), ), ), ), ); } VideoPlayerController videoPlayerController; ChewieController chewieAudioController; Chewie chewies; Widget videoWidget(double width, double height, src, sandboxMode) { print("src : $src"); return Container( width: MediaQuery.of(context).size.width, height: (MediaQuery.of(context).size.width) / (width / height), child: chewies = Chewie( controller: chewieAudioController = ChewieController( videoPlayerController: videoPlayerController = VideoPlayerController.network( src, ), aspectRatio: width / height, //宽高比 autoPlay: !true, //自动播放 looping: false, //循环播放 // 拖动条样式颜色 materialProgressColors: chewie.ChewieProgressColors( playedColor: Colors.white, handleColor: Colors.white, backgroundColor: Colors.grey, bufferedColor: Colors.transparent, ), autoInitialize: true, ), ), ); } Widget audioWidget(showControls, loop, autoplay, src, width) { return Container( width: width, child: chewies = Chewie( controller: chewieAudioController = ChewieController( videoPlayerController: VideoPlayerController.network( src.first ?? "", ), autoPlay: autoplay, looping: loop, showControls: showControls, autoInitialize: true, ), ), ); } Widget commentItem(MemberCommentList memberList, int index, int max, GestureTapCallback callback) { return Container( child: Column( children: [ Padding( padding: EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ MImage( memberList.userAvatarUrl ?? "", fit: BoxFit.cover, isCircle: true, width: 40, height: 40, fadeSrc: "assets/image/default_user.png", errorSrc: "assets/image/default_user.png", ), SizedBox( width: 12.w, ), Expanded( child: Container( height: 60.h, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text.rich( TextSpan( children: [ TextSpan( text: memberList.username, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14.sp, color: Colors.black, ), ), ], ), textDirection: TextDirection.ltr, ), Text( memberList.createTime, overflow: TextOverflow.ellipsis, maxLines: 2, style: TextStyle( fontSize: 12.sp, color: Color(0xff808080), ), ), ], ), ), flex: 1, ), Container( alignment: Alignment.topRight, child: Row( children: [ GestureDetector( onTap: () { if (memberList.isFabulous ?? false) return; queryCommentLike(memberList.id); }, child: Image.asset( !(memberList.isFabulous ?? false) ? "assets/image/icon_like_h.png" : "assets/image/icon_like.png", width: 16, height: 16, ), ), Text( memberList.likes.toString(), style: TextStyle( fontSize: 12.sp, color: Color(0xff1A1A1A), ), ), ], ), ), ], ), ), Padding( padding: EdgeInsets.only(left: 68, right: 16), child: Align( alignment: Alignment.centerLeft, child: GestureDetector( onTap: callback, child: Text( memberList.content, style: TextStyle( fontSize: 14.sp, color: Color(0xff1A1A1A), ), ), ), ), ), SizedBox( height: 12.h, ), if (memberList.parentContent != null) Container( margin: EdgeInsets.only(left: 68.w, right: 16.w), decoration: BoxDecoration( color: Color(0xffF2F2F2), borderRadius: BorderRadius.circular(2.0), ), child: Padding( padding: EdgeInsets.only(left: 4.w, top: 4.h, bottom: 4.h), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${memberList.parentUserName}:" ?? "", style: TextStyle( fontSize: 12.sp, color: Color(0xff808080), ), ), Expanded( flex: 1, child: Text( memberList.parentContent ?? "", style: TextStyle( fontSize: 12.sp, color: Color(0xff808080), ), ), ), ], ), ), ), if (index == max - 1) Container( height: 63.h, decoration: BoxDecoration( color: Color(0xffF2F2F2), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(12), offset: Offset(0, 2), blurRadius: 14, spreadRadius: 0, ) ], ), margin: EdgeInsets.only(top: 30.h), alignment: Alignment.center, child: Text( "-已显示全部评论-", style: TextStyle(fontSize: 14.sp, color: Color(0xff353535)), ), ), ], ), ); } @override void dispose() { if (chewieAudioController != null) chewieAudioController.dispose(); if (videoPlayerController != null) videoPlayerController.dispose(); super.dispose(); } }