fix video attachment fullscreen

This commit is contained in:
Salvatore Giordano
2020-05-13 15:51:45 +02:00
parent 4dcdc457f4
commit a1a3cb177d
8 changed files with 142 additions and 69 deletions
+1 -1
View File
@@ -94,7 +94,7 @@ class MyApp extends StatelessWidget {
return MaterialApp( return MaterialApp(
theme: ThemeData.light(), theme: ThemeData.light(),
darkTheme: ThemeData.dark(), darkTheme: ThemeData.dark(),
themeMode: ThemeMode.system, themeMode: ThemeMode.dark,
home: Container( home: Container(
child: StreamChat( child: StreamChat(
client: client, client: client,
+12 -13
View File
@@ -32,7 +32,6 @@ class _FullScreenVideoState extends State<FullScreenVideo> {
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
); );
} }
return Chewie( return Chewie(
controller: _chewieController, controller: _chewieController,
); );
@@ -49,28 +48,28 @@ class _FullScreenVideoState extends State<FullScreenVideo> {
_videoPlayerController.initialize().whenComplete(() { _videoPlayerController.initialize().whenComplete(() {
setState(() { setState(() {
initialized = true; initialized = true;
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController,
autoInitialize: false,
aspectRatio: _videoPlayerController.value.aspectRatio,
);
}); });
}); });
_chewieController = ChewieController( VoidCallback errorListener;
videoPlayerController: _videoPlayerController, errorListener = () {
autoInitialize: false,
aspectRatio: _videoPlayerController.value.aspectRatio,
);
_videoPlayerController.addListener(() {
if (_videoPlayerController.value.hasError) { if (_videoPlayerController.value.hasError) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) { Navigator.pop(context);
Navigator.pop(context); launchURL(context, widget.attachment.titleLink);
launchURL(context, widget.attachment.titleLink);
});
} }
}); _videoPlayerController.removeListener(errorListener);
};
_videoPlayerController.addListener(errorListener);
} }
@override @override
void dispose() { void dispose() {
_videoPlayerController.dispose(); _videoPlayerController.dispose();
_chewieController.dispose();
super.dispose(); super.dispose();
} }
} }
+51 -45
View File
@@ -32,55 +32,61 @@ class ImageAttachment extends StatelessWidget {
size: size, size: size,
child: Stack( child: Stack(
children: <Widget>[ children: <Widget>[
Hero( Column(
tag: attachment.imageUrl ?? children: <Widget>[
attachment.assetUrl ?? Expanded(
attachment.thumbUrl, child: Hero(
child: GestureDetector( tag: attachment.imageUrl ??
onTap: () { attachment.assetUrl ??
Navigator.push(context, MaterialPageRoute(builder: (_) { attachment.thumbUrl,
return FullScreenImage( child: GestureDetector(
url: attachment.imageUrl ?? onTap: () {
attachment.assetUrl ?? Navigator.push(context, MaterialPageRoute(builder: (_) {
attachment.thumbUrl, return FullScreenImage(
); url: attachment.imageUrl ??
})); attachment.assetUrl ??
}, attachment.thumbUrl,
child: CachedNetworkImage( );
height: size?.height, }));
width: size?.width, },
placeholder: (_, __) { child: CachedNetworkImage(
return Container( height: size?.height,
width: size?.width, width: size?.width,
height: size?.height, placeholder: (_, __) {
child: Center( return Container(
child: CircularProgressIndicator(), 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,
), ),
);
},
imageUrl: attachment.thumbUrl ??
attachment.imageUrl ??
attachment.assetUrl,
errorWidget: (context, url, error) => AttachmentError(
attachment: attachment,
size: size,
),
fit: BoxFit.cover,
),
),
),
if (attachment.title != null)
Positioned.fill(
child: Align(
alignment: Alignment.bottomCenter,
child: Material(
child: AttachmentTitle(
messageTheme: messageTheme,
attachment: attachment,
), ),
), ),
), ),
), if (attachment.title != null)
Positioned.fill(
child: Align(
alignment: Alignment.bottomCenter,
child: Material(
child: AttachmentTitle(
messageTheme: messageTheme,
attachment: attachment,
),
),
),
),
],
),
if (attachment.titleLink != null || attachment.ogScrapeUrl != null) if (attachment.titleLink != null || attachment.ogScrapeUrl != null)
Positioned.fill( Positioned.fill(
child: Material( child: Material(
+62 -4
View File
@@ -13,41 +13,98 @@ import 'message_text.dart';
typedef AttachmentBuilder = Widget Function(BuildContext, Message, Attachment); typedef AttachmentBuilder = Widget Function(BuildContext, Message, Attachment);
/// The display behaviour of a widget
enum DisplayWidget { enum DisplayWidget {
/// Hides the widget replacing its space with a spacer
hide, hide,
/// Hides the widget not replacing its space
gone, gone,
/// Shows the widget normally
show, show,
} }
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_widget.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_widget_paint.png)
///
/// It shows a message with reactions, replies and user avatar.
///
/// Usually you don't use this widget as it's the default message widget used by [MessageListView].
///
/// The widget components render the ui based on the first ancestor of type [StreamChatTheme].
/// Modify it to change the widget appearance.
class MessageWidget extends StatelessWidget { class MessageWidget extends StatelessWidget {
/// Function called on mention tap
final void Function(User) onMentionTap; final void Function(User) onMentionTap;
/// The function called when tapping on replies
final void Function(Message) onThreadTap; final void Function(Message) onThreadTap;
final Widget Function(BuildContext, Message) editMessageInputBuilder; final Widget Function(BuildContext, Message) editMessageInputBuilder;
final Widget Function(BuildContext, Message) textBuilder; final Widget Function(BuildContext, Message) textBuilder;
/// Function called on long press
final void Function(BuildContext, Message) onMessageActions; final void Function(BuildContext, Message) onMessageActions;
/// The message
final Message message; final Message message;
/// The message theme
final MessageTheme messageTheme; final MessageTheme messageTheme;
/// If true the widget will be mirrored
final bool reverse; final bool reverse;
/// The shape of the message text
final ShapeBorder shape; final ShapeBorder shape;
/// The shape of an attachment
final ShapeBorder attachmentShape; final ShapeBorder attachmentShape;
/// The borderside of the message text
final BorderSide borderSide; final BorderSide borderSide;
/// The borderside of an attachment
final BorderSide attachmentBorderSide; final BorderSide attachmentBorderSide;
/// The border radius of the message text
final BorderRadiusGeometry borderRadiusGeometry; final BorderRadiusGeometry borderRadiusGeometry;
/// The border radius of an attachment
final BorderRadiusGeometry attachmentBorderRadiusGeometry; final BorderRadiusGeometry attachmentBorderRadiusGeometry;
/// The padding of the widget
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
/// The internal padding of the message text
final EdgeInsetsGeometry textPadding; final EdgeInsetsGeometry textPadding;
/// The internal padding of an attachment
final EdgeInsetsGeometry attachmentPadding; final EdgeInsetsGeometry attachmentPadding;
/// It controls the display behaviour of the user avatar
final DisplayWidget showUserAvatar; final DisplayWidget showUserAvatar;
/// It controls the display behaviour of the sending indicator
final DisplayWidget showSendingIndicator; final DisplayWidget showSendingIndicator;
/// If true the widget will show the reactions
final bool showReactions; final bool showReactions;
/// If true the widget will show the reply indicator
final bool showReplyIndicator; final bool showReplyIndicator;
final bool isParent;
/// The function called when tapping on UserAvatar
final void Function(User) onUserAvatarTap;
/// If true show the users username next to the timestamp of the message
final bool showUsername; final bool showUsername;
final bool showTimestamp; final bool showTimestamp;
final bool showDeleteMessage; final bool showDeleteMessage;
final bool showEditMessage; final bool showEditMessage;
final Map<String, AttachmentBuilder> attachmentBuilders; final Map<String, AttachmentBuilder> attachmentBuilders;
final Map<String, String> reactionToEmoji = {
final Map<String, String> _reactionToEmoji = {
'love': '❤️', 'love': '❤️',
'haha': '😂', 'haha': '😂',
'like': '👍', 'like': '👍',
@@ -71,13 +128,13 @@ class MessageWidget extends StatelessWidget {
this.showUserAvatar = DisplayWidget.show, this.showUserAvatar = DisplayWidget.show,
this.showSendingIndicator = DisplayWidget.show, this.showSendingIndicator = DisplayWidget.show,
this.showReplyIndicator = true, this.showReplyIndicator = true,
this.isParent = false,
this.onThreadTap, this.onThreadTap,
this.showUsername = true, this.showUsername = true,
this.showTimestamp = true, this.showTimestamp = true,
this.showReactions = true, this.showReactions = true,
this.showDeleteMessage = true, this.showDeleteMessage = true,
this.showEditMessage = true, this.showEditMessage = true,
this.onUserAvatarTap,
this.onMessageActions, this.onMessageActions,
this.editMessageInputBuilder, this.editMessageInputBuilder,
this.textBuilder, this.textBuilder,
@@ -338,7 +395,7 @@ class MessageWidget extends StatelessWidget {
Text _buildReactionsText(BuildContext context) { Text _buildReactionsText(BuildContext context) {
return Text( return Text(
message.reactionCounts.keys.map((reactionType) { message.reactionCounts.keys.map((reactionType) {
return reactionToEmoji[reactionType] ?? '?'; return _reactionToEmoji[reactionType] ?? '?';
}).join(' ') + }).join(' ') +
' ${message.reactionCounts.values.fold(0, (t, v) => v + t).toString()}', ' ${message.reactionCounts.values.fold(0, (t, v) => v + t).toString()}',
style: TextStyle( style: TextStyle(
@@ -499,6 +556,7 @@ class MessageWidget extends StatelessWidget {
Offset(0, messageTheme.avatarTheme.constraints.maxHeight / 2), Offset(0, messageTheme.avatarTheme.constraints.maxHeight / 2),
child: UserAvatar( child: UserAvatar(
user: message.user, user: message.user,
onTap: onUserAvatarTap,
constraints: messageTheme.avatarTheme.constraints, constraints: messageTheme.avatarTheme.constraints,
), ),
), ),
+10 -1
View File
@@ -24,7 +24,16 @@ class StreamChatTheme extends InheritedWidget {
/// Use this method to get the current [StreamChatThemeData] instance /// Use this method to get the current [StreamChatThemeData] instance
static StreamChatThemeData of(BuildContext context) { static StreamChatThemeData of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<StreamChatTheme>().data; final streamChatTheme =
context.dependOnInheritedWidgetOfExactType<StreamChatTheme>();
if (streamChatTheme == null) {
throw Exception(
'You must have a StreamChatTheme widget at the top of your widget tree',
);
}
return streamChatTheme.data;
} }
} }
+3 -3
View File
@@ -43,7 +43,7 @@ class _VideoAttachmentState extends State<VideoAttachment> {
} }
_chewieController = ChewieController( _chewieController = ChewieController(
videoPlayerController: _videoPlayerController, videoPlayerController: _videoPlayerController,
autoInitialize: false, autoInitialize: true,
showControls: false, showControls: false,
aspectRatio: _videoPlayerController.value.aspectRatio, aspectRatio: _videoPlayerController.value.aspectRatio,
errorBuilder: (_, e) { errorBuilder: (_, e) {
@@ -137,8 +137,8 @@ class _VideoAttachmentState extends State<VideoAttachment> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_videoPlayerController = VideoPlayerController.network( _videoPlayerController =
widget.attachment.localUri ?? widget.attachment.assetUrl); VideoPlayerController.network(widget.attachment.assetUrl);
_videoPlayerController.initialize().whenComplete(() { _videoPlayerController.initialize().whenComplete(() {
setState(() { setState(() {
initialized = true; initialized = true;
+1
View File
@@ -9,6 +9,7 @@ export 'src/channels_bloc.dart';
export 'src/date_divider.dart'; export 'src/date_divider.dart';
export 'src/deleted_message.dart'; export 'src/deleted_message.dart';
export 'src/file_attachment.dart'; export 'src/file_attachment.dart';
export 'src/full_screen_video.dart';
export 'src/giphy_attachment.dart'; export 'src/giphy_attachment.dart';
export 'src/image_attachment.dart'; export 'src/image_attachment.dart';
export 'src/message_input.dart'; export 'src/message_input.dart';
+2 -2
View File
@@ -15,10 +15,10 @@ dependencies:
flutter_portal: ^0.1.0 flutter_portal: ^0.1.0
cached_network_image: ^2.2.0+1 cached_network_image: ^2.2.0+1
flutter_markdown: ^0.3.5 flutter_markdown: ^0.3.5
url_launcher: ^5.4.5 url_launcher: ^5.4.7
video_player: ^0.10.10 video_player: ^0.10.10
chewie: ^0.9.10 chewie: ^0.9.10
file_picker: ^1.8.0+2 file_picker: ^1.9.0+1
image_picker: ^0.6.6+1 image_picker: ^0.6.6+1
flutter_keyboard_visibility: ^2.0.0 flutter_keyboard_visibility: ^2.0.0
stream_chat: stream_chat: