Allow accepting video userpic suggestions.
This commit is contained in:
parent
446f0f1653
commit
9513aaa768
|
@ -1211,6 +1211,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_profile_suggest_photo" = "Suggest Profile Photo";
|
"lng_profile_suggest_photo" = "Suggest Profile Photo";
|
||||||
"lng_profile_set_photo_for" = "Set Profile Photo";
|
"lng_profile_set_photo_for" = "Set Profile Photo";
|
||||||
"lng_profile_photo_reset" = "Reset to Original";
|
"lng_profile_photo_reset" = "Reset to Original";
|
||||||
|
"lng_profile_set_for_done" = "You will now always see this photo for {user}'s account.";
|
||||||
|
"lng_profile_suggest_sure" = "You can suggest {user} to set this photo for their page.";
|
||||||
|
"lng_profile_suggest_button" = "Suggest";
|
||||||
|
"lng_profile_set_personal_sure" = "Only you will see this photo and it will replace any photo {user} sets for themselves.";
|
||||||
|
"lng_profile_accept_photo_sure" = "{user} suggests you to use this profile photo for your Telegram account.";
|
||||||
|
"lng_profile_set_photo_button" = "Set Photo";
|
||||||
|
"lng_profile_accept_video_sure" = "{user} suggests you to use this profile video for your Telegram account.";
|
||||||
|
"lng_profile_set_video_button" = "Set Video";
|
||||||
|
"lng_profile_changed_photo_title" = "Photo updated";
|
||||||
|
"lng_profile_changed_photo_about" = "You can change it in {link}.";
|
||||||
|
"lng_profile_changed_photo_link" = "Settings";
|
||||||
"lng_media_type_photos" = "Photos";
|
"lng_media_type_photos" = "Photos";
|
||||||
"lng_media_type_gifs" = "GIFs";
|
"lng_media_type_gifs" = "GIFs";
|
||||||
"lng_media_type_videos" = "Videos";
|
"lng_media_type_videos" = "Videos";
|
||||||
|
@ -1569,6 +1580,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_action_suggested_photo_me" = "You suggested {user} to use this profile photo.";
|
"lng_action_suggested_photo_me" = "You suggested {user} to use this profile photo.";
|
||||||
"lng_action_suggested_photo" = "{user} suggests you to use this profile photo.";
|
"lng_action_suggested_photo" = "{user} suggests you to use this profile photo.";
|
||||||
"lng_action_suggested_photo_button" = "View Photo";
|
"lng_action_suggested_photo_button" = "View Photo";
|
||||||
|
"lng_action_suggested_video_me" = "You suggested {user} to use this profile video.";
|
||||||
|
"lng_action_suggested_video" = "{user} suggests you to use this profile video.";
|
||||||
|
"lng_action_suggested_video_button" = "View Video";
|
||||||
"lng_action_attach_menu_bot_allowed" = "You allowed this bot to message you when you added it in the attachment menu.";
|
"lng_action_attach_menu_bot_allowed" = "You allowed this bot to message you when you added it in the attachment menu.";
|
||||||
"lng_action_topic_created_inside" = "Topic created";
|
"lng_action_topic_created_inside" = "Topic created";
|
||||||
"lng_action_topic_closed_inside" = "Topic closed";
|
"lng_action_topic_closed_inside" = "Topic closed";
|
||||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_peer.h"
|
#include "data/data_peer.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
@ -121,16 +122,32 @@ void PeerPhoto::uploadFallback(not_null<PeerData*> peer, QImage &&image) {
|
||||||
upload(peer, std::move(image), UploadType::Fallback);
|
upload(peer, std::move(image), UploadType::Fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerPhoto::updateSelf(not_null<PhotoData*> photo) {
|
void PeerPhoto::updateSelf(
|
||||||
_api.request(MTPphotos_UpdateProfilePhoto(
|
not_null<PhotoData*> photo,
|
||||||
MTP_flags(0),
|
Data::FileOrigin origin) {
|
||||||
photo->mtpInput()
|
const auto send = [=](auto resend) -> void {
|
||||||
)).done([=](const MTPphotos_Photo &result) {
|
const auto usedFileReference = photo->fileReference();
|
||||||
result.match([&](const MTPDphotos_photo &data) {
|
_api.request(MTPphotos_UpdateProfilePhoto(
|
||||||
_session->data().processPhoto(data.vphoto());
|
MTP_flags(0),
|
||||||
_session->data().processUsers(data.vusers());
|
photo->mtpInput()
|
||||||
});
|
)).done([=](const MTPphotos_Photo &result) {
|
||||||
}).send();
|
result.match([&](const MTPDphotos_photo &data) {
|
||||||
|
_session->data().processPhoto(data.vphoto());
|
||||||
|
_session->data().processUsers(data.vusers());
|
||||||
|
});
|
||||||
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
if (error.code() == 400
|
||||||
|
&& error.type().startsWith(u"FILE_REFERENCE_"_q)) {
|
||||||
|
photo->session().api().refreshFileReference(origin, [=](
|
||||||
|
const auto &) {
|
||||||
|
if (photo->fileReference() != usedFileReference) {
|
||||||
|
resend(resend);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
send(send);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerPhoto::upload(
|
void PeerPhoto::upload(
|
||||||
|
|
|
@ -13,6 +13,10 @@ class ApiWrap;
|
||||||
class PeerData;
|
class PeerData;
|
||||||
class UserData;
|
class UserData;
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
struct FileOrigin;
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
@ -26,7 +30,9 @@ public:
|
||||||
|
|
||||||
void upload(not_null<PeerData*> peer, QImage &&image);
|
void upload(not_null<PeerData*> peer, QImage &&image);
|
||||||
void uploadFallback(not_null<PeerData*> peer, QImage &&image);
|
void uploadFallback(not_null<PeerData*> peer, QImage &&image);
|
||||||
void updateSelf(not_null<PhotoData*> photo);
|
void updateSelf(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
Data::FileOrigin origin);
|
||||||
void suggest(not_null<PeerData*> peer, QImage &&image);
|
void suggest(not_null<PeerData*> peer, QImage &&image);
|
||||||
void clear(not_null<PhotoData*> photo);
|
void clear(not_null<PhotoData*> photo);
|
||||||
void clearPersonal(not_null<UserData*> user);
|
void clearPersonal(not_null<UserData*> user);
|
||||||
|
|
|
@ -28,6 +28,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_premium_limits.h"
|
#include "data/data_premium_limits.h"
|
||||||
#include "data/stickers/data_stickers.h"
|
#include "data/stickers/data_stickers.h"
|
||||||
#include "data/stickers/data_custom_emoji.h"
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
|
#include "editor/editor_layer_widget.h"
|
||||||
|
#include "editor/photo_editor.h"
|
||||||
#include "editor/photo_editor_layer_widget.h"
|
#include "editor/photo_editor_layer_widget.h"
|
||||||
#include "history/history_drag_area.h"
|
#include "history/history_drag_area.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
|
@ -453,13 +455,18 @@ void EditCaptionBox::setupPhotoEditorEventHandler() {
|
||||||
rebuildPreview();
|
rebuildPreview();
|
||||||
};
|
};
|
||||||
const auto fileImage = std::make_shared<Image>(*large);
|
const auto fileImage = std::make_shared<Image>(*large);
|
||||||
|
auto editor = base::make_unique_q<Editor::PhotoEditor>(
|
||||||
|
this,
|
||||||
|
&controller->window(),
|
||||||
|
fileImage,
|
||||||
|
Editor::PhotoModifications());
|
||||||
|
const auto raw = editor.get();
|
||||||
|
auto layer = std::make_unique<Editor::LayerWidget>(
|
||||||
|
this,
|
||||||
|
std::move(editor));
|
||||||
|
Editor::InitEditorLayer(layer.get(), raw, std::move(callback));
|
||||||
controller->showLayer(
|
controller->showLayer(
|
||||||
std::make_unique<Editor::LayerWidget>(
|
std::move(layer),
|
||||||
this,
|
|
||||||
&controller->window(),
|
|
||||||
fileImage,
|
|
||||||
Editor::PhotoModifications(),
|
|
||||||
std::move(callback)),
|
|
||||||
Ui::LayerOption::KeepOther);
|
Ui::LayerOption::KeepOther);
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
|
@ -95,6 +95,8 @@ struct FileReferenceAccumulator {
|
||||||
data.vaction().match(
|
data.vaction().match(
|
||||||
[&](const MTPDmessageActionChatEditPhoto &data) {
|
[&](const MTPDmessageActionChatEditPhoto &data) {
|
||||||
push(data.vphoto());
|
push(data.vphoto());
|
||||||
|
}, [&](const MTPDmessageActionSuggestProfilePhoto &data) {
|
||||||
|
push(data.vphoto());
|
||||||
}, [](const auto &data) {
|
}, [](const auto &data) {
|
||||||
});
|
});
|
||||||
}, [](const MTPDmessageEmpty &data) {
|
}, [](const MTPDmessageEmpty &data) {
|
||||||
|
|
50
Telegram/SourceFiles/editor/editor_layer_widget.cpp
Normal file
50
Telegram/SourceFiles/editor/editor_layer_widget.cpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
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 "editor/editor_layer_widget.h"
|
||||||
|
|
||||||
|
#include <QtGui/QGuiApplication>
|
||||||
|
|
||||||
|
namespace Editor {
|
||||||
|
|
||||||
|
LayerWidget::LayerWidget(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
base::unique_qptr<Ui::RpWidget> content)
|
||||||
|
: Ui::LayerWidget(parent)
|
||||||
|
, _content(std::move(content)) {
|
||||||
|
_content->setParent(this);
|
||||||
|
_content->show();
|
||||||
|
|
||||||
|
paintRequest(
|
||||||
|
) | rpl::start_with_next([=](const QRect &clip) {
|
||||||
|
auto p = QPainter(this);
|
||||||
|
p.fillRect(clip, st::photoEditorBg);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
sizeValue(
|
||||||
|
) | rpl::start_with_next([=](const QSize &size) {
|
||||||
|
_content->resize(size);
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayerWidget::parentResized() {
|
||||||
|
resizeToWidth(parentWidget()->width());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayerWidget::keyPressEvent(QKeyEvent *e) {
|
||||||
|
QGuiApplication::sendEvent(_content.get(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LayerWidget::resizeGetHeight(int newWidth) {
|
||||||
|
return parentWidget()->height();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerWidget::closeByOutsideClick() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Editor
|
42
Telegram/SourceFiles/editor/editor_layer_widget.h
Normal file
42
Telegram/SourceFiles/editor/editor_layer_widget.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
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 "ui/layers/layer_widget.h"
|
||||||
|
#include "ui/image/image.h"
|
||||||
|
#include "editor/photo_editor_common.h"
|
||||||
|
#include "base/unique_qptr.h"
|
||||||
|
|
||||||
|
enum class ImageRoundRadius;
|
||||||
|
|
||||||
|
namespace Window {
|
||||||
|
class Controller;
|
||||||
|
class SessionController;
|
||||||
|
} // namespace Window
|
||||||
|
|
||||||
|
namespace Editor {
|
||||||
|
|
||||||
|
class LayerWidget final : public Ui::LayerWidget {
|
||||||
|
public:
|
||||||
|
LayerWidget(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
base::unique_qptr<Ui::RpWidget> content);
|
||||||
|
|
||||||
|
void parentResized() override;
|
||||||
|
bool closeByOutsideClick() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent *e) override;
|
||||||
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const base::unique_qptr<Ui::RpWidget> _content;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Editor
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "editor/photo_editor_controls.h"
|
#include "editor/photo_editor_controls.h"
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
#include "ui/layers/layer_widget.h"
|
||||||
#include "styles/style_editor.h"
|
#include "styles/style_editor.h"
|
||||||
|
|
||||||
namespace Editor {
|
namespace Editor {
|
||||||
|
@ -46,7 +47,7 @@ constexpr auto kPrecision = 100000;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
PhotoEditor::PhotoEditor(
|
PhotoEditor::PhotoEditor(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller,
|
||||||
std::shared_ptr<Image> photo,
|
std::shared_ptr<Image> photo,
|
||||||
PhotoModifications modifications,
|
PhotoModifications modifications,
|
||||||
|
@ -174,7 +175,7 @@ PhotoEditor::PhotoEditor(
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhotoEditor::handleKeyPress(not_null<QKeyEvent*> e) {
|
void PhotoEditor::keyPressEvent(QKeyEvent *e) {
|
||||||
if (!_colorPicker->preventHandleKeyPress()) {
|
if (!_colorPicker->preventHandleKeyPress()) {
|
||||||
_content->handleKeyPress(e) || _controls->handleKeyPress(e);
|
_content->handleKeyPress(e) || _controls->handleKeyPress(e);
|
||||||
}
|
}
|
||||||
|
@ -193,4 +194,24 @@ rpl::producer<> PhotoEditor::cancelRequests() const {
|
||||||
return _cancel.events();
|
return _cancel.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InitEditorLayer(
|
||||||
|
not_null<Ui::LayerWidget*> layer,
|
||||||
|
not_null<PhotoEditor*> editor,
|
||||||
|
Fn<void(PhotoModifications)> doneCallback) {
|
||||||
|
editor->cancelRequests(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
layer->closeLayer();
|
||||||
|
}, editor->lifetime());
|
||||||
|
|
||||||
|
const auto weak = Ui::MakeWeak(layer.get());
|
||||||
|
editor->doneRequests(
|
||||||
|
) | rpl::start_with_next([=, done = std::move(doneCallback)](
|
||||||
|
const PhotoModifications &mods) {
|
||||||
|
done(mods);
|
||||||
|
if (const auto strong = weak.data()) {
|
||||||
|
strong->closeLayer();
|
||||||
|
}
|
||||||
|
}, editor->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
|
|
|
@ -8,11 +8,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
#include "ui/image/image.h"
|
||||||
#include "base/unique_qptr.h"
|
#include "base/unique_qptr.h"
|
||||||
#include "editor/photo_editor_common.h"
|
#include "editor/photo_editor_common.h"
|
||||||
#include "editor/photo_editor_inner_common.h"
|
#include "editor/photo_editor_inner_common.h"
|
||||||
#include "ui/image/image.h"
|
|
||||||
|
namespace Ui {
|
||||||
|
class LayerWidget;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
class Controller;
|
class Controller;
|
||||||
|
@ -28,19 +31,18 @@ struct Controllers;
|
||||||
class PhotoEditor final : public Ui::RpWidget {
|
class PhotoEditor final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
PhotoEditor(
|
PhotoEditor(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller,
|
||||||
std::shared_ptr<Image> photo,
|
std::shared_ptr<Image> photo,
|
||||||
PhotoModifications modifications,
|
PhotoModifications modifications,
|
||||||
EditorData data = EditorData());
|
EditorData data = EditorData());
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
rpl::producer<PhotoModifications> doneRequests() const;
|
[[nodiscard]] rpl::producer<PhotoModifications> doneRequests() const;
|
||||||
rpl::producer<> cancelRequests() const;
|
[[nodiscard]] rpl::producer<> cancelRequests() const;
|
||||||
|
|
||||||
void handleKeyPress(not_null<QKeyEvent*> e);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void keyPressEvent(QKeyEvent *e) override;
|
||||||
|
|
||||||
PhotoModifications _modifications;
|
PhotoModifications _modifications;
|
||||||
|
|
||||||
|
@ -59,4 +61,9 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void InitEditorLayer(
|
||||||
|
not_null<Ui::LayerWidget*> layer,
|
||||||
|
not_null<PhotoEditor*> editor,
|
||||||
|
Fn<void(PhotoModifications)> doneCallback);
|
||||||
|
|
||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
|
|
|
@ -8,12 +8,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "editor/photo_editor_layer_widget.h"
|
#include "editor/photo_editor_layer_widget.h"
|
||||||
|
|
||||||
#include "ui/boxes/confirm_box.h" // InformBox
|
#include "ui/boxes/confirm_box.h" // InformBox
|
||||||
|
#include "editor/editor_layer_widget.h"
|
||||||
#include "editor/photo_editor.h"
|
#include "editor/photo_editor.h"
|
||||||
#include "storage/storage_media_prepare.h"
|
#include "storage/storage_media_prepare.h"
|
||||||
#include "ui/chat/attach/attach_prepare.h"
|
#include "ui/chat/attach/attach_prepare.h"
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
|
||||||
|
#include <QtGui/QGuiApplication>
|
||||||
|
|
||||||
namespace Editor {
|
namespace Editor {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -22,7 +25,7 @@ constexpr auto kProfilePhotoSize = 640;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void OpenWithPreparedFile(
|
void OpenWithPreparedFile(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<Ui::PreparedFile*> file,
|
not_null<Ui::PreparedFile*> file,
|
||||||
int previewWidth,
|
int previewWidth,
|
||||||
|
@ -54,18 +57,19 @@ void OpenWithPreparedFile(
|
||||||
};
|
};
|
||||||
auto copy = image->data;
|
auto copy = image->data;
|
||||||
const auto fileImage = std::make_shared<Image>(std::move(copy));
|
const auto fileImage = std::make_shared<Image>(std::move(copy));
|
||||||
controller->showLayer(
|
auto editor = base::make_unique_q<PhotoEditor>(
|
||||||
std::make_unique<LayerWidget>(
|
parent,
|
||||||
parent,
|
&controller->window(),
|
||||||
&controller->window(),
|
fileImage,
|
||||||
fileImage,
|
image->modifications);
|
||||||
image->modifications,
|
const auto raw = editor.get();
|
||||||
std::move(callback)),
|
auto layer = std::make_unique<LayerWidget>(parent, std::move(editor));
|
||||||
Ui::LayerOption::KeepOther);
|
InitEditorLayer(layer.get(), raw, std::move(callback));
|
||||||
|
controller->showLayer(std::move(layer), Ui::LayerOption::KeepOther);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrepareProfilePhoto(
|
void PrepareProfilePhoto(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller,
|
||||||
ImageRoundRadius radius,
|
ImageRoundRadius radius,
|
||||||
Fn<void(QImage &&image)> &&doneCallback,
|
Fn<void(QImage &&image)> &&doneCallback,
|
||||||
|
@ -112,24 +116,25 @@ void PrepareProfilePhoto(
|
||||||
minSide);
|
minSide);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
controller->showLayer(
|
auto editor = base::make_unique_q<PhotoEditor>(
|
||||||
std::make_unique<LayerWidget>(
|
parent,
|
||||||
parent,
|
controller,
|
||||||
controller,
|
fileImage,
|
||||||
fileImage,
|
PhotoModifications{ .crop = std::move(crop) },
|
||||||
PhotoModifications{ .crop = std::move(crop) },
|
EditorData{
|
||||||
std::move(applyModifications),
|
.cropType = (radius == ImageRoundRadius::Ellipse
|
||||||
EditorData{
|
? EditorData::CropType::Ellipse
|
||||||
.cropType = (radius == ImageRoundRadius::Ellipse
|
: EditorData::CropType::RoundedRect),
|
||||||
? EditorData::CropType::Ellipse
|
.keepAspectRatio = true,
|
||||||
: EditorData::CropType::RoundedRect),
|
});
|
||||||
.keepAspectRatio = true,
|
const auto raw = editor.get();
|
||||||
}),
|
auto layer = std::make_unique<LayerWidget>(parent, std::move(editor));
|
||||||
Ui::LayerOption::KeepOther);
|
InitEditorLayer(layer.get(), raw, std::move(applyModifications));
|
||||||
|
controller->showLayer(std::move(layer), Ui::LayerOption::KeepOther);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrepareProfilePhotoFromFile(
|
void PrepareProfilePhotoFromFile(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller,
|
||||||
ImageRoundRadius radius,
|
ImageRoundRadius radius,
|
||||||
Fn<void(QImage &&image)> &&doneCallback) {
|
Fn<void(QImage &&image)> &&doneCallback) {
|
||||||
|
@ -158,60 +163,4 @@ void PrepareProfilePhotoFromFile(
|
||||||
crl::guard(parent, callback));
|
crl::guard(parent, callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerWidget::LayerWidget(
|
|
||||||
not_null<Ui::RpWidget*> parent,
|
|
||||||
not_null<Window::Controller*> window,
|
|
||||||
std::shared_ptr<Image> photo,
|
|
||||||
PhotoModifications modifications,
|
|
||||||
Fn<void(PhotoModifications)> &&doneCallback,
|
|
||||||
EditorData data)
|
|
||||||
: Ui::LayerWidget(parent)
|
|
||||||
, _content(base::make_unique_q<PhotoEditor>(
|
|
||||||
this,
|
|
||||||
window,
|
|
||||||
photo,
|
|
||||||
std::move(modifications),
|
|
||||||
std::move(data))) {
|
|
||||||
|
|
||||||
paintRequest(
|
|
||||||
) | rpl::start_with_next([=](const QRect &clip) {
|
|
||||||
auto p = QPainter(this);
|
|
||||||
p.fillRect(clip, st::photoEditorBg);
|
|
||||||
}, lifetime());
|
|
||||||
|
|
||||||
_content->cancelRequests(
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
closeLayer();
|
|
||||||
}, lifetime());
|
|
||||||
|
|
||||||
const auto weak = Ui::MakeWeak(_content.get());
|
|
||||||
_content->doneRequests(
|
|
||||||
) | rpl::start_with_next([=, done = std::move(doneCallback)](
|
|
||||||
const PhotoModifications &mods) {
|
|
||||||
done(mods);
|
|
||||||
if (weak) closeLayer();
|
|
||||||
}, lifetime());
|
|
||||||
|
|
||||||
sizeValue(
|
|
||||||
) | rpl::start_with_next([=](const QSize &size) {
|
|
||||||
_content->resize(size);
|
|
||||||
}, lifetime());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::parentResized() {
|
|
||||||
resizeToWidth(parentWidget()->width());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::keyPressEvent(QKeyEvent *e) {
|
|
||||||
_content->handleKeyPress(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LayerWidget::resizeGetHeight(int newWidth) {
|
|
||||||
return parentWidget()->height();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LayerWidget::closeByOutsideClick() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
|
|
|
@ -6,16 +6,15 @@ For license and copyright information please follow this link:
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
//
|
||||||
#include "ui/layers/layer_widget.h"
|
//#include "ui/image/image.h"
|
||||||
|
//#include "editor/photo_editor_common.h"
|
||||||
#include "base/unique_qptr.h"
|
//#include "base/unique_qptr.h"
|
||||||
#include "editor/photo_editor_common.h"
|
|
||||||
#include "ui/image/image.h"
|
|
||||||
|
|
||||||
enum class ImageRoundRadius;
|
enum class ImageRoundRadius;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
class RpWidget;
|
||||||
struct PreparedFile;
|
struct PreparedFile;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
|
@ -27,47 +26,23 @@ class SessionController;
|
||||||
namespace Editor {
|
namespace Editor {
|
||||||
|
|
||||||
void OpenWithPreparedFile(
|
void OpenWithPreparedFile(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<Ui::PreparedFile*> file,
|
not_null<Ui::PreparedFile*> file,
|
||||||
int previewWidth,
|
int previewWidth,
|
||||||
Fn<void()> &&doneCallback);
|
Fn<void()> &&doneCallback);
|
||||||
|
|
||||||
void PrepareProfilePhoto(
|
void PrepareProfilePhoto(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller,
|
||||||
ImageRoundRadius radius,
|
ImageRoundRadius radius,
|
||||||
Fn<void(QImage &&image)> &&doneCallback,
|
Fn<void(QImage &&image)> &&doneCallback,
|
||||||
QImage &&image);
|
QImage &&image);
|
||||||
|
|
||||||
void PrepareProfilePhotoFromFile(
|
void PrepareProfilePhotoFromFile(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller,
|
||||||
ImageRoundRadius radius,
|
ImageRoundRadius radius,
|
||||||
Fn<void(QImage &&image)> &&doneCallback);
|
Fn<void(QImage &&image)> &&doneCallback);
|
||||||
|
|
||||||
class PhotoEditor;
|
|
||||||
|
|
||||||
class LayerWidget : public Ui::LayerWidget {
|
|
||||||
public:
|
|
||||||
LayerWidget(
|
|
||||||
not_null<Ui::RpWidget*> parent,
|
|
||||||
not_null<Window::Controller*> window,
|
|
||||||
std::shared_ptr<Image> photo,
|
|
||||||
PhotoModifications modifications,
|
|
||||||
Fn<void(PhotoModifications)> &&doneCallback,
|
|
||||||
EditorData data = EditorData());
|
|
||||||
|
|
||||||
void parentResized() override;
|
|
||||||
bool closeByOutsideClick() const override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void keyPressEvent(QKeyEvent *e) override;
|
|
||||||
int resizeGetHeight(int newWidth) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const base::unique_qptr<PhotoEditor> _content;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
|
|
|
@ -3884,6 +3884,12 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
||||||
auto prepareSuggestProfilePhoto = [this](const MTPDmessageActionSuggestProfilePhoto &action) {
|
auto prepareSuggestProfilePhoto = [this](const MTPDmessageActionSuggestProfilePhoto &action) {
|
||||||
auto result = PreparedServiceText{};
|
auto result = PreparedServiceText{};
|
||||||
const auto isSelf = (_from->id == _from->session().userPeerId());
|
const auto isSelf = (_from->id == _from->session().userPeerId());
|
||||||
|
const auto isVideo = action.vphoto().match([&](const MTPDphoto &data) {
|
||||||
|
return data.vvideo_sizes().has_value()
|
||||||
|
&& !data.vvideo_sizes()->v.isEmpty();
|
||||||
|
}, [](const MTPDphotoEmpty &) {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
const auto peer = isSelf ? history()->peer : _from;
|
const auto peer = isSelf ? history()->peer : _from;
|
||||||
const auto user = peer->asUser();
|
const auto user = peer->asUser();
|
||||||
const auto name = (user && !user->firstName.isEmpty())
|
const auto name = (user && !user->firstName.isEmpty())
|
||||||
|
@ -3891,8 +3897,12 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
||||||
: peer->name();
|
: peer->name();
|
||||||
result.links.push_back(peer->createOpenLink());
|
result.links.push_back(peer->createOpenLink());
|
||||||
result.text = (isSelf
|
result.text = (isSelf
|
||||||
? tr::lng_action_suggested_photo_me
|
? (isVideo
|
||||||
: tr::lng_action_suggested_photo)(
|
? tr::lng_action_suggested_video_me
|
||||||
|
: tr::lng_action_suggested_photo_me)
|
||||||
|
: (isVideo
|
||||||
|
? tr::lng_action_suggested_video
|
||||||
|
: tr::lng_action_suggested_photo))(
|
||||||
tr::now,
|
tr::now,
|
||||||
lt_user,
|
lt_user,
|
||||||
Ui::Text::Link(name, 1), // Link 1.
|
Ui::Text::Link(name, 1), // Link 1.
|
||||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
#include "ui/boxes/confirm_box.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
@ -56,7 +57,11 @@ QString UserpicSuggestion::title() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString UserpicSuggestion::button() {
|
QString UserpicSuggestion::button() {
|
||||||
return tr::lng_action_suggested_photo_button(tr::now);
|
return _photo.getPhoto()->hasVideo()
|
||||||
|
? (_photo.parent()->data()->out()
|
||||||
|
? tr::lng_action_suggested_video_button(tr::now)
|
||||||
|
: tr::lng_profile_set_video_button(tr::now))
|
||||||
|
: tr::lng_action_suggested_photo_button(tr::now);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString UserpicSuggestion::subtitle() {
|
QString UserpicSuggestion::subtitle() {
|
||||||
|
@ -67,6 +72,7 @@ ClickHandlerPtr UserpicSuggestion::createViewLink() {
|
||||||
const auto out = _photo.parent()->data()->out();
|
const auto out = _photo.parent()->data()->out();
|
||||||
const auto photo = _photo.getPhoto();
|
const auto photo = _photo.getPhoto();
|
||||||
const auto itemId = _photo.parent()->data()->fullId();
|
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 show = crl::guard(&_photo, [=](FullMsgId id) {
|
||||||
_photo.showPhoto(id);
|
_photo.showPhoto(id);
|
||||||
});
|
});
|
||||||
|
@ -76,7 +82,29 @@ ClickHandlerPtr UserpicSuggestion::createViewLink() {
|
||||||
const auto media = photo->activeMediaView();
|
const auto media = photo->activeMediaView();
|
||||||
if (media->loaded()) {
|
if (media->loaded()) {
|
||||||
if (out) {
|
if (out) {
|
||||||
PhotoOpenClickHandler(photo, show, itemId).onClick(context);
|
PhotoOpenClickHandler(photo, show, itemId).onClick(
|
||||||
|
context);
|
||||||
|
} else if (photo->hasVideo()) {
|
||||||
|
const auto user = peer->asUser();
|
||||||
|
const auto name = (user && !user->firstName.isEmpty())
|
||||||
|
? user->firstName
|
||||||
|
: peer->name();
|
||||||
|
const auto done = [=] {
|
||||||
|
using namespace Settings;
|
||||||
|
const auto session = &photo->session();
|
||||||
|
auto &peerPhotos = session->api().peerPhoto();
|
||||||
|
peerPhotos.updateSelf(photo, itemId);
|
||||||
|
controller->showSettings(Information::Id());
|
||||||
|
};
|
||||||
|
controller->show(Ui::MakeConfirmBox({
|
||||||
|
.text = tr::lng_profile_accept_video_sure(
|
||||||
|
tr::now,
|
||||||
|
lt_user,
|
||||||
|
name),
|
||||||
|
.confirmed = done,
|
||||||
|
.confirmText = tr::lng_profile_set_video_button(
|
||||||
|
tr::now),
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
const auto original = std::make_shared<QImage>(
|
const auto original = std::make_shared<QImage>(
|
||||||
media->image(Data::PhotoSize::Large)->original());
|
media->image(Data::PhotoSize::Large)->original());
|
||||||
|
@ -88,7 +116,7 @@ ClickHandlerPtr UserpicSuggestion::createViewLink() {
|
||||||
auto &peerPhotos = session->api().peerPhoto();
|
auto &peerPhotos = session->api().peerPhoto();
|
||||||
if (original->size() == image.size()
|
if (original->size() == image.size()
|
||||||
&& original->constBits() == image.constBits()) {
|
&& original->constBits() == image.constBits()) {
|
||||||
peerPhotos.updateSelf(photo);
|
peerPhotos.updateSelf(photo, itemId);
|
||||||
} else {
|
} else {
|
||||||
peerPhotos.upload(user, std::move(image));
|
peerPhotos.upload(user, std::move(image));
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,8 @@ UserpicButton::UserpicButton(
|
||||||
, _role(role) {
|
, _role(role) {
|
||||||
Expects(_role == Role::ChangePhoto || _role == Role::ChoosePhoto);
|
Expects(_role == Role::ChangePhoto || _role == Role::ChoosePhoto);
|
||||||
|
|
||||||
|
showCustom({});
|
||||||
|
_waiting = false;
|
||||||
prepare();
|
prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +159,9 @@ UserpicButton::UserpicButton(
|
||||||
, _peer(peer)
|
, _peer(peer)
|
||||||
, _role(role)
|
, _role(role)
|
||||||
, _source(source) {
|
, _source(source) {
|
||||||
if (_source != Source::Custom) {
|
if (_source == Source::Custom) {
|
||||||
|
showCustom({});
|
||||||
|
} else {
|
||||||
processPeerPhoto();
|
processPeerPhoto();
|
||||||
setupPeerViewers();
|
setupPeerViewers();
|
||||||
}
|
}
|
||||||
|
@ -175,7 +179,9 @@ UserpicButton::UserpicButton(
|
||||||
, _source(Source::PeerPhoto) {
|
, _source(Source::PeerPhoto) {
|
||||||
Expects(_role != Role::OpenPhoto);
|
Expects(_role != Role::OpenPhoto);
|
||||||
|
|
||||||
if (_source != Source::Custom) {
|
if (_source == Source::Custom) {
|
||||||
|
showCustom({});
|
||||||
|
} else {
|
||||||
processPeerPhoto();
|
processPeerPhoto();
|
||||||
setupPeerViewers();
|
setupPeerViewers();
|
||||||
}
|
}
|
||||||
|
@ -813,7 +819,9 @@ void UserpicButton::onStateChanged(
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserpicButton::showCustom(QImage &&image) {
|
void UserpicButton::showCustom(QImage &&image) {
|
||||||
grabOldUserpic();
|
if (!_notShownYet) {
|
||||||
|
grabOldUserpic();
|
||||||
|
}
|
||||||
|
|
||||||
clearStreaming();
|
clearStreaming();
|
||||||
_sourceLifetime.destroy();
|
_sourceLifetime.destroy();
|
||||||
|
|
|
@ -73,6 +73,8 @@ PRIVATE
|
||||||
editor/controllers/undo_controller.h
|
editor/controllers/undo_controller.h
|
||||||
editor/editor_crop.cpp
|
editor/editor_crop.cpp
|
||||||
editor/editor_crop.h
|
editor/editor_crop.h
|
||||||
|
editor/editor_layer_widget.cpp
|
||||||
|
editor/editor_layer_widget.h
|
||||||
editor/photo_editor_common.cpp
|
editor/photo_editor_common.cpp
|
||||||
editor/photo_editor_common.h
|
editor/photo_editor_common.h
|
||||||
editor/photo_editor_inner_common.h
|
editor/photo_editor_inner_common.h
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b178a5d15f4e422f4497e9c0334fe340df9d6046
|
Subproject commit 07d9420c19c008f9b49faaabde3e7d2139255961
|
Loading…
Reference in New Issue
Block a user