Allow setting background for both sides.

This commit is contained in:
John Preston 2023-11-28 18:29:29 +04:00
parent e58940a876
commit 8c3fa14a75
13 changed files with 245 additions and 23 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

View File

@ -839,6 +839,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_background_dimming" = "Background dimming";
"lng_background_sure_reset_default" = "Are you sure you want to reset the wallpaper?";
"lng_background_reset_default" = "Reset";
"lng_background_apply_me" = "Apply for me";
"lng_background_apply_both" = "Apply for me and {user}";
"lng_download_path_ask" = "Ask download path for each file";
"lng_download_path" = "Download path";

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/background_preview_box.h"
#include "base/unixtime.h"
#include "boxes/premium_preview_box.h"
#include "lang/lang_keys.h"
#include "mainwidget.h"
#include "window/themes/window_theme.h"
@ -18,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/continuous_sliders.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/painter.h"
#include "ui/vertical_list.h"
@ -34,12 +37,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_media.h"
#include "data/data_document_resolver.h"
#include "data/data_file_origin.h"
#include "base/unixtime.h"
#include "boxes/background_preview_box.h"
#include "window/window_session_controller.h"
#include "window/themes/window_themes_embedded.h"
#include "data/data_peer_values.h"
#include "settings/settings_premium.h"
#include "storage/file_upload.h"
#include "storage/localimageloader.h"
#include "window/window_session_controller.h"
#include "window/themes/window_themes_embedded.h"
#include "styles/style_chat.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
@ -509,6 +512,10 @@ void BackgroundPreviewBox::recreateBlurCheckbox() {
}, _blur->lifetime());
_blur->setDisabled(_paper.document() && _full.isNull());
if (_forBothOverlay) {
_forBothOverlay->raise();
}
}
void BackgroundPreviewBox::apply() {
@ -519,7 +526,7 @@ void BackgroundPreviewBox::apply() {
}
}
void BackgroundPreviewBox::uploadForPeer() {
void BackgroundPreviewBox::uploadForPeer(bool both) {
Expects(_forPeer != nullptr);
if (_uploadId) {
@ -578,7 +585,7 @@ void BackgroundPreviewBox::uploadForPeer() {
"Got wallPaperNoFile after account.UploadWallPaper."));
});
if (const auto paper = Data::WallPaper::Create(session, result)) {
setExistingForPeer(*paper);
setExistingForPeer(*paper, both);
}
}).send();
}, _uploadLifetime);
@ -587,7 +594,9 @@ void BackgroundPreviewBox::uploadForPeer() {
_radial.start(_uploadProgress);
}
void BackgroundPreviewBox::setExistingForPeer(const Data::WallPaper &paper) {
void BackgroundPreviewBox::setExistingForPeer(
const Data::WallPaper &paper,
bool both) {
Expects(_forPeer != nullptr);
if (const auto already = _forPeer->wallPaper()) {
@ -601,6 +610,7 @@ void BackgroundPreviewBox::setExistingForPeer(const Data::WallPaper &paper) {
api->request(MTPmessages_SetChatWallPaper(
MTP_flags((_fromMessageId ? Flag::f_id : Flag())
| (_fromMessageId ? Flag() : Flag::f_wallpaper)
| (both ? Flag::f_for_both : Flag())
| Flag::f_settings),
_forPeer->input,
paper.mtpInput(&_controller->session()),
@ -617,10 +627,117 @@ void BackgroundPreviewBox::setExistingForPeer(const Data::WallPaper &paper) {
void BackgroundPreviewBox::applyForPeer() {
Expects(_forPeer != nullptr);
if (Data::IsCustomWallPaper(_paper)) {
uploadForPeer();
if (!Data::IsCustomWallPaper(_paper)) {
if (const auto already = _forPeer->wallPaper()) {
if (already->equals(_paper)) {
_controller->finishChatThemeEdit(_forPeer);
return;
}
}
}
if (!_fromMessageId && _forPeer->session().premiumPossible()) {
if (_forBothOverlay) {
return;
}
const auto size = this->size() * style::DevicePixelRatio();
const auto bg = Images::DitherImage(
Images::BlurLargeImage(
Ui::GrabWidgetToImage(this).scaled(
size / style::ConvertScale(4),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation),
24).scaled(
size,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
_forBothOverlay = std::make_unique<Ui::FadeWrap<>>(
this,
object_ptr<Ui::RpWidget>(this));
const auto overlay = _forBothOverlay->entity();
sizeValue() | rpl::start_with_next([=](QSize size) {
_forBothOverlay->setGeometry({ QPoint(), size });
overlay->setGeometry({ QPoint(), size });
}, _forBothOverlay->lifetime());
overlay->paintRequest(
) | rpl::start_with_next([=](QRect clip) {
auto p = QPainter(overlay);
p.drawImage(0, 0, bg);
p.fillRect(clip, QColor(0, 0, 0, 64));
}, overlay->lifetime());
using namespace Ui;
const auto forMe = CreateChild<RoundButton>(
overlay,
tr::lng_background_apply_me(),
st::backgroundConfirm);
forMe->setClickedCallback([=] {
applyForPeer(false);
});
using namespace rpl::mappers;
const auto forBoth = ::Settings::CreateLockedButton(
overlay,
tr::lng_background_apply_both(
lt_user,
rpl::single(_forPeer->shortName())),
st::backgroundConfirm,
Data::AmPremiumValue(&_forPeer->session()) | rpl::map(!_1));
forBoth->setClickedCallback([=] {
if (_forPeer->session().premium()) {
applyForPeer(true);
} else {
ShowPremiumPreviewBox(
_controller->uiShow(),
PremiumPreview::AnimatedEmoji);
}
});
const auto cancel = CreateChild<RoundButton>(
overlay,
tr::lng_cancel(),
st::backgroundConfirmCancel);
cancel->setClickedCallback([=] {
const auto raw = _forBothOverlay.release();
raw->shownValue() | rpl::filter(
!rpl::mappers::_1
) | rpl::take(1) | rpl::start_with_next(crl::guard(raw, [=] {
delete raw;
}), raw->lifetime());
raw->toggle(false, anim::type::normal);
});
forMe->setTextTransform(RoundButton::TextTransform::NoTransform);
forBoth->setTextTransform(RoundButton::TextTransform::NoTransform);
cancel->setTextTransform(RoundButton::TextTransform::NoTransform);
overlay->sizeValue(
) | rpl::start_with_next([=](QSize size) {
const auto padding = st::backgroundConfirmPadding;
const auto width = size.width()
- padding.left()
- padding.right();
const auto height = cancel->height();
auto top = size.height() - padding.bottom() - height;
cancel->setGeometry(padding.left(), top, width, height);
top -= height + padding.top();
forBoth->setGeometry(padding.left(), top, width, height);
top -= height + padding.top();
forMe->setGeometry(padding.left(), top, width, height);
}, _forBothOverlay->lifetime());
_forBothOverlay->hide(anim::type::instant);
_forBothOverlay->show(anim::type::normal);
} else {
setExistingForPeer(_paper);
applyForPeer(false);
}
}
void BackgroundPreviewBox::applyForPeer(bool both) {
if (Data::IsCustomWallPaper(_paper)) {
uploadForPeer(both);
} else {
setExistingForPeer(_paper, both);
}
}

View File

@ -29,6 +29,8 @@ class ChatStyle;
class MediaSlider;
template <typename Widget>
class SlideWrap;
template <typename Widget>
class FadeWrap;
} // namespace Ui
struct BackgroundPreviewArgs {
@ -66,9 +68,10 @@ private:
void apply();
void applyForPeer();
void applyForPeer(bool both);
void applyForEveryone();
void uploadForPeer();
void setExistingForPeer(const Data::WallPaper &paper);
void uploadForPeer(bool both);
void setExistingForPeer(const Data::WallPaper &paper, bool both);
void share();
void radialAnimationCallback(crl::time now);
QRect radialRect() const;
@ -131,6 +134,8 @@ private:
float64 _uploadProgress = 0.;
rpl::lifetime _uploadLifetime;
std::unique_ptr<Ui::FadeWrap<Ui::RpWidget>> _forBothOverlay;
rpl::variable<QColor> _paletteServiceBg;
rpl::lifetime _serviceBgLifetime;

View File

@ -753,7 +753,28 @@ backgroundCheck: ServiceCheck {
color: msgServiceFg;
duration: 200;
}
backgroundConfirmPadding: margins(24px, 16px, 24px, 16px);
backgroundConfirm: RoundButton(defaultActiveButton) {
height: 44px;
textTop: 12px;
font: font(13px semibold);
}
backgroundConfirmCancel: RoundButton(backgroundConfirm) {
textFg: mediaviewSaveMsgFg;
textFgOver: mediaviewSaveMsgFg;
numbersTextFg: mediaviewSaveMsgFg;
numbersTextFgOver: mediaviewSaveMsgFg;
textBg: shadowFg;
textBgOver: shadowFg;
height: 44px;
textTop: 12px;
font: font(13px semibold);
ripple: RippleAnimation(defaultRippleAnimation) {
color: shadowFg;
}
}
urlAuthCheckbox: Checkbox(defaultBoxCheckbox) {
width: 240px;
}

View File

@ -406,6 +406,11 @@ void SimilarChannels::validateCounterBg(const Channel &channel) const {
channel.counterRect = badge.marginsAdded(
st::chatSimilarBadgePadding);
constexpr auto kMinSaturation = 0;
constexpr auto kMaxSaturation = 96;
constexpr auto kMinLightness = 160;
constexpr auto kMaxLightness = 208;
const auto width = channel.counterRect.width();
const auto height = channel.counterRect.height();
const auto ratio = style::DevicePixelRatio();
@ -413,16 +418,12 @@ void SimilarChannels::validateCounterBg(const Channel &channel) const {
channel.counterRect.size() * ratio,
QImage::Format_ARGB32_Premultiplied);
auto color = channel.more
? st::windowBgRipple->c
? QColor(kMinLightness, kMinLightness, kMinLightness)
: Ui::CountAverageColor(
channel.thumbnail->image(photo).copy(
QRect(photo / 3, photo / 3, photo / 3, photo / 3)));
const auto hsl = color.toHsl();
constexpr auto kMinSaturation = 0;
constexpr auto kMaxSaturation = 96;
constexpr auto kMinLightness = 160;
constexpr auto kMaxLightness = 208;
if (!base::in_range(hsl.saturation(), kMinSaturation, kMaxSaturation)
|| !base::in_range(hsl.lightness(), kMinLightness, kMaxLightness)) {
color = QColor::fromHsl(

View File

@ -956,7 +956,15 @@ permissionsExpandIcon: icon{{ "info/edit/expand_arrow_small", windowBoldFg }};
similarChannelsLockOverlap: 58px;
similarChannelsLockFade: 58px;
similarChannelsLock: defaultActiveButton;
similarChannelsLock: RoundButton(defaultActiveButton) {
height: 44px;
textTop: 12px;
font: font(13px semibold);
}
similarChannelsLockLabel: FlatLabel(defaultFlatLabel) {
textFg: premiumButtonFg;
style: semiboldTextStyle;
}
similarChannelsLockPadding: margins(12px, 12px, 12px, 12px);
similarChannelsLockAbout: FlatLabel(defaultFlatLabel) {
textFg: windowSubTextFg;

View File

@ -144,15 +144,16 @@ void ListController::setupUnlock() {
_unlock = Ui::CreateChild<Ui::RpWidget>(_content);
_unlock->show();
const auto button = Ui::CreateChild<Ui::RoundButton>(
const auto button = ::Settings::CreateLockedButton(
_unlock,
tr::lng_similar_channels_show_more(),
st::similarChannelsLock);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
st::similarChannelsLock,
rpl::single(true));
button->setClickedCallback([=] {
const auto window = _controller->parentController();
::Settings::ShowPremium(window, u"similar_channels"_q);
});
const auto upto = Data::PremiumLimits(
&_channel->session()).similarChannelsPremium();
const auto about = Ui::CreateChild<Ui::FlatLabel>(

View File

@ -56,6 +56,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h"
#include "apiwrap.h"
#include "api/api_premium.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_premium.h"
#include "styles/style_info.h"
#include "styles/style_layers.h"
@ -1497,6 +1498,60 @@ void ShowPremiumPromoToast(
});
}
not_null<Ui::RoundButton*> CreateLockedButton(
not_null<QWidget*> parent,
rpl::producer<QString> text,
const style::RoundButton &st,
rpl::producer<bool> locked) {
const auto result = Ui::CreateChild<Ui::RoundButton>(
parent.get(),
rpl::single(QString()),
st);
const auto labelSt = result->lifetime().make_state<style::FlatLabel>(
st::defaultFlatLabel);
labelSt->style.font = st.font;
labelSt->textFg = st.textFg;
const auto label = Ui::CreateChild<Ui::FlatLabel>(
result,
std::move(text),
*labelSt);
label->setAttribute(Qt::WA_TransparentForMouseEvents);
const auto icon = Ui::CreateChild<Ui::RpWidget>(result);
icon->setAttribute(Qt::WA_TransparentForMouseEvents);
icon->resize(st::stickersPremiumLock.size());
icon->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(icon);
st::stickersPremiumLock.paint(p, 0, 0, icon->width());
}, icon->lifetime());
rpl::combine(
result->widthValue(),
label->widthValue(),
std::move(locked)
) | rpl::start_with_next([=](int outer, int inner, bool locked) {
if (locked) {
icon->show();
inner += icon->width();
label->move(
(outer - inner) / 2 + icon->width(),
st::similarChannelsLock.textTop);
icon->move(
(outer - inner) / 2,
st::similarChannelsLock.textTop);
} else {
icon->hide();
label->move(
(outer - inner) / 2,
st::similarChannelsLock.textTop);
}
}, result->lifetime());
return result;
}
not_null<Ui::GradientButton*> CreateSubscribeButton(
SubscribeButtonArgs &&args) {
Expects(args.show || args.controller);

View File

@ -11,12 +11,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
enum class PremiumPreview;
namespace style {
struct RoundButton;
} // namespace style
namespace ChatHelpers {
class Show;
} // namespace ChatHelpers
namespace Ui {
class RpWidget;
class RoundButton;
class GradientButton;
} // namespace Ui
@ -66,6 +71,13 @@ struct SubscribeButtonArgs final {
std::shared_ptr<ChatHelpers::Show> show;
};
[[nodiscard]] not_null<Ui::RoundButton*> CreateLockedButton(
not_null<QWidget*> parent,
rpl::producer<QString> text,
const style::RoundButton &st,
rpl::producer<bool> locked);
[[nodiscard]] not_null<Ui::GradientButton*> CreateSubscribeButton(
SubscribeButtonArgs &&args);

View File

@ -991,8 +991,8 @@ chatSimilarBadgePadding: margins(2px, 0px, 3px, 1px);
chatSimilarBadgeTop: 43px;
chatSimilarBadgeIcon: icon{{ "chat/mini_subscribers", premiumButtonFg }};
chatSimilarBadgeIconPosition: point(0px, 1px);
chatSimilarLockedIcon: icon{{ "emoji/premium_lock", premiumButtonFg }};
chatSimilarLockedIconPosition: point(0px, -1px);
chatSimilarLockedIcon: icon{{ "chat/mini_lock", premiumButtonFg }};
chatSimilarLockedIconPosition: point(0px, 1px);
chatSimilarBadgeFont: font(10px bold);
chatSimilarNameTop: 59px;
chatSimilarName: TextStyle(defaultTextStyle) {