[MessageActionsModal] Fix various alignment, size and color issues

Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
Sahil Kumar
2021-01-08 14:19:24 +05:30
parent b9ae0eeab1
commit 91feed9bac
4 changed files with 199 additions and 169 deletions
+128 -79
View File
@@ -1,3 +1,4 @@
import 'dart:math';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@@ -92,8 +93,9 @@ class MessageActionsModal extends StatelessWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: reverse
crossAxisAlignment: CrossAxisAlignment.stretch, ? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
if (showReactions && if (showReactions &&
(message.status == MessageSendingStatus.SENT || (message.status == MessageSendingStatus.SENT ||
@@ -143,7 +145,6 @@ class MessageActionsModal extends StatelessWidget {
), ),
); );
}), }),
SizedBox(height: 8),
TweenAnimationBuilder<double>( TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0), tween: Tween(begin: 0.0, end: 1.0),
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
@@ -153,47 +154,56 @@ class MessageActionsModal extends StatelessWidget {
transform: Matrix4.identity() transform: Matrix4.identity()
..scale(val) ..scale(val)
..rotateZ(-1.0 + val), ..rotateZ(-1.0 + val),
alignment: Alignment.topRight, alignment: reverse
? Alignment.topRight
: Alignment.topLeft,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: EdgeInsets.only(
horizontal: 48.0, right: reverse ? 16 : 0,
left: reverse ? 0 : 48,
), ),
child: Material( child: SizedBox(
color: StreamChatTheme.of(context) width: MediaQuery.of(context).size.width * 0.75,
.colorTheme child: Material(
.whiteSnow, color: StreamChatTheme.of(context)
clipBehavior: Clip.hardEdge, .colorTheme
shape: RoundedRectangleBorder( .whiteSnow,
borderRadius: BorderRadius.circular(16), clipBehavior: Clip.hardEdge,
), shape: RoundedRectangleBorder(
child: Column( borderRadius: BorderRadius.circular(16),
crossAxisAlignment: ),
CrossAxisAlignment.stretch, child: Column(
children: ListTile.divideTiles( crossAxisAlignment:
context: context, CrossAxisAlignment.stretch,
tiles: [ children: ListTile.divideTiles(
if (showReply && color: StreamChatTheme.of(context)
(message.status == .colorTheme
MessageSendingStatus.SENT || .greyWhisper,
message.status == null) && context: context,
message.parentId == null) tiles: [
_buildReplyButton(context), if (showReply &&
if (showThreadReply && (message.status ==
(message.status == MessageSendingStatus.SENT ||
MessageSendingStatus.SENT || message.status == null) &&
message.status == null) && message.parentId == null)
message.parentId == null) _buildReplyButton(context),
_buildThreadReplyButton(context), if (showThreadReply &&
if (showResendMessage) (message.status ==
_buildResendMessage(context), MessageSendingStatus.SENT ||
if (showEditMessage) message.status == null) &&
_buildEditMessage(context), message.parentId == null)
if (showDeleteMessage) _buildThreadReplyButton(context),
_buildDeleteButton(context), if (showResendMessage)
if (showCopyMessage) _buildResendMessage(context),
_buildCopyButton(context), if (showEditMessage)
], _buildEditMessage(context),
).toList(), if (showCopyMessage)
_buildCopyButton(context),
if (showDeleteMessage)
_buildDeleteButton(context),
],
).toList(),
),
), ),
), ),
), ),
@@ -211,12 +221,18 @@ class MessageActionsModal extends StatelessWidget {
Widget _buildReplyButton(BuildContext context) { Widget _buildReplyButton(BuildContext context) {
return ListTile( return ListTile(
title: Text( dense: true,
'Reply', title: Row(
style: Theme.of(context).textTheme.headline6, children: [
), StreamSvgIcon.reply(
leading: StreamSvgIcon.reply( color: StreamChatTheme.of(context).primaryIconTheme.color,
color: StreamChatTheme.of(context).primaryIconTheme.color, ),
const SizedBox(width: 16),
Text(
'Reply',
style: StreamChatTheme.of(context).textTheme.headline,
),
],
), ),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@@ -230,13 +246,21 @@ class MessageActionsModal extends StatelessWidget {
Widget _buildDeleteButton(BuildContext context) { Widget _buildDeleteButton(BuildContext context) {
final isDeleteFailed = message.status == MessageSendingStatus.FAILED_DELETE; final isDeleteFailed = message.status == MessageSendingStatus.FAILED_DELETE;
return ListTile( return ListTile(
title: Text( dense: true,
isDeleteFailed ? 'Retry deleting message' : 'Delete message', title: Row(
style: children: [
Theme.of(context).textTheme.headline6.copyWith(color: Colors.red), StreamSvgIcon.delete(
), color: Colors.red,
leading: StreamSvgIcon.delete( ),
color: Colors.red, const SizedBox(width: 16),
Text(
isDeleteFailed ? 'Retry Deleting Message' : 'Delete Message',
style: StreamChatTheme.of(context)
.textTheme
.headline
.copyWith(color: Colors.red),
),
],
), ),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@@ -250,12 +274,19 @@ class MessageActionsModal extends StatelessWidget {
Widget _buildCopyButton(BuildContext context) { Widget _buildCopyButton(BuildContext context) {
return ListTile( return ListTile(
title: Text( dense: true,
'Copy message', title: Row(
style: Theme.of(context).textTheme.headline6, children: [
), StreamSvgIcon.copy(
leading: StreamSvgIcon.copy( size: 24,
color: StreamChatTheme.of(context).primaryIconTheme.color, color: StreamChatTheme.of(context).primaryIconTheme.color,
),
const SizedBox(width: 16),
Text(
'Copy Message',
style: StreamChatTheme.of(context).textTheme.headline,
),
],
), ),
onTap: () async { onTap: () async {
await Clipboard.setData(ClipboardData(text: message.text)); await Clipboard.setData(ClipboardData(text: message.text));
@@ -266,12 +297,18 @@ class MessageActionsModal extends StatelessWidget {
Widget _buildEditMessage(BuildContext context) { Widget _buildEditMessage(BuildContext context) {
return ListTile( return ListTile(
title: Text( dense: true,
'Edit message', title: Row(
style: Theme.of(context).textTheme.headline6, children: [
), StreamSvgIcon.edit(
leading: StreamSvgIcon.edit( color: StreamChatTheme.of(context).primaryIconTheme.color,
color: StreamChatTheme.of(context).primaryIconTheme.color, ),
const SizedBox(width: 16),
Text(
'Edit Message',
style: StreamChatTheme.of(context).textTheme.headline,
),
],
), ),
onTap: () async { onTap: () async {
Navigator.pop(context); Navigator.pop(context);
@@ -283,12 +320,18 @@ class MessageActionsModal extends StatelessWidget {
Widget _buildResendMessage(BuildContext context) { Widget _buildResendMessage(BuildContext context) {
final isUpdateFailed = message.status == MessageSendingStatus.FAILED_UPDATE; final isUpdateFailed = message.status == MessageSendingStatus.FAILED_UPDATE;
return ListTile( return ListTile(
title: Text( dense: true,
isUpdateFailed ? 'Resend edited message' : 'Resend', title: Row(
style: Theme.of(context).textTheme.headline6, children: [
), StreamSvgIcon.circle_up(
leading: StreamSvgIcon.circle_up( color: StreamChatTheme.of(context).colorTheme.accentBlue,
color: StreamChatTheme.of(context).colorTheme.accentBlue, ),
const SizedBox(width: 16),
Text(
isUpdateFailed ? 'Resend Edited Message' : 'Resend',
style: StreamChatTheme.of(context).textTheme.headline,
),
],
), ),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@@ -374,12 +417,18 @@ class MessageActionsModal extends StatelessWidget {
Widget _buildThreadReplyButton(BuildContext context) { Widget _buildThreadReplyButton(BuildContext context) {
return ListTile( return ListTile(
title: Text( dense: true,
'Thread reply', title: Row(
style: Theme.of(context).textTheme.headline6, children: [
), StreamSvgIcon.thread(
leading: StreamSvgIcon.thread( color: StreamChatTheme.of(context).primaryIconTheme.color,
color: StreamChatTheme.of(context).primaryIconTheme.color, ),
const SizedBox(width: 16),
Text(
'Thread Reply',
style: StreamChatTheme.of(context).textTheme.headline,
),
],
), ),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
+12 -14
View File
@@ -423,10 +423,12 @@ class _MessageWidgetState extends State<MessageWidget> {
widget.reverse ? pi : 0), widget.reverse ? pi : 0),
child: CustomPaint( child: CustomPaint(
painter: ReactionBubblePainter( painter: ReactionBubblePainter(
widget.messageTheme StreamChatTheme.of(context)
.reactionsBackgroundColor, .colorTheme
widget.messageTheme .white,
.reactionsBorderColor, StreamChatTheme.of(context)
.colorTheme
.white,
), ),
), ),
), ),
@@ -492,18 +494,16 @@ class _MessageWidgetState extends State<MessageWidget> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
StreamSvgIcon.eye( StreamSvgIcon.eye(
color: color: StreamChatTheme.of(context).colorTheme.grey,
StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5),
size: 16.0, size: 16.0,
), ),
SizedBox(width: 8.0), SizedBox(width: 8.0),
Text( Text(
'Only visible to you', 'Only visible to you',
style: StreamChatTheme.of(context).textTheme.footnote.copyWith( style: StreamChatTheme.of(context)
color: StreamChatTheme.of(context) .textTheme
.colorTheme .footnote
.black .copyWith(color: StreamChatTheme.of(context).colorTheme.grey),
.withOpacity(0.5)),
), ),
], ],
), ),
@@ -754,9 +754,7 @@ class _MessageWidgetState extends State<MessageWidget> {
side: widget.attachmentBorderSide ?? side: widget.attachmentBorderSide ??
widget.borderSide ?? widget.borderSide ??
BorderSide( BorderSide(
color: Theme.of(context).brightness == Brightness.dark color: StreamChatTheme.of(context).colorTheme.greyGainsboro,
? StreamChatTheme.of(context).colorTheme.white.withAlpha(24)
: StreamChatTheme.of(context).colorTheme.black.withAlpha(24),
), ),
borderRadius: widget.attachmentBorderRadiusGeometry ?? borderRadius: widget.attachmentBorderRadiusGeometry ??
widget.borderRadiusGeometry ?? widget.borderRadiusGeometry ??
+53 -50
View File
@@ -58,62 +58,65 @@ class _ReactionPickerState extends State<ReactionPicker>
return Transform.scale( return Transform.scale(
scale: val, scale: val,
child: Material( child: Material(
color: widget.messageTheme.reactionsBackgroundColor, color: StreamChatTheme.of(context).colorTheme.white,
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24), borderRadius: BorderRadius.circular(24),
), ),
child: Row( child: Padding(
crossAxisAlignment: CrossAxisAlignment.start, padding: const EdgeInsets.symmetric(horizontal: 8.0),
mainAxisAlignment: MainAxisAlignment.end, child: Row(
mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start,
children: reactionIcons.map((reactionIcon) { mainAxisAlignment: MainAxisAlignment.end,
final ownReactionIndex = widget.message.ownReactions mainAxisSize: MainAxisSize.min,
?.indexWhere((reaction) => children: reactionIcons.map((reactionIcon) {
reaction.type == reactionIcon.type) ?? final ownReactionIndex = widget.message.ownReactions
-1; ?.indexWhere((reaction) =>
var index = reactionIcons.indexOf(reactionIcon); reaction.type == reactionIcon.type) ??
-1;
var index = reactionIcons.indexOf(reactionIcon);
return IconButton( return IconButton(
iconSize: 24, iconSize: 24,
icon: AnimatedBuilder( icon: AnimatedBuilder(
animation: animations[index], animation: animations[index],
builder: (context, val) { builder: (context, val) {
return Transform( return Transform(
transform: Matrix4.identity() transform: Matrix4.identity()
..scale(animations[index].value, ..scale(animations[index].value,
animations[index].value) animations[index].value)
..rotateZ(1.0 - animations[index].value), ..rotateZ(1.0 - animations[index].value),
child: StreamSvgIcon( child: StreamSvgIcon(
assetName: reactionIcon.assetName, assetName: reactionIcon.assetName,
height: animations[index].value * 24.0, height: animations[index].value * 24.0,
width: animations[index].value * 24.0, width: animations[index].value * 24.0,
color: ownReactionIndex != -1 color: ownReactionIndex != -1
? StreamChatTheme.of(context) ? StreamChatTheme.of(context)
.colorTheme .colorTheme
.accentBlue .accentBlue
: Theme.of(context) : Theme.of(context)
.iconTheme .iconTheme
.color .color
.withOpacity(.5), .withOpacity(.5),
), ),
);
}),
onPressed: () {
if (ownReactionIndex != -1) {
removeReaction(
context,
widget.message.ownReactions[ownReactionIndex],
); );
}), } else {
onPressed: () { sendReaction(
if (ownReactionIndex != -1) { context,
removeReaction( reactionIcon.type,
context, );
widget.message.ownReactions[ownReactionIndex], }
); },
} else { );
sendReaction( }).toList(),
context, ),
reactionIcon.type,
);
}
},
);
}).toList(),
), ),
), ),
); );
+6 -26
View File
@@ -228,19 +228,9 @@ class StreamChatThemeData {
inputBackground: colorTheme.white.withAlpha(12), inputBackground: colorTheme.white.withAlpha(12),
), ),
ownMessageTheme: MessageTheme( ownMessageTheme: MessageTheme(
messageText: TextStyle( messageText: textTheme.body,
fontSize: 14.5, createdAt: textTheme.footnote.copyWith(color: colorTheme.grey),
color: colorTheme.black, replies: textTheme.footnoteBold.copyWith(color: accentColor),
),
createdAt: TextStyle(
color: colorTheme.black.withOpacity(.5),
fontSize: 12,
),
replies: TextStyle(
color: accentColor,
fontWeight: FontWeight.w600,
fontSize: 12,
),
messageBackgroundColor: colorTheme.greyGainsboro, messageBackgroundColor: colorTheme.greyGainsboro,
reactionsBackgroundColor: colorTheme.white, reactionsBackgroundColor: colorTheme.white,
reactionsBorderColor: colorTheme.greyWhisper, reactionsBorderColor: colorTheme.greyWhisper,
@@ -259,19 +249,9 @@ class StreamChatThemeData {
otherMessageTheme: MessageTheme( otherMessageTheme: MessageTheme(
reactionsBackgroundColor: colorTheme.greyGainsboro, reactionsBackgroundColor: colorTheme.greyGainsboro,
reactionsBorderColor: colorTheme.white, reactionsBorderColor: colorTheme.white,
messageText: TextStyle( messageText: textTheme.body,
fontSize: 14.5, createdAt: textTheme.footnote.copyWith(color: colorTheme.grey),
color: colorTheme.black, replies: textTheme.footnoteBold.copyWith(color: accentColor),
),
createdAt: TextStyle(
color: colorTheme.black.withOpacity(.5),
fontSize: 12,
),
replies: TextStyle(
color: accentColor,
fontWeight: FontWeight.w600,
fontSize: 12,
),
messageLinks: TextStyle( messageLinks: TextStyle(
color: accentColor, color: accentColor,
), ),