diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index 3866d85b8..59334123d 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -3652,10 +3652,22 @@ void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) {
 		auto &d = update.c_updateNewMessage();
 		auto needToAdd = true;
 		if (d.vmessage().type() == mtpc_message) { // index forwarded messages to links _overview
-			if (_session->data().checkEntitiesAndViewsUpdate(d.vmessage().c_message())) { // already in blocks
+			const auto &data = d.vmessage().c_message();
+			if (_session->data().checkEntitiesAndViewsUpdate(data)) { // already in blocks
 				LOG(("Skipping message, because it is already in blocks!"));
 				needToAdd = false;
 			}
+			if (needToAdd && !data.is_from_scheduled()) {
+				// If we still need to add a new message,
+				// we should first check if this message is in
+				// the list of scheduled messages.
+				// This is necessary to correctly update the file reference.
+				// Note that when a message is scheduled until online
+				// while the recipient is already online, the server sends
+				// an ordinary new message with skipped "from_scheduled" flag.
+				_session->data().scheduledMessages().checkEntitiesAndUpdate(
+					data);
+			}
 		}
 		if (needToAdd) {
 			_session->data().addNewMessage(
diff --git a/Telegram/SourceFiles/data/data_scheduled_messages.cpp b/Telegram/SourceFiles/data/data_scheduled_messages.cpp
index 288359fee..042bbcb44 100644
--- a/Telegram/SourceFiles/data/data_scheduled_messages.cpp
+++ b/Telegram/SourceFiles/data/data_scheduled_messages.cpp
@@ -132,6 +132,45 @@ void ScheduledMessages::apply(const MTPDupdateNewScheduledMessage &update) {
 	_updates.fire_copy(history);
 }
 
+void ScheduledMessages::checkEntitiesAndUpdate(const MTPDmessage &data) {
+	// When the user sends a message with a media scheduled until online
+	// while the recipient is already online, the server sends
+	// updateNewMessage to the client and the client calls this method.
+
+	const auto peer = peerFromMTP(data.vto_id());
+	if (!peerIsUser(peer)) {
+		return;
+	}
+
+	const auto history = _session->data().historyLoaded(peer);
+	if (!history) {
+		return;
+	}
+
+	const auto i = _data.find(history);
+	if (i == end(_data)) {
+		return;
+	}
+
+	const auto &itemMap = i->second.itemById;
+	const auto j = itemMap.find(data.vid().v);
+	if (j == end(itemMap)) {
+		return;
+	}
+
+	const auto existing = j->second;
+	Assert(existing->date() == kScheduledUntilOnlineTimestamp);
+	existing->updateSentContent({
+		qs(data.vmessage()),
+		Api::EntitiesFromMTP(data.ventities().value_or_empty())
+	}, data.vmedia());
+	existing->updateReplyMarkup(data.vreply_markup());
+	existing->updateForwardedInfo(data.vfwd_from());
+	_session->data().requestItemTextRefresh(existing);
+
+	existing->destroy();
+}
+
 void ScheduledMessages::apply(
 		const MTPDupdateDeleteScheduledMessages &update) {
 	const auto peer = peerFromMTP(update.vpeer());
diff --git a/Telegram/SourceFiles/data/data_scheduled_messages.h b/Telegram/SourceFiles/data/data_scheduled_messages.h
index 68c586f42..09a2c3eb4 100644
--- a/Telegram/SourceFiles/data/data_scheduled_messages.h
+++ b/Telegram/SourceFiles/data/data_scheduled_messages.h
@@ -31,6 +31,7 @@ public:
 	[[nodiscard]] MsgId lookupId(not_null<HistoryItem*> item) const;
 	[[nodiscard]] int count(not_null<History*> history) const;
 
+	void checkEntitiesAndUpdate(const MTPDmessage &data);
 	void apply(const MTPDupdateNewScheduledMessage &update);
 	void apply(const MTPDupdateDeleteScheduledMessages &update);
 	void apply(