diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index ac5ef1dec2..b7fd3a4be9 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -7142,6 +7142,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "ayu_ContextCopyID" = "Copy ID"; "ayu_IDCopiedToast" = "ID copied to clipboard."; "ayu_ContextHideMessage" = "Hide"; +"ayu_ShowNearPosts" = "Show Near Posts"; "ayu_ContextCopyCallbackData" = "Copy Callback Data"; "ayu_RegisterURLScheme" = "Register URL Scheme"; "ayu_SessionTerminated" = "Session **{item}** was terminated. You may still browse cached messages."; diff --git a/Telegram/SourceFiles/ayu/ayu_settings.cpp b/Telegram/SourceFiles/ayu/ayu_settings.cpp index 3d55d637a8..16616e0ee0 100644 --- a/Telegram/SourceFiles/ayu/ayu_settings.cpp +++ b/Telegram/SourceFiles/ayu/ayu_settings.cpp @@ -297,6 +297,7 @@ AyuGramSettings::AyuGramSettings() { showMessageSeconds = false; showMessageShot = true; + showHideButtonNearPosts = true; // ~ Confirmations stickerConfirmation = false; gifConfirmation = false; @@ -565,6 +566,9 @@ void set_showMessageShot(bool val) { settings->showMessageShot = val; } +void set_showHideButtonNearPosts(bool val) { + settings->showHideButtonNearPosts = val; +} void set_stickerConfirmation(bool val) { settings->stickerConfirmation = val; } diff --git a/Telegram/SourceFiles/ayu/ayu_settings.h b/Telegram/SourceFiles/ayu/ayu_settings.h index 86f2d8c205..5395b30ec5 100644 --- a/Telegram/SourceFiles/ayu/ayu_settings.h +++ b/Telegram/SourceFiles/ayu/ayu_settings.h @@ -121,6 +121,7 @@ public: bool showMessageSeconds; bool showMessageShot; + bool showHideButtonNearPosts; bool stickerConfirmation; bool gifConfirmation; bool voiceConfirmation; @@ -205,6 +206,7 @@ void set_showPeerId(int val); void set_showMessageSeconds(bool val); void set_showMessageShot(bool val); +void set_showHideButtonNearPosts(bool val); void set_stickerConfirmation(bool val); void set_gifConfirmation(bool val); void set_voiceConfirmation(bool val); @@ -269,6 +271,7 @@ inline void to_json(nlohmann::json &nlohmann_json_j, const AyuGramSettings &nloh NLOHMANN_JSON_TO(showMessageSeconds) NLOHMANN_JSON_TO(showMessageShot) NLOHMANN_JSON_TO(stickerConfirmation) + NLOHMANN_JSON_TO(showHideButtonNearPosts) NLOHMANN_JSON_TO(gifConfirmation) NLOHMANN_JSON_TO(voiceConfirmation) } @@ -334,6 +337,7 @@ inline void from_json(const nlohmann::json &nlohmann_json_j, AyuGramSettings &nl NLOHMANN_JSON_FROM_WITH_DEFAULT(showMessageSeconds) NLOHMANN_JSON_FROM_WITH_DEFAULT(showMessageShot) NLOHMANN_JSON_FROM_WITH_DEFAULT(stickerConfirmation) + NLOHMANN_JSON_FROM_WITH_DEFAULT(showHideButtonNearPosts) NLOHMANN_JSON_FROM_WITH_DEFAULT(gifConfirmation) NLOHMANN_JSON_FROM_WITH_DEFAULT(voiceConfirmation) } diff --git a/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp b/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp index e6c05e1ffb..288839faf0 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp +++ b/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp @@ -20,6 +20,7 @@ #include "styles/style_chat_helpers.h" #include "styles/style_ayu_styles.h" #include "styles/style_basic.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_info.h" #include "styles/style_menu_icons.h" @@ -935,23 +936,71 @@ void SetupContextMenuElements(not_null container, AyuSettings::save(); }); - AddChooseButtonWithIconAndRightText( - container, - controller, - settings->showHideMessageInContextMenu, - options, - tr::ayu_ContextHideMessage(), - tr::ayu_SettingsContextMenuTitle(), - st::menuIconClear, - [=](int index) - { - AyuSettings::set_showHideMessageInContextMenu(index); - AyuSettings::save(); - }); - AddChooseButtonWithIconAndRightText( - container, - controller, - settings->showUserMessagesInContextMenu, + auto hideValue = container->lifetime().make_state>(settings->showHideMessageInContextMenu); + rpl::producer hideLabel = hideValue->value() | rpl::map([=](int val) { + return options[val]; + }); + // добавляем кнопку для пункта "Hide" с изменяемым подпунктом + // 4-й параметр - стиль, 5-й - иконка + Settings::AddButtonWithLabel( + container, + tr::ayu_ContextHideMessage(), + hideLabel, + st::settingsButton, + { &st::menuIconClear } + )->addClickHandler([=] { + controller->show(Box([=](not_null box) { + box->setTitle(tr::ayu_SettingsContextMenuTitle()); + box->addButton(tr::lng_box_ok(), [=] { box->closeBox(); }); + const auto group = std::make_shared(hideValue->current()); + const auto layout = box->verticalLayout(); + layout->add(object_ptr( + layout, + st::boxOptionListPadding.top() + st::autolockButton.margin.top())); + int idx = 0; + for (const auto &text : options) { + layout->add( + object_ptr( + layout, + group, + idx++, + text, + st::defaultBoxCheckbox, + st::defaultRadio), + QMargins( + st::boxPadding.left() + st::boxOptionListPadding.left(), + 0, + st::boxPadding.right(), + st::boxOptionListSkip)); + } + const auto check = layout->add( + object_ptr( + layout, + tr::ayu_ShowNearPosts(), + settings->showHideButtonNearPosts, + st::defaultBoxCheckbox), + QMargins( + st::boxPadding.left() + st::boxOptionListPadding.left(), + 0, + st::boxPadding.right(), + st::boxOptionListSkip)); + group->setChangedCallback([=](int index) { + AyuSettings::set_showHideMessageInContextMenu(index); + AyuSettings::save(); + hideValue->force_assign(index); + box->closeBox(); + }); + check->checkedValue() + | rpl::start_with_next([=](bool enabled) { + AyuSettings::set_showHideButtonNearPosts(enabled); + AyuSettings::save(); + }, check->lifetime()); + })); + }); + AddChooseButtonWithIconAndRightText( + container, + controller, + settings->showUserMessagesInContextMenu, options, tr::ayu_UserMessagesMenuText(), tr::ayu_SettingsContextMenuTitle(), diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 586c2033df..029772697c 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -66,6 +66,9 @@ namespace { // A new message from the same sender is attached to previous within 15 minutes. constexpr int kAttachMessageToPreviousSecondsDelta = 900; +// Отступ между правыми кнопками и краем +constexpr auto kRightActionsMargin = 10; +constexpr auto kRightActionsMarginWide = 1; Element *HoveredElement/* = nullptr*/; Element *PressedElement/* = nullptr*/; @@ -1838,6 +1841,11 @@ ClickHandlerPtr Element::rightActionLink( return ClickHandlerPtr(); } +// Заглушка для дополнительной кнопки "глазик" +ClickHandlerPtr Element::viewActionLink( + std::optional pressPoint) const { + return ClickHandlerPtr(); +} TimeId Element::displayedEditDate() const { return TimeId(0); } diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index 34bc8679ce..02cec87b79 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -121,6 +121,9 @@ public: const FullMsgId &context) = 0; virtual void elementHandleViaClick(not_null bot) = 0; virtual ElementChatMode elementChatMode() = 0; + [[nodiscard]] bool elementIsChatWide() { + return elementChatMode() == ElementChatMode::Wide; + } virtual not_null elementPathShiftGradient() = 0; virtual void elementReplyTo(const FullReplyTo &to) = 0; virtual void elementStartInteraction(not_null view) = 0; @@ -552,6 +555,9 @@ public: int outerWidth) const; [[nodiscard]] virtual ClickHandlerPtr rightActionLink( std::optional pressPoint) const; + // Возвращает ссылку для дополнительной кнопки "глазик" + [[nodiscard]] virtual ClickHandlerPtr viewActionLink( + std::optional pressPoint) const; [[nodiscard]] virtual TimeId displayedEditDate() const; [[nodiscard]] virtual bool hasVisibleText() const; [[nodiscard]] int textualMaxWidth() const; diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 708127f9b9..b2f6b470ac 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -55,12 +55,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL // AyuGram includes #include "ayu/features/messageshot/message_shot.h" #include "styles/style_ayu_icons.h" +#include "ayu/ayu_state.h" +#include "ayu/ayu_settings.h" namespace HistoryView { namespace { constexpr auto kPlayStatusLimit = 12; +// Минимальный отступ между кнопкой просмотра и правым краем +constexpr auto kRightActionsMargin = 10; +// Отступ для широких окон, чтобы кнопки стояли чуть правее +constexpr auto kRightActionsMarginWide = 1; const auto kPsaTooltipPrefix = "cloud_lng_tooltip_psa_"; class KeyboardStyle : public ReplyKeyboard::Style { @@ -401,6 +407,10 @@ struct Message::RightAction { ClickHandlerPtr link; QPoint lastPoint; std::unique_ptr second; + // Дополнительные элементы для кнопки с глазиком + std::unique_ptr viewRipple; + ClickHandlerPtr viewLink; + QPoint viewLastPoint; }; LogEntryOriginal::LogEntryOriginal() = default; @@ -1562,9 +1572,12 @@ void Message::draw(Painter &p, const PaintContext &context) const { (g.height() - size->height()) / 2, 0, st::historyFastShareBottom); + const auto margin = delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; const auto fastShareLeft = hasRightLayout() ? (g.left() - size->width() - st::historyFastShareLeft) - : (g.left() + g.width() + st::historyFastShareLeft); + : (g.left() + g.width() + st::historyFastShareLeft - margin); const auto fastShareTop = data()->isSponsored() ? g.top() + fastShareSkip : g.top() + g.height() - fastShareSkip - size->height(); @@ -1639,7 +1652,7 @@ void Message::draw(Painter &p, const PaintContext &context) const { const auto outerWidth = st::historySwipeIconSkip + (isLeftSize ? rect::right(g) : width()) + ((g.height() < size * kMaxHeightRatio) - ? rightActionSize().value_or(QSize()).width() + ? rightActionSize().value_or(QSize()).width() * 2 : 0); const auto shift = std::min( (size * kShiftRatio * context.gestureHorizontal.ratio), @@ -2328,6 +2341,8 @@ void Message::clickHandlerPressedChanged( return; } else if (_rightAction && (handler == _rightAction->link)) { toggleRightActionRipple(pressed); + } else if (_rightAction && (handler == _rightAction->viewLink)) { + toggleViewActionRipple(pressed); } else if (_rightAction && _rightAction->second && (handler == _rightAction->second->link)) { @@ -2399,6 +2414,26 @@ void Message::toggleRightActionRipple(bool pressed) { } } +// Ripple для дополнительной кнопки +void Message::toggleViewActionRipple(bool pressed) { + Expects(_rightAction != nullptr); + + const auto rightSize = rightActionSize(); + Assert(rightSize != std::nullopt); + + if (pressed) { + if (!_rightAction->viewRipple) { + _rightAction->viewRipple = std::make_unique( + st::defaultRippleAnimation, + Ui::RippleAnimation::RoundRectMask(*rightSize, rightSize->width() / 2), + [=] { repaint(); }); + } + _rightAction->viewRipple->add(_rightAction->viewLastPoint); + } else if (_rightAction->viewRipple) { + _rightAction->viewRipple->lastStop(); + } +} + void Message::toggleReplyRipple(bool pressed) { const auto reply = Get(); if (!reply) { @@ -2823,20 +2858,33 @@ TextState Message::textState( (g.height() - size->height()) / 2, 0, st::historyFastShareBottom); + const auto margin = delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; const auto fastShareLeft = hasRightLayout() ? (g.left() - size->width() - st::historyFastShareLeft) - : (g.left() + g.width() + st::historyFastShareLeft); + : (g.left() + g.width() + st::historyFastShareLeft - margin); const auto fastShareTop = data()->isSponsored() ? g.top() + fastShareSkip : g.top() + g.height() - fastShareSkip - size->height(); - if (QRect( + const auto fastShareRect = QRect( fastShareLeft, fastShareTop, size->width(), - size->height() - ).contains(point)) { + size->height()); + if (fastShareRect.contains(point)) { result.link = rightActionLink(point - QPoint(fastShareLeft, fastShareTop)); + } else if (AyuSettings::getInstance().showHideButtonNearPosts) { + const auto viewRect = QRect( + fastShareLeft + size->width() + st::historyFastShareLeft, + fastShareTop, + size->width(), + size->height()); + if (viewRect.contains(point)) { + result.link = viewActionLink(point + - QPoint(viewRect.x(), fastShareTop)); + } } } } else if (media && media->isDisplayed()) { @@ -3687,6 +3735,12 @@ void Message::refreshDataIdHook() { if (_rightAction && base::take(_rightAction->link)) { _rightAction->link = rightActionLink(_rightAction->lastPoint); } + if (AyuSettings::getInstance().showHideButtonNearPosts + && _rightAction && base::take(_rightAction->viewLink)) { + _rightAction->viewLink = viewActionLink(_rightAction->viewLastPoint); + } else if (_rightAction) { + _rightAction->viewLink = nullptr; + } if (base::take(_fastReplyLink)) { _fastReplyLink = fastReplyLink(); } @@ -4089,6 +4143,7 @@ void Message::drawRightAction( const auto size = rightActionSize(); const auto st = context.st; + const auto showEye = AyuSettings::getInstance().showHideButtonNearPosts; if (_rightAction->ripple) { const auto &stm = context.messageStyle(); @@ -4103,6 +4158,19 @@ void Message::drawRightAction( _rightAction->ripple.reset(); } } + if (showEye && _rightAction->viewRipple) { + const auto &stm = context.messageStyle(); + const auto colorOverride = &stm->msgWaveformInactive->c; + _rightAction->viewRipple->paint( + p, + left + size->width() + st::historyFastShareLeft, + top, + size->width(), + colorOverride); + if (_rightAction->viewRipple->empty()) { + _rightAction->viewRipple.reset(); + } + } if (_rightAction->second && _rightAction->second->ripple) { const auto &stm = context.messageStyle(); const auto colorOverride = &stm->msgWaveformInactive->c; @@ -4134,6 +4202,22 @@ void Message::drawRightAction( p.drawRoundedRect(rect, usual / 2, usual / 2); } } + // Фон для второй кнопки с глазиком + if (showEye) { + PainterHighQualityEnabler hq(p); + const auto rect = style::rtlrect( + left + size->width() + st::historyFastShareLeft, + top, + size->width(), + size->height(), + outerWidth); + const auto usual = st::historyFastShareSize; + if (size->width() == size->height() && size->width() == usual) { + p.drawEllipse(rect); + } else { + p.drawRoundedRect(rect, usual / 2, usual / 2); + } + } if (displayRightActionComments()) { const auto &icon = st->historyFastCommentsIcon(); icon.paint( @@ -4169,6 +4253,15 @@ void Message::drawRightAction( ? st->historyFastShareIcon() : st->historyGoToOriginalIcon(); icon.paintInCenter(p, Rect(left, top, *size)); + // Рисуем копию с глазиком правее исходной кнопки + if (showEye) { + const auto &viewIcon = st->historyFastViewIcon(); + viewIcon.paintInCenter( + p, + Rect(left + size->width() + st::historyFastShareLeft, + top, + *size)); + } } } @@ -4191,6 +4284,43 @@ ClickHandlerPtr Message::rightActionLink( return _rightAction->link; } +// Возвращает ссылку для кнопки с глазиком +// Теперь она скрывает выбранное сообщение, как пункт "Hide" в контекстном меню +ClickHandlerPtr Message::viewActionLink( + std::optional pressPoint) const { + if (delegate()->elementInSelectionMode(this).progress > 0) { + return nullptr; + } + if (!AyuSettings::getInstance().showHideButtonNearPosts) { + return nullptr; + } + ensureRightAction(); + if (!_rightAction->viewLink) { + const auto sessionId = data()->history()->session().uniqueId(); + const auto owner = &data()->history()->owner(); + const auto ids = owner->itemOrItsGroup(data()); // список всех сообщений в группе + const auto history = data()->history(); + + _rightAction->viewLink = std::make_shared([=](ClickContext context) { + const auto controller = ExtractController(context); + if (!controller || controller->session().uniqueId() != sessionId) { + return; + } + // Для альбомов скрываем каждое сообщение группы + for (const auto &fullId : ids) { + if (const auto item = owner->message(fullId)) { + item->destroy(); + AyuState::hide(item); + } + } + history->requestChatListMessage(); + }); + } + if (pressPoint) { + _rightAction->viewLastPoint = *pressPoint; + } + return _rightAction->viewLink; +} void Message::ensureRightAction() const { if (_rightAction) { return; @@ -4442,9 +4572,16 @@ QRect Message::innerGeometry() const { const auto w = std::max( (media() ? media()->resolveCustomInfoRightBottom().x() : 0), result.width()); - result.setWidth(std::min( - w + rightActionSize().value_or(QSize(0, 0)).width() * 2, - width())); + // Учитываем две кнопки и дополнительный отступ от правого края + const auto margin = hasRightLayout() ? 0 + : (delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin); + const auto eye = AyuSettings::getInstance().showHideButtonNearPosts ? 2 : 1; + const auto actionsWidth = rightActionSize().value_or(QSize()).width() * eye + + st::historyFastShareLeft * eye + margin; + const auto extra = std::max(actionsWidth - st::msgMargin.right(), 0); + result.setWidth(std::min(w + extra, width())); } if (hasBubble()) { const auto cut = [&](int amount) { @@ -4488,9 +4625,7 @@ QRect Message::countGeometry() const { ? media->width() : width(); const auto outbg = hasOutLayout(); - const auto useMoreSpace = (delegate()->elementChatMode() - == ElementChatMode::Narrow); - const auto wideSkip = useMoreSpace + const auto wideSkip = delegate()->elementIsChatWide() ? st::msgMargin.left() : st::msgMargin.right(); const auto availableWidth = width() @@ -4500,12 +4635,23 @@ QRect Message::countGeometry() const { auto contentWidth = availableWidth; if (hasFromPhoto()) { contentLeft += st::msgPhotoSkip; - if (const auto size = rightActionSize()) { - contentWidth -= size->width() + (st::msgPhotoSkip - st::historyFastShareSize); - } - //} else if (!Adaptive::Wide() && !out() && !fromChannel() && st::msgPhotoSkip - (hmaxwidth - hwidth) > 0) { - // contentLeft += st::msgPhotoSkip - (hmaxwidth - hwidth); } + if (const auto size = rightActionSize()) { + // Ширина двух кнопок и отступ от правого края + const auto margin = hasRightLayout() ? 0 + : (delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin); + const auto eye = AyuSettings::getInstance().showHideButtonNearPosts ? 2 : 1; + const auto actionsWidth = size->width() * eye + st::historyFastShareLeft * eye + margin; + // Отнимаем только разницу между необходимым и уже заложенным отступом + const auto extra = std::max(actionsWidth - st::msgMargin.right(), 0); + contentWidth -= extra; + if (hasFromPhoto()) { + // Для сообщений с аватаркой учитываем дополнительное смещение + contentWidth -= (st::msgPhotoSkip - st::historyFastShareSize); + } + } accumulate_min(contentWidth, maxWidth()); accumulate_min(contentWidth, int(_bubbleWidthLimit)); if (mediaWidth < contentWidth) { @@ -4622,17 +4768,21 @@ int Message::resizeContentGetHeight(int newWidth) { // This code duplicates countGeometry() but also resizes media. const auto centeredView = item->isFakeAboutView() || (context() == Context::Replies && item->isDiscussionPost()); - const auto useMoreSpace = (delegate()->elementChatMode() - == ElementChatMode::Narrow); - const auto wideSkip = useMoreSpace - ? st::msgMargin.left() - : st::msgMargin.right(); auto contentWidth = newWidth - st::msgMargin.left() - - (centeredView ? st::msgMargin.left() : wideSkip); + - (centeredView ? st::msgMargin.left() : st::msgMargin.right()); + if (const auto size = rightActionSize()) { + const auto margin = hasRightLayout() ? 0 + : (delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin); + const auto eye = AyuSettings::getInstance().showHideButtonNearPosts ? 2 : 1; + const auto actionsWidth = size->width() * eye + st::historyFastShareLeft * eye + margin; + const auto extra = std::max(actionsWidth - st::msgMargin.right(), 0); + contentWidth -= extra; if (hasFromPhoto()) { - if (const auto size = rightActionSize()) { - contentWidth -= size->width() + (st::msgPhotoSkip - st::historyFastShareSize); + // Учёт области под аватарку + contentWidth -= (st::msgPhotoSkip - st::historyFastShareSize); } } accumulate_min(contentWidth, maxWidth()); diff --git a/Telegram/SourceFiles/history/view/history_view_message.h b/Telegram/SourceFiles/history/view/history_view_message.h index ad3dfd226e..456fc48bb8 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.h +++ b/Telegram/SourceFiles/history/view/history_view_message.h @@ -139,6 +139,8 @@ public: int outerWidth) const override; [[nodiscard]] ClickHandlerPtr rightActionLink( std::optional pressPoint) const override; + [[nodiscard]] ClickHandlerPtr viewActionLink( + std::optional pressPoint) const override; [[nodiscard]] TimeId displayedEditDate() const override; [[nodiscard]] bool toggleSelectionByHandlerClick( const ClickHandlerPtr &handler) const override; @@ -197,6 +199,7 @@ private: void createTopicButtonRipple(); void toggleRightActionRipple(bool pressed); + void toggleViewActionRipple(bool pressed); void toggleReplyRipple(bool pressed); diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 802d55e244..56314ebc13 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -72,6 +72,8 @@ namespace { constexpr auto kMaxGifForwardedBarLines = 4; constexpr auto kUseNonBlurredThreshold = 240; constexpr auto kMaxInlineArea = 1920 * 1080; +constexpr auto kRightActionsMargin = 10; +constexpr auto kRightActionsMarginWide = 1; [[nodiscard]] int GifMaxStatusWidth(not_null document) { auto result = st::normalFont->width( @@ -851,15 +853,18 @@ void Gif::draw(Painter &p, const PaintContext &context) const { const auto rightActionWidth = size ? size->width() : _transcribe->size().width(); + const auto margin = _parent->delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; auto fastShareLeft = rightLayout ? (paintx + usex - size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); + : (fullRight + st::historyFastShareLeft - margin); auto fastShareTop = fullBottom - st::historyFastShareBottom - (size ? size->height() : 0); - if (fastShareLeft + rightActionWidth > maxRight) { + if (fastShareLeft + rightActionWidth * 2 > maxRight) { fastShareLeft = fullRight - - rightActionWidth + - rightActionWidth * 2 - st::msgDateImgDelta; fastShareTop -= st::msgDateImgDelta + st::msgDateImgPadding.y() @@ -1335,24 +1340,40 @@ TextState Gif::textState(QPoint point, StateRequest request) const { } if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { const auto rightActionWidth = size->width(); + const auto margin = _parent->delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; auto fastShareLeft = _parent->hasRightLayout() ? (paintx + usex - size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); + : (fullRight + st::historyFastShareLeft - margin); auto fastShareTop = fullBottom - st::historyFastShareBottom - size->height(); - if (fastShareLeft + rightActionWidth > maxRight) { + if (fastShareLeft + rightActionWidth * 2 > maxRight) { fastShareLeft = fullRight - - rightActionWidth + - rightActionWidth * 2 - st::msgDateImgDelta; fastShareTop -= st::msgDateImgDelta + st::msgDateImgPadding.y() + st::msgDateFont->height + st::msgDateImgPadding.y(); } - if (QRect(QPoint(fastShareLeft, fastShareTop), *size).contains(point)) { + const auto fastShareRect = QRect( + fastShareLeft, + fastShareTop, + size->width(), + size->height()); + const auto viewRect = QRect( + fastShareLeft + size->width() + st::historyFastShareLeft, + fastShareTop, + size->width(), + size->height()); + if (fastShareRect.contains(point)) { result.link = _parent->rightActionLink(point - QPoint(fastShareLeft, fastShareTop)); + } else if (viewRect.contains(point)) { + result.link = _parent->viewActionLink(point + - QPoint(viewRect.x(), fastShareTop)); } } if (_transcribe && _transcribe->contains(point)) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_location.cpp b/Telegram/SourceFiles/history/view/media/history_view_location.cpp index 5b8b18e61b..f8e5b44b7e 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_location.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_location.cpp @@ -28,6 +28,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace HistoryView { namespace { +constexpr auto kRightActionsMargin = 10; +constexpr auto kRightActionsMarginWide = 1; constexpr auto kUntilOffPeriod = std::numeric_limits::max(); constexpr auto kLiveElapsedPartOpacity = 0.2; @@ -464,9 +466,12 @@ void Location::draw(Painter &p, const PaintContext &context) const { paintx * 2 + paintw, InfoDisplayType::Image); if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { + const auto margin = _parent->delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; auto fastShareLeft = _parent->hasRightLayout() ? (paintx - size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); + : (fullRight + st::historyFastShareLeft - margin); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); _parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw); } @@ -669,9 +674,12 @@ TextState Location::textState(QPoint point, StateRequest request) const { return bottomInfoResult; } if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { + const auto margin = _parent->delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; auto fastShareLeft = _parent->hasRightLayout() ? (paintx - size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); + : (fullRight + st::historyFastShareLeft - margin); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) { result.link = _parent->rightActionLink(point diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp index 6b8a133955..71becab0bd 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp @@ -30,6 +30,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace HistoryView { namespace { +constexpr auto kRightActionsMargin = 10; +constexpr auto kRightActionsMarginWide = 1; std::vector LayoutPlaylist( const std::vector &sizes) { Expects(!sizes.empty()); @@ -472,9 +474,12 @@ void GroupedMedia::draw(Painter &p, const PaintContext &context) const { InfoDisplayType::Image); } if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) { + const auto margin = _parent->delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; auto fastShareLeft = _parent->hasRightLayout() ? (-size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); + : (fullRight + st::historyFastShareLeft - margin); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); _parent->drawRightAction(p, context, fastShareLeft, fastShareTop, width()); } @@ -539,13 +544,29 @@ TextState GroupedMedia::textState(QPoint point, StateRequest request) const { return bottomInfoResult; } if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) { + const auto margin = _parent->delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; auto fastShareLeft = _parent->hasRightLayout() ? (-size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); + : (fullRight + st::historyFastShareLeft - margin); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); - if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) { + const auto fastShareRect = QRect( + fastShareLeft, + fastShareTop, + size->width(), + size->height()); + const auto viewRect = QRect( + fastShareLeft + size->width() + st::historyFastShareLeft, + fastShareTop, + size->width(), + size->height()); + if (fastShareRect.contains(point)) { result.link = _parent->rightActionLink(point - QPoint(fastShareLeft, fastShareTop)); + } else if (viewRect.contains(point)) { + result.link = _parent->viewActionLink(point + - QPoint(viewRect.x(), fastShareTop)); } } } diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp index 73adc03cc6..6ad7d1930e 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp @@ -30,6 +30,8 @@ namespace HistoryView { namespace { constexpr auto kMaxForwardedBarLines = 4; +constexpr auto kRightActionsMargin = 10; +constexpr auto kRightActionsMarginWide = 1; } // namespace @@ -520,10 +522,23 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const { fullBottom, fullRight, *rightActionSize); - if (QRect(position.x(), position.y(), rightActionSize->width(), rightActionSize->height()).contains(point)) { + const auto fastShareRect = QRect( + position.x(), + position.y(), + rightActionSize->width(), + rightActionSize->height()); + const auto viewRect = QRect( + position.x() + rightActionSize->width() + st::historyFastShareLeft, + position.y(), + rightActionSize->width(), + rightActionSize->height()); + if (fastShareRect.contains(point)) { result.link = _parent->rightActionLink(point - position); return result; - } + } else if (viewRect.contains(point)) { + result.link = _parent->viewActionLink(point - QPoint(viewRect.x(), position.y())); + return result; + } } } @@ -604,8 +619,8 @@ int UnwrappedMedia::calculateFullRight(const QRect &inner) const { ? st::msgMargin.right() : st::msgPadding.right()); const auto rightActionWidth = rightActionSize - ? (st::historyFastShareLeft * 2 - + rightActionSize->width()) + ? (st::historyFastShareLeft * 3 + + rightActionSize->width() * 2) : 0; auto fullRight = inner.x() + inner.width() @@ -633,12 +648,15 @@ QPoint UnwrappedMedia::calculateFastActionPosition( - size.height()); const auto doesRightActionHitReply = replyRight && (fastShareTop < replyHeight); + const auto margin = _parent->delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; const auto fastShareLeft = rightAligned ? ((doesRightActionHitReply ? replyLeft : inner.x()) - size.width() - st::historyFastShareLeft) : ((doesRightActionHitReply ? replyRight : fullRight) - + st::historyFastShareLeft); + + st::historyFastShareLeft - margin); return QPoint(fastShareLeft, fastShareTop); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index b67f72b2ee..87f5a5c1e5 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -54,6 +54,8 @@ namespace { constexpr auto kStoryWidth = 720; constexpr auto kStoryHeight = 1280; +constexpr auto kRightActionsMargin = 10; +constexpr auto kRightActionsMarginWide = 1; using Data::PhotoSize; @@ -418,9 +420,12 @@ void Photo::draw(Painter &p, const PaintContext &context) const { InfoDisplayType::Image); } if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { + const auto margin = _parent->delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; auto fastShareLeft = _parent->hasRightLayout() ? (paintx - size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); + : (fullRight + st::historyFastShareLeft - margin); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); _parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw); } @@ -700,13 +705,29 @@ TextState Photo::textState(QPoint point, StateRequest request) const { return bottomInfoResult; } if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { + const auto margin = _parent->delegate()->elementIsChatWide() + ? kRightActionsMarginWide + : kRightActionsMargin; auto fastShareLeft = _parent->hasRightLayout() ? (paintx - size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); + : (fullRight + st::historyFastShareLeft - margin); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); - if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) { + const auto fastShareRect = QRect( + fastShareLeft, + fastShareTop, + size->width(), + size->height()); + const auto viewRect = QRect( + fastShareLeft + size->width() + st::historyFastShareLeft, + fastShareTop, + size->width(), + size->height()); + if (fastShareRect.contains(point)) { result.link = _parent->rightActionLink(point - QPoint(fastShareLeft, fastShareTop)); + } else if (viewRect.contains(point)) { + result.link = _parent->viewActionLink(point + - QPoint(viewRect.x(), fastShareTop)); } } } diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index c5d072ac11..97227f6a0b 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -570,6 +570,7 @@ historyFastShareSize: 31px; historyFastShareLeft: 13px; historyFastShareBottom: 5px; historyFastShareIcon: icon {{ "fast_share", msgServiceFg }}; +historyFastViewIcon: icon {{ "history_views", msgServiceFg }}; historyGoToOriginalIcon: icon {{ "filled_go_to_message", msgServiceFg, point(0px, 0px) }}; historyFastCommentsIcon: icon {{ "fast_comments", msgServiceFg }}; historyFastCloseSize: 30px; diff --git a/Telegram/SourceFiles/ui/chat/chat_style.cpp b/Telegram/SourceFiles/ui/chat/chat_style.cpp index e8a2f4906b..1b005e7e96 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_style.cpp @@ -201,6 +201,7 @@ ChatStyle::ChatStyle(rpl::producer colorIndices) { make(_msgBotKbCopyIcon, st::msgBotKbCopyIcon); make(_historyFastCommentsIcon, st::historyFastCommentsIcon); make(_historyFastShareIcon, st::historyFastShareIcon); + make(_historyFastViewIcon, st::historyFastViewIcon); make(_historyFastTranscribeIcon, st::historyFastTranscribeIcon); make(_historyFastTranscribeLock, st::historyFastTranscribeLock); make(_historyGoToOriginalIcon, st::historyGoToOriginalIcon); diff --git a/Telegram/SourceFiles/ui/chat/chat_style.h b/Telegram/SourceFiles/ui/chat/chat_style.h index 4e75c5cecf..2f3293392e 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.h +++ b/Telegram/SourceFiles/ui/chat/chat_style.h @@ -407,6 +407,9 @@ public: [[nodiscard]] const style::icon &historyFastShareIcon() const { return _historyFastShareIcon; } + [[nodiscard]] const style::icon &historyFastViewIcon() const { + return _historyFastViewIcon; + } [[nodiscard]] const style::icon &historyFastTranscribeIcon() const { return _historyFastTranscribeIcon; } @@ -546,6 +549,7 @@ private: style::icon _msgBotKbCopyIcon = { Qt::Uninitialized }; style::icon _historyFastCommentsIcon = { Qt::Uninitialized }; style::icon _historyFastShareIcon = { Qt::Uninitialized }; + style::icon _historyFastViewIcon = { Qt::Uninitialized }; style::icon _historyFastMoreIcon = { Qt::Uninitialized }; style::icon _historyFastTranscribeIcon = { Qt::Uninitialized }; style::icon _historyFastTranscribeLock = { Qt::Uninitialized };