diff --git a/lib/community/community_child_page.dart b/lib/community/community_child_page.dart index 6b0a075e..92e89009 100644 --- a/lib/community/community_child_page.dart +++ b/lib/community/community_child_page.dart @@ -103,6 +103,7 @@ class _CommunityChildPage extends State { child: CommunityDynamic( comments[position], 0, + isList: true, exitFull: () { setState(() {}); }, diff --git a/lib/community/community_details.dart b/lib/community/community_details.dart index 14dfe556..90f541c6 100644 --- a/lib/community/community_details.dart +++ b/lib/community/community_details.dart @@ -95,7 +95,7 @@ class _CommunityDetails extends State with WidgetsBindingObser ); BaseData
baseData = await apiService.informationInfo(comunity.id) .catchError((onError) { - debugPrint(onError); + debugPrint(onError.toString()); }); if (baseData != null && baseData.isSuccess) {} } diff --git a/lib/community/community_view/community_dynamic.dart b/lib/community/community_view/community_dynamic.dart index 7b57be89..eb6276fa 100644 --- a/lib/community/community_view/community_dynamic.dart +++ b/lib/community/community_view/community_dynamic.dart @@ -1,3 +1,4 @@ +import 'dart:io'; import 'dart:ui'; import 'package:chewie/chewie.dart'; @@ -14,8 +15,10 @@ import 'package:huixiang/view_widget/custom_image.dart'; import 'package:huixiang/view_widget/icon_text.dart'; import 'package:huixiang/view_widget/round_button.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:video_player/video_player.dart'; +import 'package:thumbnails/thumbnails.dart'; class CommunityDynamic extends StatefulWidget { final int itemCount; @@ -24,7 +27,7 @@ class CommunityDynamic extends StatefulWidget { final int commentType; final Function removalDynamic; final Function exitFull; - + final bool isList; final ComunityComment comment; CommunityDynamic( @@ -36,6 +39,7 @@ class CommunityDynamic extends StatefulWidget { this.isDetails = false, this.removalDynamic, this.exitFull, + this.isList = false, }) : super(key: key); @override @@ -65,33 +69,44 @@ class _CommunityDynamic extends State { ), }, ); + initVideo(); + } + + String filePath; + initVideo() async { if (widget.comment.subjectInfo.type == "video" && widget.comment.subjectInfo.video.isNotEmpty) { - videoPlayerController = VideoPlayerController.network( - widget.comment.subjectInfo.video, - )..initialize().then((value) { - chewieAudioController = ChewieController( - videoPlayerController: videoPlayerController, - aspectRatio: videoPlayerController.value.aspectRatio, - //宽高比 - autoPlay: false, - //自动播放 - looping: false, - //循环播放 - allowFullScreen: true, - // 拖动条样式颜色 - materialProgressColors: chewie.ChewieProgressColors( - playedColor: Colors.white, - handleColor: Colors.white, - backgroundColor: Colors.grey, - bufferedColor: Colors.transparent, - ), - autoInitialize: true, - ); - chewieAudioController.addListener(_fullScreenListener); - if (mounted) setState(() {}); - }); + if (widget.isList) { + videoPlayerController = VideoPlayerController.network( + widget.comment.subjectInfo.video, + )..initialize().then((value) {}); + } else { + videoPlayerController = VideoPlayerController.network( + widget.comment.subjectInfo.video, + )..initialize().then((value) { + chewieAudioController = ChewieController( + videoPlayerController: videoPlayerController, + aspectRatio: videoPlayerController.value.aspectRatio, + //宽高比 + autoPlay: false, + //自动播放 + looping: false, + //循环播放 + allowFullScreen: true, + // 拖动条样式颜色 + materialProgressColors: chewie.ChewieProgressColors( + playedColor: Colors.white, + handleColor: Colors.white, + backgroundColor: Colors.grey, + bufferedColor: Colors.transparent, + ), + autoInitialize: true, + ); + chewieAudioController.addListener(_fullScreenListener); + if (mounted) setState(() {}); + }); + } } } @@ -292,10 +307,10 @@ class _CommunityDynamic extends State { if (subjectInfo == null) { return Container(); } - Widget widget = Container(); + Widget itemWidget = Container(); if (subjectInfo.type == "image" && subjectInfo.images.length > 0) { if (subjectInfo.images.length == 1) { - widget = Container( + itemWidget = Container( child: MImage( subjectInfo.images[0], fit: BoxFit.cover, @@ -306,7 +321,7 @@ class _CommunityDynamic extends State { ), ); } else { - widget = GridView.builder( + itemWidget = GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: (subjectInfo.images.length == 2 || subjectInfo.images.length == 4) @@ -334,15 +349,15 @@ class _CommunityDynamic extends State { ); } } else if (subjectInfo.type == "video" && subjectInfo.video.isNotEmpty) { - widget = videoWidget( - MediaQuery.of(context).size.width - 32, - videoPlayerController != null - ? (MediaQuery.of(context).size.width - 32) / - videoPlayerController.value.aspectRatio - : MediaQuery.of(context).size.width / 2, - subjectInfo.video); + itemWidget = videoWidget( + MediaQuery.of(context).size.width - 32, + videoPlayerController != null + ? (MediaQuery.of(context).size.width - 32) / + videoPlayerController.value.aspectRatio + : MediaQuery.of(context).size.width / 2, + !widget.isList ? subjectInfo.video : widget.comment.coverImg, + ); } - return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, @@ -351,7 +366,7 @@ class _CommunityDynamic extends State { SizedBox( height: 16.h, ), - widget, + itemWidget, ], ); } @@ -378,17 +393,41 @@ class _CommunityDynamic extends State { data: MediaQuery.of(context).copyWith( textScaleFactor: 0.9, ), - child: chewieAudioController != null - ? Container( - width: width, - height: height, - child: chewies = Chewie( - controller: chewieAudioController, - ), - ) + child: !widget.isList + ? (chewieAudioController != null + ? Container( + width: width, + height: height, + child: chewies = Chewie( + controller: chewieAudioController, + ), + ) + : Container( + width: width, + height: height, + )) : Container( width: width, - height: height, + height: width / 3 * 2, + child: Stack( + children: [ + MImage( + src, + width: width, + height: width / 3 * 2, + fit: BoxFit.cover, + errorSrc: "assets/image/default_2_1.png", + fadeSrc: "assets/image/default_2_1.png", + ), + Center( + child: Icon( + Icons.play_circle_outline, + color: Colors.white, + size: 60, + ), + ), + ], + ), ), ); } diff --git a/lib/community/release_dynamic.dart b/lib/community/release_dynamic.dart index 144a6ac6..4156d9ae 100644 --- a/lib/community/release_dynamic.dart +++ b/lib/community/release_dynamic.dart @@ -14,6 +14,7 @@ import 'package:huixiang/view_widget/my_appbar.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:image_pickers/image_pickers.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:thumbnails/thumbnails.dart'; class ReleaseDynamic extends StatefulWidget { @override @@ -136,11 +137,13 @@ class _ReleaseDynamic extends State { List remoteImageUrls = []; String remoteVideoUrl = ""; + String remoteVideoCoverImg = ""; if (mediaPaths.length > 0) { if (dynamicType == 1) { remoteImageUrls = mediaPaths.map((e) => e.remotePath).toList(); } else if (dynamicType == 2) { remoteVideoUrl = mediaPaths[0].remotePath; + remoteVideoCoverImg = mediaPaths[0].thumbPath; } } @@ -149,6 +152,7 @@ class _ReleaseDynamic extends State { "subject": dynamicText, "subjectType": subjectType, "video": remoteVideoUrl, + "coverImg": remoteVideoCoverImg, }).catchError((onError) { EasyLoading.dismiss(); }); @@ -172,8 +176,31 @@ class _ReleaseDynamic extends State { element.path != null && element.path != "" && await File(element.path).exists())) { + File file = File(element.path); + if (dynamicType == 2) { + String thumbnail; + if (element.thumbPath != null && element.thumbPath != "" && await File(element.thumbPath).exists()) { + thumbnail = element.thumbPath; + } else { + thumbnail = await Thumbnails.getThumbnail( + videoFile: file.path, + imageType: ThumbFormat.WEBP, + quality: 10, + ); + } + if (thumbnail != null && thumbnail != "" && await File(thumbnail).exists()) { + BaseData baseData = await apiService.upload( + File(thumbnail), + 123123123, + ); + if (baseData != null && baseData.isSuccess) { + UploadResult uploadResult = baseData.data; + mediaPaths[mediaPaths.indexOf(element)].thumbPath = uploadResult.url; + } + } + } BaseData baseData = await apiService.upload( - File(element.path), + file, 123123123, ); if (baseData != null && baseData.isSuccess) { diff --git a/lib/retrofit/data/comunity_comment.dart b/lib/retrofit/data/comunity_comment.dart index a9fe7bc2..3cb78955 100644 --- a/lib/retrofit/data/comunity_comment.dart +++ b/lib/retrofit/data/comunity_comment.dart @@ -20,7 +20,8 @@ class ComunityComment { int comments, bool selfLike, bool selfFollow, - String createTime,}){ + String createTime, + String coverImg,}){ this.id = id; this.subject = subject; this.subjectInfo = subjectInfo; @@ -31,6 +32,7 @@ class ComunityComment { this.selfLike = selfLike; this.selfFollow = selfFollow; this.createTime = createTime; + this.coverImg = coverImg; } ComunityComment.fromJson(dynamic json) { @@ -44,6 +46,7 @@ class ComunityComment { this.selfLike = json['selfLike']; this.selfFollow = json['selfFollow']; this.createTime = json['createTime']; + this.coverImg = json['coverImg']; } String id; String subject; @@ -55,6 +58,7 @@ class ComunityComment { bool selfLike; bool selfFollow; String createTime; + String coverImg; Map toJson() { final map = {}; @@ -72,6 +76,7 @@ class ComunityComment { map['selfLike'] = this.selfLike; map['selfFollow'] = this.selfFollow; map['createTime'] = this.createTime; + map['coverImg'] = this.coverImg; return map; } @@ -118,7 +123,8 @@ class SubjectInfo { SubjectInfo({ String type, List images, - String video,}){ + String video, + String coverImg,}){ this.type = type; this.images = images; this.video = video; diff --git a/lib/view_widget/custom_image.dart b/lib/view_widget/custom_image.dart index efbd7416..dbe05a58 100644 --- a/lib/view_widget/custom_image.dart +++ b/lib/view_widget/custom_image.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter/material.dart'; @@ -29,49 +31,65 @@ class MImage extends StatelessWidget { @override Widget build(BuildContext context) { - Widget image = LayoutBuilder(builder: (context, constraints) { - String imageUrl = ""; - if (src != null && src != "") { - imageUrl = - "$src?imageMogr2/thumbnail/${constraints.constrainWidth() * scaleIndex}" - "x${constraints.constrainHeight() * scaleIndex}/format/webp/quality/100"; - } + Widget image = LayoutBuilder( + builder: (context, constraints) { + String imageUrl = ""; + if (src != null && src != "" && src.startsWith("http")) { + imageUrl = + "$src?imageMogr2/thumbnail/${constraints.constrainWidth() * scaleIndex}" + "x${constraints.constrainHeight() * scaleIndex}/format/webp/quality/100"; + } - print("constrainWidth: ${constraints.constrainWidth()}"); - print("constrainHeight: ${constraints.constrainHeight()}"); + // print("constrainWidth: ${constraints.constrainWidth()}"); + // print("constrainHeight: ${constraints.constrainHeight()}"); - if (imageUrl == null || imageUrl == "") { - return Image.asset( - "assets/image/default_2_1.png", - fit: fit, - ); - } - CachedNetworkImage cachedNetworkImage = CachedNetworkImage( - imageUrl: imageUrl, - cacheManager: DefaultCacheManager(), - fadeInDuration: Duration(milliseconds: 300), - fadeOutDuration: Duration(milliseconds: 300), - imageBuilder: (context, provide) { - return Image( - image: provide, - fit: fit, - ); - }, - errorWidget: (context, error, stackTrace) { + if (imageUrl == null || imageUrl == "") { return Image.asset( - errorSrc, + "assets/image/default_2_1.png", fit: fit, ); - }, - placeholder: (context, placeholder) { - return Image.asset( - fadeSrc, + } + Widget cachedNetworkImage; + if (src.startsWith("http")) { + cachedNetworkImage = CachedNetworkImage( + imageUrl: imageUrl, + cacheManager: DefaultCacheManager(), + fadeInDuration: Duration(milliseconds: 300), + fadeOutDuration: Duration(milliseconds: 300), + imageBuilder: (context, provide) { + return Image( + image: provide, + fit: fit, + ); + }, + errorWidget: (context, error, stackTrace) { + return Image.asset( + errorSrc, + fit: fit, + ); + }, + placeholder: (context, placeholder) { + return Image.asset( + fadeSrc, + fit: fit, + ); + }, + ); + } else if (src.startsWith("file")) { + cachedNetworkImage = Image.file( + File(src), fit: fit, + errorBuilder: (context, error, stackTrace) { + return Image.asset( + errorSrc, + fit: fit, + ); + }, ); - }, - ); - return cachedNetworkImage; - }); + } + return cachedNetworkImage; + }, + ); var clipRRect; if (isCircle) { diff --git a/pubspec.lock b/pubspec.lock index c39c4206..418f36f6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -335,7 +335,7 @@ packages: name: font_awesome_flutter url: "https://pub.flutter-io.cn" source: hosted - version: "9.1.0" + version: "9.2.0" graphs: dependency: transitive description: @@ -370,7 +370,7 @@ packages: name: image_pickers url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.0.0+1" intl: dependency: "direct main" description: @@ -726,6 +726,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.3.0" + thumbnails: + dependency: "direct main" + description: + name: thumbnails + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" tpns_flutter_plugin: dependency: "direct main" description: @@ -881,7 +888,7 @@ packages: name: win32 url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.9" + version: "2.2.10" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9f54aad3..b315fcaa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -68,6 +68,9 @@ dependencies: photo_view: ^0.11.1 video_player: ^2.2.3 + thumbnails: ^1.0.1 +# media_info: ^0.9.0 +# flutter_ffmpeg: ^0.4.2 package_info: ^2.0.2