extract videoattachment
This commit is contained in:
@@ -67,6 +67,7 @@ void main() async {
|
||||
final client = Client(
|
||||
'b67pax5b2wdq',
|
||||
logLevel: Level.INFO,
|
||||
persistenceEnabled: false,
|
||||
showLocalNotification: Platform.isAndroid ? showLocalNotification : null,
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
|
||||
class AttachmentError extends StatelessWidget {
|
||||
final Attachment attachment;
|
||||
|
||||
const AttachmentError({
|
||||
Key key,
|
||||
@required this.attachment,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (attachment.localUri != null) {
|
||||
return Image.file(
|
||||
File(attachment.localUri.path),
|
||||
);
|
||||
}
|
||||
return Center(
|
||||
child: Container(
|
||||
width: 200,
|
||||
height: 140,
|
||||
color: Color(0xffd0021B).withOpacity(.1),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.error_outline,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+17
-123
@@ -1,13 +1,11 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:chewie/chewie.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:jiffy/jiffy.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_flutter/src/attachment_error.dart';
|
||||
import 'package:stream_chat_flutter/src/full_screen_image.dart';
|
||||
import 'package:stream_chat_flutter/src/message_input.dart';
|
||||
import 'package:stream_chat_flutter/src/message_list_view.dart';
|
||||
@@ -17,9 +15,9 @@ import 'package:stream_chat_flutter/src/sending_indicator.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_channel.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
||||
import 'package:stream_chat_flutter/src/user_avatar.dart';
|
||||
import 'package:stream_chat_flutter/src/utils.dart';
|
||||
import 'package:stream_chat_flutter/src/video_attachment.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
import 'deleted_message.dart';
|
||||
import 'stream_chat.dart';
|
||||
@@ -81,9 +79,6 @@ class MessageWidget extends StatefulWidget {
|
||||
|
||||
class _MessageWidgetState extends State<MessageWidget>
|
||||
with AutomaticKeepAliveClientMixin, TickerProviderStateMixin {
|
||||
final Map<String, ChangeNotifier> _videoControllers = {};
|
||||
final Map<String, ChangeNotifier> _chuwieControllers = {};
|
||||
|
||||
MessageTheme _messageTheme;
|
||||
StreamChatState _streamChat;
|
||||
StreamChannelState _streamChannel;
|
||||
@@ -219,7 +214,10 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
|
||||
Widget attachmentWidget;
|
||||
if (attachment.type == 'video') {
|
||||
attachmentWidget = _buildVideo(attachment);
|
||||
attachmentWidget = VideoAttachment(
|
||||
attachment: attachment,
|
||||
enableFullScreen: widget.showVideoFullScreen,
|
||||
);
|
||||
} else if (attachment.type == 'image' ||
|
||||
attachment.type == 'giphy') {
|
||||
attachmentWidget = _buildImage(attachment);
|
||||
@@ -227,7 +225,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
attachmentWidget = Material(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
_launchURL(attachment.assetUrl);
|
||||
launchURL(context, attachment.assetUrl);
|
||||
},
|
||||
child: Container(
|
||||
width: 100,
|
||||
@@ -478,7 +476,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
print('tap on ${mentionedUser.name}');
|
||||
}
|
||||
} else {
|
||||
_launchURL(link);
|
||||
launchURL(context, link);
|
||||
}
|
||||
},
|
||||
styleSheet: MarkdownStyleSheet.fromTheme(
|
||||
@@ -558,7 +556,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => _launchURL(attachment.titleLink),
|
||||
onTap: () => launchURL(context, attachment.titleLink),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -568,7 +566,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (attachment.titleLink != null) {
|
||||
_launchURL(attachment.titleLink);
|
||||
launchURL(context, attachment.titleLink);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
@@ -896,7 +894,9 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
if (attachment.thumbUrl == null &&
|
||||
attachment.imageUrl == null &&
|
||||
attachment.assetUrl == null) {
|
||||
return _buildErrorImage(attachment);
|
||||
return AttachmentError(
|
||||
attachment: attachment,
|
||||
);
|
||||
}
|
||||
|
||||
return Hero(
|
||||
@@ -924,122 +924,16 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
},
|
||||
imageUrl:
|
||||
attachment.thumbUrl ?? attachment.imageUrl ?? attachment.assetUrl,
|
||||
errorWidget: (context, url, error) => _buildErrorImage(attachment),
|
||||
errorWidget: (context, url, error) => AttachmentError(
|
||||
attachment: attachment,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildErrorImage(Attachment attachment) {
|
||||
if (attachment.localUri != null) {
|
||||
return Image.file(
|
||||
File(attachment.localUri.path),
|
||||
);
|
||||
}
|
||||
return Center(
|
||||
child: Container(
|
||||
width: 200,
|
||||
height: 140,
|
||||
color: Color(0xffd0021B).withOpacity(.1),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.error_outline,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVideo(
|
||||
Attachment attachment,
|
||||
) {
|
||||
VideoPlayerController videoController;
|
||||
if (_videoControllers.containsKey(attachment.assetUrl)) {
|
||||
videoController = _videoControllers[attachment.assetUrl];
|
||||
} else {
|
||||
videoController = VideoPlayerController.network(attachment.assetUrl);
|
||||
_videoControllers[attachment.assetUrl] = videoController;
|
||||
}
|
||||
|
||||
return FutureBuilder<void>(
|
||||
future: videoController.value.initialized
|
||||
? Future.value(true)
|
||||
: videoController.initialize(),
|
||||
builder: (_, snapshot) {
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return Container(
|
||||
height: 100,
|
||||
width: 100,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
}
|
||||
ChewieController chewieController;
|
||||
if (_chuwieControllers.containsKey(attachment.assetUrl)) {
|
||||
chewieController = _chuwieControllers[attachment.assetUrl];
|
||||
} else {
|
||||
chewieController = ChewieController(
|
||||
allowFullScreen: widget.showVideoFullScreen,
|
||||
videoPlayerController: videoController,
|
||||
autoInitialize: false,
|
||||
aspectRatio: videoController.value.aspectRatio,
|
||||
errorBuilder: (_, e) {
|
||||
if (attachment.thumbUrl != null) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: CachedNetworkImageProvider(
|
||||
attachment.thumbUrl,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (attachment.titleLink != null)
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => _launchURL(attachment.titleLink),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return _buildErrorImage(attachment);
|
||||
});
|
||||
_chuwieControllers[attachment.assetUrl] = chewieController;
|
||||
}
|
||||
return Chewie(
|
||||
key: ValueKey<String>(
|
||||
'ATTACHMENT-${attachment.title}-${widget.message.id}'),
|
||||
controller: chewieController,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _launchURL(String url) async {
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
} else {
|
||||
Scaffold.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Cannot launch the url'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_videoControllers.values.forEach((element) {
|
||||
element.dispose();
|
||||
});
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
Future<void> launchURL(BuildContext context, String url) async {
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
} else {
|
||||
Scaffold.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Cannot launch the url'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
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/utils.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
import 'attachment_error.dart';
|
||||
|
||||
class VideoAttachment extends StatefulWidget {
|
||||
final Attachment attachment;
|
||||
final bool enableFullScreen;
|
||||
|
||||
VideoAttachment({
|
||||
Key key,
|
||||
@required this.attachment,
|
||||
this.enableFullScreen = true,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_VideoAttachmentState createState() => _VideoAttachmentState();
|
||||
}
|
||||
|
||||
class _VideoAttachmentState extends State<VideoAttachment> {
|
||||
ChewieController _chewieController;
|
||||
VideoPlayerController _videoPlayerController;
|
||||
bool initialized = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!initialized) {
|
||||
return Container(
|
||||
height: 100,
|
||||
width: 100,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
}
|
||||
_chewieController = ChewieController(
|
||||
allowFullScreen: widget.enableFullScreen,
|
||||
videoPlayerController: _videoPlayerController,
|
||||
autoInitialize: false,
|
||||
aspectRatio: _videoPlayerController.value.aspectRatio,
|
||||
errorBuilder: (_, e) {
|
||||
if (widget.attachment.thumbUrl != null) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: CachedNetworkImageProvider(
|
||||
widget.attachment.thumbUrl,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.attachment.titleLink != null)
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () =>
|
||||
launchURL(context, widget.attachment.titleLink),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return AttachmentError(
|
||||
attachment: widget.attachment,
|
||||
);
|
||||
});
|
||||
|
||||
return Chewie(
|
||||
controller: _chewieController,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_videoPlayerController = VideoPlayerController.network(
|
||||
widget.attachment.localUri ?? widget.attachment.assetUrl);
|
||||
_videoPlayerController.initialize().then((_) {
|
||||
if (_videoPlayerController.value.initialized) {
|
||||
setState(() {
|
||||
initialized = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_videoPlayerController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user