Hide button near posts in channels

This commit is contained in:
Neurotoxin001 2025-07-04 03:27:40 +03:00
parent 3be793032f
commit ea4bc18d3f
16 changed files with 504 additions and 115 deletions

View file

@ -6891,6 +6891,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_ContextCopyID" = "Copy ID"; "ayu_ContextCopyID" = "Copy ID";
"ayu_IDCopiedToast" = "ID copied to clipboard."; "ayu_IDCopiedToast" = "ID copied to clipboard.";
"ayu_ContextHideMessage" = "Hide"; "ayu_ContextHideMessage" = "Hide";
"ayu_ShowNearPosts" = "Show Near Posts";
"ayu_ContextCopyCallbackData" = "Copy Callback Data"; "ayu_ContextCopyCallbackData" = "Copy Callback Data";
"ayu_RegisterURLScheme" = "Register URL Scheme"; "ayu_RegisterURLScheme" = "Register URL Scheme";
"ayu_SessionTerminated" = "Session **{item}** was terminated. You may still browse cached messages."; "ayu_SessionTerminated" = "Session **{item}** was terminated. You may still browse cached messages.";

View file

@ -295,6 +295,8 @@ AyuGramSettings::AyuGramSettings() {
showMessageSeconds = false; showMessageSeconds = false;
showMessageShot = true; showMessageShot = true;
showHideButtonNearPosts = true;
// ~ Confirmations // ~ Confirmations
stickerConfirmation = false; stickerConfirmation = false;
gifConfirmation = false; gifConfirmation = false;
@ -555,6 +557,10 @@ void set_showMessageShot(bool val) {
settings->showMessageShot = val; settings->showMessageShot = val;
} }
void set_showHideButtonNearPosts(bool val) {
settings->showHideButtonNearPosts = val;
}
void set_stickerConfirmation(bool val) { void set_stickerConfirmation(bool val) {
settings->stickerConfirmation = val; settings->stickerConfirmation = val;
} }

View file

