mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-22 17:17:15 +02:00
Show chat intro in an empty chat.
This commit is contained in:
parent
7f4d13c54a
commit
85554d19e4
12 changed files with 194 additions and 293 deletions
|
@ -2302,7 +2302,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_chat_intro_title" = "Intro";
|
||||
"lng_chat_intro_subtitle" = "Customize your intro";
|
||||
"lng_chat_intro_default_title" = "No messages here yet...";
|
||||
"lng_chat_intro_default_message" = "Send a message or tap on the greeting below";
|
||||
"lng_chat_intro_default_message" = "Send a message or click on the greeting below";
|
||||
"lng_chat_intro_enter_title" = "Enter Title";
|
||||
"lng_chat_intro_enter_message" = "Enter Message";
|
||||
"lng_chat_intro_choose_sticker" = "Choose Sticker";
|
||||
|
|
|
@ -153,8 +153,10 @@ BusinessRecipients FromMTP(
|
|||
}
|
||||
|
||||
BusinessDetails FromMTP(
|
||||
not_null<Session*> owner,
|
||||
const tl::conditional<MTPBusinessWorkHours> &hours,
|
||||
const tl::conditional<MTPBusinessLocation> &location) {
|
||||
const tl::conditional<MTPBusinessLocation> &location,
|
||||
const tl::conditional<MTPBusinessIntro> &intro) {
|
||||
auto result = BusinessDetails();
|
||||
if (hours) {
|
||||
const auto &data = hours->data();
|
||||
|
@ -179,6 +181,17 @@ BusinessDetails FromMTP(
|
|||
});
|
||||
}
|
||||
}
|
||||
if (intro) {
|
||||
const auto &data = intro->data();
|
||||
result.intro.title = qs(data.vtitle());
|
||||
result.intro.description = qs(data.vdescription());
|
||||
if (const auto document = data.vsticker()) {
|
||||
result.intro.sticker = owner->processDocument(*document);
|
||||
if (!result.intro.sticker->sticker()) {
|
||||
result.intro.sticker = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -334,22 +347,4 @@ WorkingIntervals ReplaceDayIntervals(
|
|||
return result.normalized();
|
||||
}
|
||||
|
||||
ChatIntro FromMTP(
|
||||
not_null<Session*> owner,
|
||||
const tl::conditional<MTPBusinessIntro> &intro) {
|
||||
auto result = ChatIntro();
|
||||
if (intro) {
|
||||
const auto &data = intro->data();
|
||||
result.title = qs(data.vtitle());
|
||||
result.description = qs(data.vdescription());
|
||||
if (const auto document = data.vsticker()) {
|
||||
result.sticker = owner->processDocument(*document);
|
||||
if (!result.sticker->sticker()) {
|
||||
result.sticker = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -182,12 +182,27 @@ struct BusinessLocation {
|
|||
const BusinessLocation &b) = default;
|
||||
};
|
||||
|
||||
struct ChatIntro {
|
||||
QString title;
|
||||
QString description;
|
||||
DocumentData *sticker = nullptr;
|
||||
|
||||
explicit operator bool() const {
|
||||
return !title.isEmpty() || !description.isEmpty();
|
||||
}
|
||||
|
||||
friend inline bool operator==(
|
||||
const ChatIntro &a,
|
||||
const ChatIntro &b) = default;
|
||||
};
|
||||
|
||||
struct BusinessDetails {
|
||||
WorkingHours hours;
|
||||
BusinessLocation location;
|
||||
ChatIntro intro;
|
||||
|
||||
explicit operator bool() const {
|
||||
return hours || location;
|
||||
return hours || location || intro;
|
||||
}
|
||||
|
||||
friend inline bool operator==(
|
||||
|
@ -196,8 +211,10 @@ struct BusinessDetails {
|
|||
};
|
||||
|
||||
[[nodiscard]] BusinessDetails FromMTP(
|
||||
not_null<Session*> owner,
|
||||
const tl::conditional<MTPBusinessWorkHours> &hours,
|
||||
const tl::conditional<MTPBusinessLocation> &location);
|
||||
const tl::conditional<MTPBusinessLocation> &location,
|
||||
const tl::conditional<MTPBusinessIntro> &intro);
|
||||
|
||||
enum class AwayScheduleType : uchar {
|
||||
Never = 0,
|
||||
|
@ -252,22 +269,4 @@ struct GreetingSettings {
|
|||
not_null<Session*> owner,
|
||||
const tl::conditional<MTPBusinessGreetingMessage> &message);
|
||||
|
||||
struct ChatIntro {
|
||||
QString title;
|
||||
QString description;
|
||||
DocumentData *sticker = nullptr;
|
||||
|
||||
explicit operator bool() const {
|
||||
return !title.isEmpty() || !description.isEmpty();
|
||||
}
|
||||
|
||||
friend inline bool operator==(
|
||||
const ChatIntro &a,
|
||||
const ChatIntro &b) = default;
|
||||
};
|
||||
|
||||
[[nodiscard]] ChatIntro FromMTP(
|
||||
not_null<Session*> owner,
|
||||
const tl::conditional<MTPBusinessIntro> &intro);
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -96,6 +96,40 @@ void BusinessInfo::saveWorkingHours(
|
|||
session->user()->setBusinessDetails(std::move(details));
|
||||
}
|
||||
|
||||
void BusinessInfo::saveChatIntro(ChatIntro data, Fn<void(QString)> fail) {
|
||||
const auto session = &_owner->session();
|
||||
auto details = session->user()->businessDetails();
|
||||
const auto &was = details.intro;
|
||||
if (was == data) {
|
||||
return;
|
||||
} else {
|
||||
const auto session = &_owner->session();
|
||||
using Flag = MTPaccount_UpdateBusinessIntro::Flag;
|
||||
session->api().request(MTPaccount_UpdateBusinessIntro(
|
||||
MTP_flags(data ? Flag::f_intro : Flag()),
|
||||
MTP_inputBusinessIntro(
|
||||
MTP_flags(data.sticker
|
||||
? MTPDinputBusinessIntro::Flag::f_sticker
|
||||
: MTPDinputBusinessIntro::Flag()),
|
||||
MTP_string(data.title),
|
||||
MTP_string(data.description),
|
||||
(data.sticker
|
||||
? data.sticker->mtpInput()
|
||||
: MTP_inputDocumentEmpty()))
|
||||
)).fail([=](const MTP::Error &error) {
|
||||
auto details = session->user()->businessDetails();
|
||||
details.intro = was;
|
||||
session->user()->setBusinessDetails(std::move(details));
|
||||
if (fail) {
|
||||
fail(error.type());
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
details.intro = std::move(data);
|
||||
session->user()->setBusinessDetails(std::move(details));
|
||||
}
|
||||
|
||||
void BusinessInfo::applyAwaySettings(AwaySettings data) {
|
||||
if (_awaySettings == data) {
|
||||
return;
|
||||
|
@ -184,54 +218,6 @@ rpl::producer<> BusinessInfo::greetingSettingsChanged() const {
|
|||
return _greetingSettingsChanged.events();
|
||||
}
|
||||
|
||||
void BusinessInfo::saveChatIntro(ChatIntro data, Fn<void(QString)> fail) {
|
||||
const auto &was = _chatIntro;
|
||||
if (was == data) {
|
||||
return;
|
||||
} else {
|
||||
const auto session = &_owner->session();
|
||||
using Flag = MTPaccount_UpdateBusinessIntro::Flag;
|
||||
session->api().request(MTPaccount_UpdateBusinessIntro(
|
||||
MTP_flags(data ? Flag::f_intro : Flag()),
|
||||
MTP_inputBusinessIntro(
|
||||
MTP_flags(data.sticker ? MTPDinputBusinessIntro::Flag::f_sticker : MTPDinputBusinessIntro::Flag()),
|
||||
MTP_string(data.title),
|
||||
MTP_string(data.description),
|
||||
(data.sticker
|
||||
? data.sticker->mtpInput()
|
||||
: MTP_inputDocumentEmpty()))
|
||||
)).fail([=](const MTP::Error &error) {
|
||||
_chatIntro = was;
|
||||
_chatIntroChanged.fire({});
|
||||
if (fail) {
|
||||
fail(error.type());
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
_chatIntro = std::move(data);
|
||||
_chatIntroChanged.fire({});
|
||||
}
|
||||
|
||||
void BusinessInfo::applyChatIntro(ChatIntro data) {
|
||||
if (_chatIntro == data) {
|
||||
return;
|
||||
}
|
||||
_chatIntro = data;
|
||||
_chatIntroChanged.fire({});
|
||||
}
|
||||
|
||||
ChatIntro BusinessInfo::chatIntro() const {
|
||||
return _chatIntro.value_or(ChatIntro());
|
||||
}
|
||||
|
||||
bool BusinessInfo::chatIntroLoaded() const {
|
||||
return _chatIntro.has_value();
|
||||
}
|
||||
|
||||
rpl::producer<> BusinessInfo::chatIntroChanged() const {
|
||||
return _chatIntroChanged.events();
|
||||
}
|
||||
|
||||
void BusinessInfo::preload() {
|
||||
preloadTimezones();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
void preload();
|
||||
|
||||
void saveWorkingHours(WorkingHours data, Fn<void(QString)> fail);
|
||||
void saveChatIntro(ChatIntro data, Fn<void(QString)> fail);
|
||||
|
||||
void saveAwaySettings(AwaySettings data, Fn<void(QString)> fail);
|
||||
void applyAwaySettings(AwaySettings data);
|
||||
|
@ -36,12 +37,6 @@ public:
|
|||
[[nodiscard]] bool greetingSettingsLoaded() const;
|
||||
[[nodiscard]] rpl::producer<> greetingSettingsChanged() const;
|
||||
|
||||
void saveChatIntro(ChatIntro data, Fn<void(QString)> fail);
|
||||
void applyChatIntro(ChatIntro data);
|
||||
[[nodiscard]] ChatIntro chatIntro() const;
|
||||
[[nodiscard]] bool chatIntroLoaded() const;
|
||||
[[nodiscard]] rpl::producer<> chatIntroChanged() const;
|
||||
|
||||
void preloadTimezones();
|
||||
[[nodiscard]] bool timezonesLoaded() const;
|
||||
[[nodiscard]] rpl::producer<Timezones> timezonesValue() const;
|
||||
|
@ -57,9 +52,6 @@ private:
|
|||
std::optional<GreetingSettings> _greetingSettings;
|
||||
rpl::event_stream<> _greetingSettingsChanged;
|
||||
|
||||
std::optional<ChatIntro> _chatIntro;
|
||||
rpl::event_stream<> _chatIntroChanged;
|
||||
|
||||
mtpRequestId _timezonesRequestId = 0;
|
||||
int32 _timezonesHash = 0;
|
||||
|
||||
|
|
|
@ -594,15 +594,15 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
|
|||
}
|
||||
|
||||
user->setBusinessDetails(FromMTP(
|
||||
&user->owner(),
|
||||
update.vbusiness_work_hours(),
|
||||
update.vbusiness_location()));
|
||||
update.vbusiness_location(),
|
||||
update.vbusiness_intro()));
|
||||
if (user->isSelf()) {
|
||||
user->owner().businessInfo().applyAwaySettings(
|
||||
FromMTP(&user->owner(), update.vbusiness_away_message()));
|
||||
user->owner().businessInfo().applyGreetingSettings(
|
||||
FromMTP(&user->owner(), update.vbusiness_greeting_message()));
|
||||
user->owner().businessInfo().applyChatIntro(
|
||||
FromMTP(&user->owner(), update.vbusiness_intro()));
|
||||
}
|
||||
|
||||
user->owner().stories().apply(user, update.vstories());
|
||||
|
|
|
@ -502,7 +502,7 @@ void Stickers::undoInstallLocally(uint64 setId) {
|
|||
Ui::LayerOption::KeepOther);
|
||||
}
|
||||
|
||||
bool Stickers::isFaved(not_null<const DocumentData*> document) {
|
||||
bool Stickers::isFaved(not_null<const DocumentData*> document) const {
|
||||
const auto &sets = this->sets();
|
||||
const auto it = sets.find(FavedSetId);
|
||||
if (it == sets.cend()) {
|
||||
|
|
|
@ -80,13 +80,13 @@ public:
|
|||
|
||||
void incrementSticker(not_null<DocumentData*> document);
|
||||
|
||||
bool updateNeeded(crl::time now) const {
|
||||
[[nodiscard]] bool updateNeeded(crl::time now) const {
|
||||
return updateNeeded(_lastUpdate, now);
|
||||
}
|
||||
void setLastUpdate(crl::time update) {
|
||||
_lastUpdate = update;
|
||||
}
|
||||
bool recentUpdateNeeded(crl::time now) const {
|
||||
[[nodiscard]] bool recentUpdateNeeded(crl::time now) const {
|
||||
return updateNeeded(_lastRecentUpdate, now);
|
||||
}
|
||||
void setLastRecentUpdate(crl::time update) {
|
||||
|
@ -95,19 +95,19 @@ public:
|
|||
}
|
||||
_lastRecentUpdate = update;
|
||||
}
|
||||
bool masksUpdateNeeded(crl::time now) const {
|
||||
[[nodiscard]] bool masksUpdateNeeded(crl::time now) const {
|
||||
return updateNeeded(_lastMasksUpdate, now);
|
||||
}
|
||||
void setLastMasksUpdate(crl::time update) {
|
||||
_lastMasksUpdate = update;
|
||||
}
|
||||
bool emojiUpdateNeeded(crl::time now) const {
|
||||
[[nodiscard]] bool emojiUpdateNeeded(crl::time now) const {
|
||||
return updateNeeded(_lastEmojiUpdate, now);
|
||||
}
|
||||
void setLastEmojiUpdate(crl::time update) {
|
||||
_lastEmojiUpdate = update;
|
||||
}
|
||||
bool recentAttachedUpdateNeeded(crl::time now) const {
|
||||
[[nodiscard]] bool recentAttachedUpdateNeeded(crl::time now) const {
|
||||
return updateNeeded(_lastRecentAttachedUpdate, now);
|
||||
}
|
||||
void setLastRecentAttachedUpdate(crl::time update) {
|
||||
|
@ -116,31 +116,31 @@ public:
|
|||
}
|
||||
_lastRecentAttachedUpdate = update;
|
||||
}
|
||||
bool favedUpdateNeeded(crl::time now) const {
|
||||
[[nodiscard]] bool favedUpdateNeeded(crl::time now) const {
|
||||
return updateNeeded(_lastFavedUpdate, now);
|
||||
}
|
||||
void setLastFavedUpdate(crl::time update) {
|
||||
_lastFavedUpdate = update;
|
||||
}
|
||||
bool featuredUpdateNeeded(crl::time now) const {
|
||||
[[nodiscard]] bool featuredUpdateNeeded(crl::time now) const {
|
||||
return updateNeeded(_lastFeaturedUpdate, now);
|
||||
}
|
||||
void setLastFeaturedUpdate(crl::time update) {
|
||||
_lastFeaturedUpdate = update;
|
||||
}
|
||||
bool featuredEmojiUpdateNeeded(crl::time now) const {
|
||||
[[nodiscard]] bool featuredEmojiUpdateNeeded(crl::time now) const {
|
||||
return updateNeeded(_lastFeaturedEmojiUpdate, now);
|
||||
}
|
||||
void setLastFeaturedEmojiUpdate(crl::time update) {
|
||||
_lastFeaturedEmojiUpdate = update;
|
||||
}
|
||||
bool savedGifsUpdateNeeded(crl::time now) const {
|
||||
[[nodiscard]] bool savedGifsUpdateNeeded(crl::time now) const {
|
||||
return updateNeeded(_lastSavedGifsUpdate, now);
|
||||
}
|
||||
void setLastSavedGifsUpdate(crl::time update) {
|
||||
_lastSavedGifsUpdate = update;
|
||||
}
|
||||
int featuredSetsUnreadCount() const {
|
||||
[[nodiscard]] int featuredSetsUnreadCount() const {
|
||||
return _featuredSetsUnreadCount.current();
|
||||
}
|
||||
void setFeaturedSetsUnreadCount(int count) {
|
||||
|
@ -149,58 +149,58 @@ public:
|
|||
[[nodiscard]] rpl::producer<int> featuredSetsUnreadCountValue() const {
|
||||
return _featuredSetsUnreadCount.value();
|
||||
}
|
||||
const StickersSets &sets() const {
|
||||
[[nodiscard]] const StickersSets &sets() const {
|
||||
return _sets;
|
||||
}
|
||||
StickersSets &setsRef() {
|
||||
[[nodiscard]] StickersSets &setsRef() {
|
||||
return _sets;
|
||||
}
|
||||
const StickersSetsOrder &setsOrder() const {
|
||||
[[nodiscard]] const StickersSetsOrder &setsOrder() const {
|
||||
return _setsOrder;
|
||||
}
|
||||
StickersSetsOrder &setsOrderRef() {
|
||||
[[nodiscard]] StickersSetsOrder &setsOrderRef() {
|
||||
return _setsOrder;
|
||||
}
|
||||
const StickersSetsOrder &maskSetsOrder() const {
|
||||
[[nodiscard]] const StickersSetsOrder &maskSetsOrder() const {
|
||||
return _maskSetsOrder;
|
||||
}
|
||||
StickersSetsOrder &maskSetsOrderRef() {
|
||||
[[nodiscard]] StickersSetsOrder &maskSetsOrderRef() {
|
||||
return _maskSetsOrder;
|
||||
}
|
||||
const StickersSetsOrder &emojiSetsOrder() const {
|
||||
[[nodiscard]] const StickersSetsOrder &emojiSetsOrder() const {
|
||||
return _emojiSetsOrder;
|
||||
}
|
||||
StickersSetsOrder &emojiSetsOrderRef() {
|
||||
[[nodiscard]] StickersSetsOrder &emojiSetsOrderRef() {
|
||||
return _emojiSetsOrder;
|
||||
}
|
||||
const StickersSetsOrder &featuredSetsOrder() const {
|
||||
[[nodiscard]] const StickersSetsOrder &featuredSetsOrder() const {
|
||||
return _featuredSetsOrder;
|
||||
}
|
||||
StickersSetsOrder &featuredSetsOrderRef() {
|
||||
[[nodiscard]] StickersSetsOrder &featuredSetsOrderRef() {
|
||||
return _featuredSetsOrder;
|
||||
}
|
||||
const StickersSetsOrder &featuredEmojiSetsOrder() const {
|
||||
[[nodiscard]] const StickersSetsOrder &featuredEmojiSetsOrder() const {
|
||||
return _featuredEmojiSetsOrder;
|
||||
}
|
||||
StickersSetsOrder &featuredEmojiSetsOrderRef() {
|
||||
[[nodiscard]] StickersSetsOrder &featuredEmojiSetsOrderRef() {
|
||||
return _featuredEmojiSetsOrder;
|
||||
}
|
||||
const StickersSetsOrder &archivedSetsOrder() const {
|
||||
[[nodiscard]] const StickersSetsOrder &archivedSetsOrder() const {
|
||||
return _archivedSetsOrder;
|
||||
}
|
||||
StickersSetsOrder &archivedSetsOrderRef() {
|
||||
[[nodiscard]] StickersSetsOrder &archivedSetsOrderRef() {
|
||||
return _archivedSetsOrder;
|
||||
}
|
||||
const StickersSetsOrder &archivedMaskSetsOrder() const {
|
||||
[[nodiscard]] const StickersSetsOrder &archivedMaskSetsOrder() const {
|
||||
return _archivedMaskSetsOrder;
|
||||
}
|
||||
StickersSetsOrder &archivedMaskSetsOrderRef() {
|
||||
[[nodiscard]] StickersSetsOrder &archivedMaskSetsOrderRef() {
|
||||
return _archivedMaskSetsOrder;
|
||||
}
|
||||
const SavedGifs &savedGifs() const {
|
||||
[[nodiscard]] const SavedGifs &savedGifs() const {
|
||||
return _savedGifs;
|
||||
}
|
||||
SavedGifs &savedGifsRef() {
|
||||
[[nodiscard]] SavedGifs &savedGifsRef() {
|
||||
return _savedGifs;
|
||||
}
|
||||
void removeFromRecentSet(not_null<DocumentData*> document);
|
||||
|
@ -214,7 +214,7 @@ public:
|
|||
const MTPDmessages_stickerSetInstallResultArchive &d);
|
||||
void installLocally(uint64 setId);
|
||||
void undoInstallLocally(uint64 setId);
|
||||
bool isFaved(not_null<const DocumentData*> document);
|
||||
[[nodiscard]] bool isFaved(not_null<const DocumentData*> document) const;
|
||||
void setFaved(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
not_null<DocumentData*> document,
|
||||
|
@ -235,12 +235,12 @@ public:
|
|||
const MTPmessages_FeaturedStickers &result);
|
||||
void gifsReceived(const QVector<MTPDocument> &items, uint64 hash);
|
||||
|
||||
std::vector<not_null<DocumentData*>> getListByEmoji(
|
||||
[[nodiscard]] std::vector<not_null<DocumentData*>> getListByEmoji(
|
||||
std::vector<EmojiPtr> emoji,
|
||||
uint64 seed,
|
||||
bool forceAllResults = false);
|
||||
std::optional<std::vector<not_null<EmojiPtr>>> getEmojiListFromSet(
|
||||
not_null<DocumentData*> document);
|
||||
[[nodiscard]] auto getEmojiListFromSet(not_null<DocumentData*> document)
|
||||
-> std::optional<std::vector<not_null<EmojiPtr>>>;
|
||||
|
||||
not_null<StickersSet*> feedSet(const MTPStickerSet &data);
|
||||
not_null<StickersSet*> feedSet(const MTPStickerSetCovered &data);
|
||||
|
@ -254,15 +254,14 @@ public:
|
|||
const QVector<MTPDocument> &documents);
|
||||
void newSetReceived(const MTPDmessages_stickerSet &set);
|
||||
|
||||
QString getSetTitle(const MTPDstickerSet &s);
|
||||
[[nodiscard]] QString getSetTitle(const MTPDstickerSet &s);
|
||||
|
||||
RecentStickerPack &getRecentPack() const;
|
||||
[[nodiscard]] RecentStickerPack &getRecentPack() const;
|
||||
|
||||
private:
|
||||
bool updateNeeded(crl::time lastUpdate, crl::time now) const {
|
||||
[[nodiscard]] bool updateNeeded(crl::time last, crl::time now) const {
|
||||
constexpr auto kUpdateTimeout = crl::time(3600'000);
|
||||
return (lastUpdate == 0)
|
||||
|| (now >= lastUpdate + kUpdateTimeout);
|
||||
return (last == 0) || (now >= last + kUpdateTimeout);
|
||||
}
|
||||
void checkFavedLimit(
|
||||
StickersSet &set,
|
||||
|
|
|
@ -4072,7 +4072,7 @@ void HistoryInner::refreshAboutView() {
|
|||
_history->delegateMixin()->delegate());
|
||||
}
|
||||
if (!info->inited) {
|
||||
session().api().requestFullPeer(_peer);
|
||||
session().api().requestFullPeer(user);
|
||||
}
|
||||
} else if (user->meRequiresPremiumToWrite()
|
||||
&& !user->session().premium()
|
||||
|
@ -4082,8 +4082,15 @@ void HistoryInner::refreshAboutView() {
|
|||
_history,
|
||||
_history->delegateMixin()->delegate());
|
||||
}
|
||||
} else {
|
||||
_aboutView = nullptr;
|
||||
} else if (!historyHeight()) {
|
||||
if (!_aboutView) {
|
||||
_aboutView = std::make_unique<HistoryView::AboutView>(
|
||||
_history,
|
||||
_history->delegateMixin()->delegate());
|
||||
}
|
||||
if (!user->isFullLoaded()) {
|
||||
session().api().requestFullPeer(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "history/view/history_view_about_view.h"
|
||||
|
||||
#include "api/api_premium.h"
|
||||
#include "apiwrap.h"
|
||||
#include "base/random.h"
|
||||
#include "chat_helpers/stickers_lottie.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "data/business/data_business_common.h"
|
||||
|
@ -70,47 +73,11 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class ChatIntroBox final : public ServiceBoxContent {
|
||||
public:
|
||||
ChatIntroBox(not_null<Element*> parent, Data::ChatIntro data);
|
||||
~ChatIntroBox();
|
||||
|
||||
int width() override;
|
||||
int top() override;
|
||||
QSize size() override;
|
||||
QString title() override;
|
||||
TextWithEntities subtitle() override;
|
||||
int buttonSkip() override;
|
||||
rpl::producer<QString> button() override;
|
||||
void draw(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
const QRect &geometry) override;
|
||||
ClickHandlerPtr createViewLink() override;
|
||||
|
||||
bool hideServiceText() override {
|
||||
return true;
|
||||
}
|
||||
|
||||
void stickerClearLoopPlayed() override;
|
||||
std::unique_ptr<StickerPlayer> stickerTakePlayer(
|
||||
not_null<DocumentData*> data,
|
||||
const Lottie::ColorReplacements *replacements) override;
|
||||
|
||||
bool hasHeavyPart() override;
|
||||
void unloadHeavyPart() override;
|
||||
|
||||
private:
|
||||
const not_null<Element*> _parent;
|
||||
const Data::ChatIntro _data;
|
||||
mutable std::optional<Sticker> _sticker;
|
||||
|
||||
};
|
||||
|
||||
auto GenerateChatIntro(
|
||||
not_null<Element*> parent,
|
||||
Element *replacing,
|
||||
const Data::ChatIntro &data)
|
||||
const Data::ChatIntro &data,
|
||||
Fn<void(not_null<DocumentData*>)> helloChosen)
|
||||
-> Fn<void(Fn<void(std::unique_ptr<MediaInBubble::Part>)>)> {
|
||||
return [=](Fn<void(std::unique_ptr<MediaInBubble::Part>)> push) {
|
||||
auto pushText = [&](
|
||||
|
@ -137,8 +104,19 @@ auto GenerateChatIntro(
|
|||
: st::chatIntroMargin);
|
||||
const auto sticker = [=] {
|
||||
using Tag = ChatHelpers::StickerLottieSize;
|
||||
auto sticker = data.sticker;
|
||||
if (!sticker) {
|
||||
const auto api = &parent->history()->session().api();
|
||||
const auto &list = api->premium().helloStickers();
|
||||
if (!list.empty()) {
|
||||
sticker = list[base::RandomIndex(list.size())];
|
||||
if (helloChosen) {
|
||||
helloChosen(sticker);
|
||||
}
|
||||
}
|
||||
}
|
||||
return StickerInBubblePart::Data{
|
||||
.sticker = data.sticker,
|
||||
.sticker = sticker,
|
||||
.size = st::chatIntroStickerSize,
|
||||
.cacheTag = Tag::ChatIntroHelloSticker,
|
||||
};
|
||||
|
@ -220,96 +198,6 @@ bool PremiumRequiredBox::hasHeavyPart() {
|
|||
void PremiumRequiredBox::unloadHeavyPart() {
|
||||
}
|
||||
|
||||
ChatIntroBox::ChatIntroBox(not_null<Element*> parent, Data::ChatIntro data)
|
||||
: _parent(parent)
|
||||
, _data(data) {
|
||||
if (const auto document = data.sticker) {
|
||||
if (const auto sticker = document->sticker()) {
|
||||
const auto skipPremiumEffect = true;
|
||||
_sticker.emplace(_parent, document, skipPremiumEffect, _parent);
|
||||
_sticker->initSize(st::chatIntroStickerSize);
|
||||
_sticker->setCustomCachingTag(
|
||||
ChatHelpers::StickerLottieSize::ChatIntroHelloSticker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChatIntroBox::~ChatIntroBox() = default;
|
||||
|
||||
int ChatIntroBox::width() {
|
||||
return st::chatIntroWidth;
|
||||
}
|
||||
|
||||
int ChatIntroBox::top() {
|
||||
return st::msgServiceGiftBoxButtonMargins.top();
|
||||
}
|
||||
|
||||
QSize ChatIntroBox::size() {
|
||||
return { st::msgServicePhotoWidth, st::msgServicePhotoWidth };
|
||||
}
|
||||
|
||||
QString ChatIntroBox::title() {
|
||||
return _data ? _data.title : tr::lng_chat_intro_default_title(tr::now);
|
||||
}
|
||||
|
||||
int ChatIntroBox::buttonSkip() {
|
||||
return st::storyMentionButtonSkip;
|
||||
}
|
||||
|
||||
rpl::producer<QString> ChatIntroBox::button() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TextWithEntities ChatIntroBox::subtitle() {
|
||||
return {
|
||||
(_data
|
||||
? _data.description
|
||||
: tr::lng_chat_intro_default_message(tr::now))
|
||||
};
|
||||
}
|
||||
|
||||
ClickHandlerPtr ChatIntroBox::createViewLink() {
|
||||
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
|
||||
const auto my = context.other.value<ClickHandlerContext>();
|
||||
if (const auto controller = my.sessionWindow.get()) {
|
||||
Settings::ShowPremium(controller, u"require_premium"_q);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ChatIntroBox::draw(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
const QRect &geometry) {
|
||||
if (_sticker) {
|
||||
_sticker->draw(p, context, geometry);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatIntroBox::stickerClearLoopPlayed() {
|
||||
if (_sticker) {
|
||||
_sticker->stickerClearLoopPlayed();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<StickerPlayer> ChatIntroBox::stickerTakePlayer(
|
||||
not_null<DocumentData*> data,
|
||||
const Lottie::ColorReplacements *replacements) {
|
||||
return _sticker
|
||||
? _sticker->stickerTakePlayer(data, replacements)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
bool ChatIntroBox::hasHeavyPart() {
|
||||
return _sticker && _sticker->hasHeavyPart();
|
||||
}
|
||||
|
||||
void ChatIntroBox::unloadHeavyPart() {
|
||||
if (_sticker) {
|
||||
_sticker->unloadHeavyPart();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AboutView::AboutView(
|
||||
|
@ -339,21 +227,22 @@ HistoryItem *AboutView::item() const {
|
|||
}
|
||||
|
||||
bool AboutView::refresh() {
|
||||
const auto bot = _history->peer->asUser();
|
||||
const auto info = bot ? bot->botInfo.get() : nullptr;
|
||||
const auto user = _history->peer->asUser();
|
||||
const auto info = user ? user->botInfo.get() : nullptr;
|
||||
if (!info) {
|
||||
if (bot
|
||||
&& bot->meRequiresPremiumToWrite()
|
||||
&& !bot->session().premium()
|
||||
&& _history->isDisplayedEmpty()) {
|
||||
if (user && _history->isDisplayedEmpty()) {
|
||||
if (_item) {
|
||||
return false;
|
||||
} else if (user->meRequiresPremiumToWrite()
|
||||
&& !user->session().premium()) {
|
||||
setItem(makePremiumRequired(), nullptr);
|
||||
} else {
|
||||
makeIntro(user);
|
||||
}
|
||||
_item = makePremiumRequired();
|
||||
return true;
|
||||
}
|
||||
if (_item) {
|
||||
_item = {};
|
||||
setItem({}, nullptr);
|
||||
return true;
|
||||
}
|
||||
_version = 0;
|
||||
|
@ -364,10 +253,14 @@ bool AboutView::refresh() {
|
|||
return false;
|
||||
}
|
||||
_version = version;
|
||||
_item = makeAboutBot(info);
|
||||
setItem(makeAboutBot(info), nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AboutView::makeIntro(not_null<UserData*> user) {
|
||||
make(user->businessDetails().intro);
|
||||
}
|
||||
|
||||
void AboutView::make(Data::ChatIntro data) {
|
||||
const auto item = _history->makeMessage({
|
||||
.id = _history->nextNonHistoryEntryId(),
|
||||
|
@ -377,31 +270,58 @@ void AboutView::make(Data::ChatIntro data) {
|
|||
.from = _history->peer->id,
|
||||
}, PreparedServiceText{ { } });
|
||||
|
||||
if (data.sticker) {
|
||||
_helloChosen = nullptr;
|
||||
} else if (_helloChosen) {
|
||||
data.sticker = _helloChosen;
|
||||
}
|
||||
|
||||
auto owned = AdminLog::OwnedItem(_delegate, item);
|
||||
const auto helloChosen = [=](not_null<DocumentData*> sticker) {
|
||||
setHelloChosen(sticker);
|
||||
};
|
||||
owned->overrideMedia(std::make_unique<HistoryView::MediaInBubble>(
|
||||
owned.get(),
|
||||
GenerateChatIntro(owned.get(), _item.get(), data),
|
||||
GenerateChatIntro(owned.get(), _item.get(), data, helloChosen),
|
||||
HistoryView::MediaInBubbleDescriptor{
|
||||
.maxWidth = st::chatIntroWidth,
|
||||
.service = true,
|
||||
.hideServiceText = true,
|
||||
}));
|
||||
if (!data.sticker && _helloChosen) {
|
||||
data.sticker = _helloChosen;
|
||||
}
|
||||
setItem(std::move(owned), data.sticker);
|
||||
}
|
||||
|
||||
void AboutView::setItem(AdminLog::OwnedItem item, DocumentData *sticker) {
|
||||
if (const auto was = _item ? _item->data().get() : nullptr) {
|
||||
void AboutView::toggleStickerRegistered(bool registered) {
|
||||
if (const auto item = _item ? _item->data().get() : nullptr) {
|
||||
if (_sticker) {
|
||||
was->history()->owner().unregisterDocumentItem(_sticker, was);
|
||||
const auto owner = &item->history()->owner();
|
||||
if (registered) {
|
||||
owner->registerDocumentItem(_sticker, item);
|
||||
} else {
|
||||
owner->unregisterDocumentItem(_sticker, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!registered) {
|
||||
_sticker = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AboutView::setHelloChosen(not_null<DocumentData*> sticker) {
|
||||
_helloChosen = sticker;
|
||||
toggleStickerRegistered(false);
|
||||
_sticker = sticker;
|
||||
toggleStickerRegistered(true);
|
||||
}
|
||||
|
||||
void AboutView::setItem(AdminLog::OwnedItem item, DocumentData *sticker) {
|
||||
toggleStickerRegistered(false);
|
||||
_item = std::move(item);
|
||||
_sticker = sticker;
|
||||
if (const auto now = _item ? _item->data().get() : nullptr) {
|
||||
if (_sticker) {
|
||||
now->history()->owner().registerDocumentItem(_sticker, now);
|
||||
}
|
||||
}
|
||||
toggleStickerRegistered(true);
|
||||
}
|
||||
|
||||
AdminLog::OwnedItem AboutView::makeAboutBot(not_null<BotInfo*> info) {
|
||||
|
|
|
@ -36,11 +36,15 @@ public:
|
|||
private:
|
||||
[[nodiscard]] AdminLog::OwnedItem makeAboutBot(not_null<BotInfo*> info);
|
||||
[[nodiscard]] AdminLog::OwnedItem makePremiumRequired();
|
||||
void makeIntro(not_null<UserData*> user);
|
||||
void setItem(AdminLog::OwnedItem item, DocumentData *sticker);
|
||||
void setHelloChosen(not_null<DocumentData*> sticker);
|
||||
void toggleStickerRegistered(bool registered);
|
||||
|
||||
const not_null<History*> _history;
|
||||
const not_null<ElementDelegate*> _delegate;
|
||||
AdminLog::OwnedItem _item;
|
||||
DocumentData *_helloChosen = nullptr;
|
||||
DocumentData *_sticker = nullptr;
|
||||
int _version = 0;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "history/view/media/history_view_media_common.h"
|
||||
#include "history/view/media/history_view_sticker_player.h"
|
||||
#include "history/view/history_view_about_view.h"
|
||||
|
@ -564,10 +565,8 @@ void ChatIntro::setupContent(
|
|||
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
const auto session = &controller->session();
|
||||
const auto info = &session->data().businessInfo();
|
||||
const auto current = info->chatIntro();
|
||||
_intro = controller->session().user()->businessDetails().intro;
|
||||
|
||||
_intro = info->chatIntro();
|
||||
const auto change = [=](Fn<void(Data::ChatIntro &)> modify) {
|
||||
auto intro = _intro.current();
|
||||
modify(intro);
|
||||
|
@ -584,12 +583,12 @@ void ChatIntro::setupContent(
|
|||
const auto title = AddPartInput(
|
||||
content,
|
||||
tr::lng_chat_intro_enter_title(),
|
||||
current.title,
|
||||
_intro.current().title,
|
||||
PartLimit(session, u"intro_title_length_limit"_q, 32));
|
||||
const auto description = AddPartInput(
|
||||
content,
|
||||
tr::lng_chat_intro_enter_message(),
|
||||
current.description,
|
||||
_intro.current().description,
|
||||
PartLimit(session, u"intro_description_length_limit"_q, 70));
|
||||
content->add(CreateIntroStickerButton(
|
||||
content,
|
||||
|
|
Loading…
Add table
Reference in a new issue