Merge remote-tracking branch 'origin/develop' into feat/localization
# Conflicts: # packages/stream_chat_flutter/example/lib/main.dart # packages/stream_chat_flutter/example/pubspec.yaml # packages/stream_chat_flutter/lib/src/channel_bottom_sheet.dart # packages/stream_chat_flutter/lib/src/channel_list_view.dart # packages/stream_chat_flutter/lib/src/gallery_footer.dart # packages/stream_chat_flutter/lib/src/message_input.dart # packages/stream_chat_flutter/lib/src/message_list_view.dart # packages/stream_chat_flutter/lib/src/user_item.dart
This commit is contained in:
@@ -26,6 +26,18 @@ import 'package:substring_highlight/substring_highlight.dart';
|
||||
import 'package:video_compress/video_compress.dart';
|
||||
import 'package:stream_chat_flutter/src/extension.dart';
|
||||
|
||||
export 'package:video_compress/video_compress.dart' show VideoQuality;
|
||||
|
||||
/// A callback that can be passed to [MessageInput.onError].
|
||||
///
|
||||
/// This callback should not throw.
|
||||
///
|
||||
/// It exists merely for error reporting, and should not be used otherwise.
|
||||
typedef ErrorListener = void Function(
|
||||
Object error,
|
||||
StackTrace? stackTrace,
|
||||
);
|
||||
|
||||
/// Builder for attachment thumbnails
|
||||
typedef AttachmentThumbnailBuilder = Widget Function(
|
||||
BuildContext,
|
||||
@@ -150,11 +162,20 @@ class MessageInput extends StatefulWidget {
|
||||
this.showCommandsButton = true,
|
||||
this.mentionsTileBuilder,
|
||||
this.maxAttachmentSize = _kDefaultMaxAttachmentSize,
|
||||
this.compressedVideoQuality = VideoQuality.DefaultQuality,
|
||||
this.compressedVideoFrameRate = 30,
|
||||
this.onError,
|
||||
}) : super(key: key);
|
||||
|
||||
/// Message to edit
|
||||
final Message? editMessage;
|
||||
|
||||
/// Video quality to use when compressing the videos
|
||||
final VideoQuality compressedVideoQuality;
|
||||
|
||||
/// Frame rate to use when compressing the videos
|
||||
final int compressedVideoFrameRate;
|
||||
|
||||
/// Max attachment size in bytes
|
||||
/// Defaults to 20 MB
|
||||
/// do not set it if you're using our default CDN
|
||||
@@ -224,6 +245,9 @@ class MessageInput extends StatefulWidget {
|
||||
/// Customize the tile for the mentions overlay
|
||||
final MentionTileBuilder? mentionsTileBuilder;
|
||||
|
||||
/// A callback for error reporting
|
||||
final ErrorListener? onError;
|
||||
|
||||
@override
|
||||
MessageInputState createState() => MessageInputState();
|
||||
|
||||
@@ -331,7 +355,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: StreamSvgIcon.reply(
|
||||
color: _streamChatTheme.colorTheme.greyGainsboro,
|
||||
color: _streamChatTheme.colorTheme.disabled,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
@@ -398,7 +422,8 @@ class MessageInputState extends State<MessageInput> {
|
||||
border: _sendAsDm
|
||||
? null
|
||||
: Border.all(
|
||||
color: _streamChatTheme.colorTheme.black.withOpacity(.5),
|
||||
color: _streamChatTheme.colorTheme.textHighEmphasis
|
||||
.withOpacity(.5),
|
||||
width: 2,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
@@ -407,8 +432,8 @@ class MessageInputState extends State<MessageInput> {
|
||||
child: Material(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: _sendAsDm
|
||||
? _streamChatTheme.colorTheme.accentBlue
|
||||
: _streamChatTheme.colorTheme.white,
|
||||
? _streamChatTheme.colorTheme.accentPrimary
|
||||
: _streamChatTheme.colorTheme.barsBg,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
@@ -423,7 +448,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
: CrossFadeState.showSecond,
|
||||
firstChild: StreamSvgIcon.check(
|
||||
size: 16,
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
),
|
||||
secondChild: const SizedBox(
|
||||
height: 16,
|
||||
@@ -439,7 +464,8 @@ class MessageInputState extends State<MessageInput> {
|
||||
child: Text(
|
||||
context.translations.alsoSendAsDirectMessageLabel,
|
||||
style: _streamChatTheme.textTheme.footnote.copyWith(
|
||||
color: _streamChatTheme.colorTheme.black.withOpacity(0.5),
|
||||
color: _streamChatTheme.colorTheme.textHighEmphasis
|
||||
.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -579,7 +605,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
isDense: true,
|
||||
hintText: _getHint(context),
|
||||
hintStyle: _streamChatTheme.messageInputTheme.inputTextStyle!.copyWith(
|
||||
color: _streamChatTheme.colorTheme.grey,
|
||||
color: _streamChatTheme.colorTheme.textLowEmphasis,
|
||||
),
|
||||
border: const OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
@@ -617,7 +643,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
constraints: BoxConstraints.tight(const Size(64, 24)),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: _streamChatTheme.colorTheme.accentBlue,
|
||||
color: _streamChatTheme.colorTheme.accentPrimary,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
@@ -831,12 +857,12 @@ class MessageInputState extends State<MessageInput> {
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Container(
|
||||
constraints: BoxConstraints.loose(const Size.fromHeight(400)),
|
||||
decoration: BoxDecoration(
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
borderRadius: BorderRadius.circular(8)),
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.all(0),
|
||||
@@ -852,14 +878,14 @@ class MessageInputState extends State<MessageInput> {
|
||||
horizontal: 8,
|
||||
),
|
||||
child: StreamSvgIcon.lightning(
|
||||
color: _streamChatTheme.colorTheme.accentBlue,
|
||||
color: _streamChatTheme.colorTheme.accentPrimary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
context.translations.instantCommandsLabel,
|
||||
style: TextStyle(
|
||||
color:
|
||||
_streamChatTheme.colorTheme.black.withOpacity(.5),
|
||||
color: _streamChatTheme.colorTheme.textHighEmphasis
|
||||
.withOpacity(.5),
|
||||
),
|
||||
)
|
||||
],
|
||||
@@ -899,7 +925,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
color: _streamChatTheme
|
||||
// ignore: lines_longer_than_80_chars
|
||||
.colorTheme
|
||||
.grey,
|
||||
.textLowEmphasis,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -943,24 +969,29 @@ class MessageInputState extends State<MessageInput> {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return _attachments.isEmpty
|
||||
? streamChatThemeData.colorTheme.accentBlue
|
||||
? streamChatThemeData.colorTheme.accentPrimary
|
||||
: (!_attachmentContainsFile
|
||||
? streamChatThemeData.colorTheme.accentBlue
|
||||
: streamChatThemeData.colorTheme.black.withOpacity(0.2));
|
||||
? streamChatThemeData.colorTheme.accentPrimary
|
||||
: streamChatThemeData.colorTheme.textHighEmphasis
|
||||
.withOpacity(0.2));
|
||||
case 1:
|
||||
return _attachmentContainsFile
|
||||
? streamChatThemeData.colorTheme.accentBlue
|
||||
? streamChatThemeData.colorTheme.accentPrimary
|
||||
: (_attachments.isEmpty
|
||||
? streamChatThemeData.colorTheme.black.withOpacity(0.5)
|
||||
: streamChatThemeData.colorTheme.black.withOpacity(0.2));
|
||||
? streamChatThemeData.colorTheme.textHighEmphasis
|
||||
.withOpacity(0.5)
|
||||
: streamChatThemeData.colorTheme.textHighEmphasis
|
||||
.withOpacity(0.2));
|
||||
case 2:
|
||||
return _attachmentContainsFile && _attachments.isNotEmpty
|
||||
? streamChatThemeData.colorTheme.black.withOpacity(0.2)
|
||||
: streamChatThemeData.colorTheme.black.withOpacity(0.5);
|
||||
? streamChatThemeData.colorTheme.textHighEmphasis.withOpacity(0.2)
|
||||
: streamChatThemeData.colorTheme.textHighEmphasis
|
||||
.withOpacity(0.5);
|
||||
case 3:
|
||||
return _attachmentContainsFile && _attachments.isNotEmpty
|
||||
? streamChatThemeData.colorTheme.black.withOpacity(0.2)
|
||||
: streamChatThemeData.colorTheme.black.withOpacity(0.5);
|
||||
? streamChatThemeData.colorTheme.textHighEmphasis.withOpacity(0.2)
|
||||
: streamChatThemeData.colorTheme.textHighEmphasis
|
||||
.withOpacity(0.5);
|
||||
default:
|
||||
return Colors.black;
|
||||
}
|
||||
@@ -970,7 +1001,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
duration: const Duration(milliseconds: 300),
|
||||
height: _openFilePickerSection ? _filePickerSize : 0,
|
||||
child: Material(
|
||||
color: _streamChatTheme.colorTheme.whiteSmoke,
|
||||
color: _streamChatTheme.colorTheme.inputBg,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -1033,7 +1064,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
},
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(16),
|
||||
topRight: Radius.circular(16),
|
||||
@@ -1049,7 +1080,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
height: 4,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: _streamChatTheme.colorTheme.whiteSmoke,
|
||||
color: _streamChatTheme.colorTheme.inputBg,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
),
|
||||
@@ -1063,7 +1094,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
Expanded(
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: _PickerWidget(
|
||||
@@ -1106,8 +1137,11 @@ class MessageInputState extends State<MessageInput> {
|
||||
|
||||
if (file.size! > widget.maxAttachmentSize) {
|
||||
if (medium.type == AssetType.video && file.path != null) {
|
||||
final mediaInfo = await (VideoService.compressVideo(file.path!)
|
||||
as FutureOr<MediaInfo>);
|
||||
final mediaInfo = await (VideoService.compressVideo(
|
||||
file.path!,
|
||||
frameRate: widget.compressedVideoFrameRate,
|
||||
quality: widget.compressedVideoQuality,
|
||||
) as FutureOr<MediaInfo>);
|
||||
|
||||
if (mediaInfo.filesize! > widget.maxAttachmentSize) {
|
||||
_showErrorAlert(
|
||||
@@ -1147,7 +1181,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
);
|
||||
case 'ban':
|
||||
return CircleAvatar(
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentBlue,
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentPrimary,
|
||||
radius: 12,
|
||||
child: StreamSvgIcon.iconUserDelete(
|
||||
size: 16,
|
||||
@@ -1156,7 +1190,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
);
|
||||
case 'flag':
|
||||
return CircleAvatar(
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentBlue,
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentPrimary,
|
||||
radius: 12,
|
||||
child: StreamSvgIcon.flag(
|
||||
size: 14,
|
||||
@@ -1165,7 +1199,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
);
|
||||
case 'imgur':
|
||||
return CircleAvatar(
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentBlue,
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentPrimary,
|
||||
radius: 12,
|
||||
child: ClipOval(
|
||||
child: StreamSvgIcon.imgur(
|
||||
@@ -1175,7 +1209,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
);
|
||||
case 'mute':
|
||||
return CircleAvatar(
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentBlue,
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentPrimary,
|
||||
radius: 12,
|
||||
child: StreamSvgIcon.mute(
|
||||
size: 16,
|
||||
@@ -1184,7 +1218,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
);
|
||||
case 'unban':
|
||||
return CircleAvatar(
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentBlue,
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentPrimary,
|
||||
radius: 12,
|
||||
child: StreamSvgIcon.userAdd(
|
||||
size: 16,
|
||||
@@ -1193,7 +1227,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
);
|
||||
case 'unmute':
|
||||
return CircleAvatar(
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentBlue,
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentPrimary,
|
||||
radius: 12,
|
||||
child: StreamSvgIcon.volumeUp(
|
||||
size: 16,
|
||||
@@ -1202,7 +1236,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
);
|
||||
default:
|
||||
return CircleAvatar(
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentBlue,
|
||||
backgroundColor: _streamChatTheme.colorTheme.accentPrimary,
|
||||
radius: 12,
|
||||
child: StreamSvgIcon.lightning(
|
||||
size: 16,
|
||||
@@ -1242,7 +1276,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
final child = Card(
|
||||
margin: const EdgeInsets.all(8),
|
||||
elevation: 2,
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
@@ -1250,7 +1284,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
child: Container(
|
||||
constraints: BoxConstraints.loose(const Size.fromHeight(240)),
|
||||
decoration: BoxDecoration(
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
),
|
||||
child: FutureBuilder<List<Member>>(
|
||||
future: queryMembers ?? Future.value(members),
|
||||
@@ -1266,7 +1300,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
.where((it) => it.user != null)
|
||||
.map(
|
||||
(m) => Material(
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
if (m.user != null) {
|
||||
@@ -1353,7 +1387,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
child: Card(
|
||||
margin: const EdgeInsets.all(8),
|
||||
elevation: 2,
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
@@ -1368,7 +1402,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
offset: Offset(0, -4),
|
||||
),
|
||||
],
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
),
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(0),
|
||||
@@ -1384,8 +1418,8 @@ class MessageInputState extends State<MessageInput> {
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: StreamSvgIcon.smile(
|
||||
color:
|
||||
_streamChatTheme.colorTheme.accentBlue,
|
||||
color: _streamChatTheme
|
||||
.colorTheme.accentPrimary,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
@@ -1394,7 +1428,8 @@ class MessageInputState extends State<MessageInput> {
|
||||
query,
|
||||
),
|
||||
style: TextStyle(
|
||||
color: _streamChatTheme.colorTheme.black
|
||||
color: _streamChatTheme
|
||||
.colorTheme.textHighEmphasis
|
||||
.withOpacity(.5),
|
||||
),
|
||||
),
|
||||
@@ -1566,11 +1601,12 @@ class MessageInputState extends State<MessageInput> {
|
||||
onPressed: () {
|
||||
setState(() => _attachments.remove(attachment.id));
|
||||
},
|
||||
fillColor: _streamChatTheme.colorTheme.black.withOpacity(.5),
|
||||
fillColor:
|
||||
_streamChatTheme.colorTheme.textHighEmphasis.withOpacity(.5),
|
||||
child: Center(
|
||||
child: StreamSvgIcon.close(
|
||||
size: 24,
|
||||
color: _streamChatTheme.colorTheme.white,
|
||||
color: _streamChatTheme.colorTheme.barsBg,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -1605,8 +1641,8 @@ class MessageInputState extends State<MessageInput> {
|
||||
errorWidget: (_, obj, trace) =>
|
||||
getFileTypeImage(attachment.extraData['other'] as String?),
|
||||
placeholder: (context, _) => Shimmer.fromColors(
|
||||
baseColor: _streamChatTheme.colorTheme.greyGainsboro,
|
||||
highlightColor: _streamChatTheme.colorTheme.whiteSmoke,
|
||||
baseColor: _streamChatTheme.colorTheme.disabled,
|
||||
highlightColor: _streamChatTheme.colorTheme.inputBg,
|
||||
child: Image.asset(
|
||||
'images/placeholder.png',
|
||||
fit: BoxFit.cover,
|
||||
@@ -1647,7 +1683,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
return IconButton(
|
||||
icon: StreamSvgIcon.lightning(
|
||||
color: s.isNotEmpty
|
||||
? _streamChatTheme.colorTheme.greyGainsboro
|
||||
? _streamChatTheme.colorTheme.disabled
|
||||
: (_commandsOverlay != null
|
||||
? _streamChatTheme.messageInputTheme.actionButtonColor
|
||||
: _streamChatTheme.messageInputTheme.actionButtonIdleColor),
|
||||
@@ -1823,11 +1859,11 @@ class MessageInputState extends State<MessageInput> {
|
||||
}
|
||||
|
||||
if (camera) {
|
||||
PickedFile? pickedFile;
|
||||
XFile? pickedFile;
|
||||
if (fileType == DefaultAttachmentTypes.image) {
|
||||
pickedFile = await _imagePicker.getImage(source: ImageSource.camera);
|
||||
pickedFile = await _imagePicker.pickImage(source: ImageSource.camera);
|
||||
} else if (fileType == DefaultAttachmentTypes.video) {
|
||||
pickedFile = await _imagePicker.getVideo(source: ImageSource.camera);
|
||||
pickedFile = await _imagePicker.pickVideo(source: ImageSource.camera);
|
||||
}
|
||||
if (pickedFile == null) {
|
||||
return;
|
||||
@@ -1879,8 +1915,11 @@ class MessageInputState extends State<MessageInput> {
|
||||
|
||||
if (file.size! > widget.maxAttachmentSize) {
|
||||
if (attachmentType == 'video' && file.path != null) {
|
||||
final mediaInfo = await (VideoService.compressVideo(file.path!)
|
||||
as FutureOr<MediaInfo>);
|
||||
final mediaInfo = await (VideoService.compressVideo(
|
||||
file.path!,
|
||||
frameRate: widget.compressedVideoFrameRate,
|
||||
quality: widget.compressedVideoQuality,
|
||||
) as FutureOr<MediaInfo>);
|
||||
|
||||
if (mediaInfo.filesize! > widget.maxAttachmentSize) {
|
||||
_showErrorAlert(
|
||||
@@ -1957,7 +1996,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
}
|
||||
|
||||
/// Sends the current message
|
||||
void sendMessage() async {
|
||||
Future<void> sendMessage() async {
|
||||
var text = textEditingController.text.trim();
|
||||
if (text.isEmpty && _attachments.isEmpty) {
|
||||
return;
|
||||
@@ -1973,9 +2012,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
|
||||
textEditingController.clear();
|
||||
_attachments.clear();
|
||||
if (widget.onQuotedMessageCleared != null) {
|
||||
widget.onQuotedMessageCleared!();
|
||||
}
|
||||
widget.onQuotedMessageCleared?.call();
|
||||
|
||||
setState(() {
|
||||
_messageIsPresent = false;
|
||||
@@ -1987,7 +2024,6 @@ class MessageInputState extends State<MessageInput> {
|
||||
_mentionsOverlay?.remove();
|
||||
_mentionsOverlay = null;
|
||||
|
||||
Future sendingFuture;
|
||||
Message message;
|
||||
if (widget.editMessage != null) {
|
||||
message = widget.editMessage!.copyWith(
|
||||
@@ -2025,33 +2061,39 @@ class MessageInputState extends State<MessageInput> {
|
||||
|
||||
_mentionedUsers.clear();
|
||||
|
||||
if (widget.editMessage == null ||
|
||||
widget.editMessage!.status == MessageSendingStatus.failed ||
|
||||
widget.editMessage!.status == MessageSendingStatus.sending) {
|
||||
sendingFuture = channel.sendMessage(message);
|
||||
} else {
|
||||
sendingFuture = channel.updateMessage(message);
|
||||
}
|
||||
try {
|
||||
Future sendingFuture;
|
||||
if (widget.editMessage == null ||
|
||||
widget.editMessage!.status == MessageSendingStatus.failed ||
|
||||
widget.editMessage!.status == MessageSendingStatus.sending) {
|
||||
sendingFuture = channel.sendMessage(message);
|
||||
} else {
|
||||
sendingFuture = channel.updateMessage(message);
|
||||
}
|
||||
|
||||
if (!shouldUnfocus) {
|
||||
FocusScope.of(context).requestFocus(_focusNode);
|
||||
}
|
||||
if (!shouldUnfocus) {
|
||||
FocusScope.of(context).requestFocus(_focusNode);
|
||||
}
|
||||
|
||||
return sendingFuture.then((resp) {
|
||||
final resp = await sendingFuture;
|
||||
if (resp.message?.type == 'error') {
|
||||
_parseExistingMessage(message);
|
||||
}
|
||||
if (widget.onMessageSent != null) {
|
||||
widget.onMessageSent!(resp.message);
|
||||
widget.onMessageSent?.call(resp.message);
|
||||
} catch (e, stk) {
|
||||
if (widget.onError != null) {
|
||||
widget.onError?.call(e, stk);
|
||||
} else {
|
||||
rethrow;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
StreamSubscription? _keyboardListener;
|
||||
|
||||
void _showErrorAlert(String description) {
|
||||
showModalBottomSheet(
|
||||
backgroundColor: _streamChatTheme.colorTheme.white,
|
||||
backgroundColor: _streamChatTheme.colorTheme.barsBg,
|
||||
context: context,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
@@ -2065,7 +2107,7 @@ class MessageInputState extends State<MessageInput> {
|
||||
height: 26,
|
||||
),
|
||||
StreamSvgIcon.error(
|
||||
color: _streamChatTheme.colorTheme.accentRed,
|
||||
color: _streamChatTheme.colorTheme.accentError,
|
||||
size: 24,
|
||||
),
|
||||
const SizedBox(
|
||||
@@ -2089,7 +2131,8 @@ class MessageInputState extends State<MessageInput> {
|
||||
height: 36,
|
||||
),
|
||||
Container(
|
||||
color: _streamChatTheme.colorTheme.black.withOpacity(.08),
|
||||
color:
|
||||
_streamChatTheme.colorTheme.textHighEmphasis.withOpacity(.08),
|
||||
height: 1,
|
||||
),
|
||||
Row(
|
||||
@@ -2101,8 +2144,8 @@ class MessageInputState extends State<MessageInput> {
|
||||
},
|
||||
child: Text(
|
||||
context.translations.okLabel,
|
||||
style: _streamChatTheme.textTheme.bodyBold
|
||||
.copyWith(color: _streamChatTheme.colorTheme.accentBlue),
|
||||
style: _streamChatTheme.textTheme.bodyBold.copyWith(
|
||||
color: _streamChatTheme.colorTheme.accentPrimary),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -2243,12 +2286,12 @@ class __PickerWidgetState extends State<_PickerWidget> {
|
||||
},
|
||||
child: Container(
|
||||
constraints: const BoxConstraints.expand(),
|
||||
color: widget.streamChatTheme.colorTheme.whiteSmoke,
|
||||
color: widget.streamChatTheme.colorTheme.inputBg,
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
context.translations.addMoreFilesLabel,
|
||||
style: TextStyle(
|
||||
color: widget.streamChatTheme.colorTheme.accentBlue,
|
||||
color: widget.streamChatTheme.colorTheme.accentPrimary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -2266,7 +2309,7 @@ class __PickerWidgetState extends State<_PickerWidget> {
|
||||
PhotoManager.openSetting();
|
||||
},
|
||||
child: Container(
|
||||
color: widget.streamChatTheme.colorTheme.whiteSmoke,
|
||||
color: widget.streamChatTheme.colorTheme.inputBg,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
@@ -2275,12 +2318,13 @@ class __PickerWidgetState extends State<_PickerWidget> {
|
||||
'svgs/icon_picture_empty_state.svg',
|
||||
package: 'stream_chat_flutter',
|
||||
height: 140,
|
||||
color: widget.streamChatTheme.colorTheme.greyGainsboro,
|
||||
color: widget.streamChatTheme.colorTheme.disabled,
|
||||
),
|
||||
Text(
|
||||
context.translations.enablePhotoAndVideoAccessMessage,
|
||||
style: widget.streamChatTheme.textTheme.body.copyWith(
|
||||
color: widget.streamChatTheme.colorTheme.grey),
|
||||
color:
|
||||
widget.streamChatTheme.colorTheme.textLowEmphasis),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
@@ -2288,7 +2332,7 @@ class __PickerWidgetState extends State<_PickerWidget> {
|
||||
child: Text(
|
||||
context.translations.allowGalleryAccessMessage,
|
||||
style: widget.streamChatTheme.textTheme.bodyBold.copyWith(
|
||||
color: widget.streamChatTheme.colorTheme.accentBlue,
|
||||
color: widget.streamChatTheme.colorTheme.accentPrimary,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user