@ -92,6 +92,7 @@ public:
bool showMessageSeconds; bool showMessageSeconds;
bool showMessageShot; bool showMessageShot;
bool showHideButtonNearPosts;
bool stickerConfirmation; bool stickerConfirmation;
bool gifConfirmation; bool gifConfirmation;
bool voiceConfirmation; bool voiceConfirmation;
@ -174,72 +175,138 @@ void set_showPeerId(int val);
void set_showMessageSeconds(bool val); void set_showMessageSeconds(bool val);
void set_showMessageShot(bool val); void set_showMessageShot(bool val);
void set_showHideButtonNearPosts(bool val);
void set_stickerConfirmation(bool val); void set_stickerConfirmation(bool val);
void set_gifConfirmation(bool val); void set_gifConfirmation(bool val);
void set_voiceConfirmation(bool val); void set_voiceConfirmation(bool val);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( inline void to_json(nlohmann::json &nlohmann_json_j, const AyuGramSettings &nlohmann_json_t) {
AyuGramSettings, NLOHMANN_JSON_TO(sendReadMessages)
sendReadMessages, NLOHMANN_JSON_TO(sendReadStories)
sendReadStories, NLOHMANN_JSON_TO(sendOnlinePackets)
sendOnlinePackets, NLOHMANN_JSON_TO(sendUploadProgress)
sendUploadProgress, NLOHMANN_JSON_TO(sendOfflinePacketAfterOnline)
sendOfflinePacketAfterOnline, NLOHMANN_JSON_TO(markReadAfterAction)
markReadAfterAction, NLOHMANN_JSON_TO(useScheduledMessages)
useScheduledMessages, NLOHMANN_JSON_TO(sendWithoutSound)
sendWithoutSound, NLOHMANN_JSON_TO(saveDeletedMessages)
saveDeletedMessages, NLOHMANN_JSON_TO(saveMessagesHistory)
saveMessagesHistory, NLOHMANN_JSON_TO(saveForBots)
saveForBots, NLOHMANN_JSON_TO(hideFromBlocked)
hideFromBlocked, NLOHMANN_JSON_TO(disableAds)
disableAds, NLOHMANN_JSON_TO(disableStories)
disableStories, NLOHMANN_JSON_TO(disableCustomBackgrounds)
disableCustomBackgrounds, NLOHMANN_JSON_TO(showOnlyAddedEmojisAndStickers)
showOnlyAddedEmojisAndStickers, NLOHMANN_JSON_TO(collapseSimilarChannels)
collapseSimilarChannels, NLOHMANN_JSON_TO(hideSimilarChannels)
hideSimilarChannels, NLOHMANN_JSON_TO(wideMultiplier)
wideMultiplier, NLOHMANN_JSON_TO(spoofWebviewAsAndroid)
spoofWebviewAsAndroid, NLOHMANN_JSON_TO(increaseWebviewHeight)
increaseWebviewHeight, NLOHMANN_JSON_TO(increaseWebviewWidth)
increaseWebviewWidth, NLOHMANN_JSON_TO(disableNotificationsDelay)
disableNotificationsDelay, NLOHMANN_JSON_TO(localPremium)
localPremium, NLOHMANN_JSON_TO(appIcon)
appIcon, NLOHMANN_JSON_TO(simpleQuotesAndReplies)
simpleQuotesAndReplies, NLOHMANN_JSON_TO(replaceBottomInfoWithIcons)
replaceBottomInfoWithIcons, NLOHMANN_JSON_TO(deletedMark)
deletedMark, NLOHMANN_JSON_TO(editedMark)
editedMark, NLOHMANN_JSON_TO(recentStickersCount)
recentStickersCount, NLOHMANN_JSON_TO(showReactionsPanelInContextMenu)
showReactionsPanelInContextMenu, NLOHMANN_JSON_TO(showViewsPanelInContextMenu)
showViewsPanelInContextMenu, NLOHMANN_JSON_TO(showHideMessageInContextMenu)
showHideMessageInContextMenu, NLOHMANN_JSON_TO(showUserMessagesInContextMenu)
showUserMessagesInContextMenu, NLOHMANN_JSON_TO(showMessageDetailsInContextMenu)
showMessageDetailsInContextMenu, NLOHMANN_JSON_TO(showAttachButtonInMessageField)
showAttachButtonInMessageField, NLOHMANN_JSON_TO(showCommandsButtonInMessageField)
showCommandsButtonInMessageField, NLOHMANN_JSON_TO(showEmojiButtonInMessageField)
showEmojiButtonInMessageField, NLOHMANN_JSON_TO(showMicrophoneButtonInMessageField)
showMicrophoneButtonInMessageField, NLOHMANN_JSON_TO(showAutoDeleteButtonInMessageField)
showAutoDeleteButtonInMessageField, NLOHMANN_JSON_TO(showAttachPopup)
showAttachPopup, NLOHMANN_JSON_TO(showEmojiPopup)
showEmojiPopup, NLOHMANN_JSON_TO(showLReadToggleInDrawer)
showLReadToggleInDrawer, NLOHMANN_JSON_TO(showSReadToggleInDrawer)
showSReadToggleInDrawer, NLOHMANN_JSON_TO(showGhostToggleInDrawer)
showGhostToggleInDrawer, NLOHMANN_JSON_TO(showStreamerToggleInDrawer)
showStreamerToggleInDrawer, NLOHMANN_JSON_TO(showGhostToggleInTray)
showGhostToggleInTray, NLOHMANN_JSON_TO(showStreamerToggleInTray)
showStreamerToggleInTray, NLOHMANN_JSON_TO(monoFont)
monoFont, NLOHMANN_JSON_TO(hideNotificationCounters)
hideNotificationCounters, NLOHMANN_JSON_TO(hideNotificationBadge)
hideNotificationBadge, NLOHMANN_JSON_TO(hideAllChatsFolder)
hideAllChatsFolder, NLOHMANN_JSON_TO(channelBottomButton)
channelBottomButton, NLOHMANN_JSON_TO(showPeerId)
showPeerId, NLOHMANN_JSON_TO(showMessageSeconds)
showMessageSeconds, NLOHMANN_JSON_TO(showMessageShot)
showMessageShot, NLOHMANN_JSON_TO(stickerConfirmation)
stickerConfirmation, NLOHMANN_JSON_TO(showHideButtonNearPosts)
gifConfirmation, NLOHMANN_JSON_TO(gifConfirmation)
voiceConfirmation NLOHMANN_JSON_TO(voiceConfirmation)
); }
inline void from_json(const nlohmann::json &nlohmann_json_j, AyuGramSettings &nlohmann_json_t) {
const AyuGramSettings nlohmann_json_default_obj{};
NLOHMANN_JSON_FROM_WITH_DEFAULT(sendReadMessages)
NLOHMANN_JSON_FROM_WITH_DEFAULT(sendReadStories)
NLOHMANN_JSON_FROM_WITH_DEFAULT(sendOnlinePackets)
NLOHMANN_JSON_FROM_WITH_DEFAULT(sendUploadProgress)
NLOHMANN_JSON_FROM_WITH_DEFAULT(sendOfflinePacketAfterOnline)
NLOHMANN_JSON_FROM_WITH_DEFAULT(markReadAfterAction)
NLOHMANN_JSON_FROM_WITH_DEFAULT(useScheduledMessages)
NLOHMANN_JSON_FROM_WITH_DEFAULT(sendWithoutSound)
NLOHMANN_JSON_FROM_WITH_DEFAULT(saveDeletedMessages)
NLOHMANN_JSON_FROM_WITH_DEFAULT(saveMessagesHistory)
NLOHMANN_JSON_FROM_WITH_DEFAULT(saveForBots)
NLOHMANN_JSON_FROM_WITH_DEFAULT(hideFromBlocked)
NLOHMANN_JSON_FROM_WITH_DEFAULT(disableAds)
NLOHMANN_JSON_FROM_WITH_DEFAULT(disableStories)
NLOHMANN_JSON_FROM_WITH_DEFAULT(disableCustomBackgrounds)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showOnlyAddedEmojisAndStickers)
NLOHMANN_JSON_FROM_WITH_DEFAULT(collapseSimilarChannels)
NLOHMANN_JSON_FROM_WITH_DEFAULT(hideSimilarChannels)
NLOHMANN_JSON_FROM_WITH_DEFAULT(wideMultiplier)
NLOHMANN_JSON_FROM_WITH_DEFAULT(spoofWebviewAsAndroid)
NLOHMANN_JSON_FROM_WITH_DEFAULT(increaseWebviewHeight)
NLOHMANN_JSON_FROM_WITH_DEFAULT(increaseWebviewWidth)
NLOHMANN_JSON_FROM_WITH_DEFAULT(disableNotificationsDelay)
NLOHMANN_JSON_FROM_WITH_DEFAULT(localPremium)
NLOHMANN_JSON_FROM_WITH_DEFAULT(appIcon)
NLOHMANN_JSON_FROM_WITH_DEFAULT(simpleQuotesAndReplies)
NLOHMANN_JSON_FROM_WITH_DEFAULT(replaceBottomInfoWithIcons)
NLOHMANN_JSON_FROM_WITH_DEFAULT(deletedMark)
NLOHMANN_JSON_FROM_WITH_DEFAULT(editedMark)
NLOHMANN_JSON_FROM_WITH_DEFAULT(recentStickersCount)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showReactionsPanelInContextMenu)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showViewsPanelInContextMenu)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showHideMessageInContextMenu)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showUserMessagesInContextMenu)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showMessageDetailsInContextMenu)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showAttachButtonInMessageField)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showCommandsButtonInMessageField)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showEmojiButtonInMessageField)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showMicrophoneButtonInMessageField)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showAutoDeleteButtonInMessageField)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showAttachPopup)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showEmojiPopup)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showLReadToggleInDrawer)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showSReadToggleInDrawer)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showGhostToggleInDrawer)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showStreamerToggleInDrawer)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showGhostToggleInTray)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showStreamerToggleInTray)
NLOHMANN_JSON_FROM_WITH_DEFAULT(monoFont)
NLOHMANN_JSON_FROM_WITH_DEFAULT(hideNotificationCounters)
NLOHMANN_JSON_FROM_WITH_DEFAULT(hideNotificationBadge)
NLOHMANN_JSON_FROM_WITH_DEFAULT(hideAllChatsFolder)
NLOHMANN_JSON_FROM_WITH_DEFAULT(channelBottomButton)
NLOHMANN_JSON_FROM_WITH_DEFAULT(showPeerId)
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)
}
AyuGramSettings &getInstance(); AyuGramSettings &getInstance();

