diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
index ac149705f..646c780eb 100644
--- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
+++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
@@ -828,6 +828,7 @@ public:
 		const QString &msg,
 		DisplayOptions options);
 	void clearAll();
+	void clearFromItem(not_null<HistoryItem*> item);
 	void clearFromHistory(not_null<History*> history);
 	void clearFromSession(not_null<Main::Session*> session);
 	void clearNotification(NotificationId id);
@@ -943,6 +944,30 @@ void Manager::Private::clearAll() {
 	}
 }
 
+void Manager::Private::clearFromItem(not_null<HistoryItem*> item) {
+	if (!Supported()) {
+		return;
+	}
+	const auto key = FullPeer{
+		.sessionId = item->history()->session().uniqueId(),
+		.peerId = item->history()->peer->id
+	};
+	const auto i = _notifications.find(key);
+	if (i == _notifications.cend()) {
+		return;
+	}
+	const auto j = i->second.find(item->id);
+	if (j == i->second.end()) {
+		return;
+	}
+	const auto taken = base::take(j->second);
+	i->second.erase(j);
+	if (i->second.empty()) {
+		_notifications.erase(i);
+	}
+	taken->close();
+}
+
 void Manager::Private::clearFromHistory(not_null<History*> history) {
 	if (!Supported()) {
 		return;
@@ -952,7 +977,7 @@ void Manager::Private::clearFromHistory(not_null<History*> history) {
 		.sessionId = history->session().uniqueId(),
 		.peerId = history->peer->id
 	};
-	auto i = _notifications.find(key);
+	const auto i = _notifications.find(key);
 	if (i != _notifications.cend()) {
 		const auto temp = base::take(i->second);
 		_notifications.erase(i);
@@ -1033,6 +1058,10 @@ void Manager::doClearAllFast() {
 	_private->clearAll();
 }
 
+void Manager::doClearFromItem(not_null<HistoryItem*> item) {
+	_private->clearFromItem(item);
+}
+
 void Manager::doClearFromHistory(not_null<History*> history) {
 	_private->clearFromHistory(history);
 }
diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h
index 2689e4f82..4dcc870df 100644
--- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h
+++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h
@@ -28,6 +28,7 @@ protected:
 		const QString &msg,
 		DisplayOptions options) override;
 	void doClearAllFast() override;
+	void doClearFromItem(not_null<HistoryItem*> item) override;
 	void doClearFromHistory(not_null<History*> history) override;
 	void doClearFromSession(not_null<Main::Session*> session) override;
 	bool doSkipAudio() const override;
diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h
index a743f1794..50bb84100 100644
--- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h
+++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h
@@ -28,6 +28,7 @@ protected:
 		const QString &msg,
 		DisplayOptions options) override;
 	void doClearAllFast() override;
+	void doClearFromItem(not_null<HistoryItem*> item) override;
 	void doClearFromHistory(not_null<History*> history) override;
 	void doClearFromSession(not_null<Main::Session*> session) override;
 	QString accountNameSeparator() override;
diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm
index 5e1e6fbf0..5b0ad0616 100644
--- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm
+++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm
@@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "base/platform/mac/base_utilities_mac.h"
 #include "base/random.h"
 #include "history/history.h"
+#include "history/history_item.h"
 #include "ui/empty_userpic.h"
 #include "main/main_session.h"
 #include "mainwindow.h"
@@ -107,7 +108,7 @@ using Manager = Platform::Notifications::Manager;
 	}
 
 	NSNumber *msgObject = [notificationUserInfo objectForKey:@"msgid"];
