diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 9b1492e9a2..3cd6952ce9 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_widget.h" #include "dialogs/dialogs_search_from_controllers.h" #include "dialogs/dialogs_search_tags.h" +#include "dialogs/dialogs_swipe_action.h" #include "history/view/history_view_context_menu.h" #include "history/history.h" #include "history/history_item.h" @@ -5037,17 +5038,8 @@ void InnerWidget::prepareSwipeAction( int64 key, Dialogs::Ui::SwipeDialogAction action) { if (key) { - auto name = (action == Dialogs::Ui::SwipeDialogAction::Mute) - ? u"swipe_mute"_q - : (action == Dialogs::Ui::SwipeDialogAction::Pin) - ? u"swipe_pin"_q - : (action == Dialogs::Ui::SwipeDialogAction::Read) - ? u"swipe_read"_q - : (action == Dialogs::Ui::SwipeDialogAction::Archive) - ? u"swipe_archive"_q - : (action == Dialogs::Ui::SwipeDialogAction::Delete) - ? u"swipe_delete"_q - : u"swipe_disabled"_q; + const auto peer = session().data().peer(PeerId(key)); + auto name = ResolveSwipeDialogLottieIconName(peer, action, _filterId); _swipeLottieIcon = Lottie::MakeIcon({ .name = std::move(name), .sizeOverride = Size(st::dialogsSwipeActionSize), diff --git a/Telegram/SourceFiles/dialogs/dialogs_swipe_action.cpp b/Telegram/SourceFiles/dialogs/dialogs_swipe_action.cpp index 90ed1fc032..9409b3a1e5 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_swipe_action.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_swipe_action.cpp @@ -8,22 +8,134 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_swipe_action.h" #include "dialogs/ui/dialogs_swipe_context.h" +#include "apiwrap.h" +#include "data/data_histories.h" #include "data/data_peer.h" #include "data/data_session.h" +#include "dialogs/dialogs_entry.h" #include "history/history.h" +#include "lang/lang_keys.h" #include "main/main_session.h" #include "menu/menu_mute.h" +#include "window/window_peer_menu.h" +#include "window/window_session_controller.h" namespace Dialogs { void PerformSwipeDialogAction( + not_null controller, not_null peer, - Ui::SwipeDialogAction action) { + Ui::SwipeDialogAction action, + FilterId filterId) { + const auto history = peer->owner().history(peer); if (action == Dialogs::Ui::SwipeDialogAction::Mute) { - const auto history = peer->owner().history(peer); - MuteMenu::ThreadDescriptor(history).updateMutePeriod( - std::numeric_limits::max()); + const auto isMuted = rpl::variable( + MuteMenu::ThreadDescriptor(history).isMutedValue()).current(); + MuteMenu::ThreadDescriptor(history).updateMutePeriod(isMuted + ? 0 + : std::numeric_limits::max()); + } else if (action == Dialogs::Ui::SwipeDialogAction::Pin) { + const auto entry = (Dialogs::Entry*)(history); + Window::TogglePinnedThread(controller, entry, filterId); + } else if (action == Dialogs::Ui::SwipeDialogAction::Read) { + if (Window::IsUnreadThread(history)) { + Window::MarkAsReadThread(history); + } else if (history) { + peer->owner().histories().changeDialogUnreadMark(history, true); + } + } else if (action == Dialogs::Ui::SwipeDialogAction::Archive) { + history->session().api().toggleHistoryArchived( + history, + !Window::IsArchived(history), + [] {}); + } else if (action == Dialogs::Ui::SwipeDialogAction::Delete) { + Window::DeleteAndLeaveHandler(controller, peer)(); } } +QString ResolveSwipeDialogLottieIconName( + not_null peer, + Ui::SwipeDialogAction action, + FilterId filterId) { + if (action == Dialogs::Ui::SwipeDialogAction::Mute) { + const auto history = peer->owner().history(peer); + const auto isMuted = rpl::variable( + MuteMenu::ThreadDescriptor(history).isMutedValue()).current(); + return isMuted ? u"swipe_unmute"_q : u"swipe_mute"_q; + } else if (action == Dialogs::Ui::SwipeDialogAction::Pin) { + const auto history = peer->owner().history(peer); + const auto entry = (Dialogs::Entry*)(history); + return entry->isPinnedDialog(filterId) + ? u"swipe_unpin"_q + : u"swipe_pin"_q; + } else if (action == Dialogs::Ui::SwipeDialogAction::Read) { + const auto history = peer->owner().history(peer); + return Window::IsUnreadThread(history) + ? u"swipe_read"_q + : u"swipe_unread"_q; + } else if (action == Dialogs::Ui::SwipeDialogAction::Archive) { + const auto history = peer->owner().history(peer); + return Window::IsArchived(history) + ? u"swipe_unarchive"_q + : u"swipe_archive"_q; + } else if (action == Dialogs::Ui::SwipeDialogAction::Delete) { + return u"swipe_delete"_q; + } + return u"swipe_disabled"_q; +} + +Ui::SwipeDialogActionLabel ResolveSwipeDialogLabel( + not_null history, + Ui::SwipeDialogAction action, + FilterId filterId) { + if (action == Dialogs::Ui::SwipeDialogAction::Mute) { + const auto isMuted = rpl::variable( + MuteMenu::ThreadDescriptor(history).isMutedValue()).current(); + return isMuted + ? Ui::SwipeDialogActionLabel::Unmute + : Ui::SwipeDialogActionLabel::Mute; + } else if (action == Dialogs::Ui::SwipeDialogAction::Pin) { + const auto entry = (Dialogs::Entry*)(history); + return entry->isPinnedDialog(filterId) + ? Ui::SwipeDialogActionLabel::Unpin + : Ui::SwipeDialogActionLabel::Pin; + } else if (action == Dialogs::Ui::SwipeDialogAction::Read) { + return Window::IsUnreadThread(history) + ? Ui::SwipeDialogActionLabel::Read + : Ui::SwipeDialogActionLabel::Unread; + } else if (action == Dialogs::Ui::SwipeDialogAction::Archive) { + return Window::IsArchived(history) + ? Ui::SwipeDialogActionLabel::Unarchive + : Ui::SwipeDialogActionLabel::Archive; + } else if (action == Dialogs::Ui::SwipeDialogAction::Delete) { + return Ui::SwipeDialogActionLabel::Delete; + } + return Ui::SwipeDialogActionLabel::Disabled; +} + +QString ResolveSwipeDialogLabel(Ui::SwipeDialogActionLabel action) { + switch (action) { + case Ui::SwipeDialogActionLabel::Mute: + return tr::lng_settings_swipe_mute(tr::now); + case Ui::SwipeDialogActionLabel::Unmute: + return tr::lng_settings_swipe_unmute(tr::now); + case Ui::SwipeDialogActionLabel::Pin: + return tr::lng_settings_swipe_pin(tr::now); + case Ui::SwipeDialogActionLabel::Unpin: + return tr::lng_settings_swipe_unpin(tr::now); + case Ui::SwipeDialogActionLabel::Read: + return tr::lng_settings_swipe_read(tr::now); + case Ui::SwipeDialogActionLabel::Unread: + return tr::lng_settings_swipe_unread(tr::now); + case Ui::SwipeDialogActionLabel::Archive: + return tr::lng_settings_swipe_archive(tr::now); + case Ui::SwipeDialogActionLabel::Unarchive: + return tr::lng_settings_swipe_unarchive(tr::now); + case Ui::SwipeDialogActionLabel::Delete: + return tr::lng_settings_swipe_delete(tr::now); + default: + return tr::lng_settings_swipe_disabled(tr::now); + }; +} + } // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_swipe_action.h b/Telegram/SourceFiles/dialogs/dialogs_swipe_action.h index 9dca99277c..3918f983a7 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_swipe_action.h +++ b/Telegram/SourceFiles/dialogs/dialogs_swipe_action.h @@ -7,16 +7,36 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +class History; class PeerData; namespace Dialogs::Ui { enum class SwipeDialogAction; +enum class SwipeDialogActionLabel; } // namespace Dialogs::Ui +namespace Window { +class SessionController; +} // namespace Window + namespace Dialogs { void PerformSwipeDialogAction( + not_null controller, not_null peer, - Ui::SwipeDialogAction action); + Ui::SwipeDialogAction action, + FilterId filterId); + +[[nodiscard]] QString ResolveSwipeDialogLottieIconName( + not_null peer, + Ui::SwipeDialogAction action, + FilterId filterId); + +[[nodiscard]] Ui::SwipeDialogActionLabel ResolveSwipeDialogLabel( + not_null history, + Ui::SwipeDialogAction action, + FilterId filterId); + +[[nodiscard]] QString ResolveSwipeDialogLabel(Ui::SwipeDialogActionLabel); } // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index c143945410..793a10b92f 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -690,10 +690,11 @@ void Widget::setupSwipeBack() { Ui::Controls::SetupSwipeHandler(_inner, _scroll.data(), [=]( Ui::Controls::SwipeContextData data) { if (data.translation != 0) { - if (data.translation < 0) { - if (_inner) { - _inner->setSwipeContextData(std::move(data)); - } + if (data.translation < 0 + && _inner + && (Core::App().settings().swipeDialogAction() + != Ui::SwipeDialogAction::Disabled)) { + _inner->setSwipeContextData(std::move(data)); } else { if (!_swipeBackData.callback) { _swipeBackData = Ui::Controls::SetupSwipeBack( @@ -726,16 +727,21 @@ void Widget::setupSwipeBack() { return Ui::Controls::SwipeHandlerFinishData(); } const auto isRightToLeft = direction == Qt::RightToLeft; + const auto action = Core::App().settings().swipeDialogAction(); + const auto isDisabled = action == Ui::SwipeDialogAction::Disabled; if (!isRightToLeft && _inner) { - if (const auto key = _inner->calcSwipeKey(top)) { - const auto action - = Core::App().settings().swipeDialogAction(); + if (const auto key = _inner->calcSwipeKey(top); + key && !isDisabled) { _inner->prepareSwipeAction(key, action); return Ui::Controls::SwipeHandlerFinishData{ .callback = [=, session = &session()] { auto callback = [=, peerId = PeerId(key)] { const auto peer = session->data().peer(peerId); - PerformSwipeDialogAction(peer, action); + PerformSwipeDialogAction( + controller(), + peer, + action, + _inner->filterId()); }; base::call_delayed( st::slideWrapDuration, @@ -788,7 +794,9 @@ void Widget::setupSwipeBack() { } }); } - if (_chatFilters && session().data().chatsFilters().has()) { + if (_chatFilters + && session().data().chatsFilters().has() + && isDisabled) { _swipeBackMirrored = !isRightToLeft; using namespace Window; const auto next = !isRightToLeft; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp index 9cb8692927..83b140292d 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/stickers/data_custom_emoji.h" #include "dialogs/dialogs_list.h" #include "dialogs/dialogs_three_state_icon.h" +#include "dialogs/dialogs_swipe_action.h" #include "dialogs/ui/dialogs_video_userpic.h" #include "history/history.h" #include "history/history_item.h" @@ -69,23 +70,11 @@ const auto kPsaBadgePrefix = "cloud_lng_badge_psa_"; return !history->isForum(); } -[[nodiscard]] QString SwipeActionText(Dialogs::Ui::SwipeDialogAction type) { - return (type == Dialogs::Ui::SwipeDialogAction::Archive) - ? tr::lng_settings_swipe_archive(tr::now) - : (type == Dialogs::Ui::SwipeDialogAction::Delete) - ? tr::lng_settings_swipe_delete(tr::now) - : (type == Dialogs::Ui::SwipeDialogAction::Read) - ? tr::lng_settings_swipe_read(tr::now) - : (type == Dialogs::Ui::SwipeDialogAction::Pin) - ? tr::lng_settings_swipe_pin(tr::now) - : tr::lng_settings_swipe_mute(tr::now); -} - const style::font &SwipeActionFont( - Dialogs::Ui::SwipeDialogAction action, + Dialogs::Ui::SwipeDialogActionLabel action, int availableWidth) { struct Entry final { - Dialogs::Ui::SwipeDialogAction action; + Dialogs::Ui::SwipeDialogActionLabel action; QString langId; style::font font; }; @@ -104,7 +93,7 @@ const style::font &SwipeActionFont( style::ConvertScale(i, style::Scale()), st::semiboldFont->flags(), st::semiboldFont->family()); - if (font->width(SwipeActionText(action)) <= availableWidth + if (font->width(ResolveSwipeDialogLabel(action)) <= availableWidth || i == kMinFontSize) { Fonts.emplace_back(Entry{ .action = action, @@ -920,11 +909,14 @@ void PaintRow( - iconOffset * 2 - st::dialogsSwipeActionSize; const auto availableWidth = geometry.width() - left; - p.setFont( - SwipeActionFont(context.swipeContext.action, availableWidth)); + const auto labelType = ResolveSwipeDialogLabel( + history, + context.swipeContext.action, + context.filter); + p.setFont(SwipeActionFont(labelType, availableWidth)); p.drawText( QRect(left, 0, availableWidth, geometry.height()), - SwipeActionText(context.swipeContext.action), + ResolveSwipeDialogLabel(labelType), style::al_bottom); } p.translate(0, topTranslation); diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_swipe_context.h b/Telegram/SourceFiles/dialogs/ui/dialogs_swipe_context.h index bbfc81d018..03cfdadb64 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_swipe_context.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_swipe_context.h @@ -26,6 +26,19 @@ enum class SwipeDialogAction { Disabled, }; +enum class SwipeDialogActionLabel { + Mute, + Unmute, + Pin, + Unpin, + Read, + Unread, + Archive, + Unarchive, + Delete, + Disabled, +}; + struct SwipeContext { ::Ui::Controls::SwipeContextData data; Lottie::Icon *icon = nullptr; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index b4c1daf624..9768688eed 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -438,40 +438,6 @@ void TogglePinnedThread( } } -void TogglePinnedThread( - not_null controller, - not_null entry, - FilterId filterId) { - if (!filterId) { - return TogglePinnedThread(controller, entry); - } - const auto history = entry->asHistory(); - if (!history) { - return; - } - const auto owner = &history->owner(); - - // This can happen when you remove this filter from another client. - if (!ranges::contains( - (&owner->session())->data().chatsFilters().list(), - filterId, - &Data::ChatFilter::id)) { - controller->showToast(tr::lng_cant_do_this(tr::now)); - return; - } - - const auto isPinned = !history->isPinnedDialog(filterId); - if (isPinned && PinnedLimitReached(controller, history, filterId)) { - return; - } - - owner->setChatPinned(history, filterId, isPinned); - Api::SaveNewFilterPinned(&owner->session(), filterId); - if (isPinned) { - controller->content()->dialogsToUp(); - } -} - Filler::Filler( not_null controller, Dialogs::EntryState request, @@ -726,7 +692,7 @@ void Filler::addToggleArchive() { } } const auto isArchived = [=] { - return (history->folder() != nullptr); + return IsArchived(history); }; const auto label = [=] { return isArchived() @@ -3316,4 +3282,42 @@ void AddSeparatorAndShiftUp(const PeerMenuCallback &addAction) { addAction({ .addTopShift = -shift }); } +void TogglePinnedThread( + not_null controller, + not_null entry, + FilterId filterId) { + if (!filterId) { + return TogglePinnedThread(controller, entry); + } + const auto history = entry->asHistory(); + if (!history) { + return; + } + const auto owner = &history->owner(); + + // This can happen when you remove this filter from another client. + if (!ranges::contains( + (&owner->session())->data().chatsFilters().list(), + filterId, + &Data::ChatFilter::id)) { + controller->showToast(tr::lng_cant_do_this(tr::now)); + return; + } + + const auto isPinned = !history->isPinnedDialog(filterId); + if (isPinned && PinnedLimitReached(controller, history, filterId)) { + return; + } + + owner->setChatPinned(history, filterId, isPinned); + Api::SaveNewFilterPinned(&owner->session(), filterId); + if (isPinned) { + controller->content()->dialogsToUp(); + } +} + +bool IsArchived(not_null history) { + return (history->folder() != nullptr); +} + } // namespace Window diff --git a/Telegram/SourceFiles/window/window_peer_menu.h b/Telegram/SourceFiles/window/window_peer_menu.h index 97268366c7..e3adf079bf 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.h +++ b/Telegram/SourceFiles/window/window_peer_menu.h @@ -40,6 +40,7 @@ class MainList; struct EntryState; struct UnreadState; class Key; +class Entry; } // namespace Dialogs namespace ChatHelpers { @@ -196,6 +197,10 @@ void ToggleMessagePinned( not_null navigation, FullMsgId itemId, bool pin); +void TogglePinnedThread( + not_null controller, + not_null entry, + FilterId filterId); void HidePinnedBar( not_null navigation, not_null peer, @@ -210,4 +215,6 @@ void MarkAsReadThread(not_null thread); void AddSeparatorAndShiftUp(const PeerMenuCallback &addAction); +[[nodiscard]] bool IsArchived(not_null history); + } // namespace Window