Fix send menus with additional items.

This commit is contained in:
John Preston 2024-10-11 18:19:40 +04:00
parent ba31756bf9
commit 5767cbd0e3
6 changed files with 122 additions and 54 deletions

View file

@ -1428,9 +1428,13 @@ void StickerSetBox::Inner::contextMenuEvent(QContextMenuEvent *e) {
const auto send = crl::guard(this, [=](Api::SendOptions options) { const auto send = crl::guard(this, [=](Api::SendOptions options) {
chosen(index, document, options); chosen(index, document, options);
}); });
// In case we're adding items after FillSendMenu we have
// to pass nullptr for showForEffect and attach selector later.
// Otherwise added items widths won't be respected in menu geometry.
SendMenu::FillSendMenu( SendMenu::FillSendMenu(
_menu.get(), _menu.get(),
_show, nullptr, // showForEffect
details, details,
SendMenu::DefaultCallback(_show, send)); SendMenu::DefaultCallback(_show, send));
@ -1464,6 +1468,12 @@ void StickerSetBox::Inner::contextMenuEvent(QContextMenuEvent *e) {
.isAttention = true, .isAttention = true,
}); });
} }
SendMenu::AttachSendMenuEffect(
_menu.get(),
_show,
details,
SendMenu::DefaultCallback(_show, send));
} }
if (_menu->empty()) { if (_menu->empty()) {
_menu = nullptr; _menu = nullptr;

View file

@ -402,9 +402,13 @@ base::unique_qptr<Ui::PopupMenu> GifsListWidget::fillContextMenu(
// inline results don't have effects // inline results don't have effects
copyDetails.effectAllowed = false; copyDetails.effectAllowed = false;
} }
// In case we're adding items after FillSendMenu we have
// to pass nullptr for showForEffect and attach selector later.
// Otherwise added items widths won't be respected in menu geometry.
SendMenu::FillSendMenu( SendMenu::FillSendMenu(
menu, menu,
_show, nullptr, // showForMenu
copyDetails, copyDetails,
SendMenu::DefaultCallback(_show, send), SendMenu::DefaultCallback(_show, send),
icons); icons);
@ -441,6 +445,13 @@ base::unique_qptr<Ui::PopupMenu> GifsListWidget::fillContextMenu(
AddGifAction(std::move(callback), _show, document, icons); AddGifAction(std::move(callback), _show, document, icons);
} }
} }
SendMenu::AttachSendMenuEffect(
menu,
_show,
copyDetails,
SendMenu::DefaultCallback(_show, send));
return menu; return menu;
} }

View file

@ -1780,9 +1780,13 @@ base::unique_qptr<Ui::PopupMenu> StickersListWidget::fillContextMenu(
}); });
}); });
const auto icons = &st().icons; const auto icons = &st().icons;
// In case we're adding items after FillSendMenu we have
// to pass nullptr for showForEffect and attach selector later.
// Otherwise added items widths won't be respected in menu geometry.
SendMenu::FillSendMenu( SendMenu::FillSendMenu(
menu, menu,
_show, nullptr, // showForEffect
details, details,
SendMenu::DefaultCallback(_show, send), SendMenu::DefaultCallback(_show, send),
icons); icons);
@ -1816,6 +1820,13 @@ base::unique_qptr<Ui::PopupMenu> StickersListWidget::fillContextMenu(
false); false);
}, &icons->menuRecentRemove); }, &icons->menuRecentRemove);
} }
SendMenu::AttachSendMenuEffect(
menu,
_show,
details,
SendMenu::DefaultCallback(_show, send));
return menu; return menu;
} }

View file

@ -346,11 +346,16 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) {
const auto send = crl::guard(this, [=](Api::SendOptions options) { const auto send = crl::guard(this, [=](Api::SendOptions options) {
selectInlineResult(selected, options, false); selectInlineResult(selected, options, false);
}); });
const auto show = _controller->uiShow();
// In case we're adding items after FillSendMenu we have
// to pass nullptr for showForEffect and attach selector later.
// Otherwise added items widths won't be respected in menu geometry.
SendMenu::FillSendMenu( SendMenu::FillSendMenu(
_menu, _menu,
_controller->uiShow(), nullptr, // showForEffect
details, details,
SendMenu::DefaultCallback(_controller->uiShow(), send)); SendMenu::DefaultCallback(show, send));
const auto item = _mosaic.itemAt(_selected); const auto item = _mosaic.itemAt(_selected);
if (const auto previewDocument = item->getPreviewDocument()) { if (const auto previewDocument = item->getPreviewDocument()) {
@ -366,6 +371,12 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) {
previewDocument); previewDocument);
} }
SendMenu::AttachSendMenuEffect(
_menu,
show,
details,
SendMenu::DefaultCallback(show, send));
if (!_menu->empty()) { if (!_menu->empty()) {
_menu->popup(QCursor::pos()); _menu->popup(QCursor::pos());
} }

View file

@ -609,6 +609,67 @@ Fn<void(Action, Details)> DefaultCallback(
}; };
} }
FillMenuResult AttachSendMenuEffect(
not_null<Ui::PopupMenu*> menu,
std::shared_ptr<ChatHelpers::Show> show,
Details details,
Fn<void(Action, Details)> action,
std::optional<QPoint> desiredPositionOverride) {
Expects(show != nullptr);
using namespace HistoryView::Reactions;
const auto effect = std::make_shared<QPointer<EffectPreview>>();
const auto position = desiredPositionOverride.value_or(QCursor::pos());
const auto selector = (show && details.effectAllowed)
? AttachSelectorToMenu(
menu,
position,
st::reactPanelEmojiPan,
show,
LookupPossibleEffects(&show->session()),
{ tr::lng_effect_add_title(tr::now) },
nullptr, // iconFactory
[=] { return (*effect) != nullptr; }) // paused
: base::make_unexpected(AttachSelectorResult::Skipped);
if (!selector) {
if (selector.error() == AttachSelectorResult::Failed) {
return FillMenuResult::Failed;
}
menu->prepareGeometryFor(position);
return FillMenuResult::Prepared;
}
(*selector)->chosen(
) | rpl::start_with_next([=](ChosenReaction chosen) {
const auto &reactions = show->session().data().reactions();
const auto &effects = reactions.list(Data::Reactions::Type::Effects);
const auto i = ranges::find(effects, chosen.id, &Data::Reaction::id);
if (i != end(effects)) {
if (const auto strong = effect->data()) {
strong->hideAnimated();
}
const auto weak = Ui::MakeWeak(menu);
const auto done = [=] {
delete effect->data();
if (const auto strong = weak.data()) {
strong->hideMenu(true);
}
};
*effect = Ui::CreateChild<EffectPreview>(
menu,
show,
details,
menu->mapFromGlobal(chosen.globalGeometry.center()),
*i,
action,
crl::guard(menu, done));
(*effect)->show();
}
}, menu->lifetime());
return FillMenuResult::Prepared;
}
FillMenuResult FillSendMenu( FillMenuResult FillSendMenu(
not_null<Ui::PopupMenu*> menu, not_null<Ui::PopupMenu*> menu,
std::shared_ptr<ChatHelpers::Show> showForEffect, std::shared_ptr<ChatHelpers::Show> showForEffect,
@ -691,57 +752,14 @@ FillMenuResult FillSendMenu(
&icons.menuPrice); &icons.menuPrice);
} }
using namespace HistoryView::Reactions; return showForEffect
const auto effect = std::make_shared<QPointer<EffectPreview>>(); ? AttachSendMenuEffect(
const auto position = desiredPositionOverride.value_or(QCursor::pos());
const auto selector = (showForEffect && details.effectAllowed)
? AttachSelectorToMenu(
menu, menu,
position,
st::reactPanelEmojiPan,
showForEffect, showForEffect,
LookupPossibleEffects(&showForEffect->session()), details,
{ tr::lng_effect_add_title(tr::now) }, action,
nullptr, // iconFactory desiredPositionOverride)
[=] { return (*effect) != nullptr; }) // paused : FillMenuResult::Prepared;
: base::make_unexpected(AttachSelectorResult::Skipped);
if (!selector) {
if (selector.error() == AttachSelectorResult::Failed) {
return FillMenuResult::Failed;
}
menu->prepareGeometryFor(position);
return FillMenuResult::Prepared;
}
(*selector)->chosen(
) | rpl::start_with_next([=](ChosenReaction chosen) {
const auto &reactions = showForEffect->session().data().reactions();
const auto &effects = reactions.list(Data::Reactions::Type::Effects);
const auto i = ranges::find(effects, chosen.id, &Data::Reaction::id);
if (i != end(effects)) {
if (const auto strong = effect->data()) {
strong->hideAnimated();
}
const auto weak = Ui::MakeWeak(menu);
const auto done = [=] {
delete effect->data();
if (const auto strong = weak.data()) {
strong->hideMenu(true);
}
};
*effect = Ui::CreateChild<EffectPreview>(
menu,
showForEffect,
details,
menu->mapFromGlobal(chosen.globalGeometry.center()),
*i,
action,
crl::guard(menu, done));
(*effect)->show();
}
}, menu->lifetime());
return FillMenuResult::Prepared;
} }
void SetupMenuAndShortcuts( void SetupMenuAndShortcuts(

View file

@ -90,6 +90,13 @@ FillMenuResult FillSendMenu(
const style::ComposeIcons *iconsOverride = nullptr, const style::ComposeIcons *iconsOverride = nullptr,
std::optional<QPoint> desiredPositionOverride = std::nullopt); std::optional<QPoint> desiredPositionOverride = std::nullopt);
FillMenuResult AttachSendMenuEffect(
not_null<Ui::PopupMenu*> menu,
std::shared_ptr<ChatHelpers::Show> show,
Details details,
Fn<void(Action, Details)> action,
std::optional<QPoint> desiredPositionOverride = std::nullopt);
void SetupMenuAndShortcuts( void SetupMenuAndShortcuts(
not_null<Ui::RpWidget*> button, not_null<Ui::RpWidget*> button,
std::shared_ptr<ChatHelpers::Show> show, std::shared_ptr<ChatHelpers::Show> show,