diff --git a/lib/models/irc.dart b/lib/models/irc.dart index d73b62ff..3457bd28 100644 --- a/lib/models/irc.dart +++ b/lib/models/irc.dart @@ -300,14 +300,17 @@ class IRCMessage { // Add the colon separator between the username and their message to the span. if (action == false) span.add(const TextSpan(text: ':')); - // Italicize the text it was called with an IRC Action i.e., "/me". + // Italicize the text if it was called with an IRC Action (e.g., "/me"). final textStyle = action == true ? const TextStyle(fontStyle: FontStyle.italic) : style; if (!showMessage) { span.add(const TextSpan(text: ' ')); } else { + // Check if the message is a reply. If it is, remove the reply username from the message. + final replyUser = tags['reply-parent-display-name']; + final words = replyUser == null ? split : split?.sublist(1); + // Add the message and any emotes to the span. - final words = split; if (words != null) { if (useZeroWidth) { // Keep a local span which will be reversed and added to the final span. diff --git a/lib/screens/channel/chat/widgets/chat_message.dart b/lib/screens/channel/chat/widgets/chat_message.dart index 5ea42929..e8de5c6b 100644 --- a/lib/screens/channel/chat/widgets/chat_message.dart +++ b/lib/screens/channel/chat/widgets/chat_message.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:frosty/constants.dart'; import 'package:frosty/models/irc.dart'; import 'package:frosty/screens/channel/chat/stores/chat_store.dart'; import 'package:frosty/screens/channel/chat/widgets/chat_user_modal.dart'; @@ -53,13 +54,14 @@ class ChatMessage extends StatelessWidget { builder: (context) { Color? color; final Widget renderMessage; + switch (ircMessage.command) { case Command.privateMessage: case Command.userState: // If user is being mentioned in the message, highlight it red. if (ircMessage.mention == true) color = Colors.red.withOpacity(0.3); - renderMessage = Text.rich( + final messageSpan = Text.rich( TextSpan( children: ircMessage.generateSpan( onLongPressName: onLongPressName, @@ -75,11 +77,52 @@ class ChatMessage extends StatelessWidget { ), ), ); + + // Check if the message is replying to another message. + final replyUser = ircMessage.tags['reply-parent-display-name']; + final replyBody = ircMessage.tags['reply-parent-msg-body']; + + if (replyUser != null && replyBody != null) { + renderMessage = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Opacity( + opacity: 0.5, + child: Row( + children: [ + Icon( + Icons.reply, + size: defaultBadgeSize * chatStore.settings.badgeScale, + ), + const SizedBox(width: 5.0), + Flexible( + child: Tooltip( + message: 'Replying to @$replyUser: $replyBody', + preferBelow: false, + child: Text( + 'Replying to @$replyUser: $replyBody', + maxLines: 1, + style: const TextStyle(overflow: TextOverflow.ellipsis), + ), + ), + ), + ], + ), + ), + const SizedBox(height: 5.0), + messageSpan, + ], + ); + } else { + renderMessage = messageSpan; + } + break; case Command.clearChat: case Command.clearMessage: // Render timeouts and bans final banDuration = ircMessage.tags['ban-duration']; + renderMessage = Opacity( opacity: 0.5, child: Column(