mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Replaced mosaic drawing in InlineBots::Layout::Inner.
This commit is contained in:
parent
9699aeb1cd
commit
81c39af122
5 changed files with 101 additions and 283 deletions
|
@ -168,6 +168,7 @@ GifsListWidget::GifsListWidget(
|
||||||
, _api(&controller->session().mtp())
|
, _api(&controller->session().mtp())
|
||||||
, _section(Section::Gifs)
|
, _section(Section::Gifs)
|
||||||
, _updateInlineItems([=] { updateInlineItems(); })
|
, _updateInlineItems([=] { updateInlineItems(); })
|
||||||
|
, _mosaic(st::emojiPanWidth - st::inlineResultsLeft)
|
||||||
, _previewTimer([=] { showPreview(); }) {
|
, _previewTimer([=] { showPreview(); }) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "inline_bots/inline_bot_result.h"
|
#include "inline_bots/inline_bot_result.h"
|
||||||
#include "inline_bots/inline_bot_layout_item.h"
|
#include "inline_bots/inline_bot_layout_item.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
#include "layout/layout_utils.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "facades.h"
|
#include "facades.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
@ -42,6 +43,7 @@ Inner::Inner(
|
||||||
st::windowBgOver,
|
st::windowBgOver,
|
||||||
[=] { update(); }))
|
[=] { update(); }))
|
||||||
, _updateInlineItems([=] { updateInlineItems(); })
|
, _updateInlineItems([=] { updateInlineItems(); })
|
||||||
|
, _mosaic(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft)
|
||||||
, _previewTimer([=] { showPreview(); }) {
|
, _previewTimer([=] { showPreview(); }) {
|
||||||
resize(st::emojiPanWidth - st::emojiScroll.width - st::roundRadiusSmall, st::inlineResultsMinHeight);
|
resize(st::emojiPanWidth - st::emojiScroll.width - st::roundRadiusSmall, st::inlineResultsMinHeight);
|
||||||
|
|
||||||
|
@ -72,6 +74,11 @@ Inner::Inner(
|
||||||
if (h != height()) resize(width(), h);
|
if (h != height()) resize(width(), h);
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
sizeValue(
|
||||||
|
) | rpl::start_with_next([=](const QSize &s) {
|
||||||
|
_mosaic.setFullWidth(s.width());
|
||||||
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::visibleTopBottomUpdated(
|
void Inner::visibleTopBottomUpdated(
|
||||||
|
@ -120,15 +127,15 @@ bool Inner::isRestrictedView() {
|
||||||
int Inner::countHeight() {
|
int Inner::countHeight() {
|
||||||
if (isRestrictedView()) {
|
if (isRestrictedView()) {
|
||||||
return st::stickerPanPadding + _restrictedLabel->height() + st::stickerPanPadding;
|
return st::stickerPanPadding + _restrictedLabel->height() + st::stickerPanPadding;
|
||||||
} else if (_rows.isEmpty() && !_switchPmButton) {
|
} else if (_mosaic.empty() && !_switchPmButton) {
|
||||||
return st::stickerPanPadding + st::normalFont->height + st::stickerPanPadding;
|
return st::stickerPanPadding + st::normalFont->height + st::stickerPanPadding;
|
||||||
}
|
}
|
||||||
auto result = st::stickerPanPadding;
|
auto result = st::stickerPanPadding;
|
||||||
if (_switchPmButton) {
|
if (_switchPmButton) {
|
||||||
result += _switchPmButton->height() + st::inlineResultsSkip;
|
result += _switchPmButton->height() + st::inlineResultsSkip;
|
||||||
}
|
}
|
||||||
for (int i = 0, l = _rows.count(); i < l; ++i) {
|
for (auto i = 0, l = _mosaic.rowsCount(); i < l; ++i) {
|
||||||
result += _rows[i].height;
|
result += _mosaic.rowHeightAt(i);
|
||||||
}
|
}
|
||||||
return result + st::stickerPanPadding;
|
return result + st::stickerPanPadding;
|
||||||
}
|
}
|
||||||
|
@ -169,48 +176,29 @@ void Inner::paintInlineItems(Painter &p, const QRect &r) {
|
||||||
if (_restrictedLabel) {
|
if (_restrictedLabel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_rows.isEmpty() && !_switchPmButton) {
|
if (_mosaic.empty() && !_switchPmButton) {
|
||||||
p.setFont(st::normalFont);
|
p.setFont(st::normalFont);
|
||||||
p.setPen(st::noContactsColor);
|
p.setPen(st::noContactsColor);
|
||||||
p.drawText(QRect(0, 0, width(), (height() / 3) * 2 + st::normalFont->height), tr::lng_inline_bot_no_results(tr::now), style::al_center);
|
p.drawText(QRect(0, 0, width(), (height() / 3) * 2 + st::normalFont->height), tr::lng_inline_bot_no_results(tr::now), style::al_center);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto gifPaused = _controller->isGifPausedAtLeastFor(Window::GifPauseReason::InlineResults);
|
const auto gifPaused = _controller->isGifPausedAtLeastFor(
|
||||||
InlineBots::Layout::PaintContext context(crl::now(), false, gifPaused, false);
|
Window::GifPauseReason::InlineResults);
|
||||||
|
using namespace InlineBots::Layout;
|
||||||
|
PaintContext context(crl::now(), false, gifPaused, false);
|
||||||
context.pathGradient = _pathGradient.get();
|
context.pathGradient = _pathGradient.get();
|
||||||
context.pathGradient->startFrame(0, width(), width() / 2);
|
context.pathGradient->startFrame(0, width(), width() / 2);
|
||||||
|
|
||||||
auto top = st::stickerPanPadding;
|
const auto top = st::stickerPanPadding
|
||||||
if (_switchPmButton) {
|
+ (_switchPmButton
|
||||||
top += _switchPmButton->height() + st::inlineResultsSkip;
|
? _switchPmButton->height() + st::inlineResultsSkip
|
||||||
}
|
: 0);
|
||||||
|
_mosaic.paint(
|
||||||
auto fromx = rtl() ? (width() - r.x() - r.width()) : r.x();
|
p,
|
||||||
auto tox = rtl() ? (width() - r.x()) : (r.x() + r.width());
|
top,
|
||||||
for (auto row = 0, rows = _rows.size(); row != rows; ++row) {
|
st::inlineResultsLeft - st::roundRadiusSmall,
|
||||||
auto &inlineRow = _rows[row];
|
r,
|
||||||
if (top >= r.top() + r.height()) break;
|
context);
|
||||||
if (top + inlineRow.height > r.top()) {
|
|
||||||
auto left = st::inlineResultsLeft - st::roundRadiusSmall;
|
|
||||||
if (row == rows - 1) context.lastRow = true;
|
|
||||||
for (int col = 0, cols = inlineRow.items.size(); col < cols; ++col) {
|
|
||||||
if (left >= tox) break;
|
|
||||||
|
|
||||||
auto item = inlineRow.items.at(col);
|
|
||||||
auto w = item->width();
|
|
||||||
if (left + w > fromx) {
|
|
||||||
p.translate(left, top);
|
|
||||||
item->paint(p, r.translated(-left, -top), &context);
|
|
||||||
p.translate(-left, -top);
|
|
||||||
}
|
|
||||||
left += w;
|
|
||||||
if (item->hasRightSkip()) {
|
|
||||||
left += st::inlineResultsSkip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
top += inlineRow.height;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::mousePressEvent(QMouseEvent *e) {
|
void Inner::mousePressEvent(QMouseEvent *e) {
|
||||||
|
@ -246,24 +234,21 @@ void Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
using namespace InlineBots::Layout;
|
using namespace InlineBots::Layout;
|
||||||
const auto open = dynamic_cast<OpenFileClickHandler*>(activated.get());
|
const auto open = dynamic_cast<OpenFileClickHandler*>(activated.get());
|
||||||
if (dynamic_cast<SendClickHandler*>(activated.get()) || open) {
|
if (dynamic_cast<SendClickHandler*>(activated.get()) || open) {
|
||||||
const auto row = int(_selected / MatrixRowShift);
|
selectInlineResult(_selected, {}, !!open);
|
||||||
const auto column = int(_selected % MatrixRowShift);
|
|
||||||
selectInlineResult(row, column, {}, !!open);
|
|
||||||
} else {
|
} else {
|
||||||
ActivateClickHandler(window(), activated, e->button());
|
ActivateClickHandler(window(), activated, e->button());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::selectInlineResult(
|
void Inner::selectInlineResult(
|
||||||
int row,
|
int index,
|
||||||
int column,
|
|
||||||
Api::SendOptions options,
|
Api::SendOptions options,
|
||||||
bool open) {
|
bool open) {
|
||||||
if (row >= _rows.size() || column >= _rows.at(row).items.size()) {
|
const auto item = _mosaic.maybeItemAt(index);
|
||||||
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto item = _rows[row].items[column];
|
|
||||||
if (const auto inlineResult = item->getResult()) {
|
if (const auto inlineResult = item->getResult()) {
|
||||||
if (inlineResult->onChoose(item)) {
|
if (inlineResult->onChoose(item)) {
|
||||||
_resultSelectedCallback({
|
_resultSelectedCallback({
|
||||||
|
@ -299,16 +284,14 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
if (_selected < 0 || _pressed >= 0) {
|
if (_selected < 0 || _pressed >= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto row = _selected / MatrixRowShift;
|
|
||||||
const auto column = _selected % MatrixRowShift;
|
|
||||||
const auto type = _sendMenuType
|
const auto type = _sendMenuType
|
||||||
? _sendMenuType()
|
? _sendMenuType()
|
||||||
: SendMenu::Type::Disabled;
|
: SendMenu::Type::Disabled;
|
||||||
|
|
||||||
_menu = base::make_unique_q<Ui::PopupMenu>(this);
|
_menu = base::make_unique_q<Ui::PopupMenu>(this);
|
||||||
|
|
||||||
const auto send = [=](Api::SendOptions options) {
|
const auto send = [=, selected = _selected](Api::SendOptions options) {
|
||||||
selectInlineResult(row, column, options, false);
|
selectInlineResult(selected, options, false);
|
||||||
};
|
};
|
||||||
SendMenu::FillSendMenu(
|
SendMenu::FillSendMenu(
|
||||||
_menu,
|
_menu,
|
||||||
|
@ -316,7 +299,7 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
SendMenu::DefaultSilentCallback(send),
|
SendMenu::DefaultSilentCallback(send),
|
||||||
SendMenu::DefaultScheduleCallback(this, type, send));
|
SendMenu::DefaultScheduleCallback(this, type, send));
|
||||||
|
|
||||||
auto item = _rows[row].items[column];
|
const auto item = _mosaic.itemAt(_selected);
|
||||||
if (const auto previewDocument = item->getPreviewDocument()) {
|
if (const auto previewDocument = item->getPreviewDocument()) {
|
||||||
auto callback = [&](const QString &text, Fn<void()> &&done) {
|
auto callback = [&](const QString &text, Fn<void()> &&done) {
|
||||||
_menu->addAction(text, std::move(done));
|
_menu->addAction(text, std::move(done));
|
||||||
|
@ -331,9 +314,7 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
|
|
||||||
void Inner::clearSelection() {
|
void Inner::clearSelection() {
|
||||||
if (_selected >= 0) {
|
if (_selected >= 0) {
|
||||||
int srow = _selected / MatrixRowShift, scol = _selected % MatrixRowShift;
|
ClickHandler::clearActive(_mosaic.itemAt(_selected));
|
||||||
Assert(srow >= 0 && srow < _rows.size() && scol >= 0 && scol < _rows.at(srow).items.size());
|
|
||||||
ClickHandler::clearActive(_rows.at(srow).items.at(scol));
|
|
||||||
setCursor(style::cur_default);
|
setCursor(style::cur_default);
|
||||||
}
|
}
|
||||||
_selected = _pressed = -1;
|
_selected = _pressed = -1;
|
||||||
|
@ -351,39 +332,6 @@ void Inner::clearHeavyData() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inner::inlineRowsAddItem(Result *result, Row &row, int32 &sumWidth) {
|
|
||||||
auto layout = layoutPrepareInlineResult(result, (_rows.size() * MatrixRowShift) + row.items.size());
|
|
||||||
if (!layout) return false;
|
|
||||||
|
|
||||||
layout->preload();
|
|
||||||
if (inlineRowFinalize(row, sumWidth, layout->isFullLine())) {
|
|
||||||
layout->setPosition(_rows.size() * MatrixRowShift);
|
|
||||||
}
|
|
||||||
|
|
||||||
sumWidth += layout->maxWidth();
|
|
||||||
if (!row.items.isEmpty() && row.items.back()->hasRightSkip()) {
|
|
||||||
sumWidth += st::inlineResultsSkip;
|
|
||||||
}
|
|
||||||
|
|
||||||
row.items.push_back(layout);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Inner::inlineRowFinalize(Row &row, int32 &sumWidth, bool force) {
|
|
||||||
if (row.items.isEmpty()) return false;
|
|
||||||
|
|
||||||
auto full = (row.items.size() >= kInlineItemsMaxPerRow);
|
|
||||||
auto big = (sumWidth >= st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft);
|
|
||||||
if (full || big || force) {
|
|
||||||
_rows.push_back(layoutInlineRow(row, (full || big) ? sumWidth : 0));
|
|
||||||
row = Row();
|
|
||||||
row.items.reserve(kInlineItemsMaxPerRow);
|
|
||||||
sumWidth = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Inner::inlineBotChanged() {
|
void Inner::inlineBotChanged() {
|
||||||
refreshInlineRows(nullptr, nullptr, nullptr, true);
|
refreshInlineRows(nullptr, nullptr, nullptr, true);
|
||||||
}
|
}
|
||||||
|
@ -393,16 +341,11 @@ void Inner::clearInlineRows(bool resultsDeleted) {
|
||||||
_selected = _pressed = -1;
|
_selected = _pressed = -1;
|
||||||
} else {
|
} else {
|
||||||
clearSelection();
|
clearSelection();
|
||||||
for_const (auto &row, _rows) {
|
|
||||||
for_const (auto &item, row.items) {
|
|
||||||
item->setPosition(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_rows.clear();
|
_mosaic.clearRows(resultsDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemBase *Inner::layoutPrepareInlineResult(Result *result, int32 position) {
|
ItemBase *Inner::layoutPrepareInlineResult(Result *result) {
|
||||||
auto it = _inlineLayouts.find(result);
|
auto it = _inlineLayouts.find(result);
|
||||||
if (it == _inlineLayouts.cend()) {
|
if (it == _inlineLayouts.cend()) {
|
||||||
if (auto layout = ItemBase::createLayout(this, result, _inlineWithThumb)) {
|
if (auto layout = ItemBase::createLayout(this, result, _inlineWithThumb)) {
|
||||||
|
@ -416,12 +359,11 @@ ItemBase *Inner::layoutPrepareInlineResult(Result *result, int32 position) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
it->second->setPosition(position);
|
|
||||||
return it->second.get();
|
return it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::deleteUnusedInlineLayouts() {
|
void Inner::deleteUnusedInlineLayouts() {
|
||||||
if (_rows.isEmpty()) { // delete all
|
if (_mosaic.empty()) { // delete all
|
||||||
_inlineLayouts.clear();
|
_inlineLayouts.clear();
|
||||||
} else {
|
} else {
|
||||||
for (auto i = _inlineLayouts.begin(); i != _inlineLayouts.cend();) {
|
for (auto i = _inlineLayouts.begin(); i != _inlineLayouts.cend();) {
|
||||||
|
@ -434,45 +376,8 @@ void Inner::deleteUnusedInlineLayouts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inner::Row &Inner::layoutInlineRow(Row &row, int32 sumWidth) {
|
|
||||||
auto count = int(row.items.size());
|
|
||||||
Assert(count <= kInlineItemsMaxPerRow);
|
|
||||||
|
|
||||||
// enumerate items in the order of growing maxWidth()
|
|
||||||
// for that sort item indices by maxWidth()
|
|
||||||
int indices[kInlineItemsMaxPerRow];
|
|
||||||
for (auto i = 0; i != count; ++i) {
|
|
||||||
indices[i] = i;
|
|
||||||
}
|
|
||||||
std::sort(indices, indices + count, [&row](int a, int b) -> bool {
|
|
||||||
return row.items.at(a)->maxWidth() < row.items.at(b)->maxWidth();
|
|
||||||
});
|
|
||||||
|
|
||||||
row.height = 0;
|
|
||||||
int availw = width() - (st::inlineResultsLeft - st::roundRadiusSmall);
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
int index = indices[i];
|
|
||||||
int w = sumWidth ? (row.items.at(index)->maxWidth() * availw / sumWidth) : row.items.at(index)->maxWidth();
|
|
||||||
int actualw = qMax(w, int(st::inlineResultsMinWidth));
|
|
||||||
row.height = qMax(row.height, row.items.at(index)->resizeGetHeight(actualw));
|
|
||||||
if (sumWidth) {
|
|
||||||
availw -= actualw;
|
|
||||||
sumWidth -= row.items.at(index)->maxWidth();
|
|
||||||
if (index > 0 && row.items.at(index - 1)->hasRightSkip()) {
|
|
||||||
availw -= st::inlineResultsSkip;
|
|
||||||
sumWidth -= st::inlineResultsSkip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Inner::preloadImages() {
|
void Inner::preloadImages() {
|
||||||
for (auto row = 0, rows = _rows.size(); row != rows; ++row) {
|
_mosaic.preloadImages();
|
||||||
for (auto col = 0, cols = _rows[row].items.size(); col != cols; ++col) {
|
|
||||||
_rows[row].items[col]->preload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::hideInlineRowsPanel() {
|
void Inner::hideInlineRowsPanel() {
|
||||||
|
@ -532,21 +437,22 @@ int Inner::refreshInlineRows(PeerData *queryPeer, UserData *bot, const CacheEntr
|
||||||
|
|
||||||
Assert(_inlineBot != 0);
|
Assert(_inlineBot != 0);
|
||||||
|
|
||||||
auto count = int(entry->results.size());
|
const auto count = int(entry->results.size());
|
||||||
auto from = validateExistingInlineRows(entry->results);
|
const auto from = validateExistingInlineRows(entry->results);
|
||||||
auto added = 0;
|
auto added = 0;
|
||||||
|
|
||||||
if (count) {
|
if (count) {
|
||||||
_rows.reserve(count);
|
const auto resultItems = entry->results | ranges::views::slice(
|
||||||
auto row = Row();
|
from,
|
||||||
row.items.reserve(kInlineItemsMaxPerRow);
|
count
|
||||||
auto sumWidth = 0;
|
) | ranges::views::transform([&](const std::unique_ptr<Result> &r) {
|
||||||
for (auto i = from; i != count; ++i) {
|
return layoutPrepareInlineResult(r.get());
|
||||||
if (inlineRowsAddItem(entry->results[i].get(), row, sumWidth)) {
|
}) | ranges::views::filter([](const ItemBase *item) {
|
||||||
++added;
|
return item != nullptr;
|
||||||
}
|
}) | ranges::to_vector;
|
||||||
}
|
|
||||||
inlineRowFinalize(row, sumWidth, true);
|
_mosaic.addItems(resultItems);
|
||||||
|
added = resultItems.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto h = countHeight();
|
auto h = countHeight();
|
||||||
|
@ -560,56 +466,11 @@ int Inner::refreshInlineRows(PeerData *queryPeer, UserData *bot, const CacheEntr
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inner::validateExistingInlineRows(const Results &results) {
|
int Inner::validateExistingInlineRows(const Results &results) {
|
||||||
int count = results.size(), until = 0, untilrow = 0, untilcol = 0;
|
const auto until = _mosaic.validateExistingRows(results);
|
||||||
for (; until < count;) {
|
|
||||||
if (untilrow >= _rows.size() || _rows[untilrow].items[untilcol]->getResult() != results[until].get()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++until;
|
|
||||||
if (++untilcol == _rows[untilrow].items.size()) {
|
|
||||||
++untilrow;
|
|
||||||
untilcol = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (until == count) { // all items are layed out
|
|
||||||
if (untilrow == _rows.size()) { // nothing changed
|
|
||||||
return until;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = untilrow, l = _rows.size(), skip = untilcol; i < l; ++i) {
|
if (_mosaic.empty()) {
|
||||||
for (int j = 0, s = _rows[i].items.size(); j < s; ++j) {
|
|
||||||
if (skip) {
|
|
||||||
--skip;
|
|
||||||
} else {
|
|
||||||
_rows[i].items[j]->setPosition(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!untilcol) { // all good rows are filled
|
|
||||||
_rows.resize(untilrow);
|
|
||||||
return until;
|
|
||||||
}
|
|
||||||
_rows.resize(untilrow + 1);
|
|
||||||
_rows[untilrow].items.resize(untilcol);
|
|
||||||
_rows[untilrow] = layoutInlineRow(_rows[untilrow]);
|
|
||||||
return until;
|
|
||||||
}
|
|
||||||
if (untilrow && !untilcol) { // remove last row, maybe it is not full
|
|
||||||
--untilrow;
|
|
||||||
untilcol = _rows[untilrow].items.size();
|
|
||||||
}
|
|
||||||
until -= untilcol;
|
|
||||||
|
|
||||||
for (int i = untilrow, l = _rows.size(); i < l; ++i) {
|
|
||||||
for (int j = 0, s = _rows[i].items.size(); j < s; ++j) {
|
|
||||||
_rows[i].items[j]->setPosition(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_rows.resize(untilrow);
|
|
||||||
|
|
||||||
if (_rows.isEmpty()) {
|
|
||||||
_inlineWithThumb = false;
|
_inlineWithThumb = false;
|
||||||
for (int i = until; i < count; ++i) {
|
for (int i = until; i < results.size(); ++i) {
|
||||||
if (results.at(i)->hasThumbDisplay()) {
|
if (results.at(i)->hasThumbDisplay()) {
|
||||||
_inlineWithThumb = true;
|
_inlineWithThumb = true;
|
||||||
break;
|
break;
|
||||||
|
@ -624,9 +485,8 @@ void Inner::inlineItemLayoutChanged(const ItemBase *layout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int row = _selected / MatrixRowShift, col = _selected % MatrixRowShift;
|
if (const auto item = _mosaic.maybeItemAt(_selected)) {
|
||||||
if (row < _rows.size() && col < _rows.at(row).items.size()) {
|
if (layout == item) {
|
||||||
if (layout == _rows.at(row).items.at(col)) {
|
|
||||||
updateSelected();
|
updateSelected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,15 +507,15 @@ bool Inner::inlineItemVisible(const ItemBase *layout) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int row = position / MatrixRowShift, col = position % MatrixRowShift;
|
const auto &[row, column] = ::Layout::IndexToPosition(position);
|
||||||
Assert((row < _rows.size()) && (col < _rows[row].items.size()));
|
|
||||||
|
|
||||||
int top = st::stickerPanPadding;
|
auto top = st::stickerPanPadding;
|
||||||
for (int32 i = 0; i < row; ++i) {
|
for (auto i = 0; i != row; ++i) {
|
||||||
top += _rows.at(i).height;
|
top += _mosaic.rowHeightAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (top < _visibleBottom) && (top + _rows[row].items[col]->height() > _visibleTop);
|
return (top < _visibleBottom)
|
||||||
|
&& (top + _mosaic.itemAt(row, column)->height() > _visibleTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
Data::FileOrigin Inner::inlineItemFileOrigin() {
|
Data::FileOrigin Inner::inlineItemFileOrigin() {
|
||||||
|
@ -667,94 +527,55 @@ void Inner::updateSelected() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto p = mapFromGlobal(_lastMousePos);
|
const auto p = mapFromGlobal(_lastMousePos);
|
||||||
|
|
||||||
int sx = (rtl() ? width() - p.x() : p.x()) - (st::inlineResultsLeft - st::roundRadiusSmall);
|
const auto sx = (rtl() ? width() - p.x() : p.x())
|
||||||
int sy = p.y() - st::stickerPanPadding;
|
- (st::inlineResultsLeft - st::roundRadiusSmall);
|
||||||
if (_switchPmButton) {
|
const auto sy = p.y()
|
||||||
sy -= _switchPmButton->height() + st::inlineResultsSkip;
|
- st::stickerPanPadding
|
||||||
}
|
- (_switchPmButton
|
||||||
int row = -1, col = -1, sel = -1;
|
? _switchPmButton->height() + st::inlineResultsSkip
|
||||||
ClickHandlerPtr lnk;
|
: 0);
|
||||||
ClickHandlerHost *lnkhost = nullptr;
|
const auto &[link, item, selected] = _mosaic.findByPoint({ sx, sy });
|
||||||
if (sy >= 0) {
|
|
||||||
row = 0;
|
if (_selected != selected) {
|
||||||
for (int rows = _rows.size(); row < rows; ++row) {
|
if (const auto s = _mosaic.maybeItemAt(_selected)) {
|
||||||
if (sy < _rows[row].height) {
|
s->update();
|
||||||
break;
|
|
||||||
}
|
|
||||||
sy -= _rows[row].height;
|
|
||||||
}
|
}
|
||||||
}
|
_selected = selected;
|
||||||
if (sx >= 0 && row >= 0 && row < _rows.size()) {
|
if (item) {
|
||||||
auto &inlineItems = _rows[row].items;
|
item->update();
|
||||||
col = 0;
|
|
||||||
for (int cols = inlineItems.size(); col < cols; ++col) {
|
|
||||||
int width = inlineItems.at(col)->width();
|
|
||||||
if (sx < width) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sx -= width;
|
|
||||||
if (inlineItems.at(col)->hasRightSkip()) {
|
|
||||||
sx -= st::inlineResultsSkip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (col < inlineItems.size()) {
|
|
||||||
sel = row * MatrixRowShift + col;
|
|
||||||
auto result = inlineItems[col]->getState(
|
|
||||||
QPoint(sx, sy),
|
|
||||||
HistoryView::StateRequest());
|
|
||||||
lnk = result.link;
|
|
||||||
lnkhost = inlineItems[col];
|
|
||||||
} else {
|
|
||||||
row = col = -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
row = col = -1;
|
|
||||||
}
|
|
||||||
int srow = (_selected >= 0) ? (_selected / MatrixRowShift) : -1;
|
|
||||||
int scol = (_selected >= 0) ? (_selected % MatrixRowShift) : -1;
|
|
||||||
if (_selected != sel) {
|
|
||||||
if (srow >= 0 && scol >= 0) {
|
|
||||||
Assert(srow >= 0 && srow < _rows.size() && scol >= 0 && scol < _rows.at(srow).items.size());
|
|
||||||
_rows[srow].items[scol]->update();
|
|
||||||
}
|
|
||||||
_selected = sel;
|
|
||||||
if (row >= 0 && col >= 0) {
|
|
||||||
Assert(row >= 0 && row < _rows.size() && col >= 0 && col < _rows.at(row).items.size());
|
|
||||||
_rows[row].items[col]->update();
|
|
||||||
}
|
}
|
||||||
if (_previewShown && _selected >= 0 && _pressed != _selected) {
|
if (_previewShown && _selected >= 0 && _pressed != _selected) {
|
||||||
_pressed = _selected;
|
_pressed = _selected;
|
||||||
if (row >= 0 && col >= 0) {
|
if (item) {
|
||||||
auto layout = _rows.at(row).items.at(col);
|
if (const auto preview = item->getPreviewDocument()) {
|
||||||
if (const auto previewDocument = layout->getPreviewDocument()) {
|
|
||||||
_controller->widget()->showMediaPreview(
|
_controller->widget()->showMediaPreview(
|
||||||
Data::FileOrigin(),
|
Data::FileOrigin(),
|
||||||
previewDocument);
|
preview);
|
||||||
} else if (auto previewPhoto = layout->getPreviewPhoto()) {
|
} else if (const auto preview = item->getPreviewPhoto()) {
|
||||||
_controller->widget()->showMediaPreview(
|
_controller->widget()->showMediaPreview(
|
||||||
Data::FileOrigin(),
|
Data::FileOrigin(),
|
||||||
previewPhoto);
|
preview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ClickHandler::setActive(lnk, lnkhost)) {
|
if (ClickHandler::setActive(link, item)) {
|
||||||
setCursor(lnk ? style::cur_pointer : style::cur_default);
|
setCursor(link ? style::cur_pointer : style::cur_default);
|
||||||
Ui::Tooltip::Hide();
|
Ui::Tooltip::Hide();
|
||||||
}
|
}
|
||||||
if (lnk) {
|
if (link) {
|
||||||
Ui::Tooltip::Show(1000, this);
|
Ui::Tooltip::Show(1000, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::showPreview() {
|
void Inner::showPreview() {
|
||||||
if (_pressed < 0) return;
|
if (_pressed < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int row = _pressed / MatrixRowShift, col = _pressed % MatrixRowShift;
|
if (const auto layout = _mosaic.maybeItemAt(_pressed)) {
|
||||||
if (row < _rows.size() && col < _rows.at(row).items.size()) {
|
|
||||||
auto layout = _rows.at(row).items.at(col);
|
|
||||||
if (const auto previewDocument = layout->getPreviewDocument()) {
|
if (const auto previewDocument = layout->getPreviewDocument()) {
|
||||||
_previewShown = _controller->widget()->showMediaPreview(
|
_previewShown = _controller->widget()->showMediaPreview(
|
||||||
Data::FileOrigin(),
|
Data::FileOrigin(),
|
||||||
|
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "inline_bots/inline_bot_layout_item.h"
|
#include "inline_bots/inline_bot_layout_item.h"
|
||||||
|
#include "inline_bots/inline_results_mosaic_layout.h"
|
||||||
|
|
||||||
namespace Api {
|
namespace Api {
|
||||||
struct SendOptions;
|
struct SendOptions;
|
||||||
|
@ -120,11 +121,6 @@ private:
|
||||||
static constexpr bool kRefreshIconsScrollAnimation = true;
|
static constexpr bool kRefreshIconsScrollAnimation = true;
|
||||||
static constexpr bool kRefreshIconsNoAnimation = false;
|
static constexpr bool kRefreshIconsNoAnimation = false;
|
||||||
|
|
||||||
struct Row {
|
|
||||||
int height = 0;
|
|
||||||
QVector<ItemBase*> items;
|
|
||||||
};
|
|
||||||
|
|
||||||
void switchPm();
|
void switchPm();
|
||||||
|
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
|
@ -139,18 +135,13 @@ private:
|
||||||
void showPreview();
|
void showPreview();
|
||||||
void updateInlineItems();
|
void updateInlineItems();
|
||||||
void clearInlineRows(bool resultsDeleted);
|
void clearInlineRows(bool resultsDeleted);
|
||||||
ItemBase *layoutPrepareInlineResult(Result *result, int32 position);
|
ItemBase *layoutPrepareInlineResult(Result *result);
|
||||||
|
|
||||||
bool inlineRowsAddItem(Result *result, Row &row, int32 &sumWidth);
|
|
||||||
bool inlineRowFinalize(Row &row, int32 &sumWidth, bool force = false);
|
|
||||||
|
|
||||||
Row &layoutInlineRow(Row &row, int32 sumWidth = 0);
|
|
||||||
void deleteUnusedInlineLayouts();
|
void deleteUnusedInlineLayouts();
|
||||||
|
|
||||||
int validateExistingInlineRows(const Results &results);
|
int validateExistingInlineRows(const Results &results);
|
||||||
void selectInlineResult(
|
void selectInlineResult(
|
||||||
int row,
|
int index,
|
||||||
int column,
|
|
||||||
Api::SendOptions options,
|
Api::SendOptions options,
|
||||||
bool open);
|
bool open);
|
||||||
|
|
||||||
|
@ -174,7 +165,7 @@ private:
|
||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> _menu;
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
|
||||||
QVector<Row> _rows;
|
InlineBots::Layout::MosaicLayout _mosaic;
|
||||||
|
|
||||||
std::map<Result*, std::unique_ptr<ItemBase>> _inlineLayouts;
|
std::map<Result*, std::unique_ptr<ItemBase>> _inlineLayouts;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,10 @@ constexpr auto kInlineItemsMaxPerRow = 5;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
MosaicLayout::MosaicLayout(int bigWidth)
|
||||||
|
: _bigWidth(bigWidth) {
|
||||||
|
}
|
||||||
|
|
||||||
void MosaicLayout::setFullWidth(int w) {
|
void MosaicLayout::setFullWidth(int w) {
|
||||||
_width = w;
|
_width = w;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +109,7 @@ bool MosaicLayout::rowFinalize(Row &row, int &sumWidth, bool force) {
|
||||||
|
|
||||||
const auto full = (row.items.size() >= kInlineItemsMaxPerRow);
|
const auto full = (row.items.size() >= kInlineItemsMaxPerRow);
|
||||||
// Currently use the same GIFs layout for all widget sizes.
|
// Currently use the same GIFs layout for all widget sizes.
|
||||||
const auto big = (sumWidth >= st::emojiPanWidth - st::inlineResultsLeft);
|
const auto big = (sumWidth >= _bigWidth);
|
||||||
if (full || big || force) {
|
if (full || big || force) {
|
||||||
row.maxWidth = (full || big) ? sumWidth : 0;
|
row.maxWidth = (full || big) ? sumWidth : 0;
|
||||||
layoutRow(row, _width);
|
layoutRow(row, _width);
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
ItemBase *item = nullptr;
|
ItemBase *item = nullptr;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
};
|
};
|
||||||
MosaicLayout() = default;
|
MosaicLayout(int bigWidth);
|
||||||
|
|
||||||
[[nodiscard]] int rowHeightAt(int row);
|
[[nodiscard]] int rowHeightAt(int row);
|
||||||
[[nodiscard]] int countDesiredHeight(int newWidth);
|
[[nodiscard]] int countDesiredHeight(int newWidth);
|
||||||
|
@ -68,6 +68,7 @@ private:
|
||||||
bool rowFinalize(Row &row, int &sumWidth, bool force);
|
bool rowFinalize(Row &row, int &sumWidth, bool force);
|
||||||
void layoutRow(Row &row, int fullWidth);
|
void layoutRow(Row &row, int fullWidth);
|
||||||
|
|
||||||
|
const int _bigWidth;
|
||||||
int _width = 0;
|
int _width = 0;
|
||||||
std::vector<Row> _rows;
|
std::vector<Row> _rows;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue