mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-26 23:43:06 +02:00
Support personal photo edit in EditContactBox.
This commit is contained in:
parent
c7c652a277
commit
1dd83f3d34
26 changed files with 484 additions and 182 deletions
|
@ -208,6 +208,7 @@ void PeerPhoto::clearPersonal(not_null<UserData*> user) {
|
|||
_session->data().processUsers(data.vusers());
|
||||
});
|
||||
}).send();
|
||||
|
||||
if (!user->userpicPhotoUnknown() && user->hasPersonalPhoto()) {
|
||||
_session->storage().remove(Storage::UserPhotosRemoveOne(
|
||||
peerToUser(user->id),
|
||||
|
@ -304,6 +305,9 @@ void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) {
|
|||
_session->data().processPhoto(data.vphoto());
|
||||
_session->data().processUsers(data.vusers());
|
||||
});
|
||||
if (!suggestion) {
|
||||
user->updateFullForced();
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2416,6 +2416,12 @@ void ApiWrap::refreshFileReference(
|
|||
} else {
|
||||
fail();
|
||||
}
|
||||
}, [&](Data::FileOriginFullUser data) {
|
||||
if (const auto user = _session->data().user(data.userId)) {
|
||||
request(MTPusers_GetFullUser(user->inputUser));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}, [&](Data::FileOriginPeerPhoto data) {
|
||||
fail();
|
||||
}, [&](Data::FileOriginStickerSet data) {
|
||||
|
|
|
@ -465,7 +465,7 @@ void GroupInfoBox::prepare() {
|
|||
_photo.create(
|
||||
this,
|
||||
&_navigation->parentController()->window(),
|
||||
Ui::UserpicButton::Role::ChangePhoto,
|
||||
Ui::UserpicButton::Role::ChoosePhoto,
|
||||
st::defaultUserpicButton);
|
||||
_title.create(
|
||||
this,
|
||||
|
|
|
@ -86,7 +86,6 @@ void GiftBox(
|
|||
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
|
||||
top,
|
||||
user,
|
||||
Ui::UserpicButton::Role::Custom,
|
||||
st::defaultUserpicButton);
|
||||
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
top->widthValue(
|
||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/toast/toast.h"
|
||||
#include "main/main_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_peer_photo.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_info.h"
|
||||
|
@ -41,7 +42,8 @@ void SendRequest(
|
|||
bool sharePhone,
|
||||
const QString &first,
|
||||
const QString &last,
|
||||
const QString &phone) {
|
||||
const QString &phone,
|
||||
Fn<void()> done) {
|
||||
const auto wasContact = user->isContact();
|
||||
using Flag = MTPcontacts_AddContact::Flag;
|
||||
user->session().api().request(MTPcontacts_AddContact(
|
||||
|
@ -73,6 +75,7 @@ void SendRequest(
|
|||
}
|
||||
box->closeBox();
|
||||
}
|
||||
done();
|
||||
}).send();
|
||||
}
|
||||
|
||||
|
@ -103,6 +106,7 @@ private:
|
|||
QString _phone;
|
||||
Fn<void()> _focus;
|
||||
Fn<void()> _save;
|
||||
Fn<std::optional<QImage>()> _updatedPersonalPhoto;
|
||||
|
||||
};
|
||||
|
||||
|
@ -146,6 +150,7 @@ void Controller::setupCover() {
|
|||
? tr::lng_contact_mobile_hidden()
|
||||
: rpl::single(Ui::FormatPhone(_phone)))),
|
||||
style::margins());
|
||||
_updatedPersonalPhoto = [=] { return cover->updatedPersonalPhoto(); };
|
||||
}
|
||||
|
||||
void Controller::setupNameFields() {
|
||||
|
@ -199,13 +204,29 @@ void Controller::initNameFields(
|
|||
(inverted ? last : first)->showError();
|
||||
return;
|
||||
}
|
||||
const auto user = _user;
|
||||
const auto personal = _updatedPersonalPhoto
|
||||
? _updatedPersonalPhoto()
|
||||
: std::nullopt;
|
||||
const auto done = [=] {
|
||||
if (personal) {
|
||||
if (personal->isNull()) {
|
||||
user->session().api().peerPhoto().clearPersonal(user);
|
||||
} else {
|
||||
user->session().api().peerPhoto().upload(
|
||||
user,
|
||||
base::duplicate(*personal));
|
||||
}
|
||||
}
|
||||
};
|
||||
SendRequest(
|
||||
Ui::MakeWeak(_box),
|
||||
_user,
|
||||
user,
|
||||
_sharePhone && _sharePhone->checked(),
|
||||
firstValue,
|
||||
lastValue,
|
||||
_phone);
|
||||
_phone,
|
||||
done);
|
||||
};
|
||||
const auto submit = [=] {
|
||||
const auto firstValue = first->getLastText().trimmed();
|
||||
|
|
|
@ -85,11 +85,7 @@ EditParticipantBox::Inner::Inner(
|
|||
: RpWidget(parent)
|
||||
, _peer(peer)
|
||||
, _user(user)
|
||||
, _userPhoto(
|
||||
this,
|
||||
_user,
|
||||
Ui::UserpicButton::Role::Custom,
|
||||
st::rightsPhotoButton)
|
||||
, _userPhoto(this, _user, st::rightsPhotoButton)
|
||||
, _hasAdminRights(hasAdminRights)
|
||||
, _rows(this) {
|
||||
_rows->heightValue(
|
||||
|
@ -97,7 +93,7 @@ EditParticipantBox::Inner::Inner(
|
|||
resizeToWidth(width());
|
||||
}, lifetime());
|
||||
|
||||
_userPhoto->setPointerCursor(false);
|
||||
_userPhoto->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
_userName.setText(
|
||||
st::rightsNameStyle,
|
||||
_user->name(),
|
||||
|
|
|
@ -470,9 +470,10 @@ object_ptr<Ui::RpWidget> Controller::createPhotoEdit() {
|
|||
_wrap,
|
||||
object_ptr<Ui::UserpicButton>(
|
||||
_wrap,
|
||||
&_navigation->parentController()->window(),
|
||||
_navigation->parentController(),
|
||||
_peer,
|
||||
Ui::UserpicButton::Role::ChangePhoto,
|
||||
Ui::UserpicButton::Source::PeerPhoto,
|
||||
st::defaultUserpicButton),
|
||||
st::editPeerPhotoMargins);
|
||||
_controls.photo = photoWrap->entity();
|
||||
|
|
|
@ -1244,7 +1244,6 @@ void Panel::refreshTopButton() {
|
|||
auto joinAsToggle = object_ptr<Ui::UserpicButton>(
|
||||
widget(),
|
||||
joinAs,
|
||||
Ui::UserpicButton::Role::Custom,
|
||||
st::groupCallJoinAsToggle);
|
||||
_joinAsToggle.destroy();
|
||||
_joinAsToggle = std::move(joinAsToggle);
|
||||
|
|
|
@ -17,6 +17,12 @@ struct FileReferenceAccumulator {
|
|||
push(item);
|
||||
}
|
||||
}
|
||||
template <typename Type>
|
||||
void push(const tl::conditional<Type> &data) {
|
||||
if (data) {
|
||||
push(*data);
|
||||
}
|
||||
}
|
||||
void push(const MTPPhoto &data) {
|
||||
data.match([&](const MTPDphoto &data) {
|
||||
result.data.emplace(
|
||||
|
@ -47,52 +53,34 @@ struct FileReferenceAccumulator {
|
|||
}
|
||||
void push(const MTPTheme &data) {
|
||||
data.match([&](const MTPDtheme &data) {
|
||||
if (const auto document = data.vdocument()) {
|
||||
push(*document);
|
||||
}
|
||||
push(data.vdocument());
|
||||
});
|
||||
}
|
||||
void push(const MTPWebPageAttribute &data) {
|
||||
data.match([&](const MTPDwebPageAttributeTheme &data) {
|
||||
if (const auto documents = data.vdocuments()) {
|
||||
push(*documents);
|
||||
}
|
||||
push(data.vdocuments());
|
||||
});
|
||||
}
|
||||
void push(const MTPWebPage &data) {
|
||||
data.match([&](const MTPDwebPage &data) {
|
||||
if (const auto document = data.vdocument()) {
|
||||
push(*document);
|
||||
}
|
||||
if (const auto attributes = data.vattributes()) {
|
||||
push(*attributes);
|
||||
}
|
||||
if (const auto photo = data.vphoto()) {
|
||||
push(*photo);
|
||||
}
|
||||
if (const auto page = data.vcached_page()) {
|
||||
push(*page);
|
||||
}
|
||||
push(data.vdocument());
|
||||
push(data.vattributes());
|
||||
push(data.vphoto());
|
||||
push(data.vcached_page());
|
||||
}, [](const auto &data) {
|
||||
});
|
||||
}
|
||||
void push(const MTPGame &data) {
|
||||
data.match([&](const MTPDgame &data) {
|
||||
if (const auto document = data.vdocument()) {
|
||||
push(*document);
|
||||
}
|
||||
push(data.vdocument());
|
||||
}, [](const auto &data) {
|
||||
});
|
||||
}
|
||||
void push(const MTPMessageMedia &data) {
|
||||
data.match([&](const MTPDmessageMediaPhoto &data) {
|
||||
if (const auto photo = data.vphoto()) {
|
||||
push(*photo);
|
||||
}
|
||||
push(data.vphoto());
|
||||
}, [&](const MTPDmessageMediaDocument &data) {
|
||||
if (const auto document = data.vdocument()) {
|
||||
push(*document);
|
||||
}
|
||||
push(data.vdocument());
|
||||
}, [&](const MTPDmessageMediaWebPage &data) {
|
||||
push(data.vwebpage());
|
||||
}, [&](const MTPDmessageMediaGame &data) {
|
||||
|
@ -102,9 +90,7 @@ struct FileReferenceAccumulator {
|
|||
}
|
||||
void push(const MTPMessage &data) {
|
||||
data.match([&](const MTPDmessage &data) {
|
||||
if (const auto media = data.vmedia()) {
|
||||
push(*media);
|
||||
}
|
||||
push(data.vmedia());
|
||||
}, [&](const MTPDmessageService &data) {
|
||||
data.vaction().match(
|
||||
[&](const MTPDmessageActionChatEditPhoto &data) {
|
||||
|
@ -125,6 +111,11 @@ struct FileReferenceAccumulator {
|
|||
push(data.vphotos());
|
||||
});
|
||||
}
|
||||
void push(const MTPusers_UserFull &data) {
|
||||
data.match([&](const auto &data) {
|
||||
push(data.vfull_user().data().vpersonal_photo());
|
||||
});
|
||||
}
|
||||
void push(const MTPmessages_RecentStickers &data) {
|
||||
data.match([&](const MTPDmessages_recentStickers &data) {
|
||||
push(data.vstickers());
|
||||
|
@ -181,6 +172,10 @@ UpdatedFileReferences GetFileReferences(const MTPphotos_Photos &data) {
|
|||
return GetFileReferencesHelper(data);
|
||||
}
|
||||
|
||||
UpdatedFileReferences GetFileReferences(const MTPusers_UserFull &data) {
|
||||
return GetFileReferencesHelper(data);
|
||||
}
|
||||
|
||||
UpdatedFileReferences GetFileReferences(
|
||||
const MTPmessages_RecentStickers &data) {
|
||||
return GetFileReferencesHelper(data);
|
||||
|
|
|
@ -29,6 +29,18 @@ struct FileOriginUserPhoto {
|
|||
}
|
||||
};
|
||||
|
||||
struct FileOriginFullUser {
|
||||
FileOriginFullUser(UserId userId)
|
||||
: userId(userId) {
|
||||
}
|
||||
|
||||
UserId userId = 0;
|
||||
|
||||
inline bool operator<(const FileOriginFullUser &other) const {
|
||||
return userId < other.userId;
|
||||
}
|
||||
};
|
||||
|
||||
struct FileOriginPeerPhoto {
|
||||
explicit FileOriginPeerPhoto(PeerId peerId) : peerId(peerId) {
|
||||
}
|
||||
|
@ -113,6 +125,7 @@ struct FileOrigin {
|
|||
v::null_t,
|
||||
FileOriginMessage,
|
||||
FileOriginUserPhoto,
|
||||
FileOriginFullUser,
|
||||
FileOriginPeerPhoto,
|
||||
FileOriginStickerSet,
|
||||
FileOriginSavedGifs,
|
||||
|
@ -126,6 +139,8 @@ struct FileOrigin {
|
|||
}
|
||||
FileOrigin(FileOriginUserPhoto data) : data(data) {
|
||||
}
|
||||
FileOrigin(FileOriginFullUser data) : data(data) {
|
||||
}
|
||||
FileOrigin(FileOriginPeerPhoto data) : data(data) {
|
||||
}
|
||||
FileOrigin(FileOriginStickerSet data) : data(data) {
|
||||
|
@ -177,6 +192,7 @@ struct UpdatedFileReferences {
|
|||
|
||||
UpdatedFileReferences GetFileReferences(const MTPmessages_Messages &data);
|
||||
UpdatedFileReferences GetFileReferences(const MTPphotos_Photos &data);
|
||||
UpdatedFileReferences GetFileReferences(const MTPusers_UserFull &data);
|
||||
UpdatedFileReferences GetFileReferences(
|
||||
const MTPmessages_RecentStickers &data);
|
||||
UpdatedFileReferences GetFileReferences(
|
||||
|
|
|
@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_emoji_statuses.h"
|
||||
#include "data/data_user_names.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
#include "api/api_peer_photo.h"
|
||||
#include "apiwrap.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
@ -365,11 +367,18 @@ bool UserData::hasCalls() const {
|
|||
namespace Data {
|
||||
|
||||
void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
|
||||
if (const auto photo = update.vprofile_photo()) {
|
||||
user->owner().processPhoto(*photo);
|
||||
}
|
||||
if (const auto photo = update.vpersonal_photo()) {
|
||||
user->owner().processPhoto(*photo);
|
||||
const auto profilePhoto = update.vprofile_photo()
|
||||
? user->owner().processPhoto(*update.vprofile_photo()).get()
|
||||
: nullptr;
|
||||
const auto personalPhoto = update.vpersonal_photo()
|
||||
? user->owner().processPhoto(*update.vpersonal_photo()).get()
|
||||
: nullptr;
|
||||
if (personalPhoto && profilePhoto) {
|
||||
user->session().api().peerPhoto().registerNonPersonalPhoto(
|
||||
user,
|
||||
profilePhoto);
|
||||
} else {
|
||||
user->session().api().peerPhoto().unregisterNonPersonalPhoto(user);
|
||||
}
|
||||
user->setSettings(update.vsettings());
|
||||
user->owner().notifySettings().apply(user, update.vnotify_settings());
|
||||
|
|
|
@ -429,7 +429,9 @@ QSize Service::performCountCurrentSize(int newWidth) {
|
|||
}
|
||||
const auto media = this->media();
|
||||
if (media && data()->isUserpicSuggestion()) {
|
||||
newHeight = st::msgServiceMargin.top() + media->resizeGetHeight(newWidth) + st::msgServiceMargin.bottom();
|
||||
newHeight += st::msgServiceMargin.top()
|
||||
+ media->resizeGetHeight(newWidth)
|
||||
+ st::msgServiceMargin.bottom();
|
||||
} else if (!text().isEmpty()) {
|
||||
auto contentWidth = newWidth;
|
||||
if (delegate()->elementIsChatWide()) {
|
||||
|
|
|
@ -841,9 +841,7 @@ void TopBarWidget::refreshInfoButton() {
|
|||
} else if (const auto peer = _activeChat.key.peer()) {
|
||||
auto info = object_ptr<Ui::UserpicButton>(
|
||||
this,
|
||||
_controller,
|
||||
peer,
|
||||
Ui::UserpicButton::Role::Custom,
|
||||
st::topBarInfoButton);
|
||||
info->showSavedMessagesOnSelf(true);
|
||||
_info.destroy();
|
||||
|
|
|
@ -329,6 +329,7 @@ infoEditContactCover: InfoProfileCover(infoProfileCover) {
|
|||
nameTop: 33px;
|
||||
statusTop: 57px;
|
||||
}
|
||||
infoEditContactPersonalLeft: 6px;
|
||||
|
||||
infoProfileInaccessibleUserpic: icon {{ "info/inaccessible_userpic", historyPeerUserpicFg }};
|
||||
|
||||
|
|
|
@ -308,10 +308,16 @@ Cover::Cover(
|
|||
this,
|
||||
controller,
|
||||
_peer,
|
||||
(role == Role::Info
|
||||
? Ui::UserpicButton::Role::OpenPhoto
|
||||
: Ui::UserpicButton::Role::Custom),
|
||||
Ui::UserpicButton::Role::OpenPhoto,
|
||||
Ui::UserpicButton::Source::PeerPhoto,
|
||||
_st.photo))
|
||||
, _changePersonal((role == Role::Info
|
||||
|| topic
|
||||
|| !_peer->isUser()
|
||||
|| _peer->isSelf()
|
||||
|| _peer->asUser()->isBot())
|
||||
? nullptr
|
||||
: CreateUploadSubButton(this, _peer->asUser(), controller).get())
|
||||
, _iconButton(topic
|
||||
? object_ptr<TopicIconButton>(this, controller, topic)
|
||||
: nullptr)
|
||||
|
@ -363,6 +369,16 @@ void Cover::setupChildGeometry() {
|
|||
} else {
|
||||
_iconButton->moveToLeft(_st.photoLeft, _st.photoTop, newWidth);
|
||||
}
|
||||
if (_changePersonal) {
|
||||
_changePersonal->moveToLeft(
|
||||
(_st.photoLeft
|
||||
+ _st.photo.photoSize
|
||||
- _changePersonal->width()
|
||||
+ st::infoEditContactPersonalLeft),
|
||||
(_userpic->y()
|
||||
+ _userpic->height()
|
||||
- _changePersonal->height()));
|
||||
}
|
||||
refreshNameGeometry(newWidth);
|
||||
refreshStatusGeometry(newWidth);
|
||||
}, lifetime());
|
||||
|
@ -373,6 +389,10 @@ Cover *Cover::setOnlineCount(rpl::producer<int> &&count) {
|
|||
return this;
|
||||
}
|
||||
|
||||
std::optional<QImage> Cover::updatedPersonalPhoto() const {
|
||||
return _personalChosen;
|
||||
}
|
||||
|
||||
void Cover::initViewers(rpl::producer<QString> title) {
|
||||
using Flag = Data::PeerUpdate::Flag;
|
||||
std::move(
|
||||
|
@ -397,10 +417,15 @@ void Cover::initViewers(rpl::producer<QString> title) {
|
|||
) | rpl::start_with_next([=] {
|
||||
refreshUploadPhotoOverlay();
|
||||
}, lifetime());
|
||||
|
||||
setupChangePersonal();
|
||||
}
|
||||
|
||||
void Cover::refreshUploadPhotoOverlay() {
|
||||
if (!_userpic || _role == Role::EditContact) {
|
||||
if (!_userpic) {
|
||||
return;
|
||||
} else if (_role == Role::EditContact) {
|
||||
_userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -421,7 +446,7 @@ void Cover::refreshUploadPhotoOverlay() {
|
|||
auto &image = chosen.image;
|
||||
switch (chosen.type) {
|
||||
case ChosenType::Set:
|
||||
_userpic->changeTo(base::duplicate(image));
|
||||
_userpic->showCustom(base::duplicate(image));
|
||||
_peer->session().api().peerPhoto().upload(
|
||||
_peer,
|
||||
std::move(image));
|
||||
|
@ -433,6 +458,44 @@ void Cover::refreshUploadPhotoOverlay() {
|
|||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (const auto user = _peer->asUser()) {
|
||||
_userpic->resetPersonalRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
user->session().api().peerPhoto().clearPersonal(user);
|
||||
_userpic->showSource(Ui::UserpicButton::Source::PeerPhoto);
|
||||
}, lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
void Cover::setupChangePersonal() {
|
||||
if (!_changePersonal) {
|
||||
return;
|
||||
}
|
||||
|
||||
_changePersonal->chosenImages(
|
||||
) | rpl::start_with_next([=](Ui::UserpicButton::ChosenImage &&chosen) {
|
||||
if (chosen.type == Ui::UserpicButton::ChosenType::Suggest) {
|
||||
_peer->session().api().peerPhoto().suggest(
|
||||
_peer,
|
||||
std::move(chosen.image));
|
||||
} else {
|
||||
_personalChosen = std::move(chosen.image);
|
||||
_userpic->showCustom(base::duplicate(*_personalChosen));
|
||||
_changePersonal->overrideHasPersonalPhoto(true);
|
||||
_changePersonal->showSource(
|
||||
Ui::UserpicButton::Source::NonPersonalIfHasPersonal);
|
||||
}
|
||||
}, _changePersonal->lifetime());
|
||||
|
||||
_changePersonal->resetPersonalRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
_personalChosen = QImage();
|
||||
_userpic->showSource(
|
||||
Ui::UserpicButton::Source::NonPersonalPhoto);
|
||||
_changePersonal->overrideHasPersonalPhoto(false);
|
||||
_changePersonal->showCustom(QImage());
|
||||
}, _changePersonal->lifetime());
|
||||
}
|
||||
|
||||
void Cover::refreshStatusText() {
|
||||
|
|
|
@ -115,6 +115,7 @@ public:
|
|||
[[nodiscard]] rpl::producer<Section> showSection() const {
|
||||
return _showSection.events();
|
||||
}
|
||||
[[nodiscard]] std::optional<QImage> updatedPersonalPhoto() const;
|
||||
|
||||
private:
|
||||
Cover(
|
||||
|
@ -131,6 +132,7 @@ private:
|
|||
void refreshNameGeometry(int newWidth);
|
||||
void refreshStatusGeometry(int newWidth);
|
||||
void refreshUploadPhotoOverlay();
|
||||
void setupChangePersonal();
|
||||
|
||||
const style::InfoProfileCover &_st;
|
||||
|
||||
|
@ -142,6 +144,8 @@ private:
|
|||
rpl::variable<int> _onlineCount;
|
||||
|
||||
object_ptr<Ui::UserpicButton> _userpic;
|
||||
Ui::UserpicButton *_changePersonal = nullptr;
|
||||
std::optional<QImage> _personalChosen;
|
||||
object_ptr<TopicIconButton> _iconButton;
|
||||
object_ptr<Ui::FlatLabel> _name = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _status = { nullptr };
|
||||
|
|
|
@ -19,11 +19,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "info/media/info_media_buttons.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "boxes/add_contact_box.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
#include "data/data_photo.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "mainwidget.h"
|
||||
#include "main/main_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_peer_photo.h"
|
||||
#include "window/main_window.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "storage/storage_shared_media.h"
|
||||
|
@ -64,6 +68,20 @@ InnerWidget::InnerWidget(
|
|||
object_ptr<Ui::RpWidget> InnerWidget::setupContent(
|
||||
not_null<RpWidget*> parent) {
|
||||
auto result = object_ptr<Ui::VerticalLayout>(parent);
|
||||
if (const auto user = _peer->asUser()) {
|
||||
user->session().changes().peerFlagsValue(
|
||||
user,
|
||||
Data::PeerUpdate::Flag::FullInfo
|
||||
) | rpl::start_with_next([=] {
|
||||
auto &photos = user->session().api().peerPhoto();
|
||||
if (const auto original = photos.nonPersonalPhoto(user)) {
|
||||
// Preload it for the edit contact box.
|
||||
_nonPersonalView = original->createMediaView();
|
||||
const auto id = peerToUser(user->id);
|
||||
original->load(Data::FileOriginFullUser{ id });
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
_cover = _topic
|
||||
? result->add(object_ptr<Cover>(
|
||||
result,
|
||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Data {
|
||||
class ForumTopic;
|
||||
class PhotoMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Window {
|
||||
|
@ -70,6 +71,8 @@ private:
|
|||
PeerData * const _migrated = nullptr;
|
||||
Data::ForumTopic * const _topic = nullptr;
|
||||
|
||||
std::shared_ptr<Data::PhotoMedia> _nonPersonalView;
|
||||
|
||||
Members *_members = nullptr;
|
||||
Cover *_cover = nullptr;
|
||||
Ui::SlideWrap<RpWidget> *_sharedMediaWrap = nullptr;
|
||||
|
|
|
@ -29,7 +29,7 @@ SignupWidget::SignupWidget(
|
|||
, _photo(
|
||||
this,
|
||||
data->controller,
|
||||
Ui::UserpicButton::Role::ChangePhoto,
|
||||
Ui::UserpicButton::Role::ChoosePhoto,
|
||||
st::defaultUserpicButton)
|
||||
, _first(this, st::introName, tr::lng_signup_firstname())
|
||||
, _last(this, st::introName, tr::lng_signup_lastname())
|
||||
|
|
|
@ -73,7 +73,6 @@ not_null<Ui::RpWidget*> PanelForm::setupContent() {
|
|||
object_ptr<Ui::UserpicButton>(
|
||||
userpicWrap,
|
||||
bot,
|
||||
Ui::UserpicButton::Role::Custom,
|
||||
st::passportFormUserpic));
|
||||
userpicWrap->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
|
|
|
@ -31,7 +31,6 @@ PanelAskPassword::PanelAskPassword(
|
|||
, _userpic(
|
||||
this,
|
||||
_controller->bot(),
|
||||
Ui::UserpicButton::Role::Custom,
|
||||
st::passportPasswordUserpic)
|
||||
, _about1(
|
||||
this,
|
||||
|
|
|
@ -245,6 +245,7 @@ void SetupPhoto(
|
|||
controller,
|
||||
self,
|
||||
Ui::UserpicButton::Role::OpenPhoto,
|
||||
Ui::UserpicButton::Source::PeerPhoto,
|
||||
st::settingsInfoPhoto);
|
||||
const auto upload = CreateUploadSubButton(wrap, controller);
|
||||
|
||||
|
@ -252,7 +253,7 @@ void SetupPhoto(
|
|||
) | rpl::start_with_next([=](Ui::UserpicButton::ChosenImage &&chosen) {
|
||||
auto &image = chosen.image;
|
||||
UpdatePhotoLocally(self, image);
|
||||
photo->changeTo(base::duplicate(image));
|
||||
photo->showCustom(base::duplicate(image));
|
||||
self->session().api().peerPhoto().upload(self, std::move(image));
|
||||
}, upload->lifetime());
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ Cover::Cover(
|
|||
controller,
|
||||
_user,
|
||||
Ui::UserpicButton::Role::OpenPhoto,
|
||||
Ui::UserpicButton::Source::PeerPhoto,
|
||||
st::infoProfileCover.photo)
|
||||
, _name(this, st::infoProfileCover.name)
|
||||
, _phone(this, st::defaultFlatLabel)
|
||||
|
@ -141,7 +142,7 @@ Cover::Cover(
|
|||
_userpic->switchChangePhotoOverlay(_user->isSelf(), [=](
|
||||
Ui::UserpicButton::ChosenImage chosen) {
|
||||
auto &image = chosen.image;
|
||||
_userpic->changeTo(base::duplicate(image));
|
||||
_userpic->showCustom(base::duplicate(image));
|
||||
_user->session().api().peerPhoto().upload(_user, std::move(image));
|
||||
});
|
||||
|
||||
|
|
|
@ -14,8 +14,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_session.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_streaming.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_photo_media.h"
|
||||
#include "history/history.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "core/application.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
|
@ -99,26 +102,32 @@ QPixmap CreateSquarePixmap(int width, Callback &&paintCallback) {
|
|||
return Ui::PixmapFromImage(std::move(image));
|
||||
};
|
||||
|
||||
} // namespace
|
||||
void SetupSubButtonBackground(
|
||||
not_null<Ui::UserpicButton*> upload,
|
||||
not_null<Ui::RpWidget*> background) {
|
||||
const auto border = st::uploadUserpicButtonBorder;
|
||||
const auto size = upload->rect().marginsAdded(
|
||||
{ border, border, border, border }
|
||||
).size();
|
||||
|
||||
UserpicButton::UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<Window::Controller*> window,
|
||||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
const style::UserpicButton &st)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _controller(window->sessionController())
|
||||
, _window(window)
|
||||
, _peer(peer)
|
||||
, _role(role) {
|
||||
Expects(_role == Role::ChangePhoto);
|
||||
background->resize(size);
|
||||
background->paintRequest(
|
||||
) | rpl::start_with_next([=] {
|
||||
auto p = QPainter(background);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setBrush(st::boxBg);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(background->rect());
|
||||
}, background->lifetime());
|
||||
|
||||
_waiting = false;
|
||||
prepare();
|
||||
upload->positionValue(
|
||||
) | rpl::start_with_next([=](QPoint position) {
|
||||
background->move(position - QPoint(border, border));
|
||||
}, background->lifetime());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
UserpicButton::UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<Window::Controller*> window,
|
||||
|
@ -131,7 +140,6 @@ UserpicButton::UserpicButton(
|
|||
, _role(role) {
|
||||
Expects(_role == Role::ChangePhoto || _role == Role::ChoosePhoto);
|
||||
|
||||
_waiting = false;
|
||||
prepare();
|
||||
}
|
||||
|
||||
|
@ -140,33 +148,39 @@ UserpicButton::UserpicButton(
|
|||
not_null<Window::SessionController*> controller,
|
||||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
Source source,
|
||||
const style::UserpicButton &st)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _controller(controller)
|
||||
, _window(&controller->window())
|
||||
, _peer(peer)
|
||||
, _role(role) {
|
||||
, _role(role)
|
||||
, _source(source) {
|
||||
if (_source != Source::Custom) {
|
||||
processPeerPhoto();
|
||||
prepare();
|
||||
setupPeerViewers();
|
||||
}
|
||||
prepare();
|
||||
}
|
||||
|
||||
UserpicButton::UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
const style::UserpicButton &st)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _peer(peer)
|
||||
, _role(role) {
|
||||
Expects(_role != Role::OpenProfile && _role != Role::OpenPhoto);
|
||||
, _role(Role::Custom)
|
||||
, _source(Source::PeerPhoto) {
|
||||
Expects(_role != Role::OpenPhoto);
|
||||
|
||||
_waiting = false;
|
||||
if (_source != Source::Custom) {
|
||||
processPeerPhoto();
|
||||
prepare();
|
||||
setupPeerViewers();
|
||||
}
|
||||
_waiting = false;
|
||||
prepare();
|
||||
}
|
||||
|
||||
UserpicButton::~UserpicButton() = default;
|
||||
|
@ -182,12 +196,39 @@ void UserpicButton::prepare() {
|
|||
if (_role == Role::ChangePhoto) {
|
||||
chosenImages(
|
||||
) | rpl::start_with_next([=](ChosenImage &&chosen) {
|
||||
setImage(std::move(chosen.image));
|
||||
showCustom(std::move(chosen.image));
|
||||
}, lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
void UserpicButton::requestSuggestAvailability() {
|
||||
if (const auto user = _peer ? _peer->asUser() : nullptr) {
|
||||
if (!user->isSelf()) {
|
||||
const auto history = user->owner().history(user);
|
||||
if (!history->lastServerMessageKnown()) {
|
||||
// Server allows suggesting photos only in non-empty chats.
|
||||
user->owner().histories().requestDialogEntry(history);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UserpicButton::canSuggestPhoto(not_null<UserData*> user) const {
|
||||
// Server allows suggesting photos only in non-empty chats.
|
||||
return !user->isSelf()
|
||||
&& (user->owner().history(user)->lastServerMessage() != nullptr);
|
||||
}
|
||||
|
||||
bool UserpicButton::hasPersonalPhotoLocally() const {
|
||||
if (const auto user = _peer->asUser()) {
|
||||
return _overrideHasPersonalPhoto.value_or(user->hasPersonalPhoto());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UserpicButton::setClickHandlerByRole() {
|
||||
requestSuggestAvailability();
|
||||
|
||||
switch (_role) {
|
||||
case Role::ChoosePhoto:
|
||||
case Role::ChangePhoto:
|
||||
|
@ -197,21 +238,9 @@ void UserpicButton::setClickHandlerByRole() {
|
|||
case Role::OpenPhoto:
|
||||
addClickHandler([=] { openPeerPhoto(); });
|
||||
break;
|
||||
|
||||
case Role::OpenProfile:
|
||||
addClickHandler([this] {
|
||||
Expects(_controller != nullptr);
|
||||
|
||||
_controller->showPeerInfo(_peer);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UserpicButton::changeTo(QImage &&image) {
|
||||
setImage(std::move(image));
|
||||
}
|
||||
|
||||
void UserpicButton::choosePhotoLocally() {
|
||||
if (!_window) {
|
||||
return;
|
||||
|
@ -246,15 +275,16 @@ void UserpicButton::choosePhotoLocally() {
|
|||
tr::lng_profile_set_photo_for(tr::now),
|
||||
[=] { chooseFile(); },
|
||||
&st::menuIconPhotoSet);
|
||||
if (canSuggestPhoto(user)) {
|
||||
_menu->addAction(
|
||||
tr::lng_profile_suggest_photo(tr::now),
|
||||
[=] { chooseFile(ChosenType::Suggest); },
|
||||
&st::menuIconPhotoSuggest);
|
||||
if (user->hasPersonalPhoto()) {
|
||||
}
|
||||
if (hasPersonalPhotoLocally()) {
|
||||
_menu->addAction(
|
||||
tr::lng_profile_photo_reset(tr::now),
|
||||
[=] { user->session().api().peerPhoto().clearPersonal(
|
||||
user); _userpicCustom = false; },
|
||||
[=] { _resetPersonalRequests.fire({}); },
|
||||
&st::menuIconRemove);
|
||||
}
|
||||
} else {
|
||||
|
@ -293,23 +323,47 @@ void UserpicButton::openPeerPhoto() {
|
|||
}
|
||||
|
||||
void UserpicButton::setupPeerViewers() {
|
||||
const auto user = _peer->asUser();
|
||||
if (user
|
||||
&& (_source == Source::NonPersonalPhoto
|
||||
|| _source == Source::NonPersonalIfHasPersonal)) {
|
||||
user->session().changes().peerFlagsValue(
|
||||
user,
|
||||
Data::PeerUpdate::Flag::FullInfo
|
||||
) | rpl::map([=] {
|
||||
return std::pair(
|
||||
user->session().api().peerPhoto().nonPersonalPhoto(user),
|
||||
user->hasPersonalPhoto());
|
||||
}) | rpl::distinct_until_changed() | rpl::skip(
|
||||
1
|
||||
) | rpl::start_with_next([=] {
|
||||
processNewPeerPhoto();
|
||||
update();
|
||||
}, _sourceLifetime);
|
||||
}
|
||||
if (!user
|
||||
|| _source == Source::PeerPhoto
|
||||
|| _source == Source::NonPersonalIfHasPersonal) {
|
||||
_peer->session().changes().peerUpdates(
|
||||
_peer,
|
||||
Data::PeerUpdate::Flag::Photo
|
||||
) | rpl::start_with_next([=] {
|
||||
processNewPeerPhoto();
|
||||
update();
|
||||
}, lifetime());
|
||||
|
||||
}, _sourceLifetime);
|
||||
}
|
||||
_peer->session().downloaderTaskFinished(
|
||||
) | rpl::filter([=] {
|
||||
return _waiting;
|
||||
}) | rpl::start_with_next([=] {
|
||||
if (!Ui::PeerUserpicLoading(_userpicView)) {
|
||||
const auto loading = _showPeerUserpic
|
||||
? Ui::PeerUserpicLoading(_userpicView)
|
||||
: (_nonPersonalView && !_nonPersonalView->loaded());
|
||||
if (!loading) {
|
||||
_waiting = false;
|
||||
startNewPhotoShowing();
|
||||
}
|
||||
}, lifetime());
|
||||
}, _sourceLifetime);
|
||||
}
|
||||
|
||||
void UserpicButton::paintEvent(QPaintEvent *e) {
|
||||
|
@ -363,9 +417,9 @@ void UserpicButton::paintEvent(QPaintEvent *e) {
|
|||
p,
|
||||
photoLeft,
|
||||
photoTop,
|
||||
_userpicHasImage
|
||||
(_userpicHasImage
|
||||
? &st::shadowFg->c
|
||||
: &_st.changeButton.ripple.color->c);
|
||||
: &_st.changeButton.ripple.color->c));
|
||||
if (over || !_userpicHasImage) {
|
||||
auto iconLeft = (_st.changeIconPosition.x() < 0)
|
||||
? (_st.photoSize - _st.changeIcon.width()) / 2
|
||||
|
@ -474,10 +528,36 @@ QPoint UserpicButton::prepareRippleStartPosition() const {
|
|||
void UserpicButton::processPeerPhoto() {
|
||||
Expects(_peer != nullptr);
|
||||
|
||||
_userpicView = _peer->createUserpicView();
|
||||
_waiting = Ui::PeerUserpicLoading(_userpicView);
|
||||
const auto user = _peer->asUser();
|
||||
const auto nonPersonal = (user && _source != Source::PeerPhoto)
|
||||
? _peer->session().api().peerPhoto().nonPersonalPhoto(user)
|
||||
: nullptr;
|
||||
_showPeerUserpic = (_source == Source::PeerPhoto)
|
||||
|| (user
|
||||
&& !user->hasPersonalPhoto()
|
||||
&& (_source == Source::NonPersonalPhoto
|
||||
|| (_source == Source::NonPersonalIfHasPersonal
|
||||
&& hasPersonalPhotoLocally())));
|
||||
const auto showNonPersonal = _showPeerUserpic ? nullptr : nonPersonal;
|
||||
|
||||
_userpicView = _showPeerUserpic
|
||||
? _peer->createUserpicView()
|
||||
: PeerUserpicView();
|
||||
_nonPersonalView = showNonPersonal
|
||||
? showNonPersonal->createMediaView()
|
||||
: nullptr;
|
||||
_waiting = _showPeerUserpic
|
||||
? Ui::PeerUserpicLoading(_userpicView)
|
||||
: (_nonPersonalView && !_nonPersonalView->loaded());
|
||||
if (_waiting) {
|
||||
if (_showPeerUserpic) {
|
||||
_peer->loadUserpic();
|
||||
} else if (_nonPersonalView) {
|
||||
AssertIsDebug();
|
||||
showNonPersonal->load(Data::FileOriginFullUser{
|
||||
peerToUser(user->id),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (_role == Role::OpenPhoto) {
|
||||
if (_peer->userpicPhotoUnknown()) {
|
||||
|
@ -492,7 +572,7 @@ void UserpicButton::processPeerPhoto() {
|
|||
void UserpicButton::updateCursor() {
|
||||
Expects(_role == Role::OpenPhoto);
|
||||
|
||||
auto pointer = _canOpenPhoto
|
||||
const auto pointer = _canOpenPhoto
|
||||
|| (_changeOverlayEnabled && _cursorInChangeOverlay);
|
||||
setPointerCursor(pointer);
|
||||
}
|
||||
|
@ -634,7 +714,7 @@ void UserpicButton::setCursorInChangeOverlay(bool inOverlay) {
|
|||
}
|
||||
|
||||
void UserpicButton::processNewPeerPhoto() {
|
||||
if (_userpicCustom) {
|
||||
if (_source == Source::Custom) {
|
||||
return;
|
||||
}
|
||||
processPeerPhoto();
|
||||
|
@ -653,14 +733,13 @@ void UserpicButton::grabOldUserpic() {
|
|||
}
|
||||
|
||||
void UserpicButton::startNewPhotoShowing() {
|
||||
auto oldUniqueKey = _userpicUniqueKey;
|
||||
const auto oldUniqueKey = _userpicUniqueKey;
|
||||
prepareUserpicPixmap();
|
||||
update();
|
||||
|
||||
if (_notShownYet) {
|
||||
return;
|
||||
}
|
||||
if (oldUniqueKey != _userpicUniqueKey
|
||||
} else if (oldUniqueKey != _userpicUniqueKey
|
||||
|| _a_appearance.animating()) {
|
||||
startAnimation();
|
||||
}
|
||||
|
@ -733,9 +812,15 @@ void UserpicButton::onStateChanged(
|
|||
}
|
||||
}
|
||||
|
||||
void UserpicButton::setImage(QImage &&image) {
|
||||
void UserpicButton::showCustom(QImage &&image) {
|
||||
grabOldUserpic();
|
||||
|
||||
clearStreaming();
|
||||
_sourceLifetime.destroy();
|
||||
_source = Source::Custom;
|
||||
|
||||
_userpicHasImage = !image.isNull();
|
||||
if (_userpicHasImage) {
|
||||
auto size = QSize(_st.photoSize, _st.photoSize);
|
||||
auto small = image.scaled(
|
||||
size * cIntRetinaFactor(),
|
||||
|
@ -745,14 +830,49 @@ void UserpicButton::setImage(QImage &&image) {
|
|||
_userpic = Ui::PixmapFromImage(forum
|
||||
? Images::Round(std::move(small), Images::Option::RoundLarge)
|
||||
: Images::Circle(std::move(small)));
|
||||
} else {
|
||||
_userpic = CreateSquarePixmap(_st.photoSize, [&](Painter &p) {
|
||||
fillShape(p, _st.changeButton.textBg);
|
||||
});
|
||||
}
|
||||
_userpic.setDevicePixelRatio(cRetinaFactor());
|
||||
_userpicCustom = _userpicHasImage = true;
|
||||
_userpicUniqueKey = {};
|
||||
_result = std::move(image);
|
||||
|
||||
startNewPhotoShowing();
|
||||
}
|
||||
|
||||
void UserpicButton::showSource(Source source) {
|
||||
Expects(_peer != nullptr);
|
||||
Expects(source != Source::Custom); // Show this using showCustom().
|
||||
Expects(source == Source::PeerPhoto || _peer->isUser());
|
||||
|
||||
if (_source != source) {
|
||||
clearStreaming();
|
||||
}
|
||||
|
||||
_sourceLifetime.destroy();
|
||||
_source = source;
|
||||
|
||||
_result = QImage();
|
||||
|
||||
processPeerPhoto();
|
||||
setupPeerViewers();
|
||||
|
||||
prepareUserpicPixmap();
|
||||
update();
|
||||
}
|
||||
|
||||
void UserpicButton::overrideHasPersonalPhoto(bool has) {
|
||||
Expects(_peer && _peer->isUser());
|
||||
|
||||
_overrideHasPersonalPhoto = has;
|
||||
}
|
||||
|
||||
rpl::producer<> UserpicButton::resetPersonalRequests() const {
|
||||
return _resetPersonalRequests.events();
|
||||
}
|
||||
|
||||
void UserpicButton::fillShape(QPainter &p, const style::color &color) const {
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
|
@ -767,22 +887,69 @@ void UserpicButton::fillShape(QPainter &p, const style::color &color) const {
|
|||
}
|
||||
|
||||
void UserpicButton::prepareUserpicPixmap() {
|
||||
if (_userpicCustom) {
|
||||
if (_source == Source::Custom) {
|
||||
return;
|
||||
}
|
||||
auto size = _st.photoSize;
|
||||
_userpicHasImage = _peer
|
||||
const auto size = _st.photoSize;
|
||||
_userpicHasImage = _showPeerUserpic
|
||||
? (_peer
|
||||
&& (_peer->userpicCloudImage(_userpicView)
|
||||
|| _role != Role::ChangePhoto);
|
||||
|| _role != Role::ChangePhoto))
|
||||
: (_source == Source::NonPersonalPhoto
|
||||
|| (_source == Source::NonPersonalIfHasPersonal
|
||||
&& hasPersonalPhotoLocally()));
|
||||
_userpic = CreateSquarePixmap(size, [&](Painter &p) {
|
||||
if (_userpicHasImage) {
|
||||
_peer->paintUserpic(p, _userpicView, 0, 0, _st.photoSize);
|
||||
if (_showPeerUserpic) {
|
||||
_peer->paintUserpic(p, _userpicView, 0, 0, size);
|
||||
} else if (_nonPersonalView) {
|
||||
using Size = Data::PhotoSize;
|
||||
if (const auto full = _nonPersonalView->image(Size::Large)) {
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
auto image = full->original().scaled(
|
||||
QSize(size, size) * ratio,
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
if (_peer->isForum()) {
|
||||
image = Images::Round(
|
||||
std::move(image),
|
||||
Images::CornersMask(size
|
||||
* Ui::ForumUserpicRadiusMultiplier()));
|
||||
} else {
|
||||
image = Images::Circle(std::move(image));
|
||||
}
|
||||
p.drawImage(0, 0, image);
|
||||
}
|
||||
} else {
|
||||
const auto user = _peer->asUser();
|
||||
auto empty = Ui::EmptyUserpic(
|
||||
Ui::EmptyUserpic::UserpicColor(
|
||||
Data::PeerColorIndex(_peer->id)),
|
||||
((user && user->isInaccessible())
|
||||
? Ui::EmptyUserpic::InaccessibleName()
|
||||
: _peer->name()));
|
||||
if (_peer->isForum()) {
|
||||
empty.paintRounded(
|
||||
p,
|
||||
0,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
size * Ui::ForumUserpicRadiusMultiplier());
|
||||
} else {
|
||||
empty.paintCircle(p, 0, 0, size, size);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fillShape(p, _st.changeButton.textBg);
|
||||
}
|
||||
});
|
||||
_userpicUniqueKey = _userpicHasImage
|
||||
? (_showPeerUserpic
|
||||
? _peer->userpicUniqueKey(_userpicView)
|
||||
: _nonPersonalView
|
||||
? InMemoryKey{ _nonPersonalView->owner()->id, 0 }
|
||||
: InMemoryKey{ _peer->id.value, _peer->id.value })
|
||||
: InMemoryKey();
|
||||
}
|
||||
|
||||
|
@ -795,27 +962,7 @@ not_null<Ui::UserpicButton*> CreateUploadSubButton(
|
|||
&controller->window(),
|
||||
Ui::UserpicButton::Role::ChoosePhoto,
|
||||
st::uploadUserpicButton);
|
||||
|
||||
const auto border = st::uploadUserpicButtonBorder;
|
||||
const auto size = upload->rect().marginsAdded(
|
||||
{ border, border, border, border }
|
||||
).size();
|
||||
|
||||
background->resize(size);
|
||||
background->paintRequest(
|
||||
) | rpl::start_with_next([=] {
|
||||
auto p = QPainter(background);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setBrush(st::boxBg);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(background->rect());
|
||||
}, background->lifetime());
|
||||
|
||||
upload->positionValue(
|
||||
) | rpl::start_with_next([=](QPoint position) {
|
||||
background->move(position - QPoint(border, border));
|
||||
}, background->lifetime());
|
||||
|
||||
SetupSubButtonBackground(upload, background);
|
||||
return upload;
|
||||
}
|
||||
|
||||
|
@ -823,8 +970,16 @@ not_null<Ui::UserpicButton*> CreateUploadSubButton(
|
|||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<UserData*> contact,
|
||||
not_null<Window::SessionController*> controller) {
|
||||
const auto result = CreateUploadSubButton(parent, controller);
|
||||
return result;
|
||||
const auto background = Ui::CreateChild<Ui::RpWidget>(parent.get());
|
||||
const auto upload = Ui::CreateChild<Ui::UserpicButton>(
|
||||
parent.get(),
|
||||
controller,
|
||||
contact,
|
||||
Ui::UserpicButton::Role::ChoosePhoto,
|
||||
Ui::UserpicButton::Source::NonPersonalIfHasPersonal,
|
||||
st::uploadUserpicButton);
|
||||
SetupSubButtonBackground(upload, background);
|
||||
return upload;
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
@ -12,6 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class PeerData;
|
||||
|
||||
namespace Data {
|
||||
class PhotoMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Window {
|
||||
class Controller;
|
||||
class SessionController;
|
||||
|
@ -40,16 +44,15 @@ public:
|
|||
ChoosePhoto,
|
||||
ChangePhoto,
|
||||
OpenPhoto,
|
||||
OpenProfile,
|
||||
Custom,
|
||||
};
|
||||
enum class Source {
|
||||
PeerPhoto,
|
||||
NonPersonalPhoto,
|
||||
NonPersonalIfHasPersonal,
|
||||
Custom,
|
||||
};
|
||||
|
||||
UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<::Window::Controller*> window,
|
||||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
const style::UserpicButton &st);
|
||||
UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<::Window::Controller*> window,
|
||||
|
@ -60,11 +63,11 @@ public:
|
|||
not_null<::Window::SessionController*> controller,
|
||||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
Source source,
|
||||
const style::UserpicButton &st);
|
||||
UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
not_null<PeerData*> peer, // Role::Custom, Source::PeerPhoto
|
||||
const style::UserpicButton &st);
|
||||
~UserpicButton();
|
||||
|
||||
|
@ -91,8 +94,11 @@ public:
|
|||
return std::move(_result);
|
||||
}
|
||||
|
||||
// For Role::OpenPhoto as if it is Role::ChangePhoto.
|
||||
void changeTo(QImage &&image);
|
||||
void showCustom(QImage &&image);
|
||||
void showSource(Source source);
|
||||
|
||||
void overrideHasPersonalPhoto(bool has);
|
||||
[[nodiscard]] rpl::producer<> resetPersonalRequests() const;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
@ -106,7 +112,6 @@ protected:
|
|||
|
||||
private:
|
||||
void prepare();
|
||||
void setImage(QImage &&image);
|
||||
void setupPeerViewers();
|
||||
void startAnimation();
|
||||
void processPeerPhoto();
|
||||
|
@ -132,20 +137,24 @@ private:
|
|||
|
||||
void grabOldUserpic();
|
||||
void setClickHandlerByRole();
|
||||
void requestSuggestAvailability();
|
||||
void openPeerPhoto();
|
||||
void choosePhotoLocally();
|
||||
[[nodiscard]] bool canSuggestPhoto(not_null<UserData*> user) const;
|
||||
[[nodiscard]] bool hasPersonalPhotoLocally() const;
|
||||
|
||||
const style::UserpicButton &_st;
|
||||
::Window::SessionController *_controller = nullptr;
|
||||
::Window::Controller *_window = nullptr;
|
||||
PeerData *_peer = nullptr;
|
||||
PeerUserpicView _userpicView;
|
||||
std::shared_ptr<Data::PhotoMedia> _nonPersonalView;
|
||||
Role _role = Role::ChangePhoto;
|
||||
bool _notShownYet = true;
|
||||
bool _waiting = false;
|
||||
QPixmap _userpic, _oldUserpic;
|
||||
bool _userpicHasImage = false;
|
||||
bool _userpicCustom = false;
|
||||
bool _showPeerUserpic = false;
|
||||
InMemoryKey _userpicUniqueKey;
|
||||
Animations::Simple _a_appearance;
|
||||
QImage _result;
|
||||
|
@ -164,6 +173,11 @@ private:
|
|||
|
||||
rpl::event_stream<ChosenImage> _chosenImages;
|
||||
|
||||
Source _source = Source::Custom;
|
||||
std::optional<bool> _overrideHasPersonalPhoto;
|
||||
rpl::event_stream<> _resetPersonalRequests;
|
||||
rpl::lifetime _sourceLifetime;
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] not_null<Ui::UserpicButton*> CreateUploadSubButton(
|
||||
|
|
|
@ -354,9 +354,7 @@ MainMenu::MainMenu(
|
|||
, _controller(controller)
|
||||
, _userpicButton(
|
||||
this,
|
||||
_controller,
|
||||
_controller->session().user(),
|
||||
Ui::UserpicButton::Role::Custom,
|
||||
st::mainMenuUserpic)
|
||||
, _toggleAccounts(this)
|
||||
, _setEmojiStatus(this, SetStatusLabel(&controller->session()))
|
||||
|
|
Loading…
Add table
Reference in a new issue