-	const auto notificationMsgId = msgObject ? [msgObject intValue] : 0;
+	const auto notificationMsgId = msgObject ? [msgObject longLongValue] : 0LL;
 
 	const auto my = Window::Notifications::Manager::NotificationId{
 		.full = Manager::FullPeer{
@@ -186,6 +187,7 @@ public:
 		const QString &msg,
 		DisplayOptions options);
 	void clearAll();
+	void clearFromItem(not_null<HistoryItem*> item);
 	void clearFromHistory(not_null<History*> history);
 	void clearFromSession(not_null<Main::Session*> session);
 	void updateDelegate();
@@ -207,6 +209,9 @@ private:
 	std::mutex _clearingMutex;
 	std::condition_variable _clearingCondition;
 
+	struct ClearFromItem {
+		NotificationId id;
+	};
 	struct ClearFromHistory {
 		FullPeer fullPeer;
 	};
@@ -218,6 +223,7 @@ private:
 	struct ClearFinish {
 	};
 	using ClearTask = std::variant<
+		ClearFromItem,
 		ClearFromHistory,
 		ClearFromSession,
 		ClearAll,
@@ -268,7 +274,7 @@ void Manager::Private::showNotification(
 			@"session",
 			[NSNumber numberWithUnsignedLongLong:peer->id.value],
 			@"peer",
-			[NSNumber numberWithInt:msgId.bare],
+			[NSNumber numberWithLongLong:msgId.bare],
 			@"msgid",
 			[NSNumber numberWithUnsignedLongLong:_managerId],
 			@"manager",
@@ -305,6 +311,7 @@ void Manager::Private::clearingThreadLoop() {
 	auto finished = false;
 	while (!finished) {
 		auto clearAll = false;
+		auto clearFromItems = base::flat_set<NotificationId>();
 		auto clearFromPeers = base::flat_set<FullPeer>();
 		auto clearFromSessions = base::flat_set<uint64>();
 		{
@@ -318,6 +325,8 @@ void Manager::Private::clearingThreadLoop() {
 					clearAll = true;
 				}, [&](ClearAll) {
 					clearAll = true;
+				}, [&](const ClearFromItem &value) {
+					clearFromItems.emplace(value.id);
 				}, [&](const ClearFromHistory &value) {
 					clearFromPeers.emplace(value.fullPeer);
 				}, [&](const ClearFromSession &value) {
@@ -335,17 +344,21 @@ void Manager::Private::clearingThreadLoop() {
 			if (!notificationSessionId) {
 				return true;
 			}
-			if (NSNumber *peerObject = [notificationUserInfo objectForKey:@"peer"]) {
-				const auto notificationPeerId = [peerObject unsignedLongLongValue];
-				if (notificationPeerId) {
-					return clearFromSessions.contains(notificationSessionId)
-						|| clearFromPeers.contains(FullPeer{
-							.sessionId = notificationSessionId,
-							.peerId = PeerId(notificationPeerId)
-						});
-				}
+			NSNumber *peerObject = [notificationUserInfo objectForKey:@"peer"];
+			const auto notificationPeerId = peerObject ? [peerObject unsignedLongLongValue] : 0;
+			if (!notificationPeerId) {
+				return true;
 			}
-			return true;
+			NSNumber *msgObject = [notificationUserInfo objectForKey:@"msgid"];
+			const auto msgId = msgObject ? [msgObject longLongValue] : 0LL;
+			const auto full = FullPeer{
+				.sessionId = notificationSessionId,
+				.peerId = PeerId(notificationPeerId)
+			};
+			const auto id = NotificationId{ full, MsgId(msgId) };
+			return clearFromSessions.contains(notificationSessionId)
+				|| clearFromPeers.contains(full)
+				|| (msgId && clearFromItems.contains(id));
 		};
 
 		NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
@@ -380,6 +393,13 @@ void Manager::Private::clearAll() {
 	putClearTask(ClearAll());
 }
 
+void Manager::Private::clearFromItem(not_null<HistoryItem*> item) {
+	putClearTask(ClearFromItem { FullPeer{
+		.sessionId = history->session().uniqueId(),
+		.peerId = history->peer->id
+	}, item->id });
+}
+
 void Manager::Private::clearFromHistory(not_null<History*> history) {
 	putClearTask(ClearFromHistory { FullPeer{
 		.sessionId = history->session().uniqueId(),
@@ -434,6 +454,10 @@ void Manager::doClearAllFast() {
 	_private->clearAll();
 }
 
+void Manager::doClearFromItem(not_null<HistoryItem*> item) {
+	_private->clearFromItem(item);
+}
+
 void Manager::doClearFromHistory(not_null<History*> history) {
 	_private->clearFromHistory(history);
 }
diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp
index a1d79b582..b761b06fa 100644
--- a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp
+++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp
@@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "platform/win/windows_dlls.h"
 #include "platform/win/specific_win.h"
 #include "history/history.h"
+#include "history/history_item.h"
 #include "core/application.h"
 #include "core/core_settings.h"
 #include "main/main_session.h"
@@ -418,6 +419,7 @@ public:
 		const QString &msg,
 		DisplayOptions options);
 	void clearAll();
+	void clearFromItem(not_null<HistoryItem*> item);
 	void clearFromHistory(not_null<History*> history);
 	void clearFromSession(not_null<Main::Session*> session);
 	void beforeNotificationActivated(NotificationId id);
@@ -489,6 +491,30 @@ void Manager::Private::clearAll() {
 	}
 }
 
+void Manager::Private::clearFromItem(not_null<HistoryItem*> item) {
+	if (!_notifier) {
+		return;
+	}
+
+	auto i = _notifications.find(FullPeer{
+		.sessionId = item->history()->session().uniqueId(),
+		.peerId = item->history()->peer->id
+	});
+	if (i == _notifications.cend()) {
+		return;
+	}
+	const auto j = i->second.find(item->id);
+	if (j == end(i->second)) {
+		return;
+	}
+	const auto taken = std::exchange(j->second, nullptr);
+	i->second.erase(j);
+	if (i->second.empty()) {
+		_notifications.erase(i);
+	}
+	_notifier.Hide(taken);
+}
+
 void Manager::Private::clearFromHistory(not_null<History*> history) {
 	if (!_notifier) {
 		return;
@@ -499,7 +525,7 @@ void Manager::Private::clearFromHistory(not_null<History*> history) {
 		.peerId = history->peer->id
 	});
 	if (i != _notifications.cend()) {
-		auto temp = base::take(i->second);
+		const auto temp = base::take(i->second);
 		_notifications.erase(i);
 
 		for (const auto &[msgId, notification] : temp) {
@@ -842,6 +868,10 @@ void Manager::doClearAllFast() {
 	_private->clearAll();
 }
 
+void Manager::doClearFromItem(not_null<HistoryItem*> item) {
+	_private->clearFromItem(item);
+}
+
 void Manager::doClearFromHistory(not_null<History*> history) {
 	_private->clearFromHistory(history);
 }
diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.h b/Telegram/SourceFiles/platform/win/notifications_manager_win.h
index 9833cb8dc..5ae34cc0f 100644
--- a/Telegram/SourceFiles/platform/win/notifications_manager_win.h
+++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.h
@@ -36,6 +36,7 @@ protected:
 		const QString &msg,
 		DisplayOptions options) override;
 	void doClearAllFast() override;
+	void doClearFromItem(not_null<HistoryItem*> item) override;
 	void doClearFromHistory(not_null<History*> history) override;
 	void doClearFromSession(not_null<Main::Session*> session) override;
 	void onBeforeNotificationActivated(NotificationId id) override;
diff --git a/Telegram/SourceFiles/window/notifications_manager.h b/Telegram/SourceFiles/window/notifications_manager.h
index e867aad4c..26afab1be 100644
--- a/Telegram/SourceFiles/window/notifications_manager.h
+++ b/Telegram/SourceFiles/window/notifications_manager.h
@@ -162,6 +162,12 @@ public:
 	struct NotificationId {
 		FullPeer full;
 		MsgId msgId = 0;
+
+		friend inline bool operator<(
+				const NotificationId &a,
+				const NotificationId &b) {
+			return std::tie(a.full, a.msgId) < std::tie(b.full, b.msgId);
+		}
 	};
 
 	explicit Manager(not_null<System*> system) : _system(system) {
@@ -275,8 +281,6 @@ protected:
 	void doClearAll() override {
 		doClearAllFast();
 	}
-	void doClearFromItem(not_null<HistoryItem*> item) override {
-	}
 	void doShowNotification(
 		not_null<HistoryItem*> item,
 		int forwardedCount) override;
@@ -314,6 +318,8 @@ protected:
 	}
 	void doClearAllFast() override {
 	}
+	void doClearFromItem(not_null<HistoryItem*> item) override {
+	}
 	void doClearFromHistory(not_null<History*> history) override {
 	}
 	void doClearFromSession(not_null<Main::Session*> session) override {