mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Show toast after photo suggestion is accepted.
This commit is contained in:
parent
349fbeeb23
commit
b9b6d4dba1
7 changed files with 173 additions and 41 deletions
|
@ -114,17 +114,21 @@ PeerPhoto::PeerPhoto(not_null<ApiWrap*> api)
|
|||
});
|
||||
}
|
||||
|
||||
void PeerPhoto::upload(not_null<PeerData*> peer, QImage &&image) {
|
||||
upload(peer, std::move(image), UploadType::Default);
|
||||
void PeerPhoto::upload(
|
||||
not_null<PeerData*> peer,
|
||||
QImage &&image,
|
||||
Fn<void()> done) {
|
||||
upload(peer, std::move(image), UploadType::Default, std::move(done));
|
||||
}
|
||||
|
||||
void PeerPhoto::uploadFallback(not_null<PeerData*> peer, QImage &&image) {
|
||||
upload(peer, std::move(image), UploadType::Fallback);
|
||||
upload(peer, std::move(image), UploadType::Fallback, nullptr);
|
||||
}
|
||||
|
||||
void PeerPhoto::updateSelf(
|
||||
not_null<PhotoData*> photo,
|
||||
Data::FileOrigin origin) {
|
||||
Data::FileOrigin origin,
|
||||
Fn<void()> done) {
|
||||
const auto send = [=](auto resend) -> void {
|
||||
const auto usedFileReference = photo->fileReference();
|
||||
_api.request(MTPphotos_UpdateProfilePhoto(
|
||||
|
@ -135,6 +139,9 @@ void PeerPhoto::updateSelf(
|
|||
_session->data().processPhoto(data.vphoto());
|
||||
_session->data().processUsers(data.vusers());
|
||||
});
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
if (error.code() == 400
|
||||
&& error.type().startsWith(u"FILE_REFERENCE_"_q)) {
|
||||
|
@ -153,7 +160,8 @@ void PeerPhoto::updateSelf(
|
|||
void PeerPhoto::upload(
|
||||
not_null<PeerData*> peer,
|
||||
QImage &&image,
|
||||
UploadType type) {
|
||||
UploadType type,
|
||||
Fn<void()> done) {
|
||||
peer = peer->migrateToOrMe();
|
||||
const auto ready = PreparePeerPhoto(
|
||||
_api.instance().mainDcId(),
|
||||
|
@ -169,20 +177,16 @@ void PeerPhoto::upload(
|
|||
[](const auto &pair) { return pair.second.peer; });
|
||||
if (already != end(_uploads)) {
|
||||
_session->uploader().cancel(already->first);
|
||||
_suggestions.remove(already->first);
|
||||
_uploads.erase(already);
|
||||
}
|
||||
_uploads.emplace(
|
||||
fakeId,
|
||||
UploadValue{ peer, type == UploadType::Fallback });
|
||||
if (type == UploadType::Suggestion) {
|
||||
_suggestions.emplace(fakeId);
|
||||
}
|
||||
UploadValue{ peer, type, std::move(done) });
|
||||
_session->uploader().uploadMedia(fakeId, ready);
|
||||
}
|
||||
|
||||
void PeerPhoto::suggest(not_null<PeerData*> peer, QImage &&image) {
|
||||
upload(peer, std::move(image), UploadType::Suggestion);
|
||||
upload(peer, std::move(image), UploadType::Suggestion, nullptr);
|
||||
}
|
||||
|
||||
void PeerPhoto::clear(not_null<PhotoData*> photo) {
|
||||
|
@ -285,20 +289,22 @@ void PeerPhoto::set(not_null<PeerData*> peer, not_null<PhotoData*> photo) {
|
|||
|
||||
void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) {
|
||||
const auto maybeUploadValue = _uploads.take(msgId);
|
||||
const auto suggestion = _suggestions.contains(msgId);
|
||||
_suggestions.remove(msgId);
|
||||
if (!maybeUploadValue) {
|
||||
return;
|
||||
}
|
||||
const auto peer = maybeUploadValue->peer;
|
||||
const auto fallback = maybeUploadValue->fallback;
|
||||
const auto type = maybeUploadValue->type;
|
||||
const auto done = maybeUploadValue->done;
|
||||
const auto applier = [=](const MTPUpdates &result) {
|
||||
_session->updates().applyUpdates(result);
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
if (peer->isSelf()) {
|
||||
_api.request(MTPphotos_UploadProfilePhoto(
|
||||
MTP_flags(MTPphotos_UploadProfilePhoto::Flag::f_file
|
||||
| (fallback
|
||||
| ((type == UploadType::Fallback)
|
||||
? MTPphotos_UploadProfilePhoto::Flag::f_fallback
|
||||
: MTPphotos_UploadProfilePhoto::Flags(0))),
|
||||
file,
|
||||
|
@ -308,11 +314,14 @@ void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) {
|
|||
const auto photoId = _session->data().processPhoto(
|
||||
result.data().vphoto())->id;
|
||||
_session->data().processUsers(result.data().vusers());
|
||||
if (fallback) {
|
||||
if (type == UploadType::Fallback) {
|
||||
_session->storage().add(Storage::UserPhotosSetBack(
|
||||
peerToUser(peer->id),
|
||||
photoId));
|
||||
}
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
}).send();
|
||||
} else if (const auto chat = peer->asChat()) {
|
||||
const auto history = _session->data().history(chat);
|
||||
|
@ -338,7 +347,9 @@ void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) {
|
|||
using Flag = MTPphotos_UploadContactProfilePhoto::Flag;
|
||||
_api.request(MTPphotos_UploadContactProfilePhoto(
|
||||
MTP_flags(Flag::f_file
|
||||
| (suggestion ? Flag::f_suggest : Flag::f_save)),
|
||||
| ((type == UploadType::Suggestion)
|
||||
? Flag::f_suggest
|
||||
: Flag::f_save)),
|
||||
user->inputUser,
|
||||
file,
|
||||
MTPInputFile(), // video
|
||||
|
@ -348,9 +359,12 @@ void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) {
|
|||
_session->data().processPhoto(data.vphoto());
|
||||
_session->data().processUsers(data.vusers());
|
||||
});
|
||||
if (!suggestion) {
|
||||
if (type != UploadType::Suggestion) {
|
||||
user->updateFullForced();
|
||||
}
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,11 +28,15 @@ public:
|
|||
using UserPhotoId = PhotoId;
|
||||
explicit PeerPhoto(not_null<ApiWrap*> api);
|
||||
|
||||
void upload(not_null<PeerData*> peer, QImage &&image);
|
||||
void upload(
|
||||
not_null<PeerData*> peer,
|
||||
QImage &&image,
|
||||
Fn<void()> done = nullptr);
|
||||
void uploadFallback(not_null<PeerData*> peer, QImage &&image);
|
||||
void updateSelf(
|
||||
not_null<PhotoData*> photo,
|
||||
Data::FileOrigin origin);
|
||||
Data::FileOrigin origin,
|
||||
Fn<void()> done = nullptr);
|
||||
void suggest(not_null<PeerData*> peer, QImage &&image);
|
||||
void clear(not_null<PhotoData*> photo);
|
||||
void clearPersonal(not_null<UserData*> user);
|
||||
|
@ -59,18 +63,19 @@ private:
|
|||
void upload(
|
||||
not_null<PeerData*> peer,
|
||||
QImage &&image,
|
||||
UploadType type);
|
||||
UploadType type,
|
||||
Fn<void()> done);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
|
||||
struct UploadValue {
|
||||
not_null<PeerData*> peer;
|
||||
bool fallback = false;
|
||||
UploadType type = UploadType::Default;
|
||||
Fn<void()> done;
|
||||
};
|
||||
|
||||
base::flat_map<FullMsgId, UploadValue> _uploads;
|
||||
base::flat_set<FullMsgId> _suggestions;
|
||||
|
||||
base::flat_map<not_null<UserData*>, mtpRequestId> _userPhotosRequests;
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "window/themes/window_theme_editor_box.h" // GenerateSlug.
|
||||
#include "payments/payments_checkout_process.h"
|
||||
#include "settings/settings_common.h"
|
||||
#include "settings/settings_information.h"
|
||||
#include "settings/settings_global_ttl.h"
|
||||
#include "settings/settings_folders.h"
|
||||
#include "settings/settings_main.h"
|
||||
|
@ -488,6 +489,8 @@ bool ResolveSettings(
|
|||
return ::Settings::ChangePhone::Id();
|
||||
} else if (section == u"auto_delete"_q) {
|
||||
return ::Settings::GlobalTTLId();
|
||||
} else if (section == u"information"_q) {
|
||||
return ::Settings::Information::Id();
|
||||
}
|
||||
return ::Settings::Main::Id();
|
||||
}();
|
||||
|
@ -846,7 +849,7 @@ const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
|
|||
ResolvePrivatePost
|
||||
},
|
||||
{
|
||||
u"^settings(/language|/devices|/folders|/privacy|/themes|/change_number|/auto_delete)?$"_q,
|
||||
u"^settings(/language|/devices|/folders|/privacy|/themes|/change_number|/auto_delete|/information)?$"_q,
|
||||
ResolveSettings
|
||||
},
|
||||
{
|
||||
|
|
|
@ -481,9 +481,10 @@ QImage Photo::prepareImageCacheWithLarge(QSize outer, Image *large) const {
|
|||
|
||||
void Photo::paintUserpicFrame(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
QPoint photoPosition) const {
|
||||
const auto autoplay = _data->videoCanBePlayed() && videoAutoplayEnabled();
|
||||
QPoint photoPosition,
|
||||
bool markFrameShown) const {
|
||||
const auto autoplay = _data->videoCanBePlayed()
|
||||
&& videoAutoplayEnabled();
|
||||
const auto startPlay = autoplay && !_streamed;
|
||||
if (startPlay) {
|
||||
const_cast<Photo*>(this)->playAnimation(true);
|
||||
|
@ -493,8 +494,6 @@ void Photo::paintUserpicFrame(
|
|||
|
||||
const auto size = QSize(width(), height());
|
||||
const auto rect = QRect(photoPosition, size);
|
||||
const auto st = context.st;
|
||||
const auto sti = context.imageStyle();
|
||||
const auto forum = _parent->data()->history()->isForum();
|
||||
|
||||
if (_streamed
|
||||
|
@ -527,7 +526,7 @@ void Photo::paintUserpicFrame(
|
|||
} else {
|
||||
_streamed->frozenFrame = QImage();
|
||||
p.drawImage(rect, _streamed->instance.frame(request));
|
||||
if (!context.paused) {
|
||||
if (markFrameShown) {
|
||||
_streamed->instance.markFrameShown();
|
||||
}
|
||||
}
|
||||
|
@ -535,10 +534,23 @@ void Photo::paintUserpicFrame(
|
|||
}
|
||||
validateUserpicImageCache(size, forum);
|
||||
p.drawImage(rect, _imageCache);
|
||||
}
|
||||
|
||||
void Photo::paintUserpicFrame(
|
||||
Painter &p,
|
||||
const PaintContext &context,
|
||||
QPoint photoPosition) const {
|
||||
paintUserpicFrame(p, photoPosition, !context.paused);
|
||||
|
||||
if (_data->videoCanBePlayed() && !_streamed) {
|
||||
const auto st = context.st;
|
||||
const auto sti = context.imageStyle();
|
||||
const auto innerSize = st::msgFileLayout.thumbSize;
|
||||
auto inner = QRect(rect.x() + (rect.width() - innerSize) / 2, rect.y() + (rect.height() - innerSize) / 2, innerSize, innerSize);
|
||||
auto inner = QRect(
|
||||
photoPosition.x() + (width() - innerSize) / 2,
|
||||
photoPosition.y() + (height() - innerSize) / 2,
|
||||
innerSize,
|
||||
innerSize);
|
||||
p.setPen(Qt::NoPen);
|
||||
if (context.selected()) {
|
||||
p.setBrush(st->msgDateImgBgSelected());
|
||||
|
|
|
@ -63,6 +63,11 @@ public:
|
|||
}
|
||||
void showPhoto(FullMsgId id);
|
||||
|
||||
void paintUserpicFrame(
|
||||
Painter &p,
|
||||
QPoint photoPosition,
|
||||
bool markFrameShown) const;
|
||||
|
||||
QSize sizeForGroupingOptimal(int maxWidth) const override;
|
||||
QSize sizeForGrouping(int width) const override;
|
||||
void drawGrouped(
|
||||
|
|
|
@ -24,6 +24,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/painter.h"
|
||||
#include "mainwidget.h"
|
||||
#include "apiwrap.h"
|
||||
|
@ -34,23 +36,26 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace HistoryView {
|
||||
namespace {
|
||||
|
||||
constexpr auto kToastDuration = 5 * crl::time(1000);
|
||||
|
||||
void ShowUserpicSuggestion(
|
||||
not_null<Window::SessionController*> controller,
|
||||
const std::shared_ptr<Data::PhotoMedia> &media,
|
||||
const FullMsgId itemId,
|
||||
not_null<PeerData*> peer) {
|
||||
not_null<PeerData*> peer,
|
||||
Fn<void()> setDone) {
|
||||
const auto photo = media->owner();
|
||||
const auto from = peer->asUser();
|
||||
const auto name = (from && !from->firstName.isEmpty())
|
||||
? from->firstName
|
||||
: peer->name();
|
||||
if (photo->hasVideo()) {
|
||||
const auto done = [=] {
|
||||
const auto done = [=](Fn<void()> close) {
|
||||
using namespace Settings;
|
||||
const auto session = &photo->session();
|
||||
auto &peerPhotos = session->api().peerPhoto();
|
||||
peerPhotos.updateSelf(photo, itemId);
|
||||
controller->showSettings(Information::Id());
|
||||
peerPhotos.updateSelf(photo, itemId, setDone);
|
||||
close();
|
||||
};
|
||||
controller->show(Ui::MakeConfirmBox({
|
||||
.text = tr::lng_profile_accept_video_sure(
|
||||
|
@ -72,11 +77,10 @@ void ShowUserpicSuggestion(
|
|||
auto &peerPhotos = session->api().peerPhoto();
|
||||
if (original->size() == image.size()
|
||||
&& original->constBits() == image.constBits()) {
|
||||
peerPhotos.updateSelf(photo, itemId);
|
||||
peerPhotos.updateSelf(photo, itemId, setDone);
|
||||
} else {
|
||||
peerPhotos.upload(user, std::move(image));
|
||||
peerPhotos.upload(user, std::move(image), setDone);
|
||||
}
|
||||
controller->showSettings(Information::Id());
|
||||
};
|
||||
using namespace Editor;
|
||||
PrepareProfilePhoto(
|
||||
|
@ -96,7 +100,86 @@ void ShowUserpicSuggestion(
|
|||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] QImage GrabUserpicFrame(base::weak_ptr<Photo> photo) {
|
||||
const auto strong = photo.get();
|
||||
if (!strong || !strong->width() || !strong->height()) {
|
||||
return {};
|
||||
}
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
auto frame = QImage(
|
||||
QSize(strong->width(), strong->height()) * ratio,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
frame.fill(Qt::transparent);
|
||||
frame.setDevicePixelRatio(ratio);
|
||||
auto p = Painter(&frame);
|
||||
strong->paintUserpicFrame(p, QPoint(0, 0), false);
|
||||
p.end();
|
||||
return frame;
|
||||
}
|
||||
|
||||
void ShowSetToast(
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QImage &frame) {
|
||||
const auto text = Ui::Text::Bold(
|
||||
tr::lng_profile_changed_photo_title(tr::now)
|
||||
).append('\n').append(
|
||||
tr::lng_profile_changed_photo_about(
|
||||
tr::now,
|
||||
lt_link,
|
||||
Ui::Text::Link(
|
||||
tr::lng_profile_changed_photo_link(tr::now),
|
||||
u"tg://settings/information"_q),
|
||||
Ui::Text::WithEntities)
|
||||
);
|
||||
auto st = std::make_shared<style::Toast>(st::historyPremiumToast);
|
||||
const auto skip = st->padding.top();
|
||||
const auto size = st->style.font->height * 2;
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
auto copy = frame.scaled(
|
||||
QSize(size, size) * ratio,
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
copy.setDevicePixelRatio(ratio);
|
||||
st->padding.setLeft(skip + size + skip);
|
||||
st->palette.linkFg = st->palette.selectLinkFg = st::mediaviewTextLinkFg;
|
||||
|
||||
const auto parent = Window::Show(controller).toastParent();
|
||||
const auto weak = Ui::Toast::Show(parent, {
|
||||
.text = text,
|
||||
.st = st.get(),
|
||||
.durationMs = kToastDuration,
|
||||
.multiline = true,
|
||||
.dark = true,
|
||||
.slideSide = RectPart::Bottom,
|
||||
});
|
||||
if (const auto strong = weak.get()) {
|
||||
const auto widget = strong->widget();
|
||||
widget->lifetime().add([st = std::move(st)] {});
|
||||
|
||||
const auto preview = Ui::CreateChild<Ui::RpWidget>(widget.get());
|
||||
preview->moveToLeft(skip, skip);
|
||||
preview->resize(size, size);
|
||||
preview->show();
|
||||
preview->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
preview->paintRequest(
|
||||
) | rpl::start_with_next([=] {
|
||||
QPainter(preview).drawImage(0, 0, copy);
|
||||
}, preview->lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] Fn<void()> ShowSetToastCallback(
|
||||
base::weak_ptr<Window::SessionController> weak,
|
||||
QImage frame) {
|
||||
return [weak = std::move(weak), frame = std::move(frame)] {
|
||||
if (const auto strong = weak.get()) {
|
||||
ShowSetToast(strong, frame);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
UserpicSuggestion::UserpicSuggestion(
|
||||
not_null<Element*> parent,
|
||||
not_null<PeerData*> chat,
|
||||
|
@ -138,10 +221,15 @@ ClickHandlerPtr UserpicSuggestion::createViewLink() {
|
|||
const auto photo = _photo.getPhoto();
|
||||
const auto itemId = _photo.parent()->data()->fullId();
|
||||
const auto peer = _photo.parent()->data()->history()->peer;
|
||||
const auto show = crl::guard(&_photo, [=](FullMsgId id) {
|
||||
const auto weak = base::make_weak(&_photo);
|
||||
const auto show = crl::guard(weak, [=](FullMsgId id) {
|
||||
_photo.showPhoto(id);
|
||||
});
|
||||
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
|
||||
auto frame = GrabUserpicFrame(weak);
|
||||
if (frame.isNull()) {
|
||||
return;
|
||||
}
|
||||
const auto my = context.other.value<ClickHandlerContext>();
|
||||
if (const auto controller = my.sessionWindow.get()) {
|
||||
const auto media = photo->activeMediaView();
|
||||
|
@ -150,7 +238,12 @@ ClickHandlerPtr UserpicSuggestion::createViewLink() {
|
|||
PhotoOpenClickHandler(photo, show, itemId).onClick(
|
||||
context);
|
||||
} else {
|
||||
ShowUserpicSuggestion(controller, media, itemId, peer);
|
||||
ShowUserpicSuggestion(
|
||||
controller,
|
||||
media,
|
||||
itemId,
|
||||
peer,
|
||||
ShowSetToastCallback(controller, std::move(frame)));
|
||||
}
|
||||
} else if (!photo->loading()) {
|
||||
PhotoSaveClickHandler(photo, itemId).onClick(context);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit fbdc6ed5ac791890d87ca7f22b668ceca47d7684
|
||||
Subproject commit d079108e2949db26cd2d83108559a71f70fe52e2
|
Loading…
Add table
Reference in a new issue