Allow creating EmojiListWidget without SessionController.

This commit is contained in:
John Preston 2022-08-20 07:45:44 +03:00
parent c9a98ae723
commit 33b266175d
15 changed files with 192 additions and 123 deletions

View file

@ -366,14 +366,26 @@ EmojiListWidget::EmojiListWidget(
not_null<Window::SessionController*> controller,
Window::GifPauseReason level,
Mode mode)
: Inner(parent, controller, level)
, _mode(mode)
: EmojiListWidget(parent, {
.session = &controller->session(),
.mode = mode,
.controller = controller,
.paused = Window::PausedIn(controller, level),
}) {
}
EmojiListWidget::EmojiListWidget(
QWidget *parent,
EmojiListDescriptor &&descriptor)
: Inner(parent, descriptor.session, std::move(descriptor.paused))
, _controller(descriptor.controller)
, _mode(descriptor.mode)
, _staticCount(_mode == Mode::Full ? kEmojiSectionCount : 1)
, _premiumIcon(_mode == Mode::EmojiStatus
? std::make_unique<GradientPremiumStar>()
: nullptr)
, _localSetsManager(
std::make_unique<LocalStickersManager>(&controller->session()))
std::make_unique<LocalStickersManager>(&session()))
, _collapsedBg(st::emojiPanExpand.height / 2, st::emojiPanHeaderFg)
, _picker(this)
, _showPickerTimer([=] { showPicker(); }) {
@ -397,7 +409,7 @@ EmojiListWidget::EmojiListWidget(
pickerHidden();
}, lifetime());
controller->session().data().stickers().updated(
session().data().stickers().updated(
Data::StickersType::Emoji
) | rpl::start_with_next([=] {
refreshCustom();
@ -405,8 +417,8 @@ EmojiListWidget::EmojiListWidget(
}, lifetime());
rpl::combine(
Data::AmPremiumValue(&controller->session()),
controller->session().premiumPossibleValue()
Data::AmPremiumValue(&session()),
session().premiumPossibleValue()
) | rpl::skip(1) | rpl::start_with_next([=] {
refreshCustom();
resizeToWidth(width());
@ -520,8 +532,8 @@ object_ptr<TabbedSelector::InnerFooter> EmojiListWidget::createFooter() {
using FooterDescriptor = StickersListFooter::Descriptor;
auto result = object_ptr<StickersListFooter>(FooterDescriptor{
.controller = controller(),
.level = level(),
.session = &session(),
.paused = pausedMethod(),
.parent = this,
});
_footer = result;
@ -685,7 +697,7 @@ void EmojiListWidget::fillRecent() {
const auto star = QString::fromUtf8("\xe2\xad\x90\xef\xb8\x8f");
_recent.push_back({ .id = { Ui::Emoji::Find(star) } });
}
const auto test = controller()->session().isTestMode();
const auto test = session().isTestMode();
for (const auto &one : list) {
const auto document = std::get_if<RecentEmojiDocument>(&one.id.data);
if (_mode == Mode::EmojiStatus && !document) {
@ -725,7 +737,7 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) {
toColumn = _columnCount - toColumn;
}
const auto paused = controller()->isGifPausedAtLeastFor(level());
const auto paused = this->paused();
const auto now = crl::now();
auto selectedButton = std::get_if<OverButton>(!v::is_null(_pressed)
? &_pressed
@ -1020,8 +1032,8 @@ void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) {
removeSet(id);
} else if (hasAddButton(button->section)) {
_localSetsManager->install(id);
} else {
Settings::ShowPremium(controller(), u"animated_emoji"_q);
} else if (_controller) {
Settings::ShowPremium(_controller, u"animated_emoji"_q);
}
}
}
@ -1029,18 +1041,20 @@ void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) {
void EmojiListWidget::displaySet(uint64 setId) {
const auto &sets = session().data().stickers().sets();
auto it = sets.find(setId);
if (it != sets.cend()) {
checkHideWithBox(controller()->show(
Box<StickerSetBox>(controller(), it->second.get()),
if (it != sets.cend() && _controller) {
checkHideWithBox(_controller->show(
Box<StickerSetBox>(_controller, it->second.get()),
Ui::LayerOption::KeepOther).data());
}
}
void EmojiListWidget::removeSet(uint64 setId) {
if (auto box = MakeConfirmRemoveSetBox(&session(), setId)) {
checkHideWithBox(controller()->show(
std::move(box),
Ui::LayerOption::KeepOther));
if (_controller) {
checkHideWithBox(_controller->show(
std::move(box),
Ui::LayerOption::KeepOther));
}
}
}
@ -1315,7 +1329,7 @@ void EmojiListWidget::refreshRecent() {
void EmojiListWidget::refreshCustom() {
auto old = base::take(_custom);
const auto session = &controller()->session();
const auto session = &this->session();
const auto premiumPossible = session->premiumPossible();
const auto premiumMayBeBought = premiumPossible
&& !session->premium()

View file

@ -53,19 +53,30 @@ class StickersListFooter;
class GradientPremiumStar;
class LocalStickersManager;
enum class EmojiListMode {
Full,
EmojiStatus,
Reactions,
};
struct EmojiListDescriptor {
not_null<Main::Session*> session;
EmojiListMode mode = EmojiListMode::Full;
Window::SessionController *controller = nullptr;
Fn<bool()> paused;
};
class EmojiListWidget
: public TabbedSelector::Inner
, public Ui::AbstractTooltipShower {
public:
enum class Mode {
Full,
EmojiStatus,
};
using Mode = EmojiListMode;
EmojiListWidget(
QWidget *parent,
not_null<Window::SessionController*> controller,
Window::GifPauseReason level,
Mode mode);
EmojiListWidget(QWidget *parent, EmojiListDescriptor &&descriptor);
~EmojiListWidget();
using Section = Ui::Emoji::Section;
@ -272,6 +283,7 @@ private:
DocumentId documentId,
uint64 setId);
Window::SessionController *_controller = nullptr;
Mode _mode = Mode::Full;
const int _staticCount = 0;
StickersListFooter *_footer = nullptr;

View file

@ -170,8 +170,9 @@ GifsListWidget::GifsListWidget(
QWidget *parent,
not_null<Window::SessionController*> controller,
Window::GifPauseReason level)
: Inner(parent, controller, level)
, _api(&controller->session().mtp())
: Inner(parent, &controller->session(), Window::PausedIn(controller, level))
, _controller(controller)
, _api(&session().mtp())
, _section(Section::Gifs)
, _updateInlineItems([=] { updateInlineItems(); })
, _mosaic(st::emojiPanWidth - st::inlineResultsLeft)
@ -186,19 +187,19 @@ GifsListWidget::GifsListWidget(
this,
[=] { sendInlineRequest(); });
controller->session().data().stickers().savedGifsUpdated(
session().data().stickers().savedGifsUpdated(
) | rpl::start_with_next([=] {
refreshSavedGifs();
}, lifetime());
controller->session().downloaderTaskFinished(
session().downloaderTaskFinished(
) | rpl::start_with_next([=] {
updateInlineItems();
}, lifetime());
controller->gifPauseLevelChanged(
) | rpl::start_with_next([=] {
if (!controller->isGifPausedAtLeastFor(level)) {
if (!paused()) {
updateInlineItems();
}
}, lifetime());
@ -285,7 +286,7 @@ void GifsListWidget::inlineResultsDone(const MTPmessages_BotResults &result) {
auto adding = (it != _inlineCache.cend());
if (result.type() == mtpc_messages_botResults) {
auto &d = result.c_messages_botResults();
controller()->session().data().processUsers(d.vusers());
session().data().processUsers(d.vusers());
auto &v = d.vresults().v;
auto queryId = d.vquery_id().v;
@ -303,7 +304,7 @@ void GifsListWidget::inlineResultsDone(const MTPmessages_BotResults &result) {
auto added = 0;
for (const auto &res : v) {
auto result = InlineBots::Result::Create(
&controller()->session(),
&session(),
queryId,
res);
if (result) {
@ -343,7 +344,7 @@ void GifsListWidget::paintInlineItems(Painter &p, QRect clip) {
p.drawText(QRect(0, 0, width(), (height() / 3) * 2 + st::normalFont->height), text, style::al_center);
return;
}
const auto gifPaused = controller()->isGifPausedAtLeastFor(level());
const auto gifPaused = paused();
using namespace InlineBots::Layout;
PaintContext context(crl::now(), false, gifPaused, false);
@ -397,7 +398,7 @@ void GifsListWidget::fillContextMenu(
const style::icon *icon) {
menu->addAction(text, std::move(done), icon);
};
AddGifAction(std::move(callback), controller(), document);
AddGifAction(std::move(callback), _controller, document);
}
};
}
@ -426,7 +427,7 @@ void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) {
ActivateClickHandler(window(), activated, {
e->button(),
QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(controller().get()),
.sessionWindow = base::make_weak(_controller.get()),
})
});
}
@ -449,7 +450,7 @@ void GifsListWidget::selectInlineResult(
_mosaic.findRect(index).topLeft());
return Ui::MessageSendingAnimationFrom{
.type = Ui::MessageSendingAnimationFrom::Type::Gif,
.localId = controller()->session().data().nextLocalMessageId(),
.localId = session().data().nextLocalMessageId(),
.globalStartGeometry = mapToGlobal(rect),
.crop = true,
};
@ -554,7 +555,7 @@ void GifsListWidget::refreshSavedGifs() {
if (_section == Section::Gifs) {
clearInlineRows(false);
const auto &saved = controller()->session().data().stickers().savedGifs();
const auto &saved = session().data().stickers().savedGifs();
if (!saved.isEmpty()) {
const auto layouts = ranges::views::all(
saved
@ -827,9 +828,9 @@ void GifsListWidget::searchForGifs(const QString &query) {
Expects(result.type() == mtpc_contacts_resolvedPeer);
auto &data = result.c_contacts_resolvedPeer();
controller()->session().data().processUsers(data.vusers());
controller()->session().data().processChats(data.vchats());
const auto peer = controller()->session().data().peerLoaded(
session().data().processUsers(data.vusers());
session().data().processChats(data.vchats());
const auto peer = session().data().peerLoaded(
peerFromMTP(data.vpeer()));
if (const auto user = peer ? peer->asUser() : nullptr) {
_searchBot = user;
@ -918,11 +919,11 @@ void GifsListWidget::updateSelected() {
_pressed = _selected;
if (item) {
if (const auto preview = item->getPreviewDocument()) {
controller()->widget()->showMediaPreview(
_controller->widget()->showMediaPreview(
Data::FileOriginSavedGifs(),
preview);
} else if (const auto preview = item->getPreviewPhoto()) {
controller()->widget()->showMediaPreview(
_controller->widget()->showMediaPreview(
Data::FileOrigin(),
preview);
}
@ -940,11 +941,11 @@ void GifsListWidget::showPreview() {
}
if (const auto layout = _mosaic.maybeItemAt(_pressed)) {
if (const auto previewDocument = layout->getPreviewDocument()) {
_previewShown = controller()->widget()->showMediaPreview(
_previewShown = _controller->widget()->showMediaPreview(
Data::FileOriginSavedGifs(),
previewDocument);
} else if (const auto previewPhoto = layout->getPreviewPhoto()) {
_previewShown = controller()->widget()->showMediaPreview(
_previewShown = _controller->widget()->showMediaPreview(
Data::FileOrigin(),
previewPhoto);
}

View file

@ -140,24 +140,8 @@ private:
void repaintItems(crl::time now = 0);
void showPreview();
MTP::Sender _api;
Section _section = Section::Gifs;
crl::time _lastScrolledAt = 0;
crl::time _lastUpdatedAt = 0;
base::Timer _updateInlineItems;
bool _inlineWithThumb = false;
void clearInlineRows(bool resultsDeleted);
std::map<
not_null<DocumentData*>,
std::unique_ptr<LayoutItem>> _gifLayouts;
LayoutItem *layoutPrepareSavedGif(not_null<DocumentData*> document);
std::map<
not_null<InlineResult*>,
std::unique_ptr<LayoutItem>> _inlineLayouts;
LayoutItem *layoutPrepareInlineResult(not_null<InlineResult*> result);
void deleteUnusedGifLayouts();
@ -170,6 +154,23 @@ private:
Api::SendOptions options,
bool forceSend = false);
not_null<Window::SessionController*> _controller;
MTP::Sender _api;
Section _section = Section::Gifs;
crl::time _lastScrolledAt = 0;
crl::time _lastUpdatedAt = 0;
base::Timer _updateInlineItems;
bool _inlineWithThumb = false;
std::map<
not_null<DocumentData*>,
std::unique_ptr<LayoutItem>> _gifLayouts;
std::map<
not_null<InlineResult*>,
std::unique_ptr<LayoutItem>> _inlineLayouts;
Footer *_footer = nullptr;
Mosaic::Layout::MosaicLayout<LayoutItem> _mosaic;

View file

@ -21,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lottie/lottie_single_player.h"
#include "ui/widgets/input_fields.h"
#include "ui/widgets/buttons.h"
#include "window/window_session_controller.h"
#include "styles/style_chat_helpers.h"
#include <QtWidgets/QApplication>
@ -183,8 +182,8 @@ void GradientPremiumStar::renderOnDemand() const {
StickersListFooter::StickersListFooter(Descriptor &&descriptor)
: InnerFooter(descriptor.parent)
, _controller(descriptor.controller)
, _level(descriptor.level)
, _session(descriptor.session)
, _paused(descriptor.paused)
, _searchButtonVisible(descriptor.searchButtonVisible)
, _settingsButtonVisible(descriptor.settingsButtonVisible)
, _iconState([=] { update(); })
@ -201,7 +200,7 @@ StickersListFooter::StickersListFooter(Descriptor &&descriptor)
? st::stickerIconWidth
: 0);
_controller->session().downloaderTaskFinished(
_session->downloaderTaskFinished(
) | rpl::start_with_next([=] {
update();
}, lifetime());
@ -564,7 +563,7 @@ void StickersListFooter::paintEvent(QPaintEvent *e) {
}
const auto now = crl::now();
const auto paused = _controller->isGifPausedAtLeastFor(_level);
const auto paused = _paused();
enumerateVisibleIcons([&](const IconInfo &info) {
paintSetIcon(p, info, now, paused);
});
@ -1280,8 +1279,8 @@ void StickersListFooter::paintSetIcon(
} else {
paintOne(left, [&] {
if (icon.setId == Data::Stickers::FeaturedSetId) {
const auto session = &_controller->session();
return session->data().stickers().featuredSetsUnreadCount()
const auto &stickers = _session->data().stickers();
return stickers.featuredSetsUnreadCount()
? &st::stickersTrendingUnread
: &st::stickersTrending;
//} else if (setId == Stickers::FavedSetId) {

View file

@ -92,8 +92,8 @@ private:
class StickersListFooter final : public TabbedSelector::InnerFooter {
public:
struct Descriptor {
not_null<Window::SessionController*> controller;
Window::GifPauseReason level = {};
not_null<Main::Session*> session;
Fn<bool()> paused;
not_null<RpWidget*> parent;
bool searchButtonVisible = false;
bool settingsButtonVisible = false;
@ -228,8 +228,8 @@ private:
void clipCallback(Media::Clip::Notification notification, uint64 setId);
const not_null<Window::SessionController*> _controller;
const Window::GifPauseReason _level = {};
const not_null<Main::Session*> _session;
const Fn<bool()> _paused;
const bool _searchButtonVisible = false;
const bool _settingsButtonVisible = false;

View file

@ -164,10 +164,10 @@ StickersListWidget::StickersListWidget(
not_null<Window::SessionController*> controller,
Window::GifPauseReason level,
bool masks)
: Inner(parent, controller, level)
, _api(&controller->session().mtp())
, _localSetsManager(
std::make_unique<LocalStickersManager>(&controller->session()))
: Inner(parent, &controller->session(), Window::PausedIn(controller, level))
, _controller(controller)
, _api(&session().mtp())
, _localSetsManager(std::make_unique<LocalStickersManager>(&session()))
, _section(Section::Stickers)
, _isMasks(masks)
, _updateItemsTimer([=] { updateItems(); })
@ -181,7 +181,7 @@ StickersListWidget::StickersListWidget(
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
, _settings(this, tr::lng_stickers_you_have(tr::now))
, _previewTimer([=] { showPreview(); })
, _premiumMark(std::make_unique<StickerPremiumMark>(&controller->session()))
, _premiumMark(std::make_unique<StickerPremiumMark>(&session()))
, _searchRequestTimer([=] { sendSearchRequest(); }) {
setMouseTracking(true);
setAttribute(Qt::WA_OpaquePaintEvent);
@ -246,8 +246,8 @@ object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
using FooterDescriptor = StickersListFooter::Descriptor;
auto result = object_ptr<StickersListFooter>(FooterDescriptor{
.controller = controller(),
.level = level(),
.session = &session(),
.paused = pausedMethod(),
.parent = this,
.searchButtonVisible = !_isMasks,
.settingsButtonVisible = true,
@ -263,8 +263,8 @@ object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
_footer->openSettingsRequests(
) | rpl::start_with_next([=] {
const auto onlyFeatured = _footer->hasOnlyFeaturedSets();
controller()->show(Box<StickersBox>(
controller(),
_controller->show(Box<StickersBox>(
_controller,
(onlyFeatured
? StickersBox::Section::Featured
: _isMasks
@ -814,7 +814,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
: &_selected);
const auto now = crl::now();
const auto paused = controller()->isGifPausedAtLeastFor(level());
const auto paused = this->paused();
if (sets.empty() && _section == Section::Search) {
paintEmptySearchResults(p);
}
@ -1534,7 +1534,7 @@ QPoint StickersListWidget::buttonRippleTopLeft(int section) const {
void StickersListWidget::showStickerSetBox(not_null<DocumentData*> document) {
if (document->sticker() && document->sticker()->set) {
checkHideWithBox(StickerSetBox::Show(controller(), document));
checkHideWithBox(StickerSetBox::Show(_controller, document));
}
}
@ -1569,7 +1569,7 @@ void StickersListWidget::fillContextMenu(
SendMenu::DefaultSilentCallback(send),
SendMenu::DefaultScheduleCallback(this, type, send));
const auto window = controller();
const auto window = _controller;
const auto toggleFavedSticker = [=] {
Api::ToggleFavedSticker(
window,
@ -1674,7 +1674,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
removeSet(sets[button->section].id);
}
} else if (std::get_if<OverGroupAdd>(&pressed)) {
controller()->show(Box<StickersBox>(controller(), _megagroupSet));
_controller->show(Box<StickersBox>(_controller, _megagroupSet));
}
}
}
@ -1732,9 +1732,9 @@ void StickersListWidget::removeFavedSticker(int section, int index) {
clearSelection();
const auto &sticker = _mySets[section].stickers[index];
const auto document = sticker.document;
session().data().stickers().setFaved(controller(), document, false);
session().data().stickers().setFaved(_controller, document, false);
Api::ToggleFavedSticker(
controller(),
_controller,
document,
Data::FileOriginStickerSet(Data::Stickers::FavedSetId, 0),
false);
@ -2146,8 +2146,7 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
}
void StickersListWidget::refreshPremiumStickers() {
if (_isMasks
|| controller()->session().settings().skipPremiumStickersSet()) {
if (_isMasks || session().settings().skipPremiumStickersSet()) {
return;
}
clearSelection();
@ -2457,7 +2456,7 @@ void StickersListWidget::setSelected(OverState newSelected) {
const auto &set = sets[sticker->section];
Assert(sticker->index >= 0 && sticker->index < set.stickers.size());
const auto document = set.stickers[sticker->index].document;
controller()->widget()->showMediaPreview(
_controller->widget()->showMediaPreview(
document->stickerSetOrigin(),
document);
}
@ -2472,7 +2471,7 @@ void StickersListWidget::showPreview() {
const auto &set = sets[sticker->section];
Assert(sticker->index >= 0 && sticker->index < set.stickers.size());
const auto document = set.stickers[sticker->index].document;
controller()->widget()->showMediaPreview(
_controller->widget()->showMediaPreview(
document->stickerSetOrigin(),
document);
_previewShown = true;
@ -2586,8 +2585,8 @@ void StickersListWidget::beforeHiding() {
void StickersListWidget::displaySet(uint64 setId) {
if (setId == Data::Stickers::MegagroupSetId) {
if (_megagroupSet->canEditStickers()) {
checkHideWithBox(controller()->show(
Box<StickersBox>(controller(), _megagroupSet),
checkHideWithBox(_controller->show(
Box<StickersBox>(_controller, _megagroupSet),
Ui::LayerOption::KeepOther).data());
return;
} else if (_megagroupSet->mgInfo->stickerSet.id) {
@ -2599,8 +2598,8 @@ void StickersListWidget::displaySet(uint64 setId) {
const auto &sets = session().data().stickers().sets();
auto it = sets.find(setId);
if (it != sets.cend()) {
checkHideWithBox(controller()->show(
Box<StickerSetBox>(controller(), it->second.get()),
checkHideWithBox(_controller->show(
Box<StickerSetBox>(_controller, it->second.get()),
Ui::LayerOption::KeepOther).data());
}
}
@ -2615,7 +2614,7 @@ void StickersListWidget::removeMegagroupSet(bool locally) {
const auto cancelled = [](Fn<void()> &&close) {
close();
};
checkHideWithBox(controller()->show(Ui::MakeConfirmBox({
checkHideWithBox(_controller->show(Ui::MakeConfirmBox({
.text = tr::lng_stickers_remove_group_set(),
.confirmed = crl::guard(this, [this, group = _megagroupSet](
Fn<void()> &&close) {
@ -2639,7 +2638,7 @@ void StickersListWidget::removeSet(uint64 setId) {
|| !_megagroupSet->canEditStickers();
removeMegagroupSet(removeLocally);
} else if (auto box = MakeConfirmRemoveSetBox(&session(), setId)) {
checkHideWithBox(controller()->show(
checkHideWithBox(_controller->show(
std::move(box),
Ui::LayerOption::KeepOther));
}

View file

@ -328,6 +328,7 @@ private:
int index,
not_null<DocumentData*> document);
not_null<Window::SessionController*> _controller;
MTP::Sender _api;
std::unique_ptr<LocalStickersManager> _localSetsManager;
ChannelData *_megagroupSet = nullptr;

View file

@ -1198,13 +1198,19 @@ TabbedSelector::Inner::Inner(
QWidget *parent,
not_null<Window::SessionController*> controller,
Window::GifPauseReason level)
: RpWidget(parent)
, _controller(controller)
, _level(level) {
: Inner(
parent,
&controller->session(),
Window::PausedIn(controller, level)) {
}
Main::Session &TabbedSelector::Inner::session() const {
return controller()->session();
TabbedSelector::Inner::Inner(
QWidget *parent,
not_null<Main::Session*> session,
Fn<bool()> paused)
: RpWidget(parent)
, _session(session)
, _paused(paused) {
}
rpl::producer<int> TabbedSelector::Inner::scrollToRequests() const {

View file

@ -276,14 +276,20 @@ public:
QWidget *parent,
not_null<Window::SessionController*> controller,
Window::GifPauseReason level);
Inner(
QWidget *parent,
not_null<Main::Session*> session,
Fn<bool()> paused);
[[nodiscard]] not_null<Window::SessionController*> controller() const {
return _controller;
[[nodiscard]] Main::Session &session() const {
return *_session;
}
[[nodiscard]] Window::GifPauseReason level() const {
return _level;
[[nodiscard]] Fn<bool()> pausedMethod() const {
return _paused;
}
[[nodiscard]] bool paused() const {
return _paused();
}
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] int getVisibleTop() const {
return _visibleTop;
@ -341,8 +347,8 @@ protected:
void checkHideWithBox(QPointer<Ui::BoxContent> box);
private:
const not_null<Window::SessionController*> _controller;
const Window::GifPauseReason _level = {};
const not_null<Main::Session*> _session;
const Fn<bool()> _paused;
int _visibleTop = 0;
int _visibleBottom = 0;

View file

@ -2446,6 +2446,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
const auto attached = reactItem
? AttachSelectorToMenu(
_menu.get(),
controller,
desiredPosition,
reactItem,
[=](ChosenReaction reaction) { reactionChosen(reaction); },

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/popup_menu.h"
#include "history/history_item.h"
#include "window/window_session_controller.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_chat.h"
@ -16,9 +17,11 @@ namespace HistoryView::Reactions {
Selector::Selector(
not_null<QWidget*> parent,
not_null<Window::SessionController*> parentController,
Data::PossibleItemReactions &&reactions,
IconFactory iconFactory)
: RpWidget(parent)
, _parentController(parentController.get())
, _reactions(std::move(reactions))
, _cachedRound(
QSize(st::reactStripSkip * 2 + st::reactStripSize, st::reactStripHeight),
@ -251,25 +254,27 @@ void Selector::paintFadingExpandIcon(QPainter &p, float64 progress) {
}
void Selector::paintExpanded(QPainter &p) {
paintExpandedBg(p);
if (!_expandFinished) {
finishExpand();
}
p.drawImage(0, 0, _paintBuffer);
paintStripWithoutExpand(p);
}
void Selector::paintExpandedBg(QPainter &p) {
if (!_expandedBgReady) {
_expandedBgReady = true;
auto q = QPainter(&_paintBuffer);
q.setCompositionMode(QPainter::CompositionMode_Source);
const auto pattern = _cachedRound.validateFrame(
kFramesCount - 1,
1.,
st::roundRadiusSmall);
const auto fill = _cachedRound.FillWithImage(q, rect(), pattern);
if (!fill.isEmpty()) {
q.fillRect(fill, st::defaultPopupMenu.menu.itemBg);
}
void Selector::finishExpand() {
Expects(!_expandFinished);
_expandFinished = true;
auto q = QPainter(&_paintBuffer);
q.setCompositionMode(QPainter::CompositionMode_Source);
const auto pattern = _cachedRound.validateFrame(
kFramesCount - 1,
1.,
st::roundRadiusSmall);
const auto fill = _cachedRound.FillWithImage(q, rect(), pattern);
if (!fill.isEmpty()) {
q.fillRect(fill, st::defaultPopupMenu.menu.itemBg);
}
p.drawImage(0, 0, _paintBuffer);
}
void Selector::paintBubble(QPainter &p, int innerWidth) {
@ -441,6 +446,7 @@ bool AdjustMenuGeometryForSelector(
AttachSelectorResult AttachSelectorToMenu(
not_null<Ui::PopupMenu*> menu,
not_null<Window::SessionController*> controller,
QPoint desiredPosition,
not_null<HistoryItem*> item,
Fn<void(ChosenReaction)> chosen,
@ -452,6 +458,7 @@ AttachSelectorResult AttachSelectorToMenu(
}
const auto selector = Ui::CreateChild<Selector>(
menu.get(),
controller,
std::move(reactions),
std::move(iconFactory));
if (!AdjustMenuGeometryForSelector(menu, desiredPosition, selector)) {

View file

@ -36,6 +36,7 @@ class Selector final : public Ui::RpWidget {
public:
Selector(
not_null<QWidget*> parent,
not_null<Window::SessionController*> parentController,
Data::PossibleItemReactions &&reactions,
IconFactory iconFactory);
@ -75,15 +76,16 @@ private:
void paintStripWithoutExpand(QPainter &p);
void paintFadingExpandIcon(QPainter &p, float64 progress);
void paintExpanded(QPainter &p);
void paintExpandedBg(QPainter &p);
void paintBubble(QPainter &p, int innerWidth);
void paintBackgroundToBuffer();
void finishExpand();
[[nodiscard]] int lookupSelectedIndex(QPoint position) const;
void setSelected(int index);
void expand();
const base::weak_ptr<Window::SessionController> _parentController;
const Data::PossibleItemReactions _reactions;
Ui::RoundAreaWithShadow _cachedRound;
Strip _strip;
@ -112,7 +114,7 @@ private:
bool _appearing = false;
bool _toggling = false;
bool _expanded = false;
bool _expandedBgReady = false;
bool _expandFinished = false;
bool _small = false;
bool _over = false;
bool _low = false;
@ -126,6 +128,7 @@ enum class AttachSelectorResult {
};
AttachSelectorResult AttachSelectorToMenu(
not_null<Ui::PopupMenu*> menu,
not_null<Window::SessionController*> controller,
QPoint desiredPosition,
not_null<HistoryItem*> item,
Fn<void(ChosenReaction)> chosen,

View file

@ -144,6 +144,18 @@ void ActivateWindow(not_null<SessionController*> controller) {
Ui::ActivateWindowDelayed(window);
}
bool IsPaused(
not_null<SessionController*> controller,
GifPauseReason level) {
return controller->isGifPausedAtLeastFor(level);
}
Fn<bool()> PausedIn(
not_null<SessionController*> controller,
GifPauseReason level) {
return [=] { return IsPaused(controller, level); };
}
bool operator==(const PeerThemeOverride &a, const PeerThemeOverride &b) {
return (a.peer == b.peer) && (a.theme == b.theme);
}

View file

@ -611,6 +611,13 @@ private:
void ActivateWindow(not_null<SessionController*> controller);
[[nodiscard]] bool IsPaused(
not_null<SessionController*> controller,
GifPauseReason level);
[[nodiscard]] Fn<bool()> PausedIn(
not_null<SessionController*> controller,
GifPauseReason level);
class Show : public Ui::Show {
public:
explicit Show(not_null<SessionNavigation*> navigation);