This commit is contained in:
Deven Joshi
2021-05-05 17:47:58 +05:30
parent dca6b10c41
commit 09c6799af8
4 changed files with 81 additions and 69 deletions
@@ -2,7 +2,10 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/user_avatar.dart'; import 'package:stream_chat_flutter/src/user_avatar.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
/// Displays a list of users who reacted
class UserReactionDisplay extends StatelessWidget { class UserReactionDisplay extends StatelessWidget {
/// Constructor for creating a [UserReactionDisplay]
const UserReactionDisplay({ const UserReactionDisplay({
Key? key, Key? key,
required this.reactionToEmoji, required this.reactionToEmoji,
@@ -10,13 +13,17 @@ class UserReactionDisplay extends StatelessWidget {
this.size = 30, this.size = 30,
}) : super(key: key); }) : super(key: key);
/// Reaction map
final Map<String, String> reactionToEmoji; final Map<String, String> reactionToEmoji;
/// Message which is reacted to
final Message message; final Message message;
/// Size of Icon
final double size; final double size;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => Container(
return Container(
color: Colors.black87, color: Colors.black87,
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -25,9 +32,8 @@ class UserReactionDisplay extends StatelessWidget {
children: reactionToEmoji.keys.map((reactionType) { children: reactionToEmoji.keys.map((reactionType) {
final firstUserReaction = message.latestReactions! final firstUserReaction = message.latestReactions!
.firstWhere((element) => element.type == reactionType, .firstWhere((element) => element.type == reactionType,
orElse: () { //ignore: unnecessary_parenthesis
return null; orElse: (() => null) as Reaction Function()?);
} as Reaction Function()?);
if (firstUserReaction.user == null) { if (firstUserReaction.user == null) {
return IconButton( return IconButton(
@@ -52,5 +58,4 @@ class UserReactionDisplay extends StatelessWidget {
}).toList(), }).toList(),
), ),
); );
}
} }
+20 -25
View File
@@ -13,7 +13,7 @@ Future<void> launchURL(BuildContext context, String? url) async {
} else { } else {
// ignore: deprecated_member_use // ignore: deprecated_member_use
Scaffold.of(context).showSnackBar( Scaffold.of(context).showSnackBar(
SnackBar( const SnackBar(
content: Text('Cannot launch the url'), content: Text('Cannot launch the url'),
), ),
); );
@@ -27,11 +27,10 @@ Future<bool?> showConfirmationDialog(
Widget? icon, Widget? icon,
String? question, String? question,
String? cancelText, String? cancelText,
}) { }) => showModalBottomSheet(
return showModalBottomSheet(
backgroundColor: StreamChatTheme.of(context).colorTheme.white, backgroundColor: StreamChatTheme.of(context).colorTheme.white,
context: context, context: context,
shape: RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(16), topLeft: Radius.circular(16),
topRight: Radius.circular(16), topRight: Radius.circular(16),
@@ -42,20 +41,20 @@ Future<bool?> showConfirmationDialog(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
SizedBox(height: 26), const SizedBox(height: 26),
if (icon != null) icon, if (icon != null) icon,
SizedBox(height: 26), const SizedBox(height: 26),
Text( Text(
title, title,
style: StreamChatTheme.of(context).textTheme.headlineBold, style: StreamChatTheme.of(context).textTheme.headlineBold,
), ),
SizedBox(height: 7), const SizedBox(height: 7),
if (question != null) if (question != null)
Text( Text(
question, question,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 36), const SizedBox(height: 36),
Container( Container(
color: effect.color!.withOpacity(effect.alpha ?? 1), color: effect.color!.withOpacity(effect.alpha ?? 1),
height: 1, height: 1,
@@ -110,8 +109,8 @@ Future<bool?> showConfirmationDialog(
), ),
); );
}); });
}
/// Shows info dialog
Future<bool?> showInfoDialog( Future<bool?> showInfoDialog(
BuildContext context, { BuildContext context, {
required String title, required String title,
@@ -119,26 +118,24 @@ Future<bool?> showInfoDialog(
Widget? icon, Widget? icon,
String? details, String? details,
StreamChatThemeData? theme, StreamChatThemeData? theme,
}) { }) => showModalBottomSheet(
return showModalBottomSheet(
backgroundColor: backgroundColor:
theme?.colorTheme.white ?? StreamChatTheme.of(context).colorTheme.white, theme?.colorTheme.white ?? StreamChatTheme.of(context).colorTheme.white,
context: context, context: context,
shape: RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(16), topLeft: Radius.circular(16),
topRight: Radius.circular(16), topRight: Radius.circular(16),
)), )),
builder: (context) { builder: (context) => SafeArea(
return SafeArea(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
SizedBox( const SizedBox(
height: 26, height: 26,
), ),
if (icon != null) icon, if (icon != null) icon,
SizedBox( const SizedBox(
height: 26, height: 26,
), ),
Text( Text(
@@ -146,11 +143,11 @@ Future<bool?> showInfoDialog(
style: theme?.textTheme.headlineBold ?? style: theme?.textTheme.headlineBold ??
StreamChatTheme.of(context).textTheme.headlineBold, StreamChatTheme.of(context).textTheme.headlineBold,
), ),
SizedBox( const SizedBox(
height: 7, height: 7,
), ),
if (details != null) Text(details), if (details != null) Text(details),
SizedBox( const SizedBox(
height: 36, height: 36,
), ),
Container( Container(
@@ -175,10 +172,8 @@ Future<bool?> showInfoDialog(
), ),
], ],
), ),
); ),
},
); );
}
/// Get random png with initials /// Get random png with initials
String getRandomPicUrl(User user) => String getRandomPicUrl(User user) =>
@@ -335,15 +330,16 @@ StreamSvgIcon getFileTypeImage(String? type) {
} }
} }
/// Wraps attachment widget with custom shape
Widget wrapAttachmentWidget( Widget wrapAttachmentWidget(
BuildContext context, BuildContext context,
Widget attachmentWidget, Widget attachmentWidget,
ShapeBorder attachmentShape, ShapeBorder attachmentShape,
// ignore: avoid_positional_boolean_parameters
bool reverse, bool reverse,
BorderRadius borderRadius, BorderRadius borderRadius,
) { ) => ClipRRect(
return ClipRRect( borderRadius: borderRadius,
borderRadius: borderRadius,
child: Material( child: Material(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
shape: attachmentShape, shape: attachmentShape,
@@ -355,4 +351,3 @@ Widget wrapAttachmentWidget(
), ),
), ),
); );
}
@@ -5,12 +5,14 @@ import 'package:synchronized/synchronized.dart';
import 'package:video_compress/video_compress.dart'; import 'package:video_compress/video_compress.dart';
import 'package:video_thumbnail/video_thumbnail.dart'; import 'package:video_thumbnail/video_thumbnail.dart';
///
class IVideoService { class IVideoService {
IVideoService._();
/// Singleton instance of [IVideoService]
static final IVideoService instance = IVideoService._(); static final IVideoService instance = IVideoService._();
final _lock = Lock(); final _lock = Lock();
IVideoService._();
/// compress video from [path] /// compress video from [path]
/// compress video from [path] return [Future<MediaInfo>] /// compress video from [path] return [Future<MediaInfo>]
/// ///
@@ -26,18 +28,20 @@ class IVideoService {
/// ); /// );
/// debugPrint(info.toJson()); /// debugPrint(info.toJson());
/// ``` /// ```
Future<MediaInfo?> compressVideo(String? path) async { Future<MediaInfo?> compressVideo(String? path) async => _lock.synchronized(
return _lock.synchronized(() { () => VideoCompress.compressVideo(
return VideoCompress.compressVideo( path!,
path!, ),
); );
});
}
/// Generates a thumbnail image data in memory as UInt8List, it can be easily used by Image.memory(...). /// Generates a thumbnail image data in memory as UInt8List,
/// The video can be a local video file, or an URL repreents iOS or Android native supported video format. /// it can be easily used by Image.memory(...).
/// Speicify the maximum height or width for the thumbnail or 0 for same resolution as the original video. /// The video can be a local video file, or an URL repreents iOS or
/// The lower quality value creates lower quality of the thumbnail image, but it gets ignored for PNG format. /// Android native supported video format.
/// Speicify the maximum height or width for the thumbnail or 0 for
/// same resolution as the original video.
/// The lower quality value creates lower quality of the thumbnail image,
/// but it gets ignored for PNG format.
Future<Uint8List?> generateVideoThumbnail({ Future<Uint8List?> generateVideoThumbnail({
required String video, required String video,
ImageFormat imageFormat = ImageFormat.PNG, ImageFormat imageFormat = ImageFormat.PNG,
@@ -45,17 +49,17 @@ class IVideoService {
int maxWidth = 0, int maxWidth = 0,
int timeMs = 0, int timeMs = 0,
int quality = 10, int quality = 10,
}) { }) =>
return VideoThumbnail.thumbnailData( VideoThumbnail.thumbnailData(
video: video, video: video,
imageFormat: imageFormat, imageFormat: imageFormat,
maxHeight: maxHeight, maxHeight: maxHeight,
maxWidth: maxWidth, maxWidth: maxWidth,
timeMs: timeMs, timeMs: timeMs,
quality: quality, quality: quality,
); );
}
} }
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
/// Get instance of [IVideoService]
IVideoService get VideoService => IVideoService.instance; IVideoService get VideoService => IVideoService.instance;
@@ -9,14 +9,7 @@ import 'stream_svg_icon.dart';
import 'video_service.dart'; import 'video_service.dart';
class VideoThumbnailImage extends StatefulWidget { class VideoThumbnailImage extends StatefulWidget {
final String video; /// Constructor for creating [VideoThumbnailImage]
final double? width;
final double? height;
final BoxFit? fit;
final ImageFormat format;
final Widget Function(BuildContext, Object?)? errorBuilder;
final WidgetBuilder? placeholderBuilder;
const VideoThumbnailImage({ const VideoThumbnailImage({
Key? key, Key? key,
required this.video, required this.video,
@@ -28,6 +21,25 @@ class VideoThumbnailImage extends StatefulWidget {
this.placeholderBuilder, this.placeholderBuilder,
}) : super(key: key); }) : super(key: key);
/// Video path
final String video;
/// Width of widget
final double? width;
/// Height of widget
final double? height;
/// Fit of iamge
final BoxFit? fit;
/// Image format
final ImageFormat format;
/// Builds widget on error
final Widget Function(BuildContext, Object?)? errorBuilder;
final WidgetBuilder? placeholderBuilder;
@override @override
_VideoThumbnailImageState createState() => _VideoThumbnailImageState(); _VideoThumbnailImageState createState() => _VideoThumbnailImageState();
} }
@@ -56,11 +68,9 @@ class _VideoThumbnailImageState extends State<VideoThumbnailImage> {
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => FutureBuilder<Uint8List?>(
return FutureBuilder<Uint8List?>(
future: thumbnailFuture, future: thumbnailFuture,
builder: (context, snapshot) { builder: (context, snapshot) => AnimatedSwitcher(
return AnimatedSwitcher(
duration: const Duration(milliseconds: 350), duration: const Duration(milliseconds: 350),
child: Builder( child: Builder(
key: ValueKey<AsyncSnapshot<Uint8List?>>(snapshot), key: ValueKey<AsyncSnapshot<Uint8List?>>(snapshot),
@@ -73,7 +83,7 @@ class _VideoThumbnailImageState extends State<VideoThumbnailImage> {
} }
if (!snapshot.hasData) { if (!snapshot.hasData) {
return Container( return Container(
constraints: BoxConstraints.expand(), constraints: const BoxConstraints.expand(),
child: widget.placeholderBuilder?.call(context) ?? child: widget.placeholderBuilder?.call(context) ??
Shimmer.fromColors( Shimmer.fromColors(
baseColor: StreamChatTheme.of(context) baseColor: StreamChatTheme.of(context)
@@ -97,8 +107,6 @@ class _VideoThumbnailImageState extends State<VideoThumbnailImage> {
); );
}, },
), ),
); ),
},
); );
}
} }