diff --git a/Telegram/SourceFiles/boxes/confirm_box.cpp b/Telegram/SourceFiles/boxes/confirm_box.cpp index 7c5afd510..b88270d91 100644 --- a/Telegram/SourceFiles/boxes/confirm_box.cpp +++ b/Telegram/SourceFiles/boxes/confirm_box.cpp @@ -69,6 +69,21 @@ TextParseOptions kMarkedTextBoxOptions = { Qt::LayoutDirectionAuto, // dir }; +[[nodiscard]] bool IsOldForPin(MsgId id, not_null peer) { + const auto normal = peer->migrateToOrMe(); + const auto migrated = normal->migrateFrom(); + const auto top = Data::ResolveTopPinnedId(normal, migrated); + if (!top) { + return false; + } else if (peer == migrated) { + return top.channel || (id < top.msg); + } else if (migrated) { + return top.channel && (id < top.msg); + } else { + return (id < top.msg); + } +} + } // namespace ConfirmBox::ConfirmBox( @@ -444,7 +459,7 @@ PinMessageBox::PinMessageBox( : _peer(peer) , _api(&peer->session().mtp()) , _msgId(msgId) -, _pinningOld(msgId < Data::ResolveTopPinnedId(peer)) +, _pinningOld(IsOldForPin(msgId, peer)) , _text( this, (_pinningOld diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 2b817d695..5bf2db6d4 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -1017,7 +1017,9 @@ void SetTopPinnedMessageId(not_null peer, MsgId messageId) { peer->setHasPinnedMessages(true); } -MsgId ResolveTopPinnedId(not_null peer) { +FullMsgId ResolveTopPinnedId( + not_null peer, + PeerData *migrated) { const auto slice = peer->session().storage().snapshot( Storage::SharedMediaQuery( Storage::SharedMediaKey( @@ -1026,10 +1028,32 @@ MsgId ResolveTopPinnedId(not_null peer) { ServerMaxMsgId - 1), 1, 1)); - return slice.messageIds.empty() ? 0 : slice.messageIds.back(); + const auto old = migrated + ? migrated->session().storage().snapshot( + Storage::SharedMediaQuery( + Storage::SharedMediaKey( + migrated->id, + Storage::SharedMediaType::Pinned, + ServerMaxMsgId - 1), + 1, + 1)) + : Storage::SharedMediaResult{ + .count = 0, + .skippedBefore = 0, + .skippedAfter = 0, + }; + if (!slice.messageIds.empty()) { + return FullMsgId(peerToChannel(peer->id), slice.messageIds.back()); + } else if (!migrated || slice.count != 0 || old.messageIds.empty()) { + return FullMsgId(); + } else { + return FullMsgId(0, old.messageIds.back()); + } } -std::optional ResolvePinnedCount(not_null peer) { +std::optional ResolvePinnedCount( + not_null peer, + PeerData *migrated) { const auto slice = peer->session().storage().snapshot( Storage::SharedMediaQuery( Storage::SharedMediaKey( @@ -1038,7 +1062,23 @@ std::optional ResolvePinnedCount(not_null peer) { 0), 0, 0)); - return slice.count; + const auto old = migrated + ? migrated->session().storage().snapshot( + Storage::SharedMediaQuery( + Storage::SharedMediaKey( + migrated->id, + Storage::SharedMediaType::Pinned, + 0), + 0, + 0)) + : Storage::SharedMediaResult{ + .count = 0, + .skippedBefore = 0, + .skippedAfter = 0, + }; + return (slice.count.has_value() && old.count.has_value()) + ? std::make_optional(*slice.count + *old.count) + : std::nullopt; } } // namespace Data diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 2ffb3cbaf..3a01b6e98 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -443,7 +443,11 @@ std::optional RestrictionError( ChatRestriction restriction); void SetTopPinnedMessageId(not_null peer, MsgId messageId); -[[nodiscard]] MsgId ResolveTopPinnedId(not_null peer); -[[nodiscard]] std::optional ResolvePinnedCount(not_null peer); +[[nodiscard]] FullMsgId ResolveTopPinnedId( + not_null peer, + PeerData *migrated); +[[nodiscard]] std::optional ResolvePinnedCount( + not_null peer, + PeerData *migrated); } // namespace Data diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index d819cb0e9..91e593f2d 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -2998,6 +2998,31 @@ int HistoryInner::itemTop(const Element *view) const { return (top < 0) ? top : (top + view->y() + view->block()->y()); } +auto HistoryInner::findViewForPinnedTracking(int top) const +-> std::pair { + const auto normalTop = historyTop(); + const auto oldTop = migratedTop(); + const auto fromHistory = [&](not_null history, int historyTop) + -> std::pair { + auto [view, offset] = history->findItemAndOffset(top - historyTop); + while (view && !IsServerMsgId(view->data()->id)) { + offset -= view->height(); + view = view->nextInBlocks(); + } + return { view, offset }; + }; + if (normalTop >= 0 && (oldTop < 0 || top >= normalTop)) { + return fromHistory(_history, normalTop); + } else if (oldTop >= 0) { + auto [view, offset] = fromHistory(_migrated, oldTop); + if (!view && normalTop >= 0) { + return fromHistory(_history, normalTop); + } + return { view, offset }; + } + return { nullptr, 0 }; +} + void HistoryInner::notifyIsBotChanged() { const auto newinfo = _peer->isUser() ? _peer->asUser()->botInfo.get() diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index d58de44e1..b671f1675 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -111,6 +111,10 @@ public: int itemTop(const HistoryItem *item) const; int itemTop(const Element *view) const; + // Returns (view, offset-from-top). + [[nodiscard]] std::pair findViewForPinnedTracking( + int top) const; + void notifyIsBotChanged(); void notifyMigrateUpdated(); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 02b024b62..10eb82f6e 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -569,6 +569,12 @@ HistoryWidget::HistoryWidget( | UpdateFlag::BotStartToken | UpdateFlag::PinnedMessages ) | rpl::filter([=](const Data::PeerUpdate &update) { + if (_migrated && update.peer.get() == _migrated->peer) { + if (_pinnedTracker + && (update.flags & UpdateFlag::PinnedMessages)) { + checkPinnedBarState(); + } + } return (update.peer.get() == _peer); }) | rpl::map([](const Data::PeerUpdate &update) { return update.flags; @@ -3398,6 +3404,7 @@ void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) { if (_replyForwardPressed) { _replyForwardPressed = false; update(0, _field->y() - st::historySendPadding - st::historyReplyHeight, width(), st::historyReplyHeight); + setupPinnedTracker(); AssertIsDebug(); } if (_recording) { stopRecording(_peer && _inField); @@ -5021,6 +5028,7 @@ void HistoryWidget::handlePeerMigration() { } else { _migrated = _history->migrateFrom(); _list->notifyMigrateUpdated(); + setupPinnedTracker(); updateHistoryGeometry(); } const auto from = chat->owner().historyLoaded(chat); @@ -5168,23 +5176,14 @@ void HistoryWidget::updatePinnedViewer() { || !_historyInited) { return; } - const auto [item, offset] = [&] { - auto visibleTop = _scroll->scrollTop(); - if (_migrated - && _history->loadedAtBottom() - && _migrated->loadedAtTop()) { - visibleTop -= _migrated->height(); - } - auto [item, offset] = _history->findItemAndOffset(visibleTop); - while (item && !IsServerMsgId(item->data()->id)) { - offset -= item->height(); - item = item->nextInBlocks(); - } - return std::pair(item, offset); - }(); - const auto lessThanId = item - ? (item->data()->id + (offset > 0 ? 1 : 0)) - : (ServerMaxMsgId - 1); + const auto visibleTop = _scroll->scrollTop(); + const auto add = (st::historyReplyHeight - _pinnedBarHeight); + auto [view, offset] = _list->findViewForPinnedTracking(visibleTop + add); + const auto lessThanId = !view + ? (ServerMaxMsgId - 1) + : (view->data()->history() != _history) + ? (view->data()->id + (offset > 0 ? 1 : 0) - ServerMaxMsgId) + : (view->data()->id + (offset > 0 ? 1 : 0)); _pinnedTracker->trackAround(lessThanId); } @@ -5202,8 +5201,15 @@ void HistoryWidget::checkPinnedBarState() { const auto hiddenId = _peer->canPinMessages() ? MsgId(0) : session().settings().hiddenPinnedMessageId(_peer->id); - const auto currentPinnedId = Data::ResolveTopPinnedId(_peer); - if (currentPinnedId == hiddenId) { + const auto currentPinnedId = Data::ResolveTopPinnedId( + _peer, + _migrated ? _migrated->peer.get() : nullptr); + const auto universalPinnedId = !currentPinnedId + ? int32(0) + : (_migrated && !currentPinnedId.channel) + ? (currentPinnedId.msg - ServerMaxMsgId) + : currentPinnedId.msg; + if (universalPinnedId == hiddenId) { if (_pinnedBar) { _pinnedTracker->reset(); auto qobject = base::unique_qptr{ @@ -5221,21 +5227,13 @@ void HistoryWidget::checkPinnedBarState() { } return; } - if (_pinnedBar || !currentPinnedId) { + if (_pinnedBar || !universalPinnedId) { return; } - auto shown = _pinnedTracker->shownMessageId( - ) | rpl::map([=](HistoryView::PinnedId messageId) { - return HistoryView::PinnedBarId{ - FullMsgId{ peerToChannel(_peer->id), messageId.message }, - messageId.index, - messageId.count - }; - }); auto barContent = HistoryView::PinnedBarContent( &session(), - std::move(shown)); + _pinnedTracker->shownMessageId()); _pinnedBar = std::make_unique( this, std::move(barContent)); @@ -5268,8 +5266,8 @@ void HistoryWidget::checkPinnedBarState() { _pinnedBar->barClicks( ) | rpl::start_with_next([=] { const auto id = _pinnedTracker->currentMessageId(); - if (id.message) { - Ui::showPeerHistory(_peer, id.message); + if (const auto item = session().data().message(id.message)) { + Ui::showPeerHistory(item->history()->peer, item->id); } }, _pinnedBar->lifetime()); @@ -5303,7 +5301,11 @@ void HistoryWidget::refreshPinnedBarButton(bool many) { const auto id = _pinnedTracker->currentMessageId(); if (id.message) { controller()->showSection( - HistoryView::PinnedMemento(_history, id.message)); + HistoryView::PinnedMemento( + _history, + ((!_migrated || id.message.channel) + ? id.message.msg + : (id.message.msg - ServerMaxMsgId)))); } } }, button->lifetime()); @@ -5560,10 +5562,7 @@ void HistoryWidget::hidePinnedMessage() { return; } if (_peer->canPinMessages()) { - Window::ToggleMessagePinned( - controller(), - { peerToChannel(_peer->id), id.message }, - false); + Window::ToggleMessagePinned(controller(), id.message, false); } else { const auto callback = [=] { if (_pinnedTracker) { @@ -5877,7 +5876,9 @@ void HistoryWidget::handlePeerUpdate() { updateHistoryGeometry(); if (_peer->isChat() && _peer->asChat()->noParticipantInfo()) { session().api().requestFullPeer(_peer); - } else if (_peer->isUser() && (_peer->asUser()->blockStatus() == UserData::BlockStatus::Unknown || _peer->asUser()->callsStatus() == UserData::CallsStatus::Unknown)) { + } else if (_peer->isUser() + && (_peer->asUser()->blockStatus() == UserData::BlockStatus::Unknown + || _peer->asUser()->callsStatus() == UserData::CallsStatus::Unknown)) { session().api().requestFullPeer(_peer); } else if (auto channel = _peer->asMegagroup()) { if (!channel->mgInfo->botStatus) { diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_bar.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_bar.cpp index 96aa406de..9e536656a 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_bar.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_bar.cpp @@ -117,7 +117,7 @@ namespace { })); } -auto WithPinnedTitle(not_null session, PinnedBarId id) { +auto WithPinnedTitle(not_null session, PinnedId id) { return [=](Ui::MessageBarContent &&content) { const auto item = session->data().message(id.message); if (!item) { @@ -144,11 +144,11 @@ rpl::producer MessageBarContentByItemId( rpl::producer PinnedBarContent( not_null session, - rpl::producer id) { + rpl::producer id) { return std::move( id ) | rpl::distinct_until_changed( - ) | rpl::map([=](PinnedBarId id) { + ) | rpl::map([=](PinnedId id) { return ContentByItemId( session, id.message diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_bar.h b/Telegram/SourceFiles/history/view/history_view_pinned_bar.h index 41c20d30e..1e7c3578f 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_bar.h +++ b/Telegram/SourceFiles/history/view/history_view_pinned_bar.h @@ -28,25 +28,25 @@ namespace HistoryView { FullMsgId id); enum class PinnedIdType; -struct PinnedBarId { +struct PinnedId { FullMsgId message; int index = 0; int count = 1; - bool operator<(const PinnedBarId &other) const { + bool operator<(const PinnedId &other) const { return std::tie(message, index, count) < std::tie(other.message, other.index, other.count); } - bool operator==(const PinnedBarId &other) const { + bool operator==(const PinnedId &other) const { return std::tie(message, index, count) == std::tie(other.message, other.index, other.count); } - bool operator!=(const PinnedBarId &other) const { + bool operator!=(const PinnedId &other) const { return !(*this == other); } }; [[nodiscard]] rpl::producer PinnedBarContent( not_null session, - rpl::producer id); + rpl::producer id); } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp index 2e1355bc4..3aa58d258 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp @@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item_components.h" #include "history/history_item.h" #include "boxes/confirm_box.h" -#include "data/data_peer_values.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/shadow.h" #include "ui/layers/generic_box.h" @@ -34,10 +33,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "data/data_session.h" #include "data/data_user.h" +#include "data/data_chat.h" #include "data/data_channel.h" #include "data/data_changes.h" #include "data/data_sparse_ids.h" #include "data/data_shared_media.h" +#include "data/data_peer_values.h" #include "storage/storage_account.h" #include "platform/platform_specific.h" #include "lang/lang_keys.h" @@ -90,7 +91,8 @@ PinnedWidget::PinnedWidget( not_null controller, not_null history) : Window::SectionWidget(parent, controller) -, _history(history) +, _history(history->migrateToOrMe()) +, _migratedPeer(_history->peer->migrateFrom()) , _topBar(this, controller) , _topBarShadow(this) , _scroll(std::make_unique(this, st::historyScroll, false)) @@ -321,7 +323,8 @@ bool PinnedWidget::showInternal( not_null memento, const Window::SectionShow ¶ms) { if (auto logMemento = dynamic_cast(memento.get())) { - if (logMemento->getHistory() == history()) { + if (logMemento->getHistory() == history() + || logMemento->getHistory()->migrateToOrMe() == history()) { restoreState(logMemento); return true; } @@ -358,7 +361,9 @@ void PinnedWidget::restoreState(not_null memento) { _inner->restoreState(memento->list()); if (const auto highlight = memento->getHighlightId()) { const auto position = Data::MessagePosition{ - .fullId = FullMsgId(_history->channelId(), highlight), + .fullId = ((highlight > 0 || !_migratedPeer) + ? FullMsgId(_history->channelId(), highlight) + : FullMsgId(0, -highlight)), .date = TimeId(0), }; _inner->showAroundPosition(position, [=] { @@ -508,6 +513,28 @@ void PinnedWidget::listDeleteRequest() { confirmDeleteSelected(); } +rpl::producer SharedMediaCountValue( + not_null peer, + PeerData *migrated, + Storage::SharedMediaType type) { + auto aroundId = 0; + auto limit = 0; + auto updated = SharedMediaMergedViewer( + &peer->session(), + SharedMediaMergedKey( + SparseIdsMergedSlice::Key( + peer->id, + migrated ? migrated->id : 0, + aroundId), + type), + limit, + limit + ) | rpl::map([](const SparseIdsMergedSlice &slice) { + return slice.fullCount(); + }) | rpl::filter_optional(); + return rpl::single(0) | rpl::then(std::move(updated)); +} + rpl::producer PinnedWidget::listSource( Data::MessagePosition aroundId, int limitBefore, @@ -516,15 +543,18 @@ rpl::producer PinnedWidget::listSource( const auto messageId = aroundId.fullId.msg ? aroundId.fullId.msg : (ServerMaxMsgId - 1); - return SharedMediaViewer( + + return SharedMediaMergedViewer( &_history->session(), - Storage::SharedMediaKey( - _history->peer->id, - Storage::SharedMediaType::Pinned, - messageId), + SharedMediaMergedKey( + SparseIdsMergedSlice::Key( + _history->peer->id, + _migratedPeer ? _migratedPeer->id : 0, + messageId), + Storage::SharedMediaType::Pinned), limitBefore, limitAfter - ) | rpl::filter([=](const SparseIdsSlice &slice) { + ) | rpl::filter([=](const SparseIdsMergedSlice &slice) { const auto count = slice.fullCount(); if (!count.has_value()) { return true; @@ -535,7 +565,7 @@ rpl::producer PinnedWidget::listSource( controller()->showBackFromStack(); return false; } - }) | rpl::map([=](SparseIdsSlice &&slice) { + }) | rpl::map([=](SparseIdsMergedSlice &&slice) { auto result = Data::MessagesSlice(); result.fullCount = slice.fullCount(); result.skippedAfter = slice.skippedAfter(); @@ -543,10 +573,10 @@ rpl::producer PinnedWidget::listSource( const auto count = slice.size(); result.ids.reserve(count); if (const auto msgId = slice.nearest(messageId)) { - result.nearestToAround = FullMsgId(channelId, *msgId); + result.nearestToAround = *msgId; } for (auto i = 0; i != count; ++i) { - result.ids.emplace_back(channelId, slice[i]); + result.ids.push_back(slice[i]); } return result; }); diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.h b/Telegram/SourceFiles/history/view/history_view_pinned_section.h index d6984d44f..8025e2bc4 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.h +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.h @@ -136,6 +136,7 @@ private: void refreshClearButtonText(); const not_null _history; + PeerData *_migratedPeer = nullptr; QPointer _inner; object_ptr _topBar; object_ptr _topBarShadow; @@ -155,9 +156,11 @@ private: class PinnedMemento : public Window::SectionMemento { public: + using UniversalMsgId = int32; + explicit PinnedMemento( not_null history, - MsgId highlightId = 0); + UniversalMsgId highlightId = 0); object_ptr createWidget( QWidget *parent, @@ -172,13 +175,13 @@ public: [[nodiscard]] not_null list() { return &_list; } - [[nodiscard]] MsgId getHighlightId() const { + [[nodiscard]] UniversalMsgId getHighlightId() const { return _highlightId; } private: const not_null _history; - const MsgId _highlightId = 0; + const UniversalMsgId _highlightId = 0; ListMemento _list; }; diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp index f8c9c6d31..be5963df5 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_changes.h" #include "data/data_peer.h" +#include "data/data_chat.h" #include "data/data_channel.h" #include "data/data_shared_media.h" #include "data/data_session.h" @@ -26,13 +27,25 @@ constexpr auto kChangeViewerLimit = 2; } // namespace -PinnedTracker::PinnedTracker(not_null history) : _history(history) { - _history->session().changes().peerFlagsValue( - _history->peer, - Data::PeerUpdate::Flag::PinnedMessages - ) | rpl::map([=] { - return _history->peer->hasPinnedMessages(); - }) | rpl::distinct_until_changed( +PinnedTracker::PinnedTracker(not_null history) +: _history(history->migrateToOrMe()) +, _migratedPeer(_history->peer->migrateFrom()) { + using namespace rpl::mappers; + const auto has = [&](PeerData *peer) -> rpl::producer { + auto &changes = _history->session().changes(); + const auto flag = Data::PeerUpdate::Flag::PinnedMessages; + if (!peer) { + return rpl::single(false); + } + return changes.peerFlagsValue(peer, flag) | rpl::map([=] { + return peer->hasPinnedMessages(); + }); + }; + rpl::combine( + has(_history->peer), + has(_migratedPeer), + _1 || _2 + ) | rpl::distinct_until_changed( ) | rpl::start_with_next([=](bool has) { if (has) { refreshViewer(); @@ -62,15 +75,17 @@ void PinnedTracker::refreshViewer() { } _dataLifetime.destroy(); _viewerAroundId = _aroundId; - SharedMediaViewer( + SharedMediaMergedViewer( &_history->peer->session(), - Storage::SharedMediaKey( - _history->peer->id, - Storage::SharedMediaType::Pinned, - _viewerAroundId), + SharedMediaMergedKey( + SparseIdsMergedSlice::Key( + _history->peer->id, + _migratedPeer ? _migratedPeer->id : 0, + _viewerAroundId), + Storage::SharedMediaType::Pinned), kLoadedLimit, kLoadedLimit - ) | rpl::start_with_next([=](const SparseIdsSlice &result) { + ) | rpl::start_with_next([=](const SparseIdsMergedSlice &result) { _slice.fullCount = result.fullCount(); _slice.skippedBefore = result.skippedBefore(); _slice.skippedAfter = result.skippedAfter(); @@ -83,12 +98,23 @@ void PinnedTracker::refreshViewer() { refreshCurrentFromSlice(); if (_slice.fullCount == 0) { _history->peer->setHasPinnedMessages(false); + if (_migratedPeer) { + _migratedPeer->setHasPinnedMessages(false); + } } }, _dataLifetime); } void PinnedTracker::refreshCurrentFromSlice() { - const auto i = ranges::lower_bound(_slice.ids, _aroundId); + const auto proj1 = [](FullMsgId id) { + return id.channel ? id.msg : (id.msg - ServerMaxMsgId); + }; + const auto proj2 = [](FullMsgId id) { + return id.msg; + }; + const auto i = _migratedPeer + ? ranges::lower_bound(_slice.ids, _aroundId, ranges::less(), proj1) + : ranges::lower_bound(_slice.ids, _aroundId, ranges::less(), proj2); const auto empty = _slice.ids.empty(); const auto before = int(i - begin(_slice.ids)); const auto after = int(end(_slice.ids) - i); diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_tracker.h b/Telegram/SourceFiles/history/view/history_view_pinned_tracker.h index 9335c4851..bf4a2b8cb 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_tracker.h +++ b/Telegram/SourceFiles/history/view/history_view_pinned_tracker.h @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "history/view/history_view_pinned_bar.h" + class History; namespace Data { @@ -15,29 +17,16 @@ enum class LoadDirection : char; namespace HistoryView { -struct PinnedId { - MsgId message = 0; - int index = 0; - int count = 1; - - bool operator<(const PinnedId &other) const { - return std::tie(message, index, count) - < std::tie(other.message, other.index, other.count); - } - bool operator==(const PinnedId &other) const { - return std::tie(message, index, count) - == std::tie(other.message, other.index, other.count); - } -}; - class PinnedTracker final { public: + using UniversalMsgId = int32; + explicit PinnedTracker(not_null history); ~PinnedTracker(); [[nodiscard]] rpl::producer shownMessageId() const; [[nodiscard]] PinnedId currentMessageId() const; - void trackAround(MsgId messageId); + void trackAround(UniversalMsgId messageId); void reset(); [[nodiscard]] rpl::lifetime &lifetime() { @@ -46,7 +35,7 @@ public: private: struct Slice { - std::vector ids; + std::vector ids; std::optional fullCount; std::optional skippedBefore; std::optional skippedAfter; @@ -56,12 +45,13 @@ private: void refreshCurrentFromSlice(); const not_null _history; + PeerData *_migratedPeer = nullptr; rpl::variable _current; rpl::lifetime _dataLifetime; - MsgId _aroundId = 0; - MsgId _viewerAroundId = 0; + UniversalMsgId _aroundId = 0; + UniversalMsgId _viewerAroundId = 0; Slice _slice; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 336188181..35da3941f 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -1157,9 +1157,15 @@ void HidePinnedBar( Ui::show(Box(tr::lng_pinned_hide_all_sure(tr::now), tr::lng_pinned_hide_all_hide(tr::now), crl::guard(navigation, [=] { Ui::hideLayer(); auto &session = peer->session(); - const auto top = Data::ResolveTopPinnedId(peer); - if (top) { - session.settings().setHiddenPinnedMessageId(peer->id, top); + const auto migrated = peer->migrateFrom(); + const auto top = Data::ResolveTopPinnedId(peer, migrated); + const auto universal = !top + ? int32(0) + : (migrated && !top.channel) + ? (top.msg - ServerMaxMsgId) + : top.msg; + if (universal) { + session.settings().setHiddenPinnedMessageId(peer->id, universal); session.saveSettingsDelayed(); if (onHidden) { onHidden();