feat: Added pin message functionality
This commit is contained in:
@@ -27,6 +27,8 @@ class MessageActionsModal extends StatefulWidget {
|
||||
this.showResendMessage = true,
|
||||
this.showThreadReplyMessage = true,
|
||||
this.showFlagButton = true,
|
||||
this.showPinButton = true,
|
||||
this.showPinHighlight = false,
|
||||
this.showUserAvatar = DisplayWidget.show,
|
||||
this.editMessageInputBuilder,
|
||||
this.messageShape,
|
||||
@@ -79,6 +81,12 @@ class MessageActionsModal extends StatefulWidget {
|
||||
/// Flag for showing flag action
|
||||
final bool showFlagButton;
|
||||
|
||||
/// Flag for showing pin action
|
||||
final bool showPinButton;
|
||||
|
||||
/// Display Pin Highlight
|
||||
final bool showPinHighlight;
|
||||
|
||||
/// Flag for reversing message
|
||||
final bool reverse;
|
||||
|
||||
@@ -222,6 +230,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
showSendingIndicator: false,
|
||||
shape: widget.messageShape,
|
||||
attachmentShape: widget.attachmentShape,
|
||||
showPinHighlight: false,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
@@ -258,6 +267,8 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
_buildCopyButton(context),
|
||||
if (widget.showFlagButton)
|
||||
_buildFlagButton(context),
|
||||
if (widget.showPinButton)
|
||||
_buildPinButton(context),
|
||||
if (widget.showDeleteMessage)
|
||||
_buildDeleteButton(context),
|
||||
...widget.customActions
|
||||
@@ -359,6 +370,21 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
}
|
||||
}
|
||||
|
||||
void _togglePin() async {
|
||||
final channel = StreamChannel.of(context).channel;
|
||||
|
||||
try {
|
||||
if (!widget.message.pinned) {
|
||||
await channel.pinMessage(widget.message);
|
||||
} else {
|
||||
await channel.unpinMessage(widget.message);
|
||||
}
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
_showErrorAlert();
|
||||
}
|
||||
}
|
||||
|
||||
void _showDeleteDialog() async {
|
||||
setState(() {
|
||||
_showActions = false;
|
||||
@@ -451,6 +477,29 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPinButton(BuildContext context) {
|
||||
final streamChatThemeData = StreamChatTheme.of(context);
|
||||
return InkWell(
|
||||
onTap: _togglePin,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
StreamSvgIcon.pin(
|
||||
color: streamChatThemeData.primaryIconTheme.color,
|
||||
size: 24,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
'${widget.message.pinned ? 'Unpin from' : 'Pin to'} Conversation',
|
||||
style: streamChatThemeData.textTheme.body,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDeleteButton(BuildContext context) {
|
||||
final isDeleteFailed =
|
||||
widget.message.status == MessageSendingStatus.failed_delete;
|
||||
|
||||
@@ -157,6 +157,7 @@ class MessageReactionsModal extends StatelessWidget {
|
||||
),
|
||||
showReactionPickerIndicator: showReactions &&
|
||||
(message.status == MessageSendingStatus.sent),
|
||||
showPinHighlight: false,
|
||||
),
|
||||
),
|
||||
if (message.latestReactions?.isNotEmpty == true) ...[
|
||||
|
||||
@@ -83,6 +83,8 @@ class MessageWidget extends StatefulWidget {
|
||||
this.showResendMessage = true,
|
||||
this.showCopyMessage = true,
|
||||
this.showFlagButton = true,
|
||||
this.showPinButton = true,
|
||||
this.showPinHighlight = true,
|
||||
this.onUserAvatarTap,
|
||||
this.onLinkTap,
|
||||
this.onMessageActions,
|
||||
@@ -367,6 +369,12 @@ class MessageWidget extends StatefulWidget {
|
||||
/// Show flag action
|
||||
final bool showFlagButton;
|
||||
|
||||
/// Show flag action
|
||||
final bool showPinButton;
|
||||
|
||||
/// Display Pin Highlight
|
||||
final bool showPinHighlight;
|
||||
|
||||
/// Builder for respective attachment types
|
||||
final Map<String, AttachmentBuilder> attachmentBuilders;
|
||||
|
||||
@@ -450,7 +458,12 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
widget.showUserAvatar != DisplayWidget.gone ? avatarWidth + 8.5 : 0.5;
|
||||
|
||||
return Material(
|
||||
type: MaterialType.transparency,
|
||||
type: widget.message.pinned && widget.showPinHighlight
|
||||
? MaterialType.card
|
||||
: MaterialType.transparency,
|
||||
color: widget.message.pinned && widget.showPinHighlight
|
||||
? StreamChatTheme.of(context).colorTheme.highlight
|
||||
: null,
|
||||
child: Portal(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
@@ -483,6 +496,10 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (widget.message.pinned &&
|
||||
widget.message.pinnedBy != null &&
|
||||
widget.showPinHighlight)
|
||||
_buildPinnedMessage(widget.message),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -918,6 +935,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
!isFailedState &&
|
||||
widget.onThreadTap != null,
|
||||
showFlagButton: widget.showFlagButton,
|
||||
showPinButton: widget.showPinButton,
|
||||
customActions: widget.customActions,
|
||||
),
|
||||
));
|
||||
@@ -1113,8 +1131,38 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPinnedMessage(Message message) {
|
||||
final pinnedBy = message.pinnedBy;
|
||||
final pinnedByMe = StreamChat.of(context).user!.id == pinnedBy!.id;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
StreamSvgIcon.pin(
|
||||
size: 16,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
Text(
|
||||
'Pinned by ${pinnedByMe ? 'You' : pinnedBy.name}',
|
||||
style: TextStyle(
|
||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool get isOnlyEmoji => widget.message.text!.isOnlyEmoji;
|
||||
|
||||
bool get isPinned => widget.message.pinned;
|
||||
|
||||
Color? _getBackgroundColor() {
|
||||
if (hasQuotedMessage) {
|
||||
return widget.messageTheme.messageBackgroundColor;
|
||||
|
||||
@@ -889,6 +889,18 @@ class StreamSvgIcon extends StatelessWidget {
|
||||
height: size,
|
||||
);
|
||||
|
||||
/// [StreamSvgIcon] type
|
||||
factory StreamSvgIcon.pin({
|
||||
double? size,
|
||||
Color? color,
|
||||
}) =>
|
||||
StreamSvgIcon(
|
||||
assetName: 'icon_pin.svg',
|
||||
color: color,
|
||||
width: size,
|
||||
height: size,
|
||||
);
|
||||
|
||||
/// Name of icon asset
|
||||
final String? assetName;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user