View file

@ -21,6 +21,7 @@
#include "styles/style_chat_helpers.h" #include "styles/style_chat_helpers.h"
#include "styles/style_ayu_styles.h" #include "styles/style_ayu_styles.h"
#include "styles/style_basic.h" #include "styles/style_basic.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
@ -894,23 +895,71 @@ void SetupContextMenuElements(not_null<Ui::VerticalLayout*> container,
AyuSettings::save(); AyuSettings::save();
}); });
AddChooseButtonWithIconAndRightText( auto hideValue = container->lifetime().make_state<rpl::variable<int>>(settings.showHideMessageInContextMenu);
container, rpl::producer<QString> hideLabel = hideValue->value() | rpl::map([=](int val) {
controller, return options[val];
settings.showHideMessageInContextMenu, });
options, // добавляем кнопку для пункта "Hide" с изменяемым подпунктом
tr::ayu_ContextHideMessage(), // 4-й параметр - стиль, 5-й - иконка
tr::ayu_SettingsContextMenuTitle(), Settings::AddButtonWithLabel(
st::menuIconClear, container,
[=](int index) tr::ayu_ContextHideMessage(),
{ hideLabel,
AyuSettings::set_showHideMessageInContextMenu(index); st::settingsButton,
AyuSettings::save(); { &st::menuIconClear }
}); )->addClickHandler([=] {
AddChooseButtonWithIconAndRightText( controller->show(Box([=](not_null<Ui::GenericBox*> box) {
container, box->setTitle(tr::ayu_SettingsContextMenuTitle());
controller, box->addButton(tr::lng_box_ok(), [=] { box->closeBox(); });
settings.showUserMessagesInContextMenu, const auto group = std::make_shared<Ui::RadiobuttonGroup>(hideValue->current());
const auto layout = box->verticalLayout();
layout->add(object_ptr<Ui::FixedHeightWidget>(
layout,
st::boxOptionListPadding.top() + st::autolockButton.margin.top()));
int idx = 0;
for (const auto &text : options) {
layout->add(
object_ptr<Ui::Radiobutton>(
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<Ui::Checkbox>(
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, options,
tr::ayu_UserMessagesMenuText(), tr::ayu_UserMessagesMenuText(),
tr::ayu_SettingsContextMenuTitle(), tr::ayu_SettingsContextMenuTitle(),

View file

@ -61,6 +61,9 @@ namespace {
// A new message from the same sender is attached to previous within 15 minutes. // A new message from the same sender is attached to previous within 15 minutes.
constexpr int kAttachMessageToPreviousSecondsDelta = 900; constexpr int kAttachMessageToPreviousSecondsDelta = 900;
// Отступ между правыми кнопками и краем
constexpr auto kRightActionsMargin = 10;
constexpr auto kRightActionsMarginWide = 1;
Element *HoveredElement/* = nullptr*/; Element *HoveredElement/* = nullptr*/;
Element *PressedElement/* = nullptr*/; Element *PressedElement/* = nullptr*/;
@ -1590,6 +1593,11 @@ ClickHandlerPtr Element::rightActionLink(
return ClickHandlerPtr(); return ClickHandlerPtr();
} }
// Заглушка для дополнительной кнопки "глазик"
ClickHandlerPtr Element::viewActionLink(
std::optional<QPoint> pressPoint) const {
return ClickHandlerPtr();
}
TimeId Element::displayedEditDate() const { TimeId Element::displayedEditDate() const {
return TimeId(0); return TimeId(0);
} }

View file

@ -493,6 +493,9 @@ public:
int outerWidth) const; int outerWidth) const;
[[nodiscard]] virtual ClickHandlerPtr rightActionLink( [[nodiscard]] virtual ClickHandlerPtr rightActionLink(
std::optional<QPoint> pressPoint) const; std::optional<QPoint> pressPoint) const;
// Возвращает ссылку для дополнительной кнопки "глазик"
[[nodiscard]] virtual ClickHandlerPtr viewActionLink(
std::optional<QPoint> pressPoint) const;
[[nodiscard]] virtual TimeId displayedEditDate() const; [[nodiscard]] virtual TimeId displayedEditDate() const;
[[nodiscard]] virtual bool hasVisibleText() const; [[nodiscard]] virtual bool hasVisibleText() const;
[[nodiscard]] int textualMaxWidth() const; [[nodiscard]] int textualMaxWidth() const;

View file

@ -51,12 +51,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
// AyuGram includes // AyuGram includes
#include "ayu/features/messageshot/message_shot.h" #include "ayu/features/messageshot/message_shot.h"
#include "styles/style_ayu_icons.h" #include "styles/style_ayu_icons.h"
#include "ayu/ayu_state.h"
#include "ayu/ayu_settings.h"
namespace HistoryView { namespace HistoryView {
namespace { namespace {
constexpr auto kPlayStatusLimit = 12; constexpr auto kPlayStatusLimit = 12;
// Минимальный отступ между кнопкой просмотра и правым краем
constexpr auto kRightActionsMargin = 10;
// Отступ для широких окон, чтобы кнопки стояли чуть правее
constexpr auto kRightActionsMarginWide = 1;
const auto kPsaTooltipPrefix = "cloud_lng_tooltip_psa_"; const auto kPsaTooltipPrefix = "cloud_lng_tooltip_psa_";
class KeyboardStyle : public ReplyKeyboard::Style { class KeyboardStyle : public ReplyKeyboard::Style {
@ -397,6 +403,10 @@ struct Message::RightAction {
ClickHandlerPtr link; ClickHandlerPtr link;
QPoint lastPoint; QPoint lastPoint;
std::unique_ptr<SecondRightAction> second; std::unique_ptr<SecondRightAction> second;
// Дополнительные элементы для кнопки с глазиком
std::unique_ptr<Ui::RippleAnimation> viewRipple;
ClickHandlerPtr viewLink;
QPoint viewLastPoint;
}; };
LogEntryOriginal::LogEntryOriginal() = default; LogEntryOriginal::LogEntryOriginal() = default;
@ -1506,9 +1516,12 @@ void Message::draw(Painter &p, const PaintContext &context) const {
(g.height() - size->height()) / 2, (g.height() - size->height()) / 2,
0, 0,
st::historyFastShareBottom); st::historyFastShareBottom);
const auto margin = delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
const auto fastShareLeft = hasRightLayout() const auto fastShareLeft = hasRightLayout()
? (g.left() - size->width() - st::historyFastShareLeft) ? (g.left() - size->width() - st::historyFastShareLeft)
: (g.left() + g.width() + st::historyFastShareLeft); : (g.left() + g.width() + st::historyFastShareLeft - margin);
const auto fastShareTop = data()->isSponsored() const auto fastShareTop = data()->isSponsored()
? g.top() + fastShareSkip ? g.top() + fastShareSkip
: g.top() + g.height() - fastShareSkip - size->height(); : g.top() + g.height() - fastShareSkip - size->height();
@ -1583,7 +1596,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
const auto outerWidth = st::historySwipeIconSkip const auto outerWidth = st::historySwipeIconSkip
+ (isLeftSize ? rect::right(g) : width()) + (isLeftSize ? rect::right(g) : width())
+ ((g.height() < size * kMaxHeightRatio) + ((g.height() < size * kMaxHeightRatio)
? rightActionSize().value_or(QSize()).width() ? rightActionSize().value_or(QSize()).width() * 2
: 0); : 0);
const auto shift = std::min( const auto shift = std::min(
(size * kShiftRatio * context.gestureHorizontal.ratio), (size * kShiftRatio * context.gestureHorizontal.ratio),
@ -2271,6 +2284,8 @@ void Message::clickHandlerPressedChanged(
return; return;
} else if (_rightAction && (handler == _rightAction->link)) { } else if (_rightAction && (handler == _rightAction->link)) {
toggleRightActionRipple(pressed); toggleRightActionRipple(pressed);
} else if (_rightAction && (handler == _rightAction->viewLink)) {
toggleViewActionRipple(pressed);
} else if (_rightAction } else if (_rightAction
&& _rightAction->second && _rightAction->second
&& (handler == _rightAction->second->link)) { && (handler == _rightAction->second->link)) {
@ -2342,6 +2357,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<Ui::RippleAnimation>(
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) { void Message::toggleReplyRipple(bool pressed) {
const auto reply = Get<Reply>(); const auto reply = Get<Reply>();
if (!reply) { if (!reply) {
@ -2762,20 +2797,33 @@ TextState Message::textState(
(g.height() - size->height()) / 2, (g.height() - size->height()) / 2,
0, 0,
st::historyFastShareBottom); st::historyFastShareBottom);
const auto margin = delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
const auto fastShareLeft = hasRightLayout() const auto fastShareLeft = hasRightLayout()
? (g.left() - size->width() - st::historyFastShareLeft) ? (g.left() - size->width() - st::historyFastShareLeft)
: (g.left() + g.width() + st::historyFastShareLeft); : (g.left() + g.width() + st::historyFastShareLeft - margin);
const auto fastShareTop = data()->isSponsored() const auto fastShareTop = data()->isSponsored()
? g.top() + fastShareSkip ? g.top() + fastShareSkip
: g.top() + g.height() - fastShareSkip - size->height(); : g.top() + g.height() - fastShareSkip - size->height();
if (QRect( const auto fastShareRect = QRect(
fastShareLeft, fastShareLeft,
fastShareTop, fastShareTop,
size->width(), size->width(),
size->height() size->height());
).contains(point)) { if (fastShareRect.contains(point)) {
result.link = rightActionLink(point result.link = rightActionLink(point
- QPoint(fastShareLeft, fastShareTop)); - 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()) { } else if (media && media->isDisplayed()) {
@ -3626,6 +3674,12 @@ void Message::refreshDataIdHook() {
if (_rightAction && base::take(_rightAction->link)) { if (_rightAction && base::take(_rightAction->link)) {
_rightAction->link = rightActionLink(_rightAction->lastPoint); _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)) { if (base::take(_fastReplyLink)) {
_fastReplyLink = fastReplyLink(); _fastReplyLink = fastReplyLink();
} }
@ -4021,6 +4075,7 @@ void Message::drawRightAction(
const auto size = rightActionSize(); const auto size = rightActionSize();
const auto st = context.st; const auto st = context.st;
const auto showEye = AyuSettings::getInstance().showHideButtonNearPosts;
if (_rightAction->ripple) { if (_rightAction->ripple) {
const auto &stm = context.messageStyle(); const auto &stm = context.messageStyle();
@ -4035,6 +4090,19 @@ void Message::drawRightAction(
_rightAction->ripple.reset(); _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) { if (_rightAction->second && _rightAction->second->ripple) {
const auto &stm = context.messageStyle(); const auto &stm = context.messageStyle();
const auto colorOverride = &stm->msgWaveformInactive->c; const auto colorOverride = &stm->msgWaveformInactive->c;
@ -4066,6 +4134,22 @@ void Message::drawRightAction(
p.drawRoundedRect(rect, usual / 2, usual / 2); 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()) { if (displayRightActionComments()) {
const auto &icon = st->historyFastCommentsIcon(); const auto &icon = st->historyFastCommentsIcon();
icon.paint( icon.paint(
@ -4101,6 +4185,15 @@ void Message::drawRightAction(
? st->historyFastShareIcon() ? st->historyFastShareIcon()
: st->historyGoToOriginalIcon(); : st->historyGoToOriginalIcon();
icon.paintInCenter(p, Rect(left, top, *size)); 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));
}
} }
} }
@ -4123,6 +4216,43 @@ ClickHandlerPtr Message::rightActionLink(
return _rightAction->link; return _rightAction->link;
} }
// Возвращает ссылку для кнопки с глазиком
// Теперь она скрывает выбранное сообщение, как пункт "Hide" в контекстном меню
ClickHandlerPtr Message::viewActionLink(
std::optional<QPoint> 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<LambdaClickHandler>([=](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 { void Message::ensureRightAction() const {
if (_rightAction) { if (_rightAction) {
return; return;
@ -4374,9 +4504,16 @@ QRect Message::innerGeometry() const {
const auto w = std::max( const auto w = std::max(
(media() ? media()->resolveCustomInfoRightBottom().x() : 0), (media() ? media()->resolveCustomInfoRightBottom().x() : 0),
result.width()); result.width());
result.setWidth(std::min( // Учитываем две кнопки и дополнительный отступ от правого края
w + rightActionSize().value_or(QSize(0, 0)).width() * 2, const auto margin = hasRightLayout() ? 0
width())); : (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()) { if (hasBubble()) {
const auto cut = [&](int amount) { const auto cut = [&](int amount) {
@ -4429,12 +4566,23 @@ QRect Message::countGeometry() const {
auto contentWidth = availableWidth; auto contentWidth = availableWidth;
if (hasFromPhoto()) { if (hasFromPhoto()) {
contentLeft += st::msgPhotoSkip; 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, maxWidth());
accumulate_min(contentWidth, int(_bubbleWidthLimit)); accumulate_min(contentWidth, int(_bubbleWidthLimit));
if (mediaWidth < contentWidth) { if (mediaWidth < contentWidth) {
@ -4553,9 +4701,18 @@ int Message::resizeContentGetHeight(int newWidth) {
auto contentWidth = newWidth auto contentWidth = newWidth
- st::msgMargin.left() - st::msgMargin.left()
- (centeredView ? st::msgMargin.left() : st::msgMargin.right()); - (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 (hasFromPhoto()) {
if (const auto size = rightActionSize()) { // Учёт области под аватарку
contentWidth -= size->width() + (st::msgPhotoSkip - st::historyFastShareSize); contentWidth -= (st::msgPhotoSkip - st::historyFastShareSize);
} }
} }
accumulate_min(contentWidth, maxWidth()); accumulate_min(contentWidth, maxWidth());

View file

@ -139,6 +139,8 @@ public:
int outerWidth) const override; int outerWidth) const override;
[[nodiscard]] ClickHandlerPtr rightActionLink( [[nodiscard]] ClickHandlerPtr rightActionLink(
std::optional<QPoint> pressPoint) const override; std::optional<QPoint> pressPoint) const override;
[[nodiscard]] ClickHandlerPtr viewActionLink(
std::optional<QPoint> pressPoint) const override;
[[nodiscard]] TimeId displayedEditDate() const override; [[nodiscard]] TimeId displayedEditDate() const override;
[[nodiscard]] bool toggleSelectionByHandlerClick( [[nodiscard]] bool toggleSelectionByHandlerClick(
const ClickHandlerPtr &handler) const override; const ClickHandlerPtr &handler) const override;
@ -193,6 +195,7 @@ private:
void createTopicButtonRipple(); void createTopicButtonRipple();
void toggleRightActionRipple(bool pressed); void toggleRightActionRipple(bool pressed);
void toggleViewActionRipple(bool pressed);
void toggleReplyRipple(bool pressed); void toggleReplyRipple(bool pressed);

View file

@ -72,6 +72,8 @@ namespace {
constexpr auto kMaxGifForwardedBarLines = 4; constexpr auto kMaxGifForwardedBarLines = 4;
constexpr auto kUseNonBlurredThreshold = 240; constexpr auto kUseNonBlurredThreshold = 240;
constexpr auto kMaxInlineArea = 1920 * 1080; constexpr auto kMaxInlineArea = 1920 * 1080;
constexpr auto kRightActionsMargin = 10;
constexpr auto kRightActionsMarginWide = 1;
[[nodiscard]] int GifMaxStatusWidth(not_null<DocumentData*> document) { [[nodiscard]] int GifMaxStatusWidth(not_null<DocumentData*> document) {
auto result = st::normalFont->width( auto result = st::normalFont->width(
@ -851,15 +853,18 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
const auto rightActionWidth = size const auto rightActionWidth = size
? size->width() ? size->width()
: _transcribe->size().width(); : _transcribe->size().width();
const auto margin = _parent->delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
auto fastShareLeft = rightLayout auto fastShareLeft = rightLayout
? (paintx + usex - size->width() - st::historyFastShareLeft) ? (paintx + usex - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft); : (fullRight + st::historyFastShareLeft - margin);
auto fastShareTop = fullBottom auto fastShareTop = fullBottom
- st::historyFastShareBottom - st::historyFastShareBottom
- (size ? size->height() : 0); - (size ? size->height() : 0);
if (fastShareLeft + rightActionWidth > maxRight) { if (fastShareLeft + rightActionWidth * 2 > maxRight) {
fastShareLeft = fullRight fastShareLeft = fullRight
- rightActionWidth - rightActionWidth * 2
- st::msgDateImgDelta; - st::msgDateImgDelta;
fastShareTop -= st::msgDateImgDelta fastShareTop -= st::msgDateImgDelta
+ st::msgDateImgPadding.y() + st::msgDateImgPadding.y()
@ -1335,24 +1340,40 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
} }
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
const auto rightActionWidth = size->width(); const auto rightActionWidth = size->width();
const auto margin = _parent->delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
auto fastShareLeft = _parent->hasRightLayout() auto fastShareLeft = _parent->hasRightLayout()
? (paintx + usex - size->width() - st::historyFastShareLeft) ? (paintx + usex - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft); : (fullRight + st::historyFastShareLeft - margin);
auto fastShareTop = fullBottom auto fastShareTop = fullBottom
- st::historyFastShareBottom - st::historyFastShareBottom
- size->height(); - size->height();
if (fastShareLeft + rightActionWidth > maxRight) { if (fastShareLeft + rightActionWidth * 2 > maxRight) {
fastShareLeft = fullRight fastShareLeft = fullRight
- rightActionWidth - rightActionWidth * 2
- st::msgDateImgDelta; - st::msgDateImgDelta;
fastShareTop -= st::msgDateImgDelta fastShareTop -= st::msgDateImgDelta
+ st::msgDateImgPadding.y() + st::msgDateImgPadding.y()
+ st::msgDateFont->height + st::msgDateFont->height
+ st::msgDateImgPadding.y(); + 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 result.link = _parent->rightActionLink(point
- QPoint(fastShareLeft, fastShareTop)); - QPoint(fastShareLeft, fastShareTop));
} else if (viewRect.contains(point)) {
result.link = _parent->viewActionLink(point
- QPoint(viewRect.x(), fastShareTop));
} }
} }
if (_transcribe && _transcribe->contains(point)) { if (_transcribe && _transcribe->contains(point)) {

View file

@ -28,6 +28,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace HistoryView { namespace HistoryView {
namespace { namespace {
constexpr auto kRightActionsMargin = 10;
constexpr auto kRightActionsMarginWide = 1;
constexpr auto kUntilOffPeriod = std::numeric_limits<TimeId>::max(); constexpr auto kUntilOffPeriod = std::numeric_limits<TimeId>::max();
constexpr auto kLiveElapsedPartOpacity = 0.2; constexpr auto kLiveElapsedPartOpacity = 0.2;
@ -464,9 +466,12 @@ void Location::draw(Painter &p, const PaintContext &context) const {
paintx * 2 + paintw, paintx * 2 + paintw,
InfoDisplayType::Image); InfoDisplayType::Image);
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
const auto margin = _parent->delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
auto fastShareLeft = _parent->hasRightLayout() auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft) ? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft); : (fullRight + st::historyFastShareLeft - margin);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw); _parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw);
} }
@ -669,9 +674,12 @@ TextState Location::textState(QPoint point, StateRequest request) const {
return bottomInfoResult; return bottomInfoResult;
} }
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
const auto margin = _parent->delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
auto fastShareLeft = _parent->hasRightLayout() auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft) ? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft); : (fullRight + st::historyFastShareLeft - margin);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) { if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink(point result.link = _parent->rightActionLink(point

View file

@ -30,6 +30,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace HistoryView { namespace HistoryView {
namespace { namespace {
constexpr auto kRightActionsMargin = 10;
constexpr auto kRightActionsMarginWide = 1;
std::vector<Ui::GroupMediaLayout> LayoutPlaylist( std::vector<Ui::GroupMediaLayout> LayoutPlaylist(
const std::vector<QSize> &sizes) { const std::vector<QSize> &sizes) {
Expects(!sizes.empty()); Expects(!sizes.empty());
@ -472,9 +474,12 @@ void GroupedMedia::draw(Painter &p, const PaintContext &context) const {
InfoDisplayType::Image); InfoDisplayType::Image);
} }
if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) { if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) {
const auto margin = _parent->delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
auto fastShareLeft = _parent->hasRightLayout() auto fastShareLeft = _parent->hasRightLayout()
? (-size->width() - st::historyFastShareLeft) ? (-size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft); : (fullRight + st::historyFastShareLeft - margin);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, context, fastShareLeft, fastShareTop, width()); _parent->drawRightAction(p, context, fastShareLeft, fastShareTop, width());
} }
@ -539,13 +544,29 @@ TextState GroupedMedia::textState(QPoint point, StateRequest request) const {
return bottomInfoResult; return bottomInfoResult;
} }
if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) { if (const auto size = _parent->hasBubble() ? std::nullopt : _parent->rightActionSize()) {
const auto margin = _parent->delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
auto fastShareLeft = _parent->hasRightLayout() auto fastShareLeft = _parent->hasRightLayout()
? (-size->width() - st::historyFastShareLeft) ? (-size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft); : (fullRight + st::historyFastShareLeft - margin);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); 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 result.link = _parent->rightActionLink(point
- QPoint(fastShareLeft, fastShareTop)); - QPoint(fastShareLeft, fastShareTop));
} else if (viewRect.contains(point)) {
result.link = _parent->viewActionLink(point
- QPoint(viewRect.x(), fastShareTop));
} }
} }
} }

View file

@ -30,6 +30,8 @@ namespace HistoryView {
namespace { namespace {
constexpr auto kMaxForwardedBarLines = 4; constexpr auto kMaxForwardedBarLines = 4;
constexpr auto kRightActionsMargin = 10;
constexpr auto kRightActionsMarginWide = 1;
} // namespace } // namespace
@ -520,10 +522,23 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
fullBottom, fullBottom,
fullRight, fullRight,
*rightActionSize); *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); result.link = _parent->rightActionLink(point - position);
return result; 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::msgMargin.right()
: st::msgPadding.right()); : st::msgPadding.right());
const auto rightActionWidth = rightActionSize const auto rightActionWidth = rightActionSize
? (st::historyFastShareLeft * 2 ? (st::historyFastShareLeft * 3
+ rightActionSize->width()) + rightActionSize->width() * 2)
: 0; : 0;
auto fullRight = inner.x() auto fullRight = inner.x()
+ inner.width() + inner.width()
@ -633,12 +648,15 @@ QPoint UnwrappedMedia::calculateFastActionPosition(
- size.height()); - size.height());
const auto doesRightActionHitReply = replyRight const auto doesRightActionHitReply = replyRight
&& (fastShareTop < replyHeight); && (fastShareTop < replyHeight);
const auto margin = _parent->delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
const auto fastShareLeft = rightAligned const auto fastShareLeft = rightAligned
? ((doesRightActionHitReply ? replyLeft : inner.x()) ? ((doesRightActionHitReply ? replyLeft : inner.x())
- size.width() - size.width()
- st::historyFastShareLeft) - st::historyFastShareLeft)
: ((doesRightActionHitReply ? replyRight : fullRight) : ((doesRightActionHitReply ? replyRight : fullRight)
+ st::historyFastShareLeft); + st::historyFastShareLeft - margin);
return QPoint(fastShareLeft, fastShareTop); return QPoint(fastShareLeft, fastShareTop);
} }

View file

@ -54,6 +54,8 @@ namespace {
constexpr auto kStoryWidth = 720; constexpr auto kStoryWidth = 720;
constexpr auto kStoryHeight = 1280; constexpr auto kStoryHeight = 1280;
constexpr auto kRightActionsMargin = 10;
constexpr auto kRightActionsMarginWide = 1;
using Data::PhotoSize; using Data::PhotoSize;
@ -418,9 +420,12 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
InfoDisplayType::Image); InfoDisplayType::Image);
} }
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
const auto margin = _parent->delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
auto fastShareLeft = _parent->hasRightLayout() auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft) ? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft); : (fullRight + st::historyFastShareLeft - margin);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
_parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw); _parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw);
} }
@ -700,13 +705,29 @@ TextState Photo::textState(QPoint point, StateRequest request) const {
return bottomInfoResult; return bottomInfoResult;
} }
if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) {
const auto margin = _parent->delegate()->elementIsChatWide()
? kRightActionsMarginWide
: kRightActionsMargin;
auto fastShareLeft = _parent->hasRightLayout() auto fastShareLeft = _parent->hasRightLayout()
? (paintx - size->width() - st::historyFastShareLeft) ? (paintx - size->width() - st::historyFastShareLeft)
: (fullRight + st::historyFastShareLeft); : (fullRight + st::historyFastShareLeft - margin);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); 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 result.link = _parent->rightActionLink(point
- QPoint(fastShareLeft, fastShareTop)); - QPoint(fastShareLeft, fastShareTop));
} else if (viewRect.contains(point)) {
result.link = _parent->viewActionLink(point
- QPoint(viewRect.x(), fastShareTop));
} }
} }
} }

View file

@ -569,6 +569,7 @@ historyFastShareSize: 31px;
historyFastShareLeft: 13px; historyFastShareLeft: 13px;
historyFastShareBottom: 5px; historyFastShareBottom: 5px;
historyFastShareIcon: icon {{ "fast_share", msgServiceFg }}; historyFastShareIcon: icon {{ "fast_share", msgServiceFg }};
historyFastViewIcon: icon {{ "history_views", msgServiceFg }};
historyGoToOriginalIcon: icon {{ "filled_go_to_message", msgServiceFg, point(0px, 0px) }}; historyGoToOriginalIcon: icon {{ "filled_go_to_message", msgServiceFg, point(0px, 0px) }};
historyFastCommentsIcon: icon {{ "fast_comments", msgServiceFg }}; historyFastCommentsIcon: icon {{ "fast_comments", msgServiceFg }};
historyFastCloseSize: 30px; historyFastCloseSize: 30px;

View file

@ -201,6 +201,7 @@ ChatStyle::ChatStyle(rpl::producer<ColorIndicesCompressed> colorIndices) {
make(_msgBotKbCopyIcon, st::msgBotKbCopyIcon); make(_msgBotKbCopyIcon, st::msgBotKbCopyIcon);
make(_historyFastCommentsIcon, st::historyFastCommentsIcon); make(_historyFastCommentsIcon, st::historyFastCommentsIcon);
make(_historyFastShareIcon, st::historyFastShareIcon); make(_historyFastShareIcon, st::historyFastShareIcon);
make(_historyFastViewIcon, st::historyFastViewIcon);
make(_historyFastTranscribeIcon, st::historyFastTranscribeIcon); make(_historyFastTranscribeIcon, st::historyFastTranscribeIcon);
make(_historyFastTranscribeLock, st::historyFastTranscribeLock); make(_historyFastTranscribeLock, st::historyFastTranscribeLock);
make(_historyGoToOriginalIcon, st::historyGoToOriginalIcon); make(_historyGoToOriginalIcon, st::historyGoToOriginalIcon);

View file

@ -406,6 +406,9 @@ public:
[[nodiscard]] const style::icon &historyFastShareIcon() const { [[nodiscard]] const style::icon &historyFastShareIcon() const {
return _historyFastShareIcon; return _historyFastShareIcon;
} }
[[nodiscard]] const style::icon &historyFastViewIcon() const {
return _historyFastViewIcon;
}
[[nodiscard]] const style::icon &historyFastTranscribeIcon() const { [[nodiscard]] const style::icon &historyFastTranscribeIcon() const {
return _historyFastTranscribeIcon; return _historyFastTranscribeIcon;
} }
@ -545,6 +548,7 @@ private:
style::icon _msgBotKbCopyIcon = { Qt::Uninitialized }; style::icon _msgBotKbCopyIcon = { Qt::Uninitialized };
style::icon _historyFastCommentsIcon = { Qt::Uninitialized }; style::icon _historyFastCommentsIcon = { Qt::Uninitialized };
style::icon _historyFastShareIcon = { Qt::Uninitialized }; style::icon _historyFastShareIcon = { Qt::Uninitialized };
style::icon _historyFastViewIcon = { Qt::Uninitialized };
style::icon _historyFastMoreIcon = { Qt::Uninitialized }; style::icon _historyFastMoreIcon = { Qt::Uninitialized };
style::icon _historyFastTranscribeIcon = { Qt::Uninitialized }; style::icon _historyFastTranscribeIcon = { Qt::Uninitialized };
style::icon _historyFastTranscribeLock = { Qt::Uninitialized }; style::icon _historyFastTranscribeLock = { Qt::Uninitialized };