mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-25 15:03:03 +02:00
Show monoforums as forums in chats list.
This commit is contained in:
parent
5dc50b6d96
commit
358e64f2cc
22 changed files with 303 additions and 75 deletions
|
@ -247,7 +247,7 @@ void ChannelData::setFlags(ChannelDataFlags which) {
|
|||
if (const auto forum = this->forum()) {
|
||||
forum->preloadTopics();
|
||||
} else if (const auto monoforum = this->monoforum()) {
|
||||
monoforum->loadMore();
|
||||
monoforum->preloadSublists();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,7 +202,7 @@ void Forum::applyTopicDeleted(MsgId rootId) {
|
|||
}
|
||||
|
||||
void Forum::reorderLastTopics() {
|
||||
// We want first kShowChatNamesCount histories, by last message date.
|
||||
// We want first kShowTopicNamesCount histories, by last message date.
|
||||
const auto pred = [](not_null<ForumTopic*> a, not_null<ForumTopic*> b) {
|
||||
const auto aItem = a->chatListMessage();
|
||||
const auto bItem = b->chatListMessage();
|
||||
|
|
|
@ -60,14 +60,14 @@ MTPInputReplyTo ReplyToForMTP(
|
|||
&& (to->history() != history || to->id != replyingToTopicId))
|
||||
? to->topicRootId()
|
||||
: replyingToTopicId;
|
||||
const auto possibleMonoforumPeer = (to && to->savedSublistPeer())
|
||||
? to->savedSublistPeer()
|
||||
const auto possibleMonoforumPeerId = (to && to->sublistPeerId())
|
||||
? to->sublistPeerId()
|
||||
: replyTo.monoforumPeerId
|
||||
? history->owner().peer(replyTo.monoforumPeerId).get()
|
||||
: history->session().user().get();
|
||||
const auto replyToMonoforumPeer = history->peer->amMonoforumAdmin()
|
||||
? possibleMonoforumPeer
|
||||
: nullptr;
|
||||
? replyTo.monoforumPeerId
|
||||
: history->session().user()->id;
|
||||
const auto replyToMonoforumPeerId = history->peer->amMonoforumAdmin()
|
||||
? possibleMonoforumPeerId
|
||||
: PeerId();
|
||||
const auto external = replyTo.messageId
|
||||
&& (replyTo.messageId.peer != history->peer->id
|
||||
|| replyingToTopicId != replyToTopicId);
|
||||
|
@ -82,7 +82,9 @@ MTPInputReplyTo ReplyToForMTP(
|
|||
| (replyTo.quote.text.isEmpty()
|
||||
? Flag()
|
||||
: (Flag::f_quote_text | Flag::f_quote_offset))
|
||||
| (replyToMonoforumPeer ? Flag::f_monoforum_peer_id : Flag())
|
||||
| (replyToMonoforumPeerId
|
||||
? Flag::f_monoforum_peer_id
|
||||
: Flag())
|
||||
| (quoteEntities.v.isEmpty()
|
||||
? Flag()
|
||||
: Flag::f_quote_entities)),
|
||||
|
@ -94,8 +96,8 @@ MTPInputReplyTo ReplyToForMTP(
|
|||
MTP_string(replyTo.quote.text),
|
||||
quoteEntities,
|
||||
MTP_int(replyTo.quoteOffset),
|
||||
(replyToMonoforumPeer
|
||||
? replyToMonoforumPeer->input
|
||||
(replyToMonoforumPeerId
|
||||
? history->owner().peer(replyToMonoforumPeerId)->input
|
||||
: MTPInputPeer()));
|
||||
} else if (history->peer->amMonoforumAdmin()
|
||||
&& replyTo.monoforumPeerId) {
|
||||
|
|
|
@ -25,6 +25,7 @@ constexpr auto kFirstPerPage = 10;
|
|||
constexpr auto kListPerPage = 100;
|
||||
constexpr auto kListFirstPerPage = 20;
|
||||
constexpr auto kLoadedSublistsMinCount = 20;
|
||||
constexpr auto kShowSublistNamesCount = 5;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -33,13 +34,13 @@ SavedMessages::SavedMessages(
|
|||
ChannelData *parentChat)
|
||||
: _owner(owner)
|
||||
, _parentChat(parentChat)
|
||||
, _parentHistory(parentChat ? owner->history(parentChat).get() : nullptr)
|
||||
, _chatsList(
|
||||
&_owner->session(),
|
||||
FilterId(),
|
||||
_owner->maxPinnedChatsLimitValue(this))
|
||||
, _loadMore([=] { sendLoadMoreRequests(); }) {
|
||||
if (_parentChat
|
||||
&& _parentChat->owner().history(_parentChat)->inChatList()) {
|
||||
if (_parentHistory && _parentHistory->inChatList()) {
|
||||
preloadSublists();
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +129,7 @@ void SavedMessages::sendLoadMore() {
|
|||
if (_chatsList.loaded()) {
|
||||
_chatsListLoadedEvents.fire({});
|
||||
}
|
||||
reorderLastSublists();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
if (error.type() == u"SAVED_DIALOGS_UNSUPPORTED"_q) {
|
||||
_unsupported = true;
|
||||
|
@ -366,6 +368,75 @@ void SavedMessages::apply(const MTPDupdateSavedDialogPinned &update) {
|
|||
});
|
||||
}
|
||||
|
||||
void SavedMessages::reorderLastSublists() {
|
||||
if (!_parentHistory) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We want first kShowChatNamesCount histories, by last message date.
|
||||
const auto pred = [](
|
||||
not_null<SavedSublist*> a,
|
||||
not_null<SavedSublist*> b) {
|
||||
const auto aItem = a->chatListMessage();
|
||||
const auto bItem = b->chatListMessage();
|
||||
const auto aDate = aItem ? aItem->date() : TimeId(0);
|
||||
const auto bDate = bItem ? bItem->date() : TimeId(0);
|
||||
return aDate > bDate;
|
||||
};
|
||||
_lastSublists.clear();
|
||||
_lastSublists.reserve(kShowSublistNamesCount + 1);
|
||||
auto &&sublists = ranges::views::all(
|
||||
*_chatsList.indexed()
|
||||
) | ranges::views::transform([](not_null<Dialogs::Row*> row) {
|
||||
return row->sublist();
|
||||
});
|
||||
auto nonPinnedChecked = 0;
|
||||
for (const auto sublist : sublists) {
|
||||
const auto i = ranges::upper_bound(
|
||||
_lastSublists,
|
||||
not_null(sublist),
|
||||
pred);
|
||||
if (size(_lastSublists) < kShowSublistNamesCount
|
||||
|| i != end(_lastSublists)) {
|
||||
_lastSublists.insert(i, sublist);
|
||||
}
|
||||
if (size(_lastSublists) > kShowSublistNamesCount) {
|
||||
_lastSublists.pop_back();
|
||||
}
|
||||
if (!sublist->isPinnedDialog(FilterId())
|
||||
&& ++nonPinnedChecked >= kShowSublistNamesCount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
++_lastSublistsVersion;
|
||||
_parentHistory->updateChatListEntry();
|
||||
}
|
||||
|
||||
void SavedMessages::listMessageChanged(HistoryItem *from, HistoryItem *to) {
|
||||
if (from || to) {
|
||||
reorderLastSublists();
|
||||
}
|
||||
}
|
||||
|
||||
int SavedMessages::recentSublistsListVersion() const {
|
||||
return _lastSublistsVersion;
|
||||
}
|
||||
|
||||
void SavedMessages::recentSublistsInvalidate(
|
||||
not_null<SavedSublist*> sublist) {
|
||||
Expects(_parentHistory != nullptr);
|
||||
|
||||
if (ranges::contains(_lastSublists, sublist)) {
|
||||
++_lastSublistsVersion;
|
||||
_parentHistory->updateChatListEntry();
|
||||
}
|
||||
}
|
||||
|
||||
auto SavedMessages::recentSublists() const
|
||||
-> const std::vector<not_null<SavedSublist*>> & {
|
||||
return _lastSublists;
|
||||
}
|
||||
|
||||
rpl::producer<> SavedMessages::destroyed() const {
|
||||
if (!_parentChat) {
|
||||
return rpl::never<>();
|
||||
|
|
|
@ -49,18 +49,27 @@ public:
|
|||
void apply(const MTPDupdatePinnedSavedDialogs &update);
|
||||
void apply(const MTPDupdateSavedDialogPinned &update);
|
||||
|
||||
void listMessageChanged(HistoryItem *from, HistoryItem *to);
|
||||
[[nodiscard]] int recentSublistsListVersion() const;
|
||||
void recentSublistsInvalidate(not_null<SavedSublist*> sublist);
|
||||
[[nodiscard]] auto recentSublists() const
|
||||
-> const std::vector<not_null<SavedSublist*>> &;
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
||||
private:
|
||||
void loadPinned();
|
||||
void apply(const MTPmessages_SavedDialogs &result, bool pinned);
|
||||
|
||||
void reorderLastSublists();
|
||||
|
||||
void sendLoadMore();
|
||||
void sendLoadMore(not_null<SavedSublist*> sublist);
|
||||
void sendLoadMoreRequests();
|
||||
|
||||
const not_null<Session*> _owner;
|
||||
ChannelData *_parentChat = nullptr;
|
||||
History *_parentHistory = nullptr;
|
||||
|
||||
rpl::event_stream<not_null<SavedSublist*>> _sublistDestroyed;
|
||||
|
||||
|
@ -81,6 +90,9 @@ private:
|
|||
base::flat_set<not_null<SavedSublist*>> _loadMoreSublistsScheduled;
|
||||
bool _loadMoreScheduled = false;
|
||||
|
||||
std::vector<not_null<SavedSublist*>> _lastSublists;
|
||||
int _lastSublistsVersion = 0;
|
||||
|
||||
rpl::event_stream<> _chatsListChanges;
|
||||
rpl::event_stream<> _chatsListLoadedEvents;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_saved_sublist.h"
|
||||
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_saved_messages.h"
|
||||
|
@ -80,6 +81,7 @@ void SavedSublist::applyMaybeLast(not_null<HistoryItem*> item, bool added) {
|
|||
: (IsServerMsgId(b->id) ? false : (a->id < b->id));
|
||||
};
|
||||
|
||||
const auto was = _items.empty() ? nullptr : _items.front().get();
|
||||
if (_items.empty()) {
|
||||
_items.push_back(item);
|
||||
} else if (_items.front() == item) {
|
||||
|
@ -104,6 +106,8 @@ void SavedSublist::applyMaybeLast(not_null<HistoryItem*> item, bool added) {
|
|||
if (_items.front() == item) {
|
||||
setChatListTimeId(item->date());
|
||||
resolveChatListMessageGroup();
|
||||
|
||||
_parent->listMessageChanged(was, item.get());
|
||||
}
|
||||
_changed.fire({});
|
||||
}
|
||||
|
@ -132,6 +136,8 @@ void SavedSublist::removeOne(not_null<HistoryItem*> item) {
|
|||
} else {
|
||||
setChatListTimeId(_items.front()->date());
|
||||
}
|
||||
|
||||
_parent->listMessageChanged(item.get(), chatListMessage());
|
||||
}
|
||||
if (removed || _fullCount) {
|
||||
_changed.fire({});
|
||||
|
@ -195,6 +201,11 @@ int SavedSublist::fixedOnTopIndex() const {
|
|||
}
|
||||
|
||||
bool SavedSublist::shouldBeInChatList() const {
|
||||
if (const auto monoforum = _parent->parentChat()) {
|
||||
if (monoforum == sublistPeer()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return isPinnedDialog(FilterId()) || !_items.empty();
|
||||
}
|
||||
|
||||
|
|
|
@ -229,6 +229,13 @@ uint64 Entry::computeSortPosition(FilterId filterId) const {
|
|||
}
|
||||
|
||||
void Entry::updateChatListExistence() {
|
||||
if (const auto history = asHistory()) {
|
||||
if (const auto channel = history->peer->asMonoforum()) {
|
||||
if (!folderKnown()) {
|
||||
history->clearFolder();
|
||||
}
|
||||
}
|
||||
}
|
||||
setChatListExistence(shouldBeInChatList());
|
||||
}
|
||||
|
||||
|
|
|
@ -892,10 +892,11 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
const auto active = mayBeActive && isRowActive(row, activeEntry);
|
||||
const auto history = key.history();
|
||||
const auto forum = history && history->isForum();
|
||||
if (forum && !_topicJumpCache) {
|
||||
const auto monoforum = history && history->amMonoforumAdmin();
|
||||
if ((forum || monoforum) && !_topicJumpCache) {
|
||||
_topicJumpCache = std::make_unique<Ui::TopicJumpCache>();
|
||||
}
|
||||
const auto expanding = forum
|
||||
const auto expanding = (forum || monoforum)
|
||||
&& (history->peer->id == childListShown.peerId);
|
||||
context.rightButton = maybeCacheRightButton(row);
|
||||
if (history) {
|
||||
|
@ -921,14 +922,14 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
context.st = (forum ? &st::forumDialogRow : _st.get());
|
||||
context.st = (forum || monoforum) ? &st::forumDialogRow : _st.get();
|
||||
|
||||
auto chatsFilterTags = std::vector<QImage*>();
|
||||
if (context.narrow) {
|
||||
context.chatsFilterTags = nullptr;
|
||||
} else if (row->entry()->hasChatsFilterTags(context.filter)) {
|
||||
const auto a = active;
|
||||
context.st = forum
|
||||
context.st = (forum || monoforum)
|
||||
? &st::taggedForumDialogRow
|
||||
: &st::taggedDialogRow;
|
||||
auto availableWidth = context.width
|
||||
|
|
|
@ -320,7 +320,7 @@ Row::~Row() {
|
|||
void Row::recountHeight(float64 narrowRatio, FilterId filterId) {
|
||||
if (const auto history = _id.history()) {
|
||||
const auto hasTags = _id.entry()->hasChatsFilterTags(filterId);
|
||||
_height = history->isForum()
|
||||
_height = (history->isForum() || history->amMonoforumAdmin())
|
||||
? anim::interpolate(
|
||||
hasTags
|
||||
? st::taggedForumDialogRow.height
|
||||
|
@ -466,7 +466,7 @@ void Row::PaintCornerBadgeFrame(
|
|||
for (auto i = 0; i != storiesUnreadCount; ++i) {
|
||||
segments.push_back({ storiesUnreadBrush, storiesUnread });
|
||||
}
|
||||
if (peer && peer->forum()) {
|
||||
if (peer && (peer->forum() || peer->monoforum())) {
|
||||
const auto radius = context.st->photoSize
|
||||
* Ui::ForumUserpicRadiusMultiplier();
|
||||
Ui::PaintOutlineSegments(q, outline, radius, segments);
|
||||
|
|
|
@ -67,7 +67,7 @@ const auto kPsaBadgePrefix = "cloud_lng_badge_psa_";
|
|||
} else if (const auto user = history->peer->asUser()) {
|
||||
return !user->lastseen().isHidden();
|
||||
}
|
||||
return !history->isForum();
|
||||
return !history->isForum() && !history->amMonoforumAdmin();
|
||||
}
|
||||
|
||||
void PaintRowTopRight(
|
||||
|
@ -1046,21 +1046,23 @@ void RowPainter::Paint(
|
|||
? nullptr
|
||||
: thread
|
||||
? &thread->lastItemDialogsView()
|
||||
: sublist
|
||||
? &sublist->lastItemDialogsView()
|
||||
: nullptr;
|
||||
if (view) {
|
||||
const auto forum = context.st->topicsHeight
|
||||
? row->history()->peer->forum()
|
||||
const auto forum = (peer && context.st->topicsHeight)
|
||||
? peer->forum()
|
||||
: nullptr;
|
||||
if (!view->prepared(item, forum)) {
|
||||
const auto monoforum = (peer && context.st->topicsHeight)
|
||||
? peer->monoforum()
|
||||
: nullptr;
|
||||
if (!view->prepared(item, forum, monoforum)) {
|
||||
view->prepare(
|
||||
item,
|
||||
forum,
|
||||
monoforum,
|
||||
[=] { entry->updateChatListEntry(); },
|
||||
{});
|
||||
}
|
||||
if (forum) {
|
||||
if (forum || monoforum) {
|
||||
rect.setHeight(context.st->topicsHeight + rect.height());
|
||||
}
|
||||
view->paint(p, rect, context);
|
||||
|
@ -1154,8 +1156,13 @@ void RowPainter::Paint(
|
|||
availableWidth,
|
||||
st::dialogsTextFont->height);
|
||||
auto &view = row->itemView();
|
||||
if (!view.prepared(item, nullptr)) {
|
||||
view.prepare(item, nullptr, row->repaint(), previewOptions);
|
||||
if (!view.prepared(item, nullptr, nullptr)) {
|
||||
view.prepare(
|
||||
item,
|
||||
nullptr,
|
||||
nullptr,
|
||||
row->repaint(),
|
||||
previewOptions);
|
||||
}
|
||||
view.paint(p, itemRect, context);
|
||||
};
|
||||
|
|
|
@ -138,26 +138,39 @@ bool MessageView::dependsOn(not_null<const HistoryItem*> item) const {
|
|||
|
||||
bool MessageView::prepared(
|
||||
not_null<const HistoryItem*> item,
|
||||
Data::Forum *forum) const {
|
||||
Data::Forum *forum,
|
||||
Data::SavedMessages *monoforum) const {
|
||||
return (_textCachedFor == item.get())
|
||||
&& (!forum
|
||||
&& ((!forum && !monoforum)
|
||||
|| (_topics
|
||||
&& _topics->forum() == forum
|
||||
&& _topics->monoforum() == monoforum
|
||||
&& _topics->prepared()));
|
||||
}
|
||||
|
||||
void MessageView::prepare(
|
||||
not_null<const HistoryItem*> item,
|
||||
Data::Forum *forum,
|
||||
Data::SavedMessages *monoforum,
|
||||
Fn<void()> customEmojiRepaint,
|
||||
ToPreviewOptions options) {
|
||||
if (!forum) {
|
||||
if (!forum && !monoforum) {
|
||||
_topics = nullptr;
|
||||
} else if (!_topics || _topics->forum() != forum) {
|
||||
_topics = std::make_unique<TopicsView>(forum);
|
||||
_topics->prepare(item->topicRootId(), customEmojiRepaint);
|
||||
} else if (!_topics
|
||||
|| _topics->forum() != forum
|
||||
|| _topics->monoforum() != monoforum) {
|
||||
_topics = std::make_unique<TopicsView>(forum, monoforum);
|
||||
if (forum) {
|
||||
_topics->prepare(item->topicRootId(), customEmojiRepaint);
|
||||
} else {
|
||||
_topics->prepare(item->sublistPeerId(), customEmojiRepaint);
|
||||
}
|
||||
} else if (!_topics->prepared()) {
|
||||
_topics->prepare(item->topicRootId(), customEmojiRepaint);
|
||||
if (forum) {
|
||||
_topics->prepare(item->topicRootId(), customEmojiRepaint);
|
||||
} else {
|
||||
_topics->prepare(item->sublistPeerId(), customEmojiRepaint);
|
||||
}
|
||||
}
|
||||
if (_textCachedFor == item.get()) {
|
||||
return;
|
||||
|
|
|
@ -24,6 +24,7 @@ class SpoilerAnimation;
|
|||
|
||||
namespace Data {
|
||||
class Forum;
|
||||
class SavedMessages;
|
||||
} // namespace Data
|
||||
|
||||
namespace HistoryView {
|
||||
|
@ -56,10 +57,12 @@ public:
|
|||
|
||||
[[nodiscard]] bool prepared(
|
||||
not_null<const HistoryItem*> item,
|
||||
Data::Forum *forum) const;
|
||||
Data::Forum *forum,
|
||||
Data::SavedMessages *monoforum) const;
|
||||
void prepare(
|
||||
not_null<const HistoryItem*> item,
|
||||
Data::Forum *forum,
|
||||
Data::SavedMessages *monoforum,
|
||||
Fn<void()> customEmojiRepaint,
|
||||
ToPreviewOptions options);
|
||||
|
||||
|
|
|
@ -8,10 +8,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "dialogs/ui/dialogs_topics_view.h"
|
||||
|
||||
#include "dialogs/ui/dialogs_layout.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "data/data_forum.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_saved_messages.h"
|
||||
#include "data/data_saved_sublist.h"
|
||||
#include "data/data_session.h"
|
||||
#include "core/ui_integration.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/power_saving.h"
|
||||
#include "ui/text/text_options.h"
|
||||
|
@ -26,29 +32,35 @@ constexpr auto kIconLoopCount = 1;
|
|||
|
||||
} // namespace
|
||||
|
||||
TopicsView::TopicsView(not_null<Data::Forum*> forum)
|
||||
: _forum(forum) {
|
||||
TopicsView::TopicsView(Data::Forum *forum, Data::SavedMessages *monoforum)
|
||||
: _forum(forum)
|
||||
, _monoforum(monoforum) {
|
||||
}
|
||||
|
||||
TopicsView::~TopicsView() = default;
|
||||
|
||||
bool TopicsView::prepared() const {
|
||||
return (_version == _forum->recentTopicsListVersion());
|
||||
const auto version = _forum
|
||||
? _forum->recentTopicsListVersion()
|
||||
: _monoforum->recentSublistsListVersion();
|
||||
return (_version == version);
|
||||
}
|
||||
|
||||
void TopicsView::prepare(MsgId frontRootId, Fn<void()> customEmojiRepaint) {
|
||||
Expects(_forum != nullptr);
|
||||
|
||||
const auto &list = _forum->recentTopics();
|
||||
_version = _forum->recentTopicsListVersion();
|
||||
_titles.reserve(list.size());
|
||||
auto index = 0;
|
||||
for (const auto &topic : list) {
|
||||
const auto from = begin(_titles) + index;
|
||||
const auto rootId = topic->rootId();
|
||||
const auto key = topic->rootId().bare;
|
||||
const auto i = ranges::find(
|
||||
from,
|
||||
end(_titles),
|
||||
rootId,
|
||||
&Title::topicRootId);
|
||||
key,
|
||||
&Title::key);
|
||||
if (i != end(_titles)) {
|
||||
if (i != from) {
|
||||
ranges::rotate(from, i, i + 1);
|
||||
|
@ -58,7 +70,7 @@ void TopicsView::prepare(MsgId frontRootId, Fn<void()> customEmojiRepaint) {
|
|||
}
|
||||
auto &title = _titles[index++];
|
||||
const auto unread = topic->chatListBadgesState().unread;
|
||||
if (title.topicRootId == rootId
|
||||
if (title.key == key
|
||||
&& title.unread == unread
|
||||
&& title.version == topic->titleVersion()) {
|
||||
continue;
|
||||
|
@ -69,7 +81,7 @@ void TopicsView::prepare(MsgId frontRootId, Fn<void()> customEmojiRepaint) {
|
|||
.customEmojiLoopLimit = kIconLoopCount,
|
||||
});
|
||||
auto topicTitle = topic->titleWithIcon();
|
||||
title.topicRootId = rootId;
|
||||
title.key = key;
|
||||
title.version = topic->titleVersion();
|
||||
title.unread = unread;
|
||||
title.title.setMarkedText(
|
||||
|
@ -87,7 +99,79 @@ void TopicsView::prepare(MsgId frontRootId, Fn<void()> customEmojiRepaint) {
|
|||
_titles.pop_back();
|
||||
}
|
||||
const auto i = frontRootId
|
||||
? ranges::find(_titles, frontRootId, &Title::topicRootId)
|
||||
? ranges::find(_titles, frontRootId.bare, &Title::key)
|
||||
: end(_titles);
|
||||
_jumpToTopic = (i != end(_titles));
|
||||
if (_jumpToTopic) {
|
||||
if (i != begin(_titles)) {
|
||||
ranges::rotate(begin(_titles), i, i + 1);
|
||||
}
|
||||
if (!_titles.front().unread) {
|
||||
_jumpToTopic = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TopicsView::prepare(PeerId frontPeerId, Fn<void()> customEmojiRepaint) {
|
||||
Expects(_monoforum != nullptr);
|
||||
|
||||
const auto &list = _monoforum->recentSublists();
|
||||
const auto manager = &_monoforum->session().data().customEmojiManager();
|
||||
_version = _monoforum->recentSublistsListVersion();
|
||||
_titles.reserve(list.size());
|
||||
auto index = 0;
|
||||
for (const auto &sublist : list) {
|
||||
const auto from = begin(_titles) + index;
|
||||
const auto peer = sublist->sublistPeer();
|
||||
const auto key = peer->id.value;
|
||||
const auto i = ranges::find(
|
||||
from,
|
||||
end(_titles),
|
||||
key,
|
||||
&Title::key);
|
||||
if (i != end(_titles)) {
|
||||
if (i != from) {
|
||||
ranges::rotate(from, i, i + 1);
|
||||
}
|
||||
} else if (index >= _titles.size()) {
|
||||
_titles.emplace_back();
|
||||
}
|
||||
auto &title = _titles[index++];
|
||||
const auto unread = sublist->chatListBadgesState().unread;
|
||||
if (title.key == key
|
||||
&& title.unread == unread
|
||||
&& title.version == peer->nameVersion()) {
|
||||
continue;
|
||||
}
|
||||
const auto context = Core::TextContext({
|
||||
.session = &sublist->session(),
|
||||
.repaint = customEmojiRepaint,
|
||||
.customEmojiLoopLimit = kIconLoopCount,
|
||||
});
|
||||
auto topicTitle = TextWithEntities().append(
|
||||
Ui::Text::SingleCustomEmoji(
|
||||
manager->peerUserpicEmojiData(peer),
|
||||
u"@"_q)
|
||||
).append(peer->shortName());
|
||||
title.key = key;
|
||||
title.version = peer->nameVersion();
|
||||
title.unread = unread;
|
||||
title.title.setMarkedText(
|
||||
st::dialogsTextStyle,
|
||||
(unread
|
||||
? Ui::Text::Colorized(
|
||||
Ui::Text::Wrapped(
|
||||
std::move(topicTitle),
|
||||
EntityType::Bold))
|
||||
: std::move(topicTitle)),
|
||||
DialogTextOptions(),
|
||||
context);
|
||||
}
|
||||
while (_titles.size() > index) {
|
||||
_titles.pop_back();
|
||||
}
|
||||
const auto i = frontPeerId
|
||||
? ranges::find(_titles, frontPeerId.value, &Title::key)
|
||||
: end(_titles);
|
||||
_jumpToTopic = (i != end(_titles));
|
||||
if (_jumpToTopic) {
|
||||
|
|
|
@ -16,6 +16,8 @@ struct DialogRow;
|
|||
namespace Data {
|
||||
class Forum;
|
||||
class ForumTopic;
|
||||
class SavedMessages;
|
||||
class SavedSublist;
|
||||
} // namespace Data
|
||||
|
||||
namespace Ui {
|
||||
|
@ -59,15 +61,19 @@ void FillJumpToLastPrepared(QPainter &p, JumpToLastPrepared context);
|
|||
|
||||
class TopicsView final {
|
||||
public:
|
||||
explicit TopicsView(not_null<Data::Forum*> forum);
|
||||
TopicsView(Data::Forum *forum, Data::SavedMessages *monoforum);
|
||||
~TopicsView();
|
||||
|
||||
[[nodiscard]] not_null<Data::Forum*> forum() const {
|
||||
[[nodiscard]] Data::Forum *forum() const {
|
||||
return _forum;
|
||||
}
|
||||
[[nodiscard]] Data::SavedMessages *monoforum() const {
|
||||
return _monoforum;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool prepared() const;
|
||||
void prepare(MsgId frontRootId, Fn<void()> customEmojiRepaint);
|
||||
void prepare(PeerId frontPeerId, Fn<void()> customEmojiRepaint);
|
||||
|
||||
[[nodiscard]] int jumpToTopicWidth() const;
|
||||
|
||||
|
@ -99,7 +105,7 @@ public:
|
|||
private:
|
||||
struct Title {
|
||||
Text::String title;
|
||||
MsgId topicRootId = 0;
|
||||
uint64 key = 0;
|
||||
int version = -1;
|
||||
bool unread = false;
|
||||
};
|
||||
|
@ -107,7 +113,8 @@ private:
|
|||
[[nodiscard]] QImage topicJumpRippleMask(
|
||||
not_null<TopicJumpCache*> topicJumpCache) const;
|
||||
|
||||
const not_null<Data::Forum*> _forum;
|
||||
Data::Forum * const _forum = nullptr;
|
||||
Data::SavedMessages * const _monoforum = nullptr;
|
||||
|
||||
mutable std::vector<Title> _titles;
|
||||
mutable std::unique_ptr<RippleAnimation> _ripple;
|
||||
|
|
|
@ -3149,11 +3149,11 @@ void History::monoforumChanged(Data::SavedMessages *old) {
|
|||
}
|
||||
|
||||
if (const auto monoforum = peer->monoforum()) {
|
||||
_flags |= Flag::IsMonoforum;
|
||||
_flags |= Flag::IsMonoforumAdmin;
|
||||
|
||||
monoforum->chatsList()->unreadStateChanges(
|
||||
) | rpl::filter([=] {
|
||||
return (_flags & Flag::IsMonoforum) && inChatList();
|
||||
return (_flags & Flag::IsMonoforumAdmin) && inChatList();
|
||||
}) | rpl::map(
|
||||
AdjustedForumUnreadState
|
||||
) | rpl::start_with_next([=](const Dialogs::UnreadState &old) {
|
||||
|
@ -3165,7 +3165,7 @@ void History::monoforumChanged(Data::SavedMessages *old) {
|
|||
updateChatListEntry();
|
||||
}, monoforum->lifetime());
|
||||
} else {
|
||||
_flags &= ~Flag::IsMonoforum;
|
||||
_flags &= ~Flag::IsMonoforumAdmin;
|
||||
}
|
||||
if (cloudDraft(MsgId(0))) {
|
||||
updateChatListSortPosition();
|
||||
|
@ -3173,8 +3173,8 @@ void History::monoforumChanged(Data::SavedMessages *old) {
|
|||
_flags |= Flag::PendingAllItemsResize;
|
||||
}
|
||||
|
||||
bool History::isMonoforum() const {
|
||||
return (_flags & Flag::IsMonoforum);
|
||||
bool History::amMonoforumAdmin() const {
|
||||
return (_flags & Flag::IsMonoforumAdmin);
|
||||
}
|
||||
|
||||
not_null<History*> History::migrateToOrMe() const {
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
[[nodiscard]] bool isForum() const;
|
||||
|
||||
void monoforumChanged(Data::SavedMessages *old);
|
||||
[[nodiscard]] bool isMonoforum() const;
|
||||
[[nodiscard]] bool amMonoforumAdmin() const;
|
||||
|
||||
[[nodiscard]] not_null<History*> migrateToOrMe() const;
|
||||
[[nodiscard]] History *migrateFrom() const;
|
||||
|
@ -435,7 +435,7 @@ private:
|
|||
PendingAllItemsResize = (1 << 1),
|
||||
IsTopPromoted = (1 << 2),
|
||||
IsForum = (1 << 3),
|
||||
IsMonoforum = (1 << 4),
|
||||
IsMonoforumAdmin = (1 << 4),
|
||||
FakeUnreadWhileOpened = (1 << 5),
|
||||
HasPinnedMessages = (1 << 6),
|
||||
ResolveChatListMessage = (1 << 7),
|
||||
|
|
|
@ -3443,12 +3443,12 @@ FullStoryId HistoryItem::replyToStory() const {
|
|||
}
|
||||
|
||||
FullReplyTo HistoryItem::replyTo() const {
|
||||
const auto monoforumPeer = _history->peer->amMonoforumAdmin()
|
||||
? savedSublistPeer()
|
||||
: nullptr;
|
||||
const auto monoforumPeerId = _history->peer->amMonoforumAdmin()
|
||||
? sublistPeerId()
|
||||
: PeerId();
|
||||
auto result = FullReplyTo{
|
||||
.topicRootId = topicRootId(),
|
||||
.monoforumPeerId = monoforumPeer ? monoforumPeer->id : PeerId(),
|
||||
.monoforumPeerId = monoforumPeerId,
|
||||
};
|
||||
if (const auto reply = Get<HistoryMessageReply>()) {
|
||||
const auto &fields = reply->fields();
|
||||
|
@ -3592,11 +3592,15 @@ Data::SavedSublist *HistoryItem::savedSublist() const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
PeerData *HistoryItem::savedSublistPeer() const {
|
||||
if (const auto sublist = savedSublist()) {
|
||||
return sublist->sublistPeer();
|
||||
PeerId HistoryItem::sublistPeerId() const {
|
||||
if (const auto saved = Get<HistoryMessageSaved>()) {
|
||||
return saved->sublistPeerId;
|
||||
} else if (_history->peer->isSelf()) {
|
||||
return _history->peer->id;
|
||||
} else if (_history->peer->monoforum()) {
|
||||
return _from->id;
|
||||
}
|
||||
return nullptr;
|
||||
return PeerId();
|
||||
}
|
||||
|
||||
PeerData *HistoryItem::savedFromSender() const {
|
||||
|
@ -4046,8 +4050,8 @@ void HistoryItem::createComponentsHelper(HistoryItemCommonFields &&fields) {
|
|||
? replyTo.messageId.peer
|
||||
: PeerId();
|
||||
const auto to = LookupReplyTo(_history, replyTo.messageId);
|
||||
config.reply.monoforumPeerId = (to && to->savedSublistPeer())
|
||||
? to->savedSublistPeer()->id
|
||||
config.reply.monoforumPeerId = (to && to->sublistPeerId())
|
||||
? to->sublistPeerId()
|
||||
: replyTo.monoforumPeerId
|
||||
? replyTo.monoforumPeerId
|
||||
: PeerId();
|
||||
|
|
|
@ -491,7 +491,7 @@ public:
|
|||
[[nodiscard]] MsgId originalId() const;
|
||||
|
||||
[[nodiscard]] Data::SavedSublist *savedSublist() const;
|
||||
[[nodiscard]] PeerData *savedSublistPeer() const;
|
||||
[[nodiscard]] PeerId sublistPeerId() const;
|
||||
[[nodiscard]] PeerData *savedFromSender() const;
|
||||
[[nodiscard]] const HiddenSenderInfo *savedFromHiddenSenderInfo() const;
|
||||
|
||||
|
|
|
@ -1699,10 +1699,10 @@ FullReplyTo ChatWidget::replyTo() const {
|
|||
const auto item = custom.messageId
|
||||
? session().data().message(custom.messageId)
|
||||
: nullptr;
|
||||
const auto sublistPeer = item ? item->savedSublistPeer() : nullptr;
|
||||
const auto sublistPeerId = item ? item->sublistPeerId() : PeerId();
|
||||
if (!item
|
||||
|| !monoforumPeerId
|
||||
|| (sublistPeer && sublistPeer->id == monoforumPeerId)) {
|
||||
|| (sublistPeerId == monoforumPeerId)) {
|
||||
// Never answer to a message in a wrong monoforum peer id.
|
||||
custom.topicRootId = _repliesRootId;
|
||||
custom.monoforumPeerId = monoforumPeerId;
|
||||
|
|
|
@ -1487,7 +1487,7 @@ void Element::recountMonoforumSenderBarInBlocks() {
|
|||
}
|
||||
}
|
||||
}
|
||||
return sublistPeer;
|
||||
return (sublistPeer == parentChat) ? nullptr : sublistPeer.get();
|
||||
}();
|
||||
if (barPeer && !Has<MonoforumSenderBar>()) {
|
||||
AddComponents(MonoforumSenderBar::Bit());
|
||||
|
|
|
@ -773,7 +773,7 @@ void TopBarWidget::backClicked() {
|
|||
_controller->closeForum();
|
||||
} else if (_activeChat.section == Section::ChatsList
|
||||
&& _activeChat.key.history()
|
||||
&& _activeChat.key.history()->isMonoforum()) {
|
||||
&& _activeChat.key.history()->amMonoforumAdmin()) {
|
||||
_controller->closeMonoforum();
|
||||
} else {
|
||||
_controller->showBackFromStack();
|
||||
|
@ -1236,7 +1236,8 @@ void TopBarWidget::updateMembersShowArea() {
|
|||
} else if (const auto chat = peer->asChat()) {
|
||||
return chat->amIn();
|
||||
} else if (const auto megagroup = peer->asMegagroup()) {
|
||||
return megagroup->canViewMembers()
|
||||
return !megagroup->isMonoforum()
|
||||
&& megagroup->canViewMembers()
|
||||
&& (megagroup->membersCount()
|
||||
< megagroup->session().serverConfig().chatSizeMax);
|
||||
}
|
||||
|
|
|
@ -1777,9 +1777,14 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupPersonalChannel(
|
|||
style::al_left);
|
||||
return;
|
||||
}
|
||||
if (!state->view.prepared(item, nullptr)) {
|
||||
if (!state->view.prepared(item, nullptr, nullptr)) {
|
||||
const auto repaint = [=] { preview->update(); };
|
||||
state->view.prepare(item, nullptr, repaint, {});
|
||||
state->view.prepare(
|
||||
item,
|
||||
nullptr,
|
||||
nullptr,
|
||||
repaint,
|
||||
{});
|
||||
}
|
||||
state->view.paint(p, preview->rect(), {
|
||||
.st = &st::defaultDialogRow,
|
||||
|
|
Loading…
Add table
Reference in a new issue