diff --git a/Telegram/SourceFiles/editor/editor.style b/Telegram/SourceFiles/editor/editor.style index 9190b9a295..9c134e2d76 100644 --- a/Telegram/SourceFiles/editor/editor.style +++ b/Telegram/SourceFiles/editor/editor.style @@ -31,11 +31,25 @@ photoEditorButtonIconFgOver: mediaviewPipControlsFgOver; photoEditorButtonIconFgActive: lightButtonFg; photoEditorButtonIconFgInactive: mediaviewPipPlaybackInactive; -photoEditorButtonBarHeight: 50px; -photoEditorButtonBarWidth: windowMinWidth; +photoEditorButtonBarHeight: 48px; +photoEditorButtonBarWidth: 422px; photoEditorButtonBarPadding: margins(2px, 0px, 2px, 0px); photoEditorTextButtonPadding: margins(22px, 0px, 22px, 0px); +photoEditorButtonStyle: TextStyle(semiboldTextStyle) { + font: font(14px semibold); + linkFont: font(14px semibold); + linkFontOver: font(14px semibold underline); +} +photoEditorButtonTextTop: 15px; + +photoEditorAbout: FlatLabel(defaultFlatLabel) { + textFg: mediaviewCaptionFg; + minWidth: 240px; + align: align(top); +} +photoEditorAboutMargin: margins(10px, 22px, 10px, 0px); + photoEditorRotateButton: IconButton(defaultIconButton) { width: photoEditorButtonBarHeight; height: photoEditorButtonBarHeight; @@ -43,7 +57,7 @@ photoEditorRotateButton: IconButton(defaultIconButton) { icon: icon {{ "photo_editor/rotate", photoEditorButtonIconFg }}; iconOver: icon {{ "photo_editor/rotate", photoEditorButtonIconFgOver }}; - rippleAreaPosition: point(5px, 5px); + rippleAreaPosition: point(4px, 4px); rippleAreaSize: 40px; ripple: RippleAnimation(defaultRippleAnimation) { color: shadowFg; diff --git a/Telegram/SourceFiles/editor/photo_editor.cpp b/Telegram/SourceFiles/editor/photo_editor.cpp index c32bff0416..ef91a1aa8c 100644 --- a/Telegram/SourceFiles/editor/photo_editor.cpp +++ b/Telegram/SourceFiles/editor/photo_editor.cpp @@ -67,11 +67,12 @@ PhotoEditor::PhotoEditor( photo, _modifications, _controllers, - std::move(data))) + data)) , _controls(base::make_unique_q( this, _controllers, - _modifications)) + _modifications, + data)) , _colorPicker(std::make_unique( this, Deserialize(Core::App().settings().photoEditorBrush()))) { @@ -81,12 +82,18 @@ PhotoEditor::PhotoEditor( if (size.isEmpty()) { return; } - const auto geometry = QRect(QPoint(), size); - const auto contentRect = geometry - st::photoEditorContentMargins; - _content->setGeometry(contentRect); - const auto contentBottom = contentRect.top() + contentRect.height(); - const auto controlsRect = geometry - - style::margins(0, contentBottom, 0, 0); + _content->setGeometry(rect() - st::photoEditorContentMargins); + }, lifetime()); + + _content->innerRect( + ) | rpl::start_with_next([=](QRect inner) { + if (inner.isEmpty()) { + return; + } + const auto innerTop = _content->y() + inner.top(); + const auto skip = st::photoEditorCropPointSize; + const auto controlsRect = rect() + - style::margins(0, innerTop + inner.height() + skip, 0, 0); _controls->setGeometry(controlsRect); }, lifetime()); diff --git a/Telegram/SourceFiles/editor/photo_editor_common.h b/Telegram/SourceFiles/editor/photo_editor_common.h index b735129056..028f55c6fa 100644 --- a/Telegram/SourceFiles/editor/photo_editor_common.h +++ b/Telegram/SourceFiles/editor/photo_editor_common.h @@ -30,6 +30,8 @@ struct EditorData { RoundedRect, }; + TextWithEntities about; + QString confirm; CropType cropType = CropType::Rect; bool keepAspectRatio = false; }; diff --git a/Telegram/SourceFiles/editor/photo_editor_content.cpp b/Telegram/SourceFiles/editor/photo_editor_content.cpp index e4c92e8ca9..065b2a1a68 100644 --- a/Telegram/SourceFiles/editor/photo_editor_content.cpp +++ b/Telegram/SourceFiles/editor/photo_editor_content.cpp @@ -80,6 +80,8 @@ PhotoEditorContent::PhotoEditorContent( mods.angle, mods.flipped, imageSizeF); _paint->applyTransform(geometry, mods.angle, mods.flipped); + + _innerRect = geometry; }, lifetime()); paintRequest( diff --git a/Telegram/SourceFiles/editor/photo_editor_content.h b/Telegram/SourceFiles/editor/photo_editor_content.h index 4a9ed7b8ea..027e5574a6 100644 --- a/Telegram/SourceFiles/editor/photo_editor_content.h +++ b/Telegram/SourceFiles/editor/photo_editor_content.h @@ -37,6 +37,10 @@ public: void setupDragArea(); + [[nodiscard]] rpl::producer innerRect() const { + return _innerRect.value(); + } + private: const QSize _photoSize; @@ -44,6 +48,7 @@ private: const base::unique_qptr _crop; const std::shared_ptr _photo; + rpl::variable _innerRect; rpl::variable _modifications; rpl::event_stream _keyPresses; diff --git a/Telegram/SourceFiles/editor/photo_editor_controls.cpp b/Telegram/SourceFiles/editor/photo_editor_controls.cpp index f133977afa..ae0f3355d7 100644 --- a/Telegram/SourceFiles/editor/photo_editor_controls.cpp +++ b/Telegram/SourceFiles/editor/photo_editor_controls.cpp @@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "ui/image/image_prepare.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/labels.h" +#include "ui/wrap/fade_wrap.h" #include "ui/painter.h" #include "styles/style_editor.h" @@ -55,7 +57,7 @@ EdgeButton::EdgeButton( const style::RippleAnimation &st) : Ui::RippleButton(parent, st) , _fg(fg) -, _text(st::semiboldTextStyle, text) +, _text(st::photoEditorButtonStyle, text) , _width(_text.maxWidth() + st::photoEditorTextButtonPadding.left() + st::photoEditorTextButtonPadding.right()) @@ -78,7 +80,7 @@ void EdgeButton::init() { paintRipple(p, _rippleRect.x(), _rippleRect.y()); p.setPen(_fg); - const auto textTop = (height() - _text.minHeight()) / 2; + const auto textTop = st::photoEditorButtonTextTop; _text.draw(p, 0, textTop, width(), style::al_center); }, lifetime()); } @@ -122,25 +124,49 @@ ButtonBar::ButtonBar( sizeValue( ) | rpl::start_with_next([=](const QSize &size) { const auto children = RpWidget::children(); - if (children.empty()) { - return; - } const auto widgets = ranges::views::all( children ) | ranges::views::filter([](not_null object) { return object->isWidgetType(); }) | ranges::views::transform([](not_null object) { - return static_cast(object.get()); + return static_cast(object.get()); }) | ranges::to_vector; + if (widgets.size() < 2) { + return; + } - const auto residualWidth = size.width() - - ranges::accumulate(widgets, 0, ranges::plus(), &QWidget::width); - const auto step = residualWidth / float(widgets.size() - 1); + const auto layout = [&](bool symmetrical) { + auto widths = widgets | ranges::views::transform( + &QWidget::width + ) | ranges::to_vector; + const auto count = int(widths.size()); + const auto middle = count / 2; + if (symmetrical) { + for (auto i = 0; i != middle; ++i) { + const auto j = count - i - 1; + widths[i] = widths[j] = std::max(widths[i], widths[j]); + } + } + const auto residualWidth = size.width() + - ranges::accumulate(widths, 0); + if (symmetrical && residualWidth < 0) { + return false; + } + const auto step = residualWidth / float(count - 1); - auto left = 0.; - for (const auto &widget : widgets) { - widget->moveToLeft(int(left), 0); - left += widget->width() + step; + auto left = 0.; + auto &&ints = ranges::views::ints(0, ranges::unreachable); + auto &&list = ranges::views::zip(widgets, widths, ints); + for (const auto &[widget, width, index] : list) { + widget->move(int((index >= middle) + ? (left + width - widget->width()) + : left), 0); + left += width + step; + } + return true; + }; + if (!layout(true)) { + layout(false); } auto result = QImage( @@ -165,37 +191,45 @@ PhotoEditorControls::PhotoEditorControls( not_null parent, std::shared_ptr controllers, const PhotoModifications modifications, - bool doneControls) + const EditorData &data) : RpWidget(parent) , _bg(st::roundedBg) , _buttonHeight(st::photoEditorButtonBarHeight) , _transformButtons(base::make_unique_q(this, _bg)) , _paintTopButtons(base::make_unique_q(this, _bg)) , _paintBottomButtons(base::make_unique_q(this, _bg)) +, _about(data.about.empty() + ? nullptr + : base::make_unique_q>( + this, + object_ptr( + this, + rpl::single(data.about), + st::photoEditorAbout))) , _transformCancel(base::make_unique_q( _transformButtons, tr::lng_cancel(tr::now), _buttonHeight, true, _bg, - st::activeButtonFg, + st::mediaviewCaptionFg, st::photoEditorRotateButton.ripple)) -, _rotateButton(base::make_unique_q( - _transformButtons, - st::photoEditorRotateButton)) , _flipButton(base::make_unique_q( _transformButtons, st::photoEditorFlipButton)) +, _rotateButton(base::make_unique_q( + _transformButtons, + st::photoEditorRotateButton)) , _paintModeButton(base::make_unique_q( _transformButtons, st::photoEditorPaintModeButton)) , _transformDone(base::make_unique_q( _transformButtons, - tr::lng_box_done(tr::now), + (data.confirm.isEmpty() ? tr::lng_box_done(tr::now) : data.confirm), _buttonHeight, false, _bg, - st::lightButtonFg, + st::mediaviewTextLinkFg, st::photoEditorRotateButton.ripple)) , _paintCancel(base::make_unique_q( _paintBottomButtons, @@ -203,7 +237,7 @@ PhotoEditorControls::PhotoEditorControls( _buttonHeight, true, _bg, - st::activeButtonFg, + st::mediaviewCaptionFg, st::photoEditorRotateButton.ripple)) , _undoButton(base::make_unique_q( _paintTopButtons, @@ -225,19 +259,9 @@ PhotoEditorControls::PhotoEditorControls( _buttonHeight, false, _bg, - st::lightButtonFg, + st::mediaviewTextLinkFg, st::photoEditorRotateButton.ripple)) { - { - const auto &padding = st::photoEditorButtonBarPadding; - const auto w = st::photoEditorButtonBarWidth - - padding.left() - - padding.right(); - _transformButtons->resize(w, _buttonHeight); - _paintBottomButtons->resize(w, _buttonHeight); - _paintTopButtons->resize(w, _buttonHeight); - } - { const auto icon = &st::photoEditorPaintIconActive; _paintModeButtonActive->setIconOverride(icon, icon); @@ -250,6 +274,14 @@ PhotoEditorControls::PhotoEditorControls( return; } + const auto &padding = st::photoEditorButtonBarPadding; + const auto w = std::min(st::photoEditorButtonBarWidth, size.width()) + - padding.left() + - padding.right(); + _transformButtons->resize(w, _buttonHeight); + _paintBottomButtons->resize(w, _buttonHeight); + _paintTopButtons->resize(w, _buttonHeight); + const auto buttonsTop = bottomButtonsTop(); const auto ¤t = _transformButtons->isHidden() @@ -259,6 +291,16 @@ PhotoEditorControls::PhotoEditorControls( current->moveToLeft( (size.width() - current->width()) / 2, buttonsTop); + + if (_about) { + const auto &margin = st::photoEditorAboutMargin; + const auto skip = st::photoEditorCropPointSize; + _about->resizeToWidth( + size.width() - margin.left() - margin.right()); + _about->moveToLeft( + (size.width() - _about->width()) / 2, + margin.top() - skip); + } }, lifetime()); _mode.changes( @@ -413,6 +455,9 @@ void PhotoEditorControls::showAnimated( const auto duration = st::photoEditorBarAnimationDuration; const auto isTransform = (mode == Mode::Transform); + if (_about) { + _about->toggle(isTransform, animated); + } const auto buttonsLeft = (width() - _transformButtons->width()) / 2; const auto buttonsTop = bottomButtonsTop(); diff --git a/Telegram/SourceFiles/editor/photo_editor_controls.h b/Telegram/SourceFiles/editor/photo_editor_controls.h index 3e3763f09c..a70b0a2f68 100644 --- a/Telegram/SourceFiles/editor/photo_editor_controls.h +++ b/Telegram/SourceFiles/editor/photo_editor_controls.h @@ -15,6 +15,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Ui { class IconButton; +class FlatLabel; +template +class FadeWrap; } // namespace Ui namespace Editor { @@ -22,6 +25,7 @@ namespace Editor { class EdgeButton; class ButtonBar; struct Controllers; +struct EditorData; class PhotoEditorControls final : public Ui::RpWidget { public: @@ -29,7 +33,7 @@ public: not_null parent, std::shared_ptr controllers, const PhotoModifications modifications, - bool doneControls = true); + const EditorData &data); [[nodiscard]] rpl::producer rotateRequests() const; [[nodiscard]] rpl::producer<> flipRequests() const; @@ -58,9 +62,11 @@ private: const base::unique_qptr _paintTopButtons; const base::unique_qptr _paintBottomButtons; + const base::unique_qptr> _about; + const base::unique_qptr _transformCancel; - const base::unique_qptr _rotateButton; const base::unique_qptr _flipButton; + const base::unique_qptr _rotateButton; const base::unique_qptr _paintModeButton; const base::unique_qptr _transformDone; diff --git a/Telegram/SourceFiles/editor/photo_editor_layer_widget.cpp b/Telegram/SourceFiles/editor/photo_editor_layer_widget.cpp index c5e86bd656..d8564fdb9b 100644 --- a/Telegram/SourceFiles/editor/photo_editor_layer_widget.cpp +++ b/Telegram/SourceFiles/editor/photo_editor_layer_widget.cpp @@ -71,7 +71,7 @@ void OpenWithPreparedFile( void PrepareProfilePhoto( not_null parent, not_null controller, - ImageRoundRadius radius, + EditorData data, Fn &&doneCallback, QImage &&image) { const auto resizeToMinSize = [=]( @@ -121,12 +121,7 @@ void PrepareProfilePhoto( controller, fileImage, PhotoModifications{ .crop = std::move(crop) }, - EditorData{ - .cropType = (radius == ImageRoundRadius::Ellipse - ? EditorData::CropType::Ellipse - : EditorData::CropType::RoundedRect), - .keepAspectRatio = true, - }); + data); const auto raw = editor.get(); auto layer = std::make_unique(parent, std::move(editor)); InitEditorLayer(layer.get(), raw, std::move(applyModifications)); @@ -136,7 +131,7 @@ void PrepareProfilePhoto( void PrepareProfilePhotoFromFile( not_null parent, not_null controller, - ImageRoundRadius radius, + EditorData data, Fn &&doneCallback) { const auto callback = [=, done = std::move(doneCallback)]( const FileDialog::OpenResult &result) mutable { @@ -152,7 +147,7 @@ void PrepareProfilePhotoFromFile( PrepareProfilePhoto( parent, controller, - radius, + data, std::move(done), std::move(image)); }; diff --git a/Telegram/SourceFiles/editor/photo_editor_layer_widget.h b/Telegram/SourceFiles/editor/photo_editor_layer_widget.h index e467674a5f..d20f0c13a5 100644 --- a/Telegram/SourceFiles/editor/photo_editor_layer_widget.h +++ b/Telegram/SourceFiles/editor/photo_editor_layer_widget.h @@ -25,6 +25,8 @@ class SessionController; namespace Editor { +struct EditorData; + void OpenWithPreparedFile( not_null parent, not_null controller, @@ -35,14 +37,14 @@ void OpenWithPreparedFile( void PrepareProfilePhoto( not_null parent, not_null controller, - ImageRoundRadius radius, + EditorData data, Fn &&doneCallback, QImage &&image); void PrepareProfilePhotoFromFile( not_null parent, not_null controller, - ImageRoundRadius radius, + EditorData data, Fn &&doneCallback); } // namespace Editor diff --git a/Telegram/SourceFiles/history/view/media/history_view_userpic_suggestion.cpp b/Telegram/SourceFiles/history/view/media/history_view_userpic_suggestion.cpp index f84d800e59..4b62605db8 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_userpic_suggestion.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_userpic_suggestion.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo_media.h" #include "data/data_file_click_handler.h" #include "data/data_session.h" +#include "editor/photo_editor_common.h" #include "editor/photo_editor_layer_widget.h" #include "history/history.h" #include "history/history_item.h" @@ -31,7 +32,71 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_chat.h" namespace HistoryView { +namespace { +void ShowUserpicSuggestion( + not_null controller, + const std::shared_ptr &media, + const FullMsgId itemId, + not_null peer) { + 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 = [=] { + 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 { + const auto original = std::make_shared( + media->image(Data::PhotoSize::Large)->original()); + const auto callback = [=](QImage &&image) { + using namespace Settings; + const auto session = &photo->session(); + const auto user = session->user(); + UpdatePhotoLocally(user, image); + auto &peerPhotos = session->api().peerPhoto(); + if (original->size() == image.size() + && original->constBits() == image.constBits()) { + peerPhotos.updateSelf(photo, itemId); + } else { + peerPhotos.upload(user, std::move(image)); + } + controller->showSettings(Information::Id()); + }; + using namespace Editor; + PrepareProfilePhoto( + controller->content(), + &controller->window(), + { + .about = { tr::lng_profile_accept_photo_sure( + tr::now, + lt_user, + name) }, + .confirm = tr::lng_profile_set_photo_button(tr::now), + .cropType = EditorData::CropType::Ellipse, + .keepAspectRatio = true, + }, + callback, + base::duplicate(*original)); + } +} + +} // namespace UserpicSuggestion::UserpicSuggestion( not_null parent, not_null chat, @@ -84,50 +149,8 @@ ClickHandlerPtr UserpicSuggestion::createViewLink() { if (out) { 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 { - const auto original = std::make_shared( - media->image(Data::PhotoSize::Large)->original()); - const auto callback = [=](QImage &&image) { - using namespace Settings; - const auto session = &photo->session(); - const auto user = session->user(); - UpdatePhotoLocally(user, image); - auto &peerPhotos = session->api().peerPhoto(); - if (original->size() == image.size() - && original->constBits() == image.constBits()) { - peerPhotos.updateSelf(photo, itemId); - } else { - peerPhotos.upload(user, std::move(image)); - } - controller->showSettings(Information::Id()); - }; - Editor::PrepareProfilePhoto( - controller->content(), - &controller->window(), - ImageRoundRadius::Ellipse, - callback, - base::duplicate(*original)); + ShowUserpicSuggestion(controller, media, itemId, peer); } } else if (!photo->loading()) { PhotoSaveClickHandler(photo, itemId).onClick(context); diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index bfcfdc8530..6231f17fc8 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_user.h" #include "data/data_user_photos.h" // UserPhotosViewer. +#include "editor/photo_editor_common.h" #include "editor/photo_editor_layer_widget.h" #include "history/admin_log/history_admin_log_item.h" #include "history/history.h" @@ -1134,10 +1135,15 @@ object_ptr ProfilePhotoPrivacyController::setupBelowWidget( base::call_delayed( st::settingsButton.ripple.hideDuration, crl::guard(container, [=] { - Editor::PrepareProfilePhotoFromFile( + using namespace Editor; + PrepareProfilePhotoFromFile( container, &controller->window(), - ImageRoundRadius::Ellipse, + { + .confirm = tr::lng_profile_set_photo_button(tr::now), + .cropType = EditorData::CropType::Ellipse, + .keepAspectRatio = true, + }, [=](QImage &&image) { state->updatePhoto(std::move(image), true); state->hiddenByUser = false; diff --git a/Telegram/SourceFiles/ui/controls/userpic_button.cpp b/Telegram/SourceFiles/ui/controls/userpic_button.cpp index 90bdd0c86c..49eaa48f5b 100644 --- a/Telegram/SourceFiles/ui/controls/userpic_button.cpp +++ b/Telegram/SourceFiles/ui/controls/userpic_button.cpp @@ -22,7 +22,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "calls/calls_instance.h" #include "core/application.h" #include "ui/layers/generic_box.h" +#include "ui/text/text_utilities.h" #include "ui/painter.h" +#include "editor/photo_editor_common.h" #include "editor/photo_editor_layer_widget.h" #include "media/streaming/media_streaming_instance.h" #include "media/streaming/media_streaming_player.h" @@ -70,22 +72,29 @@ void CameraBox( } }, box->lifetime()); - auto done = [=, done = std::move(doneCallback)](QImage &&image) { + auto done = [=, done = std::move(doneCallback)]() mutable { + using namespace Editor; + auto callback = [=, done = std::move(done)](QImage &&image) { + box->closeBox(); + done(std::move(image)); + }; + PrepareProfilePhoto( + box, + controller, + { + .confirm = tr::lng_profile_set_photo_button(tr::now), + .cropType = ((peer && peer->isForum()) + ? EditorData::CropType::RoundedRect + : EditorData::CropType::Ellipse), + .keepAspectRatio = true, + }, + std::move(callback), + track->frame(FrameRequest()).mirrored(true, false)); box->closeBox(); - done(std::move(image)); }; box->setTitle(tr::lng_profile_camera_title()); - box->addButton(tr::lng_continue(), [=, done = std::move(done)]() mutable { - Editor::PrepareProfilePhoto( - box, - controller, - ((peer && peer->isForum()) - ? ImageRoundRadius::Large - : ImageRoundRadius::Ellipse), - std::move(done), - track->frame(FrameRequest()).mirrored(true, false)); - }); + box->addButton(tr::lng_continue(), std::move(done)); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); } @@ -260,12 +269,35 @@ void UserpicButton::choosePhotoLocally() { base::call_delayed( _st.changeButton.ripple.hideDuration, crl::guard(this, [=] { - Editor::PrepareProfilePhotoFromFile( + using namespace Editor; + const auto user = _peer ? _peer->asUser() : nullptr; + const auto name = (user && !user->firstName.isEmpty()) + ? user->firstName + : _peer->name(); + const auto phrase = (type == ChosenType::Suggest) + ? &tr::lng_profile_suggest_sure + : (_peer->isUser() && !_peer->isSelf()) + ? &tr::lng_profile_set_personal_sure + : nullptr; + PrepareProfilePhotoFromFile( this, _window, - ((_peer && _peer->isForum()) - ? ImageRoundRadius::Large - : ImageRoundRadius::Ellipse), + { + .about = (phrase + ? (*phrase)( + tr::now, + lt_user, + Ui::Text::Bold(name), + Ui::Text::WithEntities) + : TextWithEntities()), + .confirm = ((type == ChosenType::Suggest) + ? tr::lng_profile_suggest_button(tr::now) + : tr::lng_profile_set_photo_button(tr::now)), + .cropType = ((_peer && _peer->isForum()) + ? EditorData::CropType::RoundedRect + : EditorData::CropType::Ellipse), + .keepAspectRatio = true, + }, callback(type)); })); };