mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-22 09:07:05 +02:00
Update API scheme on layer 148.
Extract message history corner buttons code.
This commit is contained in:
parent
2c0b5b3210
commit
6a7f030ee7
24 changed files with 751 additions and 444 deletions
|
@ -690,6 +690,8 @@ PRIVATE
|
|||
history/view/history_view_contact_status.h
|
||||
history/view/history_view_context_menu.cpp
|
||||
history/view/history_view_context_menu.h
|
||||
history/view/history_view_corner_buttons.cpp
|
||||
history/view/history_view_corner_buttons.h
|
||||
history/view/history_view_cursor_state.cpp
|
||||
history/view/history_view_cursor_state.h
|
||||
history/view/history_view_element.cpp
|
||||
|
|
|
@ -222,6 +222,7 @@ inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer;
|
|||
inputNotifyUsers#193b4417 = InputNotifyPeer;
|
||||
inputNotifyChats#4a95e84e = InputNotifyPeer;
|
||||
inputNotifyBroadcasts#b1db7c7e = InputNotifyPeer;
|
||||
inputNotifyForumTopic#5c467992 peer:InputPeer top_msg_id:int = InputNotifyPeer;
|
||||
|
||||
inputPeerNotifySettings#df1f002b flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?NotificationSound = InputPeerNotifySettings;
|
||||
|
||||
|
@ -1454,7 +1455,7 @@ stickerKeyword#fcfeb29c document_id:long keyword:Vector<string> = StickerKeyword
|
|||
|
||||
username#b4073647 flags:# editable:flags.0?true active:flags.1?true username:string = Username;
|
||||
|
||||
forumTopic#18a9a864 flags:# my:flags.1?true id:int date:int title:string icon_color:int icon_emoji_id:flags.0?long top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int from_id:Peer = ForumTopic;
|
||||
forumTopic#5920d6dc flags:# my:flags.1?true id:int date:int title:string icon_color:int icon_emoji_id:flags.0?long top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int from_id:Peer notify_settings:PeerNotifySettings = ForumTopic;
|
||||
|
||||
messages.forumTopics#367617d3 flags:# order_by_create_date:flags.0?true count:int topics:Vector<ForumTopic> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> pts:int = messages.ForumTopics;
|
||||
|
||||
|
@ -1704,7 +1705,7 @@ messages.getEmojiKeywords#35a0e062 lang_code:string = EmojiKeywordsDifference;
|
|||
messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int = EmojiKeywordsDifference;
|
||||
messages.getEmojiKeywordsLanguages#4e9963b2 lang_codes:Vector<string> = Vector<EmojiLanguage>;
|
||||
messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
|
||||
messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
|
||||
messages.getSearchCounters#ae7cc1 flags:# peer:InputPeer top_msg_id:flags.0?int filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
|
||||
messages.requestUrlAuth#198fb446 flags:# peer:flags.1?InputPeer msg_id:flags.1?int button_id:flags.1?int url:flags.2?string = UrlAuthResult;
|
||||
messages.acceptUrlAuth#b12c7125 flags:# write_allowed:flags.0?true peer:flags.1?InputPeer msg_id:flags.1?int button_id:flags.1?int url:flags.2?string = UrlAuthResult;
|
||||
messages.hidePeerSettingsBar#4facb138 peer:InputPeer = Bool;
|
||||
|
@ -1754,7 +1755,7 @@ messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
|
|||
messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool;
|
||||
messages.translateText#24ce6dee flags:# peer:flags.0?InputPeer msg_id:flags.0?int text:flags.1?string from_lang:flags.2?string to_lang:string = messages.TranslatedText;
|
||||
messages.getUnreadReactions#3223495b flags:# peer:InputPeer top_msg_id:flags.0?int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.readReactions#82e251d7 peer:InputPeer = messages.AffectedHistory;
|
||||
messages.readReactions#54aa7f8e flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
|
||||
messages.searchSentMedia#107e31a0 q:string filter:MessagesFilter limit:int = messages.Messages;
|
||||
messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots;
|
||||
messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot;
|
||||
|
@ -1865,6 +1866,7 @@ channels.createForumTopic#f40c0224 flags:# channel:InputChannel title:string ico
|
|||
channels.getForumTopics#de560d1 flags:# channel:InputChannel q:flags.0?string offset_date:int offset_id:int offset_topic:int limit:int = messages.ForumTopics;
|
||||
channels.getForumTopicsByID#b0831eb9 channel:InputChannel topics:Vector<int> = messages.ForumTopics;
|
||||
channels.editForumTopic#8a7f464b flags:# channel:InputChannel topic_id:int title:flags.0?string icon_emoji_id:flags.1?long = Updates;
|
||||
channels.deleteTopicHistory#34435f2d channel:InputChannel top_msg_id:int = messages.AffectedHistory;
|
||||
|
||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||
|
|
|
@ -41,24 +41,22 @@ constexpr auto kNextRequestLimit = 100;
|
|||
UnreadThings::UnreadThings(not_null<ApiWrap*> api) : _api(api) {
|
||||
}
|
||||
|
||||
bool UnreadThings::trackMentions(PeerData *peer) const {
|
||||
bool UnreadThings::trackMentions(DialogsEntry *entry) const {
|
||||
const auto peer = entry ? ResolveHistory(entry)->peer.get() : nullptr;
|
||||
return peer && (peer->isChat() || peer->isMegagroup());
|
||||
}
|
||||
|
||||
bool UnreadThings::trackReactions(PeerData *peer) const {
|
||||
return trackMentions(peer) || (peer && peer->isUser());
|
||||
bool UnreadThings::trackReactions(DialogsEntry *entry) const {
|
||||
const auto peer = entry ? ResolveHistory(entry)->peer.get() : nullptr;
|
||||
return peer && (peer->isChat() || peer->isMegagroup());
|
||||
}
|
||||
|
||||
void UnreadThings::preloadEnough(DialogsEntry *entry) {
|
||||
if (!entry) {
|
||||
return;
|
||||
if (trackMentions(entry)) {
|
||||
preloadEnoughMentions(entry);
|
||||
}
|
||||
const auto history = ResolveHistory(entry);
|
||||
if (trackMentions(history->peer)) {
|
||||
preloadEnoughMentions(history);
|
||||
}
|
||||
if (trackReactions(history->peer)) {
|
||||
preloadEnoughReactions(history);
|
||||
if (trackReactions(entry)) {
|
||||
preloadEnoughReactions(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ public:
|
|||
|
||||
explicit UnreadThings(not_null<ApiWrap*> api);
|
||||
|
||||
[[nodiscard]] bool trackMentions(PeerData *peer) const;
|
||||
[[nodiscard]] bool trackReactions(PeerData *peer) const;
|
||||
[[nodiscard]] bool trackMentions(DialogsEntry *entry) const;
|
||||
[[nodiscard]] bool trackReactions(DialogsEntry *entry) const;
|
||||
|
||||
void preloadEnough(DialogsEntry *entry);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Data {
|
|||
|
||||
class Session;
|
||||
|
||||
class Folder final : public Dialogs::Entry, public base::has_weak_ptr {
|
||||
class Folder final : public Dialogs::Entry {
|
||||
public:
|
||||
static constexpr auto kId = 1;
|
||||
|
||||
|
|
|
@ -239,6 +239,12 @@ void Forum::clearAllUnreadMentions() {
|
|||
}
|
||||
}
|
||||
|
||||
void Forum::clearAllUnreadReactions() {
|
||||
for (const auto &[rootId, topic] : _topics) {
|
||||
topic->unreadReactions().clear();
|
||||
}
|
||||
}
|
||||
|
||||
ForumTopic *Forum::topicFor(not_null<const HistoryItem*> item) {
|
||||
const auto maybe = topicFor(item->replyToTop());
|
||||
return maybe ? maybe : topicFor(item->topicRootId());
|
||||
|
|
|
@ -60,6 +60,7 @@ public:
|
|||
void created(MsgId rootId, MsgId realId);
|
||||
|
||||
void clearAllUnreadMentions();
|
||||
void clearAllUnreadReactions();
|
||||
|
||||
private:
|
||||
struct TopicRequest {
|
||||
|
|
|
@ -10,8 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_sparse_ids.h"
|
||||
#include "storage/storage_sparse_ids_list.h"
|
||||
#include "storage/storage_shared_media.h"
|
||||
#include "base/value_ordering.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/qt/qt_compare.h"
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
|
@ -58,13 +58,9 @@ public:
|
|||
QString query;
|
||||
// from_id, min_date, max_date
|
||||
|
||||
friend inline auto value_ordering_helper(const Query &value) {
|
||||
return std::tie(
|
||||
value.peerId,
|
||||
value.migratedPeerId,
|
||||
value.type,
|
||||
value.query);
|
||||
}
|
||||
friend inline std::strong_ordering operator<=>(
|
||||
const Query &a,
|
||||
const Query &b) noexcept = default;
|
||||
|
||||
};
|
||||
struct SavedState {
|
||||
|
|
|
@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/value_ordering.h"
|
||||
#include "ui/text/text.h" // For QFIXED_MAX
|
||||
#include "data/data_peer_id.h"
|
||||
#include "data/data_msg_id.h"
|
||||
|
@ -84,9 +83,9 @@ struct MessageGroupId {
|
|||
return value;
|
||||
}
|
||||
|
||||
friend inline std::pair<uint64, uint64> value_ordering_helper(MessageGroupId value) {
|
||||
return std::make_pair(value.value, value.peer.value);
|
||||
}
|
||||
friend inline constexpr auto operator<=>(
|
||||
MessageGroupId,
|
||||
MessageGroupId) noexcept = default;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -131,6 +131,14 @@ const base::flat_set<MsgId> &Entry::unreadMentionsIds() const {
|
|||
return _unreadThings->mentions.ids();
|
||||
}
|
||||
|
||||
const base::flat_set<MsgId> &Entry::unreadReactionsIds() const {
|
||||
if (!_unreadThings) {
|
||||
static const auto Result = base::flat_set<MsgId>();
|
||||
return Result;
|
||||
}
|
||||
return _unreadThings->reactions.ids();
|
||||
}
|
||||
|
||||
bool Entry::needUpdateInChatList() const {
|
||||
return inChatList() || shouldBeInChatList();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "base/flat_map.h"
|
||||
|
||||
#include "base/weak_ptr.h"
|
||||
#include "dialogs/dialogs_key.h"
|
||||
#include "ui/unread_badge.h"
|
||||
|
||||
|
@ -105,7 +105,7 @@ inline UnreadState operator-(const UnreadState &a, const UnreadState &b) {
|
|||
return result;
|
||||
}
|
||||
|
||||
class Entry {
|
||||
class Entry : public base::has_weak_ptr {
|
||||
public:
|
||||
enum class Type : uchar {
|
||||
History,
|
||||
|
@ -223,6 +223,7 @@ protected:
|
|||
void cacheTopPromoted(bool promoted);
|
||||
|
||||
[[nodiscard]] const base::flat_set<MsgId> &unreadMentionsIds() const;
|
||||
[[nodiscard]] const base::flat_set<MsgId> &unreadReactionsIds() const;
|
||||
|
||||
private:
|
||||
enum class Flag : uchar {
|
||||
|
|
|
@ -7,8 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/value_ordering.h"
|
||||
|
||||
class History;
|
||||
class PeerData;
|
||||
|
||||
|
@ -45,29 +43,7 @@ public:
|
|||
History *parentHistory() const;
|
||||
PeerData *peer() const;
|
||||
|
||||
inline bool operator<(const Key &other) const {
|
||||
return _value < other._value;
|
||||
}
|
||||
inline bool operator>(const Key &other) const {
|
||||
return (other < *this);
|
||||
}
|
||||
inline bool operator<=(const Key &other) const {
|
||||
return !(other < *this);
|
||||
}
|
||||
inline bool operator>=(const Key &other) const {
|
||||
return !(*this < other);
|
||||
}
|
||||
inline bool operator==(const Key &other) const {
|
||||
return _value == other._value;
|
||||
}
|
||||
inline bool operator!=(const Key &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
// Not working :(
|
||||
//friend inline auto value_ordering_helper(const Key &key) {
|
||||
// return key.value;
|
||||
//}
|
||||
friend inline constexpr auto operator<=>(Key, Key) noexcept = default;
|
||||
|
||||
private:
|
||||
Entry *_value = nullptr;
|
||||
|
|
|
@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "export/output/export_output_result.h"
|
||||
#include "export/output/export_output_file.h"
|
||||
#include "mtproto/mtproto_response.h"
|
||||
#include "base/value_ordering.h"
|
||||
#include "base/bytes.h"
|
||||
#include "base/random.h"
|
||||
#include <set>
|
||||
|
|
|
@ -700,6 +700,18 @@ not_null<HistoryItem*> History::addNewLocalMessage(
|
|||
}
|
||||
|
||||
void History::clearUnreadMentionsFor(MsgId topicRootId) {
|
||||
const auto forum = peer->forum();
|
||||
if (!topicRootId) {
|
||||
if (forum) {
|
||||
forum->clearAllUnreadMentions();
|
||||
}
|
||||
unreadMentions().clear();
|
||||
return;
|
||||
} else if (forum) {
|
||||
if (const auto topic = forum->topicFor(topicRootId)) {
|
||||
topic->unreadMentions().clear();
|
||||
}
|
||||
}
|
||||
const auto &ids = unreadMentionsIds();
|
||||
if (ids.empty()) {
|
||||
return;
|
||||
|
@ -720,6 +732,39 @@ void History::clearUnreadMentionsFor(MsgId topicRootId) {
|
|||
}
|
||||
}
|
||||
|
||||
void History::clearUnreadReactionsFor(MsgId topicRootId) {
|
||||
const auto forum = peer->forum();
|
||||
if (!topicRootId) {
|
||||
if (forum) {
|
||||
forum->clearAllUnreadReactions();
|
||||
}
|
||||
unreadReactions().clear();
|
||||
return;
|
||||
} else if (forum) {
|
||||
if (const auto topic = forum->topicFor(topicRootId)) {
|
||||
topic->unreadReactions().clear();
|
||||
}
|
||||
}
|
||||
const auto &ids = unreadReactionsIds();
|
||||
if (ids.empty()) {
|
||||
return;
|
||||
}
|
||||
const auto owner = &this->owner();
|
||||
const auto peerId = peer->id;
|
||||
auto items = base::flat_set<MsgId>();
|
||||
items.reserve(ids.size());
|
||||
for (const auto &id : ids) {
|
||||
if (const auto item = owner->message(peerId, id)) {
|
||||
if (item->topicRootId() == topicRootId) {
|
||||
items.emplace(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto &id : items) {
|
||||
unreadReactions().erase(id);
|
||||
}
|
||||
}
|
||||
|
||||
not_null<HistoryItem*> History::addNewToBack(
|
||||
not_null<HistoryItem*> item,
|
||||
bool unread) {
|
||||
|
|
|
@ -331,6 +331,7 @@ public:
|
|||
|
||||
void clearLastKeyboard();
|
||||
void clearUnreadMentionsFor(MsgId topicRootId);
|
||||
void clearUnreadReactionsFor(MsgId topicRootId);
|
||||
|
||||
Data::Draft *draft(Data::DraftKey key) const;
|
||||
void setDraft(Data::DraftKey key, std::unique_ptr<Data::Draft> &&draft);
|
||||
|
|
|
@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "base/runtime_composer.h"
|
||||
#include "base/flags.h"
|
||||
#include "base/value_ordering.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "history/history_item_edition.h"
|
||||
#include "history/history_item_reply_markup.h"
|
||||
|
|
|
@ -228,15 +228,10 @@ HistoryWidget::HistoryWidget(
|
|||
controller->chatStyle()->value(lifetime(), st::historyScroll),
|
||||
false)
|
||||
, _updateHistoryItems([=] { updateHistoryItemsByTimer(); })
|
||||
, _historyDown(
|
||||
_scroll,
|
||||
controller->chatStyle()->value(lifetime(), st::historyToDown))
|
||||
, _unreadMentions(
|
||||
_scroll,
|
||||
controller->chatStyle()->value(lifetime(), st::historyUnreadMentions))
|
||||
, _unreadReactions(
|
||||
_scroll,
|
||||
controller->chatStyle()->value(lifetime(), st::historyUnreadReactions))
|
||||
, _cornerButtons(
|
||||
_scroll.data(),
|
||||
controller->chatStyle(),
|
||||
static_cast<HistoryView::CornerButtonsDelegate*>(this))
|
||||
, _fieldAutocomplete(this, controller)
|
||||
, _supportAutocomplete(session().supportMode()
|
||||
? object_ptr<Support::Autocomplete>(this, &session())
|
||||
|
@ -306,13 +301,6 @@ HistoryWidget::HistoryWidget(
|
|||
}
|
||||
}, lifetime());
|
||||
|
||||
_historyDown.widget->addClickHandler([=] { historyDownClicked(); });
|
||||
_unreadMentions.widget->addClickHandler([=] {
|
||||
showNextUnreadMention();
|
||||
});
|
||||
_unreadReactions.widget->addClickHandler([=] {
|
||||
showNextUnreadReaction();
|
||||
});
|
||||
_fieldBarCancel->addClickHandler([=] { cancelFieldAreaState(); });
|
||||
_send->addClickHandler([=] { sendButtonClicked(); });
|
||||
|
||||
|
@ -385,16 +373,6 @@ HistoryWidget::HistoryWidget(
|
|||
_scroll->updateBars();
|
||||
}, lifetime());
|
||||
|
||||
_historyDown.widget->installEventFilter(this);
|
||||
_unreadMentions.widget->installEventFilter(this);
|
||||
_unreadReactions.widget->installEventFilter(this);
|
||||
SendMenu::SetupUnreadMentionsMenu(_unreadMentions.widget.data(), [=] {
|
||||
return _history ? _history->peer.get() : nullptr;
|
||||
}, MsgId(0));
|
||||
SendMenu::SetupUnreadReactionsMenu(_unreadReactions.widget.data(), [=] {
|
||||
return _history ? _history->peer.get() : nullptr;
|
||||
});
|
||||
|
||||
InitMessageField(controller, _field, [=](
|
||||
not_null<DocumentData*> document) {
|
||||
if (_peer && Data::AllowEmojiWithoutPremium(_peer)) {
|
||||
|
@ -582,7 +560,7 @@ HistoryWidget::HistoryWidget(
|
|||
) | rpl::filter([=](not_null<ChannelData*> channel) {
|
||||
return _peer == channel.get();
|
||||
}) | rpl::start_with_next([=] {
|
||||
updateHistoryDownVisibility();
|
||||
_cornerButtons.updateJumpDownVisibility();
|
||||
preloadHistoryIfNeeded();
|
||||
}, lifetime());
|
||||
|
||||
|
@ -648,7 +626,7 @@ HistoryWidget::HistoryWidget(
|
|||
}
|
||||
if ((flags & HistoryUpdateFlag::UnreadMentions)
|
||||
|| (flags & HistoryUpdateFlag::UnreadReactions)) {
|
||||
updateUnreadThingsVisibility();
|
||||
_cornerButtons.updateUnreadThingsVisibility();
|
||||
}
|
||||
if (flags & HistoryUpdateFlag::UnreadView) {
|
||||
unreadCountUpdated();
|
||||
|
@ -1007,8 +985,8 @@ void HistoryWidget::initVoiceRecordBar() {
|
|||
|
||||
_voiceRecordBar->lockShowStarts(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateHistoryDownVisibility();
|
||||
updateUnreadThingsVisibility();
|
||||
_cornerButtons.updateJumpDownVisibility();
|
||||
_cornerButtons.updateUnreadThingsVisibility();
|
||||
}, lifetime());
|
||||
|
||||
_voiceRecordBar->updateSendButtonTypeRequests(
|
||||
|
@ -1855,73 +1833,25 @@ void HistoryWidget::setupShortcuts() {
|
|||
}, lifetime());
|
||||
}
|
||||
|
||||
void HistoryWidget::clearReplyReturns() {
|
||||
_replyReturns.clear();
|
||||
_replyReturn = nullptr;
|
||||
}
|
||||
|
||||
void HistoryWidget::pushReplyReturn(not_null<HistoryItem*> item) {
|
||||
if (item->history() == _history) {
|
||||
_replyReturns.push_back(item->id);
|
||||
} else if (item->history() == _migrated) {
|
||||
_replyReturns.push_back(-item->id);
|
||||
} else {
|
||||
if (item->history() != _history && item->history() != _migrated) {
|
||||
return;
|
||||
}
|
||||
_replyReturn = item;
|
||||
_cornerButtons.pushReplyReturn(item);
|
||||
updateControlsVisibility();
|
||||
}
|
||||
|
||||
QList<MsgId> HistoryWidget::replyReturns() {
|
||||
return _replyReturns;
|
||||
QVector<FullMsgId> HistoryWidget::replyReturns() const {
|
||||
return _cornerButtons.replyReturns();
|
||||
}
|
||||
|
||||
void HistoryWidget::setReplyReturns(PeerId peer, const QList<MsgId> &replyReturns) {
|
||||
if (!_peer || _peer->id != peer) return;
|
||||
|
||||
_replyReturns = replyReturns;
|
||||
if (_replyReturns.isEmpty()) {
|
||||
_replyReturn = nullptr;
|
||||
} else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) {
|
||||
_replyReturn = _migrated
|
||||
? session().data().message(_migrated->peer, -_replyReturns.back())
|
||||
: nullptr;
|
||||
} else {
|
||||
_replyReturn = session().data().message(peer, _replyReturns.back());
|
||||
}
|
||||
while (!_replyReturns.isEmpty() && !_replyReturn) {
|
||||
_replyReturns.pop_back();
|
||||
if (_replyReturns.isEmpty()) {
|
||||
_replyReturn = nullptr;
|
||||
} else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) {
|
||||
_replyReturn = _migrated
|
||||
? session().data().message(_migrated->peer, -_replyReturns.back())
|
||||
: nullptr;
|
||||
} else {
|
||||
_replyReturn = session().data().message(peer, _replyReturns.back());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::calcNextReplyReturn() {
|
||||
_replyReturn = nullptr;
|
||||
while (!_replyReturns.isEmpty() && !_replyReturn) {
|
||||
_replyReturns.pop_back();
|
||||
if (_replyReturns.isEmpty()) {
|
||||
_replyReturn = nullptr;
|
||||
} else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) {
|
||||
_replyReturn = _migrated
|
||||
? session().data().message(_migrated->peer, -_replyReturns.back())
|
||||
: nullptr;
|
||||
} else {
|
||||
_replyReturn = _peer
|
||||
? session().data().message(_peer, _replyReturns.back())
|
||||
: nullptr;
|
||||
}
|
||||
}
|
||||
if (!_replyReturn) {
|
||||
updateControlsVisibility();
|
||||
void HistoryWidget::setReplyReturns(
|
||||
PeerId peer,
|
||||
QVector<FullMsgId> replyReturns) {
|
||||
if (!_peer || _peer->id != peer) {
|
||||
return;
|
||||
}
|
||||
_cornerButtons.setReplyReturns(std::move(replyReturns));
|
||||
}
|
||||
|
||||
void HistoryWidget::fastShowAtEnd(not_null<History*> history) {
|
||||
|
@ -2074,14 +2004,13 @@ void HistoryWidget::showHistory(
|
|||
}
|
||||
|
||||
clearDelayedShowAt();
|
||||
while (_replyReturn) {
|
||||
if (_replyReturn->history() == _history && _replyReturn->id == showAtMsgId) {
|
||||
calcNextReplyReturn();
|
||||
} else if (_replyReturn->history() == _migrated && -_replyReturn->id == showAtMsgId) {
|
||||
calcNextReplyReturn();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
const auto skipId = (_migrated && showAtMsgId < 0)
|
||||
? FullMsgId(_migrated->peer->id, -showAtMsgId)
|
||||
: (showAtMsgId > 0)
|
||||
? FullMsgId(_history->peer->id, showAtMsgId)
|
||||
: FullMsgId();
|
||||
if (skipId) {
|
||||
_cornerButtons.skipReplyReturn(skipId);
|
||||
}
|
||||
|
||||
setMsgId(showAtMsgId);
|
||||
|
@ -2127,7 +2056,7 @@ void HistoryWidget::showHistory(
|
|||
session().sendProgressManager().cancelTyping(_history);
|
||||
}
|
||||
|
||||
clearReplyReturns();
|
||||
_cornerButtons.clearReplyReturns();
|
||||
if (_history) {
|
||||
if (Ui::InFocusChain(_list)) {
|
||||
// Removing focus from list clears selected and updates top bar.
|
||||
|
@ -2632,8 +2561,8 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_topShadow->setVisible(_peer != nullptr);
|
||||
_topBar->setVisible(_peer != nullptr);
|
||||
}
|
||||
updateHistoryDownVisibility();
|
||||
updateUnreadThingsVisibility();
|
||||
_cornerButtons.updateJumpDownVisibility();
|
||||
_cornerButtons.updateUnreadThingsVisibility();
|
||||
if (!_history || _a_show.animating()) {
|
||||
hideChildWidgets();
|
||||
return;
|
||||
|
@ -2975,8 +2904,8 @@ void HistoryWidget::unreadCountUpdated() {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
updateHistoryDownVisibility();
|
||||
_historyDown.widget->setUnreadCount(_history->chatListUnreadCount());
|
||||
_cornerButtons.updateJumpDownVisibility(
|
||||
_history->chatListUnreadCount());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3123,16 +3052,13 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
|
|||
firstLoadMessages();
|
||||
return;
|
||||
}
|
||||
while (_replyReturn) {
|
||||
if (_replyReturn->history() == _history
|
||||
&& _replyReturn->id == _delayedShowAtMsgId) {
|
||||
calcNextReplyReturn();
|
||||
} else if (_replyReturn->history() == _migrated
|
||||
&& -_replyReturn->id == _delayedShowAtMsgId) {
|
||||
calcNextReplyReturn();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
const auto skipId = (_migrated && _delayedShowAtMsgId < 0)
|
||||
? FullMsgId(_migrated->peer->id, -_delayedShowAtMsgId)
|
||||
: (_delayedShowAtMsgId > 0)
|
||||
? FullMsgId(_history->peer->id, _delayedShowAtMsgId)
|
||||
: FullMsgId();
|
||||
if (skipId) {
|
||||
_cornerButtons.skipReplyReturn(skipId);
|
||||
}
|
||||
|
||||
_delayedShowAtRequest = 0;
|
||||
|
@ -3464,8 +3390,8 @@ void HistoryWidget::preloadHistoryIfNeeded() {
|
|||
return;
|
||||
}
|
||||
|
||||
updateHistoryDownVisibility();
|
||||
updateUnreadThingsVisibility();
|
||||
_cornerButtons.updateJumpDownVisibility();
|
||||
_cornerButtons.updateUnreadThingsVisibility();
|
||||
if (!_scrollToAnimation.animating()) {
|
||||
preloadHistoryByScroll();
|
||||
checkReplyReturns();
|
||||
|
@ -3535,19 +3461,32 @@ void HistoryWidget::checkReplyReturns() {
|
|||
auto scrollTop = _scroll->scrollTop();
|
||||
auto scrollTopMax = _scroll->scrollTopMax();
|
||||
auto scrollHeight = _scroll->height();
|
||||
while (_replyReturn) {
|
||||
auto below = (!_replyReturn->mainView() && _replyReturn->history() == _history && !_history->isEmpty() && _replyReturn->id < _history->blocks.back()->messages.back()->data()->id);
|
||||
while (const auto replyReturn = _cornerButtons.replyReturn()) {
|
||||
auto below = !replyReturn->mainView()
|
||||
&& (replyReturn->history() == _history)
|
||||
&& !_history->isEmpty()
|
||||
&& (replyReturn->id
|
||||
< _history->blocks.back()->messages.back()->data()->id);
|
||||
if (!below) {
|
||||
below = (!_replyReturn->mainView() && _replyReturn->history() == _migrated && !_history->isEmpty());
|
||||
below = !replyReturn->mainView()
|
||||
&& (replyReturn->history() == _migrated)
|
||||
&& !_history->isEmpty();
|
||||
}
|
||||
if (!below) {
|
||||
below = (!_replyReturn->mainView() && _migrated && _replyReturn->history() == _migrated && !_migrated->isEmpty() && _replyReturn->id < _migrated->blocks.back()->messages.back()->data()->id);
|
||||
below = !replyReturn->mainView()
|
||||
&& _migrated
|
||||
&& (replyReturn->history() == _migrated)
|
||||
&& !_migrated->isEmpty()
|
||||
&& (replyReturn->id
|
||||
< _migrated->blocks.back()->messages.back()->data()->id);
|
||||
}
|
||||
if (!below && _replyReturn->mainView()) {
|
||||
below = (scrollTop >= scrollTopMax) || (_list->itemTop(_replyReturn) < scrollTop + scrollHeight / 2);
|
||||
if (!below && replyReturn->mainView()) {
|
||||
below = (scrollTop >= scrollTopMax)
|
||||
|| (_list->itemTop(replyReturn)
|
||||
< scrollTop + scrollHeight / 2);
|
||||
}
|
||||
if (below) {
|
||||
calcNextReplyReturn();
|
||||
_cornerButtons.calculateNextReplyReturn();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -3574,46 +3513,6 @@ void HistoryWidget::windowIsVisibleChanged() {
|
|||
});
|
||||
}
|
||||
|
||||
void HistoryWidget::historyDownClicked() {
|
||||
if (base::IsCtrlPressed()) {
|
||||
showHistory(_peer->id, ShowAtUnreadMsgId);
|
||||
} else if (_replyReturn && _replyReturn->history() == _history) {
|
||||
showHistory(_peer->id, _replyReturn->id);
|
||||
} else if (_replyReturn && _replyReturn->history() == _migrated) {
|
||||
showHistory(_peer->id, -_replyReturn->id);
|
||||
} else if (_peer) {
|
||||
showHistory(_peer->id, ShowAtUnreadMsgId);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::showNextUnreadMention() {
|
||||
const auto msgId = _history->unreadMentions().minLoaded();
|
||||
const auto already = (_showAtMsgId == msgId);
|
||||
|
||||
// Mark mention voice/video message as read.
|
||||
// See https://github.com/telegramdesktop/tdesktop/issues/5623
|
||||
if (msgId && already) {
|
||||
const auto item = _history->owner().message(
|
||||
_history->peer->id,
|
||||
msgId);
|
||||
if (const auto media = item ? item->media() : nullptr) {
|
||||
if (const auto document = media->document()) {
|
||||
if (!media->webpage()
|
||||
&& (document->isVoiceMessage()
|
||||
|| document->isVideoMessage())) {
|
||||
document->owner().markMediaRead(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
showHistory(_peer->id, msgId);
|
||||
}
|
||||
|
||||
void HistoryWidget::showNextUnreadReaction() {
|
||||
const auto msgId = _history->unreadReactions().minLoaded();
|
||||
showHistory(_peer->id, msgId);
|
||||
}
|
||||
|
||||
void HistoryWidget::saveEditMsg() {
|
||||
Expects(_history != nullptr);
|
||||
|
||||
|
@ -3771,7 +3670,7 @@ void HistoryWidget::send(Api::SendOptions options) {
|
|||
}
|
||||
|
||||
if (!options.scheduled) {
|
||||
clearReplyReturns();
|
||||
_cornerButtons.clearReplyReturns();
|
||||
}
|
||||
|
||||
const auto webPageId = (_previewState != Data::PreviewState::Allowed)
|
||||
|
@ -3965,7 +3864,7 @@ void HistoryWidget::showAnimated(
|
|||
_preserveScrollTop = true;
|
||||
show();
|
||||
_topBar->finishAnimating();
|
||||
cornerButtonsAnimationFinish();
|
||||
_cornerButtons.finishAnimations();
|
||||
if (_pinnedBar) {
|
||||
_pinnedBar->finishAnimating();
|
||||
}
|
||||
|
@ -3999,7 +3898,7 @@ void HistoryWidget::showAnimated(
|
|||
void HistoryWidget::animationCallback() {
|
||||
update();
|
||||
if (!_a_show.animating()) {
|
||||
cornerButtonsAnimationFinish();
|
||||
_cornerButtons.finishAnimations();
|
||||
if (_pinnedBar) {
|
||||
_pinnedBar->finishAnimating();
|
||||
}
|
||||
|
@ -4044,6 +3943,29 @@ void HistoryWidget::doneShow() {
|
|||
checkSuggestToGigagroup();
|
||||
}
|
||||
|
||||
void HistoryWidget::cornerButtonsShowAtPosition(
|
||||
Data::MessagePosition position) {
|
||||
if (position == Data::UnreadMessagePosition) {
|
||||
showHistory(_peer->id, ShowAtUnreadMsgId);
|
||||
} else if (_peer && position.fullId.peer == _peer->id) {
|
||||
showHistory(_peer->id, position.fullId.msg);
|
||||
} else if (_migrated && position.fullId.peer == _migrated->peer->id) {
|
||||
showHistory(_peer->id, -position.fullId.msg);
|
||||
}
|
||||
}
|
||||
|
||||
Dialogs::Entry *HistoryWidget::cornerButtonsEntry() {
|
||||
return _history;
|
||||
}
|
||||
|
||||
FullMsgId HistoryWidget::cornerButtonsCurrentId() {
|
||||
return (_migrated && _showAtMsgId < 0)
|
||||
? FullMsgId(_migrated->peer->id, -_showAtMsgId)
|
||||
: (_history && _showAtMsgId > 0)
|
||||
? FullMsgId(_history->peer->id, _showAtMsgId)
|
||||
: FullMsgId();
|
||||
}
|
||||
|
||||
void HistoryWidget::checkSuggestToGigagroup() {
|
||||
const auto group = _peer ? _peer->asMegagroup() : nullptr;
|
||||
if (!group || !group->owner().suggestToGigagroup(group)) {
|
||||
|
@ -4080,14 +4002,7 @@ void HistoryWidget::finishAnimating() {
|
|||
_a_show.stop();
|
||||
_topShadow->setVisible(_peer != nullptr);
|
||||
_topBar->setVisible(_peer != nullptr);
|
||||
cornerButtonsAnimationFinish();
|
||||
}
|
||||
|
||||
void HistoryWidget::cornerButtonsAnimationFinish() {
|
||||
_historyDown.animation.stop();
|
||||
_unreadMentions.animation.stop();
|
||||
_unreadReactions.animation.stop();
|
||||
updateCornerButtonsPositions();
|
||||
_cornerButtons.finishAnimations();
|
||||
}
|
||||
|
||||
void HistoryWidget::chooseAttach(
|
||||
|
@ -4320,12 +4235,6 @@ bool HistoryWidget::eventFilter(QObject *obj, QEvent *e) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (e->type() == QEvent::Wheel
|
||||
&& (obj == _historyDown.widget
|
||||
|| obj == _unreadMentions.widget
|
||||
|| obj == _unreadReactions.widget)) {
|
||||
return _scroll->viewportEvent(e);
|
||||
}
|
||||
return TWidget::eventFilter(obj, e);
|
||||
}
|
||||
|
||||
|
@ -5296,7 +5205,7 @@ void HistoryWidget::updateControlsGeometry() {
|
|||
|
||||
updateFieldSize();
|
||||
|
||||
updateCornerButtonsPositions();
|
||||
_cornerButtons.updatePositions();
|
||||
|
||||
if (_membersDropdown) {
|
||||
_membersDropdown->setMaxHeight(countMembersDropdownHeightMax());
|
||||
|
@ -5324,8 +5233,8 @@ void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) {
|
|||
if (item == _replyEditMsg && _replyToId) {
|
||||
cancelReply();
|
||||
}
|
||||
while (item == _replyReturn) {
|
||||
calcNextReplyReturn();
|
||||
while (item == _cornerButtons.replyReturn()) {
|
||||
_cornerButtons.calculateNextReplyReturn();
|
||||
}
|
||||
if (_kbReplyTo && item == _kbReplyTo) {
|
||||
toggleKeyboard();
|
||||
|
@ -5514,7 +5423,7 @@ void HistoryWidget::updateHistoryGeometry(
|
|||
if (_supportAutocomplete) {
|
||||
_supportAutocomplete->setBoundings(_scroll->geometry());
|
||||
}
|
||||
updateCornerButtonsPositions();
|
||||
_cornerButtons.updatePositions();
|
||||
controller()->floatPlayerAreaUpdated();
|
||||
}
|
||||
|
||||
|
@ -5856,75 +5765,24 @@ int HistoryWidget::computeMaxFieldHeight() const {
|
|||
return std::min(st::historyComposeFieldMaxHeight, available);
|
||||
}
|
||||
|
||||
void HistoryWidget::updateCornerButtonsPositions() {
|
||||
const auto checkVisibility = [](CornerButton &button) {
|
||||
const auto shouldBeHidden = !button.shown
|
||||
&& !button.animation.animating();
|
||||
if (shouldBeHidden != button.widget->isHidden()) {
|
||||
button.widget->setVisible(!shouldBeHidden);
|
||||
}
|
||||
};
|
||||
const auto shown = [](CornerButton &button) {
|
||||
return button.animation.value(button.shown ? 1. : 0.);
|
||||
};
|
||||
|
||||
// All corner buttons is a child widgets of _scroll, not me.
|
||||
|
||||
const auto historyDownShown = shown(_historyDown);
|
||||
const auto unreadMentionsShown = shown(_unreadMentions);
|
||||
const auto unreadReactionsShown = shown(_unreadReactions);
|
||||
const auto skip = st::historyUnreadThingsSkip;
|
||||
{
|
||||
const auto top = anim::interpolate(
|
||||
0,
|
||||
_historyDown.widget->height() + st::historyToDownPosition.y(),
|
||||
historyDownShown);
|
||||
_historyDown.widget->moveToRight(
|
||||
st::historyToDownPosition.x(),
|
||||
_scroll->height() - top);
|
||||
}
|
||||
{
|
||||
const auto right = anim::interpolate(
|
||||
-_unreadMentions.widget->width(),
|
||||
st::historyToDownPosition.x(),
|
||||
unreadMentionsShown);
|
||||
const auto shift = anim::interpolate(
|
||||
0,
|
||||
_historyDown.widget->height() + skip,
|
||||
historyDownShown);
|
||||
const auto top = _scroll->height()
|
||||
- _unreadMentions.widget->height()
|
||||
- st::historyToDownPosition.y()
|
||||
- shift;
|
||||
_unreadMentions.widget->moveToRight(right, top);
|
||||
}
|
||||
{
|
||||
const auto right = anim::interpolate(
|
||||
-_unreadReactions.widget->width(),
|
||||
st::historyToDownPosition.x(),
|
||||
unreadReactionsShown);
|
||||
const auto shift = anim::interpolate(
|
||||
0,
|
||||
_historyDown.widget->height() + skip,
|
||||
historyDownShown
|
||||
) + anim::interpolate(
|
||||
0,
|
||||
_unreadMentions.widget->height() + skip,
|
||||
unreadMentionsShown);
|
||||
const auto top = _scroll->height()
|
||||
- _unreadReactions.widget->height()
|
||||
- st::historyToDownPosition.y()
|
||||
- shift;
|
||||
_unreadReactions.widget->moveToRight(right, top);
|
||||
}
|
||||
|
||||
checkVisibility(_historyDown);
|
||||
checkVisibility(_unreadMentions);
|
||||
checkVisibility(_unreadReactions);
|
||||
bool HistoryWidget::cornerButtonsIgnoreVisibility() {
|
||||
return _a_show.animating();
|
||||
}
|
||||
|
||||
void HistoryWidget::updateHistoryDownVisibility() {
|
||||
if (_a_show.animating()) return;
|
||||
bool HistoryWidget::cornerButtonsDownShown() {
|
||||
if (!_list || _firstLoadRequest) {
|
||||
return false;
|
||||
}
|
||||
if (_voiceRecordBar->isLockPresent()) {
|
||||
return false;
|
||||
}
|
||||
if (!_history->loadedAtBottom() || _cornerButtons.replyReturn()) {
|
||||
return true;
|
||||
}
|
||||
const auto top = _scroll->scrollTop() + st::historyToDownShownAfter;
|
||||
if (top < _scroll->scrollTopMax()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto haveUnreadBelowBottom = [&](History *history) {
|
||||
if (!_list || !history || history->unreadCount() <= 0) {
|
||||
|
@ -5937,75 +5795,15 @@ void HistoryWidget::updateHistoryDownVisibility() {
|
|||
const auto top = _list->itemTop(unread);
|
||||
return (top >= _scroll->scrollTop() + _scroll->height());
|
||||
};
|
||||
updateCornerButtonVisibility(_historyDown, [&] {
|
||||
if (!_list || _firstLoadRequest) {
|
||||
return false;
|
||||
}
|
||||
if (_voiceRecordBar->isLockPresent()) {
|
||||
return false;
|
||||
}
|
||||
if (!_history->loadedAtBottom() || _replyReturn) {
|
||||
return true;
|
||||
}
|
||||
const auto top = _scroll->scrollTop() + st::historyToDownShownAfter;
|
||||
if (top < _scroll->scrollTopMax()) {
|
||||
return true;
|
||||
}
|
||||
if (haveUnreadBelowBottom(_history)
|
||||
|| haveUnreadBelowBottom(_migrated)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}());
|
||||
if (haveUnreadBelowBottom(_history)
|
||||
|| haveUnreadBelowBottom(_migrated)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HistoryWidget::updateCornerButtonVisibility(
|
||||
CornerButton &button,
|
||||
bool shown) {
|
||||
if (button.shown != shown) {
|
||||
button.shown = shown;
|
||||
button.animation.start(
|
||||
[=] { updateCornerButtonsPositions(); },
|
||||
shown ? 0. : 1.,
|
||||
shown ? 1. : 0.,
|
||||
st::historyToDownDuration);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::updateUnreadThingsVisibility() {
|
||||
if (_a_show.animating()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &unreadThings = session().api().unreadThings();
|
||||
unreadThings.preloadEnough(_history);
|
||||
|
||||
const auto updateWithLoadedCount = [&](CornerButton &button, int count) {
|
||||
updateCornerButtonVisibility(button, (count > 0)
|
||||
&& !_firstLoadRequest
|
||||
&& !_voiceRecordBar->isLockPresent());
|
||||
};
|
||||
if (unreadThings.trackMentions(_peer)) {
|
||||
if (const auto count = _history->unreadMentions().count(0)) {
|
||||
_unreadMentions.widget->setUnreadCount(count);
|
||||
}
|
||||
updateWithLoadedCount(
|
||||
_unreadMentions,
|
||||
_history->unreadMentions().loadedCount());
|
||||
} else {
|
||||
updateCornerButtonVisibility(_unreadMentions, false);
|
||||
}
|
||||
|
||||
if (unreadThings.trackReactions(_peer)) {
|
||||
if (const auto count = _history->unreadReactions().count(0)) {
|
||||
_unreadReactions.widget->setUnreadCount(count);
|
||||
}
|
||||
updateWithLoadedCount(
|
||||
_unreadReactions,
|
||||
_history->unreadReactions().loadedCount());
|
||||
} else {
|
||||
updateCornerButtonVisibility(_unreadReactions, false);
|
||||
}
|
||||
bool HistoryWidget::cornerButtonsUnreadMayBeShown() {
|
||||
return !_firstLoadRequest && !_voiceRecordBar->isLockPresent();
|
||||
}
|
||||
|
||||
void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "history/view/history_view_corner_buttons.h"
|
||||
#include "history/history_drag_area.h"
|
||||
#include "history/history_view_highlight_manager.h"
|
||||
#include "history/history_view_top_toast.h"
|
||||
|
@ -107,7 +108,9 @@ class HistoryInner;
|
|||
|
||||
extern const char kOptionAutoScrollInactiveChat[];
|
||||
|
||||
class HistoryWidget final : public Window::AbstractSectionWidget {
|
||||
class HistoryWidget final
|
||||
: public Window::AbstractSectionWidget
|
||||
, private HistoryView::CornerButtonsDelegate {
|
||||
public:
|
||||
using FieldHistoryAction = Ui::InputField::HistoryAction;
|
||||
using RecordLock = HistoryView::Controls::RecordLock;
|
||||
|
@ -193,11 +196,9 @@ public:
|
|||
void updateForwarding();
|
||||
void updateForwardingTexts();
|
||||
|
||||
void clearReplyReturns();
|
||||
void pushReplyReturn(not_null<HistoryItem*> item);
|
||||
QList<MsgId> replyReturns();
|
||||
void setReplyReturns(PeerId peer, const QList<MsgId> &replyReturns);
|
||||
void calcNextReplyReturn();
|
||||
[[nodiscard]] QVector<FullMsgId> replyReturns() const;
|
||||
void setReplyReturns(PeerId peer, QVector<FullMsgId> replyReturns);
|
||||
|
||||
void updatePreview();
|
||||
void previewCancel();
|
||||
|
@ -321,15 +322,15 @@ private:
|
|||
};
|
||||
using TextUpdateEvents = base::flags<TextUpdateEvent>;
|
||||
friend inline constexpr bool is_flag_type(TextUpdateEvent) { return true; };
|
||||
struct CornerButton {
|
||||
template <typename ...Args>
|
||||
CornerButton(Args &&...args) : widget(std::forward<Args>(args)...) {
|
||||
}
|
||||
|
||||
Ui::Animations::Simple animation;
|
||||
bool shown = false;
|
||||
object_ptr<Ui::HistoryDownButton> widget;
|
||||
};
|
||||
void cornerButtonsShowAtPosition(
|
||||
Data::MessagePosition position) override;
|
||||
Dialogs::Entry *cornerButtonsEntry() override;
|
||||
FullMsgId cornerButtonsCurrentId() override;
|
||||
bool cornerButtonsIgnoreVisibility() override;
|
||||
bool cornerButtonsDownShown() override;
|
||||
bool cornerButtonsUnreadMayBeShown() override;
|
||||
|
||||
void checkSuggestToGigagroup();
|
||||
|
||||
void initTabbedSelector();
|
||||
|
@ -380,9 +381,6 @@ private:
|
|||
void fullInfoUpdated();
|
||||
void toggleTabbedSelectorMode();
|
||||
void recountChatWidth();
|
||||
void historyDownClicked();
|
||||
void showNextUnreadMention();
|
||||
void showNextUnreadReaction();
|
||||
void handlePeerUpdate();
|
||||
void setMembersShowAreaActive(bool active);
|
||||
void handleHistoryChange(not_null<const History*> history);
|
||||
|
@ -410,16 +408,10 @@ private:
|
|||
void animationCallback();
|
||||
void updateOverStates(QPoint pos);
|
||||
void chooseAttach(std::optional<bool> overrideSendImagesAsPhotos = {});
|
||||
void cornerButtonsAnimationFinish();
|
||||
void sendButtonClicked();
|
||||
void newItemAdded(not_null<HistoryItem*> item);
|
||||
void maybeMarkReactionsRead(not_null<HistoryItem*> item);
|
||||
|
||||
void updateCornerButtonsPositions();
|
||||
void updateHistoryDownVisibility();
|
||||
void updateUnreadThingsVisibility();
|
||||
void updateCornerButtonVisibility(CornerButton &button, bool shown);
|
||||
|
||||
bool canSendFiles(not_null<const QMimeData*> data) const;
|
||||
bool confirmSendingFiles(
|
||||
const QStringList &files,
|
||||
|
@ -665,9 +657,6 @@ private:
|
|||
|
||||
bool _replyForwardPressed = false;
|
||||
|
||||
HistoryItem *_replyReturn = nullptr;
|
||||
QList<MsgId> _replyReturns;
|
||||
|
||||
PeerData *_peer = nullptr;
|
||||
|
||||
bool _canSendMessages = false;
|
||||
|
@ -701,9 +690,7 @@ private:
|
|||
bool _synteticScrollEvent = false;
|
||||
Ui::Animations::Simple _scrollToAnimation;
|
||||
|
||||
CornerButton _historyDown;
|
||||
CornerButton _unreadMentions;
|
||||
CornerButton _unreadReactions;
|
||||
HistoryView::CornerButtons _cornerButtons;
|
||||
|
||||
const object_ptr<FieldAutocomplete> _fieldAutocomplete;
|
||||
object_ptr<Support::Autocomplete> _supportAutocomplete;
|
||||
|
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "history/view/history_view_corner_buttons.h"
|
||||
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "base/qt/qt_key_modifiers.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/history_unread_things.h"
|
||||
#include "dialogs/dialogs_entry.h"
|
||||
#include "main/main_session.h"
|
||||
#include "menu/menu_send.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_unread_things.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_messages.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
namespace HistoryView {
|
||||
|
||||
CornerButtons::CornerButtons(
|
||||
not_null<Ui::ScrollArea*> parent,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
not_null<CornerButtonsDelegate*> delegate)
|
||||
: down(
|
||||
parent,
|
||||
st->value(parent->lifetime(), st::historyToDown))
|
||||
, mentions(
|
||||
parent,
|
||||
st->value(parent->lifetime(), st::historyUnreadMentions))
|
||||
, reactions(
|
||||
parent,
|
||||
st->value(parent->lifetime(), st::historyUnreadReactions))
|
||||
, _scroll(parent)
|
||||
, _delegate(delegate) {
|
||||
down.widget->addClickHandler([=] { downClick(); });
|
||||
mentions.widget->addClickHandler([=] { mentionsClick(); });
|
||||
reactions.widget->addClickHandler([=] { reactionsClick(); });
|
||||
|
||||
const auto filterScroll = [&](CornerButton &button) {
|
||||
button.widget->installEventFilter(this);
|
||||
};
|
||||
filterScroll(down);
|
||||
filterScroll(mentions);
|
||||
filterScroll(reactions);
|
||||
|
||||
SendMenu::SetupUnreadMentionsMenu(mentions.widget.data(), [=] {
|
||||
return _delegate->cornerButtonsEntry();
|
||||
});
|
||||
SendMenu::SetupUnreadReactionsMenu(reactions.widget.data(), [=] {
|
||||
return _delegate->cornerButtonsEntry();
|
||||
});
|
||||
}
|
||||
|
||||
bool CornerButtons::eventFilter(QObject *o, QEvent *e) {
|
||||
if (e->type() == QEvent::Wheel
|
||||
&& (o == down.widget
|
||||
|| o == mentions.widget
|
||||
|| o == reactions.widget)) {
|
||||
return _scroll->viewportEvent(e);
|
||||
}
|
||||
return QObject::eventFilter(o, e);
|
||||
}
|
||||
|
||||
void CornerButtons::downClick() {
|
||||
if (base::IsCtrlPressed() || !_replyReturn) {
|
||||
_delegate->cornerButtonsShowAtPosition(Data::UnreadMessagePosition);
|
||||
} else {
|
||||
_delegate->cornerButtonsShowAtPosition(_replyReturn->position());
|
||||
}
|
||||
}
|
||||
|
||||
void CornerButtons::mentionsClick() {
|
||||
const auto history = lookupHistory();
|
||||
if (!history) {
|
||||
return;
|
||||
}
|
||||
const auto entry = _delegate->cornerButtonsEntry();
|
||||
const auto msgId = entry->unreadMentions().minLoaded();
|
||||
const auto already = (_delegate->cornerButtonsCurrentId().msg == msgId);
|
||||
|
||||
// Mark mention voice/video message as read.
|
||||
// See https://github.com/telegramdesktop/tdesktop/issues/5623
|
||||
if (msgId && already) {
|
||||
if (const auto item = entry->owner().message(history->peer, msgId)) {
|
||||
if (const auto media = item->media()) {
|
||||
if (const auto document = media->document()) {
|
||||
if (!media->webpage()
|
||||
&& (document->isVoiceMessage()
|
||||
|| document->isVideoMessage())) {
|
||||
document->owner().markMediaRead(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
showAt(msgId);
|
||||
}
|
||||
|
||||
void CornerButtons::reactionsClick() {
|
||||
const auto history = lookupHistory();
|
||||
if (!history) {
|
||||
return;
|
||||
}
|
||||
const auto entry = _delegate->cornerButtonsEntry();
|
||||
showAt(entry->unreadReactions().minLoaded());
|
||||
}
|
||||
|
||||
void CornerButtons::clearReplyReturns() {
|
||||
_replyReturns.clear();
|
||||
_replyReturn = nullptr;
|
||||
}
|
||||
|
||||
QVector<FullMsgId> CornerButtons::replyReturns() const {
|
||||
return _replyReturns;
|
||||
}
|
||||
|
||||
void CornerButtons::setReplyReturns(QVector<FullMsgId> replyReturns) {
|
||||
_replyReturns = std::move(replyReturns);
|
||||
computeCurrentReplyReturn();
|
||||
if (!_replyReturn) {
|
||||
calculateNextReplyReturn();
|
||||
}
|
||||
}
|
||||
|
||||
void CornerButtons::computeCurrentReplyReturn() {
|
||||
const auto entry = _delegate->cornerButtonsEntry();
|
||||
_replyReturn = (!entry || _replyReturns.empty())
|
||||
? nullptr
|
||||
: entry->owner().message(_replyReturns.back());
|
||||
}
|
||||
|
||||
void CornerButtons::skipReplyReturn(FullMsgId id) {
|
||||
while (_replyReturn) {
|
||||
if (_replyReturn->fullId() == id) {
|
||||
calculateNextReplyReturn();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CornerButtons::calculateNextReplyReturn() {
|
||||
_replyReturn = nullptr;
|
||||
while (!_replyReturns.empty() && !_replyReturn) {
|
||||
_replyReturns.pop_back();
|
||||
computeCurrentReplyReturn();
|
||||
}
|
||||
if (!_replyReturn) {
|
||||
updateJumpDownVisibility();
|
||||
updateUnreadThingsVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void CornerButtons::pushReplyReturn(not_null<HistoryItem*> item) {
|
||||
_replyReturns.push_back(item->fullId());
|
||||
_replyReturn = item;
|
||||
}
|
||||
|
||||
CornerButton &CornerButtons::buttonByType(CornerButtonType type) {
|
||||
switch (type) {
|
||||
case CornerButtonType::Down: return down;
|
||||
case CornerButtonType::Mentions: return mentions;
|
||||
case CornerButtonType::Reactions: return reactions;
|
||||
}
|
||||
Unexpected("Type in CornerButtons::buttonByType.");
|
||||
}
|
||||
|
||||
History *CornerButtons::lookupHistory() const {
|
||||
const auto entry = _delegate->cornerButtonsEntry();
|
||||
if (!entry) {
|
||||
return nullptr;
|
||||
} else if (const auto history = entry->asHistory()) {
|
||||
return history;
|
||||
} else if (const auto topic = entry->asTopic()) {
|
||||
return topic->history();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CornerButtons::showAt(MsgId id) {
|
||||
if (const auto history = lookupHistory()) {
|
||||
if (const auto item = history->owner().message(history->peer, id)) {
|
||||
_delegate->cornerButtonsShowAtPosition(item->position());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CornerButtons::updateVisibility(
|
||||
CornerButtonType type,
|
||||
bool shown) {
|
||||
auto &button = buttonByType(type);
|
||||
if (button.shown != shown) {
|
||||
button.shown = shown;
|
||||
button.animation.start(
|
||||
[=] { updatePositions(); },
|
||||
shown ? 0. : 1.,
|
||||
shown ? 1. : 0.,
|
||||
st::historyToDownDuration);
|
||||
}
|
||||
}
|
||||
|
||||
void CornerButtons::updateUnreadThingsVisibility() {
|
||||
if (_delegate->cornerButtonsIgnoreVisibility()) {
|
||||
return;
|
||||
}
|
||||
const auto entry = _delegate->cornerButtonsEntry();
|
||||
if (!entry) {
|
||||
updateVisibility(CornerButtonType::Mentions, false);
|
||||
updateVisibility(CornerButtonType::Reactions, false);
|
||||
return;
|
||||
}
|
||||
auto &unreadThings = entry->session().api().unreadThings();
|
||||
unreadThings.preloadEnough(entry);
|
||||
|
||||
const auto updateWithCount = [&](CornerButtonType type, int count) {
|
||||
updateVisibility(
|
||||
type,
|
||||
(count > 0) && _delegate->cornerButtonsUnreadMayBeShown());
|
||||
};
|
||||
if (unreadThings.trackMentions(entry)) {
|
||||
if (const auto count = entry->unreadMentions().count(0)) {
|
||||
mentions.widget->setUnreadCount(count);
|
||||
}
|
||||
updateWithCount(
|
||||
CornerButtonType::Mentions,
|
||||
entry->unreadMentions().loadedCount());
|
||||
} else {
|
||||
updateVisibility(CornerButtonType::Mentions, false);
|
||||
}
|
||||
|
||||
if (unreadThings.trackReactions(entry)) {
|
||||
if (const auto count = entry->unreadReactions().count(0)) {
|
||||
reactions.widget->setUnreadCount(count);
|
||||
}
|
||||
updateWithCount(
|
||||
CornerButtonType::Reactions,
|
||||
entry->unreadReactions().loadedCount());
|
||||
} else {
|
||||
updateVisibility(CornerButtonType::Reactions, false);
|
||||
}
|
||||
}
|
||||
|
||||
void CornerButtons::updateJumpDownVisibility(std::optional<int> counter) {
|
||||
const auto shown = _delegate->cornerButtonsDownShown();
|
||||
updateVisibility(CornerButtonType::Down, shown);
|
||||
if (counter) {
|
||||
down.widget->setUnreadCount(*counter);
|
||||
}
|
||||
}
|
||||
|
||||
void CornerButtons::updatePositions() {
|
||||
const auto checkVisibility = [](CornerButton &button) {
|
||||
const auto shouldBeHidden = !button.shown
|
||||
&& !button.animation.animating();
|
||||
if (shouldBeHidden != button.widget->isHidden()) {
|
||||
button.widget->setVisible(!shouldBeHidden);
|
||||
}
|
||||
};
|
||||
const auto shown = [](CornerButton &button) {
|
||||
return button.animation.value(button.shown ? 1. : 0.);
|
||||
};
|
||||
|
||||
// All corner buttons is a child widgets of _scroll, not me.
|
||||
|
||||
const auto historyDownShown = shown(down);
|
||||
const auto unreadMentionsShown = shown(mentions);
|
||||
const auto unreadReactionsShown = shown(reactions);
|
||||
const auto skip = st::historyUnreadThingsSkip;
|
||||
{
|
||||
const auto top = anim::interpolate(
|
||||
0,
|
||||
down.widget->height() + st::historyToDownPosition.y(),
|
||||
historyDownShown);
|
||||
down.widget->moveToRight(
|
||||
st::historyToDownPosition.x(),
|
||||
_scroll->height() - top);
|
||||
}
|
||||
{
|
||||
const auto right = anim::interpolate(
|
||||
-mentions.widget->width(),
|
||||
st::historyToDownPosition.x(),
|
||||
unreadMentionsShown);
|
||||
const auto shift = anim::interpolate(
|
||||
0,
|
||||
down.widget->height() + skip,
|
||||
historyDownShown);
|
||||
const auto top = _scroll->height()
|
||||
- mentions.widget->height()
|
||||
- st::historyToDownPosition.y()
|
||||
- shift;
|
||||
mentions.widget->moveToRight(right, top);
|
||||
}
|
||||
{
|
||||
const auto right = anim::interpolate(
|
||||
-reactions.widget->width(),
|
||||
st::historyToDownPosition.x(),
|
||||
unreadReactionsShown);
|
||||
const auto shift = anim::interpolate(
|
||||
0,
|
||||
down.widget->height() + skip,
|
||||
historyDownShown
|
||||
) + anim::interpolate(
|
||||
0,
|
||||
mentions.widget->height() + skip,
|
||||
unreadMentionsShown);
|
||||
const auto top = _scroll->height()
|
||||
- reactions.widget->height()
|
||||
- st::historyToDownPosition.y()
|
||||
- shift;
|
||||
reactions.widget->moveToRight(right, top);
|
||||
}
|
||||
|
||||
checkVisibility(down);
|
||||
checkVisibility(mentions);
|
||||
checkVisibility(reactions);
|
||||
}
|
||||
|
||||
void CornerButtons::finishAnimations() {
|
||||
down.animation.stop();
|
||||
mentions.animation.stop();
|
||||
reactions.animation.stop();
|
||||
updatePositions();
|
||||
}
|
||||
|
||||
} // namespace HistoryView
|
110
Telegram/SourceFiles/history/view/history_view_corner_buttons.h
Normal file
110
Telegram/SourceFiles/history/view/history_view_corner_buttons.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/effects/animations.h"
|
||||
#include "base/object_ptr.h"
|
||||
|
||||
class History;
|
||||
class HistoryItem;
|
||||
struct FullMsgId;
|
||||
|
||||
namespace Ui {
|
||||
class ChatStyle;
|
||||
class ScrollArea;
|
||||
class HistoryDownButton;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Data {
|
||||
struct MessagePosition;
|
||||
} // namespace Data
|
||||
|
||||
namespace Dialogs {
|
||||
class Entry;
|
||||
} // namespace Dialogs
|
||||
|
||||
namespace HistoryView {
|
||||
|
||||
struct CornerButton {
|
||||
template <typename ...Args>
|
||||
CornerButton(Args &&...args) : widget(std::forward<Args>(args)...) {
|
||||
}
|
||||
|
||||
object_ptr<Ui::HistoryDownButton> widget;
|
||||
Ui::Animations::Simple animation;
|
||||
bool shown = false;
|
||||
};
|
||||
|
||||
enum class CornerButtonType {
|
||||
Down,
|
||||
Mentions,
|
||||
Reactions,
|
||||
};
|
||||
|
||||
class CornerButtonsDelegate {
|
||||
public:
|
||||
virtual void cornerButtonsShowAtPosition(
|
||||
Data::MessagePosition position) = 0;
|
||||
[[nodiscard]] virtual Dialogs::Entry *cornerButtonsEntry() = 0;
|
||||
[[nodiscard]] virtual FullMsgId cornerButtonsCurrentId() = 0;
|
||||
[[nodiscard]] virtual bool cornerButtonsIgnoreVisibility() = 0;
|
||||
[[nodiscard]] virtual bool cornerButtonsDownShown() = 0;
|
||||
[[nodiscard]] virtual bool cornerButtonsUnreadMayBeShown() = 0;
|
||||
};
|
||||
|
||||
class CornerButtons final : private QObject {
|
||||
public:
|
||||
CornerButtons(
|
||||
not_null<Ui::ScrollArea*> parent,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
not_null<CornerButtonsDelegate*> delegate);
|
||||
|
||||
void downClick();
|
||||
void mentionsClick();
|
||||
void reactionsClick();
|
||||
|
||||
void clearReplyReturns();
|
||||
[[nodiscard]] QVector<FullMsgId> replyReturns() const;
|
||||
void setReplyReturns(QVector<FullMsgId> replyReturns);
|
||||
void pushReplyReturn(not_null<HistoryItem*> item);
|
||||
void skipReplyReturn(FullMsgId id);
|
||||
void calculateNextReplyReturn();
|
||||
|
||||
void updateVisibility(CornerButtonType type, bool shown);
|
||||
void updateUnreadThingsVisibility();
|
||||
void updateJumpDownVisibility(std::optional<int> counter = {});
|
||||
void updatePositions();
|
||||
|
||||
void finishAnimations();
|
||||
|
||||
[[nodiscard]] HistoryItem *replyReturn() const {
|
||||
return _replyReturn;
|
||||
}
|
||||
|
||||
CornerButton down;
|
||||
CornerButton mentions;
|
||||
CornerButton reactions;
|
||||
|
||||
private:
|
||||
bool eventFilter(QObject *o, QEvent *e) override;
|
||||
|
||||
void computeCurrentReplyReturn();
|
||||
|
||||
[[nodiscard]] CornerButton &buttonByType(CornerButtonType type);
|
||||
[[nodiscard]] History *lookupHistory() const;
|
||||
void showAt(MsgId id);
|
||||
|
||||
const not_null<Ui::ScrollArea*> _scroll;
|
||||
const not_null<CornerButtonsDelegate*> _delegate;
|
||||
|
||||
HistoryItem *_replyReturn = nullptr;
|
||||
QVector<FullMsgId> _replyReturns;
|
||||
|
||||
};
|
||||
|
||||
} // namespace HistoryView
|
|
@ -158,7 +158,7 @@ public:
|
|||
StackItemHistory(
|
||||
not_null<History*> history,
|
||||
MsgId msgId,
|
||||
QList<MsgId> replyReturns)
|
||||
QVector<FullMsgId> replyReturns)
|
||||
: StackItem(history->peer)
|
||||
, history(history)
|
||||
, msgId(msgId)
|
||||
|
@ -171,7 +171,7 @@ public:
|
|||
|
||||
not_null<History*> history;
|
||||
MsgId msgId;
|
||||
QList<MsgId> replyReturns;
|
||||
QVector<FullMsgId> replyReturns;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1854,7 +1854,9 @@ void MainWidget::showBackFromStack(
|
|||
historyItem->peer()->id,
|
||||
params.withWay(SectionShow::Way::Backward),
|
||||
ShowAtUnreadMsgId);
|
||||
_history->setReplyReturns(historyItem->peer()->id, historyItem->replyReturns);
|
||||
_history->setReplyReturns(
|
||||
historyItem->peer()->id,
|
||||
std::move(historyItem->replyReturns));
|
||||
} else if (item->type() == SectionStackItem) {
|
||||
auto sectionItem = static_cast<StackItemSection*>(item.get());
|
||||
showNewSection(
|
||||
|
|
|
@ -152,27 +152,30 @@ void SetupMenuAndShortcuts(
|
|||
|
||||
void SetupReadAllMenu(
|
||||
not_null<Ui::RpWidget*> button,
|
||||
Fn<PeerData*()> currentPeer,
|
||||
Fn<Dialogs::Entry*()> currentEntry,
|
||||
const QString &text,
|
||||
Fn<void(not_null<PeerData*>, Fn<void()>)> sendReadRequest) {
|
||||
Fn<void(not_null<Dialogs::Entry*>, Fn<void()>)> sendReadRequest) {
|
||||
struct State {
|
||||
base::unique_qptr<Ui::PopupMenu> menu;
|
||||
base::flat_set<not_null<PeerData*>> sentForPeers;
|
||||
base::flat_set<base::weak_ptr<Dialogs::Entry>> sentForEntries;
|
||||
};
|
||||
const auto state = std::make_shared<State>();
|
||||
const auto showMenu = [=] {
|
||||
const auto peer = currentPeer();
|
||||
if (!peer) {
|
||||
const auto entry = base::make_weak(currentEntry());
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
state->menu = base::make_unique_q<Ui::PopupMenu>(
|
||||
button,
|
||||
st::popupMenuWithIcons);
|
||||
state->menu->addAction(text, [=] {
|
||||
if (!state->sentForPeers.emplace(peer).second) {
|
||||
const auto strong = entry.get();
|
||||
if (!strong || !state->sentForEntries.emplace(entry).second) {
|
||||
return;
|
||||
}
|
||||
sendReadRequest(peer, [=] { state->sentForPeers.remove(peer); });
|
||||
sendReadRequest(strong, [=] {
|
||||
state->sentForEntries.remove(entry);
|
||||
});
|
||||
}, &st::menuIconMarkRead);
|
||||
state->menu->popup(QCursor::pos());
|
||||
};
|
||||
|
@ -188,52 +191,88 @@ void SetupReadAllMenu(
|
|||
|
||||
void SetupUnreadMentionsMenu(
|
||||
not_null<Ui::RpWidget*> button,
|
||||
Fn<PeerData*()> currentPeer,
|
||||
MsgId topicRootId) {
|
||||
Fn<Dialogs::Entry*()> currentEntry) {
|
||||
const auto text = tr::lng_context_mark_read_mentions_all(tr::now);
|
||||
const auto sendRequest = [=](not_null<PeerData*> peer, Fn<void()> done) {
|
||||
const auto sendOne = [=](
|
||||
base::weak_ptr<Dialogs::Entry> weakEntry,
|
||||
Fn<void()> done,
|
||||
auto resend) -> void {
|
||||
const auto entry = weakEntry.get();
|
||||
if (!entry) {
|
||||
done();
|
||||
return;
|
||||
}
|
||||
const auto history = entry->asHistory();
|
||||
const auto topic = entry->asTopic();
|
||||
Assert(history || topic);
|
||||
const auto peer = (history ? history : topic->history().get())->peer;
|
||||
const auto rootId = topic ? topic->rootId() : 0;
|
||||
using Flag = MTPmessages_ReadMentions::Flag;
|
||||
peer->session().api().request(MTPmessages_ReadMentions(
|
||||
MTP_flags(topicRootId ? Flag::f_top_msg_id : Flag()),
|
||||
MTP_flags(rootId ? Flag::f_top_msg_id : Flag()),
|
||||
peer->input,
|
||||
MTP_int(topicRootId)
|
||||
MTP_int(rootId)
|
||||
)).done([=](const MTPmessages_AffectedHistory &result) {
|
||||
done();
|
||||
peer->session().api().applyAffectedHistory(peer, result);
|
||||
const auto forum = peer->forum();
|
||||
const auto history = peer->owner().history(peer);
|
||||
if (!topicRootId) {
|
||||
history->unreadMentions().clear();
|
||||
if (forum) {
|
||||
forum->clearAllUnreadMentions();
|
||||
}
|
||||
const auto offset = peer->session().api().applyAffectedHistory(
|
||||
peer,
|
||||
result);
|
||||
if (offset > 0) {
|
||||
resend(weakEntry, done, resend);
|
||||
} else {
|
||||
if (forum) {
|
||||
if (const auto topic = forum->topicFor(topicRootId)) {
|
||||
topic->unreadMentions().clear();
|
||||
}
|
||||
}
|
||||
history->clearUnreadMentionsFor(topicRootId);
|
||||
done();
|
||||
peer->owner().history(peer)->clearUnreadMentionsFor(rootId);
|
||||
}
|
||||
}).fail(done).send();
|
||||
};
|
||||
SetupReadAllMenu(button, currentPeer, text, sendRequest);
|
||||
const auto sendRequest = [=](
|
||||
not_null<Dialogs::Entry*> entry,
|
||||
Fn<void()> done) {
|
||||
sendOne(base::make_weak(entry.get()), std::move(done), sendOne);
|
||||
};
|
||||
SetupReadAllMenu(button, currentEntry, text, sendRequest);
|
||||
}
|
||||
|
||||
void SetupUnreadReactionsMenu(
|
||||
not_null<Ui::RpWidget*> button,
|
||||
Fn<PeerData*()> currentPeer) {
|
||||
Fn<Dialogs::Entry*()> currentEntry) {
|
||||
const auto text = tr::lng_context_mark_read_reactions_all(tr::now);
|
||||
const auto sendRequest = [=](not_null<PeerData*> peer, Fn<void()> done) {
|
||||
peer->session().api().request(MTPmessages_ReadReactions(
|
||||
peer->input
|
||||
)).done([=](const MTPmessages_AffectedHistory &result) {
|
||||
const auto sendOne = [=](
|
||||
base::weak_ptr<Dialogs::Entry> weakEntry,
|
||||
Fn<void()> done,
|
||||
auto resend) -> void {
|
||||
const auto entry = weakEntry.get();
|
||||
if (!entry) {
|
||||
done();
|
||||
peer->session().api().applyAffectedHistory(peer, result);
|
||||
peer->owner().history(peer)->unreadReactions().clear();
|
||||
return;
|
||||
}
|
||||
const auto history = entry->asHistory();
|
||||
const auto topic = entry->asTopic();
|
||||
Assert(history || topic);
|
||||
const auto peer = (history ? history : topic->history().get())->peer;
|
||||
const auto rootId = topic ? topic->rootId() : 0;
|
||||
using Flag = MTPmessages_ReadReactions::Flag;
|
||||
peer->session().api().request(MTPmessages_ReadReactions(
|
||||
MTP_flags(rootId ? Flag::f_top_msg_id : Flag(0)),
|
||||
peer->input,
|
||||
MTP_int(rootId)
|
||||
)).done([=](const MTPmessages_AffectedHistory &result) {
|
||||
const auto offset = peer->session().api().applyAffectedHistory(
|
||||
peer,
|
||||
result);
|
||||
if (offset > 0) {
|
||||
resend(weakEntry, done, resend);
|
||||
} else {
|
||||
done();
|
||||
peer->owner().history(peer)->clearUnreadReactionsFor(rootId);
|
||||
}
|
||||
}).fail(done).send();
|
||||
};
|
||||
SetupReadAllMenu(button, currentPeer, text, sendRequest);
|
||||
const auto sendRequest = [=](
|
||||
not_null<Dialogs::Entry*> entry,
|
||||
Fn<void()> done) {
|
||||
sendOne(base::make_weak(entry.get()), std::move(done), sendOne);
|
||||
};
|
||||
SetupReadAllMenu(button, currentEntry, text, sendRequest);
|
||||
}
|
||||
|
||||
} // namespace SendMenu
|
||||
|
|
|
@ -16,6 +16,10 @@ class PopupMenu;
|
|||
class RpWidget;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Dialogs {
|
||||
class Entry;
|
||||
} // namespace Dialogs
|
||||
|
||||
namespace SendMenu {
|
||||
|
||||
enum class Type {
|
||||
|
@ -51,11 +55,10 @@ void SetupMenuAndShortcuts(
|
|||
|
||||
void SetupUnreadMentionsMenu(
|
||||
not_null<Ui::RpWidget*> button,
|
||||
Fn<PeerData*()> currentPeer,
|
||||
MsgId topicRootId);
|
||||
Fn<Dialogs::Entry*()> currentEntry);
|
||||
|
||||
void SetupUnreadReactionsMenu(
|
||||
not_null<Ui::RpWidget*> button,
|
||||
Fn<PeerData*()> currentPeer);
|
||||
Fn<Dialogs::Entry*()> currentEntry);
|
||||
|
||||
} // namespace SendMenu
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1b524981f0caf2dc2f21c004694f63025fe96a71
|
||||
Subproject commit 44923c8b12bab26c707e8a7077ed82541a444f71
|
Loading…
Add table
Reference in a new issue