mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support adaptive forum userpic rounding radius.
This commit is contained in:
parent
2407ac50bc
commit
cb653df0f6
100 changed files with 662 additions and 724 deletions
|
@ -171,6 +171,11 @@ void CheckChatInvite(
|
||||||
|
|
||||||
} // namespace Api
|
} // namespace Api
|
||||||
|
|
||||||
|
struct ConfirmInviteBox::Participant {
|
||||||
|
not_null<UserData*> user;
|
||||||
|
Ui::PeerUserpicView userpic;
|
||||||
|
};
|
||||||
|
|
||||||
ConfirmInviteBox::ConfirmInviteBox(
|
ConfirmInviteBox::ConfirmInviteBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
|
@ -356,7 +361,7 @@ void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
|
||||||
{ .options = Images::Option::RoundCircle }));
|
{ .options = Images::Option::RoundCircle }));
|
||||||
}
|
}
|
||||||
} else if (_photoEmpty) {
|
} else if (_photoEmpty) {
|
||||||
_photoEmpty->paint(
|
_photoEmpty->paintCircle(
|
||||||
p,
|
p,
|
||||||
(width() - st::confirmInvitePhotoSize) / 2,
|
(width() - st::confirmInvitePhotoSize) / 2,
|
||||||
st::confirmInvitePhotoTop,
|
st::confirmInvitePhotoTop,
|
||||||
|
|
|
@ -21,7 +21,6 @@ class SessionController;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class CloudImageView;
|
|
||||||
class PhotoMedia;
|
class PhotoMedia;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
@ -55,10 +54,7 @@ protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Participant {
|
struct Participant;
|
||||||
not_null<UserData*> user;
|
|
||||||
std::shared_ptr<Data::CloudImageView> userpic;
|
|
||||||
};
|
|
||||||
struct ChatInvite {
|
struct ChatInvite {
|
||||||
QString title;
|
QString title;
|
||||||
QString about;
|
QString about;
|
||||||
|
|
|
@ -114,7 +114,7 @@ struct Context {
|
||||||
struct Userpic {
|
struct Userpic {
|
||||||
not_null<PeerData*> peer;
|
not_null<PeerData*> peer;
|
||||||
QString customEntityData;
|
QString customEntityData;
|
||||||
mutable std::shared_ptr<Data::CloudImageView> view;
|
mutable Ui::PeerUserpicView view;
|
||||||
mutable InMemoryKey uniqueKey;
|
mutable InMemoryKey uniqueKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -380,7 +380,7 @@ bool UpdateUserpics(
|
||||||
const auto peer = not_null{ resolved.peer };
|
const auto peer = not_null{ resolved.peer };
|
||||||
const auto &data = ReactionEntityData(resolved.reaction);
|
const auto &data = ReactionEntityData(resolved.reaction);
|
||||||
const auto i = ranges::find(was, peer, &Userpic::peer);
|
const auto i = ranges::find(was, peer, &Userpic::peer);
|
||||||
if (i != end(was) && i->view) {
|
if (i != end(was) && i->view.cloud) {
|
||||||
now.push_back(std::move(*i));
|
now.push_back(std::move(*i));
|
||||||
now.back().customEntityData = data;
|
now.back().customEntityData = data;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -84,7 +84,7 @@ private:
|
||||||
};
|
};
|
||||||
struct PeerButton {
|
struct PeerButton {
|
||||||
not_null<History*> history;
|
not_null<History*> history;
|
||||||
std::shared_ptr<Data::CloudImageView> userpic;
|
Ui::PeerUserpicView userpic;
|
||||||
Ui::Text::String name;
|
Ui::Text::String name;
|
||||||
Button button;
|
Button button;
|
||||||
};
|
};
|
||||||
|
|
|
@ -157,7 +157,7 @@ PaintRoundImageCallback ExceptionRow::generatePaintUserpicCallback() {
|
||||||
const auto peer = this->peer();
|
const auto peer = this->peer();
|
||||||
const auto saved = peer->isSelf();
|
const auto saved = peer->isSelf();
|
||||||
const auto replies = peer->isRepliesChat();
|
const auto replies = peer->isRepliesChat();
|
||||||
auto userpic = saved ? nullptr : ensureUserpicView();
|
auto userpic = saved ? Ui::PeerUserpicView() : ensureUserpicView();
|
||||||
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
||||||
if (saved) {
|
if (saved) {
|
||||||
Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size);
|
Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size);
|
||||||
|
|
|
@ -48,7 +48,7 @@ PaintRoundImageCallback PaintUserpicCallback(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto userpic = std::shared_ptr<Data::CloudImageView>();
|
auto userpic = Ui::PeerUserpicView();
|
||||||
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
||||||
peer->paintUserpicLeft(p, userpic, x, y, outerWidth, size);
|
peer->paintUserpicLeft(p, userpic, x, y, outerWidth, size);
|
||||||
};
|
};
|
||||||
|
@ -635,8 +635,8 @@ QString PeerListRow::generateShortName() {
|
||||||
: peer()->shortName();
|
: peer()->shortName();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Data::CloudImageView> &PeerListRow::ensureUserpicView() {
|
Ui::PeerUserpicView &PeerListRow::ensureUserpicView() {
|
||||||
if (!_userpic) {
|
if (!_userpic.cloud && peer()->hasUserpic()) {
|
||||||
_userpic = peer()->createUserpicView();
|
_userpic = peer()->createUserpicView();
|
||||||
}
|
}
|
||||||
return _userpic;
|
return _userpic;
|
||||||
|
@ -646,7 +646,7 @@ PaintRoundImageCallback PeerListRow::generatePaintUserpicCallback() {
|
||||||
const auto saved = _isSavedMessagesChat;
|
const auto saved = _isSavedMessagesChat;
|
||||||
const auto replies = _isRepliesMessagesChat;
|
const auto replies = _isRepliesMessagesChat;
|
||||||
const auto peer = this->peer();
|
const auto peer = this->peer();
|
||||||
auto userpic = saved ? nullptr : ensureUserpicView();
|
auto userpic = saved ? Ui::PeerUserpicView() : ensureUserpicView();
|
||||||
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
||||||
if (saved) {
|
if (saved) {
|
||||||
Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size);
|
Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size);
|
||||||
|
@ -840,10 +840,10 @@ void PeerListRow::lazyInitialize(const style::PeerListItem &st) {
|
||||||
void PeerListRow::createCheckbox(
|
void PeerListRow::createCheckbox(
|
||||||
const style::RoundImageCheckbox &st,
|
const style::RoundImageCheckbox &st,
|
||||||
Fn<void()> updateCallback) {
|
Fn<void()> updateCallback) {
|
||||||
const auto generateRadius = [=] {
|
const auto generateRadius = [=](int size) {
|
||||||
return (!special() && peer()->isForum())
|
return (!special() && peer()->isForum())
|
||||||
? ImageRoundRadius::Large
|
? int(size * Ui::ForumUserpicRadiusMultiplier())
|
||||||
: ImageRoundRadius::Ellipse;
|
: std::optional<int>();
|
||||||
};
|
};
|
||||||
_checkbox = std::make_unique<Ui::RoundImageCheckbox>(
|
_checkbox = std::make_unique<Ui::RoundImageCheckbox>(
|
||||||
st,
|
st,
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
#include "ui/empty_userpic.h"
|
#include "ui/empty_userpic.h"
|
||||||
#include "ui/unread_badge.h"
|
#include "ui/unread_badge.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
#include "boxes/abstract_box.h"
|
#include "boxes/abstract_box.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "data/data_cloud_file.h"
|
#include "data/data_cloud_file.h"
|
||||||
|
@ -84,7 +85,7 @@ public:
|
||||||
return _id;
|
return _id;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::shared_ptr<Data::CloudImageView> &ensureUserpicView();
|
[[nodiscard]] Ui::PeerUserpicView &ensureUserpicView();
|
||||||
|
|
||||||
[[nodiscard]] virtual QString generateName();
|
[[nodiscard]] virtual QString generateName();
|
||||||
[[nodiscard]] virtual QString generateShortName();
|
[[nodiscard]] virtual QString generateShortName();
|
||||||
|
@ -262,7 +263,7 @@ private:
|
||||||
|
|
||||||
PeerListRowId _id = 0;
|
PeerListRowId _id = 0;
|
||||||
PeerData *_peer = nullptr;
|
PeerData *_peer = nullptr;
|
||||||
mutable std::shared_ptr<Data::CloudImageView> _userpic;
|
mutable Ui::PeerUserpicView _userpic;
|
||||||
std::unique_ptr<Ui::RippleAnimation> _ripple;
|
std::unique_ptr<Ui::RippleAnimation> _ripple;
|
||||||
std::unique_ptr<Ui::RoundImageCheckbox> _checkbox;
|
std::unique_ptr<Ui::RoundImageCheckbox> _checkbox;
|
||||||
Ui::Text::String _name;
|
Ui::Text::String _name;
|
||||||
|
|
|
@ -632,7 +632,7 @@ auto ChooseTopicBoxController::Row::generatePaintUserpicCallback()
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
int size) {
|
int size) {
|
||||||
auto view = std::shared_ptr<Data::CloudImageView>();
|
auto view = Ui::PeerUserpicView();
|
||||||
p.translate(x, y);
|
p.translate(x, y);
|
||||||
_topic->paintUserpic(p, view, {
|
_topic->paintUserpic(p, view, {
|
||||||
.st = &st::forumTopicRow,
|
.st = &st::forumTopicRow,
|
||||||
|
|
|
@ -1042,11 +1042,12 @@ void AddPermanentLinkBlock(
|
||||||
state->allUserpicsLoaded = ranges::all_of(
|
state->allUserpicsLoaded = ranges::all_of(
|
||||||
state->list,
|
state->list,
|
||||||
[](const HistoryView::UserpicInRow &element) {
|
[](const HistoryView::UserpicInRow &element) {
|
||||||
return !element.peer->hasUserpic() || element.view->image();
|
return !element.peer->hasUserpic()
|
||||||
|
|| !Ui::PeerUserpicLoading(element.view);
|
||||||
});
|
});
|
||||||
state->content = Ui::JoinedCountContent{
|
state->content = Ui::JoinedCountContent{
|
||||||
.count = state->count,
|
.count = state->count,
|
||||||
.userpics = state->cachedUserpics
|
.userpics = state->cachedUserpics,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
value->value(
|
value->value(
|
||||||
|
@ -1087,7 +1088,7 @@ void AddPermanentLinkBlock(
|
||||||
} else if (element.peer->userpicUniqueKey(element.view)
|
} else if (element.peer->userpicUniqueKey(element.view)
|
||||||
!= element.uniqueKey) {
|
!= element.uniqueKey) {
|
||||||
pushing = true;
|
pushing = true;
|
||||||
} else if (!element.view->image()) {
|
} else if (Ui::PeerUserpicLoading(element.view)) {
|
||||||
state->allUserpicsLoaded = false;
|
state->allUserpicsLoaded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ struct UserpicState {
|
||||||
PeerShortInfoUserpic current;
|
PeerShortInfoUserpic current;
|
||||||
std::optional<UserPhotosSlice> userSlice;
|
std::optional<UserPhotosSlice> userSlice;
|
||||||
PhotoId userpicPhotoId = PeerData::kUnknownPhotoId;
|
PhotoId userpicPhotoId = PeerData::kUnknownPhotoId;
|
||||||
std::shared_ptr<Data::CloudImageView> userpicView;
|
Ui::PeerUserpicView userpicView;
|
||||||
std::shared_ptr<Data::PhotoMedia> photoView;
|
std::shared_ptr<Data::PhotoMedia> photoView;
|
||||||
std::vector<std::shared_ptr<Data::PhotoMedia>> photoPreloads;
|
std::vector<std::shared_ptr<Data::PhotoMedia>> photoPreloads;
|
||||||
InMemoryKey userpicKey;
|
InMemoryKey userpicKey;
|
||||||
|
@ -76,27 +76,26 @@ void ProcessUserpic(
|
||||||
not_null<UserpicState*> state) {
|
not_null<UserpicState*> state) {
|
||||||
state->current.videoDocument = nullptr;
|
state->current.videoDocument = nullptr;
|
||||||
state->userpicKey = peer->userpicUniqueKey(state->userpicView);
|
state->userpicKey = peer->userpicUniqueKey(state->userpicView);
|
||||||
if (!state->userpicView) {
|
if (!state->userpicView.cloud) {
|
||||||
GenerateImage(
|
GenerateImage(
|
||||||
state,
|
state,
|
||||||
peer->generateUserpicImage(
|
peer->generateUserpicImage(
|
||||||
state->userpicView,
|
state->userpicView,
|
||||||
st::shortInfoWidth * style::DevicePixelRatio(),
|
st::shortInfoWidth * style::DevicePixelRatio(),
|
||||||
ImageRoundRadius::None),
|
0),
|
||||||
false);
|
false);
|
||||||
state->current.photoLoadingProgress = 1.;
|
state->current.photoLoadingProgress = 1.;
|
||||||
state->photoView = nullptr;
|
state->photoView = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
peer->loadUserpic();
|
peer->loadUserpic();
|
||||||
const auto image = state->userpicView->image();
|
if (Ui::PeerUserpicLoading(state->userpicView)) {
|
||||||
if (!image) {
|
|
||||||
state->current.photoLoadingProgress = 0.;
|
state->current.photoLoadingProgress = 0.;
|
||||||
state->current.photo = QImage();
|
state->current.photo = QImage();
|
||||||
state->waitingLoad = true;
|
state->waitingLoad = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GenerateImage(state, image, true);
|
GenerateImage(state, *state->userpicView.cloud, true);
|
||||||
state->current.photoLoadingProgress = peer->userpicPhotoId() ? 0. : 1.;
|
state->current.photoLoadingProgress = peer->userpicPhotoId() ? 0. : 1.;
|
||||||
state->photoView = nullptr;
|
state->photoView = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -411,7 +410,7 @@ bool ProcessCurrent(
|
||||||
return state->waitingLoad
|
return state->waitingLoad
|
||||||
&& (state->photoView
|
&& (state->photoView
|
||||||
? (!!state->photoView->image(Data::PhotoSize::Large))
|
? (!!state->photoView->image(Data::PhotoSize::Large))
|
||||||
: (state->userpicView && state->userpicView->image()));
|
: (!Ui::PeerUserpicLoading(state->userpicView)));
|
||||||
}) | rpl::start_with_next([=] {
|
}) | rpl::start_with_next([=] {
|
||||||
push();
|
push();
|
||||||
}, lifetime);
|
}, lifetime);
|
||||||
|
|
|
@ -536,7 +536,7 @@ void ShareBox::applyFilterUpdate(const QString &query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PaintRoundImageCallback ForceRoundUserpicCallback(not_null<PeerData*> peer) {
|
PaintRoundImageCallback ForceRoundUserpicCallback(not_null<PeerData*> peer) {
|
||||||
auto userpic = std::shared_ptr<Data::CloudImageView>();
|
auto userpic = Ui::PeerUserpicView();
|
||||||
auto cache = std::make_shared<QImage>();
|
auto cache = std::make_shared<QImage>();
|
||||||
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
||||||
const auto ratio = style::DevicePixelRatio();
|
const auto ratio = style::DevicePixelRatio();
|
||||||
|
@ -956,9 +956,9 @@ ShareBox::Inner::Chat::Chat(
|
||||||
st.checkbox,
|
st.checkbox,
|
||||||
updateCallback,
|
updateCallback,
|
||||||
PaintUserpicCallback(peer, true),
|
PaintUserpicCallback(peer, true),
|
||||||
[=] { return peer->isForum()
|
[=](int size) { return peer->isForum()
|
||||||
? ImageRoundRadius::Large
|
? int(size * Ui::ForumUserpicRadiusMultiplier())
|
||||||
: ImageRoundRadius::Ellipse; })
|
: std::optional<int>(); })
|
||||||
, name(st.checkbox.imageRadius * 2) {
|
, name(st.checkbox.imageRadius * 2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ class PowerSaveBlocker;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class PhotoMedia;
|
class PhotoMedia;
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
|
@ -159,7 +159,12 @@ void Userpic::refreshPhoto() {
|
||||||
_userPhotoFull = true;
|
_userPhotoFull = true;
|
||||||
createCache(_photo->image(Data::PhotoSize::Thumbnail));
|
createCache(_photo->image(Data::PhotoSize::Thumbnail));
|
||||||
} else if (_userPhoto.isNull()) {
|
} else if (_userPhoto.isNull()) {
|
||||||
createCache(_userpic ? _userpic->image() : nullptr);
|
if (const auto cloud = _peer->userpicCloudImage(_userpic)) {
|
||||||
|
auto image = Image(base::duplicate(*cloud));
|
||||||
|
createCache(&image);
|
||||||
|
} else {
|
||||||
|
createCache(nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +205,7 @@ void Userpic::createCache(Image *image) {
|
||||||
Ui::EmptyUserpic::UserpicColor(
|
Ui::EmptyUserpic::UserpicColor(
|
||||||
Data::PeerColorIndex(_peer->id)),
|
Data::PeerColorIndex(_peer->id)),
|
||||||
_peer->name()
|
_peer->name()
|
||||||
).paint(p, 0, 0, size, size);
|
).paintCircle(p, 0, 0, size, size);
|
||||||
}
|
}
|
||||||
//_userPhoto = Images::PixmapFast(Images::Round(
|
//_userPhoto = Images::PixmapFast(Images::Round(
|
||||||
// std::move(filled),
|
// std::move(filled),
|
||||||
|
|
|
@ -8,13 +8,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
|
|
||||||
class PeerData;
|
class PeerData;
|
||||||
class Image;
|
class Image;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class CloudImageView;
|
|
||||||
class PhotoMedia;
|
class PhotoMedia;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ private:
|
||||||
Ui::RpWidget _content;
|
Ui::RpWidget _content;
|
||||||
|
|
||||||
not_null<PeerData*> _peer;
|
not_null<PeerData*> _peer;
|
||||||
std::shared_ptr<Data::CloudImageView> _userpic;
|
Ui::PeerUserpicView _userpic;
|
||||||
std::shared_ptr<Data::PhotoMedia> _photo;
|
std::shared_ptr<Data::PhotoMedia> _photo;
|
||||||
Ui::Animations::Simple _mutedAnimation;
|
Ui::Animations::Simple _mutedAnimation;
|
||||||
QPixmap _userPhoto;
|
QPixmap _userPhoto;
|
||||||
|
|
|
@ -350,7 +350,7 @@ void MembersRow::updateBlobAnimation(crl::time now) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MembersRow::ensureUserpicCache(
|
void MembersRow::ensureUserpicCache(
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
int size) {
|
int size) {
|
||||||
Expects(_blobsAnimation != nullptr);
|
Expects(_blobsAnimation != nullptr);
|
||||||
|
|
||||||
|
@ -401,7 +401,7 @@ void MembersRow::paintBlobs(
|
||||||
|
|
||||||
void MembersRow::paintScaledUserpic(
|
void MembersRow::paintScaledUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpic,
|
Ui::PeerUserpicView &userpic,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct GroupCallParticipant;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class RippleAnimation;
|
class RippleAnimation;
|
||||||
|
struct PeerUserpicView;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Calls::Group {
|
namespace Calls::Group {
|
||||||
|
@ -180,7 +181,7 @@ private:
|
||||||
void setVolume(int volume);
|
void setVolume(int volume);
|
||||||
|
|
||||||
void ensureUserpicCache(
|
void ensureUserpicCache(
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
int size);
|
int size);
|
||||||
void paintBlobs(
|
void paintBlobs(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
@ -190,7 +191,7 @@ private:
|
||||||
int sizeh, PanelMode mode);
|
int sizeh, PanelMode mode);
|
||||||
void paintScaledUserpic(
|
void paintScaledUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpic,
|
Ui::PeerUserpicView &userpic,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
|
|
|
@ -59,7 +59,7 @@ private:
|
||||||
const not_null<QAction*> _dummyAction;
|
const not_null<QAction*> _dummyAction;
|
||||||
const style::Menu &_st;
|
const style::Menu &_st;
|
||||||
const not_null<PeerData*> _peer;
|
const not_null<PeerData*> _peer;
|
||||||
std::shared_ptr<Data::CloudImageView> _userpicView;
|
Ui::PeerUserpicView _userpicView;
|
||||||
|
|
||||||
Ui::Text::String _text;
|
Ui::Text::String _text;
|
||||||
Ui::Text::String _name;
|
Ui::Text::String _name;
|
||||||
|
|
|
@ -29,7 +29,6 @@ class PowerSaveBlocker;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class PhotoMedia;
|
class PhotoMedia;
|
||||||
class CloudImageView;
|
|
||||||
class GroupCall;
|
class GroupCall;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
|
|
@ -462,7 +462,7 @@ void Viewport::RendererGL::validateUserpicFrame(
|
||||||
tileData.userpicFrame = tile->row()->peer()->generateUserpicImage(
|
tileData.userpicFrame = tile->row()->peer()->generateUserpicImage(
|
||||||
tile->row()->ensureUserpicView(),
|
tile->row()->ensureUserpicView(),
|
||||||
size.width(),
|
size.width(),
|
||||||
ImageRoundRadius::None);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewport::RendererGL::paintTile(
|
void Viewport::RendererGL::paintTile(
|
||||||
|
|
|
@ -80,7 +80,7 @@ void Viewport::RendererSW::validateUserpicFrame(
|
||||||
tile->row()->peer()->generateUserpicImage(
|
tile->row()->peer()->generateUserpicImage(
|
||||||
tile->row()->ensureUserpicView(),
|
tile->row()->ensureUserpicView(),
|
||||||
size.width(),
|
size.width(),
|
||||||
ImageRoundRadius::None),
|
0),
|
||||||
kBlurRadius);
|
kBlurRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,20 @@ struct FieldAutocomplete::StickerSuggestion {
|
||||||
QImage premiumLock;
|
QImage premiumLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FieldAutocomplete::MentionRow {
|
||||||
|
not_null<UserData*> user;
|
||||||
|
Ui::Text::String name;
|
||||||
|
Ui::PeerUserpicView userpic;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FieldAutocomplete::BotCommandRow {
|
||||||
|
not_null<UserData*> user;
|
||||||
|
QString command;
|
||||||
|
QString description;
|
||||||
|
Ui::PeerUserpicView userpic;
|
||||||
|
Ui::Text::String descriptionText;
|
||||||
|
};
|
||||||
|
|
||||||
FieldAutocomplete::FieldAutocomplete(
|
FieldAutocomplete::FieldAutocomplete(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Window::SessionController*> controller)
|
not_null<Window::SessionController*> controller)
|
||||||
|
|
|
@ -31,7 +31,6 @@ class SessionController;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class DocumentMedia;
|
class DocumentMedia;
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace SendMenu {
|
namespace SendMenu {
|
||||||
|
@ -131,20 +130,8 @@ private:
|
||||||
class Inner;
|
class Inner;
|
||||||
friend class Inner;
|
friend class Inner;
|
||||||
struct StickerSuggestion;
|
struct StickerSuggestion;
|
||||||
|
struct MentionRow;
|
||||||
struct MentionRow {
|
struct BotCommandRow;
|
||||||
not_null<UserData*> user;
|
|
||||||
Ui::Text::String name;
|
|
||||||
std::shared_ptr<Data::CloudImageView> userpic;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BotCommandRow {
|
|
||||||
not_null<UserData*> user;
|
|
||||||
QString command;
|
|
||||||
QString description;
|
|
||||||
std::shared_ptr<Data::CloudImageView> userpic;
|
|
||||||
Ui::Text::String descriptionText;
|
|
||||||
};
|
|
||||||
|
|
||||||
using HashtagRows = std::vector<QString>;
|
using HashtagRows = std::vector<QString>;
|
||||||
using BotCommandRows = std::vector<BotCommandRow>;
|
using BotCommandRows = std::vector<BotCommandRow>;
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "chat_helpers/tabbed_selector.h"
|
#include "chat_helpers/tabbed_selector.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "ui/round_rect.h"
|
#include "ui/round_rect.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class InputField;
|
class InputField;
|
||||||
|
@ -21,7 +22,6 @@ namespace Data {
|
||||||
class StickersSet;
|
class StickersSet;
|
||||||
class StickersSetThumbnailView;
|
class StickersSetThumbnailView;
|
||||||
class DocumentMedia;
|
class DocumentMedia;
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Lottie {
|
namespace Lottie {
|
||||||
|
@ -73,7 +73,7 @@ struct StickerIcon {
|
||||||
ChannelData *megagroup = nullptr;
|
ChannelData *megagroup = nullptr;
|
||||||
mutable std::shared_ptr<Data::StickersSetThumbnailView> thumbnailMedia;
|
mutable std::shared_ptr<Data::StickersSetThumbnailView> thumbnailMedia;
|
||||||
mutable std::shared_ptr<Data::DocumentMedia> stickerMedia;
|
mutable std::shared_ptr<Data::DocumentMedia> stickerMedia;
|
||||||
mutable std::shared_ptr<Data::CloudImageView> megagroupUserpic;
|
mutable Ui::PeerUserpicView megagroupUserpic;
|
||||||
int pixw = 0;
|
int pixw = 0;
|
||||||
int pixh = 0;
|
int pixh = 0;
|
||||||
mutable rpl::lifetime lifetime;
|
mutable rpl::lifetime lifetime;
|
||||||
|
|
|
@ -22,13 +22,6 @@ CloudFile::~CloudFile() {
|
||||||
base::take(loader);
|
base::take(loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudImageView::set(
|
|
||||||
not_null<Main::Session*> session,
|
|
||||||
QImage image) {
|
|
||||||
_image.emplace(std::move(image));
|
|
||||||
session->notifyDownloaderTaskFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
CloudImage::CloudImage() = default;
|
CloudImage::CloudImage() = default;
|
||||||
|
|
||||||
CloudImage::CloudImage(
|
CloudImage::CloudImage(
|
||||||
|
@ -37,10 +30,6 @@ CloudImage::CloudImage(
|
||||||
update(session, data);
|
update(session, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *CloudImageView::image() {
|
|
||||||
return _image ? &*_image : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CloudImage::set(
|
void CloudImage::set(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const ImageWithLocation &data) {
|
const ImageWithLocation &data) {
|
||||||
|
@ -52,11 +41,11 @@ void CloudImage::set(
|
||||||
_file.location = ImageLocation();
|
_file.location = ImageLocation();
|
||||||
_file.byteSize = 0;
|
_file.byteSize = 0;
|
||||||
_file.flags = CloudFile::Flag();
|
_file.flags = CloudFile::Flag();
|
||||||
_view = std::weak_ptr<CloudImageView>();
|
_view = std::weak_ptr<QImage>();
|
||||||
} else if (was != now
|
} else if (was != now
|
||||||
&& (!v::is<InMemoryLocation>(was) || v::is<InMemoryLocation>(now))) {
|
&& (!v::is<InMemoryLocation>(was) || v::is<InMemoryLocation>(now))) {
|
||||||
_file.location = ImageLocation();
|
_file.location = ImageLocation();
|
||||||
_view = std::weak_ptr<CloudImageView>();
|
_view = std::weak_ptr<QImage>();
|
||||||
}
|
}
|
||||||
UpdateCloudFile(
|
UpdateCloudFile(
|
||||||
_file,
|
_file,
|
||||||
|
@ -65,9 +54,7 @@ void CloudImage::set(
|
||||||
kImageCacheTag,
|
kImageCacheTag,
|
||||||
[=](FileOrigin origin) { load(session, origin); },
|
[=](FileOrigin origin) { load(session, origin); },
|
||||||
[=](QImage preloaded, QByteArray) {
|
[=](QImage preloaded, QByteArray) {
|
||||||
if (const auto view = activeView()) {
|
setToActive(session, std::move(preloaded));
|
||||||
view->set(session, data.preloaded);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,9 +68,7 @@ void CloudImage::update(
|
||||||
kImageCacheTag,
|
kImageCacheTag,
|
||||||
[=](FileOrigin origin) { load(session, origin); },
|
[=](FileOrigin origin) { load(session, origin); },
|
||||||
[=](QImage preloaded, QByteArray) {
|
[=](QImage preloaded, QByteArray) {
|
||||||
if (const auto view = activeView()) {
|
setToActive(session, std::move(preloaded));
|
||||||
view->set(session, data.preloaded);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,16 +92,14 @@ void CloudImage::load(not_null<Main::Session*> session, FileOrigin origin) {
|
||||||
const auto autoLoading = false;
|
const auto autoLoading = false;
|
||||||
const auto finalCheck = [=] {
|
const auto finalCheck = [=] {
|
||||||
if (const auto active = activeView()) {
|
if (const auto active = activeView()) {
|
||||||
return !active->image();
|
return active->isNull();
|
||||||
} else if (_file.flags & CloudFile::Flag::Loaded) {
|
} else if (_file.flags & CloudFile::Flag::Loaded) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !(_file.flags & CloudFile::Flag::Loaded);
|
return !(_file.flags & CloudFile::Flag::Loaded);
|
||||||
};
|
};
|
||||||
const auto done = [=](QImage result, QByteArray) {
|
const auto done = [=](QImage result, QByteArray) {
|
||||||
if (const auto active = activeView()) {
|
setToActive(session, std::move(result));
|
||||||
active->set(session, std::move(result));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
LoadCloudFile(
|
LoadCloudFile(
|
||||||
session,
|
session,
|
||||||
|
@ -137,27 +120,37 @@ int CloudImage::byteSize() const {
|
||||||
return _file.byteSize;
|
return _file.byteSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<CloudImageView> CloudImage::createView() {
|
std::shared_ptr<QImage> CloudImage::createView() {
|
||||||
if (auto active = activeView()) {
|
if (auto active = activeView()) {
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
auto view = std::make_shared<CloudImageView>();
|
auto view = std::make_shared<QImage>();
|
||||||
_view = view;
|
_view = view;
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<CloudImageView> CloudImage::activeView() const {
|
std::shared_ptr<QImage> CloudImage::activeView() const {
|
||||||
return _view.lock();
|
return _view.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CloudImage::isCurrentView(
|
bool CloudImage::isCurrentView(const std::shared_ptr<QImage> &view) const {
|
||||||
const std::shared_ptr<CloudImageView> &view) const {
|
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return empty();
|
return empty();
|
||||||
}
|
}
|
||||||
return !view.owner_before(_view) && !_view.owner_before(view);
|
return !view.owner_before(_view) && !_view.owner_before(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CloudImage::setToActive(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
QImage image) {
|
||||||
|
if (const auto view = activeView()) {
|
||||||
|
*view = image.isNull()
|
||||||
|
? Image::Empty()->original()
|
||||||
|
: std::move(image);
|
||||||
|
session->notifyDownloaderTaskFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateCloudFile(
|
void UpdateCloudFile(
|
||||||
CloudFile &file,
|
CloudFile &file,
|
||||||
const ImageWithLocation &data,
|
const ImageWithLocation &data,
|
||||||
|
|
|
@ -44,17 +44,6 @@ struct CloudFile final {
|
||||||
base::flags<Flag> flags;
|
base::flags<Flag> flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CloudImageView final {
|
|
||||||
public:
|
|
||||||
void set(not_null<Main::Session*> session, QImage image);
|
|
||||||
|
|
||||||
[[nodiscard]] Image *image();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::optional<Image> _image;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class CloudImage final {
|
class CloudImage final {
|
||||||
public:
|
public:
|
||||||
CloudImage();
|
CloudImage();
|
||||||
|
@ -79,14 +68,16 @@ public:
|
||||||
[[nodiscard]] const ImageLocation &location() const;
|
[[nodiscard]] const ImageLocation &location() const;
|
||||||
[[nodiscard]] int byteSize() const;
|
[[nodiscard]] int byteSize() const;
|
||||||
|
|
||||||
[[nodiscard]] std::shared_ptr<CloudImageView> createView();
|
[[nodiscard]] std::shared_ptr<QImage> createView();
|
||||||
[[nodiscard]] std::shared_ptr<CloudImageView> activeView() const;
|
[[nodiscard]] std::shared_ptr<QImage> activeView() const;
|
||||||
[[nodiscard]] bool isCurrentView(
|
[[nodiscard]] bool isCurrentView(
|
||||||
const std::shared_ptr<CloudImageView> &view) const;
|
const std::shared_ptr<QImage> &view) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setToActive(not_null<Main::Session*> session, QImage image);
|
||||||
|
|
||||||
CloudFile _file;
|
CloudFile _file;
|
||||||
std::weak_ptr<CloudImageView> _view;
|
std::weak_ptr<QImage> _view;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -216,7 +216,7 @@ void Folder::loadUserpic() {
|
||||||
|
|
||||||
void Folder::paintUserpic(
|
void Folder::paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
const Dialogs::Ui::PaintContext &context) const {
|
const Dialogs::Ui::PaintContext &context) const {
|
||||||
paintUserpic(
|
paintUserpic(
|
||||||
p,
|
p,
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
void loadUserpic() override;
|
void loadUserpic() override;
|
||||||
void paintUserpic(
|
void paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
const Dialogs::Ui::PaintContext &context) const override;
|
const Dialogs::Ui::PaintContext &context) const override;
|
||||||
void paintUserpic(Painter &p, int x, int y, int size) const;
|
void paintUserpic(Painter &p, int x, int y, int size) const;
|
||||||
void paintUserpic(
|
void paintUserpic(
|
||||||
|
|
|
@ -568,7 +568,7 @@ void ForumTopic::loadUserpic() {
|
||||||
|
|
||||||
void ForumTopic::paintUserpic(
|
void ForumTopic::paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
const Dialogs::Ui::PaintContext &context) const {
|
const Dialogs::Ui::PaintContext &context) const {
|
||||||
const auto &st = context.st;
|
const auto &st = context.st;
|
||||||
auto position = QPoint(st->padding.left(), st->padding.top());
|
auto position = QPoint(st->padding.left(), st->padding.top());
|
||||||
|
|
|
@ -150,7 +150,7 @@ public:
|
||||||
void loadUserpic() override;
|
void loadUserpic() override;
|
||||||
void paintUserpic(
|
void paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
const Dialogs::Ui::PaintContext &context) const override;
|
const Dialogs::Ui::PaintContext &context) const override;
|
||||||
void clearUserpicLoops();
|
void clearUserpicLoops();
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,7 @@ void PeerData::updateNameDelayed(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_name = newName;
|
_name = newName;
|
||||||
_userpicEmpty = nullptr;
|
invalidateEmptyUserpic();
|
||||||
|
|
||||||
auto flags = UpdateFlag::None | UpdateFlag::None;
|
auto flags = UpdateFlag::None | UpdateFlag::None;
|
||||||
auto oldFirstLetters = base::flat_set<QChar>();
|
auto oldFirstLetters = base::flat_set<QChar>();
|
||||||
|
@ -231,13 +231,17 @@ not_null<Ui::EmptyUserpic*> PeerData::ensureEmptyUserpic() const {
|
||||||
const auto user = asUser();
|
const auto user = asUser();
|
||||||
_userpicEmpty = std::make_unique<Ui::EmptyUserpic>(
|
_userpicEmpty = std::make_unique<Ui::EmptyUserpic>(
|
||||||
Ui::EmptyUserpic::UserpicColor(Data::PeerColorIndex(id)),
|
Ui::EmptyUserpic::UserpicColor(Data::PeerColorIndex(id)),
|
||||||
user && user->isInaccessible()
|
((user && user->isInaccessible())
|
||||||
? Ui::EmptyUserpic::InaccessibleName()
|
? Ui::EmptyUserpic::InaccessibleName()
|
||||||
: name());
|
: name()));
|
||||||
}
|
}
|
||||||
return _userpicEmpty.get();
|
return _userpicEmpty.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PeerData::invalidateEmptyUserpic() {
|
||||||
|
_userpicEmpty = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ClickHandlerPtr PeerData::createOpenLink() {
|
ClickHandlerPtr PeerData::createOpenLink() {
|
||||||
return std::make_shared<PeerClickHandler>(this);
|
return std::make_shared<PeerClickHandler>(this);
|
||||||
}
|
}
|
||||||
|
@ -265,50 +269,45 @@ void PeerData::setUserpicPhoto(const MTPPhoto &data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *PeerData::currentUserpic(
|
QImage *PeerData::userpicCloudImage(Ui::PeerUserpicView &view) const {
|
||||||
std::shared_ptr<Data::CloudImageView> &view) const {
|
if (!_userpic.isCurrentView(view.cloud)) {
|
||||||
if (!_userpic.isCurrentView(view)) {
|
if (!_userpic.empty()) {
|
||||||
view = _userpic.createView();
|
view.cloud = _userpic.createView();
|
||||||
_userpic.load(&session(), userpicOrigin());
|
_userpic.load(&session(), userpicOrigin());
|
||||||
|
} else {
|
||||||
|
view.cloud = nullptr;
|
||||||
|
if (view.empty.null()) {
|
||||||
|
view.paletteVersion = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const auto image = view ? view->image() : nullptr;
|
if (const auto image = view.cloud.get(); image && !image->isNull()) {
|
||||||
if (image) {
|
|
||||||
_userpicEmpty = nullptr;
|
_userpicEmpty = nullptr;
|
||||||
|
return image;
|
||||||
} else if (isNotificationsUser()) {
|
} else if (isNotificationsUser()) {
|
||||||
static auto result = Image(
|
static auto result = Window::LogoNoMargin().scaledToWidth(
|
||||||
Window::LogoNoMargin().scaledToWidth(
|
kUserpicSize,
|
||||||
kUserpicSize,
|
Qt::SmoothTransformation);
|
||||||
Qt::SmoothTransformation));
|
|
||||||
return &result;
|
return &result;
|
||||||
}
|
}
|
||||||
return image;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerData::paintUserpic(
|
void PeerData::paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int size) const {
|
int size) const {
|
||||||
if (const auto userpic = currentUserpic(view)) {
|
const auto cloud = userpicCloudImage(view);
|
||||||
const auto rounding = isForum()
|
const auto ratio = style::DevicePixelRatio();
|
||||||
? Images::Option::RoundLarge
|
Ui::ValidateUserpicCache(
|
||||||
: Images::Option::RoundCircle;
|
view,
|
||||||
p.drawPixmap(
|
cloud,
|
||||||
x,
|
cloud ? nullptr : ensureEmptyUserpic().get(),
|
||||||
y,
|
size * ratio,
|
||||||
userpic->pix(size, size, { .options = rounding }));
|
isForum());
|
||||||
} else if (isForum()) {
|
p.drawImage(QRect(x, y, size, size), view.cached);
|
||||||
ensureEmptyUserpic()->paintRounded(
|
|
||||||
p,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
x + size + x,
|
|
||||||
size,
|
|
||||||
st::roundRadiusLarge);
|
|
||||||
} else{
|
|
||||||
ensureEmptyUserpic()->paint(p, x, y, x + size + x, size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerData::loadUserpic() {
|
void PeerData::loadUserpic() {
|
||||||
|
@ -319,112 +318,76 @@ bool PeerData::hasUserpic() const {
|
||||||
return !_userpic.empty();
|
return !_userpic.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Data::CloudImageView> PeerData::activeUserpicView() {
|
Ui::PeerUserpicView PeerData::activeUserpicView() {
|
||||||
return _userpic.empty() ? nullptr : _userpic.activeView();
|
return { .cloud = _userpic.empty() ? nullptr : _userpic.activeView() };
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Data::CloudImageView> PeerData::createUserpicView() {
|
Ui::PeerUserpicView PeerData::createUserpicView() {
|
||||||
if (_userpic.empty()) {
|
if (_userpic.empty()) {
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
auto result = _userpic.createView();
|
auto result = _userpic.createView();
|
||||||
_userpic.load(&session(), userpicPhotoOrigin());
|
_userpic.load(&session(), userpicPhotoOrigin());
|
||||||
return result;
|
return { .cloud = result };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerData::useEmptyUserpic(
|
bool PeerData::useEmptyUserpic(Ui::PeerUserpicView &view) const {
|
||||||
std::shared_ptr<Data::CloudImageView> &view) const {
|
return !userpicCloudImage(view);
|
||||||
return !currentUserpic(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InMemoryKey PeerData::userpicUniqueKey(
|
InMemoryKey PeerData::userpicUniqueKey(Ui::PeerUserpicView &view) const {
|
||||||
std::shared_ptr<Data::CloudImageView> &view) const {
|
|
||||||
return useEmptyUserpic(view)
|
return useEmptyUserpic(view)
|
||||||
? ensureEmptyUserpic()->uniqueKey()
|
? ensureEmptyUserpic()->uniqueKey()
|
||||||
: inMemoryKey(_userpic.location());
|
: inMemoryKey(_userpic.location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerData::saveUserpic(
|
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
|
||||||
const QString &path,
|
|
||||||
int size) const {
|
|
||||||
generateUserpicImage(view, size * cIntRetinaFactor()).save(path, "PNG");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeerData::saveUserpicRounded(
|
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
|
||||||
const QString &path,
|
|
||||||
int size) const {
|
|
||||||
generateUserpicImage(
|
|
||||||
view,
|
|
||||||
size * cIntRetinaFactor(),
|
|
||||||
ImageRoundRadius::Small).save(path, "PNG");
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap PeerData::genUserpic(
|
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
|
||||||
int size) const {
|
|
||||||
if (const auto userpic = currentUserpic(view)) {
|
|
||||||
const auto rounding = isForum()
|
|
||||||
? Images::Option::RoundLarge
|
|
||||||
: Images::Option::RoundCircle;
|
|
||||||
return userpic->pix(size, size, { .options = rounding });
|
|
||||||
}
|
|
||||||
const auto ratio = style::DevicePixelRatio();
|
|
||||||
auto result = QImage(
|
|
||||||
QSize(size, size) * ratio,
|
|
||||||
QImage::Format_ARGB32_Premultiplied);
|
|
||||||
result.setDevicePixelRatio(ratio);
|
|
||||||
result.fill(Qt::transparent);
|
|
||||||
{
|
|
||||||
Painter p(&result);
|
|
||||||
paintUserpic(p, view, 0, 0, size);
|
|
||||||
}
|
|
||||||
return Ui::PixmapFromImage(std::move(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage PeerData::generateUserpicImage(
|
QImage PeerData::generateUserpicImage(
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
int size) const {
|
|
||||||
return generateUserpicImage(
|
|
||||||
view,
|
|
||||||
size,
|
|
||||||
isForum() ? ImageRoundRadius::Large : ImageRoundRadius::Ellipse);
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage PeerData::generateUserpicImage(
|
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
|
||||||
int size,
|
int size,
|
||||||
ImageRoundRadius radius) const {
|
std::optional<int> radius) const {
|
||||||
if (const auto userpic = currentUserpic(view)) {
|
if (const auto userpic = userpicCloudImage(view)) {
|
||||||
const auto options = (radius == ImageRoundRadius::Ellipse)
|
auto image = userpic->scaled(
|
||||||
? Images::Option::RoundCircle
|
|
||||||
: (radius == ImageRoundRadius::Large)
|
|
||||||
? Images::Option::RoundLarge
|
|
||||||
: (radius == ImageRoundRadius::Small)
|
|
||||||
? Images::Option::RoundSmall
|
|
||||||
: Images::Option();
|
|
||||||
return userpic->pixNoCache(
|
|
||||||
{ size, size },
|
{ size, size },
|
||||||
{ .options = options }).toImage();
|
Qt::IgnoreAspectRatio,
|
||||||
|
Qt::SmoothTransformation);
|
||||||
|
const auto round = [&](int radius) {
|
||||||
|
return Images::Round(
|
||||||
|
std::move(image),
|
||||||
|
Images::CornersMask(radius));
|
||||||
|
};
|
||||||
|
if (radius == 0) {
|
||||||
|
return image;
|
||||||
|
} else if (radius) {
|
||||||
|
return round(*radius);
|
||||||
|
} else if (isForum()) {
|
||||||
|
return round(size * Ui::ForumUserpicRadiusMultiplier());
|
||||||
|
} else {
|
||||||
|
return Images::Circle(std::move(image));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto result = QImage(
|
auto result = QImage(
|
||||||
QSize(size, size),
|
QSize(size, size),
|
||||||
QImage::Format_ARGB32_Premultiplied);
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
result.fill(Qt::transparent);
|
result.fill(Qt::transparent);
|
||||||
{
|
|
||||||
Painter p(&result);
|
Painter p(&result);
|
||||||
if (radius == ImageRoundRadius::Ellipse) {
|
if (radius == 0) {
|
||||||
ensureEmptyUserpic()->paint(p, 0, 0, size, size);
|
ensureEmptyUserpic()->paintSquare(p, 0, 0, size, size);
|
||||||
} else if (radius == ImageRoundRadius::None) {
|
} else if (radius) {
|
||||||
ensureEmptyUserpic()->paintSquare(p, 0, 0, size, size);
|
ensureEmptyUserpic()->paintRounded(p, 0, 0, size, size, *radius);
|
||||||
} else if (radius == ImageRoundRadius::Large) {
|
} else if (isForum()) {
|
||||||
const auto radius = st::roundRadiusLarge;
|
ensureEmptyUserpic()->paintRounded(
|
||||||
ensureEmptyUserpic()->paintRounded(p, 0, 0, size, size, radius);
|
p,
|
||||||
} else {
|
0,
|
||||||
ensureEmptyUserpic()->paintRounded(p, 0, 0, size, size);
|
0,
|
||||||
}
|
size,
|
||||||
|
size,
|
||||||
|
size * Ui::ForumUserpicRadiusMultiplier());
|
||||||
|
} else {
|
||||||
|
ensureEmptyUserpic()->paintCircle(p, 0, 0, size, size);
|
||||||
}
|
}
|
||||||
|
p.end();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_flags.h"
|
#include "data/data_flags.h"
|
||||||
#include "data/notify/data_peer_notify_settings.h"
|
#include "data/notify/data_peer_notify_settings.h"
|
||||||
#include "data/data_cloud_file.h"
|
#include "data/data_cloud_file.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
|
|
||||||
struct BotInfo;
|
struct BotInfo;
|
||||||
class PeerData;
|
class PeerData;
|
||||||
|
@ -36,13 +37,12 @@ class Forum;
|
||||||
class ForumTopic;
|
class ForumTopic;
|
||||||
class Session;
|
class Session;
|
||||||
class GroupCall;
|
class GroupCall;
|
||||||
class CloudImageView;
|
|
||||||
struct ReactionId;
|
struct ReactionId;
|
||||||
|
|
||||||
int PeerColorIndex(PeerId peerId);
|
[[nodiscard]] int PeerColorIndex(PeerId peerId);
|
||||||
|
|
||||||
// Must be used only for PeerColor-s.
|
// Must be used only for PeerColor-s.
|
||||||
PeerId FakePeerIdForJustName(const QString &name);
|
[[nodiscard]] PeerId FakePeerIdForJustName(const QString &name);
|
||||||
|
|
||||||
class RestrictionCheckResult {
|
class RestrictionCheckResult {
|
||||||
public:
|
public:
|
||||||
|
@ -264,13 +264,13 @@ public:
|
||||||
void setUserpicPhoto(const MTPPhoto &data);
|
void setUserpicPhoto(const MTPPhoto &data);
|
||||||
void paintUserpic(
|
void paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int size) const;
|
int size) const;
|
||||||
void paintUserpicLeft(
|
void paintUserpicLeft(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int w,
|
int w,
|
||||||
|
@ -279,30 +279,14 @@ public:
|
||||||
}
|
}
|
||||||
void loadUserpic();
|
void loadUserpic();
|
||||||
[[nodiscard]] bool hasUserpic() const;
|
[[nodiscard]] bool hasUserpic() const;
|
||||||
[[nodiscard]] std::shared_ptr<Data::CloudImageView> activeUserpicView();
|
[[nodiscard]] Ui::PeerUserpicView activeUserpicView();
|
||||||
[[nodiscard]] std::shared_ptr<Data::CloudImageView> createUserpicView();
|
[[nodiscard]] Ui::PeerUserpicView createUserpicView();
|
||||||
[[nodiscard]] bool useEmptyUserpic(
|
[[nodiscard]] bool useEmptyUserpic(Ui::PeerUserpicView &view) const;
|
||||||
std::shared_ptr<Data::CloudImageView> &view) const;
|
[[nodiscard]] InMemoryKey userpicUniqueKey(Ui::PeerUserpicView &view) const;
|
||||||
[[nodiscard]] InMemoryKey userpicUniqueKey(
|
|
||||||
std::shared_ptr<Data::CloudImageView> &view) const;
|
|
||||||
void saveUserpic(
|
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
|
||||||
const QString &path,
|
|
||||||
int size) const;
|
|
||||||
void saveUserpicRounded(
|
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
|
||||||
const QString &path,
|
|
||||||
int size) const;
|
|
||||||
[[nodiscard]] QPixmap genUserpic(
|
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
|
||||||
int size) const;
|
|
||||||
[[nodiscard]] QImage generateUserpicImage(
|
[[nodiscard]] QImage generateUserpicImage(
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
int size) const;
|
|
||||||
[[nodiscard]] QImage generateUserpicImage(
|
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
|
||||||
int size,
|
int size,
|
||||||
ImageRoundRadius radius) const;
|
std::optional<int> radius = {}) const;
|
||||||
[[nodiscard]] ImageLocation userpicLocation() const {
|
[[nodiscard]] ImageLocation userpicLocation() const {
|
||||||
return _userpic.location();
|
return _userpic.location();
|
||||||
}
|
}
|
||||||
|
@ -332,8 +316,7 @@ public:
|
||||||
return _openLink;
|
return _openLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Image *currentUserpic(
|
[[nodiscard]] QImage *userpicCloudImage(Ui::PeerUserpicView &view) const;
|
||||||
std::shared_ptr<Data::CloudImageView> &view) const;
|
|
||||||
|
|
||||||
[[nodiscard]] bool canPinMessages() const;
|
[[nodiscard]] bool canPinMessages() const;
|
||||||
[[nodiscard]] bool canEditMessagesIndefinitely() const;
|
[[nodiscard]] bool canEditMessagesIndefinitely() const;
|
||||||
|
@ -423,6 +406,7 @@ protected:
|
||||||
const QString &newUsername);
|
const QString &newUsername);
|
||||||
void updateUserpic(PhotoId photoId, MTP::DcId dcId, bool hasVideo);
|
void updateUserpic(PhotoId photoId, MTP::DcId dcId, bool hasVideo);
|
||||||
void clearUserpic();
|
void clearUserpic();
|
||||||
|
void invalidateEmptyUserpic();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void fillNames();
|
void fillNames();
|
||||||
|
|
|
@ -515,17 +515,10 @@ bool ChannelHasActiveCall(not_null<ChannelData*> channel) {
|
||||||
rpl::producer<QImage> PeerUserpicImageValue(
|
rpl::producer<QImage> PeerUserpicImageValue(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
int size) {
|
int size) {
|
||||||
return PeerUserpicImageValue(peer, size, ImageRoundRadius::Ellipse);
|
|
||||||
}
|
|
||||||
|
|
||||||
rpl::producer<QImage> PeerUserpicImageValue(
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
int size,
|
|
||||||
ImageRoundRadius radius) {
|
|
||||||
return [=](auto consumer) {
|
return [=](auto consumer) {
|
||||||
auto result = rpl::lifetime();
|
auto result = rpl::lifetime();
|
||||||
struct State {
|
struct State {
|
||||||
std::shared_ptr<CloudImageView> view;
|
Ui::PeerUserpicView view;
|
||||||
rpl::lifetime waiting;
|
rpl::lifetime waiting;
|
||||||
InMemoryKey key = {};
|
InMemoryKey key = {};
|
||||||
bool empty = true;
|
bool empty = true;
|
||||||
|
@ -534,7 +527,7 @@ rpl::producer<QImage> PeerUserpicImageValue(
|
||||||
const auto state = result.make_state<State>();
|
const auto state = result.make_state<State>();
|
||||||
state->push = [=] {
|
state->push = [=] {
|
||||||
const auto key = peer->userpicUniqueKey(state->view);
|
const auto key = peer->userpicUniqueKey(state->view);
|
||||||
const auto loading = state->view && !state->view->image();
|
const auto loading = Ui::PeerUserpicLoading(state->view);
|
||||||
|
|
||||||
if (loading && !state->waiting) {
|
if (loading && !state->waiting) {
|
||||||
peer->session().downloaderTaskFinished(
|
peer->session().downloaderTaskFinished(
|
||||||
|
@ -548,8 +541,7 @@ rpl::producer<QImage> PeerUserpicImageValue(
|
||||||
}
|
}
|
||||||
state->key = key;
|
state->key = key;
|
||||||
state->empty = false;
|
state->empty = false;
|
||||||
consumer.put_next(
|
consumer.put_next(peer->generateUserpicImage(state->view, size));
|
||||||
peer->generateUserpicImage(state->view, size, radius));
|
|
||||||
};
|
};
|
||||||
peer->session().changes().peerFlagsValue(
|
peer->session().changes().peerFlagsValue(
|
||||||
peer,
|
peer,
|
||||||
|
|
|
@ -134,10 +134,6 @@ inline auto PeerFullFlagValue(
|
||||||
[[nodiscard]] rpl::producer<QImage> PeerUserpicImageValue(
|
[[nodiscard]] rpl::producer<QImage> PeerUserpicImageValue(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
int size);
|
int size);
|
||||||
[[nodiscard]] rpl::producer<QImage> PeerUserpicImageValue(
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
int size,
|
|
||||||
ImageRoundRadius radius);
|
|
||||||
|
|
||||||
[[nodiscard]] const AllowedReactions &PeerAllowedReactions(
|
[[nodiscard]] const AllowedReactions &PeerAllowedReactions(
|
||||||
not_null<PeerData*> peer);
|
not_null<PeerData*> peer);
|
||||||
|
|
|
@ -228,22 +228,27 @@ void UserData::setAccessHash(uint64 accessHash) {
|
||||||
if (accessHash == kInaccessibleAccessHashOld) {
|
if (accessHash == kInaccessibleAccessHashOld) {
|
||||||
_accessHash = 0;
|
_accessHash = 0;
|
||||||
_flags.add(Flag::Deleted);
|
_flags.add(Flag::Deleted);
|
||||||
|
invalidateEmptyUserpic();
|
||||||
} else {
|
} else {
|
||||||
_accessHash = accessHash;
|
_accessHash = accessHash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserData::setFlags(UserDataFlags which) {
|
void UserData::setFlags(UserDataFlags which) {
|
||||||
|
if ((which & UserDataFlag::Deleted)
|
||||||
|
!= (flags() & UserDataFlag::Deleted)) {
|
||||||
|
invalidateEmptyUserpic();
|
||||||
|
}
|
||||||
_flags.set((flags() & UserDataFlag::Self)
|
_flags.set((flags() & UserDataFlag::Self)
|
||||||
| (which & ~UserDataFlag::Self));
|
| (which & ~UserDataFlag::Self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserData::addFlags(UserDataFlags which) {
|
void UserData::addFlags(UserDataFlags which) {
|
||||||
_flags.add(which & ~UserDataFlag::Self);
|
setFlags(flags() | which);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserData::removeFlags(UserDataFlags which) {
|
void UserData::removeFlags(UserDataFlags which) {
|
||||||
_flags.remove(which & ~UserDataFlag::Self);
|
setFlags(flags() & ~which);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserData::isVerified() const {
|
bool UserData::isVerified() const {
|
||||||
|
|
|
@ -25,10 +25,10 @@ class Session;
|
||||||
class Forum;
|
class Forum;
|
||||||
class Folder;
|
class Folder;
|
||||||
class ForumTopic;
|
class ForumTopic;
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
struct PeerUserpicView;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Dialogs::Ui {
|
namespace Dialogs::Ui {
|
||||||
|
@ -233,7 +233,7 @@ public:
|
||||||
virtual void loadUserpic() = 0;
|
virtual void loadUserpic() = 0;
|
||||||
virtual void paintUserpic(
|
virtual void paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
const Ui::PaintContext &context) const = 0;
|
const Ui::PaintContext &context) const = 0;
|
||||||
|
|
||||||
[[nodiscard]] TimeId chatListTimeId() const {
|
[[nodiscard]] TimeId chatListTimeId() const {
|
||||||
|
|
|
@ -1134,7 +1134,7 @@ void InnerWidget::paintSearchInFilter(
|
||||||
void InnerWidget::paintSearchInPeer(
|
void InnerWidget::paintSearchInPeer(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpic,
|
Ui::PeerUserpicView &userpic,
|
||||||
int top,
|
int top,
|
||||||
const Ui::Text::String &text) const {
|
const Ui::Text::String &text) const {
|
||||||
const auto paintUserpic = [&](Painter &p, int x, int y, int size) {
|
const auto paintUserpic = [&](Painter &p, int x, int y, int size) {
|
||||||
|
@ -1168,7 +1168,7 @@ void InnerWidget::paintSearchInTopic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const Ui::PaintContext &context,
|
const Ui::PaintContext &context,
|
||||||
not_null<Data::ForumTopic*> topic,
|
not_null<Data::ForumTopic*> topic,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpic,
|
Ui::PeerUserpicView &userpic,
|
||||||
int top,
|
int top,
|
||||||
const Ui::Text::String &text) const {
|
const Ui::Text::String &text) const {
|
||||||
const auto paintUserpic = [&](Painter &p, int x, int y, int size) {
|
const auto paintUserpic = [&](Painter &p, int x, int y, int size) {
|
||||||
|
@ -2846,7 +2846,7 @@ void InnerWidget::searchInChat(Key key, PeerData *from) {
|
||||||
_searchFromUserUserpic = _searchFromPeer->createUserpicView();
|
_searchFromUserUserpic = _searchFromPeer->createUserpicView();
|
||||||
} else {
|
} else {
|
||||||
_cancelSearchFromUser->hide();
|
_cancelSearchFromUser->hide();
|
||||||
_searchFromUserUserpic = nullptr;
|
_searchFromUserUserpic = {};
|
||||||
}
|
}
|
||||||
if (_searchInChat || _searchFromPeer) {
|
if (_searchInChat || _searchFromPeer) {
|
||||||
refreshSearchInChatLabel();
|
refreshSearchInChatLabel();
|
||||||
|
@ -2855,7 +2855,7 @@ void InnerWidget::searchInChat(Key key, PeerData *from) {
|
||||||
if (const auto peer = _searchInChat.peer()) {
|
if (const auto peer = _searchInChat.peer()) {
|
||||||
_searchInChatUserpic = peer->createUserpicView();
|
_searchInChatUserpic = peer->createUserpicView();
|
||||||
} else {
|
} else {
|
||||||
_searchInChatUserpic = nullptr;
|
_searchInChatUserpic = {};
|
||||||
}
|
}
|
||||||
moveCancelSearchButtons();
|
moveCancelSearchButtons();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/dragging_scroll_manager.h"
|
#include "ui/dragging_scroll_manager.h"
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
#include "base/flags.h"
|
#include "base/flags.h"
|
||||||
#include "base/object_ptr.h"
|
#include "base/object_ptr.h"
|
||||||
|
|
||||||
|
@ -39,7 +40,6 @@ class SessionController;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class CloudImageView;
|
|
||||||
class Thread;
|
class Thread;
|
||||||
class Folder;
|
class Folder;
|
||||||
class Forum;
|
class Forum;
|
||||||
|
@ -340,7 +340,7 @@ private:
|
||||||
void paintSearchInPeer(
|
void paintSearchInPeer(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpic,
|
Ui::PeerUserpicView &userpic,
|
||||||
int top,
|
int top,
|
||||||
const Ui::Text::String &text) const;
|
const Ui::Text::String &text) const;
|
||||||
void paintSearchInSaved(
|
void paintSearchInSaved(
|
||||||
|
@ -355,7 +355,7 @@ private:
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const Ui::PaintContext &context,
|
const Ui::PaintContext &context,
|
||||||
not_null<Data::ForumTopic*> topic,
|
not_null<Data::ForumTopic*> topic,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpic,
|
Ui::PeerUserpicView &userpic,
|
||||||
int top,
|
int top,
|
||||||
const Ui::Text::String &text) const;
|
const Ui::Text::String &text) const;
|
||||||
template <typename PaintUserpic>
|
template <typename PaintUserpic>
|
||||||
|
@ -470,8 +470,8 @@ private:
|
||||||
Key _searchInChat;
|
Key _searchInChat;
|
||||||
History *_searchInMigrated = nullptr;
|
History *_searchInMigrated = nullptr;
|
||||||
PeerData *_searchFromPeer = nullptr;
|
PeerData *_searchFromPeer = nullptr;
|
||||||
mutable std::shared_ptr<Data::CloudImageView> _searchInChatUserpic;
|
mutable Ui::PeerUserpicView _searchInChatUserpic;
|
||||||
mutable std::shared_ptr<Data::CloudImageView> _searchFromUserUserpic;
|
mutable Ui::PeerUserpicView _searchFromUserUserpic;
|
||||||
Ui::Text::String _searchInChatText;
|
Ui::Text::String _searchInChatText;
|
||||||
Ui::Text::String _searchFromUserText;
|
Ui::Text::String _searchFromUserText;
|
||||||
RowDescriptor _menuRow;
|
RowDescriptor _menuRow;
|
||||||
|
|
|
@ -38,11 +38,11 @@ constexpr auto kNoneLayer = 0;
|
||||||
void PaintCornerBadgeTTLFrame(
|
void PaintCornerBadgeTTLFrame(
|
||||||
QPainter &q,
|
QPainter &q,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
float64 progress,
|
float64 progress,
|
||||||
int photoSize) {
|
int photoSize) {
|
||||||
const auto ttl = peer->messagesTTL();
|
const auto ttl = peer->messagesTTL();
|
||||||
if (!ttl || !view) {
|
if (!ttl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using Radius = ImageRoundRadius;
|
using Radius = ImageRoundRadius;
|
||||||
|
@ -54,7 +54,7 @@ void PaintCornerBadgeTTLFrame(
|
||||||
const auto ratio = style::DevicePixelRatio();
|
const auto ratio = style::DevicePixelRatio();
|
||||||
const auto fullSize = photoSize;
|
const auto fullSize = photoSize;
|
||||||
const auto blurredFull = Images::BlurLargeImage(
|
const auto blurredFull = Images::BlurLargeImage(
|
||||||
peer->generateUserpicImage(view, fullSize * ratio, Radius::None),
|
peer->generateUserpicImage(view, fullSize * ratio, 0),
|
||||||
kBlurRadius);
|
kBlurRadius);
|
||||||
const auto partRect = CornerBadgeTTLRect(fullSize);
|
const auto partRect = CornerBadgeTTLRect(fullSize);
|
||||||
const auto &partSize = partRect.width();
|
const auto &partSize = partRect.width();
|
||||||
|
@ -338,7 +338,7 @@ void Row::PaintCornerBadgeFrame(
|
||||||
not_null<CornerBadgeUserpic*> data,
|
not_null<CornerBadgeUserpic*> data,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Ui::VideoUserpic *videoUserpic,
|
Ui::VideoUserpic *videoUserpic,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
const Ui::PaintContext &context) {
|
const Ui::PaintContext &context) {
|
||||||
data->frame.fill(Qt::transparent);
|
data->frame.fill(Qt::transparent);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/text/text.h"
|
#include "ui/text/text.h"
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/unread_badge.h"
|
#include "ui/unread_badge.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
#include "dialogs/dialogs_key.h"
|
#include "dialogs/dialogs_key.h"
|
||||||
#include "dialogs/ui/dialogs_message_view.h"
|
#include "dialogs/ui/dialogs_message_view.h"
|
||||||
|
|
||||||
|
@ -20,10 +21,6 @@ namespace style {
|
||||||
struct DialogRow;
|
struct DialogRow;
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|
||||||
namespace Data {
|
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class RippleAnimation;
|
class RippleAnimation;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
@ -69,13 +66,12 @@ public:
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
const QColor *colorOverride = nullptr) const;
|
const QColor *colorOverride = nullptr) const;
|
||||||
|
|
||||||
[[nodiscard]] auto userpicView() const
|
[[nodiscard]] Ui::PeerUserpicView &userpicView() const {
|
||||||
-> std::shared_ptr<Data::CloudImageView> & {
|
|
||||||
return _userpic;
|
return _userpic;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable std::shared_ptr<Data::CloudImageView> _userpic;
|
mutable Ui::PeerUserpicView _userpic;
|
||||||
mutable std::unique_ptr<Ui::RippleAnimation> _ripple;
|
mutable std::unique_ptr<Ui::RippleAnimation> _ripple;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -182,7 +178,7 @@ private:
|
||||||
not_null<CornerBadgeUserpic*> data,
|
not_null<CornerBadgeUserpic*> data,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Ui::VideoUserpic *videoUserpic,
|
Ui::VideoUserpic *videoUserpic,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
const Ui::PaintContext &context);
|
const Ui::PaintContext &context);
|
||||||
|
|
||||||
Key _id;
|
Key _id;
|
||||||
|
|
|
@ -285,9 +285,9 @@ void PaintRow(
|
||||||
not_null<Entry*> entry,
|
not_null<Entry*> entry,
|
||||||
VideoUserpic *videoUserpic,
|
VideoUserpic *videoUserpic,
|
||||||
PeerData *from,
|
PeerData *from,
|
||||||
Ui::PeerBadge &fromBadge,
|
PeerBadge &fromBadge,
|
||||||
Fn<void()> customEmojiRepaint,
|
Fn<void()> customEmojiRepaint,
|
||||||
const Ui::Text::String &fromName,
|
const Text::String &fromName,
|
||||||
const HiddenSenderInfo *hiddenSenderInfo,
|
const HiddenSenderInfo *hiddenSenderInfo,
|
||||||
HistoryItem *item,
|
HistoryItem *item,
|
||||||
const Data::Draft *draft,
|
const Data::Draft *draft,
|
||||||
|
@ -306,8 +306,8 @@ void PaintRow(
|
||||||
: context.selected
|
: context.selected
|
||||||
? st::dialogsBgOver
|
? st::dialogsBgOver
|
||||||
: anim::brush(
|
: anim::brush(
|
||||||
st::dialogsBg,
|
st::dialogsBg,
|
||||||
st::dialogsBgOver,
|
st::dialogsBgOver,
|
||||||
context.childListShown);
|
context.childListShown);
|
||||||
p.fillRect(geometry, bg);
|
p.fillRect(geometry, bg);
|
||||||
if (!(flags & Flag::TopicJumpRipple)) {
|
if (!(flags & Flag::TopicJumpRipple)) {
|
||||||
|
@ -342,7 +342,7 @@ void PaintRow(
|
||||||
(flags & Flag::AllowUserOnline) ? history : nullptr,
|
(flags & Flag::AllowUserOnline) ? history : nullptr,
|
||||||
context);
|
context);
|
||||||
} else if (hiddenSenderInfo) {
|
} else if (hiddenSenderInfo) {
|
||||||
hiddenSenderInfo->emptyUserpic.paint(
|
hiddenSenderInfo->emptyUserpic.paintCircle(
|
||||||
p,
|
p,
|
||||||
context.st->padding.left(),
|
context.st->padding.left(),
|
||||||
context.st->padding.top(),
|
context.st->padding.top(),
|
||||||
|
|
|
@ -38,8 +38,8 @@ using namespace ::Ui;
|
||||||
class VideoUserpic;
|
class VideoUserpic;
|
||||||
|
|
||||||
struct TopicJumpCorners {
|
struct TopicJumpCorners {
|
||||||
Ui::CornersPixmaps normal;
|
CornersPixmaps normal;
|
||||||
Ui::CornersPixmaps inverted;
|
CornersPixmaps inverted;
|
||||||
QPixmap small;
|
QPixmap small;
|
||||||
int invertedRadius = 0;
|
int invertedRadius = 0;
|
||||||
int smallKey = 0; // = `-radius` if top right else `radius`.
|
int smallKey = 0; // = `-radius` if top right else `radius`.
|
||||||
|
|
|
@ -30,7 +30,7 @@ int VideoUserpic::frameIndex() const {
|
||||||
|
|
||||||
void VideoUserpic::paintLeft(
|
void VideoUserpic::paintLeft(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int w,
|
int w,
|
||||||
|
@ -133,7 +133,7 @@ void PaintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Ui::VideoUserpic *videoUserpic,
|
Ui::VideoUserpic *videoUserpic,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
|
|
|
@ -12,10 +12,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
class Painter;
|
class Painter;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class CloudImageView;
|
|
||||||
class PhotoMedia;
|
class PhotoMedia;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
struct PeerUserpicView;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Dialogs::Ui {
|
namespace Dialogs::Ui {
|
||||||
|
|
||||||
using namespace ::Ui;
|
using namespace ::Ui;
|
||||||
|
@ -29,7 +32,7 @@ public:
|
||||||
|
|
||||||
void paintLeft(
|
void paintLeft(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
PeerUserpicView &view,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int w,
|
int w,
|
||||||
|
@ -54,8 +57,8 @@ private:
|
||||||
void PaintUserpic(
|
void PaintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Ui::VideoUserpic *videoUserpic,
|
VideoUserpic *videoUserpic,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
PeerUserpicView &view,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "editor/editor_crop.h"
|
#include "editor/editor_crop.h"
|
||||||
|
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
#include "styles/style_editor.h"
|
#include "styles/style_editor.h"
|
||||||
#include "styles/style_basic.h"
|
#include "styles/style_basic.h"
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
|
@ -149,7 +150,7 @@ void Crop::setCropPaint(QRectF &&rect) {
|
||||||
_painterPath.addEllipse(_cropPaint);
|
_painterPath.addEllipse(_cropPaint);
|
||||||
} else if (_data.cropType == EditorData::CropType::RoundedRect) {
|
} else if (_data.cropType == EditorData::CropType::RoundedRect) {
|
||||||
const auto radius = std::min(_cropPaint.width(), _cropPaint.height())
|
const auto radius = std::min(_cropPaint.width(), _cropPaint.height())
|
||||||
* st::roundRadiusLarge / float64(st::defaultDialogRow.photoSize);
|
* Ui::ForumUserpicRadiusMultiplier();
|
||||||
_painterPath.addRoundedRect(_cropPaint, radius, radius);
|
_painterPath.addRoundedRect(_cropPaint, radius, radius);
|
||||||
} else {
|
} else {
|
||||||
_painterPath.addRect(_cropPaint);
|
_painterPath.addRect(_cropPaint);
|
||||||
|
|
|
@ -20,10 +20,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
namespace Data {
|
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
|
||||||
|
|
||||||
namespace AdminLog {
|
namespace AdminLog {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -64,7 +60,7 @@ private:
|
||||||
QRect _checkRect;
|
QRect _checkRect;
|
||||||
|
|
||||||
const not_null<UserData*> _user;
|
const not_null<UserData*> _user;
|
||||||
std::shared_ptr<Data::CloudImageView> _userpic;
|
Ui::PeerUserpicView _userpic;
|
||||||
Ui::Text::String _name;
|
Ui::Text::String _name;
|
||||||
QString _statusText;
|
QString _statusText;
|
||||||
bool _statusOnline = false;
|
bool _statusOnline = false;
|
||||||
|
|
|
@ -19,10 +19,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
struct ChatRestrictionsInfo;
|
struct ChatRestrictionsInfo;
|
||||||
|
|
||||||
namespace Data {
|
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
@ -38,6 +34,7 @@ enum class PointState : char;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class PopupMenu;
|
class PopupMenu;
|
||||||
class ChatStyle;
|
class ChatStyle;
|
||||||
|
struct PeerUserpicView;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
|
@ -278,9 +275,8 @@ private:
|
||||||
std::map<not_null<const HistoryItem*>, not_null<Element*>> _itemsByData;
|
std::map<not_null<const HistoryItem*>, not_null<Element*>> _itemsByData;
|
||||||
base::flat_map<not_null<const HistoryItem*>, TimeId> _itemDates;
|
base::flat_map<not_null<const HistoryItem*>, TimeId> _itemDates;
|
||||||
base::flat_set<FullMsgId> _animatedStickersPlayed;
|
base::flat_set<FullMsgId> _animatedStickersPlayed;
|
||||||
base::flat_map<
|
base::flat_map<not_null<PeerData*>, Ui::PeerUserpicView> _userpics;
|
||||||
not_null<PeerData*>,
|
base::flat_map<not_null<PeerData*>, Ui::PeerUserpicView> _userpicsCache;
|
||||||
std::shared_ptr<Data::CloudImageView>> _userpics, _userpicsCache;
|
|
||||||
int _itemsTop = 0;
|
int _itemsTop = 0;
|
||||||
int _itemsWidth = 0;
|
int _itemsWidth = 0;
|
||||||
int _itemsHeight = 0;
|
int _itemsHeight = 0;
|
||||||
|
|
|
@ -2262,7 +2262,7 @@ void History::loadUserpic() {
|
||||||
|
|
||||||
void History::paintUserpic(
|
void History::paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
const Dialogs::Ui::PaintContext &context) const {
|
const Dialogs::Ui::PaintContext &context) const {
|
||||||
peer->paintUserpic(
|
peer->paintUserpic(
|
||||||
p,
|
p,
|
||||||
|
|
|
@ -398,7 +398,7 @@ public:
|
||||||
void loadUserpic() override;
|
void loadUserpic() override;
|
||||||
void paintUserpic(
|
void paintUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
std::shared_ptr<Data::CloudImageView> &view,
|
Ui::PeerUserpicView &view,
|
||||||
const Dialogs::Ui::PaintContext &context) const override;
|
const Dialogs::Ui::PaintContext &context) const override;
|
||||||
|
|
||||||
void refreshChatListNameSortKey();
|
void refreshChatListNameSortKey();
|
||||||
|
|
|
@ -1135,7 +1135,8 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
// paint the userpic if it intersects the painted rect
|
// paint the userpic if it intersects the painted rect
|
||||||
if (userpicTop + st::msgPhotoSize > clip.top()) {
|
if (userpicTop + st::msgPhotoSize > clip.top()) {
|
||||||
if (const auto from = view->data()->displayFrom()) {
|
const auto item = view->data();
|
||||||
|
if (const auto from = item->displayFrom()) {
|
||||||
Dialogs::Ui::PaintUserpic(
|
Dialogs::Ui::PaintUserpic(
|
||||||
p,
|
p,
|
||||||
from,
|
from,
|
||||||
|
@ -1146,28 +1147,25 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||||
width(),
|
width(),
|
||||||
st::msgPhotoSize,
|
st::msgPhotoSize,
|
||||||
context.paused);
|
context.paused);
|
||||||
} else if (const auto info = view->data()->hiddenSenderInfo()) {
|
} else if (const auto info = item->hiddenSenderInfo()) {
|
||||||
if (info->customUserpic.empty()) {
|
if (info->customUserpic.empty()) {
|
||||||
info->emptyUserpic.paint(
|
info->emptyUserpic.paintCircle(
|
||||||
p,
|
p,
|
||||||
st::historyPhotoLeft,
|
st::historyPhotoLeft,
|
||||||
userpicTop,
|
userpicTop,
|
||||||
width(),
|
width(),
|
||||||
st::msgPhotoSize);
|
st::msgPhotoSize);
|
||||||
} else {
|
} else {
|
||||||
const auto painted = info->paintCustomUserpic(
|
auto &userpic = _hiddenSenderUserpics[item->id];
|
||||||
|
const auto valid = info->paintCustomUserpic(
|
||||||
p,
|
p,
|
||||||
|
userpic,
|
||||||
st::historyPhotoLeft,
|
st::historyPhotoLeft,
|
||||||
userpicTop,
|
userpicTop,
|
||||||
width(),
|
width(),
|
||||||
st::msgPhotoSize);
|
st::msgPhotoSize);
|
||||||
if (!painted) {
|
if (!valid) {
|
||||||
const auto itemId = view->data()->fullId();
|
info->customUserpic.load(&session(), item->fullId());
|
||||||
auto &v = _sponsoredUserpics[itemId.msg];
|
|
||||||
if (!info->customUserpic.isCurrentView(v)) {
|
|
||||||
v = info->customUserpic.createView();
|
|
||||||
info->customUserpic.load(&session(), itemId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,7 +20,6 @@ struct ClickHandlerContext;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
struct Group;
|
struct Group;
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
|
@ -51,6 +50,7 @@ class PopupMenu;
|
||||||
enum class ReportReason;
|
enum class ReportReason;
|
||||||
struct ChatPaintContext;
|
struct ChatPaintContext;
|
||||||
class PathShiftGradient;
|
class PathShiftGradient;
|
||||||
|
struct PeerUserpicView;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Dialogs::Ui {
|
namespace Dialogs::Ui {
|
||||||
|
@ -458,12 +458,9 @@ private:
|
||||||
bool _isChatWide = false;
|
bool _isChatWide = false;
|
||||||
|
|
||||||
base::flat_set<not_null<const HistoryItem*>> _animatedStickersPlayed;
|
base::flat_set<not_null<const HistoryItem*>> _animatedStickersPlayed;
|
||||||
base::flat_map<
|
base::flat_map<not_null<PeerData*>, Ui::PeerUserpicView> _userpics;
|
||||||
not_null<PeerData*>,
|
base::flat_map<not_null<PeerData*>, Ui::PeerUserpicView> _userpicsCache;
|
||||||
std::shared_ptr<Data::CloudImageView>> _userpics, _userpicsCache;
|
base::flat_map<MsgId, Ui::PeerUserpicView> _hiddenSenderUserpics;
|
||||||
base::flat_map<
|
|
||||||
MsgId,
|
|
||||||
std::shared_ptr<Data::CloudImageView>> _sponsoredUserpics;
|
|
||||||
base::flat_map<
|
base::flat_map<
|
||||||
not_null<PeerData*>,
|
not_null<PeerData*>,
|
||||||
std::unique_ptr<VideoUserpic>> _videoUserpics;
|
std::unique_ptr<VideoUserpic>> _videoUserpics;
|
||||||
|
|
|
@ -144,22 +144,31 @@ ClickHandlerPtr HiddenSenderInfo::ForwardClickHandler() {
|
||||||
|
|
||||||
bool HiddenSenderInfo::paintCustomUserpic(
|
bool HiddenSenderInfo::paintCustomUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
Ui::PeerUserpicView &view,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
int size) const {
|
int size) const {
|
||||||
const auto view = customUserpic.activeView();
|
Expects(!customUserpic.empty());
|
||||||
if (const auto image = view ? view->image() : nullptr) {
|
|
||||||
const auto circled = Images::Option::RoundCircle;
|
auto valid = true;
|
||||||
p.drawPixmap(
|
if (!customUserpic.isCurrentView(view.cloud)) {
|
||||||
x,
|
view.cloud = customUserpic.createView();
|
||||||
y,
|
valid = false;
|
||||||
image->pix(size, size, { .options = circled }));
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
emptyUserpic.paint(p, x, y, outerWidth, size);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
const auto image = *view.cloud;
|
||||||
|
if (image.isNull()) {
|
||||||
|
emptyUserpic.paintCircle(p, x, y, outerWidth, size);
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
Ui::ValidateUserpicCache(
|
||||||
|
view,
|
||||||
|
image.isNull() ? nullptr : &image,
|
||||||
|
image.isNull() ? &emptyUserpic : nullptr,
|
||||||
|
size * style::DevicePixelRatio(),
|
||||||
|
false);
|
||||||
|
p.drawImage(QRect(x, y, size, size), view.cached);
|
||||||
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessageForwarded::create(const HistoryMessageVia *via) const {
|
void HistoryMessageForwarded::create(const HistoryMessageVia *via) const {
|
||||||
|
|
|
@ -19,6 +19,7 @@ class VoiceSeekClickHandler;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
struct ChatPaintContext;
|
struct ChatPaintContext;
|
||||||
class ChatStyle;
|
class ChatStyle;
|
||||||
|
struct PeerUserpicView;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
@ -94,6 +95,7 @@ public:
|
||||||
[[nodiscard]] const Ui::Text::String &nameText() const;
|
[[nodiscard]] const Ui::Text::String &nameText() const;
|
||||||
[[nodiscard]] bool paintCustomUserpic(
|
[[nodiscard]] bool paintCustomUserpic(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
Ui::PeerUserpicView &view,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
|
|
|
@ -139,12 +139,12 @@ rpl::producer<Ui::GroupCallBarContent> GroupCallBarContentByCall(
|
||||||
state->someUserpicsNotLoaded = false;
|
state->someUserpicsNotLoaded = false;
|
||||||
for (auto &userpic : state->userpics) {
|
for (auto &userpic : state->userpics) {
|
||||||
userpic.peer->loadUserpic();
|
userpic.peer->loadUserpic();
|
||||||
const auto pic = userpic.peer->genUserpic(
|
auto image = userpic.peer->generateUserpicImage(
|
||||||
userpic.view,
|
userpic.view,
|
||||||
userpicSize);
|
userpicSize);
|
||||||
userpic.uniqueKey = userpic.peer->userpicUniqueKey(userpic.view);
|
userpic.uniqueKey = userpic.peer->userpicUniqueKey(userpic.view);
|
||||||
state->current.users.push_back({
|
state->current.users.push_back({
|
||||||
.userpic = pic.toImage(),
|
.userpic = std::move(image),
|
||||||
.userpicKey = userpic.uniqueKey,
|
.userpicKey = userpic.uniqueKey,
|
||||||
.id = userpic.peer->id.value,
|
.id = userpic.peer->id.value,
|
||||||
.speaking = userpic.speaking,
|
.speaking = userpic.speaking,
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
struct GroupCallBarContent;
|
struct GroupCallBarContent;
|
||||||
|
@ -15,7 +16,6 @@ struct GroupCallBarContent;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class GroupCall;
|
class GroupCall;
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
|
@ -27,7 +27,7 @@ namespace HistoryView {
|
||||||
struct UserpicInRow {
|
struct UserpicInRow {
|
||||||
not_null<PeerData*> peer;
|
not_null<PeerData*> peer;
|
||||||
bool speaking = false;
|
bool speaking = false;
|
||||||
mutable std::shared_ptr<Data::CloudImageView> view;
|
mutable Ui::PeerUserpicView view;
|
||||||
mutable InMemoryKey uniqueKey;
|
mutable InMemoryKey uniqueKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2132,7 +2132,8 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
// paint the userpic if it intersects the painted rect
|
// paint the userpic if it intersects the painted rect
|
||||||
if (userpicTop + st::msgPhotoSize > clip.top()) {
|
if (userpicTop + st::msgPhotoSize > clip.top()) {
|
||||||
if (const auto from = view->data()->displayFrom()) {
|
const auto item = view->data();
|
||||||
|
if (const auto from = item->displayFrom()) {
|
||||||
from->paintUserpicLeft(
|
from->paintUserpicLeft(
|
||||||
p,
|
p,
|
||||||
_userpics[from],
|
_userpics[from],
|
||||||
|
@ -2140,28 +2141,25 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
||||||
userpicTop,
|
userpicTop,
|
||||||
view->width(),
|
view->width(),
|
||||||
st::msgPhotoSize);
|
st::msgPhotoSize);
|
||||||
} else if (const auto info = view->data()->hiddenSenderInfo()) {
|
} else if (const auto info = item->hiddenSenderInfo()) {
|
||||||
if (info->customUserpic.empty()) {
|
if (info->customUserpic.empty()) {
|
||||||
info->emptyUserpic.paint(
|
info->emptyUserpic.paintCircle(
|
||||||
p,
|
p,
|
||||||
st::historyPhotoLeft,
|
st::historyPhotoLeft,
|
||||||
userpicTop,
|
userpicTop,
|
||||||
view->width(),
|
view->width(),
|
||||||
st::msgPhotoSize);
|
st::msgPhotoSize);
|
||||||
} else {
|
} else {
|
||||||
const auto painted = info->paintCustomUserpic(
|
auto &userpic = _hiddenSenderUserpics[item->id];
|
||||||
|
const auto valid = info->paintCustomUserpic(
|
||||||
p,
|
p,
|
||||||
|
userpic,
|
||||||
st::historyPhotoLeft,
|
st::historyPhotoLeft,
|
||||||
userpicTop,
|
userpicTop,
|
||||||
view->width(),
|
view->width(),
|
||||||
st::msgPhotoSize);
|
st::msgPhotoSize);
|
||||||
if (!painted) {
|
if (!valid) {
|
||||||
const auto itemId = view->data()->fullId();
|
info->customUserpic.load(session, item->fullId());
|
||||||
auto &v = _sponsoredUserpics[itemId.msg];
|
|
||||||
if (!info->customUserpic.isCurrentView(v)) {
|
|
||||||
v = info->customUserpic.createView();
|
|
||||||
info->customUserpic.load(session, itemId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -29,6 +29,7 @@ class PopupMenu;
|
||||||
class ChatTheme;
|
class ChatTheme;
|
||||||
struct ChatPaintContext;
|
struct ChatPaintContext;
|
||||||
enum class TouchScrollState;
|
enum class TouchScrollState;
|
||||||
|
struct PeerUserpicView;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
|
@ -37,7 +38,6 @@ class SessionController;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
struct Group;
|
struct Group;
|
||||||
class CloudImageView;
|
|
||||||
struct Reaction;
|
struct Reaction;
|
||||||
struct AllowedReactions;
|
struct AllowedReactions;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
@ -637,12 +637,9 @@ private:
|
||||||
ItemRevealAnimation> _itemRevealAnimations;
|
ItemRevealAnimation> _itemRevealAnimations;
|
||||||
int _itemsRevealHeight = 0;
|
int _itemsRevealHeight = 0;
|
||||||
base::flat_set<FullMsgId> _animatedStickersPlayed;
|
base::flat_set<FullMsgId> _animatedStickersPlayed;
|
||||||
base::flat_map<
|
base::flat_map<not_null<PeerData*>, Ui::PeerUserpicView> _userpics;
|
||||||
not_null<PeerData*>,
|
base::flat_map<not_null<PeerData*>, Ui::PeerUserpicView> _userpicsCache;
|
||||||
std::shared_ptr<Data::CloudImageView>> _userpics, _userpicsCache;
|
base::flat_map<MsgId, Ui::PeerUserpicView> _hiddenSenderUserpics;
|
||||||
base::flat_map<
|
|
||||||
MsgId,
|
|
||||||
std::shared_ptr<Data::CloudImageView>> _sponsoredUserpics;
|
|
||||||
|
|
||||||
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
|
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
|
||||||
|
|
||||||
|
|
|
@ -1105,10 +1105,10 @@ void Message::paintCommentsButton(
|
||||||
auto &entry = list[i];
|
auto &entry = list[i];
|
||||||
const auto peer = entry.peer;
|
const auto peer = entry.peer;
|
||||||
auto &view = entry.view;
|
auto &view = entry.view;
|
||||||
const auto wasView = view.get();
|
const auto wasView = view.cloud.get();
|
||||||
if (views->recentRepliers[i] != peer->id
|
if (views->recentRepliers[i] != peer->id
|
||||||
|| peer->userpicUniqueKey(view) != entry.uniqueKey
|
|| peer->userpicUniqueKey(view) != entry.uniqueKey
|
||||||
|| view.get() != wasView) {
|
|| view.cloud.get() != wasView) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,12 +86,12 @@ rpl::producer<Ui::RequestsBarContent> RequestsBarContentByPeer(
|
||||||
state->someUserpicsNotLoaded = false;
|
state->someUserpicsNotLoaded = false;
|
||||||
for (auto &userpic : state->userpics) {
|
for (auto &userpic : state->userpics) {
|
||||||
userpic.peer->loadUserpic();
|
userpic.peer->loadUserpic();
|
||||||
const auto pic = userpic.peer->genUserpic(
|
auto image = userpic.peer->generateUserpicImage(
|
||||||
userpic.view,
|
userpic.view,
|
||||||
userpicSize);
|
userpicSize);
|
||||||
userpic.uniqueKey = userpic.peer->userpicUniqueKey(userpic.view);
|
userpic.uniqueKey = userpic.peer->userpicUniqueKey(userpic.view);
|
||||||
state->current.users.push_back({
|
state->current.users.push_back({
|
||||||
.userpic = pic.toImage(),
|
.userpic = std::move(image),
|
||||||
.userpicKey = userpic.uniqueKey,
|
.userpicKey = userpic.uniqueKey,
|
||||||
.id = userpic.peer->id.value,
|
.id = userpic.peer->id.value,
|
||||||
});
|
});
|
||||||
|
|
|
@ -96,8 +96,8 @@ Contact::Contact(
|
||||||
|
|
||||||
Contact::~Contact() {
|
Contact::~Contact() {
|
||||||
history()->owner().unregisterContactView(_userId, _parent);
|
history()->owner().unregisterContactView(_userId, _parent);
|
||||||
if (_userpic) {
|
if (!_userpic.null()) {
|
||||||
_userpic = nullptr;
|
_userpic = {};
|
||||||
_parent->checkHeavyPart();
|
_parent->checkHeavyPart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,13 +177,13 @@ void Contact::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (_userId) {
|
if (_userId) {
|
||||||
QRect rthumb(style::rtlrect(st.padding.left(), st.padding.top() - topMinus, st.thumbSize, st.thumbSize, paintw));
|
QRect rthumb(style::rtlrect(st.padding.left(), st.padding.top() - topMinus, st.thumbSize, st.thumbSize, paintw));
|
||||||
if (_contact) {
|
if (_contact) {
|
||||||
const auto was = (_userpic != nullptr);
|
const auto was = !_userpic.null();
|
||||||
_contact->paintUserpic(p, _userpic, rthumb.x(), rthumb.y(), st.thumbSize);
|
_contact->paintUserpic(p, _userpic, rthumb.x(), rthumb.y(), st.thumbSize);
|
||||||
if (!was && _userpic) {
|
if (!was && !_userpic.null()) {
|
||||||
history()->owner().registerHeavyViewPart(_parent);
|
history()->owner().registerHeavyViewPart(_parent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_photoEmpty->paint(p, st.padding.left(), st.padding.top() - topMinus, paintw, st.thumbSize);
|
_photoEmpty->paintCircle(p, st.padding.left(), st.padding.top() - topMinus, paintw, st.thumbSize);
|
||||||
}
|
}
|
||||||
if (context.selected()) {
|
if (context.selected()) {
|
||||||
PainterHighQualityEnabler hq(p);
|
PainterHighQualityEnabler hq(p);
|
||||||
|
@ -197,7 +197,7 @@ void Contact::draw(Painter &p, const PaintContext &context) const {
|
||||||
p.setPen(stm->msgFileThumbLinkFg);
|
p.setPen(stm->msgFileThumbLinkFg);
|
||||||
p.drawTextLeft(nameleft, linktop, paintw, _link, _linkw);
|
p.drawTextLeft(nameleft, linktop, paintw, _link, _linkw);
|
||||||
} else {
|
} else {
|
||||||
_photoEmpty->paint(p, st.padding.left(), st.padding.top() - topMinus, paintw, st.thumbSize);
|
_photoEmpty->paintCircle(p, st.padding.left(), st.padding.top() - topMinus, paintw, st.thumbSize);
|
||||||
}
|
}
|
||||||
const auto namewidth = paintw - nameleft - nameright;
|
const auto namewidth = paintw - nameleft - nameright;
|
||||||
|
|
||||||
|
@ -232,11 +232,11 @@ TextState Contact::textState(QPoint point, StateRequest request) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Contact::unloadHeavyPart() {
|
void Contact::unloadHeavyPart() {
|
||||||
_userpic = nullptr;
|
_userpic = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Contact::hasHeavyPart() const {
|
bool Contact::hasHeavyPart() const {
|
||||||
return (_userpic != nullptr);
|
return !_userpic.null();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -8,10 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "history/view/media/history_view_media.h"
|
#include "history/view/media/history_view_media.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
namespace Data {
|
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class EmptyUserpic;
|
class EmptyUserpic;
|
||||||
|
@ -72,7 +69,7 @@ private:
|
||||||
QString _fname, _lname, _phone;
|
QString _fname, _lname, _phone;
|
||||||
Ui::Text::String _name;
|
Ui::Text::String _name;
|
||||||
std::unique_ptr<Ui::EmptyUserpic> _photoEmpty;
|
std::unique_ptr<Ui::EmptyUserpic> _photoEmpty;
|
||||||
mutable std::shared_ptr<Data::CloudImageView> _userpic;
|
mutable Ui::PeerUserpicView _userpic;
|
||||||
|
|
||||||
ClickHandlerPtr _linkl;
|
ClickHandlerPtr _linkl;
|
||||||
int _linkw = 0;
|
int _linkw = 0;
|
||||||
|
|
|
@ -245,17 +245,16 @@ void Location::draw(Painter &p, const PaintContext &context) const {
|
||||||
void Location::validateImageCache(
|
void Location::validateImageCache(
|
||||||
QSize outer,
|
QSize outer,
|
||||||
Ui::BubbleRounding rounding) const {
|
Ui::BubbleRounding rounding) const {
|
||||||
|
Expects(_media != nullptr);
|
||||||
|
|
||||||
const auto ratio = style::DevicePixelRatio();
|
const auto ratio = style::DevicePixelRatio();
|
||||||
if (_imageCache.size() == (outer * ratio)
|
if (_imageCache.size() == (outer * ratio)
|
||||||
&& _imageCacheRounding == rounding) {
|
&& _imageCacheRounding == rounding
|
||||||
return;
|
|| _media->isNull()) {
|
||||||
}
|
|
||||||
const auto thumbnail = _media->image();
|
|
||||||
if (!thumbnail) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_imageCache = Images::Round(
|
_imageCache = Images::Round(
|
||||||
thumbnail->original().scaled(
|
_media->scaled(
|
||||||
outer * ratio,
|
outer * ratio,
|
||||||
Qt::IgnoreAspectRatio,
|
Qt::IgnoreAspectRatio,
|
||||||
Qt::SmoothTransformation),
|
Qt::SmoothTransformation),
|
||||||
|
|
|
@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class CloudImage;
|
class CloudImage;
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
|
@ -81,7 +80,7 @@ private:
|
||||||
[[nodiscard]] int fullHeight() const;
|
[[nodiscard]] int fullHeight() const;
|
||||||
|
|
||||||
const not_null<Data::CloudImage*> _data;
|
const not_null<Data::CloudImage*> _data;
|
||||||
mutable std::shared_ptr<Data::CloudImageView> _media;
|
mutable std::shared_ptr<QImage> _media;
|
||||||
Ui::Text::String _title, _description;
|
Ui::Text::String _title, _description;
|
||||||
ClickHandlerPtr _link;
|
ClickHandlerPtr _link;
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ struct Photo::Streamed {
|
||||||
::Media::Streaming::Instance instance;
|
::Media::Streaming::Instance instance;
|
||||||
::Media::Streaming::FrameRequest frozenRequest;
|
::Media::Streaming::FrameRequest frozenRequest;
|
||||||
QImage frozenFrame;
|
QImage frozenFrame;
|
||||||
|
std::array<QImage, 4> roundingCorners;
|
||||||
QImage roundingMask;
|
QImage roundingMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -352,22 +353,66 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Photo::validateUserpicImageCache(QSize size, bool forum) const {
|
||||||
|
const auto forumValue = forum ? 1 : 0;
|
||||||
|
const auto large = _dataMedia->image(PhotoSize::Large);
|
||||||
|
const auto ratio = style::DevicePixelRatio();
|
||||||
|
const auto blurredValue = large ? 0 : 1;
|
||||||
|
if (_imageCache.size() == (size * ratio)
|
||||||
|
&& _imageCacheForum == forumValue
|
||||||
|
&& _imageCacheBlurred == blurredValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto original = [&] {
|
||||||
|
if (large) {
|
||||||
|
return large->original();
|
||||||
|
} else if (const auto thumbnail = _dataMedia->image(
|
||||||
|
PhotoSize::Thumbnail)) {
|
||||||
|
return thumbnail->original();
|
||||||
|
} else if (const auto small = _dataMedia->image(
|
||||||
|
PhotoSize::Small)) {
|
||||||
|
return small->original();
|
||||||
|
} else if (const auto blurred = _dataMedia->thumbnailInline()) {
|
||||||
|
return blurred->original();
|
||||||
|
} else {
|
||||||
|
return Image::Empty()->original();
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
auto args = Images::PrepareArgs();
|
||||||
|
if (blurredValue) {
|
||||||
|
args = args.blurred();
|
||||||
|
}
|
||||||
|
original = Images::Prepare(std::move(original), size, args);
|
||||||
|
if (forumValue) {
|
||||||
|
original = Images::Round(
|
||||||
|
std::move(original),
|
||||||
|
Images::CornersMask(std::min(size.width(), size.height())
|
||||||
|
* Ui::ForumUserpicRadiusMultiplier()
|
||||||
|
* style::DevicePixelRatio()));
|
||||||
|
} else {
|
||||||
|
original = Images::Circle(std::move(original));
|
||||||
|
}
|
||||||
|
_imageCache = std::move(original);
|
||||||
|
_imageCacheForum = forumValue;
|
||||||
|
_imageCacheBlurred = blurredValue;
|
||||||
|
}
|
||||||
|
|
||||||
void Photo::validateImageCache(
|
void Photo::validateImageCache(
|
||||||
QSize outer,
|
QSize outer,
|
||||||
std::optional<Ui::BubbleRounding> rounding) const {
|
std::optional<Ui::BubbleRounding> rounding) const {
|
||||||
const auto large = _dataMedia->image(PhotoSize::Large);
|
const auto large = _dataMedia->image(PhotoSize::Large);
|
||||||
const auto ratio = style::DevicePixelRatio();
|
const auto ratio = style::DevicePixelRatio();
|
||||||
const auto shouldBeBlurred = !large;
|
const auto blurredValue = large ? 0 : 1;
|
||||||
if (_imageCache.size() == (outer * ratio)
|
if (_imageCache.size() == (outer * ratio)
|
||||||
&& _imageCacheRounding == rounding
|
&& _imageCacheRounding == rounding
|
||||||
&& _imageCacheBlurred == shouldBeBlurred) {
|
&& _imageCacheBlurred == blurredValue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_imageCache = Images::Round(
|
_imageCache = Images::Round(
|
||||||
prepareImageCache(outer),
|
prepareImageCache(outer),
|
||||||
MediaRoundingMask(rounding));
|
MediaRoundingMask(rounding));
|
||||||
_imageCacheRounding = rounding;
|
_imageCacheRounding = rounding;
|
||||||
_imageCacheBlurred = shouldBeBlurred;
|
_imageCacheBlurred = blurredValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage Photo::prepareImageCache(QSize outer) const {
|
QImage Photo::prepareImageCache(QSize outer) const {
|
||||||
|
@ -405,17 +450,23 @@ void Photo::paintUserpicFrame(
|
||||||
const auto rect = QRect(photoPosition, size);
|
const auto rect = QRect(photoPosition, size);
|
||||||
const auto st = context.st;
|
const auto st = context.st;
|
||||||
const auto sti = context.imageStyle();
|
const auto sti = context.imageStyle();
|
||||||
|
const auto forum = _parent->data()->history()->isForum();
|
||||||
|
|
||||||
if (_streamed
|
if (_streamed
|
||||||
&& _streamed->instance.player().ready()
|
&& _streamed->instance.player().ready()
|
||||||
&& !_streamed->instance.player().videoSize().isEmpty()) {
|
&& !_streamed->instance.player().videoSize().isEmpty()) {
|
||||||
|
const auto ratio = style::DevicePixelRatio();
|
||||||
auto request = ::Media::Streaming::FrameRequest();
|
auto request = ::Media::Streaming::FrameRequest();
|
||||||
request.outer = size * cIntRetinaFactor();
|
request.outer = request.resize = size * ratio;
|
||||||
request.resize = size * cIntRetinaFactor();
|
|
||||||
const auto forum = _parent->data()->history()->isForum();
|
|
||||||
if (forum) {
|
if (forum) {
|
||||||
|
const auto radius = int(std::min(size.width(), size.height())
|
||||||
|
* Ui::ForumUserpicRadiusMultiplier()
|
||||||
|
* ratio);
|
||||||
|
if (_streamed->roundingCorners[0].width() != radius) {
|
||||||
|
_streamed->roundingCorners = Images::CornersMask(radius);
|
||||||
|
}
|
||||||
request.rounding = Images::CornersMaskRef(
|
request.rounding = Images::CornersMaskRef(
|
||||||
Images::CornersMask(ImageRoundRadius::Large));
|
_streamed->roundingCorners);
|
||||||
} else {
|
} else {
|
||||||
if (_streamed->roundingMask.size() != request.outer) {
|
if (_streamed->roundingMask.size() != request.outer) {
|
||||||
_streamed->roundingMask = Images::EllipseMask(size);
|
_streamed->roundingMask = Images::EllipseMask(size);
|
||||||
|
@ -438,28 +489,8 @@ void Photo::paintUserpicFrame(
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto pix = [&] {
|
validateUserpicImageCache(size, forum);
|
||||||
const auto forum = _parent->data()->history()->isForum();
|
p.drawImage(rect, _imageCache);
|
||||||
const auto args = Images::PrepareArgs{
|
|
||||||
.options = (forum
|
|
||||||
? Images::Option::RoundLarge
|
|
||||||
: Images::Option::RoundCircle),
|
|
||||||
};
|
|
||||||
if (const auto large = _dataMedia->image(PhotoSize::Large)) {
|
|
||||||
return large->pix(size, args);
|
|
||||||
} else if (const auto thumbnail = _dataMedia->image(
|
|
||||||
PhotoSize::Thumbnail)) {
|
|
||||||
return thumbnail->pix(size, args.blurred());
|
|
||||||
} else if (const auto small = _dataMedia->image(
|
|
||||||
PhotoSize::Small)) {
|
|
||||||
return small->pix(size, args.blurred());
|
|
||||||
} else if (const auto blurred = _dataMedia->thumbnailInline()) {
|
|
||||||
return blurred->pix(size, args.blurred());
|
|
||||||
} else {
|
|
||||||
return QPixmap();
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
p.drawPixmap(rect, pix);
|
|
||||||
|
|
||||||
if (_data->videoCanBePlayed() && !_streamed) {
|
if (_data->videoCanBePlayed() && !_streamed) {
|
||||||
const auto innerSize = st::msgFileLayout.thumbSize;
|
const auto innerSize = st::msgFileLayout.thumbSize;
|
||||||
|
|
|
@ -129,6 +129,7 @@ private:
|
||||||
void validateImageCache(
|
void validateImageCache(
|
||||||
QSize outer,
|
QSize outer,
|
||||||
std::optional<Ui::BubbleRounding> rounding) const;
|
std::optional<Ui::BubbleRounding> rounding) const;
|
||||||
|
void validateUserpicImageCache(QSize size, bool forum) const;
|
||||||
[[nodiscard]] QImage prepareImageCache(QSize outer) const;
|
[[nodiscard]] QImage prepareImageCache(QSize outer) const;
|
||||||
|
|
||||||
bool videoAutoplayEnabled() const;
|
bool videoAutoplayEnabled() const;
|
||||||
|
@ -150,8 +151,9 @@ private:
|
||||||
mutable std::unique_ptr<Streamed> _streamed;
|
mutable std::unique_ptr<Streamed> _streamed;
|
||||||
mutable QImage _imageCache;
|
mutable QImage _imageCache;
|
||||||
mutable std::optional<Ui::BubbleRounding> _imageCacheRounding;
|
mutable std::optional<Ui::BubbleRounding> _imageCacheRounding;
|
||||||
int _serviceWidth = 0;
|
int _serviceWidth : 30 = 0;
|
||||||
mutable bool _imageCacheBlurred = false;
|
mutable int _imageCacheForum : 1 = 0;
|
||||||
|
mutable int _imageCacheBlurred : 1 = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,11 @@ struct Poll::CloseInformation {
|
||||||
Ui::Animations::Basic radial;
|
Ui::Animations::Basic radial;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Poll::RecentVoter {
|
||||||
|
not_null<UserData*> user;
|
||||||
|
mutable Ui::PeerUserpicView userpic;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Callback>
|
template <typename Callback>
|
||||||
Poll::SendingAnimation::SendingAnimation(
|
Poll::SendingAnimation::SendingAnimation(
|
||||||
const QByteArray &option,
|
const QByteArray &option,
|
||||||
|
@ -886,9 +891,9 @@ void Poll::paintRecentVoters(
|
||||||
|
|
||||||
auto created = false;
|
auto created = false;
|
||||||
for (auto &recent : _recentVoters) {
|
for (auto &recent : _recentVoters) {
|
||||||
const auto was = (recent.userpic != nullptr);
|
const auto was = !recent.userpic.null();
|
||||||
recent.user->paintUserpic(p, recent.userpic, x, y, size);
|
recent.user->paintUserpic(p, recent.userpic, x, y, size);
|
||||||
if (!was && recent.userpic) {
|
if (!was && !recent.userpic.null()) {
|
||||||
created = true;
|
created = true;
|
||||||
}
|
}
|
||||||
const auto paintContent = [&](QPainter &p) {
|
const auto paintContent = [&](QPainter &p) {
|
||||||
|
@ -1499,13 +1504,13 @@ void Poll::clickHandlerPressedChanged(
|
||||||
|
|
||||||
void Poll::unloadHeavyPart() {
|
void Poll::unloadHeavyPart() {
|
||||||
for (auto &recent : _recentVoters) {
|
for (auto &recent : _recentVoters) {
|
||||||
recent.userpic = nullptr;
|
recent.userpic = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Poll::hasHeavyPart() const {
|
bool Poll::hasHeavyPart() const {
|
||||||
for (auto &recent : _recentVoters) {
|
for (auto &recent : _recentVoters) {
|
||||||
if (recent.userpic) {
|
if (!recent.userpic.null()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_poll.h"
|
#include "data/data_poll.h"
|
||||||
#include "base/weak_ptr.h"
|
#include "base/weak_ptr.h"
|
||||||
|
|
||||||
namespace Data {
|
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class RippleAnimation;
|
class RippleAnimation;
|
||||||
class FireworksAnimation;
|
class FireworksAnimation;
|
||||||
|
@ -75,11 +71,7 @@ private:
|
||||||
struct SendingAnimation;
|
struct SendingAnimation;
|
||||||
struct Answer;
|
struct Answer;
|
||||||
struct CloseInformation;
|
struct CloseInformation;
|
||||||
|
struct RecentVoter;
|
||||||
struct RecentVoter {
|
|
||||||
not_null<UserData*> user;
|
|
||||||
mutable std::shared_ptr<Data::CloudImageView> userpic;
|
|
||||||
};
|
|
||||||
|
|
||||||
QSize countOptimalSize() override;
|
QSize countOptimalSize() override;
|
||||||
QSize countCurrentSize(int newWidth) override;
|
QSize countCurrentSize(int newWidth) override;
|
||||||
|
|
|
@ -524,9 +524,9 @@ void InlineList::resolveUserpicsImage(const Button &button) const {
|
||||||
for (auto &entry : userpics->list) {
|
for (auto &entry : userpics->list) {
|
||||||
const auto peer = entry.peer;
|
const auto peer = entry.peer;
|
||||||
auto &view = entry.view;
|
auto &view = entry.view;
|
||||||
const auto wasView = view.get();
|
const auto wasView = view.cloud.get();
|
||||||
if (peer->userpicUniqueKey(view) != entry.uniqueKey
|
if (peer->userpicUniqueKey(view) != entry.uniqueKey
|
||||||
|| view.get() != wasView) {
|
|| view.cloud.get() != wasView) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_message_reaction_id.h"
|
#include "data/data_message_reaction_id.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class CloudImageView;
|
|
||||||
class Reactions;
|
class Reactions;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
|
|
@ -879,9 +879,17 @@ void Video::prepareThumbnail(QSize size) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto resultThumbnailImage = _documentMedia
|
||||||
|
? nullptr
|
||||||
|
: getResultThumb(fileOrigin());
|
||||||
|
const auto resultThumbnail = Image(resultThumbnailImage
|
||||||
|
? base::duplicate(*resultThumbnailImage)
|
||||||
|
: QImage());
|
||||||
const auto thumb = _documentMedia
|
const auto thumb = _documentMedia
|
||||||
? _documentMedia->thumbnail()
|
? _documentMedia->thumbnail()
|
||||||
: getResultThumb(fileOrigin());
|
: resultThumbnailImage
|
||||||
|
? &resultThumbnail
|
||||||
|
: nullptr;
|
||||||
if (!thumb) {
|
if (!thumb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1245,7 +1253,7 @@ void Contact::prepareThumbnail(int width, int height) const {
|
||||||
w = width;
|
w = width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_thumb = thumb->pixNoCache(
|
_thumb = Image(base::duplicate(*thumb)).pixNoCache(
|
||||||
QSize(w, h) * style::DevicePixelRatio(),
|
QSize(w, h) * style::DevicePixelRatio(),
|
||||||
{
|
{
|
||||||
.options = Images::Option::TransparentBackground,
|
.options = Images::Option::TransparentBackground,
|
||||||
|
@ -1403,7 +1411,7 @@ void Article::prepareThumbnail(int width, int height) const {
|
||||||
w = width;
|
w = width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_thumb = thumb->pixNoCache(
|
_thumb = Image(base::duplicate(*thumb)).pixNoCache(
|
||||||
QSize(w, h) * style::DevicePixelRatio(),
|
QSize(w, h) * style::DevicePixelRatio(),
|
||||||
{
|
{
|
||||||
.options = Images::Option::TransparentBackground,
|
.options = Images::Option::TransparentBackground,
|
||||||
|
|
|
@ -142,7 +142,7 @@ bool ItemBase::hasResultThumb() const {
|
||||||
|| !_result->_locationThumbnail.empty());
|
|| !_result->_locationThumbnail.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *ItemBase::getResultThumb(Data::FileOrigin origin) const {
|
QImage *ItemBase::getResultThumb(Data::FileOrigin origin) const {
|
||||||
if (_result && !_thumbnail) {
|
if (_result && !_thumbnail) {
|
||||||
if (!_result->_thumbnail.empty()) {
|
if (!_result->_thumbnail.empty()) {
|
||||||
_thumbnail = _result->_thumbnail.createView();
|
_thumbnail = _result->_thumbnail.createView();
|
||||||
|
@ -152,7 +152,9 @@ Image *ItemBase::getResultThumb(Data::FileOrigin origin) const {
|
||||||
_result->_locationThumbnail.load(_result->_session, origin);
|
_result->_locationThumbnail.load(_result->_session, origin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _thumbnail->image();
|
return (_thumbnail && !_thumbnail->isNull())
|
||||||
|
? _thumbnail.get()
|
||||||
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap ItemBase::getResultContactAvatar(int width, int height) const {
|
QPixmap ItemBase::getResultContactAvatar(int width, int height) const {
|
||||||
|
|
|
@ -16,10 +16,6 @@ namespace Ui {
|
||||||
class PathShiftGradient;
|
class PathShiftGradient;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Data {
|
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
|
||||||
|
|
||||||
namespace InlineBots {
|
namespace InlineBots {
|
||||||
|
|
||||||
class Result;
|
class Result;
|
||||||
|
@ -126,7 +122,7 @@ protected:
|
||||||
DocumentData *getResultDocument() const;
|
DocumentData *getResultDocument() const;
|
||||||
PhotoData *getResultPhoto() const;
|
PhotoData *getResultPhoto() const;
|
||||||
bool hasResultThumb() const;
|
bool hasResultThumb() const;
|
||||||
Image *getResultThumb(Data::FileOrigin origin) const;
|
QImage *getResultThumb(Data::FileOrigin origin) const;
|
||||||
QPixmap getResultContactAvatar(int width, int height) const;
|
QPixmap getResultContactAvatar(int width, int height) const;
|
||||||
int getResultDuration() const;
|
int getResultDuration() const;
|
||||||
QString getResultUrl() const;
|
QString getResultUrl() const;
|
||||||
|
@ -148,7 +144,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
not_null<Context*> _context;
|
not_null<Context*> _context;
|
||||||
mutable std::shared_ptr<Data::CloudImageView> _thumbnail;
|
mutable std::shared_ptr<QImage> _thumbnail;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -110,8 +110,9 @@ Session::Session(
|
||||||
_user,
|
_user,
|
||||||
Data::PeerUpdate::Flag::Photo
|
Data::PeerUpdate::Flag::Photo
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
[[maybe_unused]] const auto image = _user->currentUserpic(
|
auto view = Ui::PeerUserpicView{ .cloud = _selfUserpicView };
|
||||||
_selfUserpicView);
|
[[maybe_unused]] const auto image = _user->userpicCloudImage(view);
|
||||||
|
_selfUserpicView = view.cloud;
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
crl::on_main(this, [=] {
|
crl::on_main(this, [=] {
|
||||||
|
|
|
@ -32,7 +32,6 @@ class Templates;
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class Session;
|
class Session;
|
||||||
class Changes;
|
class Changes;
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
|
@ -216,7 +215,7 @@ private:
|
||||||
|
|
||||||
const std::unique_ptr<Support::Helper> _supportHelper;
|
const std::unique_ptr<Support::Helper> _supportHelper;
|
||||||
|
|
||||||
std::shared_ptr<Data::CloudImageView> _selfUserpicView;
|
std::shared_ptr<QImage> _selfUserpicView;
|
||||||
rpl::variable<bool> _premiumPossible = false;
|
rpl::variable<bool> _premiumPossible = false;
|
||||||
|
|
||||||
rpl::event_stream<bool> _termsLockChanges;
|
rpl::event_stream<bool> _termsLockChanges;
|
||||||
|
|
|
@ -2827,14 +2827,16 @@ void OverlayWidget::initStreamingThumbnail() {
|
||||||
|
|
||||||
_touchbarDisplay.fire(TouchBarItemType::Video);
|
_touchbarDisplay.fire(TouchBarItemType::Video);
|
||||||
|
|
||||||
|
auto userpicImage = std::optional<Image>();
|
||||||
const auto computePhotoThumbnail = [&] {
|
const auto computePhotoThumbnail = [&] {
|
||||||
const auto thumbnail = _photoMedia->image(Data::PhotoSize::Thumbnail);
|
const auto thumbnail = _photoMedia->image(Data::PhotoSize::Thumbnail);
|
||||||
if (thumbnail) {
|
if (thumbnail) {
|
||||||
return thumbnail;
|
return thumbnail;
|
||||||
} else if (_peer && _peer->userpicPhotoId() == _photo->id) {
|
} else if (_peer && _peer->userpicPhotoId() == _photo->id) {
|
||||||
if (const auto view = _peer->activeUserpicView()) {
|
if (const auto view = _peer->activeUserpicView(); view.cloud) {
|
||||||
if (const auto image = view->image()) {
|
if (!view.cloud->isNull()) {
|
||||||
return image;
|
userpicImage.emplace(base::duplicate(*view.cloud));
|
||||||
|
return &*userpicImage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3455,8 +3457,11 @@ void OverlayWidget::validatePhotoCurrentImage() {
|
||||||
&& !_message
|
&& !_message
|
||||||
&& _peer
|
&& _peer
|
||||||
&& _peer->hasUserpic()) {
|
&& _peer->hasUserpic()) {
|
||||||
if (const auto view = _peer->activeUserpicView()) {
|
if (const auto view = _peer->activeUserpicView(); view.cloud) {
|
||||||
validatePhotoImage(view->image(), true);
|
if (!view.cloud->isNull()) {
|
||||||
|
auto image = Image(base::duplicate(*view.cloud));
|
||||||
|
validatePhotoImage(&image, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_staticContent.isNull()) {
|
if (_staticContent.isNull()) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "base/weak_ptr.h"
|
#include "base/weak_ptr.h"
|
||||||
|
#include "window/notifications_utilities.h"
|
||||||
#include "styles/style_window.h"
|
#include "styles/style_window.h"
|
||||||
|
|
||||||
#include <QtCore/QBuffer>
|
#include <QtCore/QBuffer>
|
||||||
|
@ -906,7 +907,7 @@ public:
|
||||||
void showNotification(
|
void showNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
@ -1013,7 +1014,7 @@ Manager::Private::Private(not_null<Manager*> manager)
|
||||||
void Manager::Private::showNotification(
|
void Manager::Private::showNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
@ -1041,12 +1042,8 @@ void Manager::Private::showNotification(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.hideNameAndPhoto) {
|
if (!options.hideNameAndPhoto) {
|
||||||
const auto userpic = peer->isSelf()
|
notification->setImage(
|
||||||
? Ui::EmptyUserpic::GenerateSavedMessages(st::notifyMacPhotoSize)
|
Window::Notifications::GenerateUserpic(peer, userpicView));
|
||||||
: peer->isRepliesChat()
|
|
||||||
? Ui::EmptyUserpic::GenerateRepliesMessages(st::notifyMacPhotoSize)
|
|
||||||
: peer->genUserpic(userpicView, st::notifyMacPhotoSize);
|
|
||||||
notification->setImage(userpic.toImage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto i = _notifications.find(key);
|
auto i = _notifications.find(key);
|
||||||
|
@ -1183,7 +1180,7 @@ Manager::~Manager() = default;
|
||||||
void Manager::doShowNativeNotification(
|
void Manager::doShowNativeNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
|
|
@ -22,7 +22,7 @@ protected:
|
||||||
void doShowNativeNotification(
|
void doShowNativeNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
|
|
@ -22,7 +22,7 @@ protected:
|
||||||
void doShowNativeNotification(
|
void doShowNativeNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
|
|
@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/empty_userpic.h"
|
#include "ui/empty_userpic.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "window/notification_utilities.h"
|
||||||
#include "styles/style_window.h"
|
#include "styles/style_window.h"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -189,7 +190,7 @@ public:
|
||||||
void showNotification(
|
void showNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
@ -265,7 +266,7 @@ Manager::Private::Private(Manager *manager)
|
||||||
void Manager::Private::showNotification(
|
void Manager::Private::showNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
@ -302,12 +303,8 @@ void Manager::Private::showNotification(
|
||||||
[notification setInformativeText:Q2NSString(msg)];
|
[notification setInformativeText:Q2NSString(msg)];
|
||||||
if (!options.hideNameAndPhoto
|
if (!options.hideNameAndPhoto
|
||||||
&& [notification respondsToSelector:@selector(setContentImage:)]) {
|
&& [notification respondsToSelector:@selector(setContentImage:)]) {
|
||||||
auto userpic = peer->isSelf()
|
NSImage *img = Q2NSImage(
|
||||||
? Ui::EmptyUserpic::GenerateSavedMessages(st::notifyMacPhotoSize)
|
Window::Notifications::GenerateUserpic(peer, userpicView));
|
||||||
: peer->isRepliesChat()
|
|
||||||
? Ui::EmptyUserpic::GenerateRepliesMessages(st::notifyMacPhotoSize)
|
|
||||||
: peer->genUserpic(userpicView, st::notifyMacPhotoSize);
|
|
||||||
NSImage *img = Q2NSImage(userpic.toImage());
|
|
||||||
[notification setContentImage:img];
|
[notification setContentImage:img];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +472,7 @@ Manager::~Manager() = default;
|
||||||
void Manager::doShowNativeNotification(
|
void Manager::doShowNativeNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
|
|
@ -84,7 +84,7 @@ QImage ArchiveUserpic(not_null<Data::Folder*> folder) {
|
||||||
auto result = PrepareImage();
|
auto result = PrepareImage();
|
||||||
Painter paint(&result);
|
Painter paint(&result);
|
||||||
|
|
||||||
auto view = std::shared_ptr<Data::CloudImageView>();
|
auto view = Ui::PeerUserpicView();
|
||||||
folder->paintUserpic(paint, 0, 0, result.width());
|
folder->paintUserpic(paint, 0, 0, result.width());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
|
||||||
@implementation PinnedDialogsPanel {
|
@implementation PinnedDialogsPanel {
|
||||||
struct Pin {
|
struct Pin {
|
||||||
PeerData *peer = nullptr;
|
PeerData *peer = nullptr;
|
||||||
std::shared_ptr<Data::CloudImageView> userpicView = nullptr;
|
Ui::PeerUserpicView userpicView;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
QImage userpic;
|
QImage userpic;
|
||||||
QImage unreadBadge;
|
QImage unreadBadge;
|
||||||
|
|
|
@ -405,15 +405,13 @@ void Create(Window::Notifications::System *system) {
|
||||||
#ifndef __MINGW32__
|
#ifndef __MINGW32__
|
||||||
class Manager::Private {
|
class Manager::Private {
|
||||||
public:
|
public:
|
||||||
using Type = Window::Notifications::CachedUserpics::Type;
|
explicit Private(Manager *instance);
|
||||||
|
|
||||||
explicit Private(Manager *instance, Type type);
|
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
bool showNotification(
|
bool showNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
@ -438,7 +436,7 @@ private:
|
||||||
bool showNotificationInTryCatch(
|
bool showNotificationInTryCatch(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
@ -460,9 +458,8 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Manager::Private::Private(Manager *instance, Type type)
|
Manager::Private::Private(Manager *instance)
|
||||||
: _cachedUserpics(type)
|
: _guarded(std::make_shared<Manager*>(instance)) {
|
||||||
, _guarded(std::make_shared<Manager*>(instance)) {
|
|
||||||
ToastActivations(
|
ToastActivations(
|
||||||
) | rpl::start_with_next([=](const ToastActivation &activation) {
|
) | rpl::start_with_next([=](const ToastActivation &activation) {
|
||||||
handleActivation(activation);
|
handleActivation(activation);
|
||||||
|
@ -657,7 +654,7 @@ void Manager::Private::handleActivation(const ToastActivation &activation) {
|
||||||
bool Manager::Private::showNotification(
|
bool Manager::Private::showNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
@ -692,7 +689,7 @@ std::wstring Manager::Private::ensureSendButtonIcon() {
|
||||||
bool Manager::Private::showNotificationInTryCatch(
|
bool Manager::Private::showNotificationInTryCatch(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
@ -870,7 +867,7 @@ void Manager::Private::tryHide(const ToastNotification ¬ification) {
|
||||||
|
|
||||||
Manager::Manager(Window::Notifications::System *system)
|
Manager::Manager(Window::Notifications::System *system)
|
||||||
: NativeManager(system)
|
: NativeManager(system)
|
||||||
, _private(std::make_unique<Private>(this, Private::Type::Rounded)) {
|
, _private(std::make_unique<Private>(this)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::init() {
|
bool Manager::init() {
|
||||||
|
@ -890,7 +887,7 @@ Manager::~Manager() = default;
|
||||||
void Manager::doShowNativeNotification(
|
void Manager::doShowNativeNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
|
|
@ -30,7 +30,7 @@ protected:
|
||||||
void doShowNativeNotification(
|
void doShowNativeNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
|
|
@ -8,10 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "profile/profile_block_widget.h"
|
#include "profile/profile_block_widget.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
namespace Data {
|
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class RippleAnimation;
|
class RippleAnimation;
|
||||||
|
@ -33,7 +30,7 @@ public:
|
||||||
~Item();
|
~Item();
|
||||||
|
|
||||||
const not_null<PeerData*> peer;
|
const not_null<PeerData*> peer;
|
||||||
std::shared_ptr<Data::CloudImageView> userpic;
|
Ui::PeerUserpicView userpic;
|
||||||
Ui::Text::String name;
|
Ui::Text::String name;
|
||||||
QString statusText;
|
QString statusText;
|
||||||
bool statusHasOnlineColor = false;
|
bool statusHasOnlineColor = false;
|
||||||
|
|
|
@ -644,7 +644,7 @@ void SetupAccountsWrap(
|
||||||
}
|
}
|
||||||
|
|
||||||
Ui::RpWidget userpic;
|
Ui::RpWidget userpic;
|
||||||
std::shared_ptr<Data::CloudImageView> view;
|
Ui::PeerUserpicView view;
|
||||||
base::unique_qptr<Ui::PopupMenu> menu;
|
base::unique_qptr<Ui::PopupMenu> menu;
|
||||||
};
|
};
|
||||||
const auto state = raw->lifetime().make_state<State>(raw);
|
const auto state = raw->lifetime().make_state<State>(raw);
|
||||||
|
|
|
@ -360,7 +360,7 @@ RoundImageCheckbox::RoundImageCheckbox(
|
||||||
const style::RoundImageCheckbox &st,
|
const style::RoundImageCheckbox &st,
|
||||||
Fn<void()> updateCallback,
|
Fn<void()> updateCallback,
|
||||||
PaintRoundImage &&paintRoundImage,
|
PaintRoundImage &&paintRoundImage,
|
||||||
Fn<ImageRoundRadius()> roundingRadius)
|
Fn<std::optional<int>(int size)> roundingRadius)
|
||||||
: _st(st)
|
: _st(st)
|
||||||
, _updateCallback(updateCallback)
|
, _updateCallback(updateCallback)
|
||||||
, _paintRoundImage(std::move(paintRoundImage))
|
, _paintRoundImage(std::move(paintRoundImage))
|
||||||
|
@ -390,8 +390,8 @@ void RoundImageCheckbox::paint(Painter &p, int x, int y, int outerWidth) const {
|
||||||
|
|
||||||
if (selectionLevel > 0) {
|
if (selectionLevel > 0) {
|
||||||
const auto radius = _roundingRadius
|
const auto radius = _roundingRadius
|
||||||
? _roundingRadius()
|
? _roundingRadius(_st.imageRadius)
|
||||||
: ImageRoundRadius::Ellipse;
|
: std::optional<int>();
|
||||||
PainterHighQualityEnabler hq(p);
|
PainterHighQualityEnabler hq(p);
|
||||||
p.setOpacity(std::clamp(selectionLevel, 0., 1.));
|
p.setOpacity(std::clamp(selectionLevel, 0., 1.));
|
||||||
p.setBrush(Qt::NoBrush);
|
p.setBrush(Qt::NoBrush);
|
||||||
|
@ -405,11 +405,10 @@ void RoundImageCheckbox::paint(Painter &p, int x, int y, int outerWidth) const {
|
||||||
_st.imageRadius * 2,
|
_st.imageRadius * 2,
|
||||||
_st.imageRadius * 2,
|
_st.imageRadius * 2,
|
||||||
outerWidth);
|
outerWidth);
|
||||||
if (radius == ImageRoundRadius::Ellipse) {
|
if (!radius) {
|
||||||
p.drawEllipse(rect);
|
p.drawEllipse(rect);
|
||||||
} else {
|
} else {
|
||||||
const auto pxRadius = st::roundRadiusLarge;
|
p.drawRoundedRect(rect, *radius, *radius);
|
||||||
p.drawRoundedRect(rect, pxRadius, pxRadius);
|
|
||||||
}
|
}
|
||||||
p.setOpacity(1.);
|
p.setOpacity(1.);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
const style::RoundImageCheckbox &st,
|
const style::RoundImageCheckbox &st,
|
||||||
Fn<void()> updateCallback,
|
Fn<void()> updateCallback,
|
||||||
PaintRoundImage &&paintRoundImage,
|
PaintRoundImage &&paintRoundImage,
|
||||||
Fn<ImageRoundRadius()> roundingRadius = nullptr);
|
Fn<std::optional<int>(int size)> roundingRadius = nullptr);
|
||||||
|
|
||||||
void paint(Painter &p, int x, int y, int outerWidth) const;
|
void paint(Painter &p, int x, int y, int outerWidth) const;
|
||||||
float64 checkedAnimationRatio() const;
|
float64 checkedAnimationRatio() const;
|
||||||
|
@ -76,7 +76,7 @@ private:
|
||||||
const style::RoundImageCheckbox &_st;
|
const style::RoundImageCheckbox &_st;
|
||||||
Fn<void()> _updateCallback;
|
Fn<void()> _updateCallback;
|
||||||
PaintRoundImage _paintRoundImage;
|
PaintRoundImage _paintRoundImage;
|
||||||
Fn<ImageRoundRadius()> _roundingRadius;
|
Fn<std::optional<int>(int size)> _roundingRadius;
|
||||||
|
|
||||||
QPixmap _wideCache;
|
QPixmap _wideCache;
|
||||||
Ui::Animations::Simple _selection;
|
Ui::Animations::Simple _selection;
|
||||||
|
|
|
@ -193,7 +193,7 @@ void PaintInaccessibleAccountInner(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] QPixmap Generate(int size, Fn<void(QPainter&)> callback) {
|
[[nodiscard]] QImage Generate(int size, Fn<void(QPainter&)> callback) {
|
||||||
auto result = QImage(
|
auto result = QImage(
|
||||||
QSize(size, size) * style::DevicePixelRatio(),
|
QSize(size, size) * style::DevicePixelRatio(),
|
||||||
QImage::Format_ARGB32_Premultiplied);
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
@ -203,7 +203,7 @@ void PaintInaccessibleAccountInner(
|
||||||
Painter p(&result);
|
Painter p(&result);
|
||||||
callback(p);
|
callback(p);
|
||||||
}
|
}
|
||||||
return Ui::PixmapFromImage(std::move(result));
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -286,7 +286,7 @@ void EmptyUserpic::paint(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmptyUserpic::paint(
|
void EmptyUserpic::paintCircle(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
|
@ -304,9 +304,6 @@ void EmptyUserpic::paintRounded(
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
int size,
|
int size,
|
||||||
int radius) const {
|
int radius) const {
|
||||||
if (!radius) {
|
|
||||||
radius = st::roundRadiusSmall;
|
|
||||||
}
|
|
||||||
paint(p, x, y, outerWidth, size, [&] {
|
paint(p, x, y, outerWidth, size, [&] {
|
||||||
p.drawRoundedRect(x, y, size, size, radius, radius);
|
p.drawRoundedRect(x, y, size, size, radius, radius);
|
||||||
});
|
});
|
||||||
|
@ -338,21 +335,6 @@ void EmptyUserpic::PaintSavedMessages(
|
||||||
PaintSavedMessages(p, x, y, outerWidth, size, QBrush(bg), fg);
|
PaintSavedMessages(p, x, y, outerWidth, size, QBrush(bg), fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmptyUserpic::PaintSavedMessagesRounded(
|
|
||||||
QPainter &p,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int outerWidth,
|
|
||||||
int size) {
|
|
||||||
auto bg = QLinearGradient(x, y, x, y + size);
|
|
||||||
bg.setStops({
|
|
||||||
{ 0., st::historyPeerSavedMessagesBg->c },
|
|
||||||
{ 1., st::historyPeerSavedMessagesBg2->c }
|
|
||||||
});
|
|
||||||
const auto &fg = st::historyPeerUserpicFg;
|
|
||||||
PaintSavedMessagesRounded(p, x, y, outerWidth, size, QBrush(bg), fg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmptyUserpic::PaintSavedMessages(
|
void EmptyUserpic::PaintSavedMessages(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
int x,
|
int x,
|
||||||
|
@ -371,42 +353,12 @@ void EmptyUserpic::PaintSavedMessages(
|
||||||
PaintSavedMessagesInner(p, x, y, size, fg);
|
PaintSavedMessagesInner(p, x, y, size, fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmptyUserpic::PaintSavedMessagesRounded(
|
QImage EmptyUserpic::GenerateSavedMessages(int size) {
|
||||||
QPainter &p,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int outerWidth,
|
|
||||||
int size,
|
|
||||||
QBrush bg,
|
|
||||||
const style::color &fg) {
|
|
||||||
x = style::RightToLeft() ? (outerWidth - x - size) : x;
|
|
||||||
|
|
||||||
PainterHighQualityEnabler hq(p);
|
|
||||||
p.setBrush(std::move(bg));
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
p.drawRoundedRect(
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
size,
|
|
||||||
size,
|
|
||||||
st::roundRadiusSmall,
|
|
||||||
st::roundRadiusSmall);
|
|
||||||
|
|
||||||
PaintSavedMessagesInner(p, x, y, size, fg);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap EmptyUserpic::GenerateSavedMessages(int size) {
|
|
||||||
return Generate(size, [&](QPainter &p) {
|
return Generate(size, [&](QPainter &p) {
|
||||||
PaintSavedMessages(p, 0, 0, size, size);
|
PaintSavedMessages(p, 0, 0, size, size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap EmptyUserpic::GenerateSavedMessagesRounded(int size) {
|
|
||||||
return Generate(size, [&](QPainter &p) {
|
|
||||||
PaintSavedMessagesRounded(p, 0, 0, size, size);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmptyUserpic::PaintRepliesMessages(
|
void EmptyUserpic::PaintRepliesMessages(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
int x,
|
int x,
|
||||||
|
@ -422,21 +374,6 @@ void EmptyUserpic::PaintRepliesMessages(
|
||||||
PaintRepliesMessages(p, x, y, outerWidth, size, QBrush(bg), fg);
|
PaintRepliesMessages(p, x, y, outerWidth, size, QBrush(bg), fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmptyUserpic::PaintRepliesMessagesRounded(
|
|
||||||
QPainter &p,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int outerWidth,
|
|
||||||
int size) {
|
|
||||||
auto bg = QLinearGradient(x, y, x, y + size);
|
|
||||||
bg.setStops({
|
|
||||||
{ 0., st::historyPeerSavedMessagesBg->c },
|
|
||||||
{ 1., st::historyPeerSavedMessagesBg2->c }
|
|
||||||
});
|
|
||||||
const auto &fg = st::historyPeerUserpicFg;
|
|
||||||
PaintRepliesMessagesRounded(p, x, y, outerWidth, size, QBrush(bg), fg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmptyUserpic::PaintRepliesMessages(
|
void EmptyUserpic::PaintRepliesMessages(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
int x,
|
int x,
|
||||||
|
@ -455,42 +392,12 @@ void EmptyUserpic::PaintRepliesMessages(
|
||||||
PaintRepliesMessagesInner(p, x, y, size, fg);
|
PaintRepliesMessagesInner(p, x, y, size, fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmptyUserpic::PaintRepliesMessagesRounded(
|
QImage EmptyUserpic::GenerateRepliesMessages(int size) {
|
||||||
QPainter &p,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int outerWidth,
|
|
||||||
int size,
|
|
||||||
QBrush bg,
|
|
||||||
const style::color &fg) {
|
|
||||||
x = style::RightToLeft() ? (outerWidth - x - size) : x;
|
|
||||||
|
|
||||||
PainterHighQualityEnabler hq(p);
|
|
||||||
p.setBrush(bg);
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
p.drawRoundedRect(
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
size,
|
|
||||||
size,
|
|
||||||
st::roundRadiusSmall,
|
|
||||||
st::roundRadiusSmall);
|
|
||||||
|
|
||||||
PaintRepliesMessagesInner(p, x, y, size, fg);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap EmptyUserpic::GenerateRepliesMessages(int size) {
|
|
||||||
return Generate(size, [&](QPainter &p) {
|
return Generate(size, [&](QPainter &p) {
|
||||||
PaintRepliesMessages(p, 0, 0, size, size);
|
PaintRepliesMessages(p, 0, 0, size, size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap EmptyUserpic::GenerateRepliesMessagesRounded(int size) {
|
|
||||||
return Generate(size, [&](QPainter &p) {
|
|
||||||
PaintRepliesMessagesRounded(p, 0, 0, size, size);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<uint64, uint64> EmptyUserpic::uniqueKey() const {
|
std::pair<uint64, uint64> EmptyUserpic::uniqueKey() const {
|
||||||
const auto first = (uint64(0xFFFFFFFFU) << 32)
|
const auto first = (uint64(0xFFFFFFFFU) << 32)
|
||||||
| anim::getPremultiplied(_colors.color1->c);
|
| anim::getPremultiplied(_colors.color1->c);
|
||||||
|
@ -510,7 +417,7 @@ QPixmap EmptyUserpic::generate(int size) {
|
||||||
result.fill(Qt::transparent);
|
result.fill(Qt::transparent);
|
||||||
{
|
{
|
||||||
auto p = QPainter(&result);
|
auto p = QPainter(&result);
|
||||||
paint(p, 0, 0, size, size);
|
paintCircle(p, 0, 0, size, size);
|
||||||
}
|
}
|
||||||
return Ui::PixmapFromImage(std::move(result));
|
return Ui::PixmapFromImage(std::move(result));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/weak_ptr.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
class EmptyUserpic {
|
class EmptyUserpic final : public base::has_weak_ptr {
|
||||||
public:
|
public:
|
||||||
struct BgColors {
|
struct BgColors {
|
||||||
const style::color color1;
|
const style::color color1;
|
||||||
|
@ -24,7 +26,7 @@ public:
|
||||||
|
|
||||||
EmptyUserpic(const BgColors &colors, const QString &name);
|
EmptyUserpic(const BgColors &colors, const QString &name);
|
||||||
|
|
||||||
void paint(
|
void paintCircle(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
|
@ -52,12 +54,6 @@ public:
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
int size);
|
int size);
|
||||||
static void PaintSavedMessagesRounded(
|
|
||||||
QPainter &p,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int outerWidth,
|
|
||||||
int size);
|
|
||||||
static void PaintSavedMessages(
|
static void PaintSavedMessages(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
int x,
|
int x,
|
||||||
|
@ -66,16 +62,7 @@ public:
|
||||||
int size,
|
int size,
|
||||||
QBrush bg,
|
QBrush bg,
|
||||||
const style::color &fg);
|
const style::color &fg);
|
||||||
static void PaintSavedMessagesRounded(
|
[[nodiscard]] static QImage GenerateSavedMessages(int size);
|
||||||
QPainter &p,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int outerWidth,
|
|
||||||
int size,
|
|
||||||
QBrush bg,
|
|
||||||
const style::color &fg);
|
|
||||||
[[nodiscard]] static QPixmap GenerateSavedMessages(int size);
|
|
||||||
[[nodiscard]] static QPixmap GenerateSavedMessagesRounded(int size);
|
|
||||||
|
|
||||||
static void PaintRepliesMessages(
|
static void PaintRepliesMessages(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
|
@ -83,12 +70,6 @@ public:
|
||||||
int y,
|
int y,
|
||||||
int outerWidth,
|
int outerWidth,
|
||||||
int size);
|
int size);
|
||||||
static void PaintRepliesMessagesRounded(
|
|
||||||
QPainter &p,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int outerWidth,
|
|
||||||
int size);
|
|
||||||
static void PaintRepliesMessages(
|
static void PaintRepliesMessages(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
int x,
|
int x,
|
||||||
|
@ -97,16 +78,7 @@ public:
|
||||||
int size,
|
int size,
|
||||||
QBrush bg,
|
QBrush bg,
|
||||||
const style::color &fg);
|
const style::color &fg);
|
||||||
static void PaintRepliesMessagesRounded(
|
[[nodiscard]] static QImage GenerateRepliesMessages(int size);
|
||||||
QPainter &p,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int outerWidth,
|
|
||||||
int size,
|
|
||||||
QBrush bg,
|
|
||||||
const style::color &fg);
|
|
||||||
[[nodiscard]] static QPixmap GenerateRepliesMessages(int size);
|
|
||||||
[[nodiscard]] static QPixmap GenerateRepliesMessagesRounded(int size);
|
|
||||||
|
|
||||||
~EmptyUserpic();
|
~EmptyUserpic();
|
||||||
|
|
||||||
|
|
|
@ -354,7 +354,7 @@ void UserpicButton::setupPeerViewers() {
|
||||||
) | rpl::filter([=] {
|
) | rpl::filter([=] {
|
||||||
return _waiting;
|
return _waiting;
|
||||||
}) | rpl::start_with_next([=] {
|
}) | rpl::start_with_next([=] {
|
||||||
if (!_userpicView || _userpicView->image()) {
|
if (!Ui::PeerUserpicLoading(_userpicView)) {
|
||||||
_waiting = false;
|
_waiting = false;
|
||||||
startNewPhotoShowing();
|
startNewPhotoShowing();
|
||||||
}
|
}
|
||||||
|
@ -473,12 +473,17 @@ void UserpicButton::paintUserpicFrame(Painter &p, QPoint photoPosition) {
|
||||||
: false;
|
: false;
|
||||||
auto request = Media::Streaming::FrameRequest();
|
auto request = Media::Streaming::FrameRequest();
|
||||||
auto size = QSize{ _st.photoSize, _st.photoSize };
|
auto size = QSize{ _st.photoSize, _st.photoSize };
|
||||||
request.outer = size * cIntRetinaFactor();
|
const auto ratio = style::DevicePixelRatio();
|
||||||
request.resize = size * cIntRetinaFactor();
|
request.outer = request.resize = size * ratio;
|
||||||
const auto forum = _peer && _peer->isForum();
|
const auto forum = _peer && _peer->isForum();
|
||||||
if (forum) {
|
if (forum) {
|
||||||
request.rounding = Images::CornersMaskRef(
|
const auto radius = int(_st.photoSize
|
||||||
Images::CornersMask(ImageRoundRadius::Large));
|
* Ui::ForumUserpicRadiusMultiplier()
|
||||||
|
* ratio);
|
||||||
|
if (_roundingCorners[0].width() != radius) {
|
||||||
|
_roundingCorners = Images::CornersMask(radius);
|
||||||
|
}
|
||||||
|
request.rounding = Images::CornersMaskRef(_roundingCorners);
|
||||||
} else {
|
} else {
|
||||||
if (_ellipseMask.size() != request.outer) {
|
if (_ellipseMask.size() != request.outer) {
|
||||||
_ellipseMask = Images::EllipseMask(size);
|
_ellipseMask = Images::EllipseMask(size);
|
||||||
|
@ -520,7 +525,7 @@ void UserpicButton::processPeerPhoto() {
|
||||||
Expects(_peer != nullptr);
|
Expects(_peer != nullptr);
|
||||||
|
|
||||||
_userpicView = _peer->createUserpicView();
|
_userpicView = _peer->createUserpicView();
|
||||||
_waiting = _userpicView && !_userpicView->image();
|
_waiting = Ui::PeerUserpicLoading(_userpicView);
|
||||||
if (_waiting) {
|
if (_waiting) {
|
||||||
_peer->loadUserpic();
|
_peer->loadUserpic();
|
||||||
}
|
}
|
||||||
|
@ -798,7 +803,7 @@ void UserpicButton::fillShape(QPainter &p, const style::color &color) const {
|
||||||
p.setBrush(color);
|
p.setBrush(color);
|
||||||
const auto size = _st.photoSize;
|
const auto size = _st.photoSize;
|
||||||
if (_peer && _peer->isForum()) {
|
if (_peer && _peer->isForum()) {
|
||||||
const auto radius = st::roundRadiusLarge;
|
const auto radius = size * Ui::ForumUserpicRadiusMultiplier();
|
||||||
p.drawRoundedRect(0, 0, size, size, radius, radius);
|
p.drawRoundedRect(0, 0, size, size, radius, radius);
|
||||||
} else {
|
} else {
|
||||||
p.drawEllipse(0, 0, size, size);
|
p.drawEllipse(0, 0, size, size);
|
||||||
|
@ -811,8 +816,8 @@ void UserpicButton::prepareUserpicPixmap() {
|
||||||
}
|
}
|
||||||
auto size = _st.photoSize;
|
auto size = _st.photoSize;
|
||||||
_userpicHasImage = _peer
|
_userpicHasImage = _peer
|
||||||
? (_peer->currentUserpic(_userpicView) || _role != Role::ChangePhoto)
|
&& (_peer->userpicCloudImage(_userpicView)
|
||||||
: false;
|
|| _role != Role::ChangePhoto);
|
||||||
_userpic = CreateSquarePixmap(size, [&](Painter &p) {
|
_userpic = CreateSquarePixmap(size, [&](Painter &p) {
|
||||||
if (_userpicHasImage) {
|
if (_userpicHasImage) {
|
||||||
_peer->paintUserpic(p, _userpicView, 0, 0, _st.photoSize);
|
_peer->paintUserpic(p, _userpicView, 0, 0, _st.photoSize);
|
||||||
|
|
|
@ -11,15 +11,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/tooltip.h"
|
#include "ui/widgets/tooltip.h"
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/effects/cross_line.h"
|
#include "ui/effects/cross_line.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
#include "styles/style_window.h"
|
#include "styles/style_window.h"
|
||||||
#include "styles/style_widgets.h"
|
#include "styles/style_widgets.h"
|
||||||
|
|
||||||
class PeerData;
|
class PeerData;
|
||||||
|
|
||||||
namespace Data {
|
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
class Controller;
|
class Controller;
|
||||||
class SessionController;
|
class SessionController;
|
||||||
|
@ -159,7 +156,7 @@ private:
|
||||||
::Window::SessionController *_controller = nullptr;
|
::Window::SessionController *_controller = nullptr;
|
||||||
::Window::Controller *_window = nullptr;
|
::Window::Controller *_window = nullptr;
|
||||||
PeerData *_peer = nullptr;
|
PeerData *_peer = nullptr;
|
||||||
std::shared_ptr<Data::CloudImageView> _userpicView;
|
PeerUserpicView _userpicView;
|
||||||
QString _cropTitle;
|
QString _cropTitle;
|
||||||
Role _role = Role::ChangePhoto;
|
Role _role = Role::ChangePhoto;
|
||||||
bool _notShownYet = true;
|
bool _notShownYet = true;
|
||||||
|
@ -169,28 +166,29 @@ private:
|
||||||
bool _userpicCustom = false;
|
bool _userpicCustom = false;
|
||||||
bool _requestToUpload = false;
|
bool _requestToUpload = false;
|
||||||
InMemoryKey _userpicUniqueKey;
|
InMemoryKey _userpicUniqueKey;
|
||||||
Ui::Animations::Simple _a_appearance;
|
Animations::Simple _a_appearance;
|
||||||
QImage _result;
|
QImage _result;
|
||||||
QImage _ellipseMask;
|
QImage _ellipseMask;
|
||||||
|
std::array<QImage, 4> _roundingCorners;
|
||||||
std::unique_ptr<Media::Streaming::Instance> _streamed;
|
std::unique_ptr<Media::Streaming::Instance> _streamed;
|
||||||
PhotoData *_streamedPhoto = nullptr;
|
PhotoData *_streamedPhoto = nullptr;
|
||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> _menu;
|
base::unique_qptr<PopupMenu> _menu;
|
||||||
|
|
||||||
bool _showSavedMessagesOnSelf = false;
|
bool _showSavedMessagesOnSelf = false;
|
||||||
bool _canOpenPhoto = false;
|
bool _canOpenPhoto = false;
|
||||||
bool _cursorInChangeOverlay = false;
|
bool _cursorInChangeOverlay = false;
|
||||||
bool _changeOverlayEnabled = false;
|
bool _changeOverlayEnabled = false;
|
||||||
Ui::Animations::Simple _changeOverlayShown;
|
Animations::Simple _changeOverlayShown;
|
||||||
|
|
||||||
rpl::event_stream<QImage> _chosenImages;
|
rpl::event_stream<QImage> _chosenImages;
|
||||||
rpl::event_stream<> _uploadPhotoRequests;
|
rpl::event_stream<> _uploadPhotoRequests;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SilentToggle
|
class SilentToggle final
|
||||||
: public Ui::RippleButton
|
: public RippleButton
|
||||||
, public Ui::AbstractTooltipShower {
|
, public AbstractTooltipShower {
|
||||||
public:
|
public:
|
||||||
SilentToggle(QWidget *parent, not_null<ChannelData*> channel);
|
SilentToggle(QWidget *parent, not_null<ChannelData*> channel);
|
||||||
|
|
||||||
|
@ -218,7 +216,7 @@ private:
|
||||||
not_null<ChannelData*> _channel;
|
not_null<ChannelData*> _channel;
|
||||||
bool _checked = false;
|
bool _checked = false;
|
||||||
|
|
||||||
Ui::Animations::Simple _crossLineAnimation;
|
Animations::Simple _crossLineAnimation;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
80
Telegram/SourceFiles/ui/userpic_view.cpp
Normal file
80
Telegram/SourceFiles/ui/userpic_view.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
|
|
||||||
|
#include "ui/empty_userpic.h"
|
||||||
|
#include "ui/image/image_prepare.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
|
||||||
|
float64 ForumUserpicRadiusMultiplier() {
|
||||||
|
return 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PeerUserpicLoading(const PeerUserpicView &view) {
|
||||||
|
return view.cloud && view.cloud->isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateUserpicCache(
|
||||||
|
PeerUserpicView &view,
|
||||||
|
const QImage *cloud,
|
||||||
|
const EmptyUserpic *empty,
|
||||||
|
int size,
|
||||||
|
bool forum) {
|
||||||
|
Expects(cloud != nullptr || empty != nullptr);
|
||||||
|
|
||||||
|
const auto full = QSize(size, size);
|
||||||
|
const auto version = style::PaletteVersion();
|
||||||
|
const auto forumValue = forum ? 1 : 0;
|
||||||
|
const auto regenerate = (view.cached.size() != QSize(size, size))
|
||||||
|
|| (view.forum != forumValue)
|
||||||
|
|| (cloud && !view.empty.null())
|
||||||
|
|| (empty && empty != view.empty.get())
|
||||||
|
|| (empty && view.paletteVersion != version);
|
||||||
|
if (!regenerate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
view.empty = empty;
|
||||||
|
view.forum = forumValue;
|
||||||
|
view.paletteVersion = version;
|
||||||
|
|
||||||
|
if (cloud) {
|
||||||
|
view.cached = cloud->scaled(
|
||||||
|
full,
|
||||||
|
Qt::IgnoreAspectRatio,
|
||||||
|
Qt::SmoothTransformation);
|
||||||
|
if (forum) {
|
||||||
|
view.cached = Images::Round(
|
||||||
|
std::move(view.cached),
|
||||||
|
Images::CornersMask(
|
||||||
|
size * Ui::ForumUserpicRadiusMultiplier()));
|
||||||
|
} else {
|
||||||
|
view.cached = Images::Circle(std::move(view.cached));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (view.cached.size() != full) {
|
||||||
|
view.cached = QImage(full, QImage::Format_ARGB32_Premultiplied);
|
||||||
|
}
|
||||||
|
view.cached.fill(Qt::transparent);
|
||||||
|
|
||||||
|
auto p = QPainter(&view.cached);
|
||||||
|
if (forum) {
|
||||||
|
empty->paintRounded(
|
||||||
|
p,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
size,
|
||||||
|
size,
|
||||||
|
size * Ui::ForumUserpicRadiusMultiplier());
|
||||||
|
} else {
|
||||||
|
empty->paintCircle(p, 0, 0, size, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ui
|
41
Telegram/SourceFiles/ui/userpic_view.h
Normal file
41
Telegram/SourceFiles/ui/userpic_view.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/weak_ptr.h"
|
||||||
|
|
||||||
|
#include <QtGui/QImage>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
|
||||||
|
class EmptyUserpic;
|
||||||
|
|
||||||
|
[[nodiscard]] float64 ForumUserpicRadiusMultiplier();
|
||||||
|
|
||||||
|
struct PeerUserpicView {
|
||||||
|
[[nodiscard]] bool null() const {
|
||||||
|
return cached.isNull() && !cloud && empty.null();
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage cached;
|
||||||
|
std::shared_ptr<QImage> cloud;
|
||||||
|
base::weak_ptr<const EmptyUserpic> empty;
|
||||||
|
int paletteVersion : 31 = 0;
|
||||||
|
int forum : 1 = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] bool PeerUserpicLoading(const PeerUserpicView &view);
|
||||||
|
|
||||||
|
void ValidateUserpicCache(
|
||||||
|
PeerUserpicView &view,
|
||||||
|
const QImage *cloud,
|
||||||
|
const EmptyUserpic *empty,
|
||||||
|
int size,
|
||||||
|
bool forum);
|
||||||
|
|
||||||
|
} // namespace Ui
|
|
@ -15,13 +15,16 @@ class History;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class Session;
|
class Session;
|
||||||
class CloudImageView;
|
|
||||||
class ForumTopic;
|
class ForumTopic;
|
||||||
class Thread;
|
class Thread;
|
||||||
struct ItemNotification;
|
struct ItemNotification;
|
||||||
enum class ItemNotificationType;
|
enum class ItemNotificationType;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
struct PeerUserpicView;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
@ -392,7 +395,7 @@ protected:
|
||||||
virtual void doShowNativeNotification(
|
virtual void doShowNativeNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
@ -413,7 +416,7 @@ protected:
|
||||||
void doShowNativeNotification(
|
void doShowNativeNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId topicRootId,
|
MsgId topicRootId,
|
||||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
Ui::PeerUserpicView &userpicView,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &subtitle,
|
const QString &subtitle,
|
||||||
|
|
|
@ -660,7 +660,7 @@ Notification::Notification(
|
||||||
auto position = computePosition(st::notifyMinHeight);
|
auto position = computePosition(st::notifyMinHeight);
|
||||||
updateGeometry(position.x(), position.y(), st::notifyWidth, st::notifyMinHeight);
|
updateGeometry(position.x(), position.y(), st::notifyWidth, st::notifyMinHeight);
|
||||||
|
|
||||||
_userpicLoaded = !_userpicView || (_userpicView->image() != nullptr);
|
_userpicLoaded = !Ui::PeerUserpicLoading(_userpicView);
|
||||||
updateNotifyDisplay();
|
updateNotifyDisplay();
|
||||||
|
|
||||||
_hideTimer.setSingleShot(true);
|
_hideTimer.setSingleShot(true);
|
||||||
|
@ -1004,7 +1004,7 @@ void Notification::updatePeerPhoto() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_userpicView = _peer->createUserpicView();
|
_userpicView = _peer->createUserpicView();
|
||||||
if (_userpicView && !_userpicView->image()) {
|
if (Ui::PeerUserpicLoading(_userpicView)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_userpicLoaded = true;
|
_userpicLoaded = true;
|
||||||
|
@ -1024,7 +1024,7 @@ void Notification::updatePeerPhoto() {
|
||||||
st::notifyPhotoPos.y(),
|
st::notifyPhotoPos.y(),
|
||||||
width(),
|
width(),
|
||||||
st::notifyPhotoSize);
|
st::notifyPhotoSize);
|
||||||
_userpicView = nullptr;
|
_userpicView = {};
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,16 +11,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/text/text.h"
|
#include "ui/text/text.h"
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
#include "base/binary_guard.h"
|
#include "base/binary_guard.h"
|
||||||
#include "base/object_ptr.h"
|
#include "base/object_ptr.h"
|
||||||
|
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
namespace Data {
|
|
||||||
class CloudImageView;
|
|
||||||
} // namespace Data
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class IconButton;
|
class IconButton;
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
|
@ -290,7 +287,7 @@ private:
|
||||||
History *_history = nullptr;
|
History *_history = nullptr;
|
||||||
Data::ForumTopic *_topic = nullptr;
|
Data::ForumTopic *_topic = nullptr;
|
||||||
MsgId _topicRootId = 0;
|
MsgId _topicRootId = 0;
|
||||||
std::shared_ptr<Data::CloudImageView> _userpicView;
|
Ui::PeerUserpicView _userpicView;
|
||||||
QString _author;
|
QString _author;
|
||||||
Data::ReactionId _reaction;
|
Data::ReactionId _reaction;
|
||||||
HistoryItem *_item = nullptr;
|
HistoryItem *_item = nullptr;
|
||||||
|
|
|
@ -15,8 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/empty_userpic.h"
|
#include "ui/empty_userpic.h"
|
||||||
#include "styles/style_window.h"
|
#include "styles/style_window.h"
|
||||||
|
|
||||||
namespace Window {
|
namespace Window::Notifications {
|
||||||
namespace Notifications {
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Delete notify photo file after 1 minute of not using.
|
// Delete notify photo file after 1 minute of not using.
|
||||||
|
@ -24,9 +23,16 @@ constexpr int kNotifyDeletePhotoAfterMs = 60000;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CachedUserpics::CachedUserpics(Type type)
|
QImage GenerateUserpic(not_null<PeerData*> peer, Ui::PeerUserpicView &view) {
|
||||||
: _type(type)
|
return peer->isSelf()
|
||||||
, _clearTimer([=] { clear(); }) {
|
? Ui::EmptyUserpic::GenerateSavedMessages(st::notifyMacPhotoSize)
|
||||||
|
: peer->isRepliesChat()
|
||||||
|
? Ui::EmptyUserpic::GenerateRepliesMessages(st::notifyMacPhotoSize)
|
||||||
|
: peer->generateUserpicImage(view, st::notifyMacPhotoSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedUserpics::CachedUserpics()
|
||||||
|
: _clearTimer([=] { clear(); }) {
|
||||||
QDir().mkpath(cWorkingDir() + u"tdata/temp"_q);
|
QDir().mkpath(cWorkingDir() + u"tdata/temp"_q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +43,14 @@ CachedUserpics::~CachedUserpics() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This works about 1200ms on Windows for a folder with one image O_o
|
// This works about 1200ms on Windows for a folder with one image O_o
|
||||||
// base::Platform::DeleteDirectory(cWorkingDir() + u"tdata/temp"_q);
|
//base::Platform::DeleteDirectory(cWorkingDir() + u"tdata/temp"_q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CachedUserpics::get(
|
QString CachedUserpics::get(
|
||||||
const InMemoryKey &key,
|
const InMemoryKey &key,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
std::shared_ptr<Data::CloudImageView> &view) {
|
Ui::PeerUserpicView &view) {
|
||||||
auto ms = crl::now();
|
auto ms = crl::now();
|
||||||
auto i = _images.find(key);
|
auto i = _images.find(key);
|
||||||
if (i != _images.cend()) {
|
if (i != _images.cend()) {
|
||||||
|
@ -64,21 +70,7 @@ QString CachedUserpics::get(
|
||||||
cWorkingDir(),
|
cWorkingDir(),
|
||||||
QString::number(base::RandomValue<uint64>(), 16));
|
QString::number(base::RandomValue<uint64>(), 16));
|
||||||
if (key.first || key.second) {
|
if (key.first || key.second) {
|
||||||
if (peer->isSelf()) {
|
GenerateUserpic(peer, view).save(v.path, "PNG");
|
||||||
const auto method = (_type == Type::Rounded)
|
|
||||||
? Ui::EmptyUserpic::GenerateSavedMessagesRounded
|
|
||||||
: Ui::EmptyUserpic::GenerateSavedMessages;
|
|
||||||
method(st::notifyMacPhotoSize).save(v.path, "PNG");
|
|
||||||
} else if (peer->isRepliesChat()) {
|
|
||||||
const auto method = (_type == Type::Rounded)
|
|
||||||
? Ui::EmptyUserpic::GenerateRepliesMessagesRounded
|
|
||||||
: Ui::EmptyUserpic::GenerateRepliesMessages;
|
|
||||||
method(st::notifyMacPhotoSize).save(v.path, "PNG");
|
|
||||||
} else if (_type == Type::Rounded) {
|
|
||||||
peer->saveUserpicRounded(view, v.path, st::notifyMacPhotoSize);
|
|
||||||
} else {
|
|
||||||
peer->saveUserpic(view, v.path, st::notifyMacPhotoSize);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
LogoNoMargin().save(v.path, "PNG");
|
LogoNoMargin().save(v.path, "PNG");
|
||||||
}
|
}
|
||||||
|
@ -128,5 +120,4 @@ void CachedUserpics::clear() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Notifications
|
} // namespace Window::Notifications
|
||||||
} // namespace Window
|
|
||||||
|
|
|
@ -10,34 +10,31 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "window/notifications_manager.h"
|
#include "window/notifications_manager.h"
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Ui {
|
||||||
class CloudImageView;
|
struct PeerUserpicView;
|
||||||
} // namespace Data
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Window {
|
namespace Window::Notifications {
|
||||||
namespace Notifications {
|
|
||||||
|
[[nodiscard]] QImage GenerateUserpic(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
Ui::PeerUserpicView &view);
|
||||||
|
|
||||||
class CachedUserpics : public QObject {
|
class CachedUserpics : public QObject {
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
CachedUserpics();
|
||||||
Rounded,
|
|
||||||
Circled,
|
|
||||||
};
|
|
||||||
|
|
||||||
CachedUserpics(Type type);
|
|
||||||
~CachedUserpics();
|
~CachedUserpics();
|
||||||
|
|
||||||
[[nodiscard]] QString get(
|
[[nodiscard]] QString get(
|
||||||
const InMemoryKey &key,
|
const InMemoryKey &key,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
std::shared_ptr<Data::CloudImageView> &view);
|
Ui::PeerUserpicView &view);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clear();
|
void clear();
|
||||||
void clearInMs(int ms);
|
void clearInMs(int ms);
|
||||||
crl::time clear(crl::time ms);
|
crl::time clear(crl::time ms);
|
||||||
|
|
||||||
Type _type = Type::Rounded;
|
|
||||||
struct Image {
|
struct Image {
|
||||||
crl::time until = 0;
|
crl::time until = 0;
|
||||||
QString path;
|
QString path;
|
||||||
|
@ -49,5 +46,4 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namesapce Notifications
|
} // namespace Window::Notifications
|
||||||
} // namespace Window
|
|
||||||
|
|
|
@ -982,7 +982,7 @@ void Generator::paintUserpic(int x, int y, Row::Type type, int index, QString le
|
||||||
image.fill(Qt::transparent);
|
image.fill(Qt::transparent);
|
||||||
{
|
{
|
||||||
Painter p(&image);
|
Painter p(&image);
|
||||||
userpic.paintRounded(p, 0, 0, size, size, size / 2);
|
userpic.paintCircle(p, 0, 0, size, size);
|
||||||
}
|
}
|
||||||
_p->drawImage(rtl() ? (_rect.width() - x - size) : x, y, image);
|
_p->drawImage(rtl() ? (_rect.width() - x - size) : x, y, image);
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,6 +278,8 @@ PRIVATE
|
||||||
ui/empty_userpic.h
|
ui/empty_userpic.h
|
||||||
ui/grouped_layout.cpp
|
ui/grouped_layout.cpp
|
||||||
ui/grouped_layout.h
|
ui/grouped_layout.h
|
||||||
|
ui/userpic_view.cpp
|
||||||
|
ui/userpic_view.h
|
||||||
ui/widgets/fields/special_fields.cpp
|
ui/widgets/fields/special_fields.cpp
|
||||||
ui/widgets/fields/special_fields.h
|
ui/widgets/fields/special_fields.h
|
||||||
ui/widgets/fields/time_part_input_with_placeholder.cpp
|
ui/widgets/fields/time_part_input_with_placeholder.cpp
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit e8294bbc9c7f85e6909c3ed06fe03cfd39869613
|
Subproject commit fd3531b70750ffe7ec2213a899409c08c388ce4c
|
|
@ -1 +1 @@
|
||||||
Subproject commit 22ceaae4ed958d9711965fbe4c1385a7d8c60212
|
Subproject commit 59a7b94ef4bb4d4cf6597d53bdacccbf5720e694
|
Loading…
Add table
Reference in a new issue