mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Add reaction menu to story context menu.
This commit is contained in:
parent
2dfaf27884
commit
1207e84dcb
10 changed files with 182 additions and 71 deletions
|
@ -1036,21 +1036,65 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
Fn<void(ChosenReaction)> chosen,
|
||||
Fn<void(FullMsgId)> showPremiumPromo,
|
||||
IconFactory iconFactory) {
|
||||
auto reactions = Data::LookupPossibleReactions(item);
|
||||
const auto result = AttachSelectorToMenu(
|
||||
menu,
|
||||
desiredPosition,
|
||||
st::reactPanelEmojiPan,
|
||||
controller->uiShow(),
|
||||
Data::LookupPossibleReactions(item),
|
||||
std::move(iconFactory));
|
||||
if (!result) {
|
||||
return result.error();
|
||||
}
|
||||
const auto selector = *result;
|
||||
const auto itemId = item->fullId();
|
||||
|
||||
selector->chosen() | rpl::start_with_next([=](ChosenReaction reaction) {
|
||||
menu->hideMenu();
|
||||
reaction.context = itemId;
|
||||
chosen(std::move(reaction));
|
||||
}, selector->lifetime());
|
||||
|
||||
selector->premiumPromoChosen() | rpl::start_with_next([=] {
|
||||
menu->hideMenu();
|
||||
showPremiumPromo(itemId);
|
||||
}, selector->lifetime());
|
||||
|
||||
const auto weak = base::make_weak(controller);
|
||||
controller->enableGifPauseReason(
|
||||
Window::GifPauseReason::MediaPreview);
|
||||
QObject::connect(menu.get(), &QObject::destroyed, [weak] {
|
||||
if (const auto strong = weak.get()) {
|
||||
strong->disableGifPauseReason(
|
||||
Window::GifPauseReason::MediaPreview);
|
||||
}
|
||||
});
|
||||
|
||||
return AttachSelectorResult::Attached;
|
||||
}
|
||||
|
||||
auto AttachSelectorToMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
QPoint desiredPosition,
|
||||
const style::EmojiPan &st,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const Data::PossibleItemReactionsRef &reactions,
|
||||
IconFactory iconFactory)
|
||||
-> base::expected<not_null<Selector*>, AttachSelectorResult> {
|
||||
if (reactions.recent.empty() && !reactions.morePremiumAvailable) {
|
||||
return AttachSelectorResult::Skipped;
|
||||
return base::make_unexpected(AttachSelectorResult::Skipped);
|
||||
}
|
||||
const auto withSearch = reactions.customAllowed;
|
||||
const auto selector = Ui::CreateChild<Selector>(
|
||||
menu.get(),
|
||||
st::reactPanelEmojiPan,
|
||||
controller->uiShow(),
|
||||
st,
|
||||
std::move(show),
|
||||
std::move(reactions),
|
||||
std::move(iconFactory),
|
||||
[=](bool fast) { menu->hideMenu(fast); },
|
||||
false); // child
|
||||
if (!AdjustMenuGeometryForSelector(menu, desiredPosition, selector)) {
|
||||
return AttachSelectorResult::Failed;
|
||||
return base::make_unexpected(AttachSelectorResult::Failed);
|
||||
}
|
||||
if (withSearch) {
|
||||
Ui::Platform::FixPopupMenuNativeEmojiPopup(menu);
|
||||
|
@ -1067,19 +1111,6 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
selector->initGeometry(selectorInnerTop);
|
||||
selector->show();
|
||||
|
||||
const auto itemId = item->fullId();
|
||||
|
||||
selector->chosen() | rpl::start_with_next([=](ChosenReaction reaction) {
|
||||
menu->hideMenu();
|
||||
reaction.context = itemId;
|
||||
chosen(std::move(reaction));
|
||||
}, selector->lifetime());
|
||||
|
||||
selector->premiumPromoChosen() | rpl::start_with_next([=] {
|
||||
menu->hideMenu();
|
||||
showPremiumPromo(itemId);
|
||||
}, selector->lifetime());
|
||||
|
||||
const auto correctTop = selector->y();
|
||||
menu->showStateValue(
|
||||
) | rpl::start_with_next([=](Ui::PopupMenu::ShowState state) {
|
||||
|
@ -1100,17 +1131,7 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
state.toggling);
|
||||
}, selector->lifetime());
|
||||
|
||||
const auto weak = base::make_weak(controller);
|
||||
controller->enableGifPauseReason(
|
||||
Window::GifPauseReason::MediaPreview);
|
||||
QObject::connect(menu.get(), &QObject::destroyed, [weak] {
|
||||
if (const auto strong = weak.get()) {
|
||||
strong->disableGifPauseReason(
|
||||
Window::GifPauseReason::MediaPreview);
|
||||
}
|
||||
});
|
||||
|
||||
return AttachSelectorResult::Attached;
|
||||
return selector;
|
||||
}
|
||||
|
||||
} // namespace HistoryView::Reactions
|
||||
|
|
|
@ -7,9 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "history/view/reactions/history_view_reactions_strip.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
#include "base/expected.h"
|
||||
#include "base/unique_qptr.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
#include "history/view/reactions/history_view_reactions_strip.h"
|
||||
#include "ui/effects/animation_value.h"
|
||||
#include "ui/effects/round_area_with_shadow.h"
|
||||
#include "ui/rp_widget.h"
|
||||
|
@ -210,4 +211,13 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
Fn<void(FullMsgId)> showPremiumPromo,
|
||||
IconFactory iconFactory);
|
||||
|
||||
[[nodiscard]] auto AttachSelectorToMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
QPoint desiredPosition,
|
||||
const style::EmojiPan &st,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const Data::PossibleItemReactionsRef &reactions,
|
||||
IconFactory iconFactory
|
||||
) -> base::expected<not_null<Selector*>, AttachSelectorResult>;
|
||||
|
||||
} // namespace HistoryView::Reactions
|
||||
|
|
|
@ -1552,6 +1552,13 @@ void Controller::setupStealthMode() {
|
|||
SetupStealthMode(uiShow());
|
||||
}
|
||||
|
||||
auto Controller::attachReactionsToMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
QPoint desiredPosition)
|
||||
-> AttachStripResult {
|
||||
return _reactions->attachToMenu(menu, desiredPosition);
|
||||
}
|
||||
|
||||
rpl::lifetime &Controller::lifetime() {
|
||||
return _lifetime;
|
||||
}
|
||||
|
|
|
@ -32,11 +32,13 @@ class DocumentMedia;
|
|||
namespace HistoryView::Reactions {
|
||||
class CachedIconFactory;
|
||||
struct ChosenReaction;
|
||||
enum class AttachSelectorResult;
|
||||
} // namespace HistoryView::Reactions
|
||||
|
||||
namespace Ui {
|
||||
class RpWidget;
|
||||
class BoxContent;
|
||||
class PopupMenu;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Ui::Toast {
|
||||
|
@ -167,6 +169,11 @@ public:
|
|||
[[nodiscard]] bool allowStealthMode() const;
|
||||
void setupStealthMode();
|
||||
|
||||
using AttachStripResult = HistoryView::Reactions::AttachSelectorResult;
|
||||
[[nodiscard]] AttachStripResult attachReactionsToMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
QPoint desiredPosition);
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,12 +14,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "history/view/reactions/history_view_reactions_selector.h"
|
||||
#include "main/main_session.h"
|
||||
#include "media/stories/media_stories_controller.h"
|
||||
#include "ui/effects/emoji_fly_animation.h"
|
||||
#include "ui/effects/reaction_fly_animation.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/animated_icon.h"
|
||||
#include "ui/painter.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
@ -389,6 +391,38 @@ void Reactions::attachToReactionButton(not_null<Ui::RpWidget*> button) {
|
|||
_panel->attachToReactionButton(button);
|
||||
}
|
||||
|
||||
auto Reactions::attachToMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
QPoint desiredPosition)
|
||||
-> AttachStripResult {
|
||||
using namespace HistoryView::Reactions;
|
||||
|
||||
const auto story = _controller->story();
|
||||
if (!story || story->peer()->isSelf()) {
|
||||
return AttachStripResult::Skipped;
|
||||
}
|
||||
|
||||
const auto show = _controller->uiShow();
|
||||
const auto result = AttachSelectorToMenu(
|
||||
menu,
|
||||
desiredPosition,
|
||||
st::storiesReactionsPan,
|
||||
show,
|
||||
LookupPossibleReactions(&show->session()),
|
||||
_controller->cachedReactionIconFactory().createMethod());
|
||||
if (!result) {
|
||||
return result.error();
|
||||
}
|
||||
const auto selector = *result;
|
||||
|
||||
selector->chosen() | rpl::start_with_next([=](ChosenReaction reaction) {
|
||||
menu->hideMenu();
|
||||
animateAndProcess({ reaction, ReactionsMode::Reaction });
|
||||
}, selector->lifetime());
|
||||
|
||||
return AttachSelectorResult::Attached;
|
||||
}
|
||||
|
||||
Data::ReactionId Reactions::liked() const {
|
||||
return _liked.current();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ class Story;
|
|||
namespace HistoryView::Reactions {
|
||||
class Selector;
|
||||
struct ChosenReaction;
|
||||
enum class AttachSelectorResult;
|
||||
} // namespace HistoryView::Reactions
|
||||
|
||||
namespace Ui {
|
||||
|
@ -27,6 +28,7 @@ class RpWidget;
|
|||
struct ReactionFlyAnimationArgs;
|
||||
struct ReactionFlyCenter;
|
||||
class EmojiFlyAnimation;
|
||||
class PopupMenu;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Media::Stories {
|
||||
|
@ -69,6 +71,11 @@ public:
|
|||
rpl::producer<bool> hasSendText);
|
||||
void attachToReactionButton(not_null<Ui::RpWidget*> button);
|
||||
|
||||
using AttachStripResult = HistoryView::Reactions::AttachSelectorResult;
|
||||
[[nodiscard]] AttachStripResult attachToMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
QPoint desiredPosition);
|
||||
|
||||
private:
|
||||
class Panel;
|
||||
|
||||
|
|
|
@ -123,6 +123,13 @@ void View::setupStealthMode() {
|
|||
_controller->setupStealthMode();
|
||||
}
|
||||
|
||||
auto View::attachReactionsToMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
QPoint desiredPosition)
|
||||
-> AttachStripResult {
|
||||
return _controller->attachReactionsToMenu(menu, desiredPosition);
|
||||
}
|
||||
|
||||
SiblingView View::sibling(SiblingType type) const {
|
||||
return _controller->sibling(type);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,14 @@ namespace Media::Player {
|
|||
struct TrackState;
|
||||
} // namespace Media::Player
|
||||
|
||||
namespace HistoryView::Reactions {
|
||||
enum class AttachSelectorResult;
|
||||
} // namespace HistoryView::Reactions
|
||||
|
||||
namespace Ui {
|
||||
class PopupMenu;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Media::Stories {
|
||||
|
||||
class Delegate;
|
||||
|
@ -95,6 +103,11 @@ public:
|
|||
[[nodiscard]] bool allowStealthMode() const;
|
||||
void setupStealthMode();
|
||||
|
||||
using AttachStripResult = HistoryView::Reactions::AttachSelectorResult;
|
||||
[[nodiscard]] AttachStripResult attachReactionsToMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
QPoint desiredPosition);
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
||||
private:
|
||||
|
|
|
@ -145,29 +145,30 @@ mediaviewFileIconSize: 80px;
|
|||
mediaviewFileLink: defaultLinkButton;
|
||||
|
||||
mediaviewMenuSeparator: MenuSeparator(defaultMenuSeparator) {
|
||||
fg: mediaviewMenuFg;
|
||||
fg: groupCallMenuBgOver;
|
||||
}
|
||||
mediaviewMenu: Menu(menuWithIcons) {
|
||||
itemBg: mediaviewMenuBg;
|
||||
itemBgOver: mediaviewMenuBgOver;
|
||||
itemFg: mediaviewMenuFg;
|
||||
itemFgOver: mediaviewMenuFg;
|
||||
itemFgDisabled: mediaviewMenuFg;
|
||||
itemFgShortcut: mediaviewMenuFg;
|
||||
itemFgShortcutOver: mediaviewMenuFg;
|
||||
itemFgShortcutDisabled: mediaviewMenuFg;
|
||||
itemBg: groupCallMenuBg;
|
||||
itemBgOver: groupCallMenuBgOver;
|
||||
itemFg: groupCallMembersFg;
|
||||
itemFgOver: groupCallMembersFg;
|
||||
itemFgDisabled: groupCallMemberNotJoinedStatus;
|
||||
itemFgShortcut: groupCallMemberNotJoinedStatus;
|
||||
itemFgShortcutOver: groupCallMemberNotJoinedStatus;
|
||||
itemFgShortcutDisabled: groupCallMemberNotJoinedStatus;
|
||||
|
||||
separator: mediaviewMenuSeparator;
|
||||
arrow: icon {{ "menu/submenu_arrow", groupCallMemberNotJoinedStatus }};
|
||||
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: mediaviewMenuBgRipple;
|
||||
color: groupCallMenuBgRipple;
|
||||
}
|
||||
}
|
||||
mediaviewMenuShadow: Shadow(defaultEmptyShadow) {
|
||||
fallback: mediaviewMenuBg;
|
||||
fallback: groupCallMenuBg;
|
||||
}
|
||||
mediaviewPanelAnimation: PanelAnimation(defaultPanelAnimation) {
|
||||
fadeBg: mediaviewMenuBg;
|
||||
fadeBg: groupCallMenuBg;
|
||||
shadow: mediaviewMenuShadow;
|
||||
}
|
||||
mediaviewPopupMenu: PopupMenu(defaultPopupMenu) {
|
||||
|
@ -178,7 +179,7 @@ mediaviewPopupMenu: PopupMenu(defaultPopupMenu) {
|
|||
mediaviewDropdownMenu: DropdownMenu(defaultDropdownMenu) {
|
||||
menu: mediaviewMenu;
|
||||
wrap: InnerDropdown(defaultInnerDropdown) {
|
||||
bg: mediaviewMenuBg;
|
||||
bg: groupCallMenuBg;
|
||||
animation: mediaviewPanelAnimation;
|
||||
scrollPadding: margins(0px, 8px, 0px, 8px);
|
||||
shadow: mediaviewMenuShadow;
|
||||
|
@ -312,7 +313,7 @@ mediaviewSpeedMenu: MediaSpeedMenu(mediaPlayerSpeedMenu) {
|
|||
dropdown: DropdownMenu(mediaviewDropdownMenu) {
|
||||
menu: Menu(mediaviewMenu) {
|
||||
separator: MenuSeparator(mediaviewMenuSeparator) {
|
||||
fg: mediaviewMenuBgOver;
|
||||
fg: groupCallMenuBgOver;
|
||||
padding: margins(0px, 4px, 0px, 4px);
|
||||
width: 6px;
|
||||
}
|
||||
|
@ -478,9 +479,7 @@ storiesRemoveSet: IconButton(stickerPanRemoveSet) {
|
|||
iconOver: icon {{ "simple_close", storiesComposeGrayIcon }};
|
||||
ripple: storiesComposeRippleLight;
|
||||
}
|
||||
storiesMenuSeparator: MenuSeparator(defaultMenuSeparator) {
|
||||
fg: groupCallMenuBgOver;
|
||||
}
|
||||
storiesMenuSeparator: mediaviewMenuSeparator;
|
||||
storiesMenu: Menu(defaultMenu) {
|
||||
itemBg: groupCallMenuBg;
|
||||
itemBgOver: groupCallMenuBgOver;
|
||||
|
@ -498,22 +497,14 @@ storiesMenu: Menu(defaultMenu) {
|
|||
color: groupCallMenuBgRipple;
|
||||
}
|
||||
}
|
||||
storiesMenuShadow: Shadow(defaultEmptyShadow) {
|
||||
fallback: groupCallMenuBg;
|
||||
}
|
||||
storiesMenuAnimation: PanelAnimation(defaultPanelAnimation) {
|
||||
fadeBg: groupCallMenuBg;
|
||||
shadow: storiesMenuShadow;
|
||||
}
|
||||
storiesMenuShadow: mediaviewMenuShadow;
|
||||
storiesMenuAnimation: mediaviewPanelAnimation;
|
||||
storiesPopupMenu: PopupMenu(defaultPopupMenu) {
|
||||
shadow: storiesMenuShadow;
|
||||
menu: storiesMenu;
|
||||
animation: storiesMenuAnimation;
|
||||
}
|
||||
storiesMenuWithIcons: Menu(storiesMenu) {
|
||||
itemIconPosition: point(15px, 5px);
|
||||
itemPadding: margins(54px, 8px, 17px, 8px);
|
||||
}
|
||||
storiesMenuWithIcons: mediaviewMenu;
|
||||
storiesPopupMenuWithIcons: PopupMenu(storiesPopupMenu) {
|
||||
scrollPadding: margins(0px, 5px, 0px, 5px);
|
||||
menu: storiesMenuWithIcons;
|
||||
|
@ -779,8 +770,8 @@ storiesViewsMenu: PopupMenu(storiesPopupMenuWithIcons) {
|
|||
maxHeight: 320px;
|
||||
menu: Menu(storiesMenuWithIcons) {
|
||||
itemPadding: margins(54px, 8px, 17px, 8px);
|
||||
widthMin: 215px;
|
||||
widthMax: 250px;
|
||||
widthMin: 240px;
|
||||
widthMax: 240px;
|
||||
}
|
||||
radius: 7px;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history_item_helpers.h"
|
||||
#include "history/view/media/history_view_media.h"
|
||||
#include "history/view/reactions/history_view_reactions_strip.h"
|
||||
#include "history/view/reactions/history_view_reactions_selector.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_stories.h"
|
||||
|
@ -5849,20 +5850,33 @@ bool OverlayWidget::handleContextMenu(std::optional<QPoint> position) {
|
|||
const style::icon *icon) {
|
||||
_menu->addAction(text, std::move(handler), icon);
|
||||
});
|
||||
|
||||
if (_menu->empty()) {
|
||||
_menu = nullptr;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
if (_stories) {
|
||||
_stories->menuShown(true);
|
||||
}
|
||||
_menu->setDestroyedCallback(crl::guard(_widget, [=] {
|
||||
if (_stories) {
|
||||
_stories->menuShown(true);
|
||||
_stories->menuShown(false);
|
||||
}
|
||||
_menu->setDestroyedCallback(crl::guard(_widget, [=] {
|
||||
if (_stories) {
|
||||
_stories->menuShown(false);
|
||||
}
|
||||
activateControls();
|
||||
_receiveMouse = false;
|
||||
InvokeQueued(_widget, [=] { receiveMouse(); });
|
||||
}));
|
||||
activateControls();
|
||||
_receiveMouse = false;
|
||||
InvokeQueued(_widget, [=] { receiveMouse(); });
|
||||
}));
|
||||
|
||||
using HistoryView::Reactions::AttachSelectorResult;
|
||||
const auto attached = _stories
|
||||
? _stories->attachReactionsToMenu(_menu.get(), QCursor::pos())
|
||||
: AttachSelectorResult::Skipped;
|
||||
if (attached == AttachSelectorResult::Failed) {
|
||||
_menu = nullptr;
|
||||
return true;
|
||||
} else if (attached == AttachSelectorResult::Attached) {
|
||||
_menu->popupPrepared();
|
||||
} else {
|
||||
_menu->popup(QCursor::pos());
|
||||
}
|
||||
activateControls();
|
||||
|
|
Loading…
Add table
Reference in a new issue