diff --git a/Telegram/SourceFiles/api/api_peer_photo.cpp b/Telegram/SourceFiles/api/api_peer_photo.cpp index b29769912b..9d710da6fb 100644 --- a/Telegram/SourceFiles/api/api_peer_photo.cpp +++ b/Telegram/SourceFiles/api/api_peer_photo.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "data/data_channel.h" #include "data/data_chat.h" +#include "data/data_document.h" #include "data/data_file_origin.h" #include "data/data_peer.h" #include "data/data_photo.h" @@ -32,7 +33,7 @@ namespace { constexpr auto kSharedMediaLimit = 100; -SendMediaReady PreparePeerPhoto( +[[nodiscard]] SendMediaReady PreparePeerPhoto( MTP::DcId dcId, PeerId peerId, QImage &&image) { @@ -99,6 +100,53 @@ SendMediaReady PreparePeerPhoto( 0); } +[[nodiscard]] std::optional PrepareMtpMarkup( + not_null session, + const PeerPhoto::UserPhoto &d) { + const auto &documentId = d.markupDocumentId; + const auto &colors = d.markupColors; + if (!documentId || colors.empty()) { + return std::nullopt; + } + const auto document = session->data().document(documentId); + if (const auto sticker = document->sticker()) { + if (sticker->isStatic()) { + return std::nullopt; + } + const auto serializeColor = [](const QColor &color) { + return (quint32(std::clamp(color.red(), 0, 255)) << 16) + | (quint32(std::clamp(color.green(), 0, 255)) << 8) + | quint32(std::clamp(color.blue(), 0, 255)); + }; + + auto mtpColors = QVector(); + mtpColors.reserve(colors.size()); + ranges::transform( + colors, + ranges::back_inserter(mtpColors), + [&](const QColor &c) { return MTP_int(serializeColor(c)); }); + if (sticker->set.id && sticker->set.accessHash) { + return MTP_videoSizeStickerMarkup( + MTP_inputStickerSetID( + MTP_long(sticker->set.id), + MTP_long(sticker->set.accessHash)), + MTP_long(document->id), + MTP_vector(mtpColors)); + } else if (!sticker->set.shortName.isEmpty()) { + return MTP_videoSizeStickerMarkup( + MTP_inputStickerSetShortName( + MTP_string(sticker->set.shortName)), + MTP_long(document->id), + MTP_vector(mtpColors)); + } else { + return MTP_videoSizeEmojiMarkup( + MTP_long(document->id), + MTP_vector(mtpColors)); + } + } + return std::nullopt; +} + } // namespace PeerPhoto::PeerPhoto(not_null api) @@ -109,20 +157,20 @@ PeerPhoto::PeerPhoto(not_null api) // only queued, because it is not constructed yet. _session->uploader().photoReady( ) | rpl::start_with_next([=](const Storage::UploadedMedia &data) { - ready(data.fullId, data.info.file); + ready(data.fullId, data.info.file, std::nullopt); }, _session->lifetime()); }); } void PeerPhoto::upload( not_null peer, - QImage &&image, + UserPhoto &&photo, Fn done) { - upload(peer, std::move(image), UploadType::Default, std::move(done)); + upload(peer, std::move(photo), UploadType::Default, std::move(done)); } -void PeerPhoto::uploadFallback(not_null peer, QImage &&image) { - upload(peer, std::move(image), UploadType::Fallback, nullptr); +void PeerPhoto::uploadFallback(not_null peer, UserPhoto &&photo) { + upload(peer, std::move(photo), UploadType::Fallback, nullptr); } void PeerPhoto::updateSelf( @@ -159,14 +207,11 @@ void PeerPhoto::updateSelf( void PeerPhoto::upload( not_null peer, - QImage &&image, + UserPhoto &&photo, UploadType type, Fn done) { peer = peer->migrateToOrMe(); - const auto ready = PreparePeerPhoto( - _api.instance().mainDcId(), - peer->id, - std::move(image)); + const auto mtpMarkup = PrepareMtpMarkup(_session, photo); const auto fakeId = FullMsgId( peer->id, @@ -182,11 +227,19 @@ void PeerPhoto::upload( _uploads.emplace( fakeId, UploadValue{ peer, type, std::move(done) }); - _session->uploader().uploadMedia(fakeId, ready); + if (mtpMarkup) { + ready(fakeId, std::nullopt, mtpMarkup); + } else { + const auto ready = PreparePeerPhoto( + _api.instance().mainDcId(), + peer->id, + base::take(photo.image)); + _session->uploader().uploadMedia(fakeId, ready); + } } -void PeerPhoto::suggest(not_null peer, QImage &&image) { - upload(peer, std::move(image), UploadType::Suggestion, nullptr); +void PeerPhoto::suggest(not_null peer, UserPhoto &&photo) { + upload(peer, std::move(photo), UploadType::Suggestion, nullptr); } void PeerPhoto::clear(not_null photo) { @@ -287,7 +340,10 @@ void PeerPhoto::set(not_null peer, not_null photo) { } } -void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) { +void PeerPhoto::ready( + const FullMsgId &msgId, + std::optional file, + std::optional videoSize) { const auto maybeUploadValue = _uploads.take(msgId); if (!maybeUploadValue) { return; @@ -302,15 +358,16 @@ void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) { } }; if (peer->isSelf()) { + using Flag = MTPphotos_UploadProfilePhoto::Flag; + const auto none = MTPphotos_UploadProfilePhoto::Flags(0); _api.request(MTPphotos_UploadProfilePhoto( - MTP_flags(MTPphotos_UploadProfilePhoto::Flag::f_file - | ((type == UploadType::Fallback) - ? MTPphotos_UploadProfilePhoto::Flag::f_fallback - : MTPphotos_UploadProfilePhoto::Flags(0))), - file, + MTP_flags((file ? Flag::f_file : none) + | (videoSize ? Flag::f_video_emoji_markup : none) + | ((type == UploadType::Fallback) ? Flag::f_fallback : none)), + file ? (*file) : MTPInputFile(), MTPInputFile(), // video MTPdouble(), // video_start_ts - MTPVideoSize() // video_emoji_markup + videoSize ? (*videoSize) : MTPVideoSize() // video_emoji_markup )).done([=](const MTPphotos_Photo &result) { const auto photoId = _session->data().processPhoto( result.data().vphoto())->id; @@ -326,25 +383,31 @@ void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) { }).send(); } else if (const auto chat = peer->asChat()) { const auto history = _session->data().history(chat); + using Flag = MTPDinputChatUploadedPhoto::Flag; + const auto none = MTPDinputChatUploadedPhoto::Flags(0); history->sendRequestId = _api.request(MTPmessages_EditChatPhoto( chat->inputChat, MTP_inputChatUploadedPhoto( - MTP_flags(MTPDinputChatUploadedPhoto::Flag::f_file), - file, + MTP_flags((file ? Flag::f_file : none) + | (videoSize ? Flag::f_video_emoji_markup : none)), + file ? (*file) : MTPInputFile(), MTPInputFile(), // video MTPdouble(), // video_start_ts - MTPVideoSize()) // video_emoji_markup + videoSize ? (*videoSize) : MTPVideoSize()) // video_emoji_markup )).done(applier).afterRequest(history->sendRequestId).send(); } else if (const auto channel = peer->asChannel()) { + using Flag = MTPDinputChatUploadedPhoto::Flag; + const auto none = MTPDinputChatUploadedPhoto::Flags(0); const auto history = _session->data().history(channel); history->sendRequestId = _api.request(MTPchannels_EditPhoto( channel->inputChannel, MTP_inputChatUploadedPhoto( - MTP_flags(MTPDinputChatUploadedPhoto::Flag::f_file), - file, + MTP_flags((file ? Flag::f_file : none) + | (videoSize ? Flag::f_video_emoji_markup : none)), + file ? (*file) : MTPInputFile(), MTPInputFile(), // video MTPdouble(), // video_start_ts - MTPVideoSize()) // video_emoji_markup + videoSize ? (*videoSize) : MTPVideoSize()) // video_emoji_markup )).done(applier).afterRequest(history->sendRequestId).send(); } else if (const auto user = peer->asUser()) { using Flag = MTPphotos_UploadContactProfilePhoto::Flag; @@ -354,7 +417,7 @@ void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) { ? Flag::f_suggest : Flag::f_save)), user->inputUser, - file, + *file, MTPInputFile(), // video MTPdouble() // video_start_ts )).done([=](const MTPphotos_Photo &result) { diff --git a/Telegram/SourceFiles/api/api_peer_photo.h b/Telegram/SourceFiles/api/api_peer_photo.h index 74aaaa09a4..03920d3ef5 100644 --- a/Telegram/SourceFiles/api/api_peer_photo.h +++ b/Telegram/SourceFiles/api/api_peer_photo.h @@ -33,16 +33,22 @@ public: Group, }; + struct UserPhoto { + QImage image; + DocumentId markupDocumentId = 0; + std::vector markupColors; + }; + void upload( not_null peer, - QImage &&image, + UserPhoto &&photo, Fn done = nullptr); - void uploadFallback(not_null peer, QImage &&image); + void uploadFallback(not_null peer, UserPhoto &&photo); void updateSelf( not_null photo, Data::FileOrigin origin, Fn done = nullptr); - void suggest(not_null peer, QImage &&image); + void suggest(not_null peer, UserPhoto &&photo); void clear(not_null photo); void clearPersonal(not_null user); void set(not_null peer, not_null photo); @@ -68,10 +74,13 @@ private: Fallback, }; - void ready(const FullMsgId &msgId, const MTPInputFile &file); + void ready( + const FullMsgId &msgId, + std::optional file, + std::optional videoSize); void upload( not_null peer, - QImage &&image, + UserPhoto &&photo, UploadType type, Fn done); diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp index eec7e77f1a..697a860daf 100644 --- a/Telegram/SourceFiles/boxes/add_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp @@ -104,7 +104,7 @@ void ChatCreateDone( if (!image.isNull()) { chat->session().api().peerPhoto().upload( chat, - std::move(image)); + { std::move(image) }); } if (ttlPeriod) { chat->setMessagesTTL(ttlPeriod); @@ -828,7 +828,7 @@ void GroupInfoBox::createChannel( if (!image.isNull()) { channel->session().api().peerPhoto().upload( channel, - std::move(image)); + { std::move(image) }); } if (_ttlPeriod && channel->isMegagroup()) { channel->setMessagesTTL(_ttlPeriod); diff --git a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp index d1a57c91c7..89115f0bf5 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp @@ -215,7 +215,7 @@ void Controller::initNameFields( } else { user->session().api().peerPhoto().upload( user, - base::duplicate(*personal)); + { base::duplicate(*personal) }); } } }; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index 39c9963cd5..0754484bd8 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -1879,7 +1879,9 @@ void Controller::savePhoto() { ? _controls.photo->takeResultImage() : QImage(); if (!image.isNull()) { - _peer->session().api().peerPhoto().upload(_peer, std::move(image)); + _peer->session().api().peerPhoto().upload( + _peer, + { std::move(image) }); } _box->closeBox(); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_userpic_suggestion.cpp b/Telegram/SourceFiles/history/view/media/history_view_userpic_suggestion.cpp index c20bf270c1..1d4603a14e 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_userpic_suggestion.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_userpic_suggestion.cpp @@ -79,7 +79,7 @@ void ShowUserpicSuggestion( && original->constBits() == image.constBits()) { peerPhotos.updateSelf(photo, itemId, setDone); } else { - peerPhotos.upload(user, std::move(image), setDone); + peerPhotos.upload(user, { std::move(image) }, setDone); } }; using namespace Editor; diff --git a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp index c3b4e05cbe..8074445ba7 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp @@ -449,12 +449,12 @@ void Cover::refreshUploadPhotoOverlay() { _userpic->showCustom(base::duplicate(image)); _peer->session().api().peerPhoto().upload( _peer, - std::move(image)); + { std::move(image) }); break; case ChosenType::Suggest: _peer->session().api().peerPhoto().suggest( _peer, - std::move(image)); + { std::move(image) }); break; } }); @@ -478,7 +478,7 @@ void Cover::setupChangePersonal() { if (chosen.type == Ui::UserpicButton::ChosenType::Suggest) { _peer->session().api().peerPhoto().suggest( _peer, - std::move(chosen.image)); + { std::move(chosen.image) }); } else { _personalChosen = std::move(chosen.image); _userpic->showCustom(base::duplicate(*_personalChosen)); diff --git a/Telegram/SourceFiles/intro/intro_step.cpp b/Telegram/SourceFiles/intro/intro_step.cpp index 58107ec0ac..61c7c93918 100644 --- a/Telegram/SourceFiles/intro/intro_step.cpp +++ b/Telegram/SourceFiles/intro/intro_step.cpp @@ -226,7 +226,9 @@ void Step::createSession( session.saveSettingsDelayed(); } if (!photo.isNull()) { - session.api().peerPhoto().upload(session.user(), std::move(photo)); + session.api().peerPhoto().upload( + session.user(), + { std::move(photo) }); } account->appConfig().refresh(); if (session.supportMode()) { diff --git a/Telegram/SourceFiles/settings/settings_information.cpp b/Telegram/SourceFiles/settings/settings_information.cpp index 1b0d0febb1..631056e3e0 100644 --- a/Telegram/SourceFiles/settings/settings_information.cpp +++ b/Telegram/SourceFiles/settings/settings_information.cpp @@ -256,7 +256,7 @@ void SetupPhoto( auto &image = chosen.image; UpdatePhotoLocally(self, image); photo->showCustom(base::duplicate(image)); - self->session().api().peerPhoto().upload(self, std::move(image)); + self->session().api().peerPhoto().upload(self, { std::move(image) }); }, upload->lifetime()); const auto name = Ui::CreateChild( diff --git a/Telegram/SourceFiles/settings/settings_main.cpp b/Telegram/SourceFiles/settings/settings_main.cpp index 039a276d3e..4a06d1b21c 100644 --- a/Telegram/SourceFiles/settings/settings_main.cpp +++ b/Telegram/SourceFiles/settings/settings_main.cpp @@ -144,7 +144,9 @@ Cover::Cover( Ui::UserpicButton::ChosenImage chosen) { auto &image = chosen.image; _userpic->showCustom(base::duplicate(image)); - _user->session().api().peerPhoto().upload(_user, std::move(image)); + _user->session().api().peerPhoto().upload( + _user, + { std::move(image) }); }); _badge.setPremiumClickCallback([=] { diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index f210937d3d..f983f856c4 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -1171,7 +1171,7 @@ object_ptr ProfilePhotoPrivacyController::setupBelowWidget( } else if (!state->localOriginal.isNull()) { controller->session().api().peerPhoto().uploadFallback( self, - base::take(state->localOriginal)); + { base::take(state->localOriginal) }); } }; diff --git a/Telegram/SourceFiles/ui/controls/userpic_button.h b/Telegram/SourceFiles/ui/controls/userpic_button.h index cdb3a0a258..ef0e8f8002 100644 --- a/Telegram/SourceFiles/ui/controls/userpic_button.h +++ b/Telegram/SourceFiles/ui/controls/userpic_button.h @@ -83,6 +83,10 @@ public: struct ChosenImage { QImage image; ChosenType type = ChosenType::Set; + struct { + DocumentId documentId = 0; + std::vector colors; + } markup; }; // Role::OpenPhoto