Added implementation for all swipe dialog actions.

This commit is contained in:
23rd 2025-03-16 23:37:37 +03:00
parent b95035e7a2
commit d7a89ef122
8 changed files with 226 additions and 78 deletions

View file

@ -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),

View file

@ -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<Window::SessionController*> controller,
not_null<PeerData*> 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<TimeId>::max());
const auto isMuted = rpl::variable<bool>(
MuteMenu::ThreadDescriptor(history).isMutedValue()).current();
MuteMenu::ThreadDescriptor(history).updateMutePeriod(isMuted
? 0
: std::numeric_limits<TimeId>::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<PeerData*> peer,
Ui::SwipeDialogAction action,
FilterId filterId) {
if (action == Dialogs::Ui::SwipeDialogAction::Mute) {
const auto history = peer->owner().history(peer);
const auto isMuted = rpl::variable<bool>(
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*> history,
Ui::SwipeDialogAction action,
FilterId filterId) {
if (action == Dialogs::Ui::SwipeDialogAction::Mute) {
const auto isMuted = rpl::variable<bool>(
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

View file

@ -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<Window::SessionController*> controller,
not_null<PeerData*> peer,
Ui::SwipeDialogAction action);
Ui::SwipeDialogAction action,
FilterId filterId);
[[nodiscard]] QString ResolveSwipeDialogLottieIconName(
not_null<PeerData*> peer,
Ui::SwipeDialogAction action,
FilterId filterId);
[[nodiscard]] Ui::SwipeDialogActionLabel ResolveSwipeDialogLabel(
not_null<History*> history,
Ui::SwipeDialogAction action,
FilterId filterId);
[[nodiscard]] QString ResolveSwipeDialogLabel(Ui::SwipeDialogActionLabel);
} // namespace Dialogs

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -438,40 +438,6 @@ void TogglePinnedThread(
}
}
void TogglePinnedThread(
not_null<Window::SessionController*> controller,
not_null<Dialogs::Entry*> 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<SessionController*> 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<Window::SessionController*> controller,
not_null<Dialogs::Entry*> 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*> history) {
return (history->folder() != nullptr);
}
} // namespace Window

View file

@ -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<Window::SessionNavigation*> navigation,
FullMsgId itemId,
bool pin);
void TogglePinnedThread(
not_null<Window::SessionController*> controller,
not_null<Dialogs::Entry*> entry,
FilterId filterId);
void HidePinnedBar(
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer,
@ -210,4 +215,6 @@ void MarkAsReadThread(not_null<Data::Thread*> thread);
void AddSeparatorAndShiftUp(const PeerMenuCallback &addAction);
[[nodiscard]] bool IsArchived(not_null<History*> history);
} // namespace Window