Slightly improved style of settings for quick dialog action.

This commit is contained in:
23rd 2025-03-21 21:01:31 +03:00
parent 28c125a3ec
commit 2be76760de
5 changed files with 199 additions and 12 deletions

View file

@ -1182,6 +1182,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_quick_dialog_action_title" = "Chat list quick action";
"lng_settings_quick_dialog_action_about" = "Choose the action you want to perform when you middle-click or swipe left in the chat list.";
"lng_settings_quick_dialog_action_both" = "Swipe left and Middle-click";
"lng_settings_quick_dialog_action_swipe" = "Swipe left";
"lng_settings_quick_dialog_action_mute" = "Mute";
"lng_settings_quick_dialog_action_unmute" = "Unmute";
"lng_settings_quick_dialog_action_pin" = "Pin";

View file

@ -213,8 +213,10 @@ void DrawQuickAction(
QPainter &p,
const QRect &rect,
not_null<Lottie::Icon*> icon,
Ui::QuickDialogActionLabel label) {
const auto iconSize = st::dialogsQuickActionSize;
Ui::QuickDialogActionLabel label,
float64 iconRatio,
bool twoLines) {
const auto iconSize = st::dialogsQuickActionSize * iconRatio;
const auto innerHeight = iconSize * 2;
const auto top = (rect.height() - innerHeight) / 2;
icon->paint(p, rect.x() + (rect.width() - iconSize) / 2, top);
@ -222,10 +224,22 @@ void DrawQuickAction(
p.setBrush(Qt::NoBrush);
const auto availableWidth = rect.width();
p.setFont(SwipeActionFont(label, availableWidth));
if (twoLines) {
auto text = ResolveQuickDialogLabel(label);
const auto index = text.indexOf(' ');
if (index != -1) {
text = text.replace(index, 1, '\n');
}
p.drawText(
QRect(rect.x(), top, availableWidth, innerHeight),
std::move(text),
style::al_bottom);
} else {
p.drawText(
QRect(rect.x(), top, availableWidth, innerHeight),
ResolveQuickDialogLabel(label),
style::al_bottom);
}
}
} // namespace Dialogs

View file

@ -50,6 +50,8 @@ void DrawQuickAction(
QPainter &p,
const QRect &rect,
not_null<Lottie::Icon*> icon,
Ui::QuickDialogActionLabel label);
Ui::QuickDialogActionLabel label,
float64 iconRatio = 1.,
bool twoLines = false);
} // namespace Dialogs

View file

@ -682,3 +682,5 @@ settingsChatLinkField: InputField(defaultInputField) {
style: defaultTextStyle;
}
settingsQuickDialogActionsTriggerFont: font(11px);

View file

@ -23,6 +23,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/background_preview_box.h"
#include "boxes/download_path_box.h"
#include "boxes/local_storage_box.h"
#include "dialogs/ui/dialogs_quick_action_context.h"
#include "dialogs/dialogs_quick_action.h"
#include "ui/boxes/choose_font_box.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h"
@ -39,11 +41,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h"
#include "ui/image/image.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/vertical_list.h"
#include "ui/ui_utility.h"
#include "ui/widgets/menu/menu_add_action_callback.h"
#include "history/view/history_view_quick_action.h"
#include "lang/lang_keys.h"
#include "lottie/lottie_icon.h"
#include "export/export_manager.h"
#include "window/themes/window_theme.h"
#include "window/themes/window_themes_embedded.h"
@ -76,6 +80,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_layers.h"
#include "styles/style_menu_icons.h"
#include "styles/style_window.h"
#include "styles/style_dialogs.h"
namespace Settings {
namespace {
@ -1272,7 +1277,7 @@ void SetupChatBackground(
}, adaptive->lifetime());
}
void SetupChatListSwipe(
void SetupChatListQuickAction(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
Ui::AddDivider(container);
@ -1282,13 +1287,141 @@ void SetupChatListSwipe(
tr::lng_settings_quick_dialog_action_title());
using Type = Dialogs::Ui::QuickDialogAction;
using LabelType = Dialogs::Ui::QuickDialogActionLabel;
const auto group = std::make_shared<Ui::RadioenumGroup<Type>>(
Core::App().settings().quickDialogAction());
group->setChangedCallback([=](Type value) {
Core::App().settings().setQuickDialogAction(value);
Core::App().saveSettings();
});
container->add(
const auto actionToLabel = [](Type value) {
switch (value) {
case Type::Mute: return LabelType::Mute;
case Type::Pin: return LabelType::Pin;
case Type::Read: return LabelType::Read;
case Type::Archive: return LabelType::Archive;
case Type::Delete: return LabelType::Delete;
default: return LabelType::Disabled;
}
};
static constexpr auto kDisabledIconRatio = 1.25;
const auto addPreview = [=](not_null<Ui::VerticalLayout*> container) {
const auto widget = container->add(
object_ptr<Ui::RpWidget>(container));
widget->resize(0, st::dialogsRowHeight);
struct State {
std::unique_ptr<Lottie::Icon> icon;
};
const auto state = widget->lifetime().make_state<State>();
group->value() | rpl::start_with_next([=](Type value) {
const auto label = actionToLabel(value);
state->icon = Lottie::MakeIcon({
.name = Dialogs::ResolveQuickDialogLottieIconName(label),
.sizeOverride = Size((label == LabelType::Disabled)
? int(st::dialogsQuickActionSize * kDisabledIconRatio)
: st::dialogsQuickActionSize),
});
state->icon->animate(
[=] { widget->update(); },
0,
state->icon->framesCount() - 1);
widget->update();
}, widget->lifetime());
widget->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(widget);
const auto height = st::dialogsRowHeight;
const auto actionWidth = st::dialogsQuickActionRippleSize * 0.75;
const auto rightOffset = st::dialogsQuickActionRippleSize
+ st::dialogsQuickActionSize;
const auto rect = QRect(
widget->width()
- actionWidth
- st::boxRowPadding.right()
- rightOffset,
0,
actionWidth,
height);
auto path = QPainterPath();
path.addRoundedRect(
QRect(
-actionWidth,
0,
rect::right(rect) + actionWidth,
height),
st::roundRadiusLarge,
st::roundRadiusLarge);
p.setClipPath(path);
const auto label = actionToLabel(group->current());
const auto isDisabled = (label == LabelType::Disabled);
auto hq = PainterHighQualityEnabler(p);
p.fillRect(
QRect(0, 0, rect::right(rect), st::lineWidth),
st::windowBgOver);
p.fillRect(
QRect(
0,
rect::bottom(rect) - st::lineWidth,
rect::right(rect),
st::lineWidth),
st::windowBgOver);
p.fillRect(rect, Dialogs::ResolveQuickActionBg(label));
if (state->icon) {
Dialogs::DrawQuickAction(
p,
rect,
state->icon.get(),
label,
isDisabled ? kDisabledIconRatio : 1.,
isDisabled);
}
p.translate(-height / 2, 0);
p.setPen(Qt::NoPen);
p.setBrush(st::windowBgOver);
p.drawEllipse(Rect(Size(height)) - Margins(height / 6));
const auto h = st::normalFont->ascent / 1.5;
p.drawRoundedRect(
height,
height / 2 - h * 1.5,
st::dialogsQuickActionRippleSize * 0.6,
h,
h / 2,
h / 2);
p.drawRoundedRect(
height,
height / 2 + h,
st::dialogsQuickActionRippleSize * 1.0,
h,
h / 2,
h / 2);
p.setClipping(false);
p.resetTransform();
p.setFont(st::settingsQuickDialogActionsTriggerFont);
p.setPen(st::windowSubTextFg);
p.drawText(
QRect(
widget->width()
- st::dialogsQuickActionRippleSize
- st::boxRowPadding.right(),
0,
st::dialogsQuickActionRippleSize,
height),
isDisabled
? tr::lng_settings_quick_dialog_action_swipe(tr::now)
: tr::lng_settings_quick_dialog_action_both(tr::now),
style::al_center);
}, widget->lifetime());
};
const auto &st = st::settingsButton;
const auto button = container->add(
object_ptr<Ui::SettingsButton>(
container,
group->value() | rpl::map([](Type value) {
@ -1302,8 +1435,39 @@ void SetupChatListSwipe(
? tr::lng_settings_quick_dialog_action_archive
: tr::lng_settings_quick_dialog_action_disabled)();
}) | rpl::flatten_latest(),
st::settingsButtonNoIcon)
)->setClickedCallback([=] {
st));
{
const auto icon = button->lifetime().make_state<Ui::RpWidget>(button);
icon->setAttribute(Qt::WA_TransparentForMouseEvents);
icon->resize(st::menuIconArchive.size());
icon->show();
button->sizeValue(
) | rpl::start_with_next([=, left = st.iconLeft](QSize size) {
icon->moveToLeft(
left,
(size.height() - icon->height()) / 2,
size.width());
}, icon->lifetime());
icon->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(icon);
const auto value = group->current();
((value == Dialogs::Ui::QuickDialogAction::Mute)
? st::menuIconMute
: (value == Dialogs::Ui::QuickDialogAction::Pin)
? st::menuIconPin
: (value == Dialogs::Ui::QuickDialogAction::Read)
? st::menuIconMarkRead
: (value == Dialogs::Ui::QuickDialogAction::Delete)
? st::menuIconDelete
: (value == Dialogs::Ui::QuickDialogAction::Archive)
? st::menuIconArchive
: st::menuIconShowInFolder).paintInCenter(p, icon->rect());
}, icon->lifetime());
}
button->setClickedCallback([=] {
controller->uiShow()->showBox(Box([=](not_null<Ui::GenericBox*> box) {
box->setTitle(tr::lng_settings_quick_dialog_action_title());
const auto addRadio = [&](Type value, tr::phrase<> phrase) {
@ -1316,6 +1480,9 @@ void SetupChatListSwipe(
st::settingsSendType),
st::settingsSendTypePadding);
};
addPreview(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
addRadio(Type::Mute, tr::lng_settings_quick_dialog_action_mute);
addRadio(Type::Pin, tr::lng_settings_quick_dialog_action_pin);
addRadio(Type::Read, tr::lng_settings_quick_dialog_action_read);
@ -1868,7 +2035,7 @@ void Chat::setupContent(not_null<Window::SessionController*> controller) {
SetupThemeSettings(controller, content);
SetupCloudThemes(controller, content);
SetupChatBackground(controller, content);
SetupChatListSwipe(controller, content);
SetupChatListQuickAction(controller, content);
SetupStickersEmoji(controller, content);
SetupMessages(controller, content);
Ui::AddDivider(content);