mirror of https://github.com/procxx/kepka.git
Sticker preview done for inline bot results.
ReplyMarkupClickHandler moved to .cpp (implementation details).
This commit is contained in:
parent
ba7cb1abbc
commit
a728dcfca8
|
@ -772,12 +772,12 @@ private:
|
||||||
T *_p;
|
T *_p;
|
||||||
|
|
||||||
};
|
};
|
||||||
template <typename T, class... Args>
|
template <typename T, typename... Args>
|
||||||
inline UniquePointer<T> MakeUnique(Args&&... args) {
|
inline UniquePointer<T> MakeUnique(Args&&... args) {
|
||||||
return UniquePointer<T>(new T(std_::forward<Args>(args)...));
|
return UniquePointer<T>(new T(std_::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class... Args>
|
template <typename T, typename... Args>
|
||||||
inline QSharedPointer<T> MakeShared(Args&&... args) {
|
inline QSharedPointer<T> MakeShared(Args&&... args) {
|
||||||
return QSharedPointer<T>(new T(std_::forward<Args>(args)...));
|
return QSharedPointer<T>(new T(std_::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
@ -832,6 +832,13 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using NeverFreedPointerCreator = T*(*)();
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
inline NeverFreedPointerCreator<T> MakeNeverFreedCreator(Args&&... args) {
|
||||||
|
return []() -> T* { return new T(std_::forward<Args>(args)...); };
|
||||||
|
}
|
||||||
|
|
||||||
// This pointer is used for static non-POD variables that are allocated
|
// This pointer is used for static non-POD variables that are allocated
|
||||||
// on first use by constructor and are never automatically freed.
|
// on first use by constructor and are never automatically freed.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -2172,7 +2172,9 @@ void StickerPanInner::refreshPanels(QVector<EmojiPanel*> &panels) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerPanInner::updateSelected() {
|
void StickerPanInner::updateSelected() {
|
||||||
if (_pressedSel >= 0 && !_previewShown) return;
|
if (_pressedSel >= 0 && !_previewShown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int32 selIndex = -1;
|
int32 selIndex = -1;
|
||||||
QPoint p(mapFromGlobal(_lastMousePos));
|
QPoint p(mapFromGlobal(_lastMousePos));
|
||||||
|
@ -2229,8 +2231,10 @@ void StickerPanInner::updateSelected() {
|
||||||
}
|
}
|
||||||
if (_pressedSel >= 0 && _selected >= 0 && _pressedSel != _selected) {
|
if (_pressedSel >= 0 && _selected >= 0 && _pressedSel != _selected) {
|
||||||
_pressedSel = _selected;
|
_pressedSel = _selected;
|
||||||
if (row >= 0 && col >= 0 && _inlineRows.at(row).items.at(col)->getDocument()) {
|
if (row >= 0 && col >= 0) {
|
||||||
Ui::showStickerPreview(_inlineRows.at(row).items.at(col)->getDocument());
|
if (DocumentData *previewDocument = _inlineRows.at(row).items.at(col)->getPreviewDocument()) {
|
||||||
|
Ui::showStickerPreview(previewDocument);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2329,9 +2333,11 @@ void StickerPanInner::onPreview() {
|
||||||
if (_pressedSel < 0) return;
|
if (_pressedSel < 0) return;
|
||||||
if (_showingInlineItems) {
|
if (_showingInlineItems) {
|
||||||
int32 row = _pressedSel / MatrixRowShift, col = _pressedSel % MatrixRowShift;
|
int32 row = _pressedSel / MatrixRowShift, col = _pressedSel % MatrixRowShift;
|
||||||
if (row < _inlineRows.size() && col < _inlineRows.at(row).items.size() && _inlineRows.at(row).items.at(col)->getDocument() && _inlineRows.at(row).items.at(col)->getDocument()->loaded()) {
|
if (row < _inlineRows.size() && col < _inlineRows.at(row).items.size()) {
|
||||||
Ui::showStickerPreview(_inlineRows.at(row).items.at(col)->getDocument());
|
if (DocumentData *previewDocument = _inlineRows.at(row).items.at(col)->getPreviewDocument()) {
|
||||||
_previewShown = true;
|
Ui::showStickerPreview(previewDocument);
|
||||||
|
_previewShown = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (_pressedSel < MatrixRowShift * _sets.size()) {
|
} else if (_pressedSel < MatrixRowShift * _sets.size()) {
|
||||||
int tab = (_pressedSel / MatrixRowShift), sel = _pressedSel % MatrixRowShift;
|
int tab = (_pressedSel / MatrixRowShift), sel = _pressedSel % MatrixRowShift;
|
||||||
|
|
|
@ -61,8 +61,8 @@ ClickHandlerHost::~ClickHandlerHost() {
|
||||||
ClickHandler::hostDestroyed(this);
|
ClickHandler::hostDestroyed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClickHandlerPtr *ClickHandler::_active = nullptr;
|
NeverFreedPointer<ClickHandlerPtr> ClickHandler::_active;
|
||||||
ClickHandlerPtr *ClickHandler::_pressed = nullptr;
|
NeverFreedPointer<ClickHandlerPtr> ClickHandler::_pressed;
|
||||||
ClickHandlerHost *ClickHandler::_activeHost = nullptr;
|
ClickHandlerHost *ClickHandler::_activeHost = nullptr;
|
||||||
ClickHandlerHost *ClickHandler::_pressedHost = nullptr;
|
ClickHandlerHost *ClickHandler::_pressedHost = nullptr;
|
||||||
|
|
||||||
|
@ -86,9 +86,7 @@ bool ClickHandler::setActive(const ClickHandlerPtr &p, ClickHandlerHost *host) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p) {
|
if (p) {
|
||||||
if (!_active) {
|
_active.createIfNull(MakeNeverFreedCreator<ClickHandlerPtr>());
|
||||||
_active = new ClickHandlerPtr(); // won't be deleted
|
|
||||||
}
|
|
||||||
*_active = p;
|
*_active = p;
|
||||||
if ((_activeHost = host)) {
|
if ((_activeHost = host)) {
|
||||||
bool emitClickHandlerActiveChanged = (!_pressed || !*_pressed || *_pressed == *_active);
|
bool emitClickHandlerActiveChanged = (!_pressed || !*_pressed || *_pressed == *_active);
|
||||||
|
|
|
@ -366,9 +366,7 @@ public:
|
||||||
if (!_active || !*_active) {
|
if (!_active || !*_active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!_pressed) {
|
_pressed.createIfNull(MakeNeverFreedCreator<ClickHandlerPtr>());
|
||||||
_pressed = new ClickHandlerPtr(); // won't be deleted
|
|
||||||
}
|
|
||||||
*_pressed = *_active;
|
*_pressed = *_active;
|
||||||
if ((_pressedHost = _activeHost)) {
|
if ((_pressedHost = _activeHost)) {
|
||||||
_pressedHost->clickHandlerPressedChanged(*_pressed, true);
|
_pressedHost->clickHandlerPressedChanged(*_pressed, true);
|
||||||
|
@ -428,8 +426,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static ClickHandlerPtr *_active;
|
static NeverFreedPointer<ClickHandlerPtr> _active;
|
||||||
static ClickHandlerPtr *_pressed;
|
static NeverFreedPointer<ClickHandlerPtr> _pressed;
|
||||||
static ClickHandlerHost *_activeHost;
|
static ClickHandlerHost *_activeHost;
|
||||||
static ClickHandlerHost *_pressedHost;
|
static ClickHandlerHost *_pressedHost;
|
||||||
|
|
||||||
|
|
|
@ -2740,36 +2740,57 @@ void HistoryBlock::removeItem(HistoryItem *item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplyMarkupClickHandler::onClickImpl() const {
|
class ReplyMarkupClickHandler : public LeftButtonClickHandler {
|
||||||
const HistoryItem *item = nullptr;
|
public:
|
||||||
const HistoryMessageReplyMarkup::Button *button = nullptr;
|
ReplyMarkupClickHandler(const HistoryItem *item, int row, int col) : _item(item), _row(row), _col(col) {
|
||||||
if (getItemAndButton(&item, &button)) {
|
|
||||||
App::activateBotCommand(item->history()->peer, *button, _msgId.msg);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// We need to make sure the item still exists, so we get it by id.
|
QString tooltip() const override {
|
||||||
// After that we check if the reply markup is still there and that
|
return _fullDisplayed ? QString() : text();
|
||||||
// there are enough button rows and buttons in the row.
|
}
|
||||||
// Note: it is possible that we will point to the different button
|
|
||||||
// than the one was used when constructing the handler, but not a big deal.
|
void setFullDisplayed(bool full) {
|
||||||
bool ReplyMarkupClickHandler::getItemAndButton(
|
_fullDisplayed = full;
|
||||||
const HistoryItem **outItem,
|
}
|
||||||
const HistoryMessageReplyMarkup::Button **outButton) const {
|
|
||||||
if (HistoryItem *item = App::histItemById(_msgId)) {
|
protected:
|
||||||
if (auto *markup = item->Get<HistoryMessageReplyMarkup>()) {
|
void onClickImpl() const override {
|
||||||
|
if (auto button = getButton()) {
|
||||||
|
MsgId replyTo = (_item->id > 0) ? _item->id : 0;
|
||||||
|
App::activateBotCommand(_item->history()->peer, *button, replyTo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const HistoryItem *_item = nullptr;
|
||||||
|
int _row, _col;
|
||||||
|
bool _fullDisplayed = true;
|
||||||
|
|
||||||
|
// Finds the corresponding button in the items markup struct.
|
||||||
|
// If the button is not found it returns nullptr.
|
||||||
|
// Note: it is possible that we will point to the different button
|
||||||
|
// than the one was used when constructing the handler, but not a big deal.
|
||||||
|
const HistoryMessageReplyMarkup::Button *getButton() const {
|
||||||
|
if (auto *markup = _item->Get<HistoryMessageReplyMarkup>()) {
|
||||||
if (_row < markup->rows.size()) {
|
if (_row < markup->rows.size()) {
|
||||||
const HistoryMessageReplyMarkup::ButtonRow &row(markup->rows.at(_row));
|
const HistoryMessageReplyMarkup::ButtonRow &row(markup->rows.at(_row));
|
||||||
if (_col < row.size()) {
|
if (_col < row.size()) {
|
||||||
if (outItem) *outItem = item;
|
return &row.at(_col);
|
||||||
if (outButton) *outButton = &row.at(_col);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
// Returns the full text of the corresponding button.
|
||||||
|
QString text() const {
|
||||||
|
if (auto button = getButton()) {
|
||||||
|
return button->text;
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
ReplyKeyboard::ReplyKeyboard(const HistoryItem *item, StylePtr &&s)
|
ReplyKeyboard::ReplyKeyboard(const HistoryItem *item, StylePtr &&s)
|
||||||
: _item(item)
|
: _item(item)
|
||||||
|
@ -2785,7 +2806,7 @@ ReplyKeyboard::ReplyKeyboard(const HistoryItem *item, StylePtr &&s)
|
||||||
Button &button(newRow[j]);
|
Button &button(newRow[j]);
|
||||||
QString str = row.at(j).text;
|
QString str = row.at(j).text;
|
||||||
button.type = row.at(j).type;
|
button.type = row.at(j).type;
|
||||||
button.link.reset(new ReplyMarkupClickHandler(item->fullId(), i, j));
|
button.link.reset(new ReplyMarkupClickHandler(item, i, j));
|
||||||
button.text.setText(_st->textFont(), textOneLine(str), _textPlainOptions);
|
button.text.setText(_st->textFont(), textOneLine(str), _textPlainOptions);
|
||||||
button.characters = str.isEmpty() ? 1 : str.size();
|
button.characters = str.isEmpty() ? 1 : str.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1121,45 +1121,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ReplyMarkupClickHandler : public LeftButtonClickHandler {
|
class ReplyMarkupClickHandler;
|
||||||
public:
|
|
||||||
ReplyMarkupClickHandler(const FullMsgId &msgId, int row, int col) : _msgId(msgId), _row(row), _col(col) {
|
|
||||||
}
|
|
||||||
|
|
||||||
QString tooltip() const override {
|
|
||||||
return _fullDisplayed ? QString() : text();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFullDisplayed(bool full) {
|
|
||||||
_fullDisplayed = full;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void onClickImpl() const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
FullMsgId _msgId;
|
|
||||||
int _row, _col;
|
|
||||||
bool _fullDisplayed = true;
|
|
||||||
|
|
||||||
// Finds the corresponding item and button in the items markup struct.
|
|
||||||
// If the item or the button is not found it returns false.
|
|
||||||
// Any of the two output arguments can be nullptr if its value is not needed.
|
|
||||||
bool getItemAndButton(
|
|
||||||
const HistoryItem **outItem,
|
|
||||||
const HistoryMessageReplyMarkup::Button **outButtonPointer) const;
|
|
||||||
|
|
||||||
// Returns the full text of the corresponding button.
|
|
||||||
QString text() const {
|
|
||||||
const HistoryMessageReplyMarkup::Button *button = nullptr;
|
|
||||||
if (getItemAndButton(nullptr, &button)) {
|
|
||||||
return button->text;
|
|
||||||
}
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class ReplyKeyboard {
|
class ReplyKeyboard {
|
||||||
private:
|
private:
|
||||||
struct Button;
|
struct Button;
|
||||||
|
|
|
@ -49,6 +49,24 @@ PhotoData *ItemBase::getPhoto() const {
|
||||||
return _photo;
|
return _photo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DocumentData *ItemBase::getPreviewDocument() const {
|
||||||
|
auto previewDocument = [this]() -> DocumentData* {
|
||||||
|
if (_doc) {
|
||||||
|
return _doc;
|
||||||
|
}
|
||||||
|
if (_result) {
|
||||||
|
return _result->_document;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
if (DocumentData *result = previewDocument()) {
|
||||||
|
if (result->sticker() || result->loaded()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void ItemBase::preload() const {
|
void ItemBase::preload() const {
|
||||||
if (_result) {
|
if (_result) {
|
||||||
if (_result->_photo) {
|
if (_result->_photo) {
|
||||||
|
|
|
@ -73,6 +73,10 @@ public:
|
||||||
DocumentData *getDocument() const;
|
DocumentData *getDocument() const;
|
||||||
PhotoData *getPhoto() const;
|
PhotoData *getPhoto() const;
|
||||||
|
|
||||||
|
// Get document (possibly from InlineBots::Result) for
|
||||||
|
// showing sticker or GIF preview.
|
||||||
|
DocumentData *getPreviewDocument() const;
|
||||||
|
|
||||||
virtual void preload() const;
|
virtual void preload() const;
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
|
@ -217,7 +217,7 @@ with open('scheme.tl') as f:
|
||||||
|
|
||||||
if funcsNow:
|
if funcsNow:
|
||||||
if (isTemplate != ''):
|
if (isTemplate != ''):
|
||||||
funcsText += '\ntemplate <class TQueryType>';
|
funcsText += '\ntemplate <typename TQueryType>';
|
||||||
funcsText += '\nclass MTP' + name + ' { // RPC method \'' + nametype.group(1) + '\'\n'; # class
|
funcsText += '\nclass MTP' + name + ' { // RPC method \'' + nametype.group(1) + '\'\n'; # class
|
||||||
|
|
||||||
funcsText += 'public:\n';
|
funcsText += 'public:\n';
|
||||||
|
|
|
@ -14423,7 +14423,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class TQueryType>
|
template <typename TQueryType>
|
||||||
class MTPinvokeAfterMsg { // RPC method 'invokeAfterMsg'
|
class MTPinvokeAfterMsg { // RPC method 'invokeAfterMsg'
|
||||||
public:
|
public:
|
||||||
MTPlong vmsg_id;
|
MTPlong vmsg_id;
|
||||||
|
@ -14465,7 +14465,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class TQueryType>
|
template <typename TQueryType>
|
||||||
class MTPinvokeAfterMsgs { // RPC method 'invokeAfterMsgs'
|
class MTPinvokeAfterMsgs { // RPC method 'invokeAfterMsgs'
|
||||||
public:
|
public:
|
||||||
MTPVector<MTPlong> vmsg_ids;
|
MTPVector<MTPlong> vmsg_ids;
|
||||||
|
@ -14507,7 +14507,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class TQueryType>
|
template <typename TQueryType>
|
||||||
class MTPinitConnection { // RPC method 'initConnection'
|
class MTPinitConnection { // RPC method 'initConnection'
|
||||||
public:
|
public:
|
||||||
MTPint vapi_id;
|
MTPint vapi_id;
|
||||||
|
@ -14561,7 +14561,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class TQueryType>
|
template <typename TQueryType>
|
||||||
class MTPinvokeWithLayer { // RPC method 'invokeWithLayer'
|
class MTPinvokeWithLayer { // RPC method 'invokeWithLayer'
|
||||||
public:
|
public:
|
||||||
MTPint vlayer;
|
MTPint vlayer;
|
||||||
|
@ -14603,7 +14603,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class TQueryType>
|
template <typename TQueryType>
|
||||||
class MTPinvokeWithoutUpdates { // RPC method 'invokeWithoutUpdates'
|
class MTPinvokeWithoutUpdates { // RPC method 'invokeWithoutUpdates'
|
||||||
public:
|
public:
|
||||||
TQueryType vquery;
|
TQueryType vquery;
|
||||||
|
|
Loading…
Reference in New Issue