mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-18 17:40:59 +00:00
Replace NewAvatarButton with UserpicButton.
This new control should also replace PeerAvatarButton and Profile::UserpicButton and deliver all the best of those three.
This commit is contained in:
parent
3deea14559
commit
3d37ac9235
@ -616,6 +616,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_info_channel_title" = "Channel Info";
|
||||
"lng_profile_enable_notifications" = "Notifications";
|
||||
"lng_profile_send_message" = "Send Message";
|
||||
"lng_profile_edit_group_name" = "Edit group name";
|
||||
"lng_info_add_as_contact" = "Add as contact";
|
||||
"lng_profile_shared_media" = "Shared media";
|
||||
"lng_media_type_photos" = "Photos";
|
||||
|
@ -116,6 +116,10 @@ public:
|
||||
finishPrepare();
|
||||
}
|
||||
|
||||
Window::Controller *controller() {
|
||||
return getDelegate()->controller();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void onScrollToY(int top, int bottom = -1);
|
||||
|
||||
@ -124,10 +128,6 @@ public slots:
|
||||
protected:
|
||||
virtual void prepare() = 0;
|
||||
|
||||
Window::Controller *controller() {
|
||||
return getDelegate()->controller();
|
||||
}
|
||||
|
||||
void setLayerType(bool layerType) {
|
||||
getDelegate()->setLayerType(layerType);
|
||||
}
|
||||
|
@ -307,14 +307,25 @@ void AddContactBox::updateButtons() {
|
||||
|
||||
GroupInfoBox::GroupInfoBox(QWidget*, CreatingGroupType creating, bool fromTypeChoose)
|
||||
: _creating(creating)
|
||||
, _fromTypeChoose(fromTypeChoose)
|
||||
, _photo(this, st::newGroupPhotoSize, st::newGroupPhotoIconPosition)
|
||||
, _title(this, st::defaultInputField, langFactory(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)) {
|
||||
, _fromTypeChoose(fromTypeChoose) {
|
||||
}
|
||||
|
||||
void GroupInfoBox::prepare() {
|
||||
setMouseTracking(true);
|
||||
|
||||
_photo.create(
|
||||
this,
|
||||
(_creating == CreatingGroupChannel)
|
||||
? peerFromChannel(0)
|
||||
: peerFromChat(0),
|
||||
Ui::UserpicButton::Role::ChangePhoto,
|
||||
st::defaultUserpicButton);
|
||||
_title.create(
|
||||
this,
|
||||
st::defaultInputField,
|
||||
langFactory(_creating == CreatingGroupChannel
|
||||
? lng_dlg_new_channel_name
|
||||
: lng_dlg_new_group_name));
|
||||
_title->setMaxLength(kMaxGroupChannelTitle);
|
||||
|
||||
if (_creating == CreatingGroupChannel) {
|
||||
@ -332,41 +343,9 @@ void GroupInfoBox::prepare() {
|
||||
addButton(langFactory(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), [this] { onNext(); });
|
||||
addButton(langFactory(_fromTypeChoose ? lng_create_group_back : lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setupPhotoButton();
|
||||
|
||||
updateMaxHeight();
|
||||
}
|
||||
|
||||
void GroupInfoBox::setupPhotoButton() {
|
||||
_photo->setClickedCallback(App::LambdaDelayed(st::defaultActiveButton.ripple.hideDuration, this, [this] {
|
||||
auto imgExtensions = cImgExtensions();
|
||||
auto filter = qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(");;") + FileDialog::AllFilesFilter();
|
||||
FileDialog::GetOpenPath(lang(lng_choose_image), filter, base::lambda_guarded(this, [this](const FileDialog::OpenResult &result) {
|
||||
if (result.remoteContent.isEmpty() && result.paths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QImage img;
|
||||
if (!result.remoteContent.isEmpty()) {
|
||||
img = App::readImage(result.remoteContent);
|
||||
} else {
|
||||
img = App::readImage(result.paths.front());
|
||||
}
|
||||
if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) {
|
||||
return;
|
||||
}
|
||||
auto box = Ui::show(
|
||||
Box<PhotoCropBox>(
|
||||
img,
|
||||
(_creating == CreatingGroupChannel)
|
||||
? peerFromChannel(0)
|
||||
: peerFromChat(0)),
|
||||
LayerOption::KeepOther);
|
||||
connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&)));
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
void GroupInfoBox::setInnerFocus() {
|
||||
_title->setFocusFast();
|
||||
}
|
||||
@ -376,12 +355,19 @@ void GroupInfoBox::resizeEvent(QResizeEvent *e) {
|
||||
|
||||
_photo->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top());
|
||||
|
||||
auto nameLeft = st::newGroupPhotoSize + st::newGroupNamePosition.x();
|
||||
auto nameLeft = st::defaultUserpicButton.size.width()
|
||||
+ st::newGroupNamePosition.x();
|
||||
_title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right() - nameLeft, _title->height());
|
||||
_title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left() + nameLeft, st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupNamePosition.y());
|
||||
if (_description) {
|
||||
_description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height());
|
||||
_description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::newGroupDescriptionPadding.top());
|
||||
auto descriptionLeft = st::boxPadding.left()
|
||||
+ st::newGroupInfoPadding.left();
|
||||
auto descriptionTop = st::boxPadding.top()
|
||||
+ st::newGroupInfoPadding.top()
|
||||
+ st::defaultUserpicButton.size.height()
|
||||
+ st::newGroupDescriptionPadding.top();
|
||||
_description->moveToLeft(descriptionLeft, descriptionTop);
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,8 +419,11 @@ void GroupInfoBox::createGroup(not_null<PeerListBox*> selectUsersBox, const QStr
|
||||
return App::chat(chats->front().c_chat().vid.v);
|
||||
}
|
||||
| [this](not_null<ChatData*> chat) {
|
||||
if (!_photoImage.isNull()) {
|
||||
Messenger::Instance().uploadProfilePhoto(_photoImage, chat->id);
|
||||
auto image = _photo->takeResultImage();
|
||||
if (!image.isNull()) {
|
||||
Messenger::Instance().uploadProfilePhoto(
|
||||
std::move(image),
|
||||
chat->id);
|
||||
}
|
||||
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
|
||||
};
|
||||
@ -522,9 +511,10 @@ void GroupInfoBox::createChannel(const QString &title, const QString &descriptio
|
||||
return App::channel(chats->front().c_channel().vid.v);
|
||||
}
|
||||
| [this](not_null<ChannelData*> channel) {
|
||||
if (!_photoImage.isNull()) {
|
||||
auto image = _photo->takeResultImage();
|
||||
if (!image.isNull()) {
|
||||
Messenger::Instance().uploadProfilePhoto(
|
||||
_photoImage,
|
||||
std::move(image),
|
||||
channel->id);
|
||||
}
|
||||
_createdChannel = channel;
|
||||
@ -562,18 +552,19 @@ void GroupInfoBox::onDescriptionResized() {
|
||||
}
|
||||
|
||||
void GroupInfoBox::updateMaxHeight() {
|
||||
auto newHeight = st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::boxPadding.bottom() + st::newGroupInfoPadding.bottom();
|
||||
auto newHeight = st::boxPadding.top()
|
||||
+ st::newGroupInfoPadding.top()
|
||||
+ st::defaultUserpicButton.size.height()
|
||||
+ st::boxPadding.bottom()
|
||||
+ st::newGroupInfoPadding.bottom();
|
||||
if (_description) {
|
||||
newHeight += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom();
|
||||
newHeight += st::newGroupDescriptionPadding.top()
|
||||
+ _description->height()
|
||||
+ st::newGroupDescriptionPadding.bottom();
|
||||
}
|
||||
setDimensions(st::boxWideWidth, newHeight);
|
||||
}
|
||||
|
||||
void GroupInfoBox::onPhotoReady(const QImage &img) {
|
||||
_photoImage = img;
|
||||
_photo->setImage(_photoImage);
|
||||
}
|
||||
|
||||
SetupChannelBox::SetupChannelBox(QWidget*, ChannelData *channel, bool existing)
|
||||
: _channel(channel)
|
||||
, _existing(existing)
|
||||
|
@ -39,7 +39,7 @@ class RadioenumGroup;
|
||||
template <typename Enum>
|
||||
class Radioenum;
|
||||
class LinkButton;
|
||||
class NewAvatarButton;
|
||||
class UserpicButton;
|
||||
} // namespace Ui
|
||||
|
||||
enum class PeerFloodType {
|
||||
@ -105,8 +105,6 @@ protected:
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private slots:
|
||||
void onPhotoReady(const QImage &img);
|
||||
|
||||
void onNext();
|
||||
void onNameSubmit();
|
||||
void onDescriptionResized();
|
||||
@ -115,7 +113,6 @@ private slots:
|
||||
}
|
||||
|
||||
private:
|
||||
void setupPhotoButton();
|
||||
void createChannel(const QString &title, const QString &description);
|
||||
void createGroup(not_null<PeerListBox*> selectUsersBox, const QString &title, const std::vector<not_null<PeerData*>> &users);
|
||||
|
||||
@ -125,12 +122,10 @@ private:
|
||||
CreatingGroupType _creating;
|
||||
bool _fromTypeChoose = false;
|
||||
|
||||
object_ptr<Ui::NewAvatarButton> _photo;
|
||||
object_ptr<Ui::InputField> _title;
|
||||
object_ptr<Ui::UserpicButton> _photo = { nullptr };
|
||||
object_ptr<Ui::InputField> _title = { nullptr };
|
||||
object_ptr<Ui::InputArea> _description = { nullptr };
|
||||
|
||||
QImage _photoImage;
|
||||
|
||||
// group / channel creation
|
||||
mtpRequestId _creationRequestId = 0;
|
||||
ChannelData *_createdChannel = nullptr;
|
||||
|
@ -457,11 +457,6 @@ newGroupLinkPadding: margins(4px, 27px, 4px, 21px);
|
||||
newGroupLinkTop: 3px;
|
||||
newGroupLinkFont: font(16px);
|
||||
|
||||
newGroupPhotoSize: 76px;
|
||||
newGroupPhotoIcon: icon {{ "new_chat_photo", activeButtonFg }};
|
||||
newGroupPhotoIconPosition: point(23px, 25px);
|
||||
newGroupPhotoDuration: 150;
|
||||
|
||||
newGroupNamePosition: point(27px, 5px);
|
||||
|
||||
newGroupDescriptionPadding: margins(0px, 13px, 0px, 4px);
|
||||
|
@ -36,8 +36,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "boxes/add_contact_box.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "mainwidget.h"
|
||||
#include "messenger.h"
|
||||
#include "apiwrap.h"
|
||||
#include "application.h"
|
||||
#include "auth_session.h"
|
||||
@ -77,7 +77,7 @@ private:
|
||||
struct Controls {
|
||||
Ui::InputField *title = nullptr;
|
||||
Ui::InputArea *description = nullptr;
|
||||
Ui::NewAvatarButton *photo = nullptr;
|
||||
Ui::UserpicButton *photo = nullptr;
|
||||
rpl::lifetime initialPhotoImageWaiting;
|
||||
|
||||
std::shared_ptr<Ui::RadioenumGroup<Privacy>> privacy;
|
||||
@ -118,11 +118,6 @@ private:
|
||||
void submitTitle();
|
||||
void submitDescription();
|
||||
void deleteWithConfirmation();
|
||||
void choosePhotoDelayed();
|
||||
void choosePhoto();
|
||||
void suggestPhotoFile(
|
||||
const FileDialog::OpenResult &result);
|
||||
void suggestPhoto(const QImage &image);
|
||||
void privacyChanged(Privacy value);
|
||||
|
||||
void checkUsernameAvailability();
|
||||
@ -155,6 +150,7 @@ private:
|
||||
void saveDescription();
|
||||
void saveInvites();
|
||||
void saveSignatures();
|
||||
void savePhoto();
|
||||
void pushSaveStage(base::lambda_once<void()> &&lambda);
|
||||
void continueSave();
|
||||
void cancelSave();
|
||||
@ -245,7 +241,7 @@ object_ptr<Ui::RpWidget> Controller::createPhotoAndTitleEdit() {
|
||||
container->widthValue()
|
||||
| rpl::start_with_next([titleEdit](int width) {
|
||||
auto left = st::editPeerPhotoMargins.left()
|
||||
+ st::editPeerPhotoSize;
|
||||
+ st::defaultUserpicButton.size.width();
|
||||
titleEdit->resizeToWidth(width - left);
|
||||
titleEdit->moveToLeft(left, 0, width);
|
||||
}, titleEdit->lifetime());
|
||||
@ -256,16 +252,17 @@ object_ptr<Ui::RpWidget> Controller::createPhotoAndTitleEdit() {
|
||||
object_ptr<Ui::RpWidget> Controller::createPhotoEdit() {
|
||||
Expects(_wrap != nullptr);
|
||||
|
||||
using PhotoWrap = Ui::PaddingWrap<Ui::NewAvatarButton>;
|
||||
using PhotoWrap = Ui::PaddingWrap<Ui::UserpicButton>;
|
||||
auto photoWrap = object_ptr<PhotoWrap>(
|
||||
_wrap,
|
||||
object_ptr<Ui::NewAvatarButton>(
|
||||
object_ptr<Ui::UserpicButton>(
|
||||
_wrap,
|
||||
st::editPeerPhotoSize,
|
||||
st::editPeerPhotoIconPosition),
|
||||
_box->controller(),
|
||||
_channel,
|
||||
Ui::UserpicButton::Role::ChangePhoto,
|
||||
st::defaultUserpicButton),
|
||||
st::editPeerPhotoMargins);
|
||||
_controls.photo = photoWrap->entity();
|
||||
_controls.photo->addClickHandler([this] { choosePhotoDelayed(); });
|
||||
|
||||
_controls.initialPhotoImageWaiting = base::ObservableViewer(
|
||||
Auth().downloaderTaskFinished())
|
||||
@ -278,18 +275,18 @@ object_ptr<Ui::RpWidget> Controller::createPhotoEdit() {
|
||||
}
|
||||
|
||||
void Controller::refreshInitialPhotoImage() {
|
||||
if (auto image = _channel->currentUserpic()) {
|
||||
image->load();
|
||||
if (image->loaded()) {
|
||||
_controls.photo->setImage(image->pixNoCache(
|
||||
st::editPeerPhotoSize * cIntRetinaFactor(),
|
||||
st::editPeerPhotoSize * cIntRetinaFactor(),
|
||||
Images::Option::Smooth).toImage());
|
||||
_controls.initialPhotoImageWaiting.destroy();
|
||||
}
|
||||
} else {
|
||||
_controls.initialPhotoImageWaiting.destroy();
|
||||
}
|
||||
//if (auto image = _channel->currentUserpic()) {
|
||||
// image->load();
|
||||
// if (image->loaded()) {
|
||||
// _controls.photo->setImage(image->pixNoCache(
|
||||
// st::editPeerPhotoSize * cIntRetinaFactor(),
|
||||
// st::editPeerPhotoSize * cIntRetinaFactor(),
|
||||
// Images::Option::Smooth).toImage());
|
||||
// _controls.initialPhotoImageWaiting.destroy();
|
||||
// }
|
||||
//} else {
|
||||
// _controls.initialPhotoImageWaiting.destroy();
|
||||
//}
|
||||
}
|
||||
|
||||
object_ptr<Ui::RpWidget> Controller::createTitleEdit() {
|
||||
@ -968,7 +965,7 @@ void Controller::save() {
|
||||
pushSaveStage([this] { saveDescription(); });
|
||||
pushSaveStage([this] { saveInvites(); });
|
||||
pushSaveStage([this] { saveSignatures(); });
|
||||
pushSaveStage([this] { _box->closeBox(); });
|
||||
pushSaveStage([this] { savePhoto(); });
|
||||
continueSave();
|
||||
}
|
||||
}
|
||||
@ -1122,6 +1119,18 @@ void Controller::saveSignatures() {
|
||||
}).send();
|
||||
}
|
||||
|
||||
void Controller::savePhoto() {
|
||||
auto image = _controls.photo
|
||||
? _controls.photo->takeResultImage()
|
||||
: QImage();
|
||||
if (!image.isNull()) {
|
||||
Messenger::Instance().uploadProfilePhoto(
|
||||
std::move(image),
|
||||
_channel->id);
|
||||
}
|
||||
_box->closeBox();
|
||||
}
|
||||
|
||||
void Controller::deleteWithConfirmation() {
|
||||
auto text = lang(_isGroup
|
||||
? lng_sure_delete_group
|
||||
@ -1144,66 +1153,6 @@ void Controller::deleteWithConfirmation() {
|
||||
std::move(deleteCallback)), LayerOption::KeepOther);
|
||||
}
|
||||
|
||||
void Controller::choosePhotoDelayed() {
|
||||
App::CallDelayed(
|
||||
st::defaultRippleAnimation.hideDuration,
|
||||
this,
|
||||
[this] { choosePhoto(); });
|
||||
}
|
||||
|
||||
void Controller::choosePhoto() {
|
||||
auto handleChosenPhoto = base::lambda_guarded(
|
||||
_controls.photo,
|
||||
[this](auto &&result) { suggestPhotoFile(result); });
|
||||
|
||||
auto imgExtensions = cImgExtensions();
|
||||
auto filter = qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(");;") + FileDialog::AllFilesFilter();
|
||||
FileDialog::GetOpenPath(
|
||||
lang(lng_choose_image),
|
||||
filter,
|
||||
std::move(handleChosenPhoto));
|
||||
}
|
||||
|
||||
void Controller::suggestPhotoFile(
|
||||
const FileDialog::OpenResult &result) {
|
||||
if (result.paths.isEmpty() && result.remoteContent.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto image = [&] {
|
||||
if (!result.remoteContent.isEmpty()) {
|
||||
return App::readImage(result.remoteContent);
|
||||
} else if (!result.paths.isEmpty()) {
|
||||
return App::readImage(result.paths.front());
|
||||
}
|
||||
return QImage();
|
||||
}();
|
||||
suggestPhoto(image);
|
||||
}
|
||||
|
||||
void Controller::suggestPhoto(const QImage &image) {
|
||||
auto badAspect = [](int a, int b) {
|
||||
return (a >= 10 * b);
|
||||
};
|
||||
if (image.isNull()
|
||||
|| badAspect(image.width(), image.height())
|
||||
|| badAspect(image.height(), image.width())) {
|
||||
Ui::show(Box<InformBox>(lang(lng_bad_photo)));
|
||||
return;
|
||||
}
|
||||
|
||||
auto callback = [this](const QImage &cropped) {
|
||||
_controls.photo->setImage(cropped);
|
||||
};
|
||||
auto box = Ui::show(
|
||||
Box<PhotoCropBox>(image, _channel),
|
||||
LayerOption::KeepOther);
|
||||
QObject::connect(
|
||||
box,
|
||||
&PhotoCropBox::ready,
|
||||
base::lambda_guarded(_controls.photo, std::move(callback)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EditPeerInfoBox::EditPeerInfoBox(
|
||||
|
@ -21,9 +21,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "boxes/photo_crop_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "messenger.h"
|
||||
#include "mainwidget.h"
|
||||
#include "storage/file_upload.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
@ -33,7 +30,7 @@ PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer)
|
||||
init(img, nullptr);
|
||||
}
|
||||
|
||||
PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, PeerData *peer)
|
||||
PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, not_null<PeerData*> peer)
|
||||
: _img(img)
|
||||
, _peerId(peer->id) {
|
||||
init(img, peer);
|
||||
@ -52,9 +49,6 @@ void PhotoCropBox::init(const QImage &img, PeerData *peer) {
|
||||
void PhotoCropBox::prepare() {
|
||||
addButton(langFactory(lng_settings_save), [this] { sendPhoto(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
if (peerToBareInt(_peerId)) {
|
||||
connect(this, SIGNAL(ready(const QImage&)), this, SLOT(onReady(const QImage&)));
|
||||
}
|
||||
|
||||
int32 s = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
_thumb = App::pixmapFromImageInPlace(_img.scaled(s * cIntRetinaFactor(), s * cIntRetinaFactor(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
@ -288,10 +282,9 @@ void PhotoCropBox::sendPhoto() {
|
||||
tosend = cropped.copy();
|
||||
}
|
||||
|
||||
emit ready(tosend);
|
||||
closeBox();
|
||||
}
|
||||
|
||||
void PhotoCropBox::onReady(const QImage &tosend) {
|
||||
Messenger::Instance().uploadProfilePhoto(tosend, _peerId);
|
||||
auto guard = weak(this);
|
||||
_readyImages.fire(std::move(tosend));
|
||||
if (guard) {
|
||||
closeBox();
|
||||
}
|
||||
}
|
||||
|
@ -23,19 +23,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "boxes/abstract_box.h"
|
||||
|
||||
class PhotoCropBox : public BoxContent {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer);
|
||||
PhotoCropBox(QWidget*, const QImage &img, PeerData *peer);
|
||||
PhotoCropBox(QWidget*, const QImage &img, not_null<PeerData*> peer);
|
||||
|
||||
int32 mouseState(QPoint p);
|
||||
|
||||
signals:
|
||||
void ready(const QImage &tosend);
|
||||
|
||||
private slots:
|
||||
void onReady(const QImage &tosend);
|
||||
rpl::producer<QImage> ready() const {
|
||||
return _readyImages.events();
|
||||
}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
@ -58,6 +54,7 @@ private:
|
||||
QImage _img;
|
||||
QPixmap _thumb;
|
||||
QImage _mask, _fade;
|
||||
PeerId _peerId;
|
||||
PeerId _peerId = 0;
|
||||
rpl::event_stream<QImage> _readyImages;
|
||||
|
||||
};
|
||||
|
@ -547,8 +547,6 @@ managePeerButtonLabelPosition: point(25px, 10px);
|
||||
|
||||
editPeerDeleteButtonMargins: margins(23px, 16px, 23px, 16px);
|
||||
editPeerDeleteButton: sessionTerminateAllButton;
|
||||
editPeerPhotoSize: newGroupPhotoSize;
|
||||
editPeerPhotoIconPosition: newGroupPhotoIconPosition;
|
||||
editPeerPhotoMargins: margins(23px, 16px, 23px, 8px);
|
||||
editPeerTitle: defaultInputField;
|
||||
editPeerTitleMargins: margins(27px, 21px, 23px, 8px);
|
||||
|
@ -39,8 +39,6 @@ introCoverIconTop: 46px;
|
||||
|
||||
introSettingsSkip: 10px;
|
||||
|
||||
introPhotoSize: 76px;
|
||||
introPhotoIconPosition: point(23px, 25px);
|
||||
introPhotoTop: 10px;
|
||||
|
||||
introCoverTitle: FlatLabel(defaultFlatLabel) {
|
||||
|
@ -35,7 +35,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
namespace Intro {
|
||||
|
||||
SignupWidget::SignupWidget(QWidget *parent, Widget::Data *data) : Step(parent, data)
|
||||
, _photo(this, st::introPhotoSize, st::introPhotoIconPosition)
|
||||
, _photo(
|
||||
this,
|
||||
peerFromUser(0),
|
||||
Ui::UserpicButton::Role::ChangePhoto,
|
||||
st::defaultUserpicButton)
|
||||
, _first(this, st::introName, langFactory(lng_signup_firstname))
|
||||
, _last(this, st::introName, langFactory(lng_signup_lastname))
|
||||
, _invertOrder(langFirstNameGoesSecond())
|
||||
@ -49,8 +53,6 @@ SignupWidget::SignupWidget(QWidget *parent, Widget::Data *data) : Step(parent, d
|
||||
|
||||
connect(_checkRequest, SIGNAL(timeout()), this, SLOT(onCheckRequest()));
|
||||
|
||||
setupPhotoButton();
|
||||
|
||||
setErrorCentered(true);
|
||||
|
||||
setTitleText(langFactory(lng_signup_title));
|
||||
@ -68,32 +70,6 @@ void SignupWidget::refreshLang() {
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
void SignupWidget::setupPhotoButton() {
|
||||
_photo->setClickedCallback(App::LambdaDelayed(st::defaultActiveButton.ripple.hideDuration, this, [this] {
|
||||
auto imgExtensions = cImgExtensions();
|
||||
auto filter = qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(");;") + FileDialog::AllFilesFilter();
|
||||
FileDialog::GetOpenPath(lang(lng_choose_image), filter, base::lambda_guarded(this, [this](const FileDialog::OpenResult &result) {
|
||||
if (result.remoteContent.isEmpty() && result.paths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QImage img;
|
||||
if (!result.remoteContent.isEmpty()) {
|
||||
img = App::readImage(result.remoteContent);
|
||||
} else {
|
||||
img = App::readImage(result.paths.front());
|
||||
}
|
||||
|
||||
if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) {
|
||||
showError(langFactory(lng_bad_photo));
|
||||
return;
|
||||
}
|
||||
auto box = Ui::show(Box<PhotoCropBox>(img, PeerId(0)));
|
||||
connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&)));
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
void SignupWidget::resizeEvent(QResizeEvent *e) {
|
||||
Step::resizeEvent(e);
|
||||
updateControlsGeometry();
|
||||
@ -152,11 +128,6 @@ void SignupWidget::onCheckRequest() {
|
||||
}
|
||||
}
|
||||
|
||||
void SignupWidget::onPhotoReady(const QImage &img) {
|
||||
_photoImage = img;
|
||||
_photo->setImage(_photoImage);
|
||||
}
|
||||
|
||||
void SignupWidget::nameSubmitDone(const MTPauth_Authorization &result) {
|
||||
stopCheck();
|
||||
auto &d = result.c_auth_authorization();
|
||||
@ -164,7 +135,7 @@ void SignupWidget::nameSubmitDone(const MTPauth_Authorization &result) {
|
||||
showError(&Lang::Hard::ServerError);
|
||||
return;
|
||||
}
|
||||
finish(d.vuser, _photoImage);
|
||||
finish(d.vuser, _photo->takeResultImage());
|
||||
}
|
||||
|
||||
bool SignupWidget::nameSubmitFail(const RPCError &error) {
|
||||
|
@ -25,7 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
namespace Ui {
|
||||
class RoundButton;
|
||||
class InputField;
|
||||
class NewAvatarButton;
|
||||
class UserpicButton;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Intro {
|
||||
@ -48,10 +48,8 @@ protected:
|
||||
private slots:
|
||||
void onInputChange();
|
||||
void onCheckRequest();
|
||||
void onPhotoReady(const QImage &img);
|
||||
|
||||
private:
|
||||
void setupPhotoButton();
|
||||
void refreshLang();
|
||||
void updateControlsGeometry();
|
||||
|
||||
@ -60,9 +58,7 @@ private:
|
||||
|
||||
void stopCheck();
|
||||
|
||||
QImage _photoImage;
|
||||
|
||||
object_ptr<Ui::NewAvatarButton> _photo;
|
||||
object_ptr<Ui::UserpicButton> _photo;
|
||||
object_ptr<Ui::InputField> _first;
|
||||
object_ptr<Ui::InputField> _last;
|
||||
QString _firstName, _lastName;
|
||||
|
@ -449,7 +449,7 @@ QString Widget::Step::nextButtonText() const {
|
||||
return lang(lng_intro_next);
|
||||
}
|
||||
|
||||
void Widget::Step::finish(const MTPUser &user, QImage photo) {
|
||||
void Widget::Step::finish(const MTPUser &user, QImage &&photo) {
|
||||
if (user.type() != mtpc_user || !user.c_user().is_self()) {
|
||||
// No idea what to do here.
|
||||
// We could've reset intro and MTP, but this really should not happen.
|
||||
@ -475,7 +475,9 @@ void Widget::Step::finish(const MTPUser &user, QImage photo) {
|
||||
Auth().api().requestFullPeer(user);
|
||||
}
|
||||
if (!photo.isNull()) {
|
||||
Messenger::Instance().uploadProfilePhoto(photo, Auth().userId());
|
||||
Messenger::Instance().uploadProfilePhoto(
|
||||
std::move(photo),
|
||||
Auth().userId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ public:
|
||||
Data *getData() const {
|
||||
return _data;
|
||||
}
|
||||
void finish(const MTPUser &user, QImage photo = QImage());
|
||||
void finish(const MTPUser &user, QImage &&photo = QImage());
|
||||
|
||||
void goBack() {
|
||||
if (_goCallback) _goCallback(nullptr, Direction::Back);
|
||||
|
@ -849,7 +849,7 @@ bool Messenger::openLocalUrl(const QString &url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Messenger::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId) {
|
||||
void Messenger::uploadProfilePhoto(QImage &&tosend, const PeerId &peerId) {
|
||||
PreparedPhotoThumbs photoThumbs;
|
||||
QVector<MTPPhotoSize> photoSizes;
|
||||
|
||||
|
@ -150,7 +150,7 @@ public:
|
||||
void checkStartUrl();
|
||||
bool openLocalUrl(const QString &url);
|
||||
|
||||
void uploadProfilePhoto(const QImage &tosend, const PeerId &peerId);
|
||||
void uploadProfilePhoto(QImage &&tosend, const PeerId &peerId);
|
||||
void regPhotoUpdate(const PeerId &peer, const FullMsgId &msgId);
|
||||
bool isPhotoUpdating(const PeerId &peer);
|
||||
void cancelPhotoUpdate(const PeerId &peer);
|
||||
|
@ -362,7 +362,14 @@ void CoverWidget::showSetPhotoBox(const QImage &img) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto box = Ui::show(Box<PhotoCropBox>(img, _self));
|
||||
auto peer = _self;
|
||||
auto box = Ui::show(Box<PhotoCropBox>(img, peer));
|
||||
box->ready()
|
||||
| rpl::start_with_next([=](QImage &&image) {
|
||||
Messenger::Instance().uploadProfilePhoto(
|
||||
std::move(image),
|
||||
peer->id);
|
||||
}, box->lifetime());
|
||||
subscribe(box->boxClosing, [this] { onPhotoUploadStatusChanged(); });
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,34 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "styles/style_history.h"
|
||||
#include "dialogs/dialogs_layout.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "data/data_photo.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "boxes/photo_crop_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "auth_session.h"
|
||||
#include "messenger.h"
|
||||
#include "observer_peer.h"
|
||||
|
||||
namespace Ui {
|
||||
namespace {
|
||||
|
||||
constexpr int kWideScale = 5;
|
||||
|
||||
template <typename Callback>
|
||||
QPixmap CreateSquarePixmap(int width, Callback &&paintCallback) {
|
||||
auto size = QSize(width, width) * cIntRetinaFactor();
|
||||
auto image = QImage(size, QImage::Format_ARGB32_Premultiplied);
|
||||
image.setDevicePixelRatio(cRetinaFactor());
|
||||
image.fill(Qt::transparent);
|
||||
{
|
||||
Painter p(&image);
|
||||
paintCallback(p);
|
||||
}
|
||||
return App::pixmapFromImageInPlace(std::move(image));
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
HistoryDownButton::HistoryDownButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||
@ -311,41 +333,321 @@ void PeerAvatarButton::paintEvent(QPaintEvent *e) {
|
||||
}
|
||||
}
|
||||
|
||||
NewAvatarButton::NewAvatarButton(QWidget *parent, int size, QPoint position) : RippleButton(parent, st::defaultActiveButton.ripple)
|
||||
, _position(position) {
|
||||
resize(size, size);
|
||||
UserpicButton::UserpicButton(
|
||||
QWidget *parent,
|
||||
PeerId peerForCrop,
|
||||
Role role,
|
||||
const style::UserpicButton &st)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _peerForCrop(peerForCrop)
|
||||
, _role(role) {
|
||||
Expects(_role == Role::ChangePhoto);
|
||||
|
||||
_waiting = false;
|
||||
prepare();
|
||||
}
|
||||
|
||||
void NewAvatarButton::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
UserpicButton::UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<Window::Controller*> controller,
|
||||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
const style::UserpicButton &st)
|
||||
: RippleButton(parent, st.changeButton.ripple)
|
||||
, _st(st)
|
||||
, _controller(controller)
|
||||
, _peer(peer)
|
||||
, _peerForCrop(_peer->id)
|
||||
, _role(role) {
|
||||
processPeerPhoto();
|
||||
prepare();
|
||||
setupPeerViewers();
|
||||
}
|
||||
|
||||
if (!_image.isNull()) {
|
||||
p.drawPixmap(0, 0, _image);
|
||||
void UserpicButton::prepare() {
|
||||
resize(_st.size);
|
||||
_notShownYet = _waiting;
|
||||
if (!_waiting) {
|
||||
prepareUserpicPixmap();
|
||||
}
|
||||
setClickHandlerByRole();
|
||||
}
|
||||
|
||||
void UserpicButton::setClickHandlerByRole() {
|
||||
switch (_role) {
|
||||
case Role::ChangePhoto:
|
||||
addClickHandler(App::LambdaDelayed(
|
||||
_st.changeButton.ripple.hideDuration,
|
||||
this,
|
||||
[this] { changePhotoLazy(); }));
|
||||
break;
|
||||
|
||||
case Role::OpenPhoto:
|
||||
addClickHandler([this] {
|
||||
openPeerPhoto();
|
||||
});
|
||||
break;
|
||||
|
||||
case Role::OpenProfile:
|
||||
addClickHandler([this] {
|
||||
Expects(_controller != nullptr);
|
||||
|
||||
_controller->showPeerInfo(_peer);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UserpicButton::changePhotoLazy() {
|
||||
auto imgExtensions = cImgExtensions();
|
||||
auto filter = qsl("Image files (*")
|
||||
+ imgExtensions.join(qsl(" *"))
|
||||
+ qsl(");;")
|
||||
+ FileDialog::AllFilesFilter();
|
||||
auto handleChosenPhoto = base::lambda_guarded(
|
||||
this,
|
||||
[this](auto &&result) { suggestPhotoFile(result); });
|
||||
FileDialog::GetOpenPath(
|
||||
lang(lng_choose_image),
|
||||
filter,
|
||||
std::move(handleChosenPhoto));
|
||||
}
|
||||
|
||||
void UserpicButton::suggestPhotoFile(
|
||||
const FileDialog::OpenResult &result) {
|
||||
if (result.paths.isEmpty() && result.remoteContent.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(isOver() ? st::defaultActiveButton.textBgOver : st::defaultActiveButton.textBg);
|
||||
{
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.drawEllipse(rect());
|
||||
}
|
||||
|
||||
paintRipple(p, 0, 0, getms());
|
||||
|
||||
st::newGroupPhotoIcon.paint(p, _position, width());
|
||||
auto image = [&] {
|
||||
if (!result.remoteContent.isEmpty()) {
|
||||
return App::readImage(result.remoteContent);
|
||||
} else if (!result.paths.isEmpty()) {
|
||||
return App::readImage(result.paths.front());
|
||||
}
|
||||
return QImage();
|
||||
}();
|
||||
suggestPhoto(image);
|
||||
}
|
||||
|
||||
void NewAvatarButton::setImage(const QImage &image) {
|
||||
auto small = image.scaled(size() * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
Images::prepareCircle(small);
|
||||
_image = App::pixmapFromImageInPlace(std::move(small));
|
||||
_image.setDevicePixelRatio(cRetinaFactor());
|
||||
void UserpicButton::suggestPhoto(const QImage &image) {
|
||||
auto badAspect = [](int a, int b) {
|
||||
return (a >= 10 * b);
|
||||
};
|
||||
if (image.isNull()
|
||||
|| badAspect(image.width(), image.height())
|
||||
|| badAspect(image.height(), image.width())) {
|
||||
Ui::show(
|
||||
Box<InformBox>(lang(lng_bad_photo)),
|
||||
LayerOption::KeepOther);
|
||||
return;
|
||||
}
|
||||
|
||||
auto box = Ui::show(
|
||||
Box<PhotoCropBox>(image, _peerForCrop),
|
||||
LayerOption::KeepOther);
|
||||
box->ready()
|
||||
| rpl::start_with_next([this](QImage &&image) {
|
||||
setImage(std::move(image));
|
||||
}, box->lifetime());
|
||||
}
|
||||
|
||||
void UserpicButton::openPeerPhoto() {
|
||||
Expects(_peer != nullptr);
|
||||
Expects(_controller != nullptr);
|
||||
|
||||
auto id = _peer->photoId;
|
||||
if (!id || id == UnknownPeerPhotoId) {
|
||||
return;
|
||||
}
|
||||
auto photo = App::photo(id);
|
||||
if (photo->date) {
|
||||
Messenger::Instance().showPhoto(photo, _peer);
|
||||
}
|
||||
}
|
||||
|
||||
void UserpicButton::setupPeerViewers() {
|
||||
Notify::PeerUpdateViewer(
|
||||
_peer,
|
||||
Notify::PeerUpdate::Flag::PhotoChanged)
|
||||
| rpl::start_with_next([this] {
|
||||
processNewPeerPhoto();
|
||||
update();
|
||||
}, lifetime());
|
||||
base::ObservableViewer(Auth().downloaderTaskFinished())
|
||||
| rpl::start_with_next([this] {
|
||||
if (_waiting && _peer->userpicLoaded()) {
|
||||
_waiting = false;
|
||||
startNewPhotoShowing();
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void UserpicButton::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
if (!_waiting && _notShownYet) {
|
||||
_notShownYet = false;
|
||||
startAnimation();
|
||||
}
|
||||
|
||||
auto photoPosition = countPhotoPosition();
|
||||
auto photoLeft = photoPosition.x();
|
||||
auto photoTop = photoPosition.y();
|
||||
|
||||
auto ms = getms();
|
||||
if (_a_appearance.animating(ms)) {
|
||||
p.drawPixmapLeft(photoPosition, width(), _oldUserpic);
|
||||
p.setOpacity(_a_appearance.current());
|
||||
}
|
||||
p.drawPixmapLeft(photoPosition, width(), _userpic);
|
||||
|
||||
if (_role == Role::ChangePhoto) {
|
||||
auto over = isOver() || isDown();
|
||||
if (over) {
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(_userpicHasImage
|
||||
? st::msgDateImgBg
|
||||
: _st.changeButton.textBgOver);
|
||||
p.drawEllipse(
|
||||
photoLeft,
|
||||
photoTop,
|
||||
_st.photoSize,
|
||||
_st.photoSize);
|
||||
}
|
||||
paintRipple(
|
||||
p,
|
||||
photoLeft,
|
||||
photoTop,
|
||||
ms,
|
||||
_userpicHasImage
|
||||
? &st::shadowFg->c
|
||||
: &_st.changeButton.ripple.color->c);
|
||||
if (over || !_userpicHasImage) {
|
||||
auto iconLeft = (_st.changeIconPosition.x() < 0)
|
||||
? (_st.photoSize - _st.changeIcon.width()) / 2
|
||||
: _st.changeIconPosition.x();
|
||||
auto iconTop = (_st.changeIconPosition.y() < 0)
|
||||
? (_st.photoSize - _st.changeIcon.height()) / 2
|
||||
: _st.changeIconPosition.y();
|
||||
_st.changeIcon.paint(
|
||||
p,
|
||||
photoLeft + iconLeft,
|
||||
photoTop + iconTop,
|
||||
width());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPoint UserpicButton::countPhotoPosition() const {
|
||||
auto photoLeft = (_st.photoPosition.x() < 0)
|
||||
? (width() - _st.photoSize) / 2
|
||||
: _st.photoPosition.x();
|
||||
auto photoTop = (_st.photoPosition.y() < 0)
|
||||
? (height() - _st.photoSize) / 2
|
||||
: _st.photoPosition.y();
|
||||
return { photoLeft, photoTop };
|
||||
}
|
||||
|
||||
QImage UserpicButton::prepareRippleMask() const {
|
||||
return Ui::RippleAnimation::ellipseMask(QSize(
|
||||
_st.photoSize,
|
||||
_st.photoSize));
|
||||
}
|
||||
|
||||
QPoint UserpicButton::prepareRippleStartPosition() const {
|
||||
return (_role == Role::ChangePhoto)
|
||||
? mapFromGlobal(QCursor::pos()) - countPhotoPosition()
|
||||
: DisabledRippleStartPosition();
|
||||
}
|
||||
|
||||
void UserpicButton::processPeerPhoto() {
|
||||
Expects(_peer != nullptr);
|
||||
|
||||
bool hasPhoto = (_peer->photoId && _peer->photoId != UnknownPeerPhotoId);
|
||||
setCursor(hasPhoto ? style::cur_pointer : style::cur_default);
|
||||
_waiting = !_peer->userpicLoaded();
|
||||
if (_waiting) {
|
||||
_peer->loadUserpic(true);
|
||||
}
|
||||
if (_role == Role::OpenPhoto) {
|
||||
auto id = _peer->photoId;
|
||||
if (id == UnknownPeerPhotoId) {
|
||||
_peer->updateFull();
|
||||
}
|
||||
auto canOpen = (id != 0 && id != UnknownPeerPhotoId);
|
||||
setCursor(canOpen ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
|
||||
void UserpicButton::processNewPeerPhoto() {
|
||||
if (_userpicCustom) {
|
||||
return;
|
||||
}
|
||||
processPeerPhoto();
|
||||
if (!_waiting) {
|
||||
_oldUserpic = myGrab(this);
|
||||
startNewPhotoShowing();
|
||||
}
|
||||
}
|
||||
|
||||
void UserpicButton::startNewPhotoShowing() {
|
||||
prepareUserpicPixmap();
|
||||
if (_notShownYet) {
|
||||
return;
|
||||
}
|
||||
startAnimation();
|
||||
update();
|
||||
}
|
||||
|
||||
QImage NewAvatarButton::prepareRippleMask() const {
|
||||
return Ui::RippleAnimation::ellipseMask(size());
|
||||
void UserpicButton::startAnimation() {
|
||||
_a_appearance.finish();
|
||||
_a_appearance.start([this] { update(); }, 0, 1, _st.duration);
|
||||
}
|
||||
|
||||
void UserpicButton::switchChangePhotoOverlay(bool enabled) {
|
||||
|
||||
}
|
||||
|
||||
void UserpicButton::setImage(QImage &&image) {
|
||||
_oldUserpic = myGrab(this);
|
||||
|
||||
auto size = QSize(_st.photoSize, _st.photoSize);
|
||||
auto small = image.scaled(
|
||||
size * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
Images::prepareCircle(small);
|
||||
_userpic = App::pixmapFromImageInPlace(std::move(small));
|
||||
_userpic.setDevicePixelRatio(cRetinaFactor());
|
||||
_userpicCustom = _userpicHasImage = true;
|
||||
_result = std::move(image);
|
||||
|
||||
startNewPhotoShowing();
|
||||
}
|
||||
|
||||
void UserpicButton::prepareUserpicPixmap() {
|
||||
if (_userpicCustom) {
|
||||
return;
|
||||
}
|
||||
auto size = _st.photoSize;
|
||||
auto paintButton = [&](Painter &p, const style::color &color) {
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setBrush(color);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(0, 0, size, size);
|
||||
};
|
||||
_userpicHasImage = _peer
|
||||
? (_peer->currentUserpic() || _role != Role::ChangePhoto)
|
||||
: false;
|
||||
_userpic = CreateSquarePixmap(size, [&](Painter &p) {
|
||||
if (_userpicHasImage) {
|
||||
_peer->paintUserpic(p, 0, 0, _st.photoSize);
|
||||
} else {
|
||||
paintButton(p, _st.changeButton.textBg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
@ -26,6 +26,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
class PeerData;
|
||||
|
||||
namespace Window {
|
||||
class Controller;
|
||||
} // namespace Window
|
||||
|
||||
namespace FileDialog {
|
||||
struct OpenResult;
|
||||
} // namespace FileDialog
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class HistoryDownButton : public RippleButton {
|
||||
@ -162,24 +170,69 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NewAvatarButton : public RippleButton {
|
||||
class UserpicButton : public RippleButton {
|
||||
public:
|
||||
NewAvatarButton(QWidget *parent, int size, QPoint position);
|
||||
enum class Role {
|
||||
ChangePhoto,
|
||||
OpenPhoto,
|
||||
OpenProfile,
|
||||
Custom,
|
||||
};
|
||||
|
||||
void setImage(const QImage &image);
|
||||
UserpicButton(
|
||||
QWidget *parent,
|
||||
PeerId peerForCrop,
|
||||
Role role,
|
||||
const style::UserpicButton &st);
|
||||
UserpicButton(
|
||||
QWidget *parent,
|
||||
not_null<Window::Controller*> controller,
|
||||
not_null<PeerData*> peer,
|
||||
Role role,
|
||||
const style::UserpicButton &st);
|
||||
|
||||
int naturalWidth() const override {
|
||||
return height();
|
||||
void switchChangePhotoOverlay(bool enabled);
|
||||
|
||||
QImage takeResultImage() {
|
||||
return std::move(_result);
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e);
|
||||
|
||||
QImage prepareRippleMask() const override;
|
||||
QPoint prepareRippleStartPosition() const override;
|
||||
|
||||
private:
|
||||
QPixmap _image;
|
||||
QPoint _position;
|
||||
void prepare();
|
||||
void setImage(QImage &&image);
|
||||
void setupPeerViewers();
|
||||
void startAnimation();
|
||||
void processPeerPhoto();
|
||||
void processNewPeerPhoto();
|
||||
void startNewPhotoShowing();
|
||||
void prepareUserpicPixmap();
|
||||
QPoint countPhotoPosition() const;
|
||||
|
||||
void setClickHandlerByRole();
|
||||
void openPeerPhoto();
|
||||
void changePhotoLazy();
|
||||
void suggestPhotoFile(
|
||||
const FileDialog::OpenResult &result);
|
||||
void suggestPhoto(const QImage &image);
|
||||
|
||||
const style::UserpicButton &_st;
|
||||
Window::Controller *_controller = nullptr;
|
||||
PeerData *_peer = nullptr;
|
||||
PeerId _peerForCrop = 0;
|
||||
Role _role = Role::ChangePhoto;
|
||||
bool _notShownYet = true;
|
||||
bool _waiting = false;
|
||||
QPixmap _userpic, _oldUserpic;
|
||||
bool _userpicHasImage = false;
|
||||
bool _userpicCustom = false;
|
||||
Animation _a_appearance;
|
||||
QImage _result;
|
||||
|
||||
};
|
||||
|
||||
|
@ -497,6 +497,16 @@ PeerAvatarButton {
|
||||
photoSize: pixels;
|
||||
}
|
||||
|
||||
UserpicButton {
|
||||
size: size;
|
||||
photoSize: pixels;
|
||||
photoPosition: point;
|
||||
changeButton: RoundButton;
|
||||
changeIcon: icon;
|
||||
changeIconPosition: point;
|
||||
duration: int;
|
||||
}
|
||||
|
||||
InfoProfileButton {
|
||||
textFg: color;
|
||||
textFgOver: color;
|
||||
@ -975,6 +985,16 @@ defaultImportantTooltipLabel: FlatLabel(defaultFlatLabel) {
|
||||
}
|
||||
}
|
||||
|
||||
defaultUserpicButton: UserpicButton {
|
||||
size: size(76px, 76px);
|
||||
photoSize: 76px;
|
||||
photoPosition: point(-1px, -1px);
|
||||
changeButton: defaultActiveButton;
|
||||
changeIcon: icon {{ "new_chat_photo", activeButtonFg }};
|
||||
changeIconPosition: point(23px, 25px);
|
||||
duration: 500;
|
||||
}
|
||||
|
||||
historyToDownBelow: icon {
|
||||
{ "history_down_shadow", historyToDownShadow },
|
||||
{ "history_down_circle", historyToDownBg, point(4px, 4px) },
|
||||
|
@ -350,7 +350,7 @@ void Filler::addChatActions(not_null<ChatData*> chat) {
|
||||
if (_source != PeerMenuSource::ChatsList) {
|
||||
if (chat->canEdit()) {
|
||||
_addAction(
|
||||
lang(lng_profile_edit_contact),
|
||||
lang(lng_profile_edit_group_name),
|
||||
[chat] { Ui::show(Box<EditNameTitleBox>(chat)); });
|
||||
}
|
||||
if (chat->amCreator()
|
||||
|
Loading…
Reference in New Issue
Block a user