sendMessage method

Future<SendMessageResponse> sendMessage(
  1. Message message, {
  2. bool skipPush = false,
  3. bool skipEnrichUrl = false,
})

Send a message to this channel.

If skipPush is true the message will not send a push notification.

Waits for a _messageAttachmentsUploadCompleter to complete before actually sending the message.

Implementation

Future<SendMessageResponse> sendMessage(
  Message message, {
  bool skipPush = false,
  bool skipEnrichUrl = false,
}) async {
  _checkInitialized();
  // Cancelling previous completer in case it's called again in the process
  // Eg. Updating the message while the previous call is in progress.
  _messageAttachmentsUploadCompleter
      .remove(message.id)
      ?.completeError(const StreamChatError('Message cancelled'));

  final quotedMessage = state!.messages.firstWhereOrNull(
    (m) => m.id == message.quotedMessageId,
  );
  // ignore: parameter_assignments
  message = message.copyWith(
    localCreatedAt: DateTime.now(),
    user: _client.state.currentUser,
    quotedMessage: quotedMessage,
    state: MessageState.sending,
    attachments: message.attachments.map(
      (it) {
        if (it.uploadState.isSuccess) return it;
        return it.copyWith(uploadState: const UploadState.preparing());
      },
    ).toList(),
  );

  state!.updateMessage(message);

  try {
    if (message.attachments.any((it) => !it.uploadState.isSuccess)) {
      final attachmentsUploadCompleter = Completer<Message>();
      _messageAttachmentsUploadCompleter[message.id] =
          attachmentsUploadCompleter;

      _uploadAttachments(
        message.id,
        message.attachments.map((it) => it.id),
      );

      // ignore: parameter_assignments
      message = await attachmentsUploadCompleter.future;
    }

    // Wait for the previous sendMessage call to finish. Otherwise, the order
    // of messages will not be maintained.
    final response = await _sendMessageLock.synchronized(
      () => _client.sendMessage(
        message,
        id!,
        type,
        skipPush: skipPush,
        skipEnrichUrl: skipEnrichUrl,
      ),
    );

    final sentMessage = response.message.syncWith(message).copyWith(
          // Update the message state to sent.
          state: MessageState.sent,
        );

    state!.updateMessage(sentMessage);
    if (cooldown > 0) cooldownStartedAt = DateTime.now();
    return response;
  } catch (e) {
    if (e is StreamChatNetworkError && e.isRetriable) {
      state!._retryQueue.add([
        message.copyWith(
          // Update the message state to failed.
          state: MessageState.sendingFailed,
        ),
      ]);
    }

    rethrow;
  }
}