PoC content outside of PopupMenu.

This commit is contained in:
John Preston 2022-08-17 21:03:57 +03:00
parent c20ed7c7a8
commit a0d5456a4d
14 changed files with 275 additions and 25 deletions

View File

@ -512,9 +512,10 @@ groupCallMenu: Menu(defaultMenu) {
itemFgShortcutOver: groupCallMemberNotJoinedStatus;
itemFgShortcutDisabled: groupCallMemberNotJoinedStatus;
separatorFg: groupCallMenuBgOver;
separatorPadding: margins(0px, 4px, 0px, 4px);
separator: MenuSeparator(defaultMenuSeparator) {
padding: margins(0px, 4px, 0px, 4px);
fg: groupCallMenuBgOver;
}
arrow: icon {{ "dropdown_submenu_arrow", groupCallMemberNotJoinedStatus }};
ripple: RippleAnimation(defaultRippleAnimation) {

View File

@ -50,7 +50,7 @@ bool CoverItem::isEnabled() const {
}
int CoverItem::contentHeight() const {
return _st.size + st::groupCallMenu.separatorPadding.bottom();
return _st.size + st::groupCallMenu.separator.padding.bottom();
}
AboutItem::AboutItem(

View File

@ -311,3 +311,6 @@ inlineRadialSize: 44px;
inlineFileSize: 44px;
stickersPremiumLock: icon{{ "emoji/premium_lock", premiumButtonFg }};
reactStripExtend: margins(21px, 49px, 39px, 0px);
reactStripHeight: 40px;

View File

@ -533,12 +533,20 @@ ReactionsFilter PeerReactionsFilter(not_null<PeerData*> peer) {
});
}
int UniqueReactionsLimit(not_null<Main::AppConfig*> config) {
return config->get<int>("reactions_uniq_max", 11);
}
int UniqueReactionsLimit(not_null<PeerData*> peer) {
return UniqueReactionsLimit(&peer->session().account().appConfig());
}
rpl::producer<int> UniqueReactionsLimitValue(
not_null<Main::Session*> session) {
const auto config = &session->account().appConfig();
return config->value(
) | rpl::map([=] {
return config->get<int>("reactions_uniq_max", 11);
return UniqueReactionsLimit(config);
}) | rpl::distinct_until_changed();
}

View File

@ -138,6 +138,7 @@ inline auto PeerFullFlagValue(
[[nodiscard]] rpl::producer<ReactionsFilter> PeerReactionsFilterValue(
not_null<PeerData*> peer);
[[nodiscard]] int UniqueReactionsLimit(not_null<PeerData*> peer);
[[nodiscard]] rpl::producer<int> UniqueReactionsLimitValue(
not_null<Main::Session*> session);

View File

@ -2040,11 +2040,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
e->accept();
return;
}
_menu = base::make_unique_q<Ui::PopupMenu>(
this,
(hasWhoReactedItem
? st::popupMenuExpandedSeparator
: st::popupMenuWithIcons));
_menu = base::make_unique_q<Ui::PopupMenu>(this, st::popupMenuWithIcons);
const auto session = &this->session();
const auto controller = _controller;
const auto groupLeaderOrSelf = [](HistoryItem *item) -> HistoryItem* {
@ -2451,10 +2447,25 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
if (_menu->empty()) {
_menu = nullptr;
} else {
_menu->popup(e->globalPos());
e->accept();
return;
}
using namespace HistoryView::Reactions;
const auto desiredPosition = e->globalPos();
const auto reactItem = Element::Hovered()
? Element::Hovered()->data().get()
: nullptr;
const auto attached = reactItem
? AttachSelectorToMenu(_menu.get(), desiredPosition, reactItem)
: AttachSelectorResult::Skipped;
if (attached == AttachSelectorResult::Failed) {
_menu = nullptr;
return;
} else if (attached == AttachSelectorResult::Attached) {
_menu->popupPrepared();
} else {
_menu->popup(desiredPosition);
}
e->accept();
}
bool HistoryInner::hasCopyRestriction(HistoryItem *item) const {

View File

@ -952,9 +952,7 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
auto result = base::make_unique_q<Ui::PopupMenu>(
list,
(hasWhoReactedItem
? st::popupMenuExpandedSeparator
: st::popupMenuWithIcons));
st::popupMenuWithIcons);
if (request.overSelection && !list->hasCopyRestrictionForSelected()) {
const auto text = request.selectedItems.empty()
@ -1158,7 +1156,7 @@ void AddWhoReactedAction(
}
};
if (!menu->empty()) {
menu->addSeparator();
menu->addSeparator(&st::expandedMenuSeparator);
}
menu->addAction(Ui::WhoReactedContextAction(
menu.get(),

View File

@ -9,10 +9,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_react_button.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/data_message_reactions.h"
#include "data/data_peer_values.h"
#include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_selector.h"
#include "ui/widgets/popup_menu.h"
#include "history/history.h"
#include "history/history_item.h"
#include "window/window_session_controller.h"
#include "window/window_controller.h"
#include "main/main_session.h"
#include "mainwindow.h"
#include "styles/style_chat_helpers.h"
@ -104,4 +111,175 @@ void Selector::hide(anim::type animated) {
}
}
PopupSelector::PopupSelector(
not_null<QWidget*> parent,
PossibleReactions reactions)
: RpWidget(parent) {
}
int PopupSelector::countWidth(int desiredWidth, int maxWidth) {
return maxWidth;
}
QMargins PopupSelector::extentsForShadow() const {
return st::defaultPopupMenu.shadow.extend;
}
int PopupSelector::extendTopForCategories() const {
return st::emojiFooterHeight;
}
int PopupSelector::desiredHeight() const {
return st::emojiPanMaxHeight;
}
void PopupSelector::paintEvent(QPaintEvent *e) {
QPainter(this).fillRect(e->rect(), QColor(0, 128, 0, 128));
}
[[nodiscard]] PossibleReactions LookupPossibleReactions(
not_null<HistoryItem*> item) {
if (!item->canReact()) {
return {};
}
auto result = PossibleReactions();
const auto peer = item->history()->peer;
const auto session = &peer->session();
const auto reactions = &session->data().reactions();
const auto &full = reactions->list(Data::Reactions::Type::Active);
const auto &all = item->reactions();
const auto my = item->chosenReaction();
auto myIsUnique = false;
for (const auto &[id, count] : all) {
if (count == 1 && id == my) {
myIsUnique = true;
}
}
const auto notMineCount = int(all.size()) - (myIsUnique ? 1 : 0);
const auto limit = Data::UniqueReactionsLimit(peer);
if (limit > 0 && notMineCount >= limit) {
result.recent.reserve(all.size());
for (const auto &reaction : full) {
const auto id = reaction.id;
if (all.contains(id)) {
result.recent.push_back(id);
}
}
} else {
const auto filter = Data::PeerReactionsFilter(peer);
result.recent.reserve(filter.allowed
? filter.allowed->size()
: full.size());
for (const auto &reaction : full) {
const auto id = reaction.id;
const auto emoji = filter.allowed ? id.emoji() : QString();
if (filter.allowed
&& (emoji.isEmpty() || !filter.allowed->contains(emoji))) {
continue;
} else if (reaction.premium
&& !session->premium()
&& !all.contains(id)) {
if (session->premiumPossible()) {
result.morePremiumAvailable = true;
}
continue;
} else {
result.recent.push_back(id);
}
}
result.customAllowed = peer->isUser();
}
const auto i = ranges::find(result.recent, reactions->favorite());
if (i != end(result.recent) && i != begin(result.recent)) {
std::rotate(begin(result.recent), i, i + 1);
}
return result;
}
bool SetupSelectorInMenuGeometry(
not_null<Ui::PopupMenu*> menu,
QPoint desiredPosition,
not_null<PopupSelector*> selector) {
const auto extend = st::reactStripExtend;
const auto added = extend.left() + extend.right();
const auto desiredWidth = menu->width() + added;
const auto maxWidth = menu->st().menu.widthMax + added;
const auto width = selector->countWidth(desiredWidth, maxWidth);
const auto extents = selector->extentsForShadow();
const auto categoriesTop = selector->extendTopForCategories();
menu->setForceWidth(width - added);
const auto height = menu->height();
const auto fullTop = extents.top() + categoriesTop + extend.top();
const auto minimalHeight = extents.top()
+ std::min(
selector->desiredHeight(),
categoriesTop + st::emojiPanMinHeight / 2)
+ extents.bottom();
const auto willBeHeightWithoutBottomPadding = fullTop
+ height
- menu->st().shadow.extend.top();
const auto additionalPaddingBottom
= (willBeHeightWithoutBottomPadding < minimalHeight
? (minimalHeight - willBeHeightWithoutBottomPadding)
: 0);
menu->setAdditionalMenuPadding(QMargins(
extents.left() + extend.left(),
fullTop,
extents.right() + extend.right(),
additionalPaddingBottom
), QMargins(
extents.left(),
extents.top(),
extents.right(),
std::min(additionalPaddingBottom, extents.bottom())
));
if (!menu->prepareGeometryFor(desiredPosition)) {
return false;
}
const auto origin = menu->preparedOrigin();
if (!additionalPaddingBottom
|| origin == Ui::PanelAnimation::Origin::TopLeft
|| origin == Ui::PanelAnimation::Origin::TopRight) {
return true;
}
menu->setAdditionalMenuPadding(QMargins(
extents.left() + extend.left(),
fullTop + additionalPaddingBottom,
extents.right() + extend.right(),
0
), QMargins(
extents.left(),
extents.top(),
extents.right(),
0
));
return menu->prepareGeometryFor(desiredPosition);
}
AttachSelectorResult AttachSelectorToMenu(
not_null<Ui::PopupMenu*> menu,
QPoint desiredPosition,
not_null<HistoryItem*> item) {
auto reactions = LookupPossibleReactions(item);
if (reactions.recent.empty() && !reactions.morePremiumAvailable) {
return AttachSelectorResult::Skipped;
}
const auto selector = Ui::CreateChild<PopupSelector>(
menu.get(),
std::move(reactions));
if (!SetupSelectorInMenuGeometry(menu, desiredPosition, selector)) {
return AttachSelectorResult::Failed;
}
const auto extents = selector->extentsForShadow();
const auto categoriesTop = selector->extendTopForCategories();
selector->setGeometry(
extents.left(),
menu->preparedPadding().top() - st::reactStripExtend.top(),
menu->width() - extents.left() - extents.right(),
st::reactStripHeight);
selector->lower();
selector->show();
return AttachSelectorResult::Attached;
}
} // namespace HistoryView::Reactions

View File

@ -9,6 +9,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unique_qptr.h"
#include "ui/effects/animation_value.h"
#include "ui/rp_widget.h"
namespace Data {
struct ReactionId;
} // namespace Data
namespace ChatHelpers {
class TabbedPanel;
@ -18,6 +23,10 @@ namespace Window {
class SessionController;
} // namespace Window
namespace Ui {
class PopupMenu;
} // namespace Ui
namespace HistoryView::Reactions {
struct ChosenReaction;
@ -44,4 +53,39 @@ private:
};
struct PossibleReactions {
std::vector<Data::ReactionId> recent;
bool morePremiumAvailable = false;
bool customAllowed = false;
};
class PopupSelector final : public Ui::RpWidget {
public:
PopupSelector(
not_null<QWidget*> parent,
PossibleReactions reactions);
int countWidth(int desiredWidth, int maxWidth);
[[nodiscard]] QMargins extentsForShadow() const;
[[nodiscard]] int extendTopForCategories() const;
[[nodiscard]] int desiredHeight() const;
protected:
void paintEvent(QPaintEvent *e);
private:
int _columns = 0;
};
enum class AttachSelectorResult {
Skipped,
Failed,
Attached,
};
AttachSelectorResult AttachSelectorToMenu(
not_null<Ui::PopupMenu*> menu,
QPoint desiredPosition,
not_null<HistoryItem*> item);
} // namespace HistoryView::Reactions

View File

@ -148,7 +148,9 @@ mediaviewMenu: Menu(menuWithIcons) {
itemFgShortcutOver: mediaviewMenuFg;
itemFgShortcutDisabled: mediaviewMenuFg;
separatorFg: mediaviewMenuFg;
separator: MenuSeparator(defaultMenuSeparator) {
fg: mediaviewMenuFg;
}
ripple: RippleAnimation(defaultRippleAnimation) {
color: mediaviewMenuBgRipple;
@ -186,7 +188,9 @@ mediaviewControlsMenu: Menu(defaultMenu) {
itemFgShortcutOver: mediaviewPlaybackProgressFg;
itemFgShortcutDisabled: mediaviewPlaybackProgressFg;
separatorFg: mediaviewPlaybackIconRipple;
separator: MenuSeparator(defaultMenuSeparator) {
fg: mediaviewPlaybackIconRipple;
}
arrow: icon {{ "dropdown_submenu_arrow", mediaviewPlaybackProgressFg }};

View File

@ -857,8 +857,7 @@ void PipPanel::updateDecorations() {
}
});
const auto position = countPosition();
const auto center = position.geometry.center();
const auto use = Ui::Platform::TranslucentWindowsSupported(center);
const auto use = Ui::Platform::TranslucentWindowsSupported();
const auto full = use ? st::callShadow.extend : style::margins();
const auto padding = style::margins(
(position.attached & RectPart::Left) ? 0 : full.left(),

View File

@ -936,10 +936,13 @@ ttlDividerLabelPadding: margins(22px, 10px, 22px, 19px);
ttlItemPadding: margins(0px, 4px, 0px, 4px);
ttlItemTimerFont: font(12px);
expandedMenuSeparator: MenuSeparator(defaultMenuSeparator) {
padding: margins(0px, 4px, 0px, 4px);
width: 6px;
}
popupMenuExpandedSeparator: PopupMenu(popupMenuWithIcons) {
menu: Menu(menuWithIcons) {
separatorPadding: margins(0px, 4px, 0px, 4px);
separatorWidth: 6px;
separator: expandedMenuSeparator;
}
}

@ -1 +1 @@
Subproject commit b2f2b7b6bce60bc1c6429a6b5ec4bc5891baa060
Subproject commit 0e386e22cb6ba8a114b569840a635e096dcb645e

@ -1 +1 @@
Subproject commit 1cc74a41c4d1c3fe9824e4bf47c23e3bcd1759e6
Subproject commit a76cdf7edffb6e9cbef515a0e599c3c14a8a5b53