mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Sticker preview done for inline bot results.
ReplyMarkupClickHandler moved to .cpp (implementation details).
This commit is contained in:
parent
ba7cb1abbc
commit
a728dcfca8
10 changed files with 99 additions and 85 deletions
|
@ -772,12 +772,12 @@ private:
|
|||
T *_p;
|
||||
|
||||
};
|
||||
template <typename T, class... Args>
|
||||
template <typename T, typename... Args>
|
||||
inline UniquePointer<T> MakeUnique(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) {
|
||||
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
|
||||
// on first use by constructor and are never automatically freed.
|
||||
template <typename T>
|
||||
|
|
|
@ -2172,7 +2172,9 @@ void StickerPanInner::refreshPanels(QVector<EmojiPanel*> &panels) {
|
|||
}
|
||||
|
||||
void StickerPanInner::updateSelected() {
|
||||
if (_pressedSel >= 0 && !_previewShown) return;
|
||||
if (_pressedSel >= 0 && !_previewShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32 selIndex = -1;
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
|
@ -2229,8 +2231,10 @@ void StickerPanInner::updateSelected() {
|
|||
}
|
||||
if (_pressedSel >= 0 && _selected >= 0 && _pressedSel != _selected) {
|
||||
_pressedSel = _selected;
|
||||
if (row >= 0 && col >= 0 && _inlineRows.at(row).items.at(col)->getDocument()) {
|
||||
Ui::showStickerPreview(_inlineRows.at(row).items.at(col)->getDocument());
|
||||
if (row >= 0 && col >= 0) {
|
||||
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 (_showingInlineItems) {
|
||||
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()) {
|
||||
Ui::showStickerPreview(_inlineRows.at(row).items.at(col)->getDocument());
|
||||
_previewShown = true;
|
||||
if (row < _inlineRows.size() && col < _inlineRows.at(row).items.size()) {
|
||||
if (DocumentData *previewDocument = _inlineRows.at(row).items.at(col)->getPreviewDocument()) {
|
||||
Ui::showStickerPreview(previewDocument);
|
||||
_previewShown = true;
|
||||
}
|
||||
}
|
||||
} else if (_pressedSel < MatrixRowShift * _sets.size()) {
|
||||
int tab = (_pressedSel / MatrixRowShift), sel = _pressedSel % MatrixRowShift;
|
||||
|
|
|
@ -61,8 +61,8 @@ ClickHandlerHost::~ClickHandlerHost() {
|
|||
ClickHandler::hostDestroyed(this);
|
||||
}
|
||||
|
||||
ClickHandlerPtr *ClickHandler::_active = nullptr;
|
||||
ClickHandlerPtr *ClickHandler::_pressed = nullptr;
|
||||
NeverFreedPointer<ClickHandlerPtr> ClickHandler::_active;
|
||||
NeverFreedPointer<ClickHandlerPtr> ClickHandler::_pressed;
|
||||
ClickHandlerHost *ClickHandler::_activeHost = nullptr;
|
||||
ClickHandlerHost *ClickHandler::_pressedHost = nullptr;
|
||||
|
||||
|
@ -86,9 +86,7 @@ bool ClickHandler::setActive(const ClickHandlerPtr &p, ClickHandlerHost *host) {
|
|||
}
|
||||
}
|
||||
if (p) {
|
||||
if (!_active) {
|
||||
_active = new ClickHandlerPtr(); // won't be deleted
|
||||
}
|
||||
_active.createIfNull(MakeNeverFreedCreator<ClickHandlerPtr>());
|
||||
*_active = p;
|
||||
if ((_activeHost = host)) {
|
||||
bool emitClickHandlerActiveChanged = (!_pressed || !*_pressed || *_pressed == *_active);
|
||||
|
|
|
@ -366,9 +366,7 @@ public:
|
|||
if (!_active || !*_active) {
|
||||
return;
|
||||
}
|
||||
if (!_pressed) {
|
||||
_pressed = new ClickHandlerPtr(); // won't be deleted
|
||||
}
|
||||
_pressed.createIfNull(MakeNeverFreedCreator<ClickHandlerPtr>());
|
||||
*_pressed = *_active;
|
||||
if ((_pressedHost = _activeHost)) {
|
||||
_pressedHost->clickHandlerPressedChanged(*_pressed, true);
|
||||
|
@ -428,8 +426,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
static ClickHandlerPtr *_active;
|
||||
static ClickHandlerPtr *_pressed;
|
||||
static NeverFreedPointer<ClickHandlerPtr> _active;
|
||||
static NeverFreedPointer<ClickHandlerPtr> _pressed;
|
||||
static ClickHandlerHost *_activeHost;
|
||||
static ClickHandlerHost *_pressedHost;
|
||||
|
||||
|
|
|
@ -2740,36 +2740,57 @@ void HistoryBlock::removeItem(HistoryItem *item) {
|
|||
}
|
||||
}
|
||||
|
||||
void ReplyMarkupClickHandler::onClickImpl() const {
|
||||
const HistoryItem *item = nullptr;
|
||||
const HistoryMessageReplyMarkup::Button *button = nullptr;
|
||||
if (getItemAndButton(&item, &button)) {
|
||||
App::activateBotCommand(item->history()->peer, *button, _msgId.msg);
|
||||
class ReplyMarkupClickHandler : public LeftButtonClickHandler {
|
||||
public:
|
||||
ReplyMarkupClickHandler(const HistoryItem *item, int row, int col) : _item(item), _row(row), _col(col) {
|
||||
}
|
||||
}
|
||||
|
||||
// We need to make sure the item still exists, so we get it by id.
|
||||
// After that we check if the reply markup is still there and that
|
||||
// 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.
|
||||
bool ReplyMarkupClickHandler::getItemAndButton(
|
||||
const HistoryItem **outItem,
|
||||
const HistoryMessageReplyMarkup::Button **outButton) const {
|
||||
if (HistoryItem *item = App::histItemById(_msgId)) {
|
||||
if (auto *markup = item->Get<HistoryMessageReplyMarkup>()) {
|
||||
QString tooltip() const override {
|
||||
return _fullDisplayed ? QString() : text();
|
||||
}
|
||||
|
||||
void setFullDisplayed(bool full) {
|
||||
_fullDisplayed = full;
|
||||
}
|
||||
|
||||
protected:
|
||||
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()) {
|
||||
const HistoryMessageReplyMarkup::ButtonRow &row(markup->rows.at(_row));
|
||||
if (_col < row.size()) {
|
||||
if (outItem) *outItem = item;
|
||||
if (outButton) *outButton = &row.at(_col);
|
||||
return true;
|
||||
return &row.at(_col);
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
: _item(item)
|
||||
|
@ -2785,7 +2806,7 @@ ReplyKeyboard::ReplyKeyboard(const HistoryItem *item, StylePtr &&s)
|
|||
Button &button(newRow[j]);
|
||||
QString str = row.at(j).text;
|
||||
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.characters = str.isEmpty() ? 1 : str.size();
|
||||
}
|
||||
|
|
|
@ -1121,45 +1121,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class ReplyMarkupClickHandler : public LeftButtonClickHandler {
|
||||
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 ReplyMarkupClickHandler;
|
||||
class ReplyKeyboard {
|
||||
private:
|
||||
struct Button;
|
||||
|
|
|
@ -49,6 +49,24 @@ PhotoData *ItemBase::getPhoto() const {
|
|||
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 {
|
||||
if (_result) {
|
||||
if (_result->_photo) {
|
||||
|
|
|
@ -73,6 +73,10 @@ public:
|
|||
DocumentData *getDocument() const;
|
||||
PhotoData *getPhoto() const;
|
||||
|
||||
// Get document (possibly from InlineBots::Result) for
|
||||
// showing sticker or GIF preview.
|
||||
DocumentData *getPreviewDocument() const;
|
||||
|
||||
virtual void preload() const;
|
||||
|
||||
void update();
|
||||
|
|
|
@ -217,7 +217,7 @@ with open('scheme.tl') as f:
|
|||
|
||||
if funcsNow:
|
||||
if (isTemplate != ''):
|
||||
funcsText += '\ntemplate <class TQueryType>';
|
||||
funcsText += '\ntemplate <typename TQueryType>';
|
||||
funcsText += '\nclass MTP' + name + ' { // RPC method \'' + nametype.group(1) + '\'\n'; # class
|
||||
|
||||
funcsText += 'public:\n';
|
||||
|
|
|
@ -14423,7 +14423,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <class TQueryType>
|
||||
template <typename TQueryType>
|
||||
class MTPinvokeAfterMsg { // RPC method 'invokeAfterMsg'
|
||||
public:
|
||||
MTPlong vmsg_id;
|
||||
|
@ -14465,7 +14465,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <class TQueryType>
|
||||
template <typename TQueryType>
|
||||
class MTPinvokeAfterMsgs { // RPC method 'invokeAfterMsgs'
|
||||
public:
|
||||
MTPVector<MTPlong> vmsg_ids;
|
||||
|
@ -14507,7 +14507,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <class TQueryType>
|
||||
template <typename TQueryType>
|
||||
class MTPinitConnection { // RPC method 'initConnection'
|
||||
public:
|
||||
MTPint vapi_id;
|
||||
|
@ -14561,7 +14561,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <class TQueryType>
|
||||
template <typename TQueryType>
|
||||
class MTPinvokeWithLayer { // RPC method 'invokeWithLayer'
|
||||
public:
|
||||
MTPint vlayer;
|
||||
|
@ -14603,7 +14603,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <class TQueryType>
|
||||
template <typename TQueryType>
|
||||
class MTPinvokeWithoutUpdates { // RPC method 'invokeWithoutUpdates'
|
||||
public:
|
||||
TQueryType vquery;
|
||||
|
|
Loading…
Add table
Reference in a new issue