mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Add search with categories to GIF.
This commit is contained in:
parent
4f18535f8d
commit
d51d1939b0
9 changed files with 108 additions and 37 deletions
|
@ -348,6 +348,7 @@ inlineBotsScroll: ScrollArea(defaultSolidScroll) {
|
||||||
deltab: stickerPanPadding;
|
deltab: stickerPanPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gifsPadding: margins(9px, 5px, 3px, 9px);
|
||||||
gifsSearchField: defaultMultiSelectSearchField;
|
gifsSearchField: defaultMultiSelectSearchField;
|
||||||
gifsSearchFieldPosition: point(42px, 7px);
|
gifsSearchFieldPosition: point(42px, 7px);
|
||||||
gifsSearchCancel: defaultMultiSelectSearchCancel;
|
gifsSearchCancel: defaultMultiSelectSearchCancel;
|
||||||
|
|
|
@ -12,6 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/qt/qt_key_modifiers.h"
|
#include "base/qt/qt_key_modifiers.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
#include "data/data_emoji_statuses.h"
|
||||||
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
|
@ -20,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/stickers/data_stickers.h"
|
#include "data/stickers/data_stickers.h"
|
||||||
#include "menu/menu_send.h" // SendMenu::FillSendMenu
|
#include "menu/menu_send.h" // SendMenu::FillSendMenu
|
||||||
#include "core/click_handler_types.h"
|
#include "core/click_handler_types.h"
|
||||||
|
#include "ui/controls/tabbed_search.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/input_fields.h"
|
#include "ui/widgets/input_fields.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
|
@ -186,6 +189,8 @@ GifsListWidget::GifsListWidget(
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
||||||
|
setupSearch();
|
||||||
|
|
||||||
_inlineRequestTimer.setSingleShot(true);
|
_inlineRequestTimer.setSingleShot(true);
|
||||||
connect(
|
connect(
|
||||||
&_inlineRequestTimer,
|
&_inlineRequestTimer,
|
||||||
|
@ -215,9 +220,8 @@ GifsListWidget::GifsListWidget(
|
||||||
_mosaic.setFullWidth(s.width());
|
_mosaic.setFullWidth(s.width());
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
_mosaic.setOffset(
|
_mosaic.setPadding(st::gifsPadding
|
||||||
st::inlineResultsLeft - st::roundRadiusSmall,
|
+ QMargins(-st::emojiPanRadius, _search->height(), 0, 0));
|
||||||
st::stickerPanPadding);
|
|
||||||
_mosaic.setRightSkip(st::inlineResultsSkip);
|
_mosaic.setRightSkip(st::inlineResultsSkip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +266,7 @@ void GifsListWidget::checkLoadMore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int GifsListWidget::countDesiredHeight(int newWidth) {
|
int GifsListWidget::countDesiredHeight(int newWidth) {
|
||||||
return _mosaic.countDesiredHeight(newWidth) + st::stickerPanPadding * 2;
|
return _mosaic.countDesiredHeight(newWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
GifsListWidget::~GifsListWidget() {
|
GifsListWidget::~GifsListWidget() {
|
||||||
|
@ -272,7 +276,7 @@ GifsListWidget::~GifsListWidget() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifsListWidget::cancelGifsSearch() {
|
void GifsListWidget::cancelGifsSearch() {
|
||||||
_footer->setLoading(false);
|
_search->setLoading(false);
|
||||||
if (_inlineRequestId) {
|
if (_inlineRequestId) {
|
||||||
_api.request(_inlineRequestId).cancel();
|
_api.request(_inlineRequestId).cancel();
|
||||||
_inlineRequestId = 0;
|
_inlineRequestId = 0;
|
||||||
|
@ -284,7 +288,7 @@ void GifsListWidget::cancelGifsSearch() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifsListWidget::inlineResultsDone(const MTPmessages_BotResults &result) {
|
void GifsListWidget::inlineResultsDone(const MTPmessages_BotResults &result) {
|
||||||
_footer->setLoading(false);
|
_search->setLoading(false);
|
||||||
_inlineRequestId = 0;
|
_inlineRequestId = 0;
|
||||||
|
|
||||||
auto it = _inlineCache.find(_inlineQuery);
|
auto it = _inlineCache.find(_inlineQuery);
|
||||||
|
@ -774,14 +778,14 @@ Data::FileOrigin GifsListWidget::inlineItemFileOrigin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifsListWidget::afterShown() {
|
void GifsListWidget::afterShown() {
|
||||||
if (_footer) {
|
if (_search) {
|
||||||
_footer->stealFocus();
|
_search->stealFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifsListWidget::beforeHiding() {
|
void GifsListWidget::beforeHiding() {
|
||||||
if (_footer) {
|
if (_search) {
|
||||||
_footer->returnFocus();
|
_search->returnFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,6 +801,26 @@ bool GifsListWidget::refreshInlineRows(int32 *added) {
|
||||||
return (entry != nullptr);
|
return (entry != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GifsListWidget::setupSearch() {
|
||||||
|
const auto owner = &_controller->session().data();
|
||||||
|
using Descriptor = Ui::SearchDescriptor;
|
||||||
|
_search = std::make_unique<Ui::TabbedSearch>(this, st(), Descriptor{
|
||||||
|
.st = st().search,
|
||||||
|
.groups = owner->emojiStatuses().emojiGroupsValue(),
|
||||||
|
.customEmojiFactory = owner->customEmojiManager().factory(
|
||||||
|
Data::CustomEmojiManager::SizeTag::SetIcon,
|
||||||
|
Ui::SearchWithGroups::IconSizeOverride())
|
||||||
|
});
|
||||||
|
_search->queryValue(
|
||||||
|
) | rpl::start_with_next([=](std::vector<QString> &&query) {
|
||||||
|
searchForGifs(ranges::accumulate(query, QString(), [](
|
||||||
|
QString a,
|
||||||
|
QString b) {
|
||||||
|
return a.isEmpty() ? b : (a + ' ' + b);
|
||||||
|
}));
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
int32 GifsListWidget::showInlineRows(bool newResults) {
|
int32 GifsListWidget::showInlineRows(bool newResults) {
|
||||||
auto added = 0;
|
auto added = 0;
|
||||||
refreshInlineRows(&added);
|
refreshInlineRows(&added);
|
||||||
|
@ -813,7 +837,7 @@ void GifsListWidget::searchForGifs(const QString &query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_inlineQuery != query) {
|
if (_inlineQuery != query) {
|
||||||
_footer->setLoading(false);
|
_search->setLoading(false);
|
||||||
if (_inlineRequestId) {
|
if (_inlineRequestId) {
|
||||||
_api.request(_inlineRequestId).cancel();
|
_api.request(_inlineRequestId).cancel();
|
||||||
_inlineRequestId = 0;
|
_inlineRequestId = 0;
|
||||||
|
@ -862,7 +886,7 @@ void GifsListWidget::sendInlineRequest() {
|
||||||
|
|
||||||
if (!_searchBot) {
|
if (!_searchBot) {
|
||||||
// Wait for the bot being resolved.
|
// Wait for the bot being resolved.
|
||||||
_footer->setLoading(true);
|
_search->setLoading(true);
|
||||||
_inlineRequestTimer.start(kSearchRequestDelay);
|
_inlineRequestTimer.start(kSearchRequestDelay);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -874,12 +898,12 @@ void GifsListWidget::sendInlineRequest() {
|
||||||
if (it != _inlineCache.cend()) {
|
if (it != _inlineCache.cend()) {
|
||||||
nextOffset = it->second->nextOffset;
|
nextOffset = it->second->nextOffset;
|
||||||
if (nextOffset.isEmpty()) {
|
if (nextOffset.isEmpty()) {
|
||||||
_footer->setLoading(false);
|
_search->setLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_footer->setLoading(true);
|
_search->setLoading(true);
|
||||||
_inlineRequestId = _api.request(MTPmessages_GetInlineBotResults(
|
_inlineRequestId = _api.request(MTPmessages_GetInlineBotResults(
|
||||||
MTP_flags(0),
|
MTP_flags(0),
|
||||||
_searchBot->inputUser,
|
_searchBot->inputUser,
|
||||||
|
@ -891,7 +915,7 @@ void GifsListWidget::sendInlineRequest() {
|
||||||
inlineResultsDone(result);
|
inlineResultsDone(result);
|
||||||
}).fail([this] {
|
}).fail([this] {
|
||||||
// show error?
|
// show error?
|
||||||
_footer->setLoading(false);
|
_search->setLoading(false);
|
||||||
_inlineRequestId = 0;
|
_inlineRequestId = 0;
|
||||||
}).handleAllErrors().send();
|
}).handleAllErrors().send();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ class Result;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class PopupMenu;
|
class PopupMenu;
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
|
class TabbedSearch;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
|
@ -119,6 +120,7 @@ private:
|
||||||
InlineResults results;
|
InlineResults results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void setupSearch();
|
||||||
void clearHeavyData();
|
void clearHeavyData();
|
||||||
void cancelGifsSearch();
|
void cancelGifsSearch();
|
||||||
void switchToSavedGifs();
|
void switchToSavedGifs();
|
||||||
|
@ -152,6 +154,7 @@ private:
|
||||||
bool forceSend = false);
|
bool forceSend = false);
|
||||||
|
|
||||||
not_null<Window::SessionController*> _controller;
|
not_null<Window::SessionController*> _controller;
|
||||||
|
std::unique_ptr<Ui::TabbedSearch> _search;
|
||||||
|
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,12 @@ bool ListSection::addItem(not_null<BaseLayout*> item) {
|
||||||
|
|
||||||
void ListSection::finishSection() {
|
void ListSection::finishSection() {
|
||||||
if (_type == Type::GIF) {
|
if (_type == Type::GIF) {
|
||||||
_mosaic.setOffset(st::infoMediaSkip, headerHeight());
|
_mosaic.setPadding({
|
||||||
|
st::infoMediaSkip,
|
||||||
|
headerHeight(),
|
||||||
|
st::infoMediaSkip,
|
||||||
|
st::stickerPanPadding,
|
||||||
|
});
|
||||||
_mosaic.setRightSkip(st::infoMediaSkip);
|
_mosaic.setRightSkip(st::infoMediaSkip);
|
||||||
_mosaic.addItems(_items);
|
_mosaic.addItems(_items);
|
||||||
}
|
}
|
||||||
|
@ -390,7 +395,7 @@ int ListSection::recountHeight() {
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type::GIF: {
|
case Type::GIF: {
|
||||||
return _mosaic.countDesiredHeight(0) + result;
|
return _mosaic.countDesiredHeight(0);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type::RoundVoiceFile:
|
case Type::RoundVoiceFile:
|
||||||
|
|
|
@ -443,13 +443,10 @@ void Inner::clearInlineRowsPanel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::refreshMosaicOffset() {
|
void Inner::refreshMosaicOffset() {
|
||||||
const auto top = st::stickerPanPadding
|
const auto top = _switchPmButton
|
||||||
+ (_switchPmButton
|
? (_switchPmButton->height() + st::inlineResultsSkip)
|
||||||
? _switchPmButton->height() + st::inlineResultsSkip
|
: 0;
|
||||||
: 0);
|
_mosaic.setPadding(st::gifsPadding + QMargins(0, top, 0, 0));
|
||||||
_mosaic.setOffset(
|
|
||||||
st::inlineResultsLeft - st::roundRadiusSmall,
|
|
||||||
top);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::refreshSwitchPmButton(const CacheEntry *entry) {
|
void Inner::refreshSwitchPmButton(const CacheEntry *entry) {
|
||||||
|
|
|
@ -27,12 +27,12 @@ int AbstractMosaicLayout::countDesiredHeight(int newWidth) {
|
||||||
layoutRow(row, newWidth ? newWidth : _width);
|
layoutRow(row, newWidth ? newWidth : _width);
|
||||||
result += row.height;
|
result += row.height;
|
||||||
}
|
}
|
||||||
return result;
|
return _padding.top() + result + _padding.bottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
FoundItem AbstractMosaicLayout::findByPoint(const QPoint &globalPoint) const {
|
FoundItem AbstractMosaicLayout::findByPoint(const QPoint &globalPoint) const {
|
||||||
auto sx = globalPoint.x() - _offset.x();
|
auto sx = globalPoint.x() - _padding.left();
|
||||||
auto sy = globalPoint.y() - _offset.y();
|
auto sy = globalPoint.y() - _padding.top();
|
||||||
auto row = -1;
|
auto row = -1;
|
||||||
auto col = -1;
|
auto col = -1;
|
||||||
auto sel = -1;
|
auto sel = -1;
|
||||||
|
@ -108,8 +108,8 @@ QRect AbstractMosaicLayout::findRect(int index) const {
|
||||||
if ((left + w) > fromX) {
|
if ((left + w) > fromX) {
|
||||||
if (item->position() == index) {
|
if (item->position() == index) {
|
||||||
return QRect(
|
return QRect(
|
||||||
left + _offset.x(),
|
left + _padding.left(),
|
||||||
top + _offset.y(),
|
top + _padding.top(),
|
||||||
item->width(),
|
item->width(),
|
||||||
item->height());
|
item->height());
|
||||||
}
|
}
|
||||||
|
@ -139,8 +139,8 @@ void AbstractMosaicLayout::setRightSkip(int rightSkip) {
|
||||||
_rightSkip = rightSkip;
|
_rightSkip = rightSkip;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractMosaicLayout::setOffset(int left, int top) {
|
void AbstractMosaicLayout::setPadding(QMargins padding) {
|
||||||
_offset = { left, top };
|
_padding = padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractMosaicLayout::setFullWidth(int w) {
|
void AbstractMosaicLayout::setFullWidth(int w) {
|
||||||
|
@ -211,7 +211,7 @@ void AbstractMosaicLayout::forEach(
|
||||||
void AbstractMosaicLayout::paint(
|
void AbstractMosaicLayout::paint(
|
||||||
Fn<void(not_null<AbstractLayoutItem*>, QPoint)> paintItem,
|
Fn<void(not_null<AbstractLayoutItem*>, QPoint)> paintItem,
|
||||||
const QRect &clip) const {
|
const QRect &clip) const {
|
||||||
auto top = _offset.y();
|
auto top = _padding.top();
|
||||||
const auto fromX = style::RightToLeft()
|
const auto fromX = style::RightToLeft()
|
||||||
? (_width - clip.x() - clip.width())
|
? (_width - clip.x() - clip.width())
|
||||||
: clip.x();
|
: clip.x();
|
||||||
|
@ -225,7 +225,7 @@ void AbstractMosaicLayout::paint(
|
||||||
}
|
}
|
||||||
auto &inlineRow = _rows[row];
|
auto &inlineRow = _rows[row];
|
||||||
if ((top + inlineRow.height) > clip.top()) {
|
if ((top + inlineRow.height) > clip.top()) {
|
||||||
auto left = _offset.x();
|
auto left = _padding.left();
|
||||||
if (row == (rows - 1)) {
|
if (row == (rows - 1)) {
|
||||||
// context.lastRow = true;
|
// context.lastRow = true;
|
||||||
}
|
}
|
||||||
|
@ -366,8 +366,7 @@ void AbstractMosaicLayout::layoutRow(Row &row, int fullWidth) {
|
||||||
|
|
||||||
auto desiredWidth = row.maxWidth;
|
auto desiredWidth = row.maxWidth;
|
||||||
row.height = 0;
|
row.height = 0;
|
||||||
auto availableWidth = fullWidth
|
auto availableWidth = fullWidth - _padding.left() - _padding.right();
|
||||||
- (st::inlineResultsLeft - st::roundRadiusSmall);
|
|
||||||
for (auto i = 0; i < count; ++i) {
|
for (auto i = 0; i < count; ++i) {
|
||||||
const auto index = indices[i];
|
const auto index = indices[i];
|
||||||
const auto &item = row.items[index];
|
const auto &item = row.items[index];
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
[[nodiscard]] QRect findRect(int index) const;
|
[[nodiscard]] QRect findRect(int index) const;
|
||||||
|
|
||||||
void setRightSkip(int rightSkip);
|
void setRightSkip(int rightSkip);
|
||||||
void setOffset(int left, int top);
|
void setPadding(QMargins padding);
|
||||||
void setFullWidth(int w);
|
void setFullWidth(int w);
|
||||||
|
|
||||||
[[nodiscard]] bool empty() const;
|
[[nodiscard]] bool empty() const;
|
||||||
|
@ -73,7 +73,7 @@ private:
|
||||||
int _bigWidth;
|
int _bigWidth;
|
||||||
int _width = 0;
|
int _width = 0;
|
||||||
int _rightSkip = 0;
|
int _rightSkip = 0;
|
||||||
QPoint _offset;
|
QMargins _padding;
|
||||||
std::vector<Row> _rows;
|
std::vector<Row> _rows;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -316,6 +316,7 @@ void SearchWithGroups::initField() {
|
||||||
} else {
|
} else {
|
||||||
_debounceTimer.callOnce(kDebounceTimeout);
|
_debounceTimer.callOnce(kDebounceTimeout);
|
||||||
_chosenGroup = QString();
|
_chosenGroup = QString();
|
||||||
|
scrollGroupsToStart();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -518,6 +519,26 @@ auto SearchWithGroups::debouncedQueryValue() const
|
||||||
return _debouncedQuery.value();
|
return _debouncedQuery.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchWithGroups::setLoading(bool loading) {
|
||||||
|
_cancel->setLoadingAnimation(loading);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchWithGroups::stealFocus() {
|
||||||
|
if (!_focusTakenFrom) {
|
||||||
|
_focusTakenFrom = QApplication::focusWidget();
|
||||||
|
}
|
||||||
|
_field->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchWithGroups::returnFocus() {
|
||||||
|
if (_field && _focusTakenFrom) {
|
||||||
|
if (_field->hasFocus()) {
|
||||||
|
_focusTakenFrom->setFocus();
|
||||||
|
}
|
||||||
|
_focusTakenFrom = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int SearchWithGroups::IconSizeOverride() {
|
int SearchWithGroups::IconSizeOverride() {
|
||||||
return style::ConvertScale(kCategoryIconSizeOverride);
|
return style::ConvertScale(kCategoryIconSizeOverride);
|
||||||
}
|
}
|
||||||
|
@ -600,6 +621,18 @@ int TabbedSearch::height() const {
|
||||||
return _search.height() + rect::m::sum::v(_st.searchMargin);
|
return _search.height() + rect::m::sum::v(_st.searchMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabbedSearch::setLoading(bool loading) {
|
||||||
|
_search.setLoading(loading);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabbedSearch::stealFocus() {
|
||||||
|
_search.stealFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabbedSearch::returnFocus() {
|
||||||
|
_search.returnFocus();
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<std::vector<QString>> TabbedSearch::queryValue() const {
|
rpl::producer<std::vector<QString>> TabbedSearch::queryValue() const {
|
||||||
return _search.queryValue();
|
return _search.queryValue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,10 @@ public:
|
||||||
[[nodiscard]] auto debouncedQueryValue() const
|
[[nodiscard]] auto debouncedQueryValue() const
|
||||||
-> rpl::producer<std::vector<QString>>;
|
-> rpl::producer<std::vector<QString>>;
|
||||||
|
|
||||||
|
void setLoading(bool loading);
|
||||||
|
void stealFocus();
|
||||||
|
void returnFocus();
|
||||||
|
|
||||||
[[nodiscard]] static int IconSizeOverride();
|
[[nodiscard]] static int IconSizeOverride();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -79,6 +83,7 @@ private:
|
||||||
not_null<FadeWrap<IconButton>*> _back;
|
not_null<FadeWrap<IconButton>*> _back;
|
||||||
not_null<CrossButton*> _cancel;
|
not_null<CrossButton*> _cancel;
|
||||||
not_null<InputField*> _field;
|
not_null<InputField*> _field;
|
||||||
|
QPointer<QWidget> _focusTakenFrom;
|
||||||
not_null<FadeWrap<RpWidget>*> _groups;
|
not_null<FadeWrap<RpWidget>*> _groups;
|
||||||
not_null<RpWidget*> _fade;
|
not_null<RpWidget*> _fade;
|
||||||
rpl::variable<float64> _fadeOpacity = 0.;
|
rpl::variable<float64> _fadeOpacity = 0.;
|
||||||
|
@ -111,6 +116,10 @@ public:
|
||||||
[[nodiscard]] auto debouncedQueryValue() const
|
[[nodiscard]] auto debouncedQueryValue() const
|
||||||
->rpl::producer<std::vector<QString>>;
|
->rpl::producer<std::vector<QString>>;
|
||||||
|
|
||||||
|
void setLoading(bool loading);
|
||||||
|
void stealFocus();
|
||||||
|
void returnFocus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const style::EmojiPan &_st;
|
const style::EmojiPan &_st;
|
||||||
SearchWithGroups _search;
|
SearchWithGroups _search;
|
||||||
|
|
Loading…
Add table
Reference in a new issue