mirror of https://github.com/procxx/kepka.git
Remove Qt MOC dependency for tabbed selector.
This commit is contained in:
parent
9f5b09c263
commit
ef4f0168f8
|
@ -32,6 +32,73 @@ constexpr auto kStickersPanelPerRow = 5;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
class StickerSetBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
|
||||||
|
public:
|
||||||
|
Inner(QWidget *parent, const MTPInputStickerSet &set);
|
||||||
|
|
||||||
|
bool loaded() const;
|
||||||
|
bool notInstalled() const;
|
||||||
|
bool official() const;
|
||||||
|
Fn<TextWithEntities()> title() const;
|
||||||
|
QString shortName() const;
|
||||||
|
|
||||||
|
void install();
|
||||||
|
rpl::producer<uint64> setInstalled() const;
|
||||||
|
rpl::producer<> updateControls() const;
|
||||||
|
|
||||||
|
~Inner();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
void leaveEventHook(QEvent *e) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateSelected();
|
||||||
|
void setSelected(int selected);
|
||||||
|
void startOverAnimation(int index, float64 from, float64 to);
|
||||||
|
int stickerFromGlobalPos(const QPoint &p) const;
|
||||||
|
|
||||||
|
void gotSet(const MTPmessages_StickerSet &set);
|
||||||
|
bool failedSet(const RPCError &error);
|
||||||
|
|
||||||
|
void installDone(const MTPmessages_StickerSetInstallResult &result);
|
||||||
|
bool installFail(const RPCError &error);
|
||||||
|
|
||||||
|
bool isMasksSet() const {
|
||||||
|
return (_setFlags & MTPDstickerSet::Flag::f_masks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showPreview();
|
||||||
|
|
||||||
|
std::vector<Animation> _packOvers;
|
||||||
|
Stickers::Pack _pack;
|
||||||
|
Stickers::ByEmojiMap _emoji;
|
||||||
|
bool _loaded = false;
|
||||||
|
uint64 _setId = 0;
|
||||||
|
uint64 _setAccess = 0;
|
||||||
|
QString _setTitle, _setShortName;
|
||||||
|
int _setCount = 0;
|
||||||
|
int32 _setHash = 0;
|
||||||
|
MTPDstickerSet::Flags _setFlags = 0;
|
||||||
|
TimeId _setInstallDate = TimeId(0);
|
||||||
|
|
||||||
|
MTPInputStickerSet _input;
|
||||||
|
|
||||||
|
mtpRequestId _installRequest = 0;
|
||||||
|
|
||||||
|
int _selected = -1;
|
||||||
|
|
||||||
|
base::Timer _previewTimer;
|
||||||
|
int _previewShown = -1;
|
||||||
|
|
||||||
|
rpl::event_stream<uint64> _setInstalled;
|
||||||
|
rpl::event_stream<> _updateControls;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set)
|
StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set)
|
||||||
: _set(set) {
|
: _set(set) {
|
||||||
}
|
}
|
||||||
|
@ -41,33 +108,37 @@ void StickerSetBox::prepare() {
|
||||||
|
|
||||||
_inner = setInnerWidget(object_ptr<Inner>(this, _set), st::stickersScroll);
|
_inner = setInnerWidget(object_ptr<Inner>(this, _set), st::stickersScroll);
|
||||||
Auth().data().stickersUpdated(
|
Auth().data().stickersUpdated(
|
||||||
) | rpl::start_with_next(
|
) | rpl::start_with_next([=] {
|
||||||
[this] { updateButtons(); },
|
updateButtons();
|
||||||
lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
setDimensions(st::boxWideWidth, st::stickersMaxHeight);
|
setDimensions(st::boxWideWidth, st::stickersMaxHeight);
|
||||||
|
|
||||||
onUpdateButtons();
|
updateTitleAndButtons();
|
||||||
|
|
||||||
|
_inner->updateControls(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
updateTitleAndButtons();
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
connect(_inner, SIGNAL(updateButtons()), this, SLOT(onUpdateButtons()));
|
|
||||||
_inner->setInstalled(
|
_inner->setInstalled(
|
||||||
) | rpl::start_with_next([this](auto &&setId) {
|
) | rpl::start_with_next([=](uint64 setId) {
|
||||||
Auth().api().stickerSetInstalled(setId);
|
Auth().api().stickerSetInstalled(setId);
|
||||||
this->closeBox();
|
closeBox();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerSetBox::onAddStickers() {
|
void StickerSetBox::addStickers() {
|
||||||
_inner->install();
|
_inner->install();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerSetBox::onShareStickers() {
|
void StickerSetBox::shareStickers() {
|
||||||
auto url = Messenger::Instance().createInternalLinkFull(qsl("addstickers/") + _inner->shortName());
|
auto url = Messenger::Instance().createInternalLinkFull(qsl("addstickers/") + _inner->shortName());
|
||||||
QApplication::clipboard()->setText(url);
|
QApplication::clipboard()->setText(url);
|
||||||
Ui::show(Box<InformBox>(lang(lng_stickers_copied)));
|
Ui::show(Box<InformBox>(lang(lng_stickers_copied)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerSetBox::onUpdateButtons() {
|
void StickerSetBox::updateTitleAndButtons() {
|
||||||
setTitle(_inner->title());
|
setTitle(_inner->title());
|
||||||
updateButtons();
|
updateButtons();
|
||||||
}
|
}
|
||||||
|
@ -76,16 +147,16 @@ void StickerSetBox::updateButtons() {
|
||||||
clearButtons();
|
clearButtons();
|
||||||
if (_inner->loaded()) {
|
if (_inner->loaded()) {
|
||||||
if (_inner->notInstalled()) {
|
if (_inner->notInstalled()) {
|
||||||
addButton(langFactory(lng_stickers_add_pack), [this] { onAddStickers(); });
|
addButton(langFactory(lng_stickers_add_pack), [=] { addStickers(); });
|
||||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
addButton(langFactory(lng_cancel), [=] { closeBox(); });
|
||||||
} else if (_inner->official()) {
|
} else if (_inner->official()) {
|
||||||
addButton(langFactory(lng_about_done), [this] { closeBox(); });
|
addButton(langFactory(lng_about_done), [=] { closeBox(); });
|
||||||
} else {
|
} else {
|
||||||
addButton(langFactory(lng_stickers_share_pack), [this] { onShareStickers(); });
|
addButton(langFactory(lng_stickers_share_pack), [=] { shareStickers(); });
|
||||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
addButton(langFactory(lng_cancel), [=] { closeBox(); });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
addButton(langFactory(lng_cancel), [=] { closeBox(); });
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -96,7 +167,8 @@ void StickerSetBox::resizeEvent(QResizeEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TWidget(parent)
|
StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TWidget(parent)
|
||||||
, _input(set) {
|
, _input(set)
|
||||||
|
, _previewTimer([=] { showPreview(); }) {
|
||||||
switch (set.type()) {
|
switch (set.type()) {
|
||||||
case mtpc_inputStickerSetID: _setId = set.c_inputStickerSetID().vid.v; _setAccess = set.c_inputStickerSetID().vaccess_hash.v; break;
|
case mtpc_inputStickerSetID: _setId = set.c_inputStickerSetID().vid.v; _setAccess = set.c_inputStickerSetID().vaccess_hash.v; break;
|
||||||
case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break;
|
case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break;
|
||||||
|
@ -107,9 +179,6 @@ StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TW
|
||||||
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
||||||
|
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
|
||||||
_previewTimer.setSingleShot(true);
|
|
||||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
|
void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
|
||||||
|
@ -183,8 +252,15 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
|
||||||
_loaded = true;
|
_loaded = true;
|
||||||
|
|
||||||
updateSelected();
|
updateSelected();
|
||||||
|
_updateControls.fire({});
|
||||||
|
}
|
||||||
|
|
||||||
emit updateButtons();
|
rpl::producer<uint64> StickerSetBox::Inner::setInstalled() const {
|
||||||
|
return _setInstalled.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> StickerSetBox::Inner::updateControls() const {
|
||||||
|
return _updateControls.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StickerSetBox::Inner::failedSet(const RPCError &error) {
|
bool StickerSetBox::Inner::failedSet(const RPCError &error) {
|
||||||
|
@ -273,7 +349,7 @@ bool StickerSetBox::Inner::installFail(const RPCError &error) {
|
||||||
void StickerSetBox::Inner::mousePressEvent(QMouseEvent *e) {
|
void StickerSetBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||||
int index = stickerFromGlobalPos(e->globalPos());
|
int index = stickerFromGlobalPos(e->globalPos());
|
||||||
if (index >= 0 && index < _pack.size()) {
|
if (index >= 0 && index < _pack.size()) {
|
||||||
_previewTimer.start(QApplication::startDragTime());
|
_previewTimer.callOnce(QApplication::startDragTime());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,10 +376,10 @@ void StickerSetBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_previewTimer.isActive()) {
|
if (_previewTimer.isActive()) {
|
||||||
_previewTimer.stop();
|
_previewTimer.cancel();
|
||||||
int index = stickerFromGlobalPos(e->globalPos());
|
const auto index = stickerFromGlobalPos(e->globalPos());
|
||||||
if (index >= 0 && index < _pack.size() && !isMasksSet()) {
|
if (index >= 0 && index < _pack.size() && !isMasksSet()) {
|
||||||
if (auto main = App::main()) {
|
if (const auto main = App::main()) {
|
||||||
if (main->onSendSticker(_pack[index])) {
|
if (main->onSendSticker(_pack[index])) {
|
||||||
Ui::hideSettingsAndLayer();
|
Ui::hideSettingsAndLayer();
|
||||||
}
|
}
|
||||||
|
@ -338,7 +414,7 @@ void StickerSetBox::Inner::startOverAnimation(int index, float64 from, float64 t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerSetBox::Inner::onPreview() {
|
void StickerSetBox::Inner::showPreview() {
|
||||||
int index = stickerFromGlobalPos(QCursor::pos());
|
int index = stickerFromGlobalPos(QCursor::pos());
|
||||||
if (index >= 0 && index < _pack.size()) {
|
if (index >= 0 && index < _pack.size()) {
|
||||||
_previewShown = index;
|
_previewShown = index;
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "boxes/abstract_box.h"
|
#include "boxes/abstract_box.h"
|
||||||
|
#include "base/timer.h"
|
||||||
#include "chat_helpers/stickers.h"
|
#include "chat_helpers/stickers.h"
|
||||||
|
|
||||||
class ConfirmBox;
|
class ConfirmBox;
|
||||||
|
@ -17,8 +18,6 @@ class PlainShadow;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class StickerSetBox : public BoxContent, public RPCSender {
|
class StickerSetBox : public BoxContent, public RPCSender {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StickerSetBox(QWidget*, const MTPInputStickerSet &set);
|
StickerSetBox(QWidget*, const MTPInputStickerSet &set);
|
||||||
|
|
||||||
|
@ -27,13 +26,11 @@ protected:
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onAddStickers();
|
|
||||||
void onShareStickers();
|
|
||||||
void onUpdateButtons();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateTitleAndButtons();
|
||||||
void updateButtons();
|
void updateButtons();
|
||||||
|
void addStickers();
|
||||||
|
void shareStickers();
|
||||||
|
|
||||||
MTPInputStickerSet _set;
|
MTPInputStickerSet _set;
|
||||||
|
|
||||||
|
@ -41,77 +38,3 @@ private:
|
||||||
QPointer<Inner> _inner;
|
QPointer<Inner> _inner;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class is hold in header because it requires Qt preprocessing.
|
|
||||||
class StickerSetBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
Inner(QWidget *parent, const MTPInputStickerSet &set);
|
|
||||||
|
|
||||||
bool loaded() const;
|
|
||||||
bool notInstalled() const;
|
|
||||||
bool official() const;
|
|
||||||
Fn<TextWithEntities()> title() const;
|
|
||||||
QString shortName() const;
|
|
||||||
|
|
||||||
void install();
|
|
||||||
auto setInstalled() const {
|
|
||||||
return _setInstalled.events();
|
|
||||||
}
|
|
||||||
|
|
||||||
~Inner();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
|
||||||
void paintEvent(QPaintEvent *e) override;
|
|
||||||
void leaveEventHook(QEvent *e) override;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onPreview();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void updateButtons();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateSelected();
|
|
||||||
void setSelected(int selected);
|
|
||||||
void startOverAnimation(int index, float64 from, float64 to);
|
|
||||||
int stickerFromGlobalPos(const QPoint &p) const;
|
|
||||||
|
|
||||||
void gotSet(const MTPmessages_StickerSet &set);
|
|
||||||
bool failedSet(const RPCError &error);
|
|
||||||
|
|
||||||
void installDone(const MTPmessages_StickerSetInstallResult &result);
|
|
||||||
bool installFail(const RPCError &error);
|
|
||||||
|
|
||||||
bool isMasksSet() const {
|
|
||||||
return (_setFlags & MTPDstickerSet::Flag::f_masks);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Animation> _packOvers;
|
|
||||||
Stickers::Pack _pack;
|
|
||||||
Stickers::ByEmojiMap _emoji;
|
|
||||||
bool _loaded = false;
|
|
||||||
uint64 _setId = 0;
|
|
||||||
uint64 _setAccess = 0;
|
|
||||||
QString _setTitle, _setShortName;
|
|
||||||
int _setCount = 0;
|
|
||||||
int32 _setHash = 0;
|
|
||||||
MTPDstickerSet::Flags _setFlags = 0;
|
|
||||||
TimeId _setInstallDate = TimeId(0);
|
|
||||||
|
|
||||||
MTPInputStickerSet _input;
|
|
||||||
|
|
||||||
mtpRequestId _installRequest = 0;
|
|
||||||
|
|
||||||
int _selected = -1;
|
|
||||||
|
|
||||||
QTimer _previewTimer;
|
|
||||||
int _previewShown = -1;
|
|
||||||
|
|
||||||
rpl::event_stream<uint64> _setInstalled;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
|
@ -18,6 +18,57 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace ChatHelpers {
|
namespace ChatHelpers {
|
||||||
|
|
||||||
|
class EmojiColorPicker : public Ui::RpWidget {
|
||||||
|
public:
|
||||||
|
EmojiColorPicker(QWidget *parent);
|
||||||
|
|
||||||
|
void showEmoji(EmojiPtr emoji);
|
||||||
|
|
||||||
|
void clearSelection();
|
||||||
|
void handleMouseMove(QPoint globalPos);
|
||||||
|
void handleMouseRelease(QPoint globalPos);
|
||||||
|
void setSingleSize(QSize size);
|
||||||
|
|
||||||
|
void showAnimated();
|
||||||
|
void hideAnimated();
|
||||||
|
void hideFast();
|
||||||
|
|
||||||
|
rpl::producer<EmojiPtr> chosen() const;
|
||||||
|
rpl::producer<> hidden() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void animationCallback();
|
||||||
|
void updateSize();
|
||||||
|
|
||||||
|
void drawVariant(Painter &p, int variant);
|
||||||
|
|
||||||
|
void updateSelected();
|
||||||
|
void setSelected(int newSelected);
|
||||||
|
|
||||||
|
bool _ignoreShow = false;
|
||||||
|
|
||||||
|
QVector<EmojiPtr> _variants;
|
||||||
|
|
||||||
|
int _selected = -1;
|
||||||
|
int _pressedSel = -1;
|
||||||
|
QPoint _lastMousePos;
|
||||||
|
QSize _singleSize;
|
||||||
|
|
||||||
|
bool _hiding = false;
|
||||||
|
QPixmap _cache;
|
||||||
|
Animation _a_opacity;
|
||||||
|
|
||||||
|
rpl::event_stream<EmojiPtr> _chosen;
|
||||||
|
rpl::event_stream<> _hidden;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class EmojiListWidget::Footer : public TabbedSelector::InnerFooter {
|
class EmojiListWidget::Footer : public TabbedSelector::InnerFooter {
|
||||||
public:
|
public:
|
||||||
Footer(not_null<EmojiListWidget*> parent);
|
Footer(not_null<EmojiListWidget*> parent);
|
||||||
|
@ -95,11 +146,9 @@ void EmojiListWidget::Footer::setActiveSection(Ui::Emoji::Section section) {
|
||||||
_pan->showEmojiSection(section);
|
_pan->showEmojiSection(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
EmojiColorPicker::EmojiColorPicker(QWidget *parent) : TWidget(parent) {
|
EmojiColorPicker::EmojiColorPicker(QWidget *parent)
|
||||||
|
: RpWidget(parent) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
|
||||||
_hideTimer.setSingleShot(true);
|
|
||||||
connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideAnimated()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiColorPicker::showEmoji(EmojiPtr emoji) {
|
void EmojiColorPicker::showEmoji(EmojiPtr emoji) {
|
||||||
|
@ -167,16 +216,6 @@ void EmojiColorPicker::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiColorPicker::enterEventHook(QEvent *e) {
|
|
||||||
_hideTimer.stop();
|
|
||||||
if (_hiding) showAnimated();
|
|
||||||
TWidget::enterEventHook(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmojiColorPicker::leaveEventHook(QEvent *e) {
|
|
||||||
TWidget::leaveEventHook(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmojiColorPicker::mousePressEvent(QMouseEvent *e) {
|
void EmojiColorPicker::mousePressEvent(QMouseEvent *e) {
|
||||||
if (e->button() != Qt::LeftButton) {
|
if (e->button() != Qt::LeftButton) {
|
||||||
return;
|
return;
|
||||||
|
@ -197,7 +236,7 @@ void EmojiColorPicker::handleMouseRelease(QPoint globalPos) {
|
||||||
|
|
||||||
updateSelected();
|
updateSelected();
|
||||||
if (_selected >= 0 && (pressed < 0 || _selected == pressed)) {
|
if (_selected >= 0 && (pressed < 0 || _selected == pressed)) {
|
||||||
emit emojiSelected(_variants[_selected]);
|
_chosen.fire_copy(_variants[_selected]);
|
||||||
}
|
}
|
||||||
_ignoreShow = true;
|
_ignoreShow = true;
|
||||||
hideAnimated();
|
hideAnimated();
|
||||||
|
@ -223,7 +262,7 @@ void EmojiColorPicker::animationCallback() {
|
||||||
_cache = QPixmap();
|
_cache = QPixmap();
|
||||||
if (_hiding) {
|
if (_hiding) {
|
||||||
hide();
|
hide();
|
||||||
emit hidden();
|
_hidden.fire({});
|
||||||
} else {
|
} else {
|
||||||
_lastMousePos = QCursor::pos();
|
_lastMousePos = QCursor::pos();
|
||||||
updateSelected();
|
updateSelected();
|
||||||
|
@ -236,7 +275,15 @@ void EmojiColorPicker::hideFast() {
|
||||||
_a_opacity.finish();
|
_a_opacity.finish();
|
||||||
_cache = QPixmap();
|
_cache = QPixmap();
|
||||||
hide();
|
hide();
|
||||||
emit hidden();
|
_hidden.fire({});
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<EmojiPtr> EmojiColorPicker::chosen() const {
|
||||||
|
return _chosen.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> EmojiColorPicker::hidden() const {
|
||||||
|
return _hidden.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiColorPicker::hideAnimated() {
|
void EmojiColorPicker::hideAnimated() {
|
||||||
|
@ -333,7 +380,8 @@ EmojiListWidget::EmojiListWidget(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Window::Controller*> controller)
|
not_null<Window::Controller*> controller)
|
||||||
: Inner(parent, controller)
|
: Inner(parent, controller)
|
||||||
, _picker(this) {
|
, _picker(this)
|
||||||
|
, _showPickerTimer([=] { showPicker(); }) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
||||||
|
@ -345,10 +393,18 @@ EmojiListWidget::EmojiListWidget(
|
||||||
_counts[i] = Ui::Emoji::GetSectionCount(static_cast<Section>(i));
|
_counts[i] = Ui::Emoji::GetSectionCount(static_cast<Section>(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
_showPickerTimer.setSingleShot(true);
|
_picker->chosen(
|
||||||
connect(&_showPickerTimer, SIGNAL(timeout()), this, SLOT(onShowPicker()));
|
) | rpl::start_with_next([=](EmojiPtr emoji) {
|
||||||
connect(_picker, SIGNAL(emojiSelected(EmojiPtr)), this, SLOT(onColorSelected(EmojiPtr)));
|
colorChosen(emoji);
|
||||||
connect(_picker, SIGNAL(hidden()), this, SLOT(onPickerHidden()));
|
}, lifetime());
|
||||||
|
_picker->hidden(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
pickerHidden();
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<EmojiPtr> EmojiListWidget::chosen() const {
|
||||||
|
return _chosen.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiListWidget::visibleTopBottomUpdated(
|
void EmojiListWidget::visibleTopBottomUpdated(
|
||||||
|
@ -529,9 +585,9 @@ void EmojiListWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
_pickerSel = _selected;
|
_pickerSel = _selected;
|
||||||
setCursor(style::cur_default);
|
setCursor(style::cur_default);
|
||||||
if (!cEmojiVariants().contains(_emoji[section][sel]->nonColoredId())) {
|
if (!cEmojiVariants().contains(_emoji[section][sel]->nonColoredId())) {
|
||||||
onShowPicker();
|
showPicker();
|
||||||
} else {
|
} else {
|
||||||
_showPickerTimer.start(500);
|
_showPickerTimer.callOnce(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,7 +615,7 @@ void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
updateSelected();
|
updateSelected();
|
||||||
|
|
||||||
if (_showPickerTimer.isActive()) {
|
if (_showPickerTimer.isActive()) {
|
||||||
_showPickerTimer.stop();
|
_showPickerTimer.cancel();
|
||||||
_pickerSel = -1;
|
_pickerSel = -1;
|
||||||
_picker->hide();
|
_picker->hide();
|
||||||
}
|
}
|
||||||
|
@ -582,10 +638,10 @@ void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
|
||||||
void EmojiListWidget::selectEmoji(EmojiPtr emoji) {
|
void EmojiListWidget::selectEmoji(EmojiPtr emoji) {
|
||||||
Ui::Emoji::AddRecent(emoji);
|
Ui::Emoji::AddRecent(emoji);
|
||||||
emit selected(emoji);
|
_chosen.fire_copy(emoji);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiListWidget::onShowPicker() {
|
void EmojiListWidget::showPicker() {
|
||||||
if (_pickerSel < 0) return;
|
if (_pickerSel < 0) return;
|
||||||
|
|
||||||
auto section = (_pickerSel / MatrixRowShift);
|
auto section = (_pickerSel / MatrixRowShift);
|
||||||
|
@ -607,7 +663,7 @@ void EmojiListWidget::onShowPicker() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiListWidget::onPickerHidden() {
|
void EmojiListWidget::pickerHidden() {
|
||||||
_pickerSel = -1;
|
_pickerSel = -1;
|
||||||
update();
|
update();
|
||||||
emit disableScroll(false);
|
emit disableScroll(false);
|
||||||
|
@ -627,7 +683,7 @@ QRect EmojiListWidget::emojiRect(int section, int sel) {
|
||||||
return QRect(x, y, _singleSize.width(), _singleSize.height());
|
return QRect(x, y, _singleSize.width(), _singleSize.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiListWidget::onColorSelected(EmojiPtr emoji) {
|
void EmojiListWidget::colorChosen(EmojiPtr emoji) {
|
||||||
if (emoji->hasVariants()) {
|
if (emoji->hasVariants()) {
|
||||||
cRefEmojiVariants().insert(
|
cRefEmojiVariants().insert(
|
||||||
emoji->nonColoredId(),
|
emoji->nonColoredId(),
|
||||||
|
@ -792,7 +848,7 @@ void EmojiListWidget::showEmojiSection(Section section) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
emit scrollToY(y);
|
scrollTo(y);
|
||||||
|
|
||||||
_lastMousePos = QCursor::pos();
|
_lastMousePos = QCursor::pos();
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "chat_helpers/tabbed_selector.h"
|
#include "chat_helpers/tabbed_selector.h"
|
||||||
#include "ui/widgets/tooltip.h"
|
#include "ui/widgets/tooltip.h"
|
||||||
|
#include "base/timer.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace Emoji {
|
namespace Emoji {
|
||||||
|
@ -24,66 +25,11 @@ namespace ChatHelpers {
|
||||||
|
|
||||||
constexpr auto kEmojiSectionCount = 8;
|
constexpr auto kEmojiSectionCount = 8;
|
||||||
|
|
||||||
class EmojiColorPicker : public TWidget {
|
class EmojiColorPicker;
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
EmojiColorPicker(QWidget *parent);
|
|
||||||
|
|
||||||
void showEmoji(EmojiPtr emoji);
|
|
||||||
|
|
||||||
void clearSelection();
|
|
||||||
void handleMouseMove(QPoint globalPos);
|
|
||||||
void handleMouseRelease(QPoint globalPos);
|
|
||||||
void setSingleSize(QSize size);
|
|
||||||
|
|
||||||
void hideFast();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void showAnimated();
|
|
||||||
void hideAnimated();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void emojiSelected(EmojiPtr emoji);
|
|
||||||
void hidden();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent *e) override;
|
|
||||||
void enterEventHook(QEvent *e) override;
|
|
||||||
void leaveEventHook(QEvent *e) override;
|
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void animationCallback();
|
|
||||||
void updateSize();
|
|
||||||
|
|
||||||
void drawVariant(Painter &p, int variant);
|
|
||||||
|
|
||||||
void updateSelected();
|
|
||||||
void setSelected(int newSelected);
|
|
||||||
|
|
||||||
bool _ignoreShow = false;
|
|
||||||
|
|
||||||
QVector<EmojiPtr> _variants;
|
|
||||||
|
|
||||||
int _selected = -1;
|
|
||||||
int _pressedSel = -1;
|
|
||||||
QPoint _lastMousePos;
|
|
||||||
QSize _singleSize;
|
|
||||||
|
|
||||||
bool _hiding = false;
|
|
||||||
QPixmap _cache;
|
|
||||||
Animation _a_opacity;
|
|
||||||
|
|
||||||
QTimer _hideTimer;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class EmojiListWidget : public TabbedSelector::Inner, public Ui::AbstractTooltipShower {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
|
class EmojiListWidget
|
||||||
|
: public TabbedSelector::Inner
|
||||||
|
, public Ui::AbstractTooltipShower {
|
||||||
public:
|
public:
|
||||||
EmojiListWidget(QWidget *parent, not_null<Window::Controller*> controller);
|
EmojiListWidget(QWidget *parent, not_null<Window::Controller*> controller);
|
||||||
|
|
||||||
|
@ -100,16 +46,7 @@ public:
|
||||||
QString tooltipText() const override;
|
QString tooltipText() const override;
|
||||||
QPoint tooltipPos() const override;
|
QPoint tooltipPos() const override;
|
||||||
|
|
||||||
public slots:
|
rpl::producer<EmojiPtr> chosen() const;
|
||||||
void onShowPicker();
|
|
||||||
void onPickerHidden();
|
|
||||||
void onColorSelected(EmojiPtr emoji);
|
|
||||||
|
|
||||||
bool checkPickerHide();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void selected(EmojiPtr emoji);
|
|
||||||
void switchToStickers();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void visibleTopBottomUpdated(
|
void visibleTopBottomUpdated(
|
||||||
|
@ -146,8 +83,12 @@ private:
|
||||||
SectionInfo sectionInfo(int section) const;
|
SectionInfo sectionInfo(int section) const;
|
||||||
SectionInfo sectionInfoByOffset(int yOffset) const;
|
SectionInfo sectionInfoByOffset(int yOffset) const;
|
||||||
|
|
||||||
|
void showPicker();
|
||||||
|
void pickerHidden();
|
||||||
|
void colorChosen(EmojiPtr emoji);
|
||||||
|
bool checkPickerHide();
|
||||||
|
|
||||||
void ensureLoaded(int section);
|
void ensureLoaded(int section);
|
||||||
int countSectionTop(int section) const;
|
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
void setSelected(int newSelected);
|
void setSelected(int newSelected);
|
||||||
|
|
||||||
|
@ -171,7 +112,9 @@ private:
|
||||||
QPoint _lastMousePos;
|
QPoint _lastMousePos;
|
||||||
|
|
||||||
object_ptr<EmojiColorPicker> _picker;
|
object_ptr<EmojiColorPicker> _picker;
|
||||||
QTimer _showPickerTimer;
|
base::Timer _showPickerTimer;
|
||||||
|
|
||||||
|
rpl::event_stream<EmojiPtr> _chosen;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -513,15 +513,7 @@ FieldAutocompleteInner::FieldAutocompleteInner(FieldAutocomplete *parent, Mentio
|
||||||
, _hrows(hrows)
|
, _hrows(hrows)
|
||||||
, _brows(brows)
|
, _brows(brows)
|
||||||
, _srows(srows)
|
, _srows(srows)
|
||||||
, _stickersPerRow(1)
|
, _previewTimer([=] { showPreview(); }) {
|
||||||
, _recentInlineBotsInRows(0)
|
|
||||||
, _sel(-1)
|
|
||||||
, _down(-1)
|
|
||||||
, _mouseSel(false)
|
|
||||||
, _overDelete(false)
|
|
||||||
, _previewShown(false) {
|
|
||||||
_previewTimer.setSingleShot(true);
|
|
||||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
|
||||||
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,13 +798,13 @@ void FieldAutocompleteInner::mousePressEvent(QMouseEvent *e) {
|
||||||
chooseSelected(FieldAutocomplete::ChooseMethod::ByClick);
|
chooseSelected(FieldAutocomplete::ChooseMethod::ByClick);
|
||||||
} else {
|
} else {
|
||||||
_down = _sel;
|
_down = _sel;
|
||||||
_previewTimer.start(QApplication::startDragTime());
|
_previewTimer.callOnce(QApplication::startDragTime());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FieldAutocompleteInner::mouseReleaseEvent(QMouseEvent *e) {
|
void FieldAutocompleteInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
_previewTimer.stop();
|
_previewTimer.cancel();
|
||||||
|
|
||||||
int32 pressed = _down;
|
int32 pressed = _down;
|
||||||
_down = -1;
|
_down = -1;
|
||||||
|
@ -915,7 +907,7 @@ void FieldAutocompleteInner::onParentGeometryChanged() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FieldAutocompleteInner::onPreview() {
|
void FieldAutocompleteInner::showPreview() {
|
||||||
if (_down >= 0 && _down < _srows->size()) {
|
if (_down >= 0 && _down < _srows->size()) {
|
||||||
Ui::showMediaPreview(
|
Ui::showMediaPreview(
|
||||||
(*_srows)[_down]->stickerSetOrigin(),
|
(*_srows)[_down]->stickerSetOrigin(),
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/twidget.h"
|
#include "ui/twidget.h"
|
||||||
|
#include "base/timer.h"
|
||||||
#include "chat_helpers/stickers.h"
|
#include "chat_helpers/stickers.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -152,7 +153,6 @@ signals:
|
||||||
public slots:
|
public slots:
|
||||||
void onParentGeometryChanged();
|
void onParentGeometryChanged();
|
||||||
void onUpdateSelected(bool force = false);
|
void onUpdateSelected(bool force = false);
|
||||||
void onPreview();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
@ -167,22 +167,25 @@ private:
|
||||||
|
|
||||||
void updateSelectedRow();
|
void updateSelectedRow();
|
||||||
void setSel(int sel, bool scroll = false);
|
void setSel(int sel, bool scroll = false);
|
||||||
|
void showPreview();
|
||||||
|
|
||||||
FieldAutocomplete *_parent;
|
FieldAutocomplete *_parent = nullptr;
|
||||||
MentionRows *_mrows;
|
MentionRows *_mrows = nullptr;
|
||||||
HashtagRows *_hrows;
|
HashtagRows *_hrows = nullptr;
|
||||||
BotCommandRows *_brows;
|
BotCommandRows *_brows = nullptr;
|
||||||
StickerRows *_srows;
|
StickerRows *_srows = nullptr;
|
||||||
int32 _stickersPerRow, _recentInlineBotsInRows;
|
int _stickersPerRow = 1;
|
||||||
int32 _sel, _down;
|
int _recentInlineBotsInRows = 0;
|
||||||
bool _mouseSel;
|
int _sel = -1;
|
||||||
|
int _down = -1;
|
||||||
|
bool _mouseSel = false;
|
||||||
QPoint _mousePos;
|
QPoint _mousePos;
|
||||||
|
|
||||||
bool _overDelete;
|
bool _overDelete = false;
|
||||||
|
|
||||||
bool _previewShown;
|
bool _previewShown = false;
|
||||||
|
|
||||||
QTimer _previewTimer;
|
base::Timer _previewTimer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ GifsListWidget::Footer::Footer(not_null<GifsListWidget*> parent) : InnerFooter(p
|
||||||
});
|
});
|
||||||
connect(_field, &Ui::InputField::cancelled, [=] {
|
connect(_field, &Ui::InputField::cancelled, [=] {
|
||||||
if (_field->getLastText().isEmpty()) {
|
if (_field->getLastText().isEmpty()) {
|
||||||
emit _pan->cancelled();
|
_pan->cancelled();
|
||||||
} else {
|
} else {
|
||||||
_field->setText(QString());
|
_field->setText(QString());
|
||||||
}
|
}
|
||||||
|
@ -125,16 +125,12 @@ GifsListWidget::GifsListWidget(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Window::Controller*> controller)
|
not_null<Window::Controller*> controller)
|
||||||
: Inner(parent, controller)
|
: Inner(parent, controller)
|
||||||
, _section(Section::Gifs) {
|
, _section(Section::Gifs)
|
||||||
|
, _updateInlineItems([=] { updateInlineItems(); })
|
||||||
|
, _previewTimer([=] { showPreview(); }) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
||||||
_previewTimer.setSingleShot(true);
|
|
||||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
|
||||||
|
|
||||||
_updateInlineItems.setSingleShot(true);
|
|
||||||
connect(&_updateInlineItems, SIGNAL(timeout()), this, SLOT(onUpdateInlineItems()));
|
|
||||||
|
|
||||||
_inlineRequestTimer.setSingleShot(true);
|
_inlineRequestTimer.setSingleShot(true);
|
||||||
connect(&_inlineRequestTimer, &QTimer::timeout, this, [this] { sendInlineRequest(); });
|
connect(&_inlineRequestTimer, &QTimer::timeout, this, [this] { sendInlineRequest(); });
|
||||||
|
|
||||||
|
@ -152,8 +148,22 @@ GifsListWidget::GifsListWidget(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<not_null<DocumentData*>> GifsListWidget::fileChosen() const {
|
||||||
|
return _fileChosen.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<not_null<PhotoData*>> GifsListWidget::photoChosen() const {
|
||||||
|
return _photoChosen.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GifsListWidget::inlineResultChosen() const
|
||||||
|
-> rpl::producer<InlineChosen> {
|
||||||
|
return _inlineResultChosen.events();
|
||||||
|
}
|
||||||
|
|
||||||
object_ptr<TabbedSelector::InnerFooter> GifsListWidget::createFooter() {
|
object_ptr<TabbedSelector::InnerFooter> GifsListWidget::createFooter() {
|
||||||
Expects(_footer == nullptr);
|
Expects(_footer == nullptr);
|
||||||
|
|
||||||
auto result = object_ptr<Footer>(this);
|
auto result = object_ptr<Footer>(this);
|
||||||
_footer = result;
|
_footer = result;
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
|
@ -305,11 +315,11 @@ void GifsListWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
|
|
||||||
_pressed = _selected;
|
_pressed = _selected;
|
||||||
ClickHandler::pressed();
|
ClickHandler::pressed();
|
||||||
_previewTimer.start(QApplication::startDragTime());
|
_previewTimer.callOnce(QApplication::startDragTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
_previewTimer.stop();
|
_previewTimer.cancel();
|
||||||
|
|
||||||
auto pressed = std::exchange(_pressed, -1);
|
auto pressed = std::exchange(_pressed, -1);
|
||||||
auto activated = ClickHandler::unpressed();
|
auto activated = ClickHandler::unpressed();
|
||||||
|
@ -340,29 +350,28 @@ void GifsListWidget::selectInlineResult(int row, int column) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto item = _rows[row].items[column];
|
auto item = _rows[row].items[column];
|
||||||
if (auto photo = item->getPhoto()) {
|
if (const auto photo = item->getPhoto()) {
|
||||||
if (photo->medium->loaded() || photo->thumb->loaded()) {
|
if (photo->medium->loaded() || photo->thumb->loaded()) {
|
||||||
emit selected(photo);
|
_photoChosen.fire_copy(photo);
|
||||||
} else if (!photo->medium->loading()) {
|
} else if (!photo->medium->loading()) {
|
||||||
photo->thumb->loadEvenCancelled(Data::FileOrigin());
|
photo->thumb->loadEvenCancelled(Data::FileOrigin());
|
||||||
photo->medium->loadEvenCancelled(Data::FileOrigin());
|
photo->medium->loadEvenCancelled(Data::FileOrigin());
|
||||||
}
|
}
|
||||||
} else if (const auto document = item->getDocument()) {
|
} else if (const auto document = item->getDocument()) {
|
||||||
if (document->loaded()) {
|
if (document->loaded()) {
|
||||||
emit selected(document);
|
_fileChosen.fire_copy(document);
|
||||||
} else if (document->loading()) {
|
} else if (document->loading()) {
|
||||||
document->cancel();
|
document->cancel();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
DocumentOpenClickHandler::Open(
|
DocumentOpenClickHandler::Open(
|
||||||
document->stickerOrGifOrigin(),
|
document->stickerOrGifOrigin(),
|
||||||
document,
|
document,
|
||||||
nullptr,
|
nullptr,
|
||||||
ActionOnLoadNone);
|
ActionOnLoadNone);
|
||||||
}
|
}
|
||||||
} else if (auto inlineResult = item->getResult()) {
|
} else if (const auto inlineResult = item->getResult()) {
|
||||||
if (inlineResult->onChoose(item)) {
|
if (inlineResult->onChoose(item)) {
|
||||||
emit selected(inlineResult, _searchBot);
|
_inlineResultChosen.fire({ inlineResult, _searchBot });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -622,8 +631,7 @@ void GifsListWidget::switchToSavedGifs() {
|
||||||
clearInlineRows(false);
|
clearInlineRows(false);
|
||||||
_section = Section::Gifs;
|
_section = Section::Gifs;
|
||||||
refreshSavedGifs();
|
refreshSavedGifs();
|
||||||
emit scrollToY(0);
|
scrollTo(0);
|
||||||
emit scrollUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GifsListWidget::refreshInlineRows(const InlineCacheEntry *entry, bool resultsDeleted) {
|
int GifsListWidget::refreshInlineRows(const InlineCacheEntry *entry, bool resultsDeleted) {
|
||||||
|
@ -747,7 +755,7 @@ void GifsListWidget::inlineItemRepaint(const InlineBots::Layout::ItemBase *layou
|
||||||
if (_lastScrolled + 100 <= ms) {
|
if (_lastScrolled + 100 <= ms) {
|
||||||
update();
|
update();
|
||||||
} else {
|
} else {
|
||||||
_updateInlineItems.start(_lastScrolled + 100 - ms);
|
_updateInlineItems.callOnce(_lastScrolled + 100 - ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,7 +812,7 @@ int32 GifsListWidget::showInlineRows(bool newResults) {
|
||||||
auto added = 0;
|
auto added = 0;
|
||||||
auto clear = !refreshInlineRows(&added);
|
auto clear = !refreshInlineRows(&added);
|
||||||
if (newResults) {
|
if (newResults) {
|
||||||
scrollToY(0);
|
scrollTo(0);
|
||||||
}
|
}
|
||||||
return added;
|
return added;
|
||||||
}
|
}
|
||||||
|
@ -847,6 +855,14 @@ void GifsListWidget::searchForGifs(const QString &query) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GifsListWidget::cancelled() {
|
||||||
|
_cancelled.fire({});
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> GifsListWidget::cancelRequests() const {
|
||||||
|
return _cancelled.events();
|
||||||
|
}
|
||||||
|
|
||||||
void GifsListWidget::sendInlineRequest() {
|
void GifsListWidget::sendInlineRequest() {
|
||||||
if (_inlineRequestId || !_inlineQueryPeer || _inlineNextQuery.isEmpty()) {
|
if (_inlineRequestId || !_inlineQueryPeer || _inlineNextQuery.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -977,8 +993,10 @@ void GifsListWidget::updateSelected() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifsListWidget::onPreview() {
|
void GifsListWidget::showPreview() {
|
||||||
if (_pressed < 0) return;
|
if (_pressed < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int row = _pressed / MatrixRowShift, col = _pressed % MatrixRowShift;
|
int row = _pressed / MatrixRowShift, col = _pressed % MatrixRowShift;
|
||||||
if (row < _rows.size() && col < _rows[row].items.size()) {
|
if (row < _rows.size() && col < _rows[row].items.size()) {
|
||||||
auto layout = _rows[row].items[col];
|
auto layout = _rows[row].items[col];
|
||||||
|
@ -996,12 +1014,12 @@ void GifsListWidget::onPreview() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifsListWidget::onUpdateInlineItems() {
|
void GifsListWidget::updateInlineItems() {
|
||||||
auto ms = getms();
|
auto ms = getms();
|
||||||
if (_lastScrolled + 100 <= ms) {
|
if (_lastScrolled + 100 <= ms) {
|
||||||
update();
|
update();
|
||||||
} else {
|
} else {
|
||||||
_updateInlineItems.start(_lastScrolled + 100 - ms);
|
_updateInlineItems.callOnce(_lastScrolled + 100 - ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "chat_helpers/tabbed_selector.h"
|
#include "chat_helpers/tabbed_selector.h"
|
||||||
|
#include "base/timer.h"
|
||||||
#include "inline_bots/inline_bot_layout_item.h"
|
#include "inline_bots/inline_bot_layout_item.h"
|
||||||
|
|
||||||
namespace InlineBots {
|
namespace InlineBots {
|
||||||
|
@ -32,11 +33,15 @@ class GifsListWidget
|
||||||
, public InlineBots::Layout::Context
|
, public InlineBots::Layout::Context
|
||||||
, private base::Subscriber
|
, private base::Subscriber
|
||||||
, private MTP::Sender {
|
, private MTP::Sender {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using InlineChosen = TabbedSelector::InlineChosen;
|
||||||
|
|
||||||
GifsListWidget(QWidget *parent, not_null<Window::Controller*> controller);
|
GifsListWidget(QWidget *parent, not_null<Window::Controller*> controller);
|
||||||
|
|
||||||
|
rpl::producer<not_null<DocumentData*>> fileChosen() const;
|
||||||
|
rpl::producer<not_null<PhotoData*>> photoChosen() const;
|
||||||
|
rpl::producer<InlineChosen> inlineResultChosen() const;
|
||||||
|
|
||||||
void refreshRecent() override;
|
void refreshRecent() override;
|
||||||
void preloadImages() override;
|
void preloadImages() override;
|
||||||
void clearSelection() override;
|
void clearSelection() override;
|
||||||
|
@ -56,6 +61,9 @@ public:
|
||||||
void searchForGifs(const QString &query);
|
void searchForGifs(const QString &query);
|
||||||
void sendInlineRequest();
|
void sendInlineRequest();
|
||||||
|
|
||||||
|
void cancelled();
|
||||||
|
rpl::producer<> cancelRequests() const;
|
||||||
|
|
||||||
~GifsListWidget();
|
~GifsListWidget();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -76,21 +84,6 @@ protected:
|
||||||
void processPanelHideFinished() override;
|
void processPanelHideFinished() override;
|
||||||
int countDesiredHeight(int newWidth) override;
|
int countDesiredHeight(int newWidth) override;
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onPreview();
|
|
||||||
void onUpdateInlineItems();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void selected(not_null<DocumentData*> sticker);
|
|
||||||
void selected(not_null<PhotoData*> photo);
|
|
||||||
void selected(
|
|
||||||
not_null<InlineBots::Result*> result,
|
|
||||||
not_null<UserData*> bot);
|
|
||||||
void cancelled();
|
|
||||||
|
|
||||||
void emptyInlineRows();
|
|
||||||
void scrollUpdated();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Section {
|
enum class Section {
|
||||||
Inlines,
|
Inlines,
|
||||||
|
@ -120,9 +113,12 @@ private:
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
void paintInlineItems(Painter &p, QRect clip);
|
void paintInlineItems(Painter &p, QRect clip);
|
||||||
|
|
||||||
|
void updateInlineItems();
|
||||||
|
void showPreview();
|
||||||
|
|
||||||
Section _section = Section::Gifs;
|
Section _section = Section::Gifs;
|
||||||
TimeMs _lastScrolled = 0;
|
TimeMs _lastScrolled = 0;
|
||||||
QTimer _updateInlineItems;
|
base::Timer _updateInlineItems;
|
||||||
bool _inlineWithThumb = false;
|
bool _inlineWithThumb = false;
|
||||||
|
|
||||||
struct Row {
|
struct Row {
|
||||||
|
@ -156,7 +152,7 @@ private:
|
||||||
int _pressed = -1;
|
int _pressed = -1;
|
||||||
QPoint _lastMousePos;
|
QPoint _lastMousePos;
|
||||||
|
|
||||||
QTimer _previewTimer;
|
base::Timer _previewTimer;
|
||||||
bool _previewShown = false;
|
bool _previewShown = false;
|
||||||
|
|
||||||
std::map<QString, std::unique_ptr<InlineCacheEntry>> _inlineCache;
|
std::map<QString, std::unique_ptr<InlineCacheEntry>> _inlineCache;
|
||||||
|
@ -168,6 +164,11 @@ private:
|
||||||
QString _inlineQuery, _inlineNextQuery, _inlineNextOffset;
|
QString _inlineQuery, _inlineNextQuery, _inlineNextOffset;
|
||||||
mtpRequestId _inlineRequestId = 0;
|
mtpRequestId _inlineRequestId = 0;
|
||||||
|
|
||||||
|
rpl::event_stream<not_null<DocumentData*>> _fileChosen;
|
||||||
|
rpl::event_stream<not_null<PhotoData*>> _photoChosen;
|
||||||
|
rpl::event_stream<InlineChosen> _inlineResultChosen;
|
||||||
|
rpl::event_stream<> _cancelled;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ChatHelpers
|
} // namespace ChatHelpers
|
||||||
|
|
|
@ -682,14 +682,14 @@ StickersListWidget::StickersListWidget(QWidget *parent, not_null<Window::Control
|
||||||
, _addText(lang(lng_stickers_featured_add).toUpper())
|
, _addText(lang(lng_stickers_featured_add).toUpper())
|
||||||
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
|
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
|
||||||
, _settings(this, lang(lng_stickers_you_have))
|
, _settings(this, lang(lng_stickers_you_have))
|
||||||
|
, _previewTimer([=] { showPreview(); })
|
||||||
, _searchRequestTimer([=] { sendSearchRequest(); }) {
|
, _searchRequestTimer([=] { sendSearchRequest(); }) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
||||||
connect(_settings, SIGNAL(clicked()), this, SLOT(onSettings()));
|
_settings->addClickHandler([] {
|
||||||
|
Ui::show(Box<StickersBox>(StickersBox::Section::Installed));
|
||||||
_previewTimer.setSingleShot(true);
|
});
|
||||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
|
||||||
|
|
||||||
subscribe(Auth().downloaderTaskFinished(), [=] {
|
subscribe(Auth().downloaderTaskFinished(), [=] {
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
|
@ -704,8 +704,21 @@ StickersListWidget::StickersListWidget(QWidget *parent, not_null<Window::Control
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<not_null<DocumentData*>> StickersListWidget::chosen() const {
|
||||||
|
return _chosen.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> StickersListWidget::scrollUpdated() const {
|
||||||
|
return _scrollUpdated.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> StickersListWidget::checkForHide() const {
|
||||||
|
return _checkForHide.events();
|
||||||
|
}
|
||||||
|
|
||||||
object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
|
object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
|
||||||
Expects(_footer == nullptr);
|
Expects(_footer == nullptr);
|
||||||
|
|
||||||
auto result = object_ptr<Footer>(this);
|
auto result = object_ptr<Footer>(this);
|
||||||
_footer = result;
|
_footer = result;
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
|
@ -927,7 +940,7 @@ void StickersListWidget::cancelSetsSearch() {
|
||||||
|
|
||||||
void StickersListWidget::showSearchResults() {
|
void StickersListWidget::showSearchResults() {
|
||||||
refreshSearchRows();
|
refreshSearchRows();
|
||||||
scrollToY(0);
|
scrollTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::refreshSearchRows() {
|
void StickersListWidget::refreshSearchRows() {
|
||||||
|
@ -1418,7 +1431,7 @@ void StickersListWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
|
|
||||||
setPressed(_selected);
|
setPressed(_selected);
|
||||||
ClickHandler::pressed();
|
ClickHandler::pressed();
|
||||||
_previewTimer.start(QApplication::startDragTime());
|
_previewTimer.callOnce(QApplication::startDragTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::setPressed(OverState newPressed) {
|
void StickersListWidget::setPressed(OverState newPressed) {
|
||||||
|
@ -1498,7 +1511,7 @@ QPoint StickersListWidget::buttonRippleTopLeft(int section) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
_previewTimer.stop();
|
_previewTimer.cancel();
|
||||||
|
|
||||||
auto pressed = _pressed;
|
auto pressed = _pressed;
|
||||||
setPressed(std::nullopt);
|
setPressed(std::nullopt);
|
||||||
|
@ -1531,7 +1544,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit selected(set.pack[sticker->index]);
|
_chosen.fire_copy(set.pack[sticker->index]);
|
||||||
} else if (auto set = base::get_if<OverSet>(&pressed)) {
|
} else if (auto set = base::get_if<OverSet>(&pressed)) {
|
||||||
Assert(set->section >= 0 && set->section < sets.size());
|
Assert(set->section >= 0 && set->section < sets.size());
|
||||||
displaySet(sets[set->section].id);
|
displaySet(sets[set->section].id);
|
||||||
|
@ -2170,15 +2183,11 @@ void StickersListWidget::setSelected(OverState newSelected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListWidget::onSettings() {
|
void StickersListWidget::showPreview() {
|
||||||
Ui::show(Box<StickersBox>(StickersBox::Section::Installed));
|
if (const auto sticker = base::get_if<OverSticker>(&_pressed)) {
|
||||||
}
|
const auto &sets = shownSets();
|
||||||
|
|
||||||
void StickersListWidget::onPreview() {
|
|
||||||
if (auto sticker = base::get_if<OverSticker>(&_pressed)) {
|
|
||||||
auto &sets = shownSets();
|
|
||||||
Assert(sticker->section >= 0 && sticker->section < sets.size());
|
Assert(sticker->section >= 0 && sticker->section < sets.size());
|
||||||
auto &set = sets[sticker->section];
|
const auto &set = sets[sticker->section];
|
||||||
Assert(sticker->index >= 0 && sticker->index < set.pack.size());
|
Assert(sticker->index >= 0 && sticker->index < set.pack.size());
|
||||||
Ui::showMediaPreview(
|
Ui::showMediaPreview(
|
||||||
set.pack[sticker->index]->stickerSetOrigin(),
|
set.pack[sticker->index]->stickerSetOrigin(),
|
||||||
|
@ -2202,8 +2211,8 @@ void StickersListWidget::showStickerSet(uint64 setId) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
emit scrollToY(0);
|
scrollTo(0);
|
||||||
emit scrollUpdated();
|
_scrollUpdated.fire({});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2222,8 +2231,8 @@ void StickersListWidget::showStickerSet(uint64 setId) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
emit scrollToY(y);
|
scrollTo(y);
|
||||||
emit scrollUpdated();
|
_scrollUpdated.fire({});
|
||||||
|
|
||||||
if (needRefresh && _footer) {
|
if (needRefresh && _footer) {
|
||||||
_footer->refreshIcons(ValidateIconAnimations::Scroll);
|
_footer->refreshIcons(ValidateIconAnimations::Scroll);
|
||||||
|
@ -2281,7 +2290,7 @@ void StickersListWidget::displaySet(uint64 setId) {
|
||||||
auto box = Ui::show(Box<StickersBox>(_megagroupSet));
|
auto box = Ui::show(Box<StickersBox>(_megagroupSet));
|
||||||
connect(box, &QObject::destroyed, this, [this] {
|
connect(box, &QObject::destroyed, this, [this] {
|
||||||
_displayingSetId = 0;
|
_displayingSetId = 0;
|
||||||
emit checkForHide();
|
_checkForHide.fire({});
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} else if (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) {
|
} else if (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) {
|
||||||
|
@ -2299,7 +2308,7 @@ void StickersListWidget::displaySet(uint64 setId) {
|
||||||
LayerOption::KeepOther);
|
LayerOption::KeepOther);
|
||||||
connect(box, &QObject::destroyed, this, [this] {
|
connect(box, &QObject::destroyed, this, [this] {
|
||||||
_displayingSetId = 0;
|
_displayingSetId = 0;
|
||||||
emit checkForHide();
|
_checkForHide.fire({});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2357,10 +2366,10 @@ void StickersListWidget::removeMegagroupSet(bool locally) {
|
||||||
}
|
}
|
||||||
Ui::hideLayer();
|
Ui::hideLayer();
|
||||||
_removingSetId = 0;
|
_removingSetId = 0;
|
||||||
emit checkForHide();
|
_checkForHide.fire({});
|
||||||
}), crl::guard(this, [this] {
|
}), crl::guard(this, [this] {
|
||||||
_removingSetId = 0;
|
_removingSetId = 0;
|
||||||
emit checkForHide();
|
_checkForHide.fire({});
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2370,7 +2379,7 @@ void StickersListWidget::removeSet(uint64 setId) {
|
||||||
if (it != sets.cend()) {
|
if (it != sets.cend()) {
|
||||||
_removingSetId = it->id;
|
_removingSetId = it->id;
|
||||||
auto text = lng_stickers_remove_pack(lt_sticker_pack, it->title);
|
auto text = lng_stickers_remove_pack(lt_sticker_pack, it->title);
|
||||||
Ui::show(Box<ConfirmBox>(text, lang(lng_stickers_remove_pack_confirm), crl::guard(this, [this] {
|
Ui::show(Box<ConfirmBox>(text, lang(lng_stickers_remove_pack_confirm), crl::guard(this, [=] {
|
||||||
Ui::hideLayer();
|
Ui::hideLayer();
|
||||||
auto &sets = Auth().data().stickerSetsRef();
|
auto &sets = Auth().data().stickerSetsRef();
|
||||||
auto it = sets.find(_removingSetId);
|
auto it = sets.find(_removingSetId);
|
||||||
|
@ -2406,10 +2415,10 @@ void StickersListWidget::removeSet(uint64 setId) {
|
||||||
if (writeRecent) Local::writeUserSettings();
|
if (writeRecent) Local::writeUserSettings();
|
||||||
}
|
}
|
||||||
_removingSetId = 0;
|
_removingSetId = 0;
|
||||||
emit checkForHide();
|
_checkForHide.fire({});
|
||||||
}), crl::guard(this, [this] {
|
}), crl::guard(this, [=] {
|
||||||
_removingSetId = 0;
|
_removingSetId = 0;
|
||||||
emit checkForHide();
|
_checkForHide.fire({});
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,15 @@ class StickersListWidget
|
||||||
: public TabbedSelector::Inner
|
: public TabbedSelector::Inner
|
||||||
, private base::Subscriber
|
, private base::Subscriber
|
||||||
, private MTP::Sender {
|
, private MTP::Sender {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StickersListWidget(
|
StickersListWidget(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Window::Controller*> controller);
|
not_null<Window::Controller*> controller);
|
||||||
|
|
||||||
|
rpl::producer<not_null<DocumentData*>> chosen() const;
|
||||||
|
rpl::producer<> scrollUpdated() const;
|
||||||
|
rpl::producer<> checkForHide() const;
|
||||||
|
|
||||||
void refreshRecent() override;
|
void refreshRecent() override;
|
||||||
void preloadImages() override;
|
void preloadImages() override;
|
||||||
void clearSelection() override;
|
void clearSelection() override;
|
||||||
|
@ -82,15 +84,6 @@ protected:
|
||||||
void processPanelHideFinished() override;
|
void processPanelHideFinished() override;
|
||||||
int countDesiredHeight(int newWidth) override;
|
int countDesiredHeight(int newWidth) override;
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onSettings();
|
|
||||||
void onPreview();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void selected(not_null<DocumentData*> sticker);
|
|
||||||
void scrollUpdated();
|
|
||||||
void checkForHide();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Footer;
|
class Footer;
|
||||||
|
|
||||||
|
@ -248,6 +241,8 @@ private:
|
||||||
void fillCloudSearchRows(const std::vector<uint64> &cloudSets);
|
void fillCloudSearchRows(const std::vector<uint64> &cloudSets);
|
||||||
void addSearchRow(not_null<const Stickers::Set*> set);
|
void addSearchRow(not_null<const Stickers::Set*> set);
|
||||||
|
|
||||||
|
void showPreview();
|
||||||
|
|
||||||
ChannelData *_megagroupSet = nullptr;
|
ChannelData *_megagroupSet = nullptr;
|
||||||
std::vector<Set> _mySets;
|
std::vector<Set> _mySets;
|
||||||
std::vector<Set> _featuredSets;
|
std::vector<Set> _featuredSets;
|
||||||
|
@ -281,7 +276,7 @@ private:
|
||||||
|
|
||||||
object_ptr<Ui::LinkButton> _settings;
|
object_ptr<Ui::LinkButton> _settings;
|
||||||
|
|
||||||
QTimer _previewTimer;
|
base::Timer _previewTimer;
|
||||||
bool _previewShown = false;
|
bool _previewShown = false;
|
||||||
|
|
||||||
std::map<QString, std::vector<uint64>> _searchCache;
|
std::map<QString, std::vector<uint64>> _searchCache;
|
||||||
|
@ -290,6 +285,10 @@ private:
|
||||||
QString _searchQuery, _searchNextQuery;
|
QString _searchQuery, _searchNextQuery;
|
||||||
mtpRequestId _searchRequestId = 0;
|
mtpRequestId _searchRequestId = 0;
|
||||||
|
|
||||||
|
rpl::event_stream<not_null<DocumentData*>> _chosen;
|
||||||
|
rpl::event_stream<> _scrollUpdated;
|
||||||
|
rpl::event_stream<> _checkForHide;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ChatHelpers
|
} // namespace ChatHelpers
|
||||||
|
|
|
@ -66,24 +66,31 @@ TabbedPanel::TabbedPanel(
|
||||||
|
|
||||||
_hideTimer.setCallback([this] { hideByTimerOrLeave(); });
|
_hideTimer.setCallback([this] { hideByTimerOrLeave(); });
|
||||||
|
|
||||||
connect(_selector, &TabbedSelector::checkForHide, this, [this] {
|
_selector->checkForHide(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
if (!rect().contains(mapFromGlobal(QCursor::pos()))) {
|
if (!rect().contains(mapFromGlobal(QCursor::pos()))) {
|
||||||
_hideTimer.callOnce(kDelayedHideTimeoutMs);
|
_hideTimer.callOnce(kDelayedHideTimeoutMs);
|
||||||
}
|
}
|
||||||
});
|
}, lifetime());
|
||||||
connect(_selector, &TabbedSelector::cancelled, this, [this] {
|
|
||||||
|
_selector->cancelled(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
hideAnimated();
|
hideAnimated();
|
||||||
});
|
}, lifetime());
|
||||||
connect(_selector, &TabbedSelector::slideFinished, this, [this] {
|
|
||||||
InvokeQueued(this, [this] {
|
_selector->slideFinished(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
InvokeQueued(this, [=] {
|
||||||
if (_hideAfterSlide) {
|
if (_hideAfterSlide) {
|
||||||
startOpacityAnimation(true);
|
startOpacityAnimation(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}, lifetime());
|
||||||
|
|
||||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||||
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged()));
|
connect(App::wnd()->windowHandle(), &QWindow::activeChanged, this, [=] {
|
||||||
|
windowActiveChanged();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
||||||
|
|
||||||
|
@ -122,7 +129,7 @@ void TabbedPanel::updateContentHeight() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabbedPanel::onWndActiveChanged() {
|
void TabbedPanel::windowActiveChanged() {
|
||||||
if (!App::wnd()->windowHandle()->isActive() && !isHidden() && !preventAutoHide()) {
|
if (!App::wnd()->windowHandle()->isActive() && !isHidden() && !preventAutoHide()) {
|
||||||
hideAnimated();
|
hideAnimated();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,7 @@ namespace ChatHelpers {
|
||||||
|
|
||||||
class TabbedSelector;
|
class TabbedSelector;
|
||||||
|
|
||||||
class TabbedPanel : public Ui::RpWidget{
|
class TabbedPanel : public Ui::RpWidget {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TabbedPanel(QWidget *parent, not_null<Window::Controller*> controller);
|
TabbedPanel(QWidget *parent, not_null<Window::Controller*> controller);
|
||||||
TabbedPanel(QWidget *parent, not_null<Window::Controller*> controller, object_ptr<TabbedSelector> selector);
|
TabbedPanel(QWidget *parent, not_null<Window::Controller*> controller, object_ptr<TabbedSelector> selector);
|
||||||
|
@ -55,9 +53,6 @@ protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
bool eventFilter(QObject *obj, QEvent *e) override;
|
bool eventFilter(QObject *obj, QEvent *e) override;
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onWndActiveChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void hideByTimerOrLeave();
|
void hideByTimerOrLeave();
|
||||||
void moveByBottom();
|
void moveByBottom();
|
||||||
|
@ -65,6 +60,7 @@ private:
|
||||||
return !_selector;
|
return !_selector;
|
||||||
}
|
}
|
||||||
void showFromSelector();
|
void showFromSelector();
|
||||||
|
void windowActiveChanged();
|
||||||
|
|
||||||
style::margins innerPadding() const;
|
style::margins innerPadding() const;
|
||||||
|
|
||||||
|
|
|
@ -62,13 +62,8 @@ TabbedSection::TabbedSection(
|
||||||
_selector->setGeometry(rect());
|
_selector->setGeometry(rect());
|
||||||
_selector->showStarted();
|
_selector->showStarted();
|
||||||
_selector->show();
|
_selector->show();
|
||||||
connect(_selector, &TabbedSelector::cancelled, this, [this] {
|
_selector->setAfterShownCallback(nullptr);
|
||||||
if (_cancelledCallback) {
|
_selector->setBeforeHidingCallback(nullptr);
|
||||||
_cancelledCallback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
_selector->setAfterShownCallback(Fn<void(SelectorTab)>());
|
|
||||||
_selector->setBeforeHidingCallback(Fn<void(SelectorTab)>());
|
|
||||||
|
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,6 @@ public:
|
||||||
|
|
||||||
void beforeHiding();
|
void beforeHiding();
|
||||||
void afterShown();
|
void afterShown();
|
||||||
void setCancelledCallback(Fn<void()> callback) {
|
|
||||||
_cancelledCallback = std::move(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
object_ptr<TabbedSelector> takeSelector();
|
object_ptr<TabbedSelector> takeSelector();
|
||||||
QPointer<TabbedSelector> getSelector() const;
|
QPointer<TabbedSelector> getSelector() const;
|
||||||
|
@ -77,7 +74,6 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
object_ptr<TabbedSelector> _selector;
|
object_ptr<TabbedSelector> _selector;
|
||||||
Fn<void()> _cancelledCallback;
|
|
||||||
Fn<void(object_ptr<TabbedSelector>)> _returnMethod;
|
Fn<void(object_ptr<TabbedSelector>)> _returnMethod;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -261,6 +261,7 @@ object_ptr<TabbedSelector::Inner> TabbedSelector::Tab::takeWidget() {
|
||||||
|
|
||||||
void TabbedSelector::Tab::returnWidget(object_ptr<Inner> widget) {
|
void TabbedSelector::Tab::returnWidget(object_ptr<Inner> widget) {
|
||||||
_widget = std::move(widget);
|
_widget = std::move(widget);
|
||||||
|
|
||||||
Ensures(_widget == _weak);
|
Ensures(_widget == _weak);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,29 +294,30 @@ TabbedSelector::TabbedSelector(QWidget *parent, not_null<Window::Controller*> co
|
||||||
|
|
||||||
for (auto &tab : _tabs) {
|
for (auto &tab : _tabs) {
|
||||||
auto widget = tab.widget();
|
auto widget = tab.widget();
|
||||||
connect(widget, &Inner::scrollToY, this, [this, tab = &tab](int y) {
|
|
||||||
|
widget->scrollToRequests(
|
||||||
|
) | rpl::start_with_next([=, tab = &tab](int y) {
|
||||||
if (tab == currentTab()) {
|
if (tab == currentTab()) {
|
||||||
scrollToY(y);
|
scrollToY(y);
|
||||||
} else {
|
} else {
|
||||||
tab->saveScrollTop(y);
|
tab->saveScrollTop(y);
|
||||||
}
|
}
|
||||||
});
|
}, widget->lifetime());
|
||||||
connect(widget, &Inner::disableScroll, this, [this, tab = &tab](bool disabled) {
|
|
||||||
|
widget->disableScrollRequests(
|
||||||
|
) | rpl::start_with_next([=, tab = &tab](bool disabled) {
|
||||||
if (tab == currentTab()) {
|
if (tab == currentTab()) {
|
||||||
_scroll->disableScroll(disabled);
|
_scroll->disableScroll(disabled);
|
||||||
}
|
}
|
||||||
});
|
}, widget->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(stickers(), SIGNAL(scrollUpdated()), this, SLOT(onScroll()));
|
rpl::merge(
|
||||||
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
stickers()->scrollUpdated() | rpl::map([] { return 0; }),
|
||||||
connect(emoji(), SIGNAL(selected(EmojiPtr)), this, SIGNAL(emojiSelected(EmojiPtr)));
|
_scroll->scrollTopChanges()
|
||||||
connect(stickers(), SIGNAL(selected(not_null<DocumentData*>)), this, SIGNAL(stickerOrGifSelected(not_null<DocumentData*>)));
|
) | rpl::start_with_next([=] {
|
||||||
connect(stickers(), SIGNAL(checkForHide()), this, SIGNAL(checkForHide()));
|
handleScroll();
|
||||||
connect(gifs(), SIGNAL(selected(not_null<DocumentData*>)), this, SIGNAL(stickerOrGifSelected(not_null<DocumentData*>)));
|
}, lifetime());
|
||||||
connect(gifs(), SIGNAL(selected(not_null<PhotoData*>)), this, SIGNAL(photoSelected(not_null<PhotoData*>)));
|
|
||||||
connect(gifs(), SIGNAL(selected(not_null<InlineBots::Result*>,not_null<UserData*>)), this, SIGNAL(inlineResultSelected(not_null<InlineBots::Result*>,not_null<UserData*>)));
|
|
||||||
connect(gifs(), SIGNAL(cancelled()), this, SIGNAL(cancelled()));
|
|
||||||
|
|
||||||
_topShadow->raise();
|
_topShadow->raise();
|
||||||
_bottomShadow->raise();
|
_bottomShadow->raise();
|
||||||
|
@ -340,6 +342,35 @@ TabbedSelector::TabbedSelector(QWidget *parent, not_null<Window::Controller*> co
|
||||||
showAll();
|
showAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<EmojiPtr> TabbedSelector::emojiChosen() const {
|
||||||
|
return emoji()->chosen();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<not_null<DocumentData*>> TabbedSelector::fileChosen() const {
|
||||||
|
return rpl::merge(stickers()->chosen(), gifs()->fileChosen());
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<not_null<PhotoData*>> TabbedSelector::photoChosen() const {
|
||||||
|
return gifs()->photoChosen();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto TabbedSelector::inlineResultChosen() const
|
||||||
|
-> rpl::producer<InlineChosen> {
|
||||||
|
return gifs()->inlineResultChosen();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> TabbedSelector::cancelled() const {
|
||||||
|
return gifs()->cancelRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> TabbedSelector::checkForHide() const {
|
||||||
|
return stickers()->checkForHide();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> TabbedSelector::slideFinished() const {
|
||||||
|
return _slideFinished.events();
|
||||||
|
}
|
||||||
|
|
||||||
void TabbedSelector::resizeEvent(QResizeEvent *e) {
|
void TabbedSelector::resizeEvent(QResizeEvent *e) {
|
||||||
_tabsSlider->resizeToWidth(width());
|
_tabsSlider->resizeToWidth(width());
|
||||||
_tabsSlider->moveToLeft(0, 0);
|
_tabsSlider->moveToLeft(0, 0);
|
||||||
|
@ -408,7 +439,7 @@ void TabbedSelector::paintEvent(QPaintEvent *e) {
|
||||||
if (!_a_slide.animating()) {
|
if (!_a_slide.animating()) {
|
||||||
_slideAnimation.reset();
|
_slideAnimation.reset();
|
||||||
afterShown();
|
afterShown();
|
||||||
emit slideFinished();
|
_slideFinished.fire({});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
paintContent(p);
|
paintContent(p);
|
||||||
|
@ -607,7 +638,7 @@ void TabbedSelector::hideForSliding() {
|
||||||
currentTab()->widget()->clearSelection();
|
currentTab()->widget()->clearSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabbedSelector::onScroll() {
|
void TabbedSelector::handleScroll() {
|
||||||
auto scrollTop = _scroll->scrollTop();
|
auto scrollTop = _scroll->scrollTop();
|
||||||
auto scrollBottom = scrollTop + _scroll->height();
|
auto scrollBottom = scrollTop + _scroll->height();
|
||||||
currentTab()->widget()->setVisibleTopBottom(scrollTop, scrollBottom);
|
currentTab()->widget()->setVisibleTopBottom(scrollTop, scrollBottom);
|
||||||
|
@ -712,7 +743,7 @@ void TabbedSelector::setWidgetToScrollArea() {
|
||||||
|
|
||||||
_scroll->disableScroll(false);
|
_scroll->disableScroll(false);
|
||||||
scrollToY(currentTab()->getScrollTop());
|
scrollToY(currentTab()->getScrollTop());
|
||||||
onScroll();
|
handleScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabbedSelector::scrollToY(int y) {
|
void TabbedSelector::scrollToY(int y) {
|
||||||
|
@ -729,6 +760,22 @@ TabbedSelector::Inner::Inner(
|
||||||
, _controller(controller) {
|
, _controller(controller) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<int> TabbedSelector::Inner::scrollToRequests() const {
|
||||||
|
return _scrollToRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<bool> TabbedSelector::Inner::disableScrollRequests() const {
|
||||||
|
return _disableScrollRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabbedSelector::Inner::scrollTo(int y) {
|
||||||
|
_scrollToRequests.fire_copy(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabbedSelector::Inner::disableScroll(bool disabled) {
|
||||||
|
_disableScrollRequests.fire_copy(disabled);
|
||||||
|
}
|
||||||
|
|
||||||
void TabbedSelector::Inner::visibleTopBottomUpdated(int visibleTop, int visibleBottom) {
|
void TabbedSelector::Inner::visibleTopBottomUpdated(int visibleTop, int visibleBottom) {
|
||||||
_visibleTop = visibleTop;
|
_visibleTop = visibleTop;
|
||||||
_visibleBottom = visibleBottom;
|
_visibleBottom = visibleBottom;
|
||||||
|
|
|
@ -40,11 +40,23 @@ class StickersListWidget;
|
||||||
class GifsListWidget;
|
class GifsListWidget;
|
||||||
|
|
||||||
class TabbedSelector : public Ui::RpWidget, private base::Subscriber {
|
class TabbedSelector : public Ui::RpWidget, private base::Subscriber {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct InlineChosen {
|
||||||
|
not_null<InlineBots::Result*> result;
|
||||||
|
not_null<UserData*> bot;
|
||||||
|
};
|
||||||
|
|
||||||
TabbedSelector(QWidget *parent, not_null<Window::Controller*> controller);
|
TabbedSelector(QWidget *parent, not_null<Window::Controller*> controller);
|
||||||
|
|
||||||
|
rpl::producer<EmojiPtr> emojiChosen() const;
|
||||||
|
rpl::producer<not_null<DocumentData*>> fileChosen() const;
|
||||||
|
rpl::producer<not_null<PhotoData*>> photoChosen() const;
|
||||||
|
rpl::producer<InlineChosen> inlineResultChosen() const;
|
||||||
|
|
||||||
|
rpl::producer<> cancelled() const;
|
||||||
|
rpl::producer<> checkForHide() const;
|
||||||
|
rpl::producer<> slideFinished() const;
|
||||||
|
|
||||||
void setRoundRadius(int radius);
|
void setRoundRadius(int radius);
|
||||||
void refreshStickers();
|
void refreshStickers();
|
||||||
void showMegagroupSet(ChannelData *megagroup);
|
void showMegagroupSet(ChannelData *megagroup);
|
||||||
|
@ -87,21 +99,6 @@ protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onScroll();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void emojiSelected(EmojiPtr emoji);
|
|
||||||
void stickerOrGifSelected(not_null<DocumentData*> sticker);
|
|
||||||
void photoSelected(not_null<PhotoData*> photo);
|
|
||||||
void inlineResultSelected(
|
|
||||||
not_null<InlineBots::Result*> result,
|
|
||||||
not_null<UserData*> bot);
|
|
||||||
|
|
||||||
void cancelled();
|
|
||||||
void slideFinished();
|
|
||||||
void checkForHide();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Tab {
|
class Tab {
|
||||||
public:
|
public:
|
||||||
|
@ -145,6 +142,7 @@ private:
|
||||||
void checkRestrictedPeer();
|
void checkRestrictedPeer();
|
||||||
bool isRestrictedView();
|
bool isRestrictedView();
|
||||||
void updateRestrictedLabelGeometry();
|
void updateRestrictedLabelGeometry();
|
||||||
|
void handleScroll();
|
||||||
|
|
||||||
QImage grabForAnimation();
|
QImage grabForAnimation();
|
||||||
|
|
||||||
|
@ -193,12 +191,11 @@ private:
|
||||||
Fn<void(SelectorTab)> _beforeHidingCallback;
|
Fn<void(SelectorTab)> _beforeHidingCallback;
|
||||||
|
|
||||||
rpl::event_stream<> _showRequests;
|
rpl::event_stream<> _showRequests;
|
||||||
|
rpl::event_stream<> _slideFinished;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TabbedSelector::Inner : public Ui::RpWidget {
|
class TabbedSelector::Inner : public Ui::RpWidget {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Inner(QWidget *parent, not_null<Window::Controller*> controller);
|
Inner(QWidget *parent, not_null<Window::Controller*> controller);
|
||||||
|
|
||||||
|
@ -222,11 +219,10 @@ public:
|
||||||
virtual void beforeHiding() {
|
virtual void beforeHiding() {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object_ptr<InnerFooter> createFooter() = 0;
|
rpl::producer<int> scrollToRequests() const;
|
||||||
|
rpl::producer<bool> disableScrollRequests() const;
|
||||||
|
|
||||||
signals:
|
virtual object_ptr<InnerFooter> createFooter() = 0;
|
||||||
void scrollToY(int y);
|
|
||||||
void disableScroll(bool disabled);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void visibleTopBottomUpdated(
|
void visibleTopBottomUpdated(
|
||||||
|
@ -246,6 +242,9 @@ protected:
|
||||||
virtual void processPanelHideFinished() {
|
virtual void processPanelHideFinished() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scrollTo(int y);
|
||||||
|
void disableScroll(bool disabled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
not_null<Window::Controller*> _controller;
|
not_null<Window::Controller*> _controller;
|
||||||
|
|
||||||
|
@ -253,6 +252,9 @@ private:
|
||||||
int _visibleBottom = 0;
|
int _visibleBottom = 0;
|
||||||
int _minimalHeight = 0;
|
int _minimalHeight = 0;
|
||||||
|
|
||||||
|
rpl::event_stream<int> _scrollToRequests;
|
||||||
|
rpl::event_stream<bool> _disableScrollRequests;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TabbedSelector::InnerFooter : public TWidget {
|
class TabbedSelector::InnerFooter : public TWidget {
|
||||||
|
|
|
@ -477,14 +477,9 @@ HistoryWidget::HistoryWidget(
|
||||||
connect(_field, SIGNAL(changed()), this, SLOT(onTextChange()));
|
connect(_field, SIGNAL(changed()), this, SLOT(onTextChange()));
|
||||||
connect(App::wnd()->windowHandle(), SIGNAL(visibleChanged(bool)), this, SLOT(onWindowVisibleChanged()));
|
connect(App::wnd()->windowHandle(), SIGNAL(visibleChanged(bool)), this, SLOT(onWindowVisibleChanged()));
|
||||||
connect(&_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimer()));
|
connect(&_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimer()));
|
||||||
connect(
|
|
||||||
_tabbedSelector,
|
initTabbedSelector();
|
||||||
&TabbedSelector::emojiSelected,
|
|
||||||
_field,
|
|
||||||
[=](EmojiPtr emoji) { InsertEmojiToField(_field, emoji); });
|
|
||||||
connect(_tabbedSelector, SIGNAL(stickerOrGifSelected(not_null<DocumentData*>)), this, SLOT(onStickerOrGifSend(not_null<DocumentData*>)));
|
|
||||||
connect(_tabbedSelector, SIGNAL(photoSelected(not_null<PhotoData*>)), this, SLOT(onPhotoSend(not_null<PhotoData*>)));
|
|
||||||
connect(_tabbedSelector, SIGNAL(inlineResultSelected(not_null<InlineBots::Result*>,not_null<UserData*>)), this, SLOT(onInlineResultSend(not_null<InlineBots::Result*>,not_null<UserData*>)));
|
|
||||||
connect(Media::Capture::instance(), SIGNAL(error()), this, SLOT(onRecordError()));
|
connect(Media::Capture::instance(), SIGNAL(error()), this, SLOT(onRecordError()));
|
||||||
connect(Media::Capture::instance(), SIGNAL(updated(quint16,qint32)), this, SLOT(onRecordUpdate(quint16,qint32)));
|
connect(Media::Capture::instance(), SIGNAL(updated(quint16,qint32)), this, SLOT(onRecordUpdate(quint16,qint32)));
|
||||||
connect(Media::Capture::instance(), SIGNAL(done(QByteArray,VoiceWaveform,qint32)), this, SLOT(onRecordDone(QByteArray,VoiceWaveform,qint32)));
|
connect(Media::Capture::instance(), SIGNAL(done(QByteArray,VoiceWaveform,qint32)), this, SLOT(onRecordDone(QByteArray,VoiceWaveform,qint32)));
|
||||||
|
@ -532,7 +527,9 @@ HistoryWidget::HistoryWidget(
|
||||||
connect(_fieldAutocomplete, SIGNAL(mentionChosen(UserData*,FieldAutocomplete::ChooseMethod)), this, SLOT(onMentionInsert(UserData*)));
|
connect(_fieldAutocomplete, SIGNAL(mentionChosen(UserData*,FieldAutocomplete::ChooseMethod)), this, SLOT(onMentionInsert(UserData*)));
|
||||||
connect(_fieldAutocomplete, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod)));
|
connect(_fieldAutocomplete, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod)));
|
||||||
connect(_fieldAutocomplete, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod)));
|
connect(_fieldAutocomplete, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod)));
|
||||||
connect(_fieldAutocomplete, SIGNAL(stickerChosen(not_null<DocumentData*>,FieldAutocomplete::ChooseMethod)), this, SLOT(onStickerOrGifSend(not_null<DocumentData*>)));
|
connect(_fieldAutocomplete, &FieldAutocomplete::stickerChosen, this, [=](not_null<DocumentData*> document) {
|
||||||
|
sendExistingDocument(document);
|
||||||
|
});
|
||||||
connect(_fieldAutocomplete, SIGNAL(moderateKeyActivate(int,bool*)), this, SLOT(onModerateKeyActivate(int,bool*)));
|
connect(_fieldAutocomplete, SIGNAL(moderateKeyActivate(int,bool*)), this, SLOT(onModerateKeyActivate(int,bool*)));
|
||||||
if (_supportAutocomplete) {
|
if (_supportAutocomplete) {
|
||||||
supportInitAutocomplete();
|
supportInitAutocomplete();
|
||||||
|
@ -779,6 +776,28 @@ HistoryWidget::HistoryWidget(
|
||||||
setupShortcuts();
|
setupShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::initTabbedSelector() {
|
||||||
|
_tabbedSelector->emojiChosen(
|
||||||
|
) | rpl::start_with_next([=](EmojiPtr emoji) {
|
||||||
|
InsertEmojiToField(_field, emoji);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_tabbedSelector->fileChosen(
|
||||||
|
) | rpl::start_with_next([=](not_null<DocumentData*> document) {
|
||||||
|
sendExistingDocument(document);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_tabbedSelector->photoChosen(
|
||||||
|
) | rpl::start_with_next([=](not_null<PhotoData*> photo) {
|
||||||
|
sendExistingPhoto(photo);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_tabbedSelector->inlineResultChosen(
|
||||||
|
) | rpl::start_with_next([=](TabbedSelector::InlineChosen data) {
|
||||||
|
sendInlineResult(data.result, data.bot);
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::supportInitAutocomplete() {
|
void HistoryWidget::supportInitAutocomplete() {
|
||||||
_supportAutocomplete->hide();
|
_supportAutocomplete->hide();
|
||||||
|
|
||||||
|
@ -1148,8 +1167,10 @@ void HistoryWidget::applyInlineBotQuery(UserData *bot, const QString &query) {
|
||||||
}
|
}
|
||||||
if (!_inlineResults) {
|
if (!_inlineResults) {
|
||||||
_inlineResults.create(this, controller());
|
_inlineResults.create(this, controller());
|
||||||
_inlineResults->setResultSelectedCallback([this](InlineBots::Result *result, UserData *bot) {
|
_inlineResults->setResultSelectedCallback([=](
|
||||||
onInlineResultSend(result, bot);
|
InlineBots::Result *result,
|
||||||
|
UserData *bot) {
|
||||||
|
sendInlineResult(result, bot);
|
||||||
});
|
});
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
orderWidgets();
|
orderWidgets();
|
||||||
|
@ -5488,34 +5509,7 @@ void HistoryWidget::onFieldTabbed() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryWidget::onStickerOrGifSend(not_null<DocumentData*> document) {
|
void HistoryWidget::sendInlineResult(
|
||||||
if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
|
|
||||||
if (megagroup->restricted(ChannelRestriction::f_send_stickers)) {
|
|
||||||
Ui::show(
|
|
||||||
Box<InformBox>(lang(lng_restricted_send_stickers)),
|
|
||||||
LayerOption::KeepOther);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sendExistingDocument(
|
|
||||||
document,
|
|
||||||
document->stickerOrGifOrigin(),
|
|
||||||
TextWithEntities());
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryWidget::onPhotoSend(not_null<PhotoData*> photo) {
|
|
||||||
if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
|
|
||||||
if (megagroup->restricted(ChannelRestriction::f_send_media)) {
|
|
||||||
Ui::show(
|
|
||||||
Box<InformBox>(lang(lng_restricted_send_media)),
|
|
||||||
LayerOption::KeepOther);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sendExistingPhoto(photo, TextWithEntities());
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryWidget::onInlineResultSend(
|
|
||||||
not_null<InlineBots::Result*> result,
|
not_null<InlineBots::Result*> result,
|
||||||
not_null<UserData*> bot) {
|
not_null<UserData*> bot) {
|
||||||
if (!_peer || !_peer->canWrite()) {
|
if (!_peer || !_peer->canWrite()) {
|
||||||
|
@ -5662,12 +5656,20 @@ void HistoryWidget::destroyPinnedBar() {
|
||||||
|
|
||||||
bool HistoryWidget::sendExistingDocument(
|
bool HistoryWidget::sendExistingDocument(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
Data::FileOrigin origin,
|
|
||||||
TextWithEntities caption) {
|
TextWithEntities caption) {
|
||||||
if (!_peer || !_peer->canWrite()) {
|
if (const auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
|
||||||
|
if (megagroup->restricted(ChannelRestriction::f_send_stickers)) {
|
||||||
|
Ui::show(
|
||||||
|
Box<InformBox>(lang(lng_restricted_send_stickers)),
|
||||||
|
LayerOption::KeepOther);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!_peer || !_peer->canWrite()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto origin = document->stickerOrGifOrigin();
|
||||||
|
|
||||||
auto options = ApiWrap::SendOptions(_history);
|
auto options = ApiWrap::SendOptions(_history);
|
||||||
options.clearDraft = false;
|
options.clearDraft = false;
|
||||||
options.replyTo = replyToId();
|
options.replyTo = replyToId();
|
||||||
|
@ -5688,11 +5690,18 @@ bool HistoryWidget::sendExistingDocument(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::sendExistingPhoto(
|
bool HistoryWidget::sendExistingPhoto(
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
TextWithEntities caption) {
|
TextWithEntities caption) {
|
||||||
if (!_peer || !_peer->canWrite()) {
|
if (const auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
|
||||||
return;
|
if (megagroup->restricted(ChannelRestriction::f_send_media)) {
|
||||||
|
Ui::show(
|
||||||
|
Box<InformBox>(lang(lng_restricted_send_media)),
|
||||||
|
LayerOption::KeepOther);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!_peer || !_peer->canWrite()) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto options = ApiWrap::SendOptions(_history);
|
auto options = ApiWrap::SendOptions(_history);
|
||||||
|
@ -5774,6 +5783,8 @@ void HistoryWidget::sendExistingPhoto(
|
||||||
hideSelectorControlsAnimated();
|
hideSelectorControlsAnimated();
|
||||||
|
|
||||||
_field->setFocus();
|
_field->setFocus();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::setFieldText(
|
void HistoryWidget::setFieldText(
|
||||||
|
|
|
@ -331,6 +331,13 @@ public:
|
||||||
void confirmDeleteSelected();
|
void confirmDeleteSelected();
|
||||||
void clearSelected();
|
void clearSelected();
|
||||||
|
|
||||||
|
bool sendExistingDocument(
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
TextWithEntities caption = TextWithEntities());
|
||||||
|
bool sendExistingPhoto(
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
TextWithEntities caption = TextWithEntities());
|
||||||
|
|
||||||
// Float player interface.
|
// Float player interface.
|
||||||
bool wheelEventFromFloatPlayer(QEvent *e) override;
|
bool wheelEventFromFloatPlayer(QEvent *e) override;
|
||||||
QRect rectForFloatPlayer() const override;
|
QRect rectForFloatPlayer() const override;
|
||||||
|
@ -389,11 +396,6 @@ public slots:
|
||||||
void onTextChange();
|
void onTextChange();
|
||||||
|
|
||||||
void onFieldTabbed();
|
void onFieldTabbed();
|
||||||
bool onStickerOrGifSend(not_null<DocumentData*> document);
|
|
||||||
void onPhotoSend(not_null<PhotoData*> photo);
|
|
||||||
void onInlineResultSend(
|
|
||||||
not_null<InlineBots::Result*> result,
|
|
||||||
not_null<UserData*> bot);
|
|
||||||
|
|
||||||
void onWindowVisibleChanged();
|
void onWindowVisibleChanged();
|
||||||
|
|
||||||
|
@ -431,6 +433,8 @@ private:
|
||||||
using TabbedSelector = ChatHelpers::TabbedSelector;
|
using TabbedSelector = ChatHelpers::TabbedSelector;
|
||||||
using DragState = Storage::MimeDataState;
|
using DragState = Storage::MimeDataState;
|
||||||
|
|
||||||
|
void initTabbedSelector();
|
||||||
|
|
||||||
void send(Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers());
|
void send(Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers());
|
||||||
void handlePendingHistoryUpdate();
|
void handlePendingHistoryUpdate();
|
||||||
void fullPeerUpdated(PeerData *peer);
|
void fullPeerUpdated(PeerData *peer);
|
||||||
|
@ -601,13 +605,9 @@ private:
|
||||||
void destroyPinnedBar();
|
void destroyPinnedBar();
|
||||||
void unpinDone(const MTPUpdates &updates);
|
void unpinDone(const MTPUpdates &updates);
|
||||||
|
|
||||||
bool sendExistingDocument(
|
void sendInlineResult(
|
||||||
not_null<DocumentData*> document,
|
not_null<InlineBots::Result*> result,
|
||||||
Data::FileOrigin origin,
|
not_null<UserData*> bot);
|
||||||
TextWithEntities caption);
|
|
||||||
void sendExistingPhoto(
|
|
||||||
not_null<PhotoData*> photo,
|
|
||||||
TextWithEntities caption);
|
|
||||||
|
|
||||||
void drawField(Painter &p, const QRect &rect);
|
void drawField(Painter &p, const QRect &rect);
|
||||||
void paintEditHeader(Painter &p, const QRect &rect, int left, int top) const;
|
void paintEditHeader(Painter &p, const QRect &rect, int left, int top) const;
|
||||||
|
|
|
@ -40,18 +40,14 @@ constexpr auto kInlineBotRequestDelay = 400;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Inner::Inner(QWidget *parent, not_null<Window::Controller*> controller) : TWidget(parent)
|
Inner::Inner(QWidget *parent, not_null<Window::Controller*> controller) : TWidget(parent)
|
||||||
, _controller(controller) {
|
, _controller(controller)
|
||||||
|
, _updateInlineItems([=] { updateInlineItems(); })
|
||||||
|
, _previewTimer([=] { showPreview(); }) {
|
||||||
resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, st::emojiPanMinHeight);
|
resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, st::emojiPanMinHeight);
|
||||||
|
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
||||||
_previewTimer.setSingleShot(true);
|
|
||||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
|
||||||
|
|
||||||
_updateInlineItems.setSingleShot(true);
|
|
||||||
connect(&_updateInlineItems, SIGNAL(timeout()), this, SLOT(onUpdateInlineItems()));
|
|
||||||
|
|
||||||
subscribe(Auth().downloaderTaskFinished(), [this] {
|
subscribe(Auth().downloaderTaskFinished(), [this] {
|
||||||
update();
|
update();
|
||||||
});
|
});
|
||||||
|
@ -194,11 +190,11 @@ void Inner::mousePressEvent(QMouseEvent *e) {
|
||||||
|
|
||||||
_pressed = _selected;
|
_pressed = _selected;
|
||||||
ClickHandler::pressed();
|
ClickHandler::pressed();
|
||||||
_previewTimer.start(QApplication::startDragTime());
|
_previewTimer.callOnce(QApplication::startDragTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::mouseReleaseEvent(QMouseEvent *e) {
|
void Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
_previewTimer.stop();
|
_previewTimer.cancel();
|
||||||
|
|
||||||
auto pressed = std::exchange(_pressed, -1);
|
auto pressed = std::exchange(_pressed, -1);
|
||||||
auto activated = ClickHandler::unpressed();
|
auto activated = ClickHandler::unpressed();
|
||||||
|
@ -572,7 +568,7 @@ void Inner::inlineItemRepaint(const ItemBase *layout) {
|
||||||
if (_lastScrolled + 100 <= ms) {
|
if (_lastScrolled + 100 <= ms) {
|
||||||
update();
|
update();
|
||||||
} else {
|
} else {
|
||||||
_updateInlineItems.start(_lastScrolled + 100 - ms);
|
_updateInlineItems.callOnce(_lastScrolled + 100 - ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +678,7 @@ void Inner::updateSelected() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::onPreview() {
|
void Inner::showPreview() {
|
||||||
if (_pressed < 0) return;
|
if (_pressed < 0) return;
|
||||||
|
|
||||||
int row = _pressed / MatrixRowShift, col = _pressed % MatrixRowShift;
|
int row = _pressed / MatrixRowShift, col = _pressed % MatrixRowShift;
|
||||||
|
@ -698,12 +694,12 @@ void Inner::onPreview() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::onUpdateInlineItems() {
|
void Inner::updateInlineItems() {
|
||||||
auto ms = getms();
|
auto ms = getms();
|
||||||
if (_lastScrolled + 100 <= ms) {
|
if (_lastScrolled + 100 <= ms) {
|
||||||
update();
|
update();
|
||||||
} else {
|
} else {
|
||||||
_updateInlineItems.start(_lastScrolled + 100 - ms);
|
_updateInlineItems.callOnce(_lastScrolled + 100 - ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/twidget.h"
|
#include "ui/twidget.h"
|
||||||
#include "ui/abstract_button.h"
|
#include "ui/abstract_button.h"
|
||||||
#include "ui/effects/panel_animation.h"
|
#include "ui/effects/panel_animation.h"
|
||||||
|
#include "base/timer.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "inline_bots/inline_bot_layout_item.h"
|
#include "inline_bots/inline_bot_layout_item.h"
|
||||||
|
|
||||||
|
@ -90,8 +91,6 @@ protected:
|
||||||
void enterFromChildEvent(QEvent *e, QWidget *child) override;
|
void enterFromChildEvent(QEvent *e, QWidget *child) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onPreview();
|
|
||||||
void onUpdateInlineItems();
|
|
||||||
void onSwitchPm();
|
void onSwitchPm();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -101,6 +100,11 @@ private:
|
||||||
static constexpr bool kRefreshIconsScrollAnimation = true;
|
static constexpr bool kRefreshIconsScrollAnimation = true;
|
||||||
static constexpr bool kRefreshIconsNoAnimation = false;
|
static constexpr bool kRefreshIconsNoAnimation = false;
|
||||||
|
|
||||||
|
struct Row {
|
||||||
|
int height = 0;
|
||||||
|
QVector<ItemBase*> items;
|
||||||
|
};
|
||||||
|
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
void checkRestrictedPeer();
|
void checkRestrictedPeer();
|
||||||
bool isRestrictedView();
|
bool isRestrictedView();
|
||||||
|
@ -109,30 +113,9 @@ private:
|
||||||
|
|
||||||
void refreshSwitchPmButton(const CacheEntry *entry);
|
void refreshSwitchPmButton(const CacheEntry *entry);
|
||||||
|
|
||||||
not_null<Window::Controller*> _controller;
|
void showPreview();
|
||||||
|
void updateInlineItems();
|
||||||
int _visibleTop = 0;
|
|
||||||
int _visibleBottom = 0;
|
|
||||||
|
|
||||||
UserData *_inlineBot = nullptr;
|
|
||||||
PeerData *_inlineQueryPeer = nullptr;
|
|
||||||
TimeMs _lastScrolled = 0;
|
|
||||||
QTimer _updateInlineItems;
|
|
||||||
bool _inlineWithThumb = false;
|
|
||||||
|
|
||||||
object_ptr<Ui::RoundButton> _switchPmButton = { nullptr };
|
|
||||||
QString _switchPmStartToken;
|
|
||||||
|
|
||||||
object_ptr<Ui::FlatLabel> _restrictedLabel = { nullptr };
|
|
||||||
|
|
||||||
struct Row {
|
|
||||||
int height = 0;
|
|
||||||
QVector<ItemBase*> items;
|
|
||||||
};
|
|
||||||
QVector<Row> _rows;
|
|
||||||
void clearInlineRows(bool resultsDeleted);
|
void clearInlineRows(bool resultsDeleted);
|
||||||
|
|
||||||
std::map<Result*, std::unique_ptr<ItemBase>> _inlineLayouts;
|
|
||||||
ItemBase *layoutPrepareInlineResult(Result *result, int32 position);
|
ItemBase *layoutPrepareInlineResult(Result *result, int32 position);
|
||||||
|
|
||||||
bool inlineRowsAddItem(Result *result, Row &row, int32 &sumWidth);
|
bool inlineRowsAddItem(Result *result, Row &row, int32 &sumWidth);
|
||||||
|
@ -144,11 +127,31 @@ private:
|
||||||
int validateExistingInlineRows(const Results &results);
|
int validateExistingInlineRows(const Results &results);
|
||||||
void selectInlineResult(int row, int column);
|
void selectInlineResult(int row, int column);
|
||||||
|
|
||||||
|
not_null<Window::Controller*> _controller;
|
||||||
|
|
||||||
|
int _visibleTop = 0;
|
||||||
|
int _visibleBottom = 0;
|
||||||
|
|
||||||
|
UserData *_inlineBot = nullptr;
|
||||||
|
PeerData *_inlineQueryPeer = nullptr;
|
||||||
|
TimeMs _lastScrolled = 0;
|
||||||
|
base::Timer _updateInlineItems;
|
||||||
|
bool _inlineWithThumb = false;
|
||||||
|
|
||||||
|
object_ptr<Ui::RoundButton> _switchPmButton = { nullptr };
|
||||||
|
QString _switchPmStartToken;
|
||||||
|
|
||||||
|
object_ptr<Ui::FlatLabel> _restrictedLabel = { nullptr };
|
||||||
|
|
||||||
|
QVector<Row> _rows;
|
||||||
|
|
||||||
|
std::map<Result*, std::unique_ptr<ItemBase>> _inlineLayouts;
|
||||||
|
|
||||||
int _selected = -1;
|
int _selected = -1;
|
||||||
int _pressed = -1;
|
int _pressed = -1;
|
||||||
QPoint _lastMousePos;
|
QPoint _lastMousePos;
|
||||||
|
|
||||||
QTimer _previewTimer;
|
base::Timer _previewTimer;
|
||||||
bool _previewShown = false;
|
bool _previewShown = false;
|
||||||
|
|
||||||
Fn<void(Result *result, UserData *bot)> _resultSelectedCallback;
|
Fn<void(Result *result, UserData *bot)> _resultSelectedCallback;
|
||||||
|
|
|
@ -1447,7 +1447,7 @@ void MainWidget::onSendFileConfirm(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWidget::onSendSticker(DocumentData *document) {
|
bool MainWidget::onSendSticker(DocumentData *document) {
|
||||||
return _history->onStickerOrGifSend(document);
|
return _history->sendExistingDocument(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::dialogsCancelled() {
|
void MainWidget::dialogsCancelled() {
|
||||||
|
|
|
@ -204,6 +204,9 @@ public:
|
||||||
auto scrollTopValue() const {
|
auto scrollTopValue() const {
|
||||||
return _scrollTopUpdated.events_starting_with(scrollTop());
|
return _scrollTopUpdated.events_starting_with(scrollTop());
|
||||||
}
|
}
|
||||||
|
auto scrollTopChanges() const {
|
||||||
|
return _scrollTopUpdated.events();
|
||||||
|
}
|
||||||
|
|
||||||
void scrollTo(ScrollToRequest request);
|
void scrollTo(ScrollToRequest request);
|
||||||
void scrollToWidget(not_null<QWidget*> widget);
|
void scrollToWidget(not_null<QWidget*> widget);
|
||||||
|
|
Loading…
Reference in New Issue