diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 00cd49329..d56f2ef46 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -1108,13 +1108,14 @@ void Widget::updateHasFocus(not_null focused) { } void Widget::processSearchFocusChange() { + _searchSuggestionsLocked = _suggestions && _suggestions->persist(); updateStoriesVisibility(); updateForceDisplayWide(); updateSuggestions(anim::type::normal); } void Widget::updateSuggestions(anim::type animated) { - const auto suggest = _searchHasFocus + const auto suggest = (_searchHasFocus || _searchSuggestionsLocked) && !_searchInChat && (_inner->state() == WidgetState::Default); if (anim::Disabled() || !session().data().chatsListLoaded()) { @@ -1148,6 +1149,7 @@ void Widget::updateSuggestions(anim::type animated) { controller(), TopPeersContent(&session()), RecentPeersContent(&session())); + _searchSuggestionsLocked = false; rpl::merge( _suggestions->topPeerChosen(), @@ -1155,6 +1157,10 @@ void Widget::updateSuggestions(anim::type animated) { _suggestions->myChannelChosen(), _suggestions->recommendationChosen() ) | rpl::start_with_next([=](not_null peer) { + if (_searchSuggestionsLocked + && (!_suggestions || !_suggestions->persist())) { + processSearchFocusChange(); + } chosenRow({ .key = peer->owner().history(peer), .newWindow = base::IsCtrlPressed(), @@ -1478,7 +1484,8 @@ void Widget::setInnerFocus() { return; } else if (!_search->getLastText().isEmpty() || _searchInChat - || _searchHasFocus) { + || _searchHasFocus + || _searchSuggestionsLocked) { _search->setFocus(); } else { setFocus(); @@ -1620,6 +1627,7 @@ void Widget::updateStoriesVisibility() { || !_widthAnimationCache.isNull() || _childList || _searchHasFocus + || _searchSuggestionsLocked || !_search->getLastText().isEmpty() || _searchInChat || _stories->empty(); @@ -2586,6 +2594,7 @@ void Widget::applySearchUpdate(bool force) { void Widget::updateForceDisplayWide() { controller()->setChatsForceDisplayWide(_searchHasFocus + || _searchSuggestionsLocked || !_search->getLastText().isEmpty() || _searchInChat); } @@ -3342,7 +3351,12 @@ bool Widget::cancelSearch() { setFocus(); clearingInChat = true; } - const auto clearSearchFocus = !_searchInChat && _searchHasFocus; + const auto clearSearchFocus = !_searchInChat + && (_searchHasFocus || _searchSuggestionsLocked); + if (!_searchInChat && _suggestions) { + _suggestions->clearPersistance(); + _searchSuggestionsLocked = false; + } if (!_suggestions && clearSearchFocus) { // Don't create suggestions in unfocus case. setFocus(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index 84faf7576..ac37ed427 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -304,6 +304,7 @@ private: std::vector _searchTags; rpl::lifetime _searchTagsLifetime; QString _lastSearchText; + bool _searchSuggestionsLocked = false; bool _searchHasFocus = false; rpl::event_stream> _storiesContents; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp index 17d761fe0..821530807 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp @@ -115,7 +115,6 @@ private: const not_null _window; RecentPeersList _recent; rpl::variable _count; - base::unique_qptr _menu; rpl::event_stream> _chosen; rpl::lifetime _lifetime; @@ -145,14 +144,13 @@ public: private: void setupDivider(); void appendRow(not_null channel); - void fill(); + void fill(bool force = false); const not_null _window; std::vector> _channels; rpl::variable _toggleExpanded = nullptr; rpl::variable _count = 0; rpl::variable _expanded = false; - base::unique_qptr _menu; rpl::event_stream> _chosen; rpl::lifetime _lifetime; @@ -185,7 +183,6 @@ private: const not_null _window; rpl::variable _count; - base::unique_qptr _menu; rpl::event_stream> _chosen; rpl::lifetime _lifetime; @@ -529,6 +526,27 @@ MyChannelsController::MyChannelsController( void MyChannelsController::prepare() { setupDivider(); + session().changes().peerUpdates( + Data::PeerUpdate::Flag::ChannelAmIn + ) | rpl::start_with_next([=](const Data::PeerUpdate &update) { + const auto channel = update.peer->asBroadcast(); + if (!channel || channel->amIn()) { + return; + } + const auto history = channel->owner().history(channel); + const auto i = ranges::remove(_channels, history); + if (i == end(_channels)) { + return; + } + _channels.erase(i, end(_channels)); + const auto row = delegate()->peerListFindRow(channel->id.value); + if (row) { + delegate()->peerListRemoveRow(row); + } + _count = int(_channels.size()); + fill(true); + }, _lifetime); + _channels.reserve(kProbablyMaxChannels); const auto owner = &session().data(); const auto add = [&](not_null list) { @@ -579,20 +597,20 @@ void MyChannelsController::prepare() { }, _lifetime); } -void MyChannelsController::fill() { +void MyChannelsController::fill(bool force) { const auto count = _count.current(); const auto limit = _expanded.current() ? count : std::min(count, kCollapsedChannelsCount); const auto already = delegate()->peerListFullRowsCount(); const auto delta = limit - already; - if (!delta) { + if (!delta && !force) { return; } else if (delta > 0) { for (auto i = already; i != limit; ++i) { appendRow(_channels[i]->peer->asBroadcast()); } - } else { + } else if (delta < 0) { for (auto i = already; i != limit;) { delegate()->peerListRemoveRow(delegate()->peerListRowAt(--i)); } @@ -620,7 +638,19 @@ void MyChannelsController::rowClicked(not_null row) { base::unique_qptr MyChannelsController::rowContextMenu( QWidget *parent, not_null row) { - return nullptr; + auto result = base::make_unique_q( + parent, + st::popupMenuWithIcons); + const auto peer = row->peer(); + const auto addAction = Ui::Menu::CreateAddActionCallback(result); + Window::FillDialogsEntryMenu( + _window, + Dialogs::EntryState{ + .key = peer->owner().history(peer), + .section = Dialogs::EntryState::Section::ContextMenu, + }, + addAction); + return result; } Main::Session &MyChannelsController::session() const { @@ -977,6 +1007,7 @@ void Suggestions::switchTab(Tab tab) { return; } _tab = tab; + _persist = false; if (_tabs->isHidden()) { return; } @@ -1215,6 +1246,7 @@ object_ptr> Suggestions::setupMyChannels() { controller->chosen( ) | rpl::start_with_next([=](not_null peer) { + _persist = false; _myChannelChosen.fire_copy(peer); }, lifetime); @@ -1269,6 +1301,7 @@ object_ptr> Suggestions::setupRecommendations() { controller->chosen( ) | rpl::start_with_next([=](not_null peer) { + _persist = true; _recommendationChosen.fire_copy(peer); }, lifetime); @@ -1311,6 +1344,14 @@ object_ptr> Suggestions::setupRecommendations() { return object_ptr>(this, std::move(content)); } +bool Suggestions::persist() const { + return _persist; +} + +void Suggestions::clearPersistance() { + _persist = false; +} + rpl::producer TopPeersContent( not_null session) { return [=](auto consumer) { diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h index 5749d7af7..4e08720bb 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h @@ -50,6 +50,9 @@ public: void hide(anim::type animated, Fn finish); [[nodiscard]] float64 shownOpacity() const; + [[nodiscard]] bool persist() const; + void clearPersistance(); + [[nodiscard]] rpl::producer> topPeerChosen() const { return _topPeerChosen.events(); } @@ -141,6 +144,7 @@ private: Fn _showFinished; Tab _tab = Tab::Chats; bool _hidden = false; + bool _persist = false; QPixmap _cache; Ui::Animations::Simple _slideAnimation; diff --git a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp index 2a6f031ed..d2a609c39 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp @@ -167,7 +167,8 @@ constexpr auto kStickerSetLines = 3; : (type == WebPageType::GroupWithRequest || type == WebPageType::ChannelWithRequest) ? tr::lng_view_button_request_join(tr::now) - : (type == WebPageType::ChannelBoost) + : (type == WebPageType::GroupBoost + || type == WebPageType::ChannelBoost) ? tr::lng_view_button_boost(tr::now) : (type == WebPageType::Giftcode) ? tr::lng_view_button_giftcode(tr::now) @@ -202,8 +203,11 @@ constexpr auto kStickerSetLines = 3; return webpage->iv || (type == WebPageType::Message) || (type == WebPageType::Group) + || (type == WebPageType::GroupWithRequest) + || (type == WebPageType::GroupBoost) || (type == WebPageType::Channel) || (type == WebPageType::ChannelBoost) + || (type == WebPageType::ChannelWithRequest) || (type == WebPageType::Giftcode) // || (type == WebPageType::Bot) || (type == WebPageType::User) diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index dfc7d3baa..c4ba68899 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -41,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peers/add_bot_to_chat_box.h" #include "boxes/peers/edit_contact_box.h" #include "boxes/report_messages_box.h" +#include "boxes/share_box.h" #include "boxes/translate_box.h" #include "lang/lang_keys.h" #include "menu/menu_mute.h" @@ -131,9 +132,8 @@ base::options::toggle ShowPeerIdBelowAbout({ + addToLink; } if (!link.isEmpty()) { - QGuiApplication::clipboard()->setText(link); - if (const auto window = weak.get()) { - window->showToast(tr::lng_username_copied(tr::now)); + if (const auto strong = weak.get()) { + FastShareLink(strong, link); } } };