add reactions modal
This commit is contained in:
@@ -75,7 +75,9 @@ void main() async {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await client.setUser(
|
await client.setUser(
|
||||||
User(id: 'super-band-9'),
|
User(id: 'super-band-9', extraData: {
|
||||||
|
'name': 'John Doe',
|
||||||
|
}),
|
||||||
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.0L6lGoeLwkz0aZRUcpZKsvaXtNEDHBcezVTZ0oPq40A',
|
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.0L6lGoeLwkz0aZRUcpZKsvaXtNEDHBcezVTZ0oPq40A',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: example
|
name: example
|
||||||
description: A new Flutter project.
|
description: A new Flutter project.
|
||||||
|
|
||||||
version: 1.0.28+30
|
version: 1.0.29+31
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.2.2 <3.0.0"
|
sdk: ">=2.2.2 <3.0.0"
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/reaction_bubble.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/reaction_picker.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/stream_channel.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/stream_chat.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/user_avatar.dart';
|
||||||
|
|
||||||
|
import 'message_widget.dart';
|
||||||
|
import 'stream_chat_theme.dart';
|
||||||
|
|
||||||
|
class MessageReactionsModal extends StatelessWidget {
|
||||||
|
final Widget Function(BuildContext, Message) editMessageInputBuilder;
|
||||||
|
final void Function(Message) onThreadTap;
|
||||||
|
final Message message;
|
||||||
|
final MessageTheme messageTheme;
|
||||||
|
final bool showReactions;
|
||||||
|
final bool showDeleteMessage;
|
||||||
|
final bool showEditMessage;
|
||||||
|
final bool showReply;
|
||||||
|
final bool reverse;
|
||||||
|
final ShapeBorder messageShape;
|
||||||
|
|
||||||
|
const MessageReactionsModal({
|
||||||
|
Key key,
|
||||||
|
@required this.message,
|
||||||
|
@required this.messageTheme,
|
||||||
|
this.showReactions,
|
||||||
|
this.showDeleteMessage,
|
||||||
|
this.showEditMessage,
|
||||||
|
this.onThreadTap,
|
||||||
|
this.showReply,
|
||||||
|
this.editMessageInputBuilder,
|
||||||
|
this.messageShape,
|
||||||
|
this.reverse,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final channel = StreamChannel.of(context).channel;
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(
|
||||||
|
child: GestureDetector(
|
||||||
|
behavior: HitTestBehavior.translucent,
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: BackdropFilter(
|
||||||
|
filter: ImageFilter.blur(
|
||||||
|
sigmaX: 10,
|
||||||
|
sigmaY: 10,
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: <Widget>[
|
||||||
|
if (showReactions &&
|
||||||
|
(message.status == MessageSendingStatus.SENT ||
|
||||||
|
message.status == null))
|
||||||
|
Center(
|
||||||
|
child: ReactionPicker(
|
||||||
|
channel: channel,
|
||||||
|
message: message,
|
||||||
|
messageTheme: messageTheme,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AbsorbPointer(
|
||||||
|
child: MessageWidget(
|
||||||
|
reverse: reverse,
|
||||||
|
message: message,
|
||||||
|
messageTheme: messageTheme,
|
||||||
|
showReactions: false,
|
||||||
|
showUsername: false,
|
||||||
|
showReplyIndicator: false,
|
||||||
|
showTimestamp: false,
|
||||||
|
showSendingIndicator: DisplayWidget.gone,
|
||||||
|
shape: messageShape,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
if (message.latestReactions.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0,
|
||||||
|
),
|
||||||
|
child: Card(
|
||||||
|
clipBehavior: Clip.hardEdge,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
child: GridView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 4,
|
||||||
|
crossAxisSpacing: 16,
|
||||||
|
childAspectRatio: 0.8,
|
||||||
|
mainAxisSpacing: 22,
|
||||||
|
),
|
||||||
|
itemCount: message.latestReactions.length,
|
||||||
|
itemBuilder: (context, i) {
|
||||||
|
final reaction = message.latestReactions[i];
|
||||||
|
final isCurrentUser =
|
||||||
|
reaction.user.id == StreamChat.of(context).user.id;
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Stack(
|
||||||
|
children: [
|
||||||
|
UserAvatar(
|
||||||
|
user: reaction.user,
|
||||||
|
constraints: BoxConstraints.tightFor(
|
||||||
|
height: 64,
|
||||||
|
width: 64,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(32),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
child: ReactionBubble(
|
||||||
|
reactions: [reaction],
|
||||||
|
borderColor: isCurrentUser
|
||||||
|
? messageTheme.ownReactionsBorderColor
|
||||||
|
: messageTheme.otherReactionsBorderColor,
|
||||||
|
backgroundColor: isCurrentUser
|
||||||
|
? messageTheme.ownReactionsBackgroundColor
|
||||||
|
: messageTheme
|
||||||
|
.otherReactionsBackgroundColor,
|
||||||
|
flipTail: !isCurrentUser,
|
||||||
|
),
|
||||||
|
bottom: 0,
|
||||||
|
left: isCurrentUser ? 0 : null,
|
||||||
|
right: isCurrentUser ? 0 : null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
reaction.user.name,
|
||||||
|
style: Theme.of(context).textTheme.subtitle2,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart';
|
|||||||
import 'package:flutter_portal/flutter_portal.dart';
|
import 'package:flutter_portal/flutter_portal.dart';
|
||||||
import 'package:jiffy/jiffy.dart';
|
import 'package:jiffy/jiffy.dart';
|
||||||
import 'package:stream_chat_flutter/src/message_actions_modal.dart';
|
import 'package:stream_chat_flutter/src/message_actions_modal.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/message_reactions_modal.dart';
|
||||||
import 'package:stream_chat_flutter/src/reaction_bubble.dart';
|
import 'package:stream_chat_flutter/src/reaction_bubble.dart';
|
||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
|
|
||||||
@@ -437,7 +438,7 @@ class _MessageWidgetState extends State<MessageWidget> {
|
|||||||
!widget.message.isDeleted)
|
!widget.message.isDeleted)
|
||||||
? Container(
|
? Container(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => onLongPress(context),
|
onTap: () => _showMessageReactionsModalBottomSheet(context),
|
||||||
child: FractionallySizedBox(
|
child: FractionallySizedBox(
|
||||||
widthFactor: 0.5,
|
widthFactor: 0.5,
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -452,7 +453,7 @@ class _MessageWidgetState extends State<MessageWidget> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showMessageModalBottomSheet(BuildContext context) {
|
void _showMessageActionModalBottomSheet(BuildContext context) {
|
||||||
final channel = StreamChannel.of(context).channel;
|
final channel = StreamChannel.of(context).channel;
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -476,6 +477,30 @@ class _MessageWidgetState extends State<MessageWidget> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showMessageReactionsModalBottomSheet(BuildContext context) {
|
||||||
|
final channel = StreamChannel.of(context).channel;
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return StreamChannel(
|
||||||
|
channel: channel,
|
||||||
|
child: MessageReactionsModal(
|
||||||
|
messageTheme: widget.messageTheme,
|
||||||
|
messageShape: widget.shape ?? _getDefaultShape(context),
|
||||||
|
reverse: widget.reverse,
|
||||||
|
showDeleteMessage: widget.showDeleteMessage,
|
||||||
|
message: widget.message,
|
||||||
|
editMessageInputBuilder: widget.editMessageInputBuilder,
|
||||||
|
onThreadTap: widget.onThreadTap,
|
||||||
|
showEditMessage: widget.showEditMessage,
|
||||||
|
showReactions: widget.showReactions,
|
||||||
|
showReply:
|
||||||
|
widget.showReplyIndicator && widget.onThreadTap != null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ContinuousRectangleBorder _getDefaultShape(BuildContext context) {
|
ContinuousRectangleBorder _getDefaultShape(BuildContext context) {
|
||||||
return ContinuousRectangleBorder(
|
return ContinuousRectangleBorder(
|
||||||
side: widget.attachmentBorderSide ??
|
side: widget.attachmentBorderSide ??
|
||||||
@@ -581,7 +606,7 @@ class _MessageWidgetState extends State<MessageWidget> {
|
|||||||
if (widget.onMessageActions != null) {
|
if (widget.onMessageActions != null) {
|
||||||
widget.onMessageActions(context, widget.message);
|
widget.onMessageActions(context, widget.message);
|
||||||
} else {
|
} else {
|
||||||
_showMessageModalBottomSheet(context);
|
_showMessageActionModalBottomSheet(context);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user