Show "View as Messages" preview by Alt+Click.

This commit is contained in:
John Preston 2024-05-31 14:39:35 +04:00
parent ad342a5324
commit 4e8895ddd9
9 changed files with 80 additions and 29 deletions

View file

@ -1495,6 +1495,8 @@ RowDescriptor InnerWidget::computeChatPreviewRow() const {
: 0; : 0;
if (const auto topic = peer->forumTopicFor(topicId)) { if (const auto topic = peer->forumTopicFor(topicId)) {
return { topic, FullMsgId() }; return { topic, FullMsgId() };
} else if (peer->isForum() && !result.key.topic()) {
return {};
} }
} }
return { result.key, result.message.fullId }; return { result.key, result.message.fullId };

View file

@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_list_widget.h" #include "history/view/history_view_list_widget.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/history_item_components.h"
#include "info/profile/info_profile_cover.h" #include "info/profile/info_profile_cover.h"
#include "info/profile/info_profile_values.h" #include "info/profile/info_profile_values.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -369,7 +370,10 @@ void Item::setupMarkRead() {
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
const auto state = _thread->chatListBadgesState(); const auto state = _thread->chatListBadgesState();
const auto unread = (state.unreadCounter || state.unread); const auto unread = (state.unreadCounter || state.unread);
if (_thread->asTopic() && !unread) { const auto hidden = _thread->asTopic()
? (!unread)
: _thread->peer()->isForum();
if (hidden) {
_markRead->hide(); _markRead->hide();
return; return;
} }
@ -595,7 +599,11 @@ void Item::listUpdateDateLink(
} }
bool Item::listElementHideReply(not_null<const Element*> view) { bool Item::listElementHideReply(not_null<const Element*> view) {
return false; if (!view->isTopicRootReply()) {
return false;
}
const auto reply = view->data()->Get<HistoryMessageReply>();
return reply && !reply->fields().manualQuote;
} }
bool Item::listElementShownUnread(not_null<const Element*> view) { bool Item::listElementShownUnread(not_null<const Element*> view) {
@ -769,10 +777,6 @@ ChatPreview MakeChatPreview(
const auto thread = entry->asThread(); const auto thread = entry->asThread();
if (!thread) { if (!thread) {
return {}; return {};
} else if (const auto history = entry->asHistory()) {
if (history->peer->isForum()) {
return {};
}
} }
auto result = ChatPreview{ auto result = ChatPreview{

View file

@ -1042,7 +1042,9 @@ QSize Message::performCountOptimalSize() {
void Message::refreshTopicButton() { void Message::refreshTopicButton() {
const auto item = data(); const auto item = data();
if (isAttachedToPrevious() || context() != Context::History) { if (isAttachedToPrevious()
|| (context() != Context::History
&& context() != Context::ChatPreview)) {
_topicButton = nullptr; _topicButton = nullptr;
} else if (const auto topic = item->topic()) { } else if (const auto topic = item->topic()) {
if (!_topicButton) { if (!_topicButton) {

View file

@ -33,16 +33,21 @@ ChatPreviewManager::ChatPreviewManager(
bool ChatPreviewManager::show( bool ChatPreviewManager::show(
Dialogs::RowDescriptor row, Dialogs::RowDescriptor row,
Fn<void(bool shown)> callback) { Fn<void(bool shown)> callback,
QPointer<QWidget> parentOverride) {
cancelScheduled(); cancelScheduled();
_topicLifetime.destroy(); _topicLifetime.destroy();
if (const auto topic = row.key.topic()) { if (const auto topic = row.key.topic()) {
_topicLifetime = topic->destroyed() | rpl::start_with_next([=] { _topicLifetime = topic->destroyed() | rpl::start_with_next([=] {
_menu = nullptr; _menu = nullptr;
}); });
} else if (!row.key) {
return false;
} }
const auto parent = _controller->content(); const auto parent = parentOverride
? parentOverride
: _controller->content();
auto preview = HistoryView::MakeChatPreview(parent, row.key.entry()); auto preview = HistoryView::MakeChatPreview(parent, row.key.entry());
if (!preview.menu) { if (!preview.menu) {
return false; return false;
@ -81,10 +86,14 @@ bool ChatPreviewManager::show(
}, _menu->lifetime()); }, _menu->lifetime());
QObject::connect(_menu.get(), &QObject::destroyed, [=] { QObject::connect(_menu.get(), &QObject::destroyed, [=] {
_topicLifetime.destroy(); _topicLifetime.destroy();
callback(false); if (callback) {
callback(false);
}
}); });
callback(true); if (callback) {
callback(true);
}
_menu->popup(QCursor::pos()); _menu->popup(QCursor::pos());
return true; return true;
@ -92,7 +101,8 @@ bool ChatPreviewManager::show(
bool ChatPreviewManager::schedule( bool ChatPreviewManager::schedule(
Dialogs::RowDescriptor row, Dialogs::RowDescriptor row,
Fn<void(bool shown)> callback) { Fn<void(bool shown)> callback,
QPointer<QWidget> parentOverride) {
cancelScheduled(); cancelScheduled();
_topicLifetime.destroy(); _topicLifetime.destroy();
if (const auto topic = row.key.topic()) { if (const auto topic = row.key.topic()) {
@ -100,15 +110,12 @@ bool ChatPreviewManager::schedule(
cancelScheduled(); cancelScheduled();
_menu = nullptr; _menu = nullptr;
}); });
} else if (const auto history = row.key.history()) {
if (history->peer->isForum()) {
return false;
}
} else { } else {
return false; return false;
} }
_scheduled = row; _scheduled = std::move(row);
_scheduledCallback = std::move(callback); _scheduledCallback = std::move(callback);
_scheduledParentOverride = std::move(parentOverride);
_timer.callOnce(kChatPreviewDelay); _timer.callOnce(kChatPreviewDelay);
return true; return true;
} }

View file

@ -25,10 +25,12 @@ public:
bool show( bool show(
Dialogs::RowDescriptor row, Dialogs::RowDescriptor row,
Fn<void(bool shown)> callback = nullptr); Fn<void(bool shown)> callback = nullptr,
QPointer<QWidget> parentOverride = nullptr);
bool schedule( bool schedule(
Dialogs::RowDescriptor row, Dialogs::RowDescriptor row,
Fn<void(bool shown)> callback = nullptr); Fn<void(bool shown)> callback = nullptr,
QPointer<QWidget> parentOverride = nullptr);
void cancelScheduled(); void cancelScheduled();
private: private:
@ -37,6 +39,7 @@ private:
const not_null<SessionController*> _controller; const not_null<SessionController*> _controller;
Dialogs::RowDescriptor _scheduled; Dialogs::RowDescriptor _scheduled;
Fn<void(bool)> _scheduledCallback; Fn<void(bool)> _scheduledCallback;
QPointer<QWidget> _scheduledParentOverride;
base::Timer _timer; base::Timer _timer;
rpl::lifetime _topicLifetime; rpl::lifetime _topicLifetime;

View file

@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/random.h" #include "base/random.h"
#include "base/options.h" #include "base/options.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "base/qt/qt_key_modifiers.h"
#include "boxes/delete_messages_box.h" #include "boxes/delete_messages_box.h"
#include "boxes/max_invite_box.h" #include "boxes/max_invite_box.h"
#include "boxes/moderate_messages_box.h" #include "boxes/moderate_messages_box.h"
@ -94,7 +95,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include <QAction> #include <QAction>
#include <QtGui/QGuiApplication> #include <QtWidgets/QApplication>
namespace Window { namespace Window {
namespace { namespace {
@ -1239,12 +1240,36 @@ void Filler::addViewAsMessages() {
} }
const auto peer = _peer; const auto peer = _peer;
const auto controller = _controller; const auto controller = _controller;
_addAction(tr::lng_forum_view_as_messages(tr::now), [=] { const auto parentHideRequests = std::make_shared<rpl::event_stream<>>();
const auto filterOutChatPreview = [=] {
if (base::IsAltPressed()) {
const auto callback = [=](bool shown) {
if (!shown) {
parentHideRequests->fire({});
}
};
controller->showChatPreview({
peer->owner().history(peer),
FullMsgId(),
}, callback, QApplication::activePopupWidget());
return true;
}
return false;
};
const auto open = [=] {
if (const auto forum = peer->forum()) { if (const auto forum = peer->forum()) {
peer->owner().saveViewAsMessages(forum, true); peer->owner().saveViewAsMessages(forum, true);
} }
controller->showPeerHistory(peer->id); controller->showPeerHistory(peer->id);
}, &st::menuIconAsMessages); };
auto to_instant = rpl::map_to(anim::type::instant);
_addAction({
.text = tr::lng_forum_view_as_messages(tr::now),
.handler = open,
.icon = &st::menuIconAsMessages,
.triggerFilter = filterOutChatPreview,
.hideRequests = parentHideRequests->events() | to_instant
});
} }
void Filler::addViewAsTopics() { void Filler::addViewAsTopics() {

View file

@ -2978,16 +2978,22 @@ QString SessionController::premiumRef() const {
bool SessionController::showChatPreview( bool SessionController::showChatPreview(
Dialogs::RowDescriptor row, Dialogs::RowDescriptor row,
Fn<void(bool shown)> callback) { Fn<void(bool shown)> callback,
return _chatPreviewManager->show(std::move(row), std::move(callback)); QPointer<QWidget> parentOverride) {
return _chatPreviewManager->show(
std::move(row),
std::move(callback),
std::move(parentOverride));
} }
bool SessionController::scheduleChatPreview( bool SessionController::scheduleChatPreview(
Dialogs::RowDescriptor row, Dialogs::RowDescriptor row,
Fn<void(bool shown)> callback) { Fn<void(bool shown)> callback,
QPointer<QWidget> parentOverride) {
return _chatPreviewManager->schedule( return _chatPreviewManager->schedule(
std::move(row), std::move(row),
std::move(callback)); std::move(callback),
std::move(parentOverride));
} }
void SessionController::cancelScheduledPreview() { void SessionController::cancelScheduledPreview() {

View file

@ -603,10 +603,12 @@ public:
bool showChatPreview( bool showChatPreview(
Dialogs::RowDescriptor row, Dialogs::RowDescriptor row,
Fn<void(bool shown)> callback = nullptr); Fn<void(bool shown)> callback = nullptr,
QPointer<QWidget> parentOverride = nullptr);
bool scheduleChatPreview( bool scheduleChatPreview(
Dialogs::RowDescriptor row, Dialogs::RowDescriptor row,
Fn<void(bool shown)> callback = nullptr); Fn<void(bool shown)> callback = nullptr,
QPointer<QWidget> parentOverride = nullptr);
void cancelScheduledPreview(); void cancelScheduledPreview();
[[nodiscard]] bool contentOverlapped(QWidget *w, QPaintEvent *e) const; [[nodiscard]] bool contentOverlapped(QWidget *w, QPaintEvent *e) const;

@ -1 +1 @@
Subproject commit 33aac93b160d4cd30119c8859de722e28512902b Subproject commit d0514b2b022043b3777b06d6068232aa4cda7e80