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