Add change color button with color sample.

This commit is contained in:
John Preston 2023-10-27 12:23:48 +04:00
parent 5d335341ab
commit 9561026cd4
9 changed files with 355 additions and 109 deletions

View File

@ -198,6 +198,8 @@ PRIVATE
boxes/peers/edit_participant_box.h
boxes/peers/edit_participants_box.cpp
boxes/peers/edit_participants_box.h
boxes/peers/edit_peer_color_box.cpp
boxes/peers/edit_peer_color_box.h
boxes/peers/edit_peer_common.h
boxes/peers/edit_peer_info_box.cpp
boxes/peers/edit_peer_info_box.h

View File

@ -402,6 +402,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_dlg_search_from" = "From: {user}";
"lng_settings_save" = "Save";
"lng_settings_apply" = "Apply";
"lng_username_title" = "Username";
"lng_username_description1" = "You can choose a username on Telegram. If you do, other people will be able to find you by this username and contact you without knowing your phone number.";
@ -770,11 +771,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_clear_payment_info_clear" = "Clear";
"lng_clear_payment_info_confirm" = "Delete your shipping info and instruct all payment providers to remove your saved credit cards? Note that Telegram never stores your credit card data.";
"lng_settings_theme_settings" = "Theme settings";
"lng_settings_theme_name_color" = "Your name color";
"lng_settings_auto_night_mode" = "Auto-Night mode";
"lng_settings_auto_night_enabled" = "Match the system settings";
"lng_settings_auto_night_mode_off" = "Off";
"lng_settings_auto_night_mode_on" = "System";
"lng_settings_auto_night_warning" = "You have enabled auto-night mode. If you want to change the dark mode settings, you'll need to disable it first.";
"lng_settings_auto_night_disable" = "Disable";
"lng_settings_color_title" = "Color preview";
"lng_settings_color_reply" = "Reply to your message";
"lng_settings_color_reply_channel" = "Reply to your channel message";
"lng_settings_color_text" = "Your name and replies to your messages will be shown in the selected color.";
"lng_settings_color_text_channel" = "The name of the channel and replies to its messages will be shown in the selected color.";
"lng_settings_color_link_name" = "Telegram";
"lng_settings_color_link_title" = "Link Preview";
"lng_settings_color_link_description" = "Your selected color will also tint the link preview.";
"lng_settings_color_about" = "You can choose a color to tint your name, the links you send, and replies to your messages.";
"lng_settings_color_about_channel" = "You can choose a color to tint your channel's name, the links it sends, and replies to its messages.";
"lng_settings_color_emoji" = "Add icons to replies";
"lng_settings_color_emoji_off" = "Off";
"lng_settings_color_emoji_about" = "Make replies to your messages stand out by adding custom patterns to them.";
"lng_settings_color_emoji_about_channel" = "Make replies to your channel's messages stand out by adding custom patterns to them.";
"lng_settings_color_subscribe" = "Subscribe to {link} to choose a custom color for your name.";
"lng_suggest_hide_new_title" = "Hide new chats?";
"lng_suggest_hide_new_about" = "You are receiving lots of new chats from users who are not in your Contact List.\n\nDo you want to have such chats **automatically muted** and **archived**?";
"lng_suggest_hide_new_to_settings" = "Go to Settings";
@ -802,7 +822,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_background_text1" = "Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff!";
"lng_background_text2" = "I can't even take you seriously right now.";
"lng_background_bad_link" = "This background link appears to be invalid.";
"lng_background_apply" = "Apply";
"lng_background_share" = "Share";
"lng_background_link_copied" = "Link copied to clipboard";
"lng_background_blur" = "Blurred";
@ -2035,6 +2054,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_boost_now_instead" = "You currently boost {channel}. Do you want to boost {other} instead?";
"lng_boost_now_replace" = "Replace";
"lng_boost_channel_title_color" = "Enable colors";
"lng_boost_channel_needs_level_color#one" = "Your channel needs to reach **Level {count}** to change channel color.";
"lng_boost_channel_needs_level_color#other" = "Your channel needs to reach **Level {count}** to change channel color.";
"lng_boost_channel_ask" = "Ask your **Premium** subscribers to boost your channel with this link:";
"lng_boost_channel_ask_button" = "Copy Link";
"lng_boost_channel_or" = "or";
"lng_boost_channel_gifting" = "Boost your channel by gifting your subscribers Telegram Premium. {link}";
"lng_boost_channel_gifting_link" = "Get boosts >";
"lng_giveaway_new_title" = "Boosts via Gifts";
"lng_giveaway_new_about" = "Get more boosts for your channel by gifting Premium to your subscribers.";
"lng_giveaway_create_option" = "Create Giveaway";
@ -2675,6 +2703,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_bot_title" = "Edit bot";
"lng_edit_sign_messages" = "Sign messages";
"lng_edit_group" = "Edit group";
"lng_edit_channel_color" = "Change name color";
"lng_edit_self_title" = "Edit your name";
"lng_confirm_contact_data" = "New Contact";
"lng_add_contact" = "Create";

View File

@ -435,7 +435,7 @@ void BackgroundPreviewBox::rebuildButtons(bool dark) {
clearButtons();
addButton(_forPeer
? tr::lng_background_apply_button()
: tr::lng_background_apply(), [=] { apply(); });
: tr::lng_settings_apply(), [=] { apply(); });
addButton(tr::lng_cancel(), [=] { closeBox(); });
if (!_forPeer && _paper.hasShareUrl()) {
addLeftButton(tr::lng_background_share(), [=] { share(); });

View File

@ -0,0 +1,200 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/peers/edit_peer_color_box.h"
#include "data/data_changes.h"
#include "data/data_peer.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "settings/settings_common.h"
#include "ui/chat/chat_style.h"
#include "ui/widgets/buttons.h"
#include "ui/painter.h"
#include "styles/style_menu_icons.h"
#include "styles/style_settings.h"
#include "styles/style_widgets.h"
namespace {
using namespace Settings;
class ColorSample final : public Ui::RpWidget {
public:
ColorSample(
not_null<QWidget*> parent,
std::shared_ptr<Ui::ChatStyle> st,
rpl::producer<uint8> colorIndex,
const QString &name);
int naturalWidth() const override;
private:
void paintEvent(QPaintEvent *e) override;
std::shared_ptr<Ui::ChatStyle> _st;
Ui::Text::String _name;
uint8 _index = 0;
};
ColorSample::ColorSample(
not_null<QWidget*> parent,
std::shared_ptr<Ui::ChatStyle> st,
rpl::producer<uint8> colorIndex,
const QString &name)
: RpWidget(parent)
, _st(st)
, _name(st::semiboldTextStyle, name) {
std::move(
colorIndex
) | rpl::start_with_next([=](uint8 index) {
_index = index;
update();
}, lifetime());
}
void ColorSample::paintEvent(QPaintEvent *e) {
auto p = Painter(this);
auto hq = PainterHighQualityEnabler(p);
const auto colors = _st->coloredValues(false, _index);
if (!colors.outlines[1].alpha()) {
const auto radius = height() / 2;
p.setPen(Qt::NoPen);
p.setBrush(colors.bg);
p.drawRoundedRect(rect(), radius, radius);
const auto padding = st::settingsColorSamplePadding;
p.setPen(colors.name);
p.setBrush(Qt::NoBrush);
p.setFont(st::semiboldFont);
_name.drawLeftElided(
p,
padding.left(),
padding.top(),
width() - padding.left() - padding.right(),
width(),
1,
style::al_top);
} else {
const auto size = width();
const auto half = size / 2.;
p.translate(size / 2., size / 2.);
p.rotate(-45.);
p.setPen(Qt::NoPen);
p.setClipRect(-size, -size, 3 * size, size);
p.setBrush(colors.outlines[0]);
p.drawEllipse(-half, -half, size, size);
p.setClipRect(-size, 0, 3 * size, size);
p.setBrush(colors.outlines[1]);
p.drawEllipse(-half, -half, size, size);
if (colors.outlines[2].alpha()) {
const auto center = st::settingsColorSampleCenter;
const auto radius = st::settingsColorSampleCenterRadius;
p.setClipping(false);
p.setBrush(colors.outlines[2]);
p.drawRoundedRect(
QRectF(-center / 2., -center / 2., center, center),
radius,
radius);
}
}
}
int ColorSample::naturalWidth() const {
if (_st->colorPatternIndex(_index)) {
return st::settingsColorSampleSize;
}
const auto padding = st::settingsColorSamplePadding;
return std::max(
padding.left() + _name.maxWidth() + padding.right(),
padding.top() + st::semiboldFont->height + padding.bottom());
}
} // namespace
void EditPeerColorBox(
not_null<Ui::GenericBox*> box,
std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer,
std::shared_ptr<Ui::ChatStyle> st) {
}
void AddPeerColorButton(
not_null<Ui::VerticalLayout*> container,
std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer) {
const auto button = AddButton(
container,
(peer->isSelf()
? tr::lng_settings_theme_name_color()
: tr::lng_edit_channel_color()),
st::settingsColorButton,
{ &st::menuIconChangeColors });
auto colorIndexValue = peer->session().changes().peerFlagsValue(
peer,
Data::PeerUpdate::Flag::Color
) | rpl::map([=] {
return peer->colorIndex();
});
const auto name = peer->shortName();
const auto st = std::make_shared<Ui::ChatStyle>(
peer->session().colorIndicesValue());
const auto sample = Ui::CreateChild<ColorSample>(
button.get(),
st,
rpl::duplicate(colorIndexValue),
name);
sample->show();
rpl::combine(
button->widthValue(),
tr::lng_settings_theme_name_color(),
rpl::duplicate(colorIndexValue)
) | rpl::start_with_next([=](
int width,
const QString &button,
int colorIndex) {
const auto sampleSize = st::settingsColorSampleSize;
const auto available = width
- st::settingsButton.padding.left()
- (st::settingsColorButton.padding.right() - sampleSize)
- st::settingsButton.style.font->width(button)
- st::settingsButtonRightSkip;
if (st->colorPatternIndex(colorIndex)) {
sample->resize(sampleSize, sampleSize);
} else {
const auto padding = st::settingsColorSamplePadding;
const auto wantedHeight = padding.top()
+ st::semiboldFont->height
+ padding.bottom();
const auto wantedWidth = sample->naturalWidth();
sample->resize(std::min(wantedWidth, available), wantedHeight);
}
sample->update();
}, sample->lifetime());
rpl::combine(
button->sizeValue(),
sample->sizeValue(),
std::move(colorIndexValue)
) | rpl::start_with_next([=](QSize outer, QSize inner, int colorIndex) {
const auto right = st::settingsColorButton.padding.right()
- st::settingsColorSampleSkip
- st::settingsColorSampleSize
- (st->colorPatternIndex(colorIndex)
? 0
: st::settingsColorSamplePadding.right());
sample->move(
outer.width() - right - inner.width(),
(outer.height() - inner.height()) / 2);
}, sample->lifetime());
sample->setAttribute(Qt::WA_TransparentForMouseEvents);
}

View File

@ -0,0 +1,29 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace ChatHelpers {
class Show;
} // namespace ChatHelpers
namespace Ui {
class GenericBox;
class ChatStyle;
class VerticalLayout;
} // namespace Ui
void EditPeerColorBox(
not_null<Ui::GenericBox*> box,
std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer,
std::shared_ptr<Ui::ChatStyle> st = nullptr);
void AddPeerColorButton(
not_null<Ui::VerticalLayout*> container,
std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer);

View File

@ -13,8 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "boxes/add_contact_box.h"
#include "ui/boxes/confirm_box.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/peers/edit_participants_box.h"
#include "boxes/peers/edit_peer_color_box.h"
#include "boxes/peers/edit_peer_common.h"
#include "boxes/peers/edit_peer_type_box.h"
#include "boxes/peers/edit_peer_history_visibility_box.h"
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_linked_chat_box.h"
#include "boxes/peers/edit_peer_requests_box.h"
#include "boxes/peers/edit_peer_reactions.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/stickers_box.h"
#include "boxes/username_box.h"
#include "ui/boxes/single_choice_box.h"
@ -302,6 +303,7 @@ private:
void fillLinkedChatButton();
//void fillInviteLinkButton();
void fillForumButton();
void fillColorIndexButton();
void fillSignaturesButton();
void fillHistoryVisibilityButton();
void fillManageSection();
@ -905,6 +907,13 @@ void Controller::refreshForumToggleLocked() {
_controls.forumToggle->setToggleLocked(locked);
}
void Controller::fillColorIndexButton() {
Expects(_controls.buttonsLayout != nullptr);
const auto show = _navigation->uiShow();
AddPeerColorButton(_controls.buttonsLayout, show, _peer);
}
void Controller::fillSignaturesButton() {
Expects(_controls.buttonsLayout != nullptr);
@ -1024,74 +1033,42 @@ void Controller::fillManageSection() {
return;
}
const auto canEditType = [&] {
return isChannel
? channel->amCreator()
: chat->amCreator();
}();
const auto canEditSignatures = [&] {
return isChannel
? (channel->canEditSignatures() && !channel->isMegagroup())
: false;
}();
const auto canEditPreHistoryHidden = [&] {
return isChannel
? channel->canEditPreHistoryHidden()
: chat->canEditPreHistoryHidden();
}();
const auto canEditType = isChannel
? channel->amCreator()
: chat->amCreator();
const auto canEditSignatures = isChannel
&& channel->canEditSignatures()
&& !channel->isMegagroup();
const auto canEditPreHistoryHidden = isChannel
? channel->canEditPreHistoryHidden()
: chat->canEditPreHistoryHidden();
const auto canEditForum = isChannel
? (channel->isMegagroup() && channel->amCreator())
: chat->amCreator();
const auto canEditPermissions = [&] {
return isChannel
? channel->canEditPermissions()
: chat->canEditPermissions();
}();
const auto canEditInviteLinks = [&] {
return isChannel
? channel->canHaveInviteLink()
: chat->canHaveInviteLink();
}();
const auto canViewAdmins = [&] {
return isChannel
? channel->canViewAdmins()
: chat->amIn();
}();
const auto canViewMembers = [&] {
return isChannel
? channel->canViewMembers()
: chat->amIn();
}();
const auto canViewKicked = [&] {
return isChannel
? (channel->isBroadcast() || channel->isGigagroup())
: false;
}();
const auto hasRecentActions = [&] {
return isChannel
? (channel->hasAdminRights() || channel->amCreator())
: false;
}();
const auto canEditStickers = [&] {
return isChannel
? channel->canEditStickers()
: false;
}();
const auto canDeleteChannel = [&] {
return isChannel
? channel->canDelete()
: false;
}();
const auto canViewOrEditLinkedChat = [&] {
return !isChannel
? false
: channel->linkedChat()
? true
: (channel->isBroadcast() && channel->canEditInformation());
}();
const auto canEditPermissions = isChannel
? channel->canEditPermissions()
: chat->canEditPermissions();
const auto canEditInviteLinks = isChannel
? channel->canHaveInviteLink()
: chat->canHaveInviteLink();
const auto canViewAdmins = isChannel
? channel->canViewAdmins()
: chat->amIn();
const auto canViewMembers = isChannel
? channel->canViewMembers()
: chat->amIn();
const auto canViewKicked = isChannel
&& (channel->isBroadcast() || channel->isGigagroup());
const auto hasRecentActions = isChannel
&& (channel->hasAdminRights() || channel->amCreator());
const auto canEditStickers = isChannel && channel->canEditStickers();
const auto canDeleteChannel = isChannel && channel->canDelete();
const auto canEditColorIndex = isChannel
&& !channel->isMegagroup()
&& channel->canEditInformation();
const auto canViewOrEditLinkedChat = isChannel
&& (channel->linkedChat()
|| (channel->isBroadcast() && channel->canEditInformation()));
AddSkip(_controls.buttonsLayout, 0);
@ -1109,11 +1086,15 @@ void Controller::fillManageSection() {
if (canEditForum) {
fillForumButton();
}
if (canEditColorIndex) {
fillColorIndexButton();
}
if (canEditSignatures) {
fillSignaturesButton();
}
if (canEditPreHistoryHidden
|| canEditForum
|| canEditColorIndex
|| canEditSignatures
//|| canEditInviteLinks
|| canViewOrEditLinkedChat

View File

@ -565,3 +565,12 @@ filterLinkSubsectionTitlePadding: margins(0px, 5px, 0px, -4px);
filterLinkChatsList: PeerList(peerListBox) {
padding: margins(0px, 0px, 0px, membersMarginBottom);
}
settingsColorSampleSize: 20px;
settingsColorSampleCenter: 8px;
settingsColorSampleCenterRadius: 2px;
settingsColorSamplePadding: margins(8px, 2px, 8px, 2px);
settingsColorSampleSkip: 6px;
settingsColorButton: SettingsButton(settingsButton) {
padding: margins(60px, 10px, 48px, 10px);
}

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_common.h"
#include "settings/settings_advanced.h"
#include "settings/settings_experimental.h"
#include "boxes/peers/edit_peer_color_box.h"
#include "boxes/connection_box.h"
#include "boxes/auto_download_box.h"
#include "boxes/reactions_settings_box.h"
@ -27,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/chat/attach/attach_extensions.h"
#include "ui/chat/chat_style.h"
#include "ui/chat/chat_theme.h"
#include "ui/layers/generic_box.h"
#include "ui/effects/radial_animation.h"
@ -55,6 +57,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_origin.h"
#include "data/data_message_reactions.h"
#include "data/data_peer_values.h"
#include "data/data_user.h"
#include "chat_helpers/emoji_sets_manager.h"
#include "base/platform/base_platform_info.h"
#include "platform/platform_specific.h"
@ -1561,51 +1564,44 @@ void SetupCloudThemes(
wrap->setDuration(0)->toggleOn(list->empty() | rpl::map(!_1));
}
void SetupAutoNightMode(
void SetupThemeSettings(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
if (!Core::App().settings().systemDarkMode().has_value()) {
return;
}
AddDivider(container);
AddSkip(container, st::settingsPrivacySkip);
AddSubsectionTitle(container, tr::lng_settings_auto_night_mode());
AddSubsectionTitle(container, tr::lng_settings_theme_settings());
auto wrap = object_ptr<Ui::VerticalLayout>(container);
const auto autoNight = wrap->add(
object_ptr<Ui::Checkbox>(
wrap,
tr::lng_settings_auto_night_enabled(tr::now),
Core::App().settings().systemDarkModeEnabled(),
st::settingsCheckbox),
st::settingsCheckboxPadding);
autoNight->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked != Core::App().settings().systemDarkModeEnabled());
}) | rpl::start_with_next([=](bool checked) {
if (checked && Window::Theme::Background()->editingTheme()) {
autoNight->setChecked(false);
controller->show(Ui::MakeInformBox(
tr::lng_theme_editor_cant_change_theme()));
} else {
Core::App().settings().setSystemDarkModeEnabled(checked);
Core::App().saveSettingsDelayed();
}
}, autoNight->lifetime());
Core::App().settings().systemDarkModeEnabledChanges(
) | rpl::filter([=](bool value) {
return (value != autoNight->checked());
}) | rpl::start_with_next([=](bool value) {
autoNight->setChecked(value);
}, autoNight->lifetime());
container->add(object_ptr<Ui::OverrideMargins>(
AddPeerColorButton(
container,
std::move(wrap)));
controller->uiShow(),
controller->session().user());
const auto settings = &Core::App().settings();
if (settings->systemDarkMode().has_value()) {
auto label = settings->systemDarkModeEnabledValue(
) | rpl::map([=](bool enabled) {
return enabled
? tr::lng_settings_auto_night_mode_on()
: tr::lng_settings_auto_night_mode_off();
}) | rpl::flatten_latest();
AddButtonWithLabel(
container,
tr::lng_settings_auto_night_mode(),
std::move(label),
st::settingsButton,
{ &st::menuIconNightMode }
)->setClickedCallback([=] {
const auto now = !settings->systemDarkModeEnabled();
if (now && Window::Theme::Background()->editingTheme()) {
controller->show(Ui::MakeInformBox(
tr::lng_theme_editor_cant_change_theme()));
} else {
settings->setSystemDarkModeEnabled(now);
Core::App().saveSettingsDelayed();
}
});
}
AddSkip(container, st::settingsCheckboxesSkip);
}
@ -1749,7 +1745,7 @@ void Chat::setupContent(not_null<Window::SessionController*> controller) {
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
SetupThemeOptions(controller, content);
SetupAutoNightMode(controller, content);
SetupThemeSettings(controller, content);
SetupCloudThemes(controller, content);
SetupChatBackground(controller, content);
SetupStickersEmoji(controller, content);

View File

@ -377,7 +377,7 @@ void GlobalTTL::setupContent() {
auto controller = std::make_unique<TTLChatsBoxController>(session);
auto initBox = [=, controller = controller.get()](
not_null<PeerListBox*> box) {
box->addButton(tr::lng_background_apply(), crl::guard(this, [=] {
box->addButton(tr::lng_settings_apply(), crl::guard(this, [=] {
const auto &peers = box->collectSelectedRows();
if (peers.empty()) {
return;