From 073f21dc5d07f92b571054f298785e7be97876f8 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 12 May 2020 15:27:16 +0200 Subject: [PATCH] fix attachment size --- example/lib/main.dart | 10 ++-- lib/src/attachment_actions.dart | 43 +++++++-------- lib/src/attachment_error.dart | 6 ++- lib/src/attachment_title.dart | 2 +- lib/src/file_attachment.dart | 6 ++- lib/src/full_screen_video.dart | 76 ++++++++++++++++++++++++++ lib/src/giphy_attachment.dart | 65 ++++++++++------------ lib/src/image_attachment.dart | 96 +++++++++++++++++---------------- lib/src/message_widget.dart | 23 ++++++-- lib/src/video_attachment.dart | 77 ++++++++++++++++++++------ 10 files changed, 267 insertions(+), 137 deletions(-) create mode 100644 lib/src/full_screen_video.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 251af27e..4355e1f9 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -111,11 +111,11 @@ class ChannelListPage extends StatelessWidget { return Scaffold( body: ChannelsBloc( child: ChannelListView( -// filter: { -// 'members': { -// '\$in': [StreamChat.of(context).user.id], -// } -// }, + filter: { + 'members': { + '\$in': [StreamChat.of(context).user.id], + } + }, sort: [SortOption('last_message_at')], pagination: PaginationParams( limit: 20, diff --git a/lib/src/attachment_actions.dart b/lib/src/attachment_actions.dart index 15d4665f..f101ef53 100644 --- a/lib/src/attachment_actions.dart +++ b/lib/src/attachment_actions.dart @@ -15,42 +15,37 @@ class AttachmentActions extends StatelessWidget { Widget build(BuildContext context) { final streamChannel = StreamChannel.of(context); return Row( - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, children: attachment.actions?.map((action) { if (action.style == 'primary') { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 4.0), - child: FlatButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - child: Text('${action.text}'), - color: action.style == 'primary' - ? StreamChatTheme.of(context).accentColor - : null, - textColor: Colors.white, - onPressed: () { - streamChannel.channel.sendAction(message, { - action.name: action.value, - }); - }, - ), - ); - } - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 4.0), - child: OutlineButton( + return FlatButton( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: Text('${action.text}'), - color: StreamChatTheme.of(context).accentColor, + color: action.style == 'primary' + ? StreamChatTheme.of(context).accentColor + : null, + textColor: Colors.white, onPressed: () { streamChannel.channel.sendAction(message, { action.name: action.value, }); }, + ); + } + return OutlineButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), ), + child: Text('${action.text}'), + color: StreamChatTheme.of(context).accentColor, + onPressed: () { + streamChannel.channel.sendAction(message, { + action.name: action.value, + }); + }, ); })?.toList(), ); diff --git a/lib/src/attachment_error.dart b/lib/src/attachment_error.dart index e8f87ab4..e08867b8 100644 --- a/lib/src/attachment_error.dart +++ b/lib/src/attachment_error.dart @@ -5,10 +5,12 @@ import 'package:stream_chat/stream_chat.dart'; class AttachmentError extends StatelessWidget { final Attachment attachment; + final Size size; const AttachmentError({ Key key, @required this.attachment, + this.size, }) : super(key: key); @override @@ -20,8 +22,8 @@ class AttachmentError extends StatelessWidget { } return Center( child: Container( - width: 200, - height: 140, + width: size?.width, + height: size?.height, color: Color(0xffd0021B).withOpacity(.1), child: Center( child: Icon( diff --git a/lib/src/attachment_title.dart b/lib/src/attachment_title.dart index 4d30f7b2..efa34765 100644 --- a/lib/src/attachment_title.dart +++ b/lib/src/attachment_title.dart @@ -26,7 +26,7 @@ class AttachmentTitle extends StatelessWidget { padding: const EdgeInsets.all(8.0), child: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( attachment.title, diff --git a/lib/src/file_attachment.dart b/lib/src/file_attachment.dart index d41cd13c..05318862 100644 --- a/lib/src/file_attachment.dart +++ b/lib/src/file_attachment.dart @@ -4,10 +4,12 @@ import 'package:stream_chat_flutter/src/utils.dart'; class FileAttachment extends StatelessWidget { final Attachment attachment; + final Size size; const FileAttachment({ Key key, @required this.attachment, + this.size, }) : super(key: key); @override @@ -18,8 +20,8 @@ class FileAttachment extends StatelessWidget { launchURL(context, attachment.assetUrl); }, child: Container( - width: 100, - height: 100, + width: size?.width ?? 100, + height: size?.height ?? 100, child: Center( child: Icon(Icons.attach_file), ), diff --git a/lib/src/full_screen_video.dart b/lib/src/full_screen_video.dart new file mode 100644 index 00000000..3bed2d09 --- /dev/null +++ b/lib/src/full_screen_video.dart @@ -0,0 +1,76 @@ +import 'package:chewie/chewie.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:video_player/video_player.dart'; + +import 'utils.dart'; + +class FullScreenVideo extends StatefulWidget { + final Attachment attachment; + + FullScreenVideo({ + Key key, + @required this.attachment, + }) : super(key: key); + + @override + _FullScreenVideoState createState() => _FullScreenVideoState(); +} + +class _FullScreenVideoState extends State { + ChewieController _chewieController; + VideoPlayerController _videoPlayerController; + bool initialized = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Builder( + builder: (context) { + if (!initialized) { + return Center( + child: CircularProgressIndicator(), + ); + } + + return Chewie( + controller: _chewieController, + ); + }, + ), + ); + } + + @override + void initState() { + super.initState(); + _videoPlayerController = + VideoPlayerController.network(widget.attachment.assetUrl); + _videoPlayerController.initialize().whenComplete(() { + setState(() { + initialized = true; + }); + }); + + _chewieController = ChewieController( + videoPlayerController: _videoPlayerController, + autoInitialize: false, + aspectRatio: _videoPlayerController.value.aspectRatio, + ); + _videoPlayerController.addListener(() { + if (_videoPlayerController.value.hasError) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + Navigator.pop(context); + launchURL(context, widget.attachment.titleLink); + }); + } + }); + } + + @override + void dispose() { + _videoPlayerController.dispose(); + _chewieController.dispose(); + super.dispose(); + } +} diff --git a/lib/src/giphy_attachment.dart b/lib/src/giphy_attachment.dart index 4ad9e7ab..9cc40d07 100644 --- a/lib/src/giphy_attachment.dart +++ b/lib/src/giphy_attachment.dart @@ -5,19 +5,20 @@ import 'package:stream_chat_flutter/src/attachment_actions.dart'; import '../stream_chat_flutter.dart'; import 'attachment_error.dart'; import 'attachment_title.dart'; -import 'full_screen_image.dart'; import 'utils.dart'; class GiphyAttachment extends StatelessWidget { final Attachment attachment; final MessageTheme messageTheme; final Message message; + final Size size; const GiphyAttachment({ Key key, this.attachment, this.messageTheme, this.message, + this.size, }) : super(key: key); @override @@ -36,39 +37,26 @@ class GiphyAttachment extends StatelessWidget { children: [ Stack( children: [ - Hero( - tag: attachment.imageUrl ?? - attachment.assetUrl ?? - attachment.thumbUrl, - child: CachedNetworkImage( - imageBuilder: (context, provider) { - return GestureDetector( - child: Image(image: provider), - onTap: () { - Navigator.push(context, MaterialPageRoute(builder: (_) { - return FullScreenImage( - url: attachment.imageUrl ?? - attachment.assetUrl ?? - attachment.thumbUrl, - ); - })); - }, - ); - }, - placeholder: (_, __) { - return Container( - width: 200, - height: 140, - ); - }, - imageUrl: attachment.thumbUrl ?? - attachment.imageUrl ?? - attachment.assetUrl, - errorWidget: (context, url, error) => AttachmentError( - attachment: attachment, - ), - fit: BoxFit.cover, + CachedNetworkImage( + height: size?.height, + width: size?.width, + placeholder: (_, __) { + return Container( + width: size?.width, + height: size?.height, + child: Center( + child: CircularProgressIndicator(), + ), + ); + }, + imageUrl: attachment.thumbUrl ?? + attachment.imageUrl ?? + attachment.assetUrl, + errorWidget: (context, url, error) => AttachmentError( + attachment: attachment, + size: size, ), + fit: BoxFit.cover, ), if (attachment.titleLink != null || attachment.ogScrapeUrl != null) Positioned.fill( @@ -85,9 +73,14 @@ class GiphyAttachment extends StatelessWidget { ], ), if (attachment.title != null) - AttachmentTitle( - messageTheme: messageTheme, - attachment: attachment, + Container( + alignment: Alignment.bottomCenter, + child: Material( + child: AttachmentTitle( + messageTheme: messageTheme, + attachment: attachment, + ), + ), ), if (attachment.actions != null) AttachmentActions( diff --git a/lib/src/image_attachment.dart b/lib/src/image_attachment.dart index eab4ada6..d1673dad 100644 --- a/lib/src/image_attachment.dart +++ b/lib/src/image_attachment.dart @@ -10,11 +10,13 @@ import 'utils.dart'; class ImageAttachment extends StatelessWidget { final Attachment attachment; final MessageTheme messageTheme; + final Size size; const ImageAttachment({ Key key, this.attachment, this.messageTheme, + this.size, }) : super(key: key); @override @@ -26,38 +28,34 @@ class ImageAttachment extends StatelessWidget { attachment: attachment, ); } - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Stack( - children: [ - Hero( - tag: attachment.imageUrl ?? - attachment.assetUrl ?? - attachment.thumbUrl, - child: CachedNetworkImage( - imageBuilder: (context, provider) { - return GestureDetector( - child: Image( - image: provider, - fit: BoxFit.cover, - ), - onTap: () { - Navigator.push(context, MaterialPageRoute(builder: (_) { - return FullScreenImage( - url: attachment.imageUrl ?? - attachment.assetUrl ?? - attachment.thumbUrl, - ); - })); - }, + return SizedBox.fromSize( + size: size, + child: Stack( + children: [ + Hero( + tag: attachment.imageUrl ?? + attachment.assetUrl ?? + attachment.thumbUrl, + child: GestureDetector( + onTap: () { + Navigator.push(context, MaterialPageRoute(builder: (_) { + return FullScreenImage( + url: attachment.imageUrl ?? + attachment.assetUrl ?? + attachment.thumbUrl, ); - }, + })); + }, + child: CachedNetworkImage( + height: size?.height, + width: size?.width, placeholder: (_, __) { return Container( - width: 200, - height: 140, + width: size?.width, + height: size?.height, + child: Center( + child: CircularProgressIndicator(), + ), ); }, imageUrl: attachment.thumbUrl ?? @@ -65,30 +63,38 @@ class ImageAttachment extends StatelessWidget { attachment.assetUrl, errorWidget: (context, url, error) => AttachmentError( attachment: attachment, + size: size, ), fit: BoxFit.cover, ), ), - if (attachment.titleLink != null || attachment.ogScrapeUrl != null) - Positioned.fill( + ), + if (attachment.title != null) + Positioned.fill( + child: Align( + alignment: Alignment.bottomCenter, child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () => launchURL( - context, - attachment.titleLink ?? attachment.ogScrapeUrl, - ), + child: AttachmentTitle( + messageTheme: messageTheme, + attachment: attachment, ), ), ), - ], - ), - if (attachment.title != null) - AttachmentTitle( - messageTheme: messageTheme, - attachment: attachment, - ), - ], + ), + if (attachment.titleLink != null || attachment.ogScrapeUrl != null) + Positioned.fill( + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => launchURL( + context, + attachment.titleLink ?? attachment.ogScrapeUrl, + ), + ), + ), + ), + ], + ), ); } } diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 8e4f85ba..a9f0e642 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -43,7 +43,6 @@ class MessageWidget extends StatelessWidget { final bool showReplyIndicator; final bool isParent; final bool showUsername; - final bool showVideoFullScreen; final bool showTimestamp; final bool showDeleteMessage; final bool showEditMessage; @@ -83,7 +82,6 @@ class MessageWidget extends StatelessWidget { this.editMessageInputBuilder, this.textBuilder, Map customAttachmentBuilders, - this.showVideoFullScreen = true, this.padding, this.textPadding = const EdgeInsets.all(8.0), this.attachmentPadding = EdgeInsets.zero, @@ -92,13 +90,20 @@ class MessageWidget extends StatelessWidget { return ImageAttachment( attachment: attachment, messageTheme: messageTheme, + size: Size( + MediaQuery.of(context).size.width * 0.8, + MediaQuery.of(context).size.height * 0.3, + ), ); }, 'video': (context, message, attachment) { return VideoAttachment( - enableFullScreen: showVideoFullScreen, attachment: attachment, messageTheme: messageTheme, + size: Size( + MediaQuery.of(context).size.width * 0.8, + MediaQuery.of(context).size.height * 0.3, + ), ); }, 'giphy': (context, message, attachment) { @@ -106,11 +111,19 @@ class MessageWidget extends StatelessWidget { attachment: attachment, messageTheme: messageTheme, message: message, + size: Size( + MediaQuery.of(context).size.width * 0.8, + MediaQuery.of(context).size.height * 0.3, + ), ); }, 'file': (context, message, attachment) { return FileAttachment( attachment: attachment, + size: Size( + MediaQuery.of(context).size.width * 0.8, + MediaQuery.of(context).size.height * 0.3, + ), ); }, }..addAll(customAttachmentBuilders ?? {}), @@ -165,7 +178,7 @@ class MessageWidget extends StatelessWidget { SizedBox( width: messageTheme .avatarTheme.constraints.maxWidth + - 10, + 8, ), Flexible( child: Padding( @@ -228,7 +241,7 @@ class MessageWidget extends StatelessWidget { ((message.reactionCounts.values .where((element) => element > 0) .length ~/ - 4) + + 5) + 1); } diff --git a/lib/src/video_attachment.dart b/lib/src/video_attachment.dart index 0d3339bb..2b4b1c7c 100644 --- a/lib/src/video_attachment.dart +++ b/lib/src/video_attachment.dart @@ -1,6 +1,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:chewie/chewie.dart'; import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/src/full_screen_video.dart'; import 'package:stream_chat_flutter/src/utils.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; @@ -10,14 +11,14 @@ import 'attachment_title.dart'; class VideoAttachment extends StatefulWidget { final Attachment attachment; - final bool enableFullScreen; final MessageTheme messageTheme; + final Size size; VideoAttachment({ Key key, @required this.attachment, @required this.messageTheme, - this.enableFullScreen = true, + this.size, }) : super(key: key); @override @@ -33,23 +34,25 @@ class _VideoAttachmentState extends State { Widget build(BuildContext context) { if (!initialized) { return Container( - height: 100, - width: 100, + height: widget.size?.height ?? 100, + width: widget.size?.width ?? 100, child: Center( child: CircularProgressIndicator(), ), ); } _chewieController = ChewieController( - allowFullScreen: widget.enableFullScreen, videoPlayerController: _videoPlayerController, autoInitialize: false, + showControls: false, aspectRatio: _videoPlayerController.value.aspectRatio, errorBuilder: (_, e) { if (widget.attachment.thumbUrl != null) { return Stack( children: [ Container( + height: widget.size?.height, + width: widget.size?.width, decoration: BoxDecoration( image: DecorationImage( fit: BoxFit.cover, @@ -72,22 +75,62 @@ class _VideoAttachmentState extends State { } return AttachmentError( attachment: widget.attachment, + size: widget.size, ); }); - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Chewie( - controller: _chewieController, - ), - if (widget.attachment.title != null) - AttachmentTitle( - messageTheme: widget.messageTheme, - attachment: widget.attachment, + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => FullScreenVideo( + attachment: widget.attachment, + ), ), - ], + ); + }, + child: Container( + height: widget.size?.height, + width: widget.size?.width, + child: Flex( + direction: Axis.vertical, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: FittedBox( + fit: BoxFit.cover, + child: Stack( + children: [ + Chewie( + controller: _chewieController, + ), + Positioned.fill( + child: Center( + child: Material( + shape: CircleBorder(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Icon(Icons.play_arrow), + ), + ), + ), + ), + ], + ), + ), + ), + if (widget.attachment.title != null) + Material( + child: AttachmentTitle( + messageTheme: widget.messageTheme, + attachment: widget.attachment, + ), + ), + ], + ), + ), ); }