diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 3db32bbde..3661f0608 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -108,7 +108,10 @@ DialogsInner::DialogsInner(QWidget *parent, not_null contro }, lifetime()); subscribe(App::histories().sendActionAnimationUpdated(), [this](const Histories::SendActionAnimationUpdate &update) { auto updateRect = Dialogs::Layout::RowPainter::sendActionAnimationRect(update.width, update.height, getFullWidth(), update.textUpdated); - updateDialogRow(update.history, MsgId(0), updateRect, UpdateRowSection::Default | UpdateRowSection::Filtered); + updateDialogRow( + Dialogs::RowDescriptor(update.history, MsgId(0)), + updateRect, + UpdateRowSection::Default | UpdateRowSection::Filtered); }); subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &data) { @@ -140,6 +143,15 @@ DialogsInner::DialogsInner(QWidget *parent, not_null contro } })); + _controller->activeChatEntryValue( + ) | rpl::combine_previous( + ) | rpl::start_with_next([=]( + Dialogs::RowDescriptor previous, + Dialogs::RowDescriptor next) { + const auto rect = QRect(0, 0, getFullWidth(), st::dialogsRowHeight); + updateDialogRow(previous, rect); + updateDialogRow(next, rect); + }, lifetime()); refresh(); } @@ -181,6 +193,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO if (!paintingOther) { p.setClipRect(r); } + const auto activeEntry = _controller->activeChatEntryCurrent(); auto fullWidth = getFullWidth(); auto ms = getms(); if (_state == State::Default) { @@ -195,15 +208,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO p.translate(0, st::dialogsImportantBarHeight); } auto otherStart = rows->size() * st::dialogsRowHeight; - // #TODO feeds show - const auto active = [&] { - if (const auto peer = App::main()->activePeer()) { - if (const auto history = App::historyLoaded(peer)) { - return Dialogs::Key(history); - } - } - return Dialogs::Key(); - }(); + const auto active = activeEntry.key; const auto selected = _menuKey ? _menuKey : (isPressed() @@ -238,7 +243,14 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO // Skip currently dragged chat to paint it above others after. if (lastPaintedPos != _aboveIndex) { - paintDialog(p, row, fullWidth, active, selected, paintingOther, ms); + paintDialog( + p, + row, + fullWidth, + active, + selected, + paintingOther, + ms); } p.translate(0, st::dialogsRowHeight); @@ -318,19 +330,11 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO auto to = ceilclamp(r.y() + r.height() - skip, st::dialogsRowHeight, 0, _filterResults.size()); p.translate(0, from * st::dialogsRowHeight); if (from < _filterResults.size()) { - // #TODO feeds show - const auto activePeer = App::main()->activePeer(); - const auto activeMsgId = App::main()->activeMsgId(); for (; from < to; ++from) { const auto row = _filterResults[from]; const auto key = row->key(); - const auto history = key.history(); - const auto peer = history ? history->peer.get() : nullptr; - const auto active = !activeMsgId - && peer - && activePeer - && ((peer == activePeer) - || (peer->migrateTo() == activePeer)); + const auto active = (activeEntry.key == key) + && !activeEntry.msgId; const auto selected = _menuKey ? (key == _menuKey) : (from == (isPressed() @@ -363,12 +367,11 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO auto to = ceilclamp(r.y() + r.height() - skip, st::dialogsRowHeight, 0, _peerSearchResults.size()); p.translate(0, from * st::dialogsRowHeight); if (from < _peerSearchResults.size()) { - auto activePeer = App::main()->activePeer(); - auto activeMsgId = App::main()->activeMsgId(); + const auto activePeer = activeEntry.key.peer(); for (; from < to; ++from) { const auto &result = _peerSearchResults[from]; const auto peer = result->peer; - const auto active = !activeMsgId + const auto active = !activeEntry.msgId && activePeer && ((peer == activePeer) || (peer->migrateTo() == activePeer)); @@ -414,21 +417,27 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO auto to = ceilclamp(r.y() + r.height() - skip, st::dialogsRowHeight, 0, _searchResults.size()); p.translate(0, from * st::dialogsRowHeight); if (from < _searchResults.size()) { - auto activePeer = App::main()->activePeer(); - auto activeMsgId = App::main()->activeMsgId(); + const auto activePeer = activeEntry.key.peer(); for (; from < to; ++from) { const auto &result = _searchResults[from]; const auto item = result->item(); const auto peer = item->history()->peer; const auto active = (peer == activePeer - && item->id == activeMsgId) + && item->id == activeEntry.msgId) || (peer->migrateTo() && peer->migrateTo() == activePeer - && item->id == -activeMsgId); + && item->id == -activeEntry.msgId); const auto selected = (from == (isPressed() ? _searchedPressed : _searchedSelected)); - Dialogs::Layout::RowPainter::paint(p, result.get(), fullWidth, active, selected, paintingOther, ms); + Dialogs::Layout::RowPainter::paint( + p, + result.get(), + fullWidth, + active, + selected, + paintingOther, + ms); p.translate(0, st::dialogsRowHeight); } } @@ -1243,8 +1252,7 @@ void DialogsInner::dlgUpdated( void DialogsInner::dlgUpdated(not_null history, MsgId msgId) { updateDialogRow( - history, - msgId, + Dialogs::RowDescriptor(history, msgId), QRect(0, 0, getFullWidth(), st::dialogsRowHeight)); } @@ -1264,17 +1272,20 @@ void DialogsInner::updateSearchResult(not_null peer) { } void DialogsInner::updateDialogRow( - not_null history, - MsgId msgId, + Dialogs::RowDescriptor row, QRect updateRect, UpdateRowSections sections) { - auto updateRow = [this, updateRect](int rowTop) { - rtlupdate(updateRect.x(), rowTop + updateRect.y(), updateRect.width(), updateRect.height()); + auto updateRow = [&](int rowTop) { + rtlupdate( + updateRect.x(), + rowTop + updateRect.y(), + updateRect.width(), + updateRect.height()); }; if (_state == State::Default) { if (sections & UpdateRowSection::Default) { - if (const auto row = shownDialogs()->getRow(history)) { - auto position = row->pos(); + if (const auto dialog = shownDialogs()->getRow(row.key)) { + const auto position = dialog->pos(); auto top = dialogsOffset(); if (base::in_range(position, 0, _pinnedRows.size())) { top += qRound(_pinnedRows[position].yadd.current()); @@ -1283,35 +1294,46 @@ void DialogsInner::updateDialogRow( } } } else if (_state == State::Filtered) { - if ((sections & UpdateRowSection::Filtered) && !_filterResults.isEmpty()) { - auto index = 0, add = filteredOffset(); - for_const (auto row, _filterResults) { - if (row->history() == history) { + if ((sections & UpdateRowSection::Filtered) + && !_filterResults.isEmpty()) { + const auto add = filteredOffset(); + auto index = 0; + for (const auto result : _filterResults) { + if (result->key() == row.key) { updateRow(add + index * st::dialogsRowHeight); break; } ++index; } } - if ((sections & UpdateRowSection::PeerSearch) && !_peerSearchResults.empty()) { - auto index = 0, add = peerSearchOffset(); - for_const (auto &result, _peerSearchResults) { - if (result->peer == history->peer) { - updateRow(add + index * st::dialogsRowHeight); - break; + if ((sections & UpdateRowSection::PeerSearch) + && !_peerSearchResults.empty()) { + if (const auto peer = row.key.peer()) { + const auto add = peerSearchOffset(); + auto index = 0; + for (const auto &result : _peerSearchResults) { + if (result->peer == peer) { + updateRow(add + index * st::dialogsRowHeight); + break; + } + ++index; } - ++index; } } - if ((sections & UpdateRowSection::MessageSearch) && !_searchResults.empty()) { - auto index = 0, add = searchedOffset(); - for_const (auto &result, _searchResults) { - auto item = result->item(); - if (item->history() == history && item->id == msgId) { - updateRow(add + index * st::dialogsRowHeight); - break; + if ((sections & UpdateRowSection::MessageSearch) + && !_searchResults.empty()) { + if (const auto history = row.key.history()) { + const auto add = searchedOffset(); + auto index = 0; + for (const auto &result : _searchResults) { + auto item = result->item(); + if (item->history() == history + && item->id == row.msgId) { + updateRow(add + index * st::dialogsRowHeight); + break; + } + ++index; } - ++index; } } } diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index f58a015f5..f76b34e25 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -207,8 +207,7 @@ private: void updateSearchResult(not_null peer); void updateDialogRow( - not_null history, - MsgId msgId, + Dialogs::RowDescriptor row, QRect updateRect, UpdateRowSections sections = UpdateRowSection::All); diff --git a/Telegram/SourceFiles/dialogs/dialogs_key.cpp b/Telegram/SourceFiles/dialogs/dialogs_key.cpp index 1e0e2f35b..3e64063af 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_key.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_key.cpp @@ -35,4 +35,11 @@ Data::Feed *Key::feed() const { return nullptr; } +PeerData *Key::peer() const { + if (const auto p = base::get_if>(&_value)) { + return (*p)->peer; + } + return nullptr; +} + } // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_key.h b/Telegram/SourceFiles/dialogs/dialogs_key.h index 94c3517b9..7a3f94af4 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_key.h +++ b/Telegram/SourceFiles/dialogs/dialogs_key.h @@ -37,6 +37,7 @@ public: not_null entry() const; History *history() const; Data::Feed *feed() const; + PeerData *peer() const; inline bool operator<(const Key &other) const { return _value < other._value; @@ -80,6 +81,36 @@ struct RowDescriptor { Key key; MsgId msgId = 0; + }; +inline bool operator==(const RowDescriptor &a, const RowDescriptor &b) { + return (a.key == b.key) && (a.msgId == b.msgId); +} + +inline bool operator!=(const RowDescriptor &a, const RowDescriptor &b) { + return !(a == b); +} + +inline bool operator<(const RowDescriptor &a, const RowDescriptor &b) { + if (a.key < b.key) { + return true; + } else if (a.key > b.key) { + return false; + } + return a.msgId < b.msgId; +} + +inline bool operator>(const RowDescriptor &a, const RowDescriptor &b) { + return (b < a); +} + +inline bool operator<=(const RowDescriptor &a, const RowDescriptor &b) { + return !(b < a); +} + +inline bool operator>=(const RowDescriptor &a, const RowDescriptor &b) { + return !(a < b); +} + } // namespace Dialogs diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index 87926ef47..a26a94845 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -210,7 +210,11 @@ InnerWidget::InnerWidget( , _channel(channel) , _history(App::history(channel)) , _scrollDateCheck([this] { scrollDateCheck(); }) -, _emptyText(st::historyAdminLogEmptyWidth - st::historyAdminLogEmptyPadding.left() - st::historyAdminLogEmptyPadding.left()) { +, _emptyText( + st::historyAdminLogEmptyWidth + - st::historyAdminLogEmptyPadding.left() + - st::historyAdminLogEmptyPadding.left()) +, _idManager(_history->adminLogIdManager()) { setMouseTracking(true); _scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); }); Auth().data().viewRepaintRequest( @@ -511,7 +515,9 @@ void InnerWidget::saveState(not_null memento) { void InnerWidget::restoreState(not_null memento) { _items = memento->takeItems(); _itemsByIds = memento->takeItemsByIds(); - _idManager = memento->takeIdManager(); + if (auto manager = memento->takeIdManager()) { + _idManager = std::move(manager); + } _admins = memento->takeAdmins(); _adminsCanEdit = memento->takeAdminsCanEdit(); _filter = memento->takeFilter(); @@ -601,7 +607,7 @@ void InnerWidget::addEvents(Direction direction, const QVector 1) { @@ -805,7 +811,8 @@ void InnerWidget::clearAfterFilterChange() { _filterChanged = false; _items.clear(); _itemsByIds.clear(); - _idManager = LocalIdManager(); + _idManager = nullptr; + _idManager = _history->adminLogIdManager(); updateEmptyText(); updateSize(); } diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h index 159d7263b..43082b060 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h @@ -198,7 +198,6 @@ private: int _itemsWidth = 0; int _itemsHeight = 0; - LocalIdManager _idManager; int _minHeight = 0; int _visibleTop = 0; int _visibleBottom = 0; @@ -251,6 +250,8 @@ private: std::vector> _adminsCanEdit; base::lambda _showFilterCallback; + std::shared_ptr _idManager; + }; } // namespace AdminLog diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp index 16e826d83..861607303 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp @@ -312,7 +312,7 @@ OwnedItem::~OwnedItem() { void GenerateItems( not_null delegate, not_null history, - LocalIdManager &idManager, + not_null idManager, const MTPDchannelAdminLogEvent &event, base::lambda callback) { Expects(history->peer->isChannel()); @@ -334,7 +334,7 @@ void GenerateItems( auto addSimpleServiceMessage = [&](const QString &text, PhotoData *photo = nullptr) { auto message = HistoryService::PreparedText { text }; message.links.push_back(fromLink); - addPart(new HistoryService(history, idManager.next(), ::date(date), message, 0, peerToUser(from->id), photo)); + addPart(new HistoryService(history, idManager->next(), ::date(date), message, 0, peerToUser(from->id), photo)); }; auto createChangeTitle = [&](const MTPDchannelAdminLogEventActionChangeTitle &action) { @@ -355,7 +355,7 @@ void GenerateItems( auto bodyReplyTo = 0; auto bodyViaBotId = 0; auto newDescription = PrepareText(newValue, QString()); - auto body = new HistoryMessage(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), newDescription); + auto body = new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), newDescription); if (!oldValue.isEmpty()) { auto oldDescription = PrepareText(oldValue, QString()); body->addLogEntryOriginal(id, lang(lng_admin_log_previous_description), oldDescription); @@ -376,7 +376,7 @@ void GenerateItems( auto bodyReplyTo = 0; auto bodyViaBotId = 0; auto newLink = newValue.isEmpty() ? TextWithEntities() : PrepareText(Messenger::Instance().createInternalLinkFull(newValue), QString()); - auto body = new HistoryMessage(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), newLink); + auto body = new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), newLink); if (!oldValue.isEmpty()) { auto oldLink = PrepareText(Messenger::Instance().createInternalLinkFull(oldValue), QString()); body->addLogEntryOriginal(id, lang(lng_admin_log_previous_link), oldLink); @@ -427,7 +427,7 @@ void GenerateItems( addPart(history->createItem( PrepareLogMessage( action.vmessage, - idManager.next(), + idManager->next(), date.v), detachExistingItem)); } @@ -447,7 +447,7 @@ void GenerateItems( auto body = history->createItem( PrepareLogMessage( action.vnew_message, - idManager.next(), + idManager->next(), date.v), detachExistingItem); if (oldValue.text.isEmpty()) { @@ -463,7 +463,7 @@ void GenerateItems( auto detachExistingItem = false; addPart(history->createItem( - PrepareLogMessage(action.vmessage, idManager.next(), date.v), + PrepareLogMessage(action.vmessage, idManager->next(), date.v), detachExistingItem)); }; @@ -486,7 +486,7 @@ void GenerateItems( auto bodyReplyTo = 0; auto bodyViaBotId = 0; auto bodyText = GenerateParticipantChangeText(channel, action.vparticipant); - addPart(new HistoryMessage(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), bodyText)); + addPart(new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), bodyText)); }; auto createParticipantToggleBan = [&](const MTPDchannelAdminLogEventActionParticipantToggleBan &action) { @@ -494,7 +494,7 @@ void GenerateItems( auto bodyReplyTo = 0; auto bodyViaBotId = 0; auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant, &action.vprev_participant); - addPart(new HistoryMessage(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), bodyText)); + addPart(new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), bodyText)); }; auto createParticipantToggleAdmin = [&](const MTPDchannelAdminLogEventActionParticipantToggleAdmin &action) { @@ -502,7 +502,7 @@ void GenerateItems( auto bodyReplyTo = 0; auto bodyViaBotId = 0; auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant, &action.vprev_participant); - addPart(new HistoryMessage(history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), bodyText)); + addPart(new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), bodyText)); }; auto createChangeStickerSet = [&](const MTPDchannelAdminLogEventActionChangeStickerSet &action) { @@ -523,7 +523,7 @@ void GenerateItems( auto message = HistoryService::PreparedText { text }; message.links.push_back(fromLink); message.links.push_back(setLink); - addPart(new HistoryService(history, idManager.next(), ::date(date), message, 0, peerToUser(from->id))); + addPart(new HistoryService(history, idManager->next(), ::date(date), message, 0, peerToUser(from->id))); } }; diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.h index ed20f43fa..7f238be38 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.h @@ -20,7 +20,7 @@ class LocalIdManager; void GenerateItems( not_null delegate, not_null history, - LocalIdManager &idManager, + not_null idManager, const MTPDchannelAdminLogEvent &event, base::lambda callback); diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp index 67505191a..49f00f0bf 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp @@ -279,6 +279,10 @@ not_null Widget::channel() const { return _inner->channel(); } +Dialogs::RowDescriptor Widget::activeChat() const { + return { App::history(channel()), MsgId(0) }; +} + QPixmap Widget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) { if (params.withTopBarShadow) _fixedBarShadow->hide(); auto result = Ui::GrabWidget(this); diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h index 1f5d8a757..abdb6c240 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h @@ -52,12 +52,6 @@ public: LocalIdManager() = default; LocalIdManager(const LocalIdManager &other) = delete; LocalIdManager &operator=(const LocalIdManager &other) = delete; - LocalIdManager(LocalIdManager &&other) : _counter(std::exchange(other._counter, ServerMaxMsgId)) { - } - LocalIdManager &operator=(LocalIdManager &&other) { - _counter = std::exchange(other._counter, ServerMaxMsgId); - return *this; - } MsgId next() { return ++_counter; } @@ -72,9 +66,7 @@ public: Widget(QWidget *parent, not_null controller, not_null channel); not_null channel() const; - PeerData *activePeer() const override { - return channel(); - } + Dialogs::RowDescriptor activeChat() const override; bool hasTopBarShadow() const override { return true; @@ -173,7 +165,7 @@ public: void setSearchQuery(QString &&query) { _searchQuery = std::move(query); } - void setIdManager(LocalIdManager &&manager) { + void setIdManager(std::shared_ptr &&manager) { _idManager = std::move(manager); } std::vector takeItems() { @@ -182,7 +174,7 @@ public: std::map> takeItemsByIds() { return std::move(_itemsByIds); } - LocalIdManager takeIdManager() { + std::shared_ptr takeIdManager() { return std::move(_idManager); } bool upLoaded() const { @@ -207,7 +199,7 @@ private: std::map> _itemsByIds; bool _upLoaded = false; bool _downLoaded = true; - LocalIdManager _idManager; + std::shared_ptr _idManager; FilterValue _filter; QString _searchQuery; diff --git a/Telegram/SourceFiles/history/feed/history_feed_section.cpp b/Telegram/SourceFiles/history/feed/history_feed_section.cpp index af2a9f5b5..1cee74505 100644 --- a/Telegram/SourceFiles/history/feed/history_feed_section.cpp +++ b/Telegram/SourceFiles/history/feed/history_feed_section.cpp @@ -93,6 +93,10 @@ Widget::Widget( }, lifetime()); } +Dialogs::RowDescriptor Widget::activeChat() const { + return Dialogs::RowDescriptor(_feed, MsgId(0)); +} + void Widget::updateAdaptiveLayout() { _topBarShadow->moveToLeft( Adaptive::OneColumn() ? 0 : st::lineWidth, diff --git a/Telegram/SourceFiles/history/feed/history_feed_section.h b/Telegram/SourceFiles/history/feed/history_feed_section.h index c4964b304..cf2ed7f6d 100644 --- a/Telegram/SourceFiles/history/feed/history_feed_section.h +++ b/Telegram/SourceFiles/history/feed/history_feed_section.h @@ -36,6 +36,8 @@ public: not_null controller, not_null feed); + Dialogs::RowDescriptor activeChat() const override; + bool hasTopBarShadow() const override { return true; } diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 86d337845..aad620e44 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "history/view/history_view_element.h" +#include "history/admin_log/history_admin_log_section.h" #include "history/history_message.h" #include "history/history_media_types.h" #include "history/history_service.h" @@ -1924,6 +1925,15 @@ void History::getNextFirstUnreadMessage() { _firstUnreadView = nullptr; } +std::shared_ptr History::adminLogIdManager() { + if (const auto strong = _adminLogIdManager.lock()) { + return strong; + } + auto result = std::make_shared(); + _adminLogIdManager = result; + return result; +} + QDateTime History::adjustChatListDate() const { const auto result = chatsListDate(); if (const auto draft = cloudDraft()) { diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index cdda66176..99b491a97 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -19,16 +19,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class History; +namespace HistoryView { +class Element; +} // namespace HistoryView + +namespace AdminLog { +class LocalIdManager; +} // namespace AdminLog + enum NewMessageType : char { NewMessageUnread, NewMessageLast, NewMessageExisting, }; -namespace HistoryView { -class Element; -} // namespace HistoryView - class Histories { public: using Map = QHash; @@ -331,6 +335,8 @@ public: // of the displayed window relative to the history start coordinate void countScrollState(int top); + std::shared_ptr adminLogIdManager(); + virtual ~History(); // Still public data. @@ -503,6 +509,8 @@ private: int _pinnedIndex = 0; // > 0 for pinned dialogs + std::weak_ptr _adminLogIdManager; + }; class HistoryJoined; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 92b03be30..827d0dac3 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1371,7 +1371,9 @@ bool HistoryWidget::notify_switchInlineBotButtonReceived(const QString &query, U return true; } } else if (auto bot = _peer ? _peer->asUser() : nullptr) { - PeerId toPeerId = bot->botInfo ? bot->botInfo->inlineReturnPeerId : 0; + const auto toPeerId = bot->botInfo + ? bot->botInfo->inlineReturnPeerId + : PeerId(0); if (!toPeerId) { return false; } @@ -1620,11 +1622,6 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re bool canShowNow = _history->isReadyFor(showAtMsgId); if (!canShowNow) { delayedShowAt(showAtMsgId); - - if (wasHistory) { - App::main()->dlgUpdated(wasHistory, wasMsgId); - } - emit historyShown(_history, _showAtMsgId); } else { _history->forgetScrollState(); if (_migrated) { @@ -1655,12 +1652,18 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re _topBar->update(); update(); - if (startBot && _peer->isUser() && _peer->asUser()->botInfo) { - if (wasHistory) _peer->asUser()->botInfo->inlineReturnPeerId = wasHistory->peer->id; - onBotStart(); - _history->clearLocalDraft(); - applyDraft(); - _send->finishAnimating(); + if (const auto user = _peer->asUser()) { + if (const auto &info = user->botInfo) { + if (startBot) { + if (wasHistory) { + info->inlineReturnPeerId = wasHistory->peer->id; + } + onBotStart(); + _history->clearLocalDraft(); + applyDraft(); + _send->finishAnimating(); + } + } } return; } @@ -1802,9 +1805,15 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re connect(_scroll, SIGNAL(geometryChanged()), _list, SLOT(onParentGeometryChanged())); - if (startBot && _peer->isUser() && _peer->asUser()->botInfo) { - if (wasHistory) _peer->asUser()->botInfo->inlineReturnPeerId = wasHistory->peer->id; - onBotStart(); + if (const auto user = _peer->asUser()) { + if (const auto &info = user->botInfo) { + if (startBot) { + if (wasHistory) { + info->inlineReturnPeerId = wasHistory->peer->id; + } + onBotStart(); + } + } } unreadCountChanged(_history); // set _historyDown badge. } else { @@ -1815,16 +1824,11 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re updateForwarding(); updateOverStates(mapFromGlobal(QCursor::pos())); - if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus())); - - if (wasHistory) { - App::main()->dlgUpdated(wasHistory, wasMsgId); - } - emit historyShown(_history, _showAtMsgId); + crl::on_main(App::wnd(), [] { App::wnd()->setInnerFocus(); }); controller()->historyPeer = _peer; - if (_peer) { - controller()->activePeer = _peer; + if (_history) { + controller()->setActiveChatEntry({ _history, _showAtMsgId }); } update(); } @@ -3038,9 +3042,8 @@ void HistoryWidget::setMsgId(MsgId showAtMsgId) { auto wasMsgId = _showAtMsgId; _showAtMsgId = showAtMsgId; if (_history) { - App::main()->dlgUpdated(_history, wasMsgId); + controller()->setActiveChatEntry({ _history, _showAtMsgId }); } - emit historyShown(_history, _showAtMsgId); } } diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 117c427fe..11f6d2d25 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -367,7 +367,6 @@ protected: signals: void cancelled(); - void historyShown(History *history, MsgId atMsgId); public slots: void onCancel(); diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 5bea47ab1..3ff99c4a8 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -1304,6 +1304,9 @@ bool Message::hasBubble() const { } bool Message::hasFastReply() const { + if (context() != Context::History) { + return false; + } const auto peer = data()->history()->peer; return !hasOutLayout() && (peer->isChat() || peer->isMegagroup()); } @@ -1491,23 +1494,24 @@ TextSelection Message::unskipTextSelection(TextSelection selection) const { QRect Message::countGeometry() const { const auto item = message(); + const auto media = this->media(); + const auto mediaWidth = media ? media->width() : width(); const auto outbg = hasOutLayout(); + const auto availableWidth = width() + - st::msgMargin.left() + - st::msgMargin.right(); auto contentLeft = (outbg && !Adaptive::ChatWide()) ? st::msgMargin.right() : st::msgMargin.left(); + auto contentWidth = availableWidth; if (hasFromPhoto()) { contentLeft += st::msgPhotoSkip; + if (displayRightAction()) { + contentWidth -= st::msgPhotoSkip; + } //} else if (!Adaptive::Wide() && !out() && !fromChannel() && st::msgPhotoSkip - (hmaxwidth - hwidth) > 0) { // contentLeft += st::msgPhotoSkip - (hmaxwidth - hwidth); } - - const auto media = this->media(); - const auto mediaWidth = media ? media->width() : width(); - const auto availableWidth = width() - st::msgMargin.left() - st::msgMargin.right(); - auto contentWidth = availableWidth; - if (item->history()->peer->isSelf() && !outbg) { - contentWidth -= st::msgPhotoSkip; - } accumulate_min(contentWidth, maxWidth()); accumulate_min(contentWidth, st::msgMaxWidth); if (mediaWidth < contentWidth) { @@ -1546,7 +1550,7 @@ int Message::resizeContentGetHeight(int newWidth) { // This code duplicates countGeometry() but also resizes media. auto contentWidth = newWidth - (st::msgMargin.left() + st::msgMargin.right()); - if (item->history()->peer->isSelf() && !hasOutLayout()) { + if (hasFromPhoto() && displayRightAction()) { contentWidth -= st::msgPhotoSkip; } accumulate_min(contentWidth, maxWidth()); diff --git a/Telegram/SourceFiles/info/info_section_widget.cpp b/Telegram/SourceFiles/info/info_section_widget.cpp index e86d2fb4d..8124ebb30 100644 --- a/Telegram/SourceFiles/info/info_section_widget.cpp +++ b/Telegram/SourceFiles/info/info_section_widget.cpp @@ -44,8 +44,8 @@ void SectionWidget::init() { }, _content->lifetime()); } -PeerData *SectionWidget::activePeer() const { - return _content->activePeer(); +Dialogs::RowDescriptor SectionWidget::activeChat() const { + return _content->activeChat(); } bool SectionWidget::hasTopBarShadow() const { diff --git a/Telegram/SourceFiles/info/info_section_widget.h b/Telegram/SourceFiles/info/info_section_widget.h index 5c6d1d791..86a50912f 100644 --- a/Telegram/SourceFiles/info/info_section_widget.h +++ b/Telegram/SourceFiles/info/info_section_widget.h @@ -35,7 +35,7 @@ public: Wrap wrap, not_null memento); - PeerData *activePeer() const override; + Dialogs::RowDescriptor activeChat() const override; bool hasTopBarShadow() const override; QPixmap grabForShowAnimation( diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 178fbeeba..a7c413a26 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -104,17 +104,25 @@ void WrapWidget::startInjectingActivePeerProfiles() { using namespace rpl::mappers; rpl::combine( _wrap.value(), - _controller->parentController()->activePeer.value() + _controller->parentController()->activeChatValue() ) | rpl::filter( - (_1 == Wrap::Side) && (_2 != nullptr) + (_1 == Wrap::Side) && _2 ) | rpl::map( _2 - ) | rpl::start_with_next([this](not_null peer) { - injectActivePeerProfile(peer); + ) | rpl::start_with_next([this](Dialogs::Key key) { + injectActiveProfile(key); }, lifetime()); } +void WrapWidget::injectActiveProfile(Dialogs::Key key) { + if (const auto peer = key.peer()) { + injectActivePeerProfile(peer); + } else if (const auto feed = key.feed()) { + // #TODO feed profile + } +} + void WrapWidget::injectActivePeerProfile(not_null peer) { const auto firstPeerId = hasStackHistory() ? _historyStack.front().section->peerId() @@ -169,6 +177,10 @@ not_null WrapWidget::peer() const { return _controller->peer(); } +Dialogs::RowDescriptor WrapWidget::activeChat() const { + return Dialogs::RowDescriptor(App::history(peer()), MsgId(0)); +} + // This was done for tabs support. // //void WrapWidget::createTabs() { diff --git a/Telegram/SourceFiles/info/info_wrap_widget.h b/Telegram/SourceFiles/info/info_wrap_widget.h index 19aa7e66c..0963a9c6f 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.h +++ b/Telegram/SourceFiles/info/info_wrap_widget.h @@ -78,9 +78,7 @@ public: not_null memento); not_null peer() const; - PeerData *activePeer() const override { - return peer(); - } + Dialogs::RowDescriptor activeChat() const override; Wrap wrap() const { return _wrap.current(); } @@ -140,6 +138,7 @@ private: struct StackItem; void startInjectingActivePeerProfiles(); + void injectActiveProfile(Dialogs::Key key); void injectActivePeerProfile(not_null peer); void restoreHistoryStack( std::vector> stack); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 71a752d4a..31e75f7b6 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -223,7 +223,6 @@ MainWidget::MainWidget( connect(&_byPtsTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeByPts())); connect(&_byMinChannelTimer, SIGNAL(timeout()), this, SLOT(getDifference())); connect(&_failDifferenceTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeAfterFail())); - connect(_history, SIGNAL(historyShown(History*,MsgId)), this, SLOT(onHistoryShown(History*,MsgId))); connect(&updateNotifySettingTimer, SIGNAL(timeout()), this, SLOT(onUpdateNotifySettings())); subscribe(Media::Player::Updated(), [this](const AudioMsgId &audioId) { if (audioId.type() != AudioMsgId::Type::Video) { @@ -250,15 +249,16 @@ MainWidget::MainWidget( }); using namespace rpl::mappers; - _controller->activePeer.value( - ) | rpl::map([](PeerData *peer) { + _controller->activeChatValue( + ) | rpl::map([](Dialogs::Key key) { + const auto peer = key.peer(); auto canWrite = peer ? Data::CanWriteValue(peer) : rpl::single(false); - return std::move(canWrite) | rpl::map(tuple(peer, _1)); + return std::move(canWrite) | rpl::map(tuple(key, _1)); }) | rpl::flatten_latest( - ) | rpl::start_with_next([this](PeerData *peer, bool canWrite) { - updateThirdColumnToCurrentPeer(peer, canWrite); + ) | rpl::start_with_next([this](Dialogs::Key key, bool canWrite) { + updateThirdColumnToCurrentChat(key, canWrite); }, lifetime()); QCoreApplication::instance()->installEventFilter(this); @@ -813,7 +813,6 @@ void MainWidget::noHider(HistoryHider *destroyed) { _forwardConfirm->closeBox(); _forwardConfirm = nullptr; } - onHistoryShown(_history->history(), _history->msgId()); if (_mainSection || (_history->peer() && _history->peer()->id)) { auto animationParams = ([this] { if (_mainSection) { @@ -851,7 +850,6 @@ void MainWidget::hiderLayer(object_ptr h) { _hider->hide(); auto animationParams = prepareDialogsAnimation(); - onHistoryShown(nullptr, 0); if (_mainSection) { _mainSection->hide(); } else { @@ -1039,11 +1037,13 @@ void MainWidget::removeDialog(Dialogs::Key key) { _dialogs->removeDialog(key); } -void MainWidget::deleteConversation(PeerData *peer, bool deleteHistory) { - if (activePeer() == peer) { +void MainWidget::deleteConversation( + not_null peer, + bool deleteHistory) { + if (_controller->activeChatCurrent().peer() == peer) { Ui::showChatsList(); } - if (auto history = App::historyLoaded(peer->id)) { + if (const auto history = App::historyLoaded(peer->id)) { Auth().data().setPinnedDialog(history, false); removeDialog(history); if (peer->isMegagroup() && peer->asChannel()->mgInfo->migrateFromPtr) { @@ -2163,7 +2163,7 @@ void MainWidget::ui_showPeerHistory( } } - auto wasActivePeer = activePeer(); + const auto wasActivePeer = _controller->activeChatCurrent().peer(); if (params.activation != anim::activation::background) { Ui::hideSettingsAndLayer(); } @@ -2200,9 +2200,7 @@ void MainWidget::ui_showPeerHistory( auto animationParams = animatedShow() ? prepareHistoryAnimation(peerId) : Window::SectionSlideParams(); - if (back || (way == Way::ClearStack)) { - clearEntryInStack(); - } else { + if (!back && (way != Way::ClearStack)) { // This may modify the current section, for example remove its contents. saveSectionInStack(); } @@ -2232,14 +2230,17 @@ void MainWidget::ui_showPeerHistory( } } } else { - if (!noPeer && wasActivePeer != activePeer()) { - if (activePeer()->isChannel()) { - activePeer()->asChannel()->ptsWaitingForShortPoll( + const auto nowActivePeer = _controller->activeChatCurrent().peer(); + if (nowActivePeer && nowActivePeer != wasActivePeer) { + if (const auto channel = nowActivePeer->asChannel()) { + channel->ptsWaitingForShortPoll( WaitForChannelGetDifference); } - _viewsIncremented.remove(activePeer()); + _viewsIncremented.remove(nowActivePeer); + } + if (Adaptive::OneColumn() && !_dialogs->isHidden()) { + _dialogs->hide(); } - if (Adaptive::OneColumn() && !_dialogs->isHidden()) _dialogs->hide(); if (!_a_show.animating()) { if (!animationParams.oldContentCache.isNull()) { _history->showAnimated( @@ -2255,9 +2256,6 @@ void MainWidget::ui_showPeerHistory( } } } - //if (wasActivePeer && wasActivePeer->isChannel() && activePeer() != wasActivePeer) { - // wasActivePeer->asChannel()->ptsWaitingForShortPoll(false); - //} if (!_dialogs->isHidden()) { if (!back) { @@ -2268,8 +2266,8 @@ void MainWidget::ui_showPeerHistory( _dialogs->update(); } - if (!peerId) { - _controller->activePeer = nullptr; + if (noPeer) { + _controller->setActiveChatEntry(Dialogs::Key()); } checkFloatPlayerVisibility(); @@ -2299,34 +2297,6 @@ PeerData *MainWidget::peer() { return _history->peer(); } -PeerData *MainWidget::activePeer() { - if (const auto history = _history->history()) { - return history->peer; - } else if (_historyInStack) { - return _historyInStack->peer; - } - return nullptr; -} - -MsgId MainWidget::activeMsgId() { - return _history->peer() ? _history->msgId() : _msgIdInStack; -} - -void MainWidget::setEntryInStack(not_null history, MsgId msgId) { - setEntryInStackValues(history, msgId); -} - -void MainWidget::clearEntryInStack() { - setEntryInStackValues(nullptr, 0); -} - -void MainWidget::setEntryInStackValues(History *history, MsgId msgId) { - updateCurrentChatListEntry(); - _historyInStack = history; - _msgIdInStack = msgId; - updateCurrentChatListEntry(); -} - void MainWidget::saveSectionInStack() { if (_mainSection) { if (auto memento = _mainSection->createMemento()) { @@ -2335,10 +2305,9 @@ void MainWidget::saveSectionInStack() { _stack.back()->setThirdSectionWeak(_thirdSection.data()); } } else if (const auto history = _history->history()) { - setEntryInStack(history, _history->msgId()); _stack.push_back(std::make_unique( - _historyInStack, - _msgIdInStack, + history, + _history->msgId(), _history->replyReturns())); _stack.back()->setThirdSectionWeak(_thirdSection.data()); } @@ -2618,7 +2587,9 @@ void MainWidget::showNewSection( } if (settingSection.data() == _mainSection.data()) { - _controller->activePeer = _mainSection->activePeer(); + if (const auto entry = _mainSection->activeChat(); entry.key) { + _controller->setActiveChatEntry(entry); + } } checkFloatPlayerVisibility(); @@ -2666,7 +2637,9 @@ void MainWidget::showBackFromStack( if (selectingPeer()) return; if (_stack.empty()) { _controller->clearSectionStack(params); - if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus())); + if (App::wnd()) { + QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus())); + } return; } auto item = std::move(_stack.back()); @@ -2676,14 +2649,6 @@ void MainWidget::showBackFromStack( } _thirdSectionFromStack = item->takeThirdSectionMemento(); if (item->type() == HistoryStackItem) { - clearEntryInStack(); - for (auto i = _stack.size(); i > 0;) { - if (_stack[--i]->type() == HistoryStackItem) { - auto historyItem = static_cast(_stack[i].get()); - setEntryInStack(historyItem->history, historyItem->msgId); - break; - } - } auto historyItem = static_cast(item.get()); _controller->showPeerHistory( historyItem->peer()->id, @@ -2806,12 +2771,6 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams ¶m return result; } -void MainWidget::updateCurrentChatListEntry() { - if (_historyInStack) { - _dialogs->dlgUpdated(_historyInStack, _msgIdInStack); - } -} - void MainWidget::dlgUpdated( Dialogs::Mode list, not_null row) { @@ -3248,18 +3207,23 @@ bool MainWidget::saveThirdSectionToStackBack() const { } auto MainWidget::thirdSectionForCurrentMainSection( - not_null peer) + Dialogs::Key key) -> std::unique_ptr { if (_thirdSectionFromStack) { return std::move(_thirdSectionFromStack); + } else if (const auto peer = key.peer()) { + return std::make_unique( + peer->id, + Info::Memento::DefaultSection(peer)); + } else { + return std::make_unique( + App::self()->id, + Info::Memento::DefaultSection(App::self())); } - return std::make_unique( - peer->id, - Info::Memento::DefaultSection(peer)); } -void MainWidget::updateThirdColumnToCurrentPeer( - PeerData *peer, +void MainWidget::updateThirdColumnToCurrentChat( + Dialogs::Key key, bool canWrite) { auto saveOldThirdSection = [&] { if (saveThirdSectionToStackBack()) { @@ -3285,7 +3249,7 @@ void MainWidget::updateThirdColumnToCurrentPeer( } _controller->showSection( - std::move(*thirdSectionForCurrentMainSection(peer)), + std::move(*thirdSectionForCurrentMainSection(key)), params.withThirdColumn()); }; auto switchTabbedFast = [&] { @@ -3294,7 +3258,7 @@ void MainWidget::updateThirdColumnToCurrentPeer( }; if (Adaptive::ThreeColumn() && Auth().settings().tabbedSelectorSectionEnabled() - && peer) { + && key) { if (!canWrite) { switchInfoFast(); Auth().settings().setTabbedSelectorSectionEnabled(true); @@ -3305,7 +3269,7 @@ void MainWidget::updateThirdColumnToCurrentPeer( } } else { Auth().settings().setTabbedReplacedWithInfo(false); - if (!peer) { + if (!key) { if (_thirdSection) { _thirdSection.destroy(); _thirdShadow.destroy(); @@ -3449,13 +3413,6 @@ int MainWidget::backgroundFromY() const { return -getMainSectionTop(); } -void MainWidget::onHistoryShown(History *history, MsgId atMsgId) { -// updateControlsGeometry(); - if (history) { - dlgUpdated(history, atMsgId); - } -} - void MainWidget::searchInPeer(PeerData *peer) { _dialogs->searchInPeer(peer); if (Adaptive::OneColumn()) { @@ -3626,7 +3583,7 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha if (!isFinal) { MTP_LOG(0, ("getChannelDifference { good - after not final channelDifference was received }%1").arg(cTestMode() ? " TESTMODE" : "")); getChannelDifference(channel); - } else if (activePeer() == channel) { + } else if (_controller->activeChatCurrent().peer() == channel) { channel->ptsWaitingForShortPoll(timeout ? (timeout * 1000) : WaitForChannelGetDifference); } } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 96708a033..64d59e126 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -134,8 +134,6 @@ public: const Dialogs::RowDescriptor &which) const; PeerData *peer(); - PeerData *activePeer(); - MsgId activeMsgId(); int backgroundFromY() const; void showSection( @@ -200,7 +198,9 @@ public: const QVector &ids, bool forEveryone); void deletedContact(UserData *user, const MTPcontacts_Link &result); - void deleteConversation(PeerData *peer, bool deleteHistory = true); + void deleteConversation( + not_null peer, + bool deleteHistory = true); void deleteAndExit(ChatData *chat); void deleteAllFromUser(ChannelData *channel, UserData *from); @@ -357,8 +357,6 @@ public slots: void updateOnline(bool gotOtherOffline = false); void checkIdleFinish(); - void onHistoryShown(History *history, MsgId atMsgId); - void searchInPeer(PeerData *peer); void onUpdateNotifySettings(); @@ -425,12 +423,12 @@ private: void updateMediaPlaylistPosition(int x); void updateControlsGeometry(); void updateDialogsWidthAnimated(); - void updateThirdColumnToCurrentPeer( - PeerData *peer, + void updateThirdColumnToCurrentChat( + Dialogs::Key key, bool canWrite); [[nodiscard]] bool saveThirdSectionToStackBack() const; - [[nodiscard]] auto thirdSectionForCurrentMainSection( - not_null peer) -> std::unique_ptr; + [[nodiscard]] auto thirdSectionForCurrentMainSection(Dialogs::Key key) + -> std::unique_ptr; void userIsContactUpdated(not_null user); void createPlayer(); @@ -439,11 +437,6 @@ private: void closeBothPlayers(); void playerHeightUpdated(); - void updateCurrentChatListEntry(); - void setEntryInStack(not_null history, MsgId msgId); - void clearEntryInStack(); - void setEntryInStackValues(History *history, MsgId msgId); - void setCurrentCall(Calls::Call *call); void createCallTopBar(); void destroyCallTopBar(); @@ -588,8 +581,6 @@ private: QPointer _forwardConfirm; // for single column layout object_ptr _hider = { nullptr }; std::vector> _stack; - History *_historyInStack = nullptr; - MsgId _msgIdInStack = 0; int _playerHeight = 0; int _callTopBarHeight = 0; diff --git a/Telegram/SourceFiles/rpl/combine_previous.h b/Telegram/SourceFiles/rpl/combine_previous.h index b2787b818..8f89895c9 100644 --- a/Telegram/SourceFiles/rpl/combine_previous.h +++ b/Telegram/SourceFiles/rpl/combine_previous.h @@ -26,7 +26,7 @@ public: >(); return std::move(initial).start( [consumer, previous](auto &&value) { - if (auto exists = *previous) { + if (auto &exists = *previous) { auto &existing = *exists; auto next = std::make_tuple( std::move(existing), diff --git a/Telegram/SourceFiles/rpl/operators_tests.cpp b/Telegram/SourceFiles/rpl/operators_tests.cpp index 24a029d97..704c447f2 100644 --- a/Telegram/SourceFiles/rpl/operators_tests.cpp +++ b/Telegram/SourceFiles/rpl/operators_tests.cpp @@ -401,6 +401,35 @@ TEST_CASE("basic operators tests", "[rpl::operators]") { REQUIRE(*sum == "0-11-22-3"); } + SECTION("combine_previous test") { + auto sum = std::make_shared(""); + { + rpl::lifetime lifetime; + event_stream a; + + a.events( + ) | combine_previous( + ) | start_with_next([=](int previous, int next) { + *sum += std::to_string(previous) + ' '; + *sum += std::to_string(next) + ' '; + }, lifetime); + + a.events( + ) | combine_previous( + 5 + ) | start_with_next([=](int previous, int next) { + *sum += std::to_string(10 + previous) + ' '; + *sum += std::to_string(next) + ' '; + }, lifetime); + + a.fire(1); + a.fire(2); + a.fire(3); + a.fire(4); + } + REQUIRE(*sum == "15 1 1 2 11 2 2 3 12 3 3 4 13 4 "); + } + SECTION("take test") { auto sum = std::make_shared(""); { diff --git a/Telegram/SourceFiles/window/section_widget.h b/Telegram/SourceFiles/window/section_widget.h index e421742e6..0c269c8ce 100644 --- a/Telegram/SourceFiles/window/section_widget.h +++ b/Telegram/SourceFiles/window/section_widget.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/rp_widget.h" +#include "dialogs/dialogs_key.h" namespace Window { @@ -69,8 +70,8 @@ class SectionWidget : public AbstractSectionWidget { public: SectionWidget(QWidget *parent, not_null controller); - virtual PeerData *activePeer() const { - return nullptr; + virtual Dialogs::RowDescriptor activeChat() const { + return {}; } // When resizing the widget with top edge moved up or down and we diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index 8ef31edb5..fd96720a0 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -36,6 +36,46 @@ Controller::Controller(not_null window) }, lifetime()); } +void Controller::setActiveChatEntry(Dialogs::RowDescriptor row) { + _activeChatEntry = row; +} + +void Controller::setActiveChatEntry(Dialogs::Key key) { + setActiveChatEntry({ key, MsgId(0) }); +} + +Dialogs::RowDescriptor Controller::activeChatEntryCurrent() const { + return _activeChatEntry.current(); +} + +Dialogs::Key Controller::activeChatCurrent() const { + return activeChatEntryCurrent().key; +} + +auto Controller::activeChatEntryChanges() const +-> rpl::producer { + return _activeChatEntry.changes(); +} + +rpl::producer Controller::activeChatChanges() const { + return activeChatEntryChanges( + ) | rpl::map([](const Dialogs::RowDescriptor &value) { + return value.key; + }) | rpl::distinct_until_changed(); +} + +auto Controller::activeChatEntryValue() const +-> rpl::producer { + return _activeChatEntry.value(); +} + +rpl::producer Controller::activeChatValue() const { + return activeChatEntryValue( + ) | rpl::map([](const Dialogs::RowDescriptor &value) { + return value.key; + }) | rpl::distinct_until_changed(); +} + void Controller::enableGifPauseReason(GifPauseReason reason) { if (!(_gifPauseReasons & reason)) { auto notify = (static_cast(_gifPauseReasons) < static_cast(reason)); diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index e9d9c4207..8b253e53e 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include "base/flags.h" +#include "dialogs/dialogs_key.h" class MainWidget; class HistoryMessage; @@ -118,8 +119,14 @@ public: // Also used in the Info::Profile to toggle Send Message button. rpl::variable historyPeer; - // This is used for auto-switch in third column Info::Profile. - rpl::variable activePeer; + void setActiveChatEntry(Dialogs::RowDescriptor row); + void setActiveChatEntry(Dialogs::Key key); + Dialogs::RowDescriptor activeChatEntryCurrent() const; + Dialogs::Key activeChatCurrent() const; + rpl::producer activeChatEntryChanges() const; + rpl::producer activeChatChanges() const; + rpl::producer activeChatEntryValue() const; + rpl::producer activeChatValue() const; void enableGifPauseReason(GifPauseReason reason); void disableGifPauseReason(GifPauseReason reason); @@ -237,6 +244,7 @@ private: base::Observable _gifPauseLevelChanged; base::Observable _floatPlayerAreaUpdated; + rpl::variable _activeChatEntry; base::Variable _dialogsListFocused = { false }; base::Variable _dialogsListDisplayForced = { false }; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 928810501..14104b9e7 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -158,7 +158,7 @@ Filler::Filler( bool Filler::showInfo() { if (_source == PeerMenuSource::Profile || _peer->isSelf()) { return false; - } else if (_controller->activePeer.current() != _peer) { + } else if (_controller->activeChatCurrent().peer() != _peer) { return true; } else if (!Adaptive::ThreeColumn()) { return true; @@ -626,14 +626,15 @@ base::lambda DeleteAndLeaveHandler(not_null peer) { : st::attentionBoxButton; auto callback = [peer] { Ui::hideLayer(); - if (App::wnd()->controller()->activePeer.current() == peer) { + const auto controller = App::wnd()->controller(); + if (controller->activeChatCurrent().peer() == peer) { Ui::showChatsList(); } if (peer->isUser()) { App::main()->deleteConversation(peer); - } else if (auto chat = peer->asChat()) { + } else if (const auto chat = peer->asChat()) { App::main()->deleteAndExit(chat); - } else if (auto channel = peer->asChannel()) { + } else if (const auto channel = peer->asChannel()) { // Don't delete old history by default, // because Android app doesn't. //