mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support chat wallpaper set from gallery.
This commit is contained in:
parent
9b25973b49
commit
352ae5100a
17 changed files with 347 additions and 102 deletions
|
@ -729,7 +729,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_settings_manage_enabled_dictionary" = "Dictionary is enabled";
|
"lng_settings_manage_enabled_dictionary" = "Dictionary is enabled";
|
||||||
"lng_settings_manage_remove_dictionary" = "Remove Dictionary";
|
"lng_settings_manage_remove_dictionary" = "Remove Dictionary";
|
||||||
|
|
||||||
"lng_backgrounds_header" = "Choose your new chat background";
|
"lng_backgrounds_header" = "Choose Wallpaper";
|
||||||
"lng_theme_sure_keep" = "Keep this theme?";
|
"lng_theme_sure_keep" = "Keep this theme?";
|
||||||
"lng_theme_reverting#one" = "Reverting to the old theme in {count} second.";
|
"lng_theme_reverting#one" = "Reverting to the old theme in {count} second.";
|
||||||
"lng_theme_reverting#other" = "Reverting to the old theme in {count} seconds.";
|
"lng_theme_reverting#other" = "Reverting to the old theme in {count} seconds.";
|
||||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
|
#include "data/data_peer.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
@ -61,11 +62,15 @@ class BackgroundBox::Inner final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
Inner(
|
Inner(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Main::Session*> session);
|
not_null<Main::Session*> session,
|
||||||
|
PeerData *forPeer);
|
||||||
~Inner();
|
~Inner();
|
||||||
|
|
||||||
rpl::producer<Data::WallPaper> chooseEvents() const;
|
[[nodiscard]] rpl::producer<Data::WallPaper> chooseEvents() const;
|
||||||
rpl::producer<Data::WallPaper> removeRequests() const;
|
[[nodiscard]] rpl::producer<Data::WallPaper> removeRequests() const;
|
||||||
|
|
||||||
|
[[nodiscard]] auto resolveResetCustomPaper() const
|
||||||
|
->std::optional<Data::WallPaper>;
|
||||||
|
|
||||||
void removePaper(const Data::WallPaper &data);
|
void removePaper(const Data::WallPaper &data);
|
||||||
|
|
||||||
|
@ -109,6 +114,7 @@ private:
|
||||||
void resizeToContentAndPreload();
|
void resizeToContentAndPreload();
|
||||||
void updatePapers();
|
void updatePapers();
|
||||||
void requestPapers();
|
void requestPapers();
|
||||||
|
void pushResetCustomPaper();
|
||||||
void sortPapers();
|
void sortPapers();
|
||||||
void paintPaper(
|
void paintPaper(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
|
@ -118,9 +124,13 @@ private:
|
||||||
void validatePaperThumbnail(const Paper &paper) const;
|
void validatePaperThumbnail(const Paper &paper) const;
|
||||||
|
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
|
PeerData * const _forPeer = nullptr;
|
||||||
|
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
|
|
||||||
std::vector<Paper> _papers;
|
std::vector<Paper> _papers;
|
||||||
|
uint64 _currentId = 0;
|
||||||
|
uint64 _insertedResetId = 0;
|
||||||
|
|
||||||
Selection _over;
|
Selection _over;
|
||||||
Selection _overDown;
|
Selection _overDown;
|
||||||
|
@ -133,8 +143,10 @@ private:
|
||||||
|
|
||||||
BackgroundBox::BackgroundBox(
|
BackgroundBox::BackgroundBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
not_null<Window::SessionController*> controller)
|
not_null<Window::SessionController*> controller,
|
||||||
: _controller(controller) {
|
PeerData *forPeer)
|
||||||
|
: _controller(controller)
|
||||||
|
, _forPeer(forPeer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundBox::prepare() {
|
void BackgroundBox::prepare() {
|
||||||
|
@ -145,14 +157,12 @@ void BackgroundBox::prepare() {
|
||||||
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
||||||
|
|
||||||
_inner = setInnerWidget(
|
_inner = setInnerWidget(
|
||||||
object_ptr<Inner>(this, &_controller->session()),
|
object_ptr<Inner>(this, &_controller->session(), _forPeer),
|
||||||
st::backgroundScroll);
|
st::backgroundScroll);
|
||||||
|
|
||||||
_inner->chooseEvents(
|
_inner->chooseEvents(
|
||||||
) | rpl::start_with_next([=](const Data::WallPaper &paper) {
|
) | rpl::start_with_next([=](const Data::WallPaper &paper) {
|
||||||
_controller->show(
|
chosen(paper);
|
||||||
Box<BackgroundPreviewBox>(_controller, paper),
|
|
||||||
Ui::LayerOption::KeepOther);
|
|
||||||
}, _inner->lifetime());
|
}, _inner->lifetime());
|
||||||
|
|
||||||
_inner->removeRequests(
|
_inner->removeRequests(
|
||||||
|
@ -161,6 +171,74 @@ void BackgroundBox::prepare() {
|
||||||
}, _inner->lifetime());
|
}, _inner->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BackgroundBox::hasDefaultForPeer() const {
|
||||||
|
Expects(_forPeer != nullptr);
|
||||||
|
|
||||||
|
const auto paper = _forPeer->wallPaper();
|
||||||
|
if (!paper) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto reset = _inner->resolveResetCustomPaper();
|
||||||
|
Assert(reset.has_value());
|
||||||
|
return (paper->id() == reset->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BackgroundBox::chosenDefaultForPeer(
|
||||||
|
const Data::WallPaper &paper) const {
|
||||||
|
if (!_forPeer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto reset = _inner->resolveResetCustomPaper();
|
||||||
|
Assert(reset.has_value());
|
||||||
|
return (paper.id() == reset->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BackgroundBox::chosen(const Data::WallPaper &paper) {
|
||||||
|
if (chosenDefaultForPeer(paper)) {
|
||||||
|
if (!hasDefaultForPeer()) {
|
||||||
|
const auto reset = crl::guard(this, [=](Fn<void()> close) {
|
||||||
|
resetForPeer();
|
||||||
|
close();
|
||||||
|
});
|
||||||
|
_controller->show(Ui::MakeConfirmBox({
|
||||||
|
.text = u"Are you sure you want to reset the wallpaper?"_q,
|
||||||
|
.confirmed = reset,
|
||||||
|
.confirmText = u"Reset"_q,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
closeBox();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_controller->show(
|
||||||
|
Box<BackgroundPreviewBox>(
|
||||||
|
_controller,
|
||||||
|
paper,
|
||||||
|
BackgroundPreviewArgs{ _forPeer }),
|
||||||
|
Ui::LayerOption::KeepOther);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BackgroundBox::resetForPeer() {
|
||||||
|
const auto api = &_controller->session().api();
|
||||||
|
using Flag = MTPmessages_SetChatWallPaper::Flag;
|
||||||
|
api->request(MTPmessages_SetChatWallPaper(
|
||||||
|
MTP_flags(0),
|
||||||
|
_forPeer->input,
|
||||||
|
MTPInputWallPaper(),
|
||||||
|
MTPWallPaperSettings(),
|
||||||
|
MTPint()
|
||||||
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
api->applyUpdates(result);
|
||||||
|
}).send();
|
||||||
|
|
||||||
|
const auto weak = Ui::MakeWeak(this);
|
||||||
|
_forPeer->setWallPaper(std::nullopt);
|
||||||
|
if (weak) {
|
||||||
|
_controller->finishChatThemeEdit(_forPeer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BackgroundBox::removePaper(const Data::WallPaper &paper) {
|
void BackgroundBox::removePaper(const Data::WallPaper &paper) {
|
||||||
const auto session = &_controller->session();
|
const auto session = &_controller->session();
|
||||||
const auto remove = [=, weak = Ui::MakeWeak(this)](Fn<void()> &&close) {
|
const auto remove = [=, weak = Ui::MakeWeak(this)](Fn<void()> &&close) {
|
||||||
|
@ -186,17 +264,19 @@ void BackgroundBox::removePaper(const Data::WallPaper &paper) {
|
||||||
|
|
||||||
BackgroundBox::Inner::Inner(
|
BackgroundBox::Inner::Inner(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Main::Session*> session)
|
not_null<Main::Session*> session,
|
||||||
|
PeerData *forPeer)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _session(session)
|
, _session(session)
|
||||||
|
, _forPeer(forPeer)
|
||||||
, _api(&_session->mtp())
|
, _api(&_session->mtp())
|
||||||
, _check(std::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [=] { update(); })) {
|
, _check(std::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [=] { update(); })) {
|
||||||
_check->setChecked(true, anim::type::instant);
|
_check->setChecked(true, anim::type::instant);
|
||||||
if (_session->data().wallpapers().empty()) {
|
resize(st::boxWideWidth, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
||||||
resize(st::boxWideWidth, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
Window::Theme::IsNightModeValue(
|
||||||
} else {
|
) | rpl::start_with_next([=] {
|
||||||
updatePapers();
|
updatePapers();
|
||||||
}
|
}, lifetime());
|
||||||
requestPapers();
|
requestPapers();
|
||||||
|
|
||||||
_session->downloaderTaskFinished(
|
_session->downloaderTaskFinished(
|
||||||
|
@ -219,6 +299,7 @@ BackgroundBox::Inner::Inner(
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,27 +313,78 @@ void BackgroundBox::Inner::requestPapers() {
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto BackgroundBox::Inner::resolveResetCustomPaper() const
|
||||||
|
-> std::optional<Data::WallPaper> {
|
||||||
|
if (!_forPeer) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto nonCustom = Window::Theme::Background()->paper();
|
||||||
|
const auto themeEmoji = _forPeer->themeEmoji();
|
||||||
|
if (themeEmoji.isEmpty()) {
|
||||||
|
return nonCustom;
|
||||||
|
}
|
||||||
|
const auto &themes = _forPeer->owner().cloudThemes();
|
||||||
|
const auto theme = themes.themeForEmoji(themeEmoji);
|
||||||
|
if (!theme) {
|
||||||
|
return nonCustom;
|
||||||
|
}
|
||||||
|
using Type = Data::CloudTheme::Type;
|
||||||
|
const auto dark = Window::Theme::IsNightMode();
|
||||||
|
const auto i = theme->settings.find(dark ? Type::Dark : Type::Light);
|
||||||
|
if (i != end(theme->settings) && i->second.paper) {
|
||||||
|
return *i->second.paper;
|
||||||
|
}
|
||||||
|
return nonCustom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BackgroundBox::Inner::pushResetCustomPaper() {
|
||||||
|
if (const auto reset = resolveResetCustomPaper()) {
|
||||||
|
_insertedResetId = reset->id();
|
||||||
|
const auto j = ranges::find(
|
||||||
|
_papers,
|
||||||
|
_insertedResetId,
|
||||||
|
[](const Paper &paper) { return paper.data.id(); });
|
||||||
|
if (j != end(_papers)) {
|
||||||
|
j->data = j->data.withParamsFrom(*reset);
|
||||||
|
} else {
|
||||||
|
_papers.insert(begin(_papers), Paper{ *reset });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BackgroundBox::Inner::sortPapers() {
|
void BackgroundBox::Inner::sortPapers() {
|
||||||
const auto current = Window::Theme::Background()->id();
|
const auto currentCustom = _forPeer ? _forPeer->wallPaper() : nullptr;
|
||||||
const auto night = Window::Theme::IsNightMode();
|
_currentId = currentCustom
|
||||||
|
? currentCustom->id()
|
||||||
|
: _insertedResetId
|
||||||
|
? _insertedResetId
|
||||||
|
: Window::Theme::Background()->id();
|
||||||
|
const auto dark = Window::Theme::IsNightMode();
|
||||||
ranges::stable_sort(_papers, std::greater<>(), [&](const Paper &paper) {
|
ranges::stable_sort(_papers, std::greater<>(), [&](const Paper &paper) {
|
||||||
const auto &data = paper.data;
|
const auto &data = paper.data;
|
||||||
return std::make_tuple(
|
return std::make_tuple(
|
||||||
data.id() == current,
|
_insertedResetId && (_insertedResetId == data.id()),
|
||||||
night ? data.isDark() : !data.isDark(),
|
data.id() == _currentId,
|
||||||
|
dark ? data.isDark() : !data.isDark(),
|
||||||
Data::IsDefaultWallPaper(data),
|
Data::IsDefaultWallPaper(data),
|
||||||
!data.isDefault() && !Data::IsLegacy1DefaultWallPaper(data),
|
!data.isDefault() && !Data::IsLegacy1DefaultWallPaper(data),
|
||||||
Data::IsLegacy3DefaultWallPaper(data),
|
Data::IsLegacy3DefaultWallPaper(data),
|
||||||
Data::IsLegacy2DefaultWallPaper(data),
|
Data::IsLegacy2DefaultWallPaper(data),
|
||||||
Data::IsLegacy1DefaultWallPaper(data));
|
Data::IsLegacy1DefaultWallPaper(data));
|
||||||
});
|
});
|
||||||
if (!_papers.empty() && _papers.front().data.id() == current) {
|
if (!_papers.empty()
|
||||||
|
&& _papers.front().data.id() == _currentId
|
||||||
|
&& !currentCustom
|
||||||
|
&& !_insertedResetId) {
|
||||||
_papers.front().data = _papers.front().data.withParamsFrom(
|
_papers.front().data = _papers.front().data.withParamsFrom(
|
||||||
Window::Theme::Background()->paper());
|
Window::Theme::Background()->paper());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundBox::Inner::updatePapers() {
|
void BackgroundBox::Inner::updatePapers() {
|
||||||
|
if (_session->data().wallpapers().empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_over = _overDown = Selection();
|
_over = _overDown = Selection();
|
||||||
|
|
||||||
_papers = _session->data().wallpapers(
|
_papers = _session->data().wallpapers(
|
||||||
|
@ -261,6 +393,7 @@ void BackgroundBox::Inner::updatePapers() {
|
||||||
}) | ranges::views::transform([](const Data::WallPaper &paper) {
|
}) | ranges::views::transform([](const Data::WallPaper &paper) {
|
||||||
return Paper{ paper };
|
return Paper{ paper };
|
||||||
}) | ranges::to_vector;
|
}) | ranges::to_vector;
|
||||||
|
pushResetCustomPaper();
|
||||||
sortPapers();
|
sortPapers();
|
||||||
resizeToContentAndPreload();
|
resizeToContentAndPreload();
|
||||||
}
|
}
|
||||||
|
@ -373,7 +506,7 @@ void BackgroundBox::Inner::paintPaper(
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto over = !v::is_null(_overDown) ? _overDown : _over;
|
const auto over = !v::is_null(_overDown) ? _overDown : _over;
|
||||||
if (paper.data.id() == Window::Theme::Background()->id()) {
|
if (paper.data.id() == _currentId) {
|
||||||
const auto checkLeft = x + st::backgroundSize.width() - st::overviewCheckSkip - st::overviewCheck.size;
|
const auto checkLeft = x + st::backgroundSize.width() - st::overviewCheckSkip - st::overviewCheck.size;
|
||||||
const auto checkTop = y + st::backgroundSize.height() - st::overviewCheckSkip - st::overviewCheck.size;
|
const auto checkTop = y + st::backgroundSize.height() - st::overviewCheckSkip - st::overviewCheck.size;
|
||||||
_check->paint(p, checkLeft, checkTop, width());
|
_check->paint(p, checkLeft, checkTop, width());
|
||||||
|
@ -415,14 +548,13 @@ void BackgroundBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||||
- st::stickerPanDeleteIconBg.width();
|
- st::stickerPanDeleteIconBg.width();
|
||||||
const auto deleteBottom = row * (height + skip) + skip
|
const auto deleteBottom = row * (height + skip) + skip
|
||||||
+ st::stickerPanDeleteIconBg.height();
|
+ st::stickerPanDeleteIconBg.height();
|
||||||
const auto currentId = Window::Theme::Background()->id();
|
|
||||||
const auto inDelete = (x >= deleteLeft)
|
const auto inDelete = (x >= deleteLeft)
|
||||||
&& (y < deleteBottom)
|
&& (y < deleteBottom)
|
||||||
&& Data::IsCloudWallPaper(data)
|
&& Data::IsCloudWallPaper(data)
|
||||||
&& !Data::IsDefaultWallPaper(data)
|
&& !Data::IsDefaultWallPaper(data)
|
||||||
&& !Data::IsLegacy2DefaultWallPaper(data)
|
&& !Data::IsLegacy2DefaultWallPaper(data)
|
||||||
&& !Data::IsLegacy3DefaultWallPaper(data)
|
&& !Data::IsLegacy3DefaultWallPaper(data)
|
||||||
&& (currentId != data.id());
|
&& (_currentId != data.id());
|
||||||
return (result >= _papers.size())
|
return (result >= _papers.size())
|
||||||
? Selection()
|
? Selection()
|
||||||
: inDelete
|
: inDelete
|
||||||
|
|
|
@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "boxes/abstract_box.h"
|
#include "boxes/abstract_box.h"
|
||||||
|
|
||||||
|
class PeerData;
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
class SessionController;
|
class SessionController;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
@ -19,7 +21,10 @@ class WallPaper;
|
||||||
|
|
||||||
class BackgroundBox : public Ui::BoxContent {
|
class BackgroundBox : public Ui::BoxContent {
|
||||||
public:
|
public:
|
||||||
BackgroundBox(QWidget*, not_null<Window::SessionController*> controller);
|
BackgroundBox(
|
||||||
|
QWidget*,
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
PeerData *forPeer = nullptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
@ -27,10 +32,16 @@ protected:
|
||||||
private:
|
private:
|
||||||
class Inner;
|
class Inner;
|
||||||
|
|
||||||
|
void chosen(const Data::WallPaper &paper);
|
||||||
|
[[nodiscard]] bool hasDefaultForPeer() const;
|
||||||
|
[[nodiscard]] bool chosenDefaultForPeer(
|
||||||
|
const Data::WallPaper &paper) const;
|
||||||
void removePaper(const Data::WallPaper &paper);
|
void removePaper(const Data::WallPaper &paper);
|
||||||
|
void resetForPeer();
|
||||||
|
|
||||||
const not_null<Window::SessionController*> _controller;
|
const not_null<Window::SessionController*> _controller;
|
||||||
|
|
||||||
QPointer<Inner> _inner;
|
QPointer<Inner> _inner;
|
||||||
|
PeerData *_forPeer = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -164,23 +164,17 @@ BackgroundPreviewBox::BackgroundPreviewBox(
|
||||||
, _chatStyle(std::make_unique<Ui::ChatStyle>())
|
, _chatStyle(std::make_unique<Ui::ChatStyle>())
|
||||||
, _serviceHistory(_controller->session().data().history(
|
, _serviceHistory(_controller->session().data().history(
|
||||||
PeerData::kServiceNotificationsId))
|
PeerData::kServiceNotificationsId))
|
||||||
, _service((_forPeer && !_fromMessageId)
|
, _service(nullptr)
|
||||||
? GenerateServiceItem(
|
|
||||||
delegate(),
|
|
||||||
_serviceHistory,
|
|
||||||
tr::lng_background_other_info(tr::now, lt_user, _forPeer->shortName()),
|
|
||||||
false)
|
|
||||||
: nullptr)
|
|
||||||
, _text1(GenerateTextItem(
|
, _text1(GenerateTextItem(
|
||||||
delegate(),
|
delegate(),
|
||||||
_controller->session().data().history(PeerData::kServiceNotificationsId),
|
_serviceHistory,
|
||||||
(_forPeer
|
(_forPeer
|
||||||
? tr::lng_background_apply1(tr::now)
|
? tr::lng_background_apply1(tr::now)
|
||||||
: tr::lng_background_text1(tr::now)),
|
: tr::lng_background_text1(tr::now)),
|
||||||
false))
|
false))
|
||||||
, _text2(GenerateTextItem(
|
, _text2(GenerateTextItem(
|
||||||
delegate(),
|
delegate(),
|
||||||
_controller->session().data().history(PeerData::kServiceNotificationsId),
|
_serviceHistory,
|
||||||
(_forPeer
|
(_forPeer
|
||||||
? tr::lng_background_apply2(tr::now)
|
? tr::lng_background_apply2(tr::now)
|
||||||
: tr::lng_background_text2(tr::now)),
|
: tr::lng_background_text2(tr::now)),
|
||||||
|
@ -244,11 +238,7 @@ void BackgroundPreviewBox::prepare() {
|
||||||
setScaledFromThumb();
|
setScaledFromThumb();
|
||||||
checkLoadedDocument();
|
checkLoadedDocument();
|
||||||
|
|
||||||
if (_service) {
|
_text1->setDisplayDate(false);
|
||||||
_service->initDimensions();
|
|
||||||
_service->resizeGetHeight(st::boxWideWidth);
|
|
||||||
}
|
|
||||||
_text1->setDisplayDate(!_service);
|
|
||||||
_text1->initDimensions();
|
_text1->initDimensions();
|
||||||
_text1->resizeGetHeight(st::boxWideWidth);
|
_text1->resizeGetHeight(st::boxWideWidth);
|
||||||
_text2->initDimensions();
|
_text2->initDimensions();
|
||||||
|
@ -285,12 +275,15 @@ void BackgroundPreviewBox::createBlurCheckbox() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundPreviewBox::apply() {
|
void BackgroundPreviewBox::apply() {
|
||||||
|
const auto weak = Ui::MakeWeak(this);
|
||||||
if (_forPeer) {
|
if (_forPeer) {
|
||||||
applyForPeer();
|
applyForPeer();
|
||||||
} else {
|
} else {
|
||||||
applyForEveryone();
|
applyForEveryone();
|
||||||
}
|
}
|
||||||
closeBox();
|
if (weak) {
|
||||||
|
closeBox();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundPreviewBox::applyForPeer() {
|
void BackgroundPreviewBox::applyForPeer() {
|
||||||
|
@ -311,6 +304,7 @@ void BackgroundPreviewBox::applyForPeer() {
|
||||||
}).send();
|
}).send();
|
||||||
|
|
||||||
_forPeer->setWallPaper(_paper);
|
_forPeer->setWallPaper(_paper);
|
||||||
|
_controller->finishChatThemeEdit(_forPeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundPreviewBox::applyForEveryone() {
|
void BackgroundPreviewBox::applyForEveryone() {
|
||||||
|
@ -435,8 +429,6 @@ void BackgroundPreviewBox::paintTexts(Painter &p, crl::time ms) {
|
||||||
if (_service) {
|
if (_service) {
|
||||||
_service->draw(p, context);
|
_service->draw(p, context);
|
||||||
p.translate(0, heights);
|
p.translate(0, heights);
|
||||||
} else {
|
|
||||||
paintDate(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context.outbg = _text1->hasOutLayout();
|
context.outbg = _text1->hasOutLayout();
|
||||||
|
@ -448,27 +440,6 @@ void BackgroundPreviewBox::paintTexts(Painter &p, crl::time ms) {
|
||||||
p.translate(0, height2);
|
p.translate(0, height2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundPreviewBox::paintDate(Painter &p) {
|
|
||||||
const auto date = _text1->Get<HistoryView::DateBadge>();
|
|
||||||
if (!date || !_serviceBg) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto hq = PainterHighQualityEnabler(p);
|
|
||||||
const auto text = date->text;
|
|
||||||
const auto bubbleHeight = st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom();
|
|
||||||
const auto bubbleTop = st::msgServiceMargin.top();
|
|
||||||
const auto textWidth = st::msgServiceFont->width(text);
|
|
||||||
const auto bubbleWidth = st::msgServicePadding.left() + textWidth + st::msgServicePadding.right();
|
|
||||||
const auto bubbleLeft = (width() - bubbleWidth) / 2;
|
|
||||||
const auto radius = bubbleHeight / 2;
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
p.setBrush(*_serviceBg);
|
|
||||||
p.drawRoundedRect(bubbleLeft, bubbleTop, bubbleWidth, bubbleHeight, radius, radius);
|
|
||||||
p.setPen(st::msgServiceFg);
|
|
||||||
p.setFont(st::msgServiceFont);
|
|
||||||
p.drawText(bubbleLeft + st::msgServicePadding.left(), bubbleTop + st::msgServicePadding.top() + st::msgServiceFont->ascent, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BackgroundPreviewBox::radialAnimationCallback(crl::time now) {
|
void BackgroundPreviewBox::radialAnimationCallback(crl::time now) {
|
||||||
Expects(_paper.document() != nullptr);
|
Expects(_paper.document() != nullptr);
|
||||||
|
|
||||||
|
@ -556,9 +527,29 @@ void BackgroundPreviewBox::updateServiceBg(const std::vector<QColor> &bg) {
|
||||||
green += color.green();
|
green += color.green();
|
||||||
blue += color.blue();
|
blue += color.blue();
|
||||||
}
|
}
|
||||||
_serviceBg = Ui::ThemeAdjustedColor(
|
rpl::single(
|
||||||
st::msgServiceBg->c,
|
rpl::empty
|
||||||
QColor(red / count, green / count, blue / count));
|
) | rpl::then(
|
||||||
|
style::PaletteChanged()
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
_serviceBg = Ui::ThemeAdjustedColor(
|
||||||
|
st::msgServiceBg->c,
|
||||||
|
QColor(red / count, green / count, blue / count));
|
||||||
|
_chatStyle->applyAdjustedServiceBg(*_serviceBg);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_service = GenerateServiceItem(
|
||||||
|
delegate(),
|
||||||
|
_serviceHistory,
|
||||||
|
((_forPeer && !_fromMessageId)
|
||||||
|
? tr::lng_background_other_info(
|
||||||
|
tr::now,
|
||||||
|
lt_user,
|
||||||
|
_forPeer->shortName())
|
||||||
|
: ItemDateText(_text1->data(), false)),
|
||||||
|
false);
|
||||||
|
_service->initDimensions();
|
||||||
|
_service->resizeGetHeight(st::boxWideWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundPreviewBox::checkLoadedDocument() {
|
void BackgroundPreviewBox::checkLoadedDocument() {
|
||||||
|
|
|
@ -73,7 +73,6 @@ private:
|
||||||
void paintImage(Painter &p);
|
void paintImage(Painter &p);
|
||||||
void paintRadial(Painter &p);
|
void paintRadial(Painter &p);
|
||||||
void paintTexts(Painter &p, crl::time ms);
|
void paintTexts(Painter &p, crl::time ms);
|
||||||
void paintDate(Painter &p);
|
|
||||||
void createBlurCheckbox();
|
void createBlurCheckbox();
|
||||||
int textsTop() const;
|
int textsTop() const;
|
||||||
void startFadeInFrom(QPixmap previous);
|
void startFadeInFrom(QPixmap previous);
|
||||||
|
|
|
@ -1558,7 +1558,9 @@ bool HistoryWidget::updateStickersByEmoji() {
|
||||||
return (emoji != nullptr);
|
return (emoji != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::toggleChooseChatTheme(not_null<PeerData*> peer) {
|
void HistoryWidget::toggleChooseChatTheme(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
std::optional<bool> show) {
|
||||||
const auto update = [=] {
|
const auto update = [=] {
|
||||||
updateInlineBotQuery();
|
updateInlineBotQuery();
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
|
@ -1567,7 +1569,7 @@ void HistoryWidget::toggleChooseChatTheme(not_null<PeerData*> peer) {
|
||||||
if (peer.get() != _peer) {
|
if (peer.get() != _peer) {
|
||||||
return;
|
return;
|
||||||
} else if (_chooseTheme) {
|
} else if (_chooseTheme) {
|
||||||
if (isChoosingTheme()) {
|
if (isChoosingTheme() && !show.value_or(false)) {
|
||||||
const auto was = base::take(_chooseTheme);
|
const auto was = base::take(_chooseTheme);
|
||||||
if (Ui::InFocusChain(this)) {
|
if (Ui::InFocusChain(this)) {
|
||||||
setInnerFocus();
|
setInnerFocus();
|
||||||
|
@ -1575,6 +1577,8 @@ void HistoryWidget::toggleChooseChatTheme(not_null<PeerData*> peer) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
} else if (!show.value_or(true)) {
|
||||||
|
return;
|
||||||
} else if (_voiceRecordBar->isActive()) {
|
} else if (_voiceRecordBar->isActive()) {
|
||||||
controller()->showToast({ tr::lng_chat_theme_cant_voice(tr::now) });
|
controller()->showToast({ tr::lng_chat_theme_cant_voice(tr::now) });
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -226,7 +226,9 @@ public:
|
||||||
void clearDelayedShowAtRequest();
|
void clearDelayedShowAtRequest();
|
||||||
void clearDelayedShowAt();
|
void clearDelayedShowAt();
|
||||||
|
|
||||||
void toggleChooseChatTheme(not_null<PeerData*> peer);
|
void toggleChooseChatTheme(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
std::optional<bool> show = std::nullopt);
|
||||||
[[nodiscard]] Ui::ChatTheme *customChatTheme() const;
|
[[nodiscard]] Ui::ChatTheme *customChatTheme() const;
|
||||||
|
|
||||||
void applyCloudDraft(History *history);
|
void applyCloudDraft(History *history);
|
||||||
|
|
|
@ -341,6 +341,9 @@ void ThemeDocument::prepareThumbnailFrom(
|
||||||
_patternOpacity);
|
_patternOpacity);
|
||||||
original.setDevicePixelRatio(ratio);
|
original.setDevicePixelRatio(ratio);
|
||||||
}
|
}
|
||||||
|
if (_serviceWidth) {
|
||||||
|
original = Images::Circle(std::move(original));
|
||||||
|
}
|
||||||
_thumbnail = Ui::PixmapFromImage(std::move(original));
|
_thumbnail = Ui::PixmapFromImage(std::move(original));
|
||||||
_thumbnailGood = good;
|
_thumbnailGood = good;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1231,8 +1231,10 @@ void MainWidget::clearChooseReportMessages() {
|
||||||
_history->setChooseReportMessagesDetails({}, nullptr);
|
_history->setChooseReportMessagesDetails({}, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::toggleChooseChatTheme(not_null<PeerData*> peer) {
|
void MainWidget::toggleChooseChatTheme(
|
||||||
_history->toggleChooseChatTheme(peer);
|
not_null<PeerData*> peer,
|
||||||
|
std::optional<bool> show) {
|
||||||
|
_history->toggleChooseChatTheme(peer, show);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWidget::showHistoryInDifferentWindow(
|
bool MainWidget::showHistoryInDifferentWindow(
|
||||||
|
|
|
@ -215,7 +215,9 @@ public:
|
||||||
Fn<void(MessageIdsList)> done);
|
Fn<void(MessageIdsList)> done);
|
||||||
void clearChooseReportMessages();
|
void clearChooseReportMessages();
|
||||||
|
|
||||||
void toggleChooseChatTheme(not_null<PeerData*> peer);
|
void toggleChooseChatTheme(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
std::optional<bool> show);
|
||||||
|
|
||||||
void showHistory(
|
void showHistory(
|
||||||
PeerId peer,
|
PeerId peer,
|
||||||
|
|
|
@ -439,6 +439,12 @@ void ChatStyle::apply(not_null<ChatTheme*> theme) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatStyle::applyAdjustedServiceBg(QColor serviceBg) {
|
||||||
|
auto r = 0, g = 0, b = 0, a = 0;
|
||||||
|
serviceBg.getRgb(&r, &g, &b, &a);
|
||||||
|
msgServiceBg().set(uchar(r), uchar(g), uchar(b), uchar(a));
|
||||||
|
}
|
||||||
|
|
||||||
void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
|
void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
|
||||||
*static_cast<style::palette*>(this) = *palette;
|
*static_cast<style::palette*>(this) = *palette;
|
||||||
style::internal::resetIcons();
|
style::internal::resetIcons();
|
||||||
|
|
|
@ -165,6 +165,7 @@ public:
|
||||||
explicit ChatStyle(not_null<const style::palette*> isolated);
|
explicit ChatStyle(not_null<const style::palette*> isolated);
|
||||||
|
|
||||||
void apply(not_null<ChatTheme*> theme);
|
void apply(not_null<ChatTheme*> theme);
|
||||||
|
void applyAdjustedServiceBg(QColor serviceBg);
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<> paletteChanged() const {
|
[[nodiscard]] rpl::producer<> paletteChanged() const {
|
||||||
return _paletteChanged.events();
|
return _paletteChanged.events();
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "ui/chat/choose_theme_controller.h"
|
#include "ui/chat/choose_theme_controller.h"
|
||||||
|
|
||||||
|
#include "boxes/background_box.h"
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
|
@ -35,7 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kDisableElement = "disable"_cs;
|
const auto kDisableElement = [] { return u"disable"_q; };
|
||||||
|
|
||||||
[[nodiscard]] QImage GeneratePreview(not_null<Ui::ChatTheme*> theme) {
|
[[nodiscard]] QImage GeneratePreview(not_null<Ui::ChatTheme*> theme) {
|
||||||
const auto &background = theme->background();
|
const auto &background = theme->background();
|
||||||
|
@ -164,6 +165,7 @@ ChooseThemeController::ChooseThemeController(
|
||||||
, _topShadow(std::make_unique<PlainShadow>(parent))
|
, _topShadow(std::make_unique<PlainShadow>(parent))
|
||||||
, _content(_wrap->add(object_ptr<RpWidget>(_wrap.get())))
|
, _content(_wrap->add(object_ptr<RpWidget>(_wrap.get())))
|
||||||
, _inner(CreateChild<RpWidget>(_content.get()))
|
, _inner(CreateChild<RpWidget>(_content.get()))
|
||||||
|
, _disabledEmoji(Ui::Emoji::Find(QString::fromUtf8("\xe2\x9d\x8c")))
|
||||||
, _dark(Window::Theme::IsThemeDarkValue()) {
|
, _dark(Window::Theme::IsThemeDarkValue()) {
|
||||||
init(parent->sizeValue());
|
init(parent->sizeValue());
|
||||||
}
|
}
|
||||||
|
@ -239,29 +241,45 @@ void ChooseThemeController::initButtons() {
|
||||||
controls,
|
controls,
|
||||||
tr::lng_chat_theme_apply(),
|
tr::lng_chat_theme_apply(),
|
||||||
st::defaultActiveButton);
|
st::defaultActiveButton);
|
||||||
|
const auto choose = CreateChild<RoundButton>(
|
||||||
|
controls,
|
||||||
|
rpl::single(u"Change Wallpaper"_q),
|
||||||
|
st::defaultActiveButton);
|
||||||
const auto skip = st::normalFont->spacew * 2;
|
const auto skip = st::normalFont->spacew * 2;
|
||||||
controls->resize(
|
controls->resize(
|
||||||
skip + cancel->width() + skip + apply->width() + skip,
|
skip + cancel->width() + skip + choose->width() + skip,
|
||||||
apply->height() + skip * 2);
|
apply->height() + skip * 2);
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
controls->widthValue(),
|
controls->widthValue(),
|
||||||
cancel->widthValue(),
|
cancel->widthValue(),
|
||||||
apply->widthValue()
|
apply->widthValue(),
|
||||||
|
choose->widthValue(),
|
||||||
|
_chosen.value()
|
||||||
) | rpl::start_with_next([=](
|
) | rpl::start_with_next([=](
|
||||||
int outer,
|
int outer,
|
||||||
int cancelWidth,
|
int cancelWidth,
|
||||||
int applyWidth) {
|
int applyWidth,
|
||||||
const auto inner = skip + cancelWidth + skip + applyWidth + skip;
|
int chooseWidth,
|
||||||
|
QString chosen) {
|
||||||
|
const auto was = _peer->themeEmoji();
|
||||||
|
const auto now = (chosen == kDisableElement()) ? QString() : chosen;
|
||||||
|
const auto changed = (now != was);
|
||||||
|
apply->setVisible(changed);
|
||||||
|
choose->setVisible(!changed);
|
||||||
|
const auto shown = changed ? apply : choose;
|
||||||
|
const auto shownWidth = changed ? applyWidth : chooseWidth;
|
||||||
|
const auto inner = skip + cancelWidth + skip + shownWidth + skip;
|
||||||
const auto left = (outer - inner) / 2;
|
const auto left = (outer - inner) / 2;
|
||||||
cancel->moveToLeft(left, 0);
|
cancel->moveToLeft(left, 0);
|
||||||
apply->moveToRight(left, 0);
|
shown->moveToRight(left, 0);
|
||||||
}, controls->lifetime());
|
}, controls->lifetime());
|
||||||
|
|
||||||
cancel->setClickedCallback([=] { close(); });
|
cancel->setClickedCallback([=] { close(); });
|
||||||
apply->setClickedCallback([=] {
|
apply->setClickedCallback([=] {
|
||||||
if (const auto chosen = findChosen()) {
|
if (const auto chosen = findChosen()) {
|
||||||
if (Ui::Emoji::Find(_peer->themeEmoji()) != chosen->emoji) {
|
const auto was = _peer->themeEmoji();
|
||||||
const auto now = chosen->key ? _chosen : QString();
|
const auto now = chosen->key ? _chosen.current() : QString();
|
||||||
|
if (was != now) {
|
||||||
_peer->setThemeEmoji(now);
|
_peer->setThemeEmoji(now);
|
||||||
if (chosen->theme) {
|
if (chosen->theme) {
|
||||||
// Remember while changes propagate through event loop.
|
// Remember while changes propagate through event loop.
|
||||||
|
@ -278,6 +296,9 @@ void ChooseThemeController::initButtons() {
|
||||||
}
|
}
|
||||||
_controller->toggleChooseChatTheme(_peer);
|
_controller->toggleChooseChatTheme(_peer);
|
||||||
});
|
});
|
||||||
|
choose->setClickedCallback([=] {
|
||||||
|
_controller->show(Box<BackgroundBox>(_controller, _peer));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChooseThemeController::paintEntry(QPainter &p, const Entry &entry) {
|
void ChooseThemeController::paintEntry(QPainter &p, const Entry &entry) {
|
||||||
|
@ -338,7 +359,7 @@ void ChooseThemeController::initList() {
|
||||||
} else if (entry->key) {
|
} else if (entry->key) {
|
||||||
return entry->emoji->text();
|
return entry->emoji->text();
|
||||||
} else {
|
} else {
|
||||||
return kDisableElement.utf16();
|
return kDisableElement();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
_inner->events(
|
_inner->events(
|
||||||
|
@ -375,7 +396,7 @@ void ChooseThemeController::initList() {
|
||||||
const auto mouse = static_cast<QMouseEvent*>(event.get());
|
const auto mouse = static_cast<QMouseEvent*>(event.get());
|
||||||
const auto entry = byPoint(mouse->pos());
|
const auto entry = byPoint(mouse->pos());
|
||||||
const auto chosen = chosenText(entry);
|
const auto chosen = chosenText(entry);
|
||||||
if (entry && chosen == _pressed && chosen != _chosen) {
|
if (entry && chosen == _pressed && chosen != _chosen.current()) {
|
||||||
clearCurrentBackgroundState();
|
clearCurrentBackgroundState();
|
||||||
if (const auto was = findChosen()) {
|
if (const auto was = findChosen()) {
|
||||||
was->chosen = false;
|
was->chosen = false;
|
||||||
|
@ -465,13 +486,14 @@ void ChooseThemeController::clearCurrentBackgroundState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ChooseThemeController::findChosen() -> Entry* {
|
auto ChooseThemeController::findChosen() -> Entry* {
|
||||||
if (_chosen.isEmpty()) {
|
const auto chosen = _chosen.current();
|
||||||
|
if (chosen.isEmpty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
for (auto &entry : _entries) {
|
for (auto &entry : _entries) {
|
||||||
if (!entry.key && _chosen == kDisableElement.utf16()) {
|
if (!entry.key && chosen == kDisableElement()) {
|
||||||
return &entry;
|
return &entry;
|
||||||
} else if (_chosen == entry.emoji->text()) {
|
} else if (chosen == entry.emoji->text()) {
|
||||||
return &entry;
|
return &entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -494,11 +516,14 @@ void ChooseThemeController::fill(
|
||||||
_inner->resize(full, skip + single.height() + skip);
|
_inner->resize(full, skip + single.height() + skip);
|
||||||
|
|
||||||
const auto initial = Ui::Emoji::Find(_peer->themeEmoji());
|
const auto initial = Ui::Emoji::Find(_peer->themeEmoji());
|
||||||
|
if (!initial) {
|
||||||
|
_chosen = kDisableElement();
|
||||||
|
}
|
||||||
|
|
||||||
_dark.value(
|
_dark.value(
|
||||||
) | rpl::start_with_next([=](bool dark) {
|
) | rpl::start_with_next([=](bool dark) {
|
||||||
clearCurrentBackgroundState();
|
clearCurrentBackgroundState();
|
||||||
if (_chosen.isEmpty() && initial) {
|
if (_chosen.current().isEmpty() && initial) {
|
||||||
_chosen = initial->text();
|
_chosen = initial->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,9 +532,9 @@ void ChooseThemeController::fill(
|
||||||
auto x = skip * 2;
|
auto x = skip * 2;
|
||||||
_entries.push_back({
|
_entries.push_back({
|
||||||
.preview = GenerateEmptyPreview(),
|
.preview = GenerateEmptyPreview(),
|
||||||
.emoji = Ui::Emoji::Find(QString::fromUtf8("\xe2\x9d\x8c")),
|
.emoji = _disabledEmoji,
|
||||||
.geometry = QRect(QPoint(x, skip), single),
|
.geometry = QRect(QPoint(x, skip), single),
|
||||||
.chosen = (_chosen == kDisableElement.utf16()),
|
.chosen = (_chosen.current() == kDisableElement()),
|
||||||
});
|
});
|
||||||
Assert(_entries.front().emoji != nullptr);
|
Assert(_entries.front().emoji != nullptr);
|
||||||
style::PaletteChanged(
|
style::PaletteChanged(
|
||||||
|
@ -528,7 +553,7 @@ void ChooseThemeController::fill(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto key = ChatThemeKey{ theme.id, dark };
|
const auto key = ChatThemeKey{ theme.id, dark };
|
||||||
const auto isChosen = (_chosen == emoji->text());
|
const auto isChosen = (_chosen.current() == emoji->text());
|
||||||
_entries.push_back({
|
_entries.push_back({
|
||||||
.key = key,
|
.key = key,
|
||||||
.emoji = emoji,
|
.emoji = emoji,
|
||||||
|
@ -552,7 +577,7 @@ void ChooseThemeController::fill(
|
||||||
const auto theme = data.get();
|
const auto theme = data.get();
|
||||||
i->theme = std::move(data);
|
i->theme = std::move(data);
|
||||||
i->preview = GeneratePreview(theme);
|
i->preview = GeneratePreview(theme);
|
||||||
if (_chosen == i->emoji->text()) {
|
if (_chosen.current() == i->emoji->text()) {
|
||||||
_controller->overridePeerTheme(
|
_controller->overridePeerTheme(
|
||||||
_peer,
|
_peer,
|
||||||
i->theme,
|
i->theme,
|
||||||
|
|
|
@ -66,9 +66,10 @@ private:
|
||||||
|
|
||||||
const not_null<RpWidget*> _content;
|
const not_null<RpWidget*> _content;
|
||||||
const not_null<RpWidget*> _inner;
|
const not_null<RpWidget*> _inner;
|
||||||
|
const EmojiPtr _disabledEmoji = nullptr;
|
||||||
std::vector<Entry> _entries;
|
std::vector<Entry> _entries;
|
||||||
QString _pressed;
|
QString _pressed;
|
||||||
QString _chosen;
|
rpl::variable<QString> _chosen;
|
||||||
std::optional<QPoint> _pressPosition;
|
std::optional<QPoint> _pressPosition;
|
||||||
std::optional<QPoint> _dragStartPosition;
|
std::optional<QPoint> _dragStartPosition;
|
||||||
int _dragStartInnerLeft = 0;
|
int _dragStartInnerLeft = 0;
|
||||||
|
|
|
@ -95,6 +95,33 @@ struct ResolvedPaper {
|
||||||
}) | rpl::flatten_latest();
|
}) | rpl::flatten_latest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<> DebouncedPaletteValue() {
|
||||||
|
return [=](auto consumer) {
|
||||||
|
auto lifetime = rpl::lifetime();
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
base::has_weak_ptr guard;
|
||||||
|
bool scheduled = false;
|
||||||
|
};
|
||||||
|
const auto state = lifetime.make_state<State>();
|
||||||
|
|
||||||
|
consumer.put_next_copy(rpl::empty);
|
||||||
|
style::PaletteChanged(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
if (state->scheduled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state->scheduled = true;
|
||||||
|
Ui::PostponeCall(&state->guard, [=] {
|
||||||
|
state->scheduled = false;
|
||||||
|
consumer.put_next_copy(rpl::empty);
|
||||||
|
});
|
||||||
|
}, lifetime);
|
||||||
|
|
||||||
|
return lifetime;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct ResolvedTheme {
|
struct ResolvedTheme {
|
||||||
std::optional<Data::CloudTheme> theme;
|
std::optional<Data::CloudTheme> theme;
|
||||||
std::optional<ResolvedPaper> paper;
|
std::optional<ResolvedPaper> paper;
|
||||||
|
@ -111,9 +138,22 @@ struct ResolvedTheme {
|
||||||
) | rpl::map([](
|
) | rpl::map([](
|
||||||
std::optional<Data::CloudTheme> theme,
|
std::optional<Data::CloudTheme> theme,
|
||||||
std::optional<ResolvedPaper> paper,
|
std::optional<ResolvedPaper> paper,
|
||||||
bool night) {
|
bool night) -> rpl::producer<ResolvedTheme> {
|
||||||
return ResolvedTheme{ std::move(theme), std::move(paper), night };
|
if (theme || !paper) {
|
||||||
});
|
return rpl::single<ResolvedTheme>({
|
||||||
|
std::move(theme),
|
||||||
|
std::move(paper),
|
||||||
|
night,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return DebouncedPaletteValue(
|
||||||
|
) | rpl::map([=] {
|
||||||
|
return ResolvedTheme{
|
||||||
|
.paper = paper,
|
||||||
|
.dark = night,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}) | rpl::flatten_latest();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -97,9 +97,10 @@ constexpr auto kMaxChatEntryHistorySize = 50;
|
||||||
constexpr auto kDayBaseFile = ":/gui/day-custom-base.tdesktop-theme"_cs;
|
constexpr auto kDayBaseFile = ":/gui/day-custom-base.tdesktop-theme"_cs;
|
||||||
constexpr auto kNightBaseFile = ":/gui/night-custom-base.tdesktop-theme"_cs;
|
constexpr auto kNightBaseFile = ":/gui/night-custom-base.tdesktop-theme"_cs;
|
||||||
|
|
||||||
[[nodiscard]] Fn<void(style::palette&)> PrepareDefaultPaletteCallback() {
|
[[nodiscard]] Fn<void(style::palette&)> PrepareCurrentCallback() {
|
||||||
return [=](style::palette &palette) {
|
const auto copy = std::make_shared<style::palette>();
|
||||||
palette.reset();
|
return [=, data = style::main_palette::save()](style::palette &palette) {
|
||||||
|
palette.load(data);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,6 +789,14 @@ SessionController::SessionController(
|
||||||
pushDefaultChatBackground();
|
pushDefaultChatBackground();
|
||||||
}
|
}
|
||||||
}, _lifetime);
|
}, _lifetime);
|
||||||
|
style::PaletteChanged(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
for (auto &[key, value] : _customChatThemes) {
|
||||||
|
if (!key.theme.id) {
|
||||||
|
value.theme.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, _lifetime);
|
||||||
|
|
||||||
_authedName = session->user()->name();
|
_authedName = session->user()->name();
|
||||||
session->changes().peerUpdates(
|
session->changes().peerUpdates(
|
||||||
|
@ -1831,8 +1840,22 @@ void SessionController::showInNewWindow(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionController::toggleChooseChatTheme(not_null<PeerData*> peer) {
|
void SessionController::toggleChooseChatTheme(
|
||||||
content()->toggleChooseChatTheme(peer);
|
not_null<PeerData*> peer,
|
||||||
|
std::optional<bool> show) {
|
||||||
|
content()->toggleChooseChatTheme(peer, show);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionController::finishChatThemeEdit(not_null<PeerData*> peer) {
|
||||||
|
toggleChooseChatTheme(peer, false);
|
||||||
|
const auto weak = base::make_weak(this);
|
||||||
|
const auto history = activeChatCurrent().history();
|
||||||
|
if (!history || history->peer != peer) {
|
||||||
|
showPeerHistory(peer);
|
||||||
|
}
|
||||||
|
if (weak) {
|
||||||
|
hideLayer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionController::updateColumnLayout() {
|
void SessionController::updateColumnLayout() {
|
||||||
|
@ -2082,7 +2105,7 @@ auto SessionController::cachedChatThemeValue(
|
||||||
return rpl::single(_defaultChatTheme);
|
return rpl::single(_defaultChatTheme);
|
||||||
}
|
}
|
||||||
const auto settings = data.settings.find(type);
|
const auto settings = data.settings.find(type);
|
||||||
if (!data.id && settings == end(data.settings)) {
|
if (data.id && settings == end(data.settings)) {
|
||||||
return rpl::single(_defaultChatTheme);
|
return rpl::single(_defaultChatTheme);
|
||||||
}
|
}
|
||||||
if (paper.isNull()
|
if (paper.isNull()
|
||||||
|
@ -2242,7 +2265,7 @@ void SessionController::cacheChatTheme(
|
||||||
.key = key.theme,
|
.key = key.theme,
|
||||||
.preparePalette = (data.id
|
.preparePalette = (data.id
|
||||||
? PreparePaletteCallback(dark, i->second.accentColor)
|
? PreparePaletteCallback(dark, i->second.accentColor)
|
||||||
: PrepareDefaultPaletteCallback()),
|
: PrepareCurrentCallback()),
|
||||||
.backgroundData = backgroundData(theme),
|
.backgroundData = backgroundData(theme),
|
||||||
.bubblesData = PrepareBubblesData(data, type),
|
.bubblesData = PrepareBubblesData(data, type),
|
||||||
.basedOnDark = dark,
|
.basedOnDark = dark,
|
||||||
|
|
|
@ -498,7 +498,10 @@ public:
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId msgId = ShowAtUnreadMsgId);
|
MsgId msgId = ShowAtUnreadMsgId);
|
||||||
|
|
||||||
void toggleChooseChatTheme(not_null<PeerData*> peer);
|
void toggleChooseChatTheme(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
std::optional<bool> show = std::nullopt);
|
||||||
|
void finishChatThemeEdit(not_null<PeerData*> peer);
|
||||||
|
|
||||||
[[nodiscard]] bool dialogsListFocused() const {
|
[[nodiscard]] bool dialogsListFocused() const {
|
||||||
return _dialogsListFocused.current();
|
return _dialogsListFocused.current();
|
||||||
|
|
Loading…
Add table
Reference in a new issue