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