diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 90ec1f0b5..d72cc06ad 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1486,12 +1486,12 @@ void HistoryWidget::orderWidgets() { if (_contactStatus) { _contactStatus->bar().raise(); } - if (_pinnedBar) { - _pinnedBar->raise(); - } if (_translateBar) { _translateBar->raise(); } + if (_pinnedBar) { + _pinnedBar->raise(); + } if (_requestsBar) { _requestsBar->raise(); } @@ -2097,8 +2097,8 @@ void HistoryWidget::showHistory( _history->showAtMsgId = _showAtMsgId; destroyUnreadBarOnClose(); - _translateBar = nullptr; _pinnedBar = nullptr; + _translateBar = nullptr; _pinnedTracker = nullptr; _groupCallBar = nullptr; _requestsBar = nullptr; @@ -3998,12 +3998,12 @@ void HistoryWidget::showAnimated( show(); _topBar->finishAnimating(); _cornerButtons.finishAnimations(); - if (_translateBar) { - _translateBar->finishAnimating(); - } if (_pinnedBar) { _pinnedBar->finishAnimating(); } + if (_translateBar) { + _translateBar->finishAnimating(); + } if (_groupCallBar) { _groupCallBar->finishAnimating(); } @@ -4036,12 +4036,12 @@ void HistoryWidget::showAnimated( void HistoryWidget::showFinished() { _cornerButtons.finishAnimations(); - if (_translateBar) { - _translateBar->finishAnimating(); - } if (_pinnedBar) { _pinnedBar->finishAnimating(); } + if (_translateBar) { + _translateBar->finishAnimating(); + } if (_groupCallBar) { _groupCallBar->finishAnimating(); } @@ -4067,12 +4067,12 @@ void HistoryWidget::doneShow() { _preserveScrollTop = true; preloadHistoryIfNeeded(); updatePinnedViewer(); - if (_translateBar) { - _translateBar->finishAnimating(); - } if (_pinnedBar) { _pinnedBar->finishAnimating(); } + if (_translateBar) { + _translateBar->finishAnimating(); + } if (_groupCallBar) { _groupCallBar->finishAnimating(); } @@ -5379,17 +5379,17 @@ void HistoryWidget::updateControlsGeometry() { _requestsBar->move(0, requestsTop); _requestsBar->resizeToWidth(width()); } - const auto translateTop = requestsTop + (_requestsBar ? _requestsBar->height() : 0); - if (_translateBar) { - _translateBar->move(0, translateTop); - _translateBar->resizeToWidth(width()); - } - const auto pinnedBarTop = translateTop + (_translateBar ? _translateBar->height() : 0); + const auto pinnedBarTop = requestsTop + (_requestsBar ? _requestsBar->height() : 0); if (_pinnedBar) { _pinnedBar->move(0, pinnedBarTop); _pinnedBar->resizeToWidth(width()); } - const auto contactStatusTop = pinnedBarTop + (_pinnedBar ? _pinnedBar->height() : 0); + const auto translateTop = pinnedBarTop + (_pinnedBar ? _pinnedBar->height() : 0); + if (_translateBar) { + _translateBar->move(0, translateTop); + _translateBar->resizeToWidth(width()); + } + const auto contactStatusTop = translateTop + (_translateBar ? _translateBar->height() : 0); if (_contactStatus) { _contactStatus->bar().move(0, contactStatusTop); } diff --git a/Telegram/SourceFiles/history/view/history_view_translate_bar.cpp b/Telegram/SourceFiles/history/view/history_view_translate_bar.cpp index f11e389fe..103e801b3 100644 --- a/Telegram/SourceFiles/history/view/history_view_translate_bar.cpp +++ b/Telegram/SourceFiles/history/view/history_view_translate_bar.cpp @@ -15,14 +15,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "main/main_session.h" #include "spellcheck/spellcheck_types.h" +#include "ui/effects/ripple_animation.h" #include "ui/boxes/choose_language_box.h" // EditSkipTranslationLanguages. #include "ui/layers/box_content.h" +#include "ui/widgets/menu/menu_item_base.h" #include "ui/text/text_utilities.h" #include "ui/toast/toast.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" #include "ui/widgets/popup_menu.h" #include "ui/widgets/shadow.h" +#include "ui/painter.h" #include "window/window_session_controller.h" #include "styles/style_chat.h" #include "styles/style_menu_icons.h" @@ -34,6 +37,193 @@ namespace { constexpr auto kToastDuration = 4 * crl::time(1000); +class TwoTextAction final : public Ui::Menu::ItemBase { +public: + TwoTextAction( + not_null parent, + const style::Menu &st, + const QString &text1, + const QString &text2, + Fn callback, + const style::icon *icon, + const style::icon *iconOver); + + bool isEnabled() const override; + not_null action() const override; + + void handleKeyPress(not_null e) override; + +private: + QPoint prepareRippleStartPosition() const override; + QImage prepareRippleMask() const override; + + int contentHeight() const override; + + void paint(Painter &p); + void prepare(const QString &text1); + + const not_null _dummyAction; + const style::Menu &_st; + const style::icon *_icon; + const style::icon *_iconOver; + Ui::Text::String _text1; + QString _text2; + int _textWidth1 = 0; + int _textWidth2 = 0; + const int _height; + +}; + +TextParseOptions MenuTextOptions = { + TextParseLinks, // flags + 0, // maxw + 0, // maxh + Qt::LayoutDirectionAuto, // dir +}; + +TwoTextAction::TwoTextAction( + not_null parent, + const style::Menu &st, + const QString &text1, + const QString &text2, + Fn callback, + const style::icon *icon, + const style::icon *iconOver) +: ItemBase(parent, st) +, _dummyAction(new QAction(parent)) +, _st(st) +, _icon(icon) +, _iconOver(iconOver) +, _text2(text2) +, _height(st::ttlItemPadding.top() + + _st.itemStyle.font->height + + st::ttlItemTimerFont->height + + st::ttlItemPadding.bottom()) { + initResizeHook(parent->sizeValue()); + setClickedCallback(std::move(callback)); + + paintRequest( + ) | rpl::start_with_next([=] { + Painter p(this); + paint(p); + }, lifetime()); + + enableMouseSelecting(); + prepare(text1); +} + +void TwoTextAction::paint(Painter &p) { + const auto selected = isSelected(); + if (selected && _st.itemBgOver->c.alpha() < 255) { + p.fillRect(0, 0, width(), _height, _st.itemBg); + } + p.fillRect(0, 0, width(), _height, selected ? _st.itemBgOver : _st.itemBg); + if (isEnabled()) { + paintRipple(p, 0, 0); + } + + const auto normalHeight = _st.itemPadding.top() + + _st.itemStyle.font->height + + _st.itemPadding.bottom(); + const auto deltaHeight = _height - normalHeight; + if (const auto icon = selected ? _iconOver : _icon) { + icon->paint( + p, + _st.itemIconPosition + QPoint(0, deltaHeight / 2), + width()); + } + + p.setPen(selected ? _st.itemFgOver : _st.itemFg); + _text1.drawLeftElided( + p, + _st.itemPadding.left(), + st::ttlItemPadding.top(), + _textWidth1, + width()); + + p.setFont(st::ttlItemTimerFont); + p.setPen(selected ? _st.itemFgShortcutOver : _st.itemFgShortcut); + p.drawTextLeft( + _st.itemPadding.left(), + st::ttlItemPadding.top() + _st.itemStyle.font->height, + width(), + _text2); +} + +void TwoTextAction::prepare(const QString &text1) { + _text1.setMarkedText(_st.itemStyle, { text1 }, MenuTextOptions); + const auto textWidth1 = _text1.maxWidth(); + const auto textWidth2 = st::ttlItemTimerFont->width(_text2); + const auto &padding = _st.itemPadding; + + const auto goodWidth = padding.left() + + std::max(textWidth1, textWidth2) + + padding.right(); + const auto ttlMaxWidth = [&](const QString &duration) { + return padding.left() + + st::ttlItemTimerFont->width(tr::lng_context_auto_delete_in( + tr::now, + lt_duration, + duration)) + + padding.right(); + }; + const auto maxWidth1 = ttlMaxWidth("23:59:59"); + const auto maxWidth2 = ttlMaxWidth(tr::lng_days(tr::now, lt_count, 7)); + + const auto w = std::clamp( + std::max({ goodWidth, maxWidth1, maxWidth2 }), + _st.widthMin, + _st.widthMax); + _textWidth1 = w - (goodWidth - textWidth1); + _textWidth2 = w - (goodWidth - textWidth2); + setMinWidth(w); + update(); +} + +bool TwoTextAction::isEnabled() const { + return true; +} + +not_null TwoTextAction::action() const { + return _dummyAction; +} + +QPoint TwoTextAction::prepareRippleStartPosition() const { + return mapFromGlobal(QCursor::pos()); +} + +QImage TwoTextAction::prepareRippleMask() const { + return Ui::RippleAnimation::RectMask(size()); +} + +int TwoTextAction::contentHeight() const { + return _height; +} + +void TwoTextAction::handleKeyPress(not_null e) { + if (!isSelected()) { + return; + } + const auto key = e->key(); + if (key == Qt::Key_Enter || key == Qt::Key_Return) { + setClicked(Ui::Menu::TriggeredSource::Keyboard); + } +} + +[[nodiscard]] base::unique_qptr MakeTranslateToItem( + not_null menu, + const QString &language, + Fn callback) { + return base::make_unique_q( + menu, + menu->st(), + tr::lng_translate_menu_to(tr::now), + language, + std::move(callback), + &st::menuIconTranslate, + &st::menuIconTranslate); +} + } // namespace TranslateBar::TranslateBar( @@ -42,10 +232,7 @@ TranslateBar::TranslateBar( not_null history) : _controller(controller) , _history(history) -, _wrap(parent, object_ptr( - parent, - QString(), - st::historyComposeButton)) +, _wrap(parent, object_ptr(parent)) , _shadow(std::make_unique(_wrap.parentWidget())) { _wrap.hide(anim::type::instant); _shadow->hide(); @@ -86,13 +273,21 @@ void TranslateBar::setup(not_null history) { updateControlsGeometry(rect); }, _wrap.lifetime()); - const auto button = static_cast(_wrap.entity()); const auto translateTo = [=](LanguageId id) { history->translateTo(id); if (const auto migrated = history->migrateFrom()) { migrated->translateTo(id); } }; + const auto button = static_cast(_wrap.entity()); + button->resize(0, st::historyComposeButton.height); + button->setAttribute(Qt::WA_OpaquePaintEvent); + + button->paintRequest( + ) | rpl::start_with_next([=](QRect clip) { + QPainter(button).fillRect(clip, st::historyComposeButton.bgColor); + }, button->lifetime()); + button->setClickedCallback([=] { translateTo(history->translatedTo() ? LanguageId() @@ -214,11 +409,15 @@ void TranslateBar::showMenu(base::unique_qptr menu) { _menu->setForcedOrigin(Ui::PanelAnimation::Origin::TopRight); const auto weak = base::make_weak(_controller); - _menu->addAction(tr::lng_translate_menu_to(tr::now), [=] { + const auto chooseCallback = [=] { if (const auto strong = weak.get()) { strong->show(Ui::ChooseTranslateToBox()); } - }, &st::menuIconTranslate); + }; + _menu->addAction(MakeTranslateToItem( + _menu->menu(), + Ui::LanguageName(Core::App().settings().translateTo()), + chooseCallback)); _menu->addSeparator(); const auto history = _history; if (const auto translateOfferedFrom = _history->translateOfferedFrom()) { diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 000f42735..7e70cce7b 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -1244,7 +1244,9 @@ historyTranslateSettings: IconButton(defaultIconButton) { iconOver: icon{{ "menu/customize", windowActiveTextFg }}; rippleAreaPosition: point(4px, 4px); rippleAreaSize: 38px; - ripple: defaultRippleAnimation; + ripple: RippleAnimation(defaultRippleAnimation) { + color: lightButtonBgOver; + } } historyTranslateMenuPosition: point(-6px, 40px); diff --git a/Telegram/SourceFiles/ui/controls/delete_message_context_action.cpp b/Telegram/SourceFiles/ui/controls/delete_message_context_action.cpp index e53fcf2d9..2c4bca985 100644 --- a/Telegram/SourceFiles/ui/controls/delete_message_context_action.cpp +++ b/Telegram/SourceFiles/ui/controls/delete_message_context_action.cpp @@ -34,13 +34,12 @@ public: void handleKeyPress(not_null e) override; -protected: +private: QPoint prepareRippleStartPosition() const override; QImage prepareRippleMask() const override; int contentHeight() const override; -private: void prepare(); void refreshAutoDeleteText(); void paint(Painter &p);