2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 06:35:14 +00:00

complex layouts for context gifs started

This commit is contained in:
John Preston
2015-12-30 19:56:05 +08:00
parent fa9850c319
commit e58c8a6fcb
12 changed files with 766 additions and 442 deletions

View File

@@ -1309,7 +1309,7 @@ void StickerPanInner::paintContextItems(Painter &p, const QRect &r) {
const ContextRow &contextRow(_contextRows.at(row));
if (top >= r.top() + r.height()) break;
if (top + contextRow.height > r.top()) {
int32 left = st::savedGifsLeft;
int32 left = st::inlineResultsLeft;
for (int32 col = 0, cols = contextRow.items.size(); col < cols; ++col) {
if (left >= tox) break;
@@ -1319,7 +1319,7 @@ void StickerPanInner::paintContextItems(Painter &p, const QRect &r) {
contextRow.items.at(col)->paint(p, r.translated(-left, -top), 0, &context);
p.translate(-left, -top);
}
left += w + st::savedGifsSkip;
left += w + st::inlineResultsSkip;
}
}
top += contextRow.height;
@@ -1598,6 +1598,33 @@ void StickerPanInner::refreshStickers() {
updateSelected();
}
void StickerPanInner::contextRowsAddItem(DocumentData *savedGif, ContextResult *result, ContextRow &row, int32 &sumWidth) {
LayoutContextItem *layout = 0;
if (savedGif) {
layout = layoutPrepareSavedGif(savedGif, (_contextRows.size() * MatrixRowShift) + row.items.size());
} else if (result) {
layout = layoutPrepareContextResult(result, (_contextRows.size() * MatrixRowShift) + row.items.size());
}
if (!layout) return;
contextRowFinalize(row, sumWidth, layout->fullLine());
row.items.push_back(layout);
sumWidth += layout->maxWidth();
}
void StickerPanInner::contextRowFinalize(ContextRow &row, int32 &sumWidth, bool force) {
if (row.items.isEmpty()) return;
bool full = (row.items.size() >= SavedGifsMaxPerRow);
bool big = (sumWidth >= st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - (row.items.size() - 1) * st::inlineResultsSkip);
if (full || big || force) {
_contextRows.push_back(layoutContextRow(row, (full || big) ? sumWidth : 0));
row = ContextRow();
row.items.reserve(SavedGifsMaxPerRow);
sumWidth = 0;
}
}
void StickerPanInner::refreshSavedGifs() {
if (_showingSavedGifs) {
clearContextRows();
@@ -1610,33 +1637,11 @@ void StickerPanInner::refreshSavedGifs() {
_contextRows.reserve(saved.size());
ContextRow row;
row.items.reserve(SavedGifsMaxPerRow);
int32 maxWidth = width() - st::savedGifsLeft, sumWidth = 0, widths[SavedGifsMaxPerRow] = { 0 };
int32 sumWidth = 0;
for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) {
DocumentData *doc = *i;
int32 w = doc->dimensions.width(), h = doc->dimensions.height();
if ((w <= 0 || h <= 0) && !doc->thumb->isNull()) {
w = doc->thumb->width();
h = doc->thumb->height();
}
if (w <= 0 || h <= 0) continue;
w = w * st::savedGifHeight / h;
widths[row.items.size()] = w;
w = qMax(w, int32(st::savedGifMinWidth));
sumWidth += w;
row.items.push_back(layoutPrepare(doc, (_contextRows.size() * MatrixRowShift) + row.items.size(), w));
if (row.items.size() >= SavedGifsMaxPerRow || sumWidth >= maxWidth - (row.items.size() - 1) * st::savedGifsSkip) {
_contextRows.push_back(layoutContextRow(row, widths, sumWidth));
row = ContextRow();
sumWidth = 0;
memset(widths, 0, sizeof(widths));
}
}
if (!row.items.isEmpty()) {
_contextRows.push_back(layoutContextRow(row, 0, 0));
contextRowsAddItem(*i, 0, row, sumWidth);
}
contextRowFinalize(row, sumWidth, true);
}
deleteUnusedGifLayouts();
@@ -1651,12 +1656,8 @@ void StickerPanInner::refreshSavedGifs() {
updateSelected();
}
void StickerPanInner::refreshContextResults(const ContextResults &results) {
}
void StickerPanInner::contextBotChanged() {
refreshContextResults(ContextResults());
refreshContextRows(0, ContextResults());
deleteUnusedContextLayouts();
}
@@ -1664,19 +1665,43 @@ void StickerPanInner::clearContextRows() {
clearSelection(true);
for (ContextRows::const_iterator i = _contextRows.cbegin(), e = _contextRows.cend(); i != e; ++i) {
for (ContextItems::const_iterator j = i->items.cbegin(), end = i->items.cend(); j != end; ++j) {
(*j)->setPosition(-1, 0);
(*j)->setPosition(-1);
}
}
_contextRows.clear();
}
LayoutContextGif *StickerPanInner::layoutPrepare(DocumentData *doc, int32 position, int32 width) {
LayoutContextGif *StickerPanInner::layoutPrepareSavedGif(DocumentData *doc, int32 position) {
GifLayouts::const_iterator i = _gifLayouts.constFind(doc);
if (i == _gifLayouts.cend()) {
i = _gifLayouts.insert(doc, new LayoutContextGif(doc, true));
i = _gifLayouts.insert(doc, new LayoutContextGif(0, doc, true));
i.value()->initDimensions();
}
i.value()->setPosition(position, width);
if (!i.value()->maxWidth()) return 0;
i.value()->setPosition(position);
return i.value();
}
LayoutContextItem *StickerPanInner::layoutPrepareContextResult(ContextResult *result, int32 position) {
ContextLayouts::const_iterator i = _contextLayouts.constFind(result);
if (i == _contextLayouts.cend()) {
LayoutContextItem *layout = 0;
if (result->type == qstr("gif")) {
layout = new LayoutContextGif(result, 0, false);
} else if (result->type == qstr("photo")) {
} else if (result->type == qstr("web_player_video")) {
} else if (result->type == qstr("article")) {
return 0;
}
if (!layout) return 0;
i = _contextLayouts.insert(result, layout);
layout->initDimensions();
}
if (!i.value()->maxWidth()) return 0;
i.value()->setPosition(position);
return i.value();
}
@@ -1716,20 +1741,19 @@ void StickerPanInner::deleteUnusedContextLayouts() {
}
}
StickerPanInner::ContextRow &StickerPanInner::layoutContextRow(ContextRow &row, int32 *widths, int32 sumWidth) {
StickerPanInner::ContextRow &StickerPanInner::layoutContextRow(ContextRow &row, int32 sumWidth) {
int32 count = row.items.size();
t_assert(count <= SavedGifsMaxPerRow);
row.height = 0;
int32 availw = width() - st::savedGifsLeft - st::savedGifsSkip * (count - 1);
int32 availw = width() - st::inlineResultsLeft - st::inlineResultsSkip * (count - 1);
for (int32 i = 0; i < count; ++i) {
int32 w = widths ? (widths[i] * availw / sumWidth) : row.items.at(i)->width();
int32 actualw = qMax(w, int32(st::savedGifMinWidth));
int32 w = sumWidth ? (row.items.at(i)->maxWidth() * availw / sumWidth) : row.items.at(i)->maxWidth();
int32 actualw = qMax(w, int32(st::inlineResultsMinWidth));
row.height = qMax(row.height, row.items.at(i)->resizeGetHeight(actualw));
if (widths) {
if (sumWidth) {
availw -= actualw;
sumWidth -= qMax(widths[i], int32(st::savedGifMinWidth));
sumWidth -= row.items.at(i)->maxWidth();
}
}
return row;
@@ -1778,8 +1802,85 @@ uint64 StickerPanInner::currentSet(int yOffset) const {
return _sets.isEmpty() ? RecentStickerSetId : _sets.back().id;
}
void StickerPanInner::refreshContextRows(const ContextResults &results) {
void StickerPanInner::refreshContextRows(UserData *bot, const ContextResults &results) {
int32 count = results.size(), until = 0, untilrow = 0, untilcol = 0;
if (!count) {
_contextRows.clear();
_showingSavedGifs = true;
if (_showingContextItems) {
refreshSavedGifs();
emit scrollToY(0);
emit scrollUpdated();
}
return;
}
t_assert(bot != 0);
_inlineBotTitle = lng_inline_bot_results(lt_inline_bot, bot->username.isEmpty() ? bot->name : ('@' + bot->username));
_showingContextItems = true;
_showingSavedGifs = false;
for (; until < count;) {
if (untilrow >= _contextRows.size() || _contextRows.at(untilrow).items.at(untilcol)->result() != results.at(until)) {
break;
}
++until;
if (++untilcol == _contextRows.at(untilrow).items.size()) {
++untilrow;
untilcol = 0;
}
}
if (until == count) { // all items are layed out
if (untilrow == _contextRows.size()) { // nothing changed
return;
}
for (int32 i = untilrow, l = _contextRows.size(), skip = untilcol; i < l; ++i) {
for (int32 j = 0, s = _contextRows.at(i).items.size(); j < s; ++j) {
if (skip) {
--skip;
} else {
_contextRows.at(i).items.at(j)->setPosition(-1);
}
}
}
if (!untilcol) { // all good rows are filled
_contextRows.resize(untilrow);
return;
}
_contextRows.resize(untilrow + 1);
_contextRows[untilrow].items.resize(untilcol);
_contextRows[untilrow] = layoutContextRow(_contextRows[untilrow]);
return;
}
if (untilrow && !untilcol) { // remove last row, maybe it is not full
--untilrow;
untilcol = _contextRows.at(untilrow).items.size();
}
until -= untilcol;
for (int32 i = untilrow, l = _contextRows.size(); i < l; ++i) {
for (int32 j = 0, s = _contextRows.at(i).items.size(); j < s; ++j) {
_contextRows.at(i).items.at(j)->setPosition(-1);
}
}
_contextRows.resize(untilrow);
_contextRows.reserve(count);
ContextRow row;
row.items.reserve(SavedGifsMaxPerRow);
int32 sumWidth = 0;
for (int32 i = until; i < count; ++i) {
contextRowsAddItem(0, results.at(i), row, sumWidth);
}
contextRowFinalize(row, sumWidth, true);
int32 h = countHeight();
if (h != height()) resize(width(), h);
update();
emit refreshIcons();
updateSelected();
}
void StickerPanInner::ui_repaintContextItem(const LayoutContextItem *layout) {
@@ -1916,7 +2017,7 @@ void StickerPanInner::fillPanels(QVector<EmojiPanel*> &panels) {
panels.clear();
if (_showingContextItems) {
panels.push_back(new EmojiPanel(parentWidget(), lang(lng_saved_gifs), NoneStickerSetId, true, 0));
panels.push_back(new EmojiPanel(parentWidget(), _showingSavedGifs ? lang(lng_saved_gifs) : _inlineBotTitle, NoneStickerSetId, true, 0));
panels.back()->show();
return;
}
@@ -1957,7 +2058,7 @@ void StickerPanInner::updateSelected() {
QPoint p(mapFromGlobal(_lastMousePos));
if (_showingContextItems) {
int sx = (rtl() ? width() - p.x() : p.x()) - st::savedGifsLeft, sy = p.y() - st::emojiPanHeader;
int sx = (rtl() ? width() - p.x() : p.x()) - st::inlineResultsLeft, sy = p.y() - st::emojiPanHeader;
int32 row = -1, col = -1, sel = -1;
TextLinkPtr lnk;
HistoryCursorState cursor = HistoryDefaultCursorState;
@@ -1978,7 +2079,7 @@ void StickerPanInner::updateSelected() {
if (sx < width) {
break;
}
sx -= width + st::savedGifsSkip;
sx -= width + st::inlineResultsSkip;
}
if (col < contextItems.size()) {
sel = row * MatrixRowShift + col;
@@ -2118,7 +2219,6 @@ void StickerPanInner::onPreview() {
if (_pressedSel < 0) return;
if (_showingContextItems) {
int32 row = _pressedSel / MatrixRowShift, col = _pressedSel % MatrixRowShift;
if (col >= SavedGifsMaxPerRow) col -= SavedGifsMaxPerRow;
if (row < _contextRows.size() && col < _contextRows.at(row).items.size() && _contextRows.at(row).items.at(col)->document() && _contextRows.at(row).items.at(col)->document()->loaded()) {
Ui::showStickerPreview(_contextRows.at(row).items.at(col)->document());
_previewShown = true;
@@ -2165,9 +2265,6 @@ void StickerPanInner::showStickerSet(uint64 setId) {
clearSelection(true);
if (setId == NoneStickerSetId) {
if (_contextRows.isEmpty() && !cSavedGifs().isEmpty()) {
refreshSavedGifs();
}
bool wasNotShowingGifs = !_showingContextItems;
if (wasNotShowingGifs) {
_showingContextItems = true;
@@ -2582,7 +2679,7 @@ void EmojiPan::enterEvent(QEvent *e) {
}
void EmojiPan::leaveEvent(QEvent *e) {
if (_removingSetId) return;
if (_removingSetId || s_inner.contextResultsShown()) return;
if (_a_appearance.animating()) {
hideStart();
} else {
@@ -2596,6 +2693,7 @@ void EmojiPan::otherEnter() {
}
void EmojiPan::otherLeave() {
if (_removingSetId || s_inner.contextResultsShown()) return;
if (_a_appearance.animating()) {
hideStart();
} else {
@@ -2909,6 +3007,8 @@ void EmojiPan::step_appearance(float64 ms, bool timer) {
}
void EmojiPan::hideStart() {
if (_removingSetId || s_inner.contextResultsShown()) return;
if (_cache.isNull()) {
QPixmap from = _fromCache, to = _toCache;
_fromCache = _toCache = QPixmap();
@@ -3249,6 +3349,8 @@ void EmojiPan::onDelayedHide() {
void EmojiPan::contextBotChanged() {
if (!_contextBot) return;
if (!isHidden()) hideStart();
if (_contextRequestId) MTP::cancel(_contextRequestId);
_contextRequestId = 0;
_contextQuery = _contextNextQuery = _contextNextOffset = QString();
@@ -3311,8 +3413,31 @@ void EmojiPan::contextResultsDone(const MTPmessages_BotResults &result) {
message = &r.vsend_message;
} break;
}
bool badAttachment = (!result->photo || result->photo->access) && (!result->doc || result->doc->access);
bool canSend = (result->photo || result->doc || !result->message.isEmpty());
bool badAttachment = (result->photo && !result->photo->access) || (result->doc && !result->doc->access);
if (!message) {
delete result;
continue;
}
switch (message->type()) {
case mtpc_botContextMessageMediaAuto: {
const MTPDbotContextMessageMediaAuto &r(message->c_botContextMessageMediaAuto());
result->caption = qs(r.vcaption);
} break;
case mtpc_botContextMessageText: {
const MTPDbotContextMessageText &r(message->c_botContextMessageText());
result->message = qs(r.vmessage);
if (r.has_entities()) result->entities = entitiesFromMTP(r.ventities.c_vector().v);
result->noWebPage = r.is_no_webpage();
} break;
default: {
badAttachment = true;
} break;
}
bool canSend = (result->photo || result->doc || !result->message.isEmpty() || (!result->content_url.isEmpty() && (result->type == qstr("gif") || result->type == qstr("photo"))));
if (result->type.isEmpty() || badAttachment || !canSend) {
delete result;
} else {
@@ -3323,7 +3448,7 @@ void EmojiPan::contextResultsDone(const MTPmessages_BotResults &result) {
it.value()->clearResults();
it.value()->nextOffset = QString();
}
refreshContextRows(!adding);
showContextRows(!adding);
}
bool EmojiPan::contextResultsFail(const RPCError &error) {
@@ -3332,7 +3457,7 @@ bool EmojiPan::contextResultsFail(const RPCError &error) {
return true;
}
void EmojiPan::showContextResults(UserData *bot, QString query) {
void EmojiPan::queryContextBot(UserData *bot, QString query) {
bool force = false;
if (bot != _contextBot) {
contextBotChanged();
@@ -3344,10 +3469,11 @@ void EmojiPan::showContextResults(UserData *bot, QString query) {
_contextRequestId = 0;
}
if (_contextQuery != query || force) {
if (_contextCache.contains(_contextQuery)) {
refreshContextRows(true);
if (_contextCache.contains(query)) {
_contextQuery = query;
showContextRows(true);
} else {
_contextNextQuery = _contextQuery;
_contextNextQuery = query;
_contextRequestTimer.start(ContextBotRequestDelay);
}
}
@@ -3366,16 +3492,37 @@ void EmojiPan::onContextRequest() {
_contextRequestId = MTP::send(MTPmessages_GetContextBotResults(_contextBot->inputUser, MTP_string(_contextQuery), MTP_string(nextOffset)), rpcDone(&EmojiPan::contextResultsDone), rpcFail(&EmojiPan::contextResultsFail));
}
void EmojiPan::refreshContextRows(bool newResults) {
void EmojiPan::showContextRows(bool newResults) {
bool clear = true;
ContextCache::const_iterator i = _contextCache.constFind(_contextQuery);
if (i != _contextCache.cend()) {
clear = !i.value()->results.isEmpty();
clear = i.value()->results.isEmpty();
_contextNextOffset = i.value()->nextOffset;
}
s_inner.refreshContextRows(clear ? ContextResults() : i.value()->results);
s_inner.refreshContextRows(_contextBot, clear ? ContextResults() : i.value()->results);
if (newResults) s_scroll.scrollToY(0);
if (clear && !isHidden() && _stickersShown && s_inner.contextResultsShown()) {
hideStart();
} else if (!clear) {
_hideTimer.stop();
if (!_stickersShown) {
if (!isHidden() || _hiding) {
onSwitch();
} else {
_stickersShown = true;
if (isHidden()) {
show();
a_opacity = anim::fvalue(0, 1);
a_opacity.update(0, anim::linear);
_cache = _fromCache = _toCache = QPixmap();
}
}
}
if (isHidden() || _hiding) {
showStart();
}
}
}
MentionsInner::MentionsInner(MentionsDropdown *parent, MentionRows *mrows, HashtagRows *hrows, BotCommandRows *brows)