@@ -14,6 +14,8 @@ class ChannelBottomSheet extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
|
class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
|
||||||
|
bool _showActions = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var channel = StreamChannel.of(context).channel;
|
var channel = StreamChannel.of(context).channel;
|
||||||
@@ -33,157 +35,177 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
|
|||||||
topRight: Radius.circular(16.0),
|
topRight: Radius.circular(16.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: ListView(
|
child: !_showActions
|
||||||
shrinkWrap: true,
|
? SizedBox()
|
||||||
children: [
|
: ListView(
|
||||||
SizedBox(
|
shrinkWrap: true,
|
||||||
height: 24.0,
|
|
||||||
),
|
|
||||||
Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: ChannelName(
|
|
||||||
textStyle: StreamChatTheme.of(context).textTheme.headlineBold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 5.0,
|
|
||||||
),
|
|
||||||
Center(
|
|
||||||
child: ChannelInfo(
|
|
||||||
showTypingIndicator: false,
|
|
||||||
channel: StreamChannel.of(context).channel,
|
|
||||||
textStyle:
|
|
||||||
StreamChatTheme.of(context).channelPreviewTheme.subtitle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 17.0,
|
|
||||||
),
|
|
||||||
if (channel.isDistinct && channel.memberCount == 2)
|
|
||||||
Column(
|
|
||||||
children: [
|
children: [
|
||||||
UserAvatar(
|
SizedBox(
|
||||||
user: members
|
height: 24.0,
|
||||||
.firstWhere((e) => e.user.id != userAsMember.user.id)
|
),
|
||||||
.user,
|
Center(
|
||||||
constraints: BoxConstraints(
|
child: Padding(
|
||||||
maxHeight: 64.0,
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
maxWidth: 64.0,
|
child: ChannelName(
|
||||||
|
textStyle:
|
||||||
|
StreamChatTheme.of(context).textTheme.headlineBold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(32.0),
|
|
||||||
onlineIndicatorConstraints:
|
|
||||||
BoxConstraints.tight(Size(12.0, 12.0)),
|
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 6.0,
|
height: 5.0,
|
||||||
),
|
),
|
||||||
Text(
|
Center(
|
||||||
members
|
child: ChannelInfo(
|
||||||
.firstWhere((e) => e.user.id != userAsMember.user.id)
|
showTypingIndicator: false,
|
||||||
.user
|
channel: StreamChannel.of(context).channel,
|
||||||
.name,
|
textStyle: StreamChatTheme.of(context)
|
||||||
style: StreamChatTheme.of(context).textTheme.footnoteBold,
|
.channelPreviewTheme
|
||||||
maxLines: 1,
|
.subtitle,
|
||||||
overflow: TextOverflow.ellipsis,
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 17.0,
|
||||||
|
),
|
||||||
|
if (channel.isDistinct && channel.memberCount == 2)
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
UserAvatar(
|
||||||
|
user: members
|
||||||
|
.firstWhere(
|
||||||
|
(e) => e.user.id != userAsMember.user.id)
|
||||||
|
.user,
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: 64.0,
|
||||||
|
maxWidth: 64.0,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(32.0),
|
||||||
|
onlineIndicatorConstraints:
|
||||||
|
BoxConstraints.tight(Size(12.0, 12.0)),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 6.0,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
members
|
||||||
|
.firstWhere(
|
||||||
|
(e) => e.user.id != userAsMember.user.id)
|
||||||
|
.user
|
||||||
|
.name,
|
||||||
|
style:
|
||||||
|
StreamChatTheme.of(context).textTheme.footnoteBold,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (!(channel.isDistinct && channel.memberCount == 2))
|
||||||
|
Container(
|
||||||
|
height: 94.0,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: ListView.builder(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
itemCount: members.length,
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
UserAvatar(
|
||||||
|
user: members[index].user,
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: 64.0,
|
||||||
|
maxWidth: 64.0,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(32.0),
|
||||||
|
onlineIndicatorConstraints:
|
||||||
|
BoxConstraints.tight(Size(12.0, 12.0)),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 6.0,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
members[index].user.name,
|
||||||
|
style: StreamChatTheme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.footnoteBold,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 24.0,
|
||||||
|
),
|
||||||
|
OptionListTile(
|
||||||
|
leading: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: StreamSvgIcon.user(
|
||||||
|
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: 'View Info',
|
||||||
|
onTap: widget.onViewInfoTap,
|
||||||
|
),
|
||||||
|
if (!channel.isDistinct)
|
||||||
|
OptionListTile(
|
||||||
|
leading: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: StreamSvgIcon.userRemove(
|
||||||
|
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: 'Leave Group',
|
||||||
|
onTap: () async {
|
||||||
|
setState(() {
|
||||||
|
_showActions = false;
|
||||||
|
});
|
||||||
|
await _showLeaveDialog();
|
||||||
|
setState(() {
|
||||||
|
_showActions = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (isOwner)
|
||||||
|
OptionListTile(
|
||||||
|
leading: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: StreamSvgIcon.delete(
|
||||||
|
color: StreamChatTheme.of(context).colorTheme.accentRed,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: 'Delete Conversation',
|
||||||
|
titleColor:
|
||||||
|
StreamChatTheme.of(context).colorTheme.accentRed,
|
||||||
|
onTap: () async {
|
||||||
|
setState(() {
|
||||||
|
_showActions = false;
|
||||||
|
});
|
||||||
|
await _showDeleteDialog();
|
||||||
|
setState(() {
|
||||||
|
_showActions = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
OptionListTile(
|
||||||
|
leading: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: StreamSvgIcon.close_small(
|
||||||
|
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: 'Cancel',
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (!(channel.isDistinct && channel.memberCount == 2))
|
|
||||||
Container(
|
|
||||||
height: 94.0,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: ListView.builder(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
itemCount: members.length,
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
UserAvatar(
|
|
||||||
user: members[index].user,
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
maxHeight: 64.0,
|
|
||||||
maxWidth: 64.0,
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(32.0),
|
|
||||||
onlineIndicatorConstraints:
|
|
||||||
BoxConstraints.tight(Size(12.0, 12.0)),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 6.0,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
members[index].user.name,
|
|
||||||
style: StreamChatTheme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.footnoteBold,
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 24.0,
|
|
||||||
),
|
|
||||||
OptionListTile(
|
|
||||||
leading: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: StreamSvgIcon.user(
|
|
||||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: 'View Info',
|
|
||||||
onTap: widget.onViewInfoTap,
|
|
||||||
),
|
|
||||||
if (!channel.isDistinct)
|
|
||||||
OptionListTile(
|
|
||||||
leading: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: StreamSvgIcon.userRemove(
|
|
||||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: 'Leave Group',
|
|
||||||
onTap: () async {
|
|
||||||
_showLeaveDialog();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (isOwner)
|
|
||||||
OptionListTile(
|
|
||||||
leading: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: StreamSvgIcon.delete(
|
|
||||||
color: StreamChatTheme.of(context).colorTheme.accentRed,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: 'Delete Conversation',
|
|
||||||
titleColor: StreamChatTheme.of(context).colorTheme.accentRed,
|
|
||||||
onTap: () async {
|
|
||||||
_showDeleteDialog();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
OptionListTile(
|
|
||||||
leading: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: StreamSvgIcon.close_small(
|
|
||||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: 'Cancel',
|
|
||||||
onTap: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ class MessageActionsModal extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MessageActionsModalState extends State<MessageActionsModal> {
|
class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||||
|
bool _showActions = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return _showMessageOptionsModal();
|
return _showMessageOptionsModal();
|
||||||
@@ -87,160 +89,163 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
|||||||
? 1
|
? 1
|
||||||
: (roughSentenceSize == 0 ? 1 : (roughSentenceSize / roughMaxSize));
|
: (roughSentenceSize == 0 ? 1 : (roughSentenceSize / roughMaxSize));
|
||||||
|
|
||||||
return TweenAnimationBuilder<double>(
|
final hasFileAttachment =
|
||||||
tween: Tween(begin: 0.0, end: 1.0),
|
widget.message.attachments?.any((it) => it.type == 'file') == true;
|
||||||
duration: Duration(milliseconds: 300),
|
|
||||||
curve: Curves.easeInOutBack,
|
return GestureDetector(
|
||||||
builder: (context, val, snapshot) {
|
behavior: HitTestBehavior.translucent,
|
||||||
final hasFileAttachment =
|
onTap: () => Navigator.maybePop(context),
|
||||||
widget.message.attachments?.any((it) => it.type == 'file') == true;
|
child: Stack(
|
||||||
return GestureDetector(
|
children: [
|
||||||
behavior: HitTestBehavior.translucent,
|
Positioned.fill(
|
||||||
onTap: () => Navigator.maybePop(context),
|
child: BackdropFilter(
|
||||||
child: Stack(
|
filter: ImageFilter.blur(
|
||||||
children: [
|
sigmaX: 10,
|
||||||
Positioned.fill(
|
sigmaY: 10,
|
||||||
child: BackdropFilter(
|
|
||||||
filter: ImageFilter.blur(
|
|
||||||
sigmaX: 10,
|
|
||||||
sigmaY: 10,
|
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
color: StreamChatTheme.of(context).colorTheme.overlay,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Transform.scale(
|
child: Container(
|
||||||
scale: val,
|
color: StreamChatTheme.of(context).colorTheme.overlay,
|
||||||
child: Center(
|
),
|
||||||
child: SingleChildScrollView(
|
),
|
||||||
child: Padding(
|
),
|
||||||
padding: const EdgeInsets.all(8.0),
|
if (_showActions)
|
||||||
child: Column(
|
TweenAnimationBuilder<double>(
|
||||||
crossAxisAlignment: widget.reverse
|
tween: Tween(begin: 0.0, end: 1.0),
|
||||||
? CrossAxisAlignment.end
|
duration: Duration(milliseconds: 300),
|
||||||
: CrossAxisAlignment.start,
|
curve: Curves.easeInOutBack,
|
||||||
children: <Widget>[
|
builder: (context, val, snapshot) {
|
||||||
if (widget.showReactions &&
|
return Transform.scale(
|
||||||
(widget.message.status ==
|
scale: val,
|
||||||
MessageSendingStatus.SENT ||
|
child: Center(
|
||||||
widget.message.status == null))
|
child: SingleChildScrollView(
|
||||||
Align(
|
child: Padding(
|
||||||
alignment: Alignment(
|
padding: const EdgeInsets.all(8.0),
|
||||||
user.id == widget.message.user.id
|
child: Column(
|
||||||
? (divFactor > 1.0
|
crossAxisAlignment: widget.reverse
|
||||||
? 0.0
|
? CrossAxisAlignment.end
|
||||||
: (1.0 - divFactor))
|
: CrossAxisAlignment.start,
|
||||||
: (divFactor > 1.0
|
children: <Widget>[
|
||||||
? 0.0
|
if (widget.showReactions &&
|
||||||
: -(1.0 - divFactor)),
|
(widget.message.status ==
|
||||||
0.0),
|
MessageSendingStatus.SENT ||
|
||||||
child: ReactionPicker(
|
widget.message.status == null))
|
||||||
message: widget.message,
|
Align(
|
||||||
messageTheme: widget.messageTheme,
|
alignment: Alignment(
|
||||||
),
|
user.id == widget.message.user.id
|
||||||
),
|
? (divFactor > 1.0
|
||||||
SizedBox(height: 8),
|
? 0.0
|
||||||
IgnorePointer(
|
: (1.0 - divFactor))
|
||||||
child: MessageWidget(
|
: (divFactor > 1.0
|
||||||
key: Key('MessageWidget'),
|
? 0.0
|
||||||
reverse: widget.reverse,
|
: -(1.0 - divFactor)),
|
||||||
message: widget.message.copyWith(
|
0.0),
|
||||||
text: widget.message.text.length > 200
|
child: ReactionPicker(
|
||||||
? '${widget.message.text.substring(0, 200)}...'
|
message: widget.message,
|
||||||
: widget.message.text,
|
messageTheme: widget.messageTheme,
|
||||||
),
|
|
||||||
messageTheme: widget.messageTheme,
|
|
||||||
showReactions: false,
|
|
||||||
showUsername: false,
|
|
||||||
showThreadReplyIndicator: false,
|
|
||||||
showReplyMessage: false,
|
|
||||||
showUserAvatar: widget.showUserAvatar,
|
|
||||||
attachmentPadding: EdgeInsets.all(
|
|
||||||
hasFileAttachment ? 4 : 2,
|
|
||||||
),
|
|
||||||
showTimestamp: false,
|
|
||||||
translateUserAvatar: false,
|
|
||||||
padding: const EdgeInsets.all(0),
|
|
||||||
textPadding: EdgeInsets.symmetric(
|
|
||||||
vertical: 8.0,
|
|
||||||
horizontal:
|
|
||||||
widget.message.text.isOnlyEmoji ? 0 : 16.0,
|
|
||||||
),
|
|
||||||
showReactionPickerIndicator:
|
|
||||||
widget.showReactions &&
|
|
||||||
(widget.message.status ==
|
|
||||||
MessageSendingStatus.SENT ||
|
|
||||||
widget.message.status == null),
|
|
||||||
showInChannelIndicator: false,
|
|
||||||
showSendingIndicator: false,
|
|
||||||
shape: widget.messageShape,
|
|
||||||
attachmentShape: widget.attachmentShape,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 8),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
left: widget.reverse ? 0 : 40,
|
|
||||||
),
|
|
||||||
child: SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width * 0.75,
|
|
||||||
child: Material(
|
|
||||||
color: StreamChatTheme.of(context)
|
|
||||||
.colorTheme
|
|
||||||
.whiteSnow,
|
|
||||||
clipBehavior: Clip.hardEdge,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
),
|
),
|
||||||
child: Column(
|
),
|
||||||
crossAxisAlignment:
|
SizedBox(height: 8),
|
||||||
CrossAxisAlignment.stretch,
|
IgnorePointer(
|
||||||
children: [
|
child: MessageWidget(
|
||||||
if (widget.showReplyMessage &&
|
key: Key('MessageWidget'),
|
||||||
|
reverse: widget.reverse,
|
||||||
|
message: widget.message.copyWith(
|
||||||
|
text: widget.message.text.length > 200
|
||||||
|
? '${widget.message.text.substring(0, 200)}...'
|
||||||
|
: widget.message.text,
|
||||||
|
),
|
||||||
|
messageTheme: widget.messageTheme,
|
||||||
|
showReactions: false,
|
||||||
|
showUsername: false,
|
||||||
|
showThreadReplyIndicator: false,
|
||||||
|
showReplyMessage: false,
|
||||||
|
showUserAvatar: widget.showUserAvatar,
|
||||||
|
attachmentPadding: EdgeInsets.all(
|
||||||
|
hasFileAttachment ? 4 : 2,
|
||||||
|
),
|
||||||
|
showTimestamp: false,
|
||||||
|
translateUserAvatar: false,
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
textPadding: EdgeInsets.symmetric(
|
||||||
|
vertical: 8.0,
|
||||||
|
horizontal: widget.message.text.isOnlyEmoji
|
||||||
|
? 0
|
||||||
|
: 16.0,
|
||||||
|
),
|
||||||
|
showReactionPickerIndicator:
|
||||||
|
widget.showReactions &&
|
||||||
(widget.message.status ==
|
(widget.message.status ==
|
||||||
MessageSendingStatus.SENT ||
|
MessageSendingStatus.SENT ||
|
||||||
widget.message.status == null) &&
|
widget.message.status == null),
|
||||||
widget.message.parentId == null)
|
showInChannelIndicator: false,
|
||||||
_buildReplyButton(context),
|
showSendingIndicator: false,
|
||||||
if (widget.showThreadReplyMessage &&
|
shape: widget.messageShape,
|
||||||
(widget.message.status ==
|
attachmentShape: widget.attachmentShape,
|
||||||
MessageSendingStatus.SENT ||
|
),
|
||||||
widget.message.status == null) &&
|
),
|
||||||
widget.message.parentId == null)
|
SizedBox(height: 8),
|
||||||
_buildThreadReplyButton(context),
|
Padding(
|
||||||
if (widget.showResendMessage)
|
padding: EdgeInsets.only(
|
||||||
_buildResendMessage(context),
|
left: widget.reverse ? 0 : 40,
|
||||||
if (widget.showEditMessage)
|
),
|
||||||
_buildEditMessage(context),
|
child: SizedBox(
|
||||||
if (widget.showCopyMessage)
|
width: MediaQuery.of(context).size.width * 0.75,
|
||||||
_buildCopyButton(context),
|
child: Material(
|
||||||
if (widget.showFlagButton)
|
color: StreamChatTheme.of(context)
|
||||||
_buildFlagButton(context),
|
.colorTheme
|
||||||
if (widget.showDeleteMessage)
|
.whiteSnow,
|
||||||
_buildDeleteButton(context),
|
clipBehavior: Clip.hardEdge,
|
||||||
].insertBetween(
|
shape: RoundedRectangleBorder(
|
||||||
Container(
|
borderRadius: BorderRadius.circular(16),
|
||||||
height: 1,
|
),
|
||||||
color: StreamChatTheme.of(context)
|
child: Column(
|
||||||
.colorTheme
|
crossAxisAlignment:
|
||||||
.greyWhisper,
|
CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
if (widget.showReplyMessage &&
|
||||||
|
(widget.message.status ==
|
||||||
|
MessageSendingStatus.SENT ||
|
||||||
|
widget.message.status == null) &&
|
||||||
|
widget.message.parentId == null)
|
||||||
|
_buildReplyButton(context),
|
||||||
|
if (widget.showThreadReplyMessage &&
|
||||||
|
(widget.message.status ==
|
||||||
|
MessageSendingStatus.SENT ||
|
||||||
|
widget.message.status == null) &&
|
||||||
|
widget.message.parentId == null)
|
||||||
|
_buildThreadReplyButton(context),
|
||||||
|
if (widget.showResendMessage)
|
||||||
|
_buildResendMessage(context),
|
||||||
|
if (widget.showEditMessage)
|
||||||
|
_buildEditMessage(context),
|
||||||
|
if (widget.showCopyMessage)
|
||||||
|
_buildCopyButton(context),
|
||||||
|
if (widget.showFlagButton)
|
||||||
|
_buildFlagButton(context),
|
||||||
|
if (widget.showDeleteMessage)
|
||||||
|
_buildDeleteButton(context),
|
||||||
|
].insertBetween(
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
color: StreamChatTheme.of(context)
|
||||||
|
.colorTheme
|
||||||
|
.greyWhisper,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
);
|
),
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,6 +278,9 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _showDeleteDialog() async {
|
void _showDeleteDialog() async {
|
||||||
|
setState(() {
|
||||||
|
_showActions = false;
|
||||||
|
});
|
||||||
var answer = await showConfirmationDialog(context,
|
var answer = await showConfirmationDialog(context,
|
||||||
title: 'Delete message',
|
title: 'Delete message',
|
||||||
icon: StreamSvgIcon.flag(
|
icon: StreamSvgIcon.flag(
|
||||||
@@ -293,6 +301,10 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
_showErrorAlert();
|
_showErrorAlert();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_showActions = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1026,7 +1026,11 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_attachments.add(attachment);
|
_attachments.add(attachment);
|
||||||
});
|
});
|
||||||
final mediaFile = await medium.originFile;
|
|
||||||
|
final mediaFile = await medium.originFile.timeout(
|
||||||
|
Duration(seconds: 5),
|
||||||
|
onTimeout: () => medium.originFile,
|
||||||
|
);
|
||||||
|
|
||||||
var file = PlatformFile(
|
var file = PlatformFile(
|
||||||
path: mediaFile.path,
|
path: mediaFile.path,
|
||||||
|
|||||||
@@ -813,9 +813,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
final readList = channel.state?.read?.where((read) {
|
final readList = channel.state?.read?.where((read) {
|
||||||
if (read.user.id == userId) return false;
|
if (read.user.id == userId) return false;
|
||||||
return (read.lastRead.isAfter(message.createdAt) ||
|
return (read.lastRead.isAfter(message.createdAt) ||
|
||||||
read.lastRead.isAtSameMomentAs(message.createdAt)) &&
|
read.lastRead.isAtSameMomentAs(message.createdAt));
|
||||||
(index == 0 ||
|
|
||||||
read.lastRead.isBefore(messages[index - 1].createdAt));
|
|
||||||
})?.toList() ??
|
})?.toList() ??
|
||||||
[];
|
[];
|
||||||
|
|
||||||
|
|||||||
@@ -381,12 +381,14 @@ class _MessageWidgetState extends State<MessageWidget> {
|
|||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
elevation: 0.0,
|
elevation: 0.0,
|
||||||
margin: EdgeInsets.symmetric(
|
margin: EdgeInsets.symmetric(
|
||||||
horizontal:
|
horizontal: (isFailedState
|
||||||
widget.showUserAvatar ==
|
? 15.0
|
||||||
|
: 0.0) +
|
||||||
|
(widget.showUserAvatar ==
|
||||||
DisplayWidget
|
DisplayWidget
|
||||||
.gone
|
.gone
|
||||||
? 0
|
? 0
|
||||||
: 4.0,
|
: 4.0),
|
||||||
),
|
),
|
||||||
shape: widget.shape ??
|
shape: widget.shape ??
|
||||||
RoundedRectangleBorder(
|
RoundedRectangleBorder(
|
||||||
@@ -453,16 +455,10 @@ class _MessageWidgetState extends State<MessageWidget> {
|
|||||||
),
|
),
|
||||||
if (isFailedState)
|
if (isFailedState)
|
||||||
Positioned(
|
Positioned(
|
||||||
left: widget.reverse ? -3 : null,
|
left: widget.reverse ? 0 : null,
|
||||||
right: widget.reverse ? null : -9,
|
right: widget.reverse ? null : 0,
|
||||||
bottom: showBottomRow ? 20 : 0,
|
bottom: showBottomRow ? 18 : -2,
|
||||||
child: Container(
|
child: StreamSvgIcon.error(size: 20),
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: StreamSvgIcon.error(size: 20),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ class StreamChatState extends State<StreamChat> with WidgetsBindingObserver {
|
|||||||
primaryIconTheme: streamTheme.primaryIconTheme,
|
primaryIconTheme: streamTheme.primaryIconTheme,
|
||||||
accentColor: streamTheme.colorTheme.accentBlue,
|
accentColor: streamTheme.colorTheme.accentBlue,
|
||||||
scaffoldBackgroundColor: streamTheme.colorTheme.white,
|
scaffoldBackgroundColor: streamTheme.colorTheme.white,
|
||||||
buttonTheme: streamTheme.buttonTheme,
|
|
||||||
),
|
),
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user