caching web files to local, sending of inline bots results done properly, panel ux better for inline bots

This commit is contained in:
John Preston 2015-12-31 23:27:21 +08:00
parent 945d9b1883
commit 35d4754380
24 changed files with 824 additions and 264 deletions

View File

@ -554,8 +554,8 @@ taDefFlat: flatTextarea {
font: inpDefFont;
cursor: cursor(text);
phColor: #AAA;
phFocusColor: #CCC;
phColor: #999;
phFocusColor: #AAA;
phAlign: align(topleft);
phPos: point(2px, 0px);
phShift: 50px;
@ -1595,7 +1595,7 @@ profileMinBtnPadding: 10px;
membersPadding: margins(0px, 10px, 0px, 10px);
forwardMargins: margins(30px, 10px, 30px, 10px);
forwardFont: font(16px);
forwardFont: font(16px);
forwardBg: rgba(0, 0, 0, 76);
btnProfileCancel: flatButton(btnDefFlat, btnDefBig) {
color: #666d78;

View File

@ -1443,6 +1443,18 @@ namespace App {
return 0;
}
void updateImage(ImagePtr &old, ImagePtr now) {
if (now->isNull()) return;
if (old->isNull()) {
old = now;
} else if (DelayedStorageImage *img = old->toDelayedStorageImage()) {
StorageImageLocation loc = now->location();
if (!loc.isNull()) {
img->setStorageLocation(loc);
}
}
}
PhotoData *photo(const PhotoId &photo) {
PhotosData::const_iterator i = ::photosData.constFind(photo);
if (i == ::photosData.cend()) {
@ -1465,9 +1477,9 @@ namespace App {
if (date) {
convert->access = access;
convert->date = date;
if (convert->thumb->isNull() && !thumb->isNull()) convert->thumb = thumb;
if (convert->medium->isNull() && !medium->isNull()) convert->medium = medium;
if (convert->full->isNull() && !full->isNull()) convert->full = full;
updateImage(convert->thumb, thumb);
updateImage(convert->medium, medium);
updateImage(convert->full, full);
}
}
PhotosData::const_iterator i = ::photosData.constFind(photo);
@ -1485,9 +1497,9 @@ namespace App {
if (result != convert && date) {
result->access = access;
result->date = date;
if (result->thumb->isNull() && !thumb->isNull()) result->thumb = thumb;
if (result->medium->isNull() && !medium->isNull()) result->medium = medium;
if (result->full->isNull() && !full->isNull()) result->full = full;
updateImage(result->thumb, thumb);
updateImage(result->medium, medium);
updateImage(result->full, full);
}
inLastIter = lastPhotosMap.find(result);
}
@ -1526,9 +1538,7 @@ namespace App {
if (date) {
convert->access = access;
convert->date = date;
if (convert->thumb->isNull() && !thumb->isNull()) {
convert->thumb = thumb;
}
updateImage(convert->thumb, thumb);
convert->duration = duration;
convert->w = w;
convert->h = h;
@ -1553,9 +1563,7 @@ namespace App {
result->duration = duration;
result->w = w;
result->h = h;
if (result->thumb->isNull() && !thumb->isNull()) {
result->thumb = thumb;
}
updateImage(result->thumb, thumb);
result->dc = dc;
result->size = size;
}
@ -1632,9 +1640,6 @@ namespace App {
Local::copyStickerImage(mediaKey(DocumentFileLocation, convert->dc, convert->id), mediaKey(DocumentFileLocation, dc, document));
convert->id = document;
convert->status = FileReady;
if (cSavedGifs().indexOf(convert) >= 0) { // id changed
Local::writeSavedGifs();
}
sentSticker = !!convert->sticker();
}
if (date) {
@ -1652,6 +1657,11 @@ namespace App {
convert->sticker()->loc = thumbLocation;
}
}
if (cSavedGifs().indexOf(convert) >= 0) { // id changed
Local::writeSavedGifs();
}
const FileLocation &loc(convert->location(true));
if (!loc.isEmpty()) {
Local::writeFileLocation(mediaKey(DocumentFileLocation, convert->dc, convert->id), loc);

View File

@ -330,6 +330,7 @@ void AutoDownloadBox::onSave() {
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
i.value()->automaticLoadSettingsChanged();
}
Notify::automaticLoadSettingsChangedGif();
}
changed = true;
}

View File

@ -1143,7 +1143,7 @@ void EmojiPanInner::updateSelected() {
bool startanim = false;
int oldSel = _selected, newSel = selIndex;
if (newSel != oldSel) {
if (oldSel >= 0) {
_animations.remove(oldSel + 1);
@ -1229,7 +1229,7 @@ StickerPanInner::StickerPanInner() : TWidget()
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
connect(&_settings, SIGNAL(clicked()), this, SLOT(onSettings()));
_previewTimer.setSingleShot(true);
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
@ -1252,7 +1252,7 @@ void StickerPanInner::setScrollTop(int top) {
}
int StickerPanInner::countHeight() {
int result = 0, minLastH = _maxHeight - st::rbEmoji.height - st::stickerPanPadding;
int result = 0, minLastH = _maxHeight - st::stickerPanPadding;
if (_showingInlineItems) {
result = st::emojiPanHeader;
for (int i = 0, l = _inlineRows.count(); i < l; ++i) {
@ -1560,6 +1560,10 @@ void StickerPanInner::enterFromChildEvent(QEvent *e) {
updateSelected();
}
bool StickerPanInner::showSectionIcons() const {
return !inlineResultsShown();
}
void StickerPanInner::clearSelection(bool fast) {
_lastMousePos = mapToGlobal(QPoint(-10, -10));
if (fast) {
@ -2347,6 +2351,7 @@ void StickerPanInner::showStickerSet(uint64 setId) {
refreshSavedGifs();
emit scrollToY(0);
emit scrollUpdated();
_setGifCommand = App::insertBotCommand(qsl("@gif"));
return;
}
@ -2447,9 +2452,28 @@ EmojiSwitchButton::EmojiSwitchButton(QWidget *parent, bool toStickers) : Button(
updateText();
}
void EmojiSwitchButton::updateText() {
_text = lang(_toStickers ? (cSavedGifs().isEmpty() ? lng_switch_stickers : lng_switch_stickers_gifs) : lng_switch_emoji);
void EmojiSwitchButton::updateText(const QString &inlineBotUsername) {
if (_toStickers) {
if (inlineBotUsername.isEmpty()) {
_text = lang(cSavedGifs().isEmpty() ? lng_switch_stickers : lng_switch_stickers_gifs);
} else {
_text = '@' + inlineBotUsername;
}
} else {
_text = lang(lng_switch_emoji);
}
_textWidth = st::emojiPanHeaderFont->width(_text);
if (_toStickers && !inlineBotUsername.isEmpty()) {
int32 maxw = 0;
for (int c = 0; c < emojiTabCount; ++c) {
maxw = qMax(maxw, st::emojiPanHeaderFont->width(lang(LangKey(lng_emoji_category0 + c))));
}
maxw += st::emojiPanHeaderLeft + st::emojiSwitchSkip + (st::emojiSwitchSkip - st::emojiSwitchImgSkip);
if (_textWidth > st::emojiPanWidth - maxw) {
_text = st::emojiPanHeaderFont->elided(_text, st::emojiPanWidth - maxw);
_textWidth = st::emojiPanHeaderFont->width(_text);
}
}
int32 w = st::emojiSwitchSkip + _textWidth + (st::emojiSwitchSkip - st::emojiSwitchImgSkip);
resize(w, st::emojiPanHeader);
@ -2471,6 +2495,8 @@ void EmojiSwitchButton::paintEvent(QPaintEvent *e) {
EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent)
, _maxHeight(st::emojiPanMaxHeight)
, _maxHeightEmoji(_maxHeight - st::rbEmoji.height)
, _maxHeightStickers(_maxHeight - st::rbEmoji.height)
, _horizontal(false)
, _noTabUpdate(false)
, _hiding(false)
@ -2518,8 +2544,8 @@ EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent)
_height = st::dropdownDef.padding.top() + _maxHeight + st::dropdownDef.padding.bottom();
resize(_width, _height);
e_scroll.resize(st::emojiPanWidth, _maxHeight - st::rbEmoji.height);
s_scroll.resize(st::emojiPanWidth, _maxHeight - st::rbEmoji.height);
e_scroll.resize(st::emojiPanWidth, _maxHeightEmoji);
s_scroll.resize(st::emojiPanWidth, _maxHeightStickers);
e_scroll.move(st::dropdownDef.padding.left(), st::dropdownDef.padding.top());
e_scroll.setWidget(&e_inner);
@ -2588,24 +2614,28 @@ EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent)
void EmojiPan::setMaxHeight(int32 h) {
h = qMin(int(st::emojiPanMaxHeight), h);
if (h == _maxHeight) return;
int32 he = h - st::rbEmoji.height;
int32 hs = h - (s_inner.showSectionIcons() ? st::rbEmoji.height : 0);
if (h == _maxHeight && he == _maxHeightEmoji && hs == _maxHeightStickers) return;
int32 was = _maxHeight;
int32 was = _maxHeight, wase = _maxHeightEmoji, wass = _maxHeightStickers;
_maxHeight = h;
_maxHeightEmoji = he;
_maxHeightStickers = hs;
_height = st::dropdownDef.padding.top() + _maxHeight + st::dropdownDef.padding.bottom();
resize(_width, _height);
if (was > _maxHeight) {
e_scroll.resize(st::emojiPanWidth, _maxHeight - st::rbEmoji.height);
s_scroll.resize(st::emojiPanWidth, _maxHeight - st::rbEmoji.height);
s_inner.setMaxHeight(_maxHeight);
e_inner.setMaxHeight(_maxHeight);
if (was > _maxHeight || (was == _maxHeight && wass > _maxHeightStickers)) {
e_scroll.resize(st::emojiPanWidth, _maxHeightEmoji);
s_scroll.resize(st::emojiPanWidth, _maxHeightStickers);
s_inner.setMaxHeight(_maxHeightStickers);
e_inner.setMaxHeight(_maxHeightEmoji);
} else {
s_inner.setMaxHeight(_maxHeight);
e_inner.setMaxHeight(_maxHeight);
e_scroll.resize(st::emojiPanWidth, _maxHeight - st::rbEmoji.height);
s_scroll.resize(st::emojiPanWidth, _maxHeight - st::rbEmoji.height);
s_inner.setMaxHeight(_maxHeightStickers);
e_inner.setMaxHeight(_maxHeightEmoji);
e_scroll.resize(st::emojiPanWidth, _maxHeightEmoji);
s_scroll.resize(st::emojiPanWidth, _maxHeightStickers);
}
_iconsTop = st::dropdownDef.padding.top() + _maxHeight - st::rbEmoji.height;
@ -2657,7 +2687,7 @@ void EmojiPan::paintEvent(QPaintEvent *e) {
if (_toCache.isNull()) {
if (_cache.isNull()) {
p.fillRect(myrtlrect(r.x() + r.width() - st::emojiScroll.width, r.y(), st::emojiScroll.width, e_scroll.height()), st::white->b);
if (_stickersShown) {
if (_stickersShown && s_inner.showSectionIcons()) {
p.fillRect(r.left(), _iconsTop, r.width(), st::rbEmoji.height, st::emojiPanCategories->b);
p.drawSpriteLeft(_iconsLeft + 7 * st::rbEmoji.width + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::stickersSettings);
@ -2748,6 +2778,18 @@ void EmojiPan::paintEvent(QPaintEvent *e) {
}
}
void EmojiPan::moveBottom(int32 bottom, bool force) {
if (isHidden() && !force) {
move(x(), bottom - height());
return;
}
if (_stickersShown && s_inner.inlineResultsShown()) {
moveToLeft(0, bottom - height());
} else {
moveToRight(0, bottom - height());
}
}
void EmojiPan::enterEvent(QEvent *e) {
_hideTimer.stop();
if (_hiding) showStart();
@ -2919,7 +2961,10 @@ void EmojiPan::onRefreshIcons() {
}
updatePanelsPositions(s_panels, s_scroll.scrollTop());
updateSelected();
if (_stickersShown) validateSelectedIcon();
if (_stickersShown) {
validateSelectedIcon();
setMaxHeight(_maxHeight);
}
updateIcons();
}
@ -2995,6 +3040,8 @@ void EmojiPan::updateSelected() {
}
void EmojiPan::updateIcons() {
if (!_stickersShown || !s_inner.showSectionIcons()) return;
QRect r(st::dropdownDef.padding.left(), st::dropdownDef.padding.top(), _width - st::dropdownDef.padding.left() - st::dropdownDef.padding.right(), _height - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom());
update(r.left(), _iconsTop, r.width(), st::rbEmoji.height);
}
@ -3108,6 +3155,7 @@ void EmojiPan::hideFinish() {
_cache = _toCache = _fromCache = QPixmap();
_a_slide.stop();
_horizontal = false;
_hiding = false;
e_scroll.scrollToY(0);
if (!_recent.checked()) {
@ -3129,16 +3177,26 @@ void EmojiPan::hideFinish() {
}
void EmojiPan::showStart() {
if (!isHidden() && a_opacity.current() == 1) {
if (!isHidden() && !_hiding) {
return;
}
if (isHidden()) {
e_inner.refreshRecent();
s_inner.refreshRecent();
if (s_inner.inlineResultsShown() && refreshInlineRows()) {
_stickersShown = true;
} else {
s_inner.refreshRecent();
_stickersShown = false;
}
s_inner.preloadImages();
_stickersShown = false;
setMaxHeight(_maxHeight);
_fromCache = _toCache = QPixmap();
_a_slide.stop();
moveBottom(y() + height(), true);
} else if (_hiding) {
if (s_inner.inlineResultsShown() && refreshInlineRows()) {
onSwitch();
}
}
if (_cache.isNull()) {
QPixmap from = _fromCache, to = _toCache;
@ -3170,9 +3228,10 @@ bool EmojiPan::eventFilter(QObject *obj, QEvent *e) {
//}
} else if (e->type() == QEvent::MouseButtonPress && static_cast<QMouseEvent*>(e)->button() == Qt::LeftButton/* && !dynamic_cast<StickerPan*>(obj)*/) {
if (isHidden() || _hiding) {
otherEnter();
_hideTimer.stop();
showStart();
} else {
otherLeave();
hideAnimated();
}
}
return false;
@ -3181,6 +3240,7 @@ bool EmojiPan::eventFilter(QObject *obj, QEvent *e) {
void EmojiPan::stickersInstalled(uint64 setId) {
_stickersShown = true;
if (isHidden()) {
moveBottom(y() + height(), true);
show();
a_opacity = anim::fvalue(0, 1);
a_opacity.update(0, anim::linear);
@ -3188,6 +3248,7 @@ void EmojiPan::stickersInstalled(uint64 setId) {
}
showAll();
s_inner.showStickerSet(setId);
setMaxHeight(_maxHeight);
showStart();
}
@ -3211,6 +3272,14 @@ bool EmojiPan::ui_isInlineItemBeingChosen() {
return false;
}
void EmojiPan::notify_automaticLoadSettingsChangedGif() {
for (InlineCache::const_iterator i = _inlineCache.cbegin(), ei = _inlineCache.cend(); i != ei; ++i) {
for (InlineResults::const_iterator j = i.value()->results.cbegin(), ej = i.value()->results.cend(); j != ej; ++j) {
(*j)->automaticLoadSettingsChangedGif();
}
}
}
void EmojiPan::showAll() {
if (_stickersShown) {
s_scroll.show();
@ -3344,20 +3413,20 @@ void EmojiPan::onSwitch() {
_stickersShown = !_stickersShown;
if (!_stickersShown) {
Notify::clipStopperHidden(ClipStopperSavedGifsPanel);
}
if (cShowingSavedGifs() && cSavedGifs().isEmpty()) {
s_inner.showStickerSet(DefaultStickerSetId);
} else if (!cShowingSavedGifs() && !cSavedGifs().isEmpty() && cStickerSets().isEmpty()) {
s_inner.showStickerSet(NoneStickerSetId);
} else {
if (cShowingSavedGifs() && cSavedGifs().isEmpty()) {
s_inner.showStickerSet(DefaultStickerSetId);
} else if (!cShowingSavedGifs() && !cSavedGifs().isEmpty() && cStickerSets().isEmpty()) {
s_inner.showStickerSet(NoneStickerSetId);
}
validateSelectedIcon();
setMaxHeight(_maxHeight);
}
_iconOver = -1;
_iconHovers = _icons.isEmpty() ? QVector<float64>() : QVector<float64>(_icons.size(), 0);
_iconAnimations.clear();
_a_icons.stop();
validateSelectedIcon();
_cache = QPixmap();
showAll();
_toCache = myGrab(this, rect().marginsRemoved(st::dropdownDef.padding));
@ -3425,10 +3494,20 @@ void EmojiPan::onDelayedHide() {
_removingSetId = 0;
}
void EmojiPan::clearInlineBot() {
inlineBotChanged();
e_switch.updateText();
e_switch.moveToRight(0, 0, st::emojiPanWidth);
}
void EmojiPan::inlineBotChanged() {
if (!_inlineBot) return;
if (!isHidden()) hideAnimated();
if (!isHidden() && !_hiding) {
if (_stickersShown || !rect().contains(mapFromGlobal(QCursor::pos()))) {
hideAnimated();
}
}
if (_inlineRequestId) MTP::cancel(_inlineRequestId);
_inlineRequestId = 0;
@ -3555,6 +3634,7 @@ void EmojiPan::queryInlineBot(UserData *bot, QString query) {
_inlineRequestId = 0;
}
if (_inlineCache.contains(query)) {
_inlineRequestTimer.stop();
_inlineQuery = query;
showInlineRows(true);
} else {
@ -3565,7 +3645,7 @@ void EmojiPan::queryInlineBot(UserData *bot, QString query) {
}
void EmojiPan::onInlineRequest() {
if (_inlineRequestId) return;
if (_inlineRequestId || !_inlineBot) return;
_inlineQuery = _inlineNextQuery;
QString nextOffset;
@ -3577,7 +3657,7 @@ void EmojiPan::onInlineRequest() {
_inlineRequestId = MTP::send(MTPmessages_GetInlineBotResults(_inlineBot->inputUser, MTP_string(_inlineQuery), MTP_string(nextOffset)), rpcDone(&EmojiPan::inlineResultsDone), rpcFail(&EmojiPan::inlineResultsFail));
}
void EmojiPan::showInlineRows(bool newResults) {
bool EmojiPan::refreshInlineRows() {
bool clear = true;
InlineCache::const_iterator i = _inlineCache.constFind(_inlineQuery);
if (i != _inlineCache.cend()) {
@ -3586,26 +3666,25 @@ void EmojiPan::showInlineRows(bool newResults) {
}
s_inner.refreshInlineRows(_inlineBot, clear ? InlineResults() : i.value()->results, false);
return !clear;
}
void EmojiPan::showInlineRows(bool newResults) {
bool clear = !refreshInlineRows();
if (newResults) s_scroll.scrollToY(0);
if (clear && !isHidden() && _stickersShown && s_inner.inlineResultsShown()) {
e_switch.updateText(clear ? QString() : _inlineBot->username);
e_switch.moveToRight(0, 0, st::emojiPanWidth);
bool hidden = isHidden();
if (clear && !hidden && _stickersShown && s_inner.inlineResultsShown()) {
hideAnimated();
} else if (!clear) {
_hideTimer.stop();
if (!isHidden() || _hiding) {
if (!_stickersShown) {
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) {
if (hidden || _hiding) {
showStart();
} else if (!_stickersShown) {
onSwitch();
}
}
}
@ -3662,7 +3741,7 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
user->photo->load();
p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pixRounded(st::mentionPhotoSize));
user->nameText.drawElided(p, 2 * st::mentionPadding.left() + st::mentionPhotoSize, i * st::mentionHeight + st::mentionTop, namewidth);
p.setFont(st::mentionFont->f);
p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p);
p.drawText(mentionleft + namewidth + st::mentionPadding.right(), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
@ -4094,7 +4173,7 @@ void MentionsDropdown::setBoundings(QRect boundings) {
void MentionsDropdown::recount(bool toDown) {
int32 h = (_mrows.isEmpty() ? (_hrows.isEmpty() ? _brows.size() : _hrows.size()) : _mrows.size()) * st::mentionHeight, oldst = _scroll.scrollTop(), st = oldst;
if (_inner.height() != h) {
// st += h - _inner.height();
_inner.resize(width(), h);

View File

@ -254,7 +254,7 @@ public:
void fillPanels(QVector<EmojiPanel*> &panels);
void refreshPanels(QVector<EmojiPanel*> &panels);
public slots:
void updateSelected();
@ -336,6 +336,7 @@ public:
void hideFinish();
void showStickerSet(uint64 setId);
bool showSectionIcons() const;
void clearSelection(bool fast = false);
void refreshStickers();
@ -398,7 +399,7 @@ private:
void paintInlineItems(Painter &p, const QRect &r);
void paintStickers(Painter &p, const QRect &r);
int32 _maxHeight;
void appendSet(uint64 setId);
@ -514,7 +515,7 @@ public:
EmojiSwitchButton(QWidget *parent, bool toStickers); // otherwise toEmoji
void paintEvent(QPaintEvent *e);
void updateText();
void updateText(const QString &inlineBotUsername = QString());
protected:
@ -534,6 +535,8 @@ public:
void setMaxHeight(int32 h);
void paintEvent(QPaintEvent *e);
void moveBottom(int32 bottom, bool force = false);
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void otherEnter();
@ -558,7 +561,7 @@ public:
void stickersInstalled(uint64 setId);
void queryInlineBot(UserData *bot, QString query);
void inlineBotChanged();
void clearInlineBot();
bool overlaps(const QRect &globalRect) {
if (isHidden() || !_cache.isNull()) return false;
@ -574,6 +577,8 @@ public:
bool ui_isInlineItemVisible(const LayoutInlineItem *layout);
bool ui_isInlineItemBeingChosen();
void notify_automaticLoadSettingsChangedGif();
public slots:
void refreshStickers();
@ -614,7 +619,7 @@ private:
void validateSelectedIcon(bool animated = false);
int32 _maxHeight;
int32 _maxHeight, _maxHeightEmoji, _maxHeightStickers;
bool _horizontal;
void leaveToChildEvent(QEvent *e);
@ -693,7 +698,9 @@ private:
InlineCache _inlineCache;
QTimer _inlineRequestTimer;
void inlineBotChanged();
void showInlineRows(bool newResults);
bool refreshInlineRows();
UserData *_inlineBot;
QString _inlineQuery, _inlineNextQuery, _inlineNextOffset;
mtpRequestId _inlineRequestId;

View File

@ -164,4 +164,8 @@ namespace Notify {
if (MainWidget *m = App::main()) m->notify_historyItemLayoutChanged(item);
}
void automaticLoadSettingsChangedGif() {
if (MainWidget *m = App::main()) m->notify_automaticLoadSettingsChangedGif();
}
}

View File

@ -90,4 +90,6 @@ namespace Notify {
}
void historyItemLayoutChanged(const HistoryItem *item);
void automaticLoadSettingsChangedGif();
};

View File

@ -30,6 +30,7 @@ FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const
, _maxLength(-1)
, _ctrlEnterSubmit(true)
, _oldtext(v)
, _phAfter(0)
, _phVisible(!v.length())
, a_phLeft(_phVisible ? 0 : st.phShift)
, a_phAlpha(_phVisible ? 1 : 0)
@ -47,10 +48,10 @@ FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const
, _correcting(false) {
setAcceptRichText(false);
resize(_st.width, _st.font->height);
setFont(_st.font->f);
setAlignment(_st.align);
setPlaceholder(pholder);
QPalette p(palette());
@ -87,8 +88,21 @@ FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const
}
}
void FlatTextarea::setTextFast(const QString &text) {
setPlainText(text);
void FlatTextarea::setTextFast(const QString &text, bool withUndo) {
if (withUndo) {
QTextCursor c(document()->docHandle(), 0);
c.joinPreviousEditBlock();
c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
c.insertText(text);
c.movePosition(QTextCursor::End);
c.endEditBlock();
} else {
setPlainText(text);
}
finishPlaceholder();
}
void FlatTextarea::finishPlaceholder() {
if (_a_appearance.animating()) {
a_phLeft.finish();
a_phAlpha.finish();
@ -206,10 +220,14 @@ void FlatTextarea::paintEvent(QPaintEvent *e) {
if (phDraw) {
p.save();
p.setClipRect(r);
QRect phRect(_st.textMrg.left() - _fakeMargin + _st.phPos.x() + a_phLeft.current(), _st.textMrg.top() - _fakeMargin + _st.phPos.y(), width() - _st.textMrg.left() - _st.textMrg.right(), height() - _st.textMrg.top() - _st.textMrg.bottom());
p.setFont(_st.font->f);
p.setFont(_st.font);
p.setPen(a_phColor.current());
p.drawText(phRect, _ph, QTextOption(_st.phAlign));
if (_st.phAlign == style::al_topleft && _phAfter > 0) {
p.drawText(_st.textMrg.left() - _fakeMargin + a_phLeft.current() + _st.font->width(getLastText().mid(0, _phAfter)), _st.textMrg.top() - _fakeMargin - st::lineWidth + _st.font->ascent, _ph);
} else {
QRect phRect(_st.textMrg.left() - _fakeMargin + _st.phPos.x() + a_phLeft.current(), _st.textMrg.top() - _fakeMargin + _st.phPos.y(), width() - _st.textMrg.left() - _st.textMrg.right(), height() - _st.textMrg.top() - _st.textMrg.bottom());
p.drawText(phRect, _ph, QTextOption(_st.phAlign));
}
p.restore();
p.setOpacity(1);
}
@ -241,7 +259,7 @@ EmojiPtr FlatTextarea::getSingleEmoji() const {
QTextFragment fragment;
getSingleEmojiFragment(text, fragment);
if (!text.isEmpty()) {
QTextCharFormat format = fragment.charFormat();
QString imageName = static_cast<QTextImageFormat*>(&format)->name();
@ -253,9 +271,6 @@ EmojiPtr FlatTextarea::getSingleEmoji() const {
}
void FlatTextarea::getMentionHashtagBotCommandStart(QString &start, UserData *&inlineBot, QString &inlineBotUsername) const {
int32 pos = textCursor().position();
if (textCursor().anchor() != pos) return;
// check inline bot query
const QString &text(getLastText());
int32 inlineUsernameStart = 1, inlineUsernameLength = 0, size = text.size();
@ -303,6 +318,9 @@ void FlatTextarea::getMentionHashtagBotCommandStart(QString &start, UserData *&i
inlineBotUsername = QString();
}
int32 pos = textCursor().position();
if (textCursor().anchor() != pos) return;
// check mention / hashtag / bot command
QTextDocument *doc(document());
QTextBlock block = doc->findBlock(pos);
@ -764,7 +782,7 @@ void FlatTextarea::processDocumentContentsChange(int position, int charsAdded) {
emoji = 0;
replacePosition = -1;
} else {
} else {
break;
}
}
@ -888,14 +906,18 @@ void FlatTextarea::step_appearance(float64 ms, bool timer) {
if (timer) update();
}
void FlatTextarea::setPlaceholder(const QString &ph) {
void FlatTextarea::setPlaceholder(const QString &ph, int32 afterSymbols) {
_ph = ph;
_phelided = _st.font->elided(_ph, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1);
if (_phAfter != afterSymbols) {
_phAfter = afterSymbols;
updatePlaceholder();
}
_phelided = _st.font->elided(_ph, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1 - (_phAfter ? _st.font->width(getLastText().mid(0, _phAfter)) : 0));
if (_phVisible) update();
}
void FlatTextarea::updatePlaceholder() {
bool vis = getLastText().isEmpty();
bool vis = (getLastText().size() <= _phAfter);
if (vis == _phVisible) return;
a_phLeft.start(vis ? 0 : _st.phShift);

View File

@ -51,8 +51,9 @@ public:
const QString &getLastText() const {
return _oldtext;
}
void setPlaceholder(const QString &ph);
void setPlaceholder(const QString &ph, int32 afterSymbols = 0);
void updatePlaceholder();
void finishPlaceholder();
QRect getTextRect() const;
int32 fakeMargin() const;
@ -78,7 +79,7 @@ public:
QMimeData *createMimeDataFromSelection() const;
void setCtrlEnterSubmit(bool ctrlEnterSubmit);
void setTextFast(const QString &text);
void setTextFast(const QString &text, bool withUndo = false);
public slots:
@ -124,6 +125,7 @@ private:
bool _ctrlEnterSubmit;
QString _ph, _phelided, _oldtext;
int32 _phAfter;
bool _phVisible;
anim::ivalue a_phLeft;
anim::fvalue a_phAlpha;

View File

@ -591,6 +591,10 @@ Image *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap
return new Image(filecontent, format, pixmap);
}
Image *getImage(int32 width, int32 height) {
return new DelayedStorageImage(width, height);
}
void clearStorageImages() {
for (StorageImages::const_iterator i = storageImages.cbegin(), e = storageImages.cend(); i != e; ++i) {
delete i.value();
@ -644,6 +648,13 @@ void RemoteImage::doCheckload() const {
_forgot = false;
}
void RemoteImage::loadLocal() {
if (loaded() || amLoading()) return;
_loader = createLoader(LoadFromLocalOnly, true);
if (_loader) _loader->start();
}
void RemoteImage::setData(QByteArray &bytes, const QByteArray &bytesFormat) {
QBuffer buffer(&bytes);
@ -781,6 +792,89 @@ FileLoader *StorageImage::createLoader(LoadFromCloudSetting fromCloud, bool auto
return new mtpFileLoader(&_location, _size, fromCloud, autoLoading);
}
DelayedStorageImage::DelayedStorageImage() : StorageImage(StorageImageLocation())
, _loadRequested(false)
, _loadCancelled(false)
, _loadFromCloud(false) {
}
DelayedStorageImage::DelayedStorageImage(int32 w, int32 h) : StorageImage(StorageImageLocation(w, h, 0, 0, 0, 0))
, _loadRequested(false)
, _loadCancelled(false)
, _loadFromCloud(false) {
}
DelayedStorageImage::DelayedStorageImage(QByteArray &bytes) : StorageImage(StorageImageLocation(), bytes)
, _loadRequested(false)
, _loadCancelled(false)
, _loadFromCloud(false) {
}
void DelayedStorageImage::setStorageLocation(const StorageImageLocation location) {
_location = location;
if (_loadRequested) {
if (!_loadCancelled) {
if (_loadFromCloud) {
load();
} else {
loadLocal();
}
}
_loadRequested = false;
}
}
void DelayedStorageImage::automaticLoad(const HistoryItem *item) {
if (_location.isNull()) {
if (!_loadCancelled && item) {
bool loadFromCloud = false;
if (item->history()->peer->isUser()) {
loadFromCloud = !(cAutoDownloadPhoto() & dbiadNoPrivate);
} else {
loadFromCloud = !(cAutoDownloadPhoto() & dbiadNoGroups);
}
if (_loadRequested) {
if (loadFromCloud) _loadFromCloud = loadFromCloud;
} else {
_loadFromCloud = loadFromCloud;
_loadRequested = true;
}
}
} else {
StorageImage::automaticLoad(item);
}
}
void DelayedStorageImage::automaticLoadSettingsChanged() {
if (_loadCancelled) _loadCancelled = false;
StorageImage::automaticLoadSettingsChanged();
}
void DelayedStorageImage::load(bool loadFirst, bool prior) {
if (_location.isNull()) {
_loadRequested = _loadFromCloud = true;
} else {
StorageImage::load(loadFirst, prior);
}
}
void DelayedStorageImage::loadEvenCancelled(bool loadFirst, bool prior) {
_loadCancelled = false;
StorageImage::loadEvenCancelled(loadFirst, prior);
}
bool DelayedStorageImage::displayLoading() const {
return _location.isNull() ? true : StorageImage::displayLoading();
}
void DelayedStorageImage::cancel() {
if (_loadRequested) {
_loadRequested = false;
}
StorageImage::cancel();
}
StorageImage *getImage(const StorageImageLocation &location, int32 size) {
StorageKey key(storageKey(location));
StorageImages::const_iterator i = storageImages.constFind(key);

View File

@ -109,6 +109,8 @@ inline bool operator!=(const StorageImageLocation &a, const StorageImageLocation
QPixmap imagePix(QImage img, int32 w, int32 h, bool smooth, bool blurred, bool rounded, int32 outerw, int32 outerh);
class DelayedStorageImage;
class HistoryItem;
class Image {
public:
@ -173,7 +175,7 @@ public:
}
bool isNull() const;
void forget() const;
QByteArray savedFormat() const {
@ -183,6 +185,13 @@ public:
return _saved;
}
virtual DelayedStorageImage *toDelayedStorageImage() {
return 0;
}
virtual const DelayedStorageImage *toDelayedStorageImage() const {
return 0;
}
virtual ~Image();
protected:
@ -209,6 +218,7 @@ Image *getImage(const QString &file, QByteArray format);
Image *getImage(const QByteArray &filecontent, QByteArray format);
Image *getImage(const QPixmap &pixmap, QByteArray format);
Image *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
Image *getImage(int32 width, int32 height);
typedef QPair<uint64, uint64> StorageKey;
inline uint64 storageMix32To64(int32 a, int32 b) {
@ -256,6 +266,7 @@ protected:
void checkload() const {
doCheckload();
}
void loadLocal();
private:
mutable FileLoader *_loader;
@ -271,10 +282,10 @@ public:
StorageImage(const StorageImageLocation &location, int32 size = 0);
StorageImage(const StorageImageLocation &location, QByteArray &bytes);
int32 width() const;
int32 height() const;
virtual void setInformation(int32 size, int32 width, int32 height);
virtual FileLoader *createLoader(LoadFromCloudSetting fromCloud, bool autoLoading);
@ -282,12 +293,45 @@ public:
return _location;
}
private:
protected:
StorageImageLocation _location;
int32 _size;
};
class DelayedStorageImage : public StorageImage {
public:
DelayedStorageImage();
DelayedStorageImage(int32 w, int32 h);
DelayedStorageImage(QByteArray &bytes);
void setStorageLocation(const StorageImageLocation location);
virtual DelayedStorageImage *toDelayedStorageImage() {
return this;
}
virtual const DelayedStorageImage *toDelayedStorageImage() const {
return this;
}
void automaticLoad(const HistoryItem *item); // auto load photo
void automaticLoadSettingsChanged();
bool loading() const {
return _location.isNull() ? _loadRequested : StorageImage::loading();
}
bool displayLoading() const;
void cancel();
void load(bool loadFirst = false, bool prior = true);
void loadEvenCancelled(bool loadFirst = false, bool prior = true);
private:
bool _loadRequested, _loadCancelled, _loadFromCloud;
};
StorageImage *getImage(const StorageImageLocation &location, int32 size = 0);
StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes);
Image *getImage(int32 width, int32 height, const MTPFileLocation &location);
@ -327,8 +371,22 @@ public:
ImagePtr(const StorageImageLocation &location, const QByteArray &bytes) : Parent(getImage(location, bytes)) {
}
ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr());
ImagePtr(int32 width, int32 height) : Parent(getImage(width, height)) {
}
};
inline QSize resizeKeepAspect(int32 width, int32 height, int32 towidth, int32 toheight) {
int32 w = qMax(width, 1), h = qMax(height, 1);
if (w * toheight > h * towidth) {
h = qRound(h * towidth / float64(w));
w = towidth;
} else {
w = qRound(w * toheight / float64(h));
h = toheight;
}
return QSize(qMax(w, 1), qMax(h, 1));
}
void clearStorageImages();
void clearAllImages();
int64 imageCacheSize();

View File

@ -209,7 +209,7 @@ void FakeDialogRow::paint(Painter &p, int32 w, bool act, bool sel, bool onlyBack
QRect fullRect(0, 0, w, st::dlgHeight);
p.fillRect(fullRect, (act ? st::dlgActiveBG : (sel ? st::dlgHoverBG : st::dlgBG))->b);
if (onlyBackground) return;
History *history = _item->history();
if (history->peer->migrateTo()) {
p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, history->peer->migrateTo()->photo->pix(st::dlgPhotoSize));
@ -2358,7 +2358,7 @@ void History::getNextShowFrom(HistoryBlock *block, int32 i) {
void History::addUnreadBar() {
if (unreadBar || !showFrom || showFrom->detached() || !unreadCount) return;
int32 count = unreadCount;
if (peer->migrateTo()) {
if (History *h = App::historyLoaded(peer->migrateTo()->id)) {
@ -2842,7 +2842,7 @@ void HistoryBlock::removeItem(HistoryItem *item) {
nextCollapse->destroy();
}
}
// fix date items
HistoryItem *nextItem = (i < items.size() - 1) ? items[i + 1] : ((myIndex < history->blocks.size() - 1) ? history->blocks[myIndex + 1]->items[0] : 0);
if (nextItem && nextItem == history->unreadBar) { // skip unread bar
@ -2991,7 +2991,7 @@ void HistoryItem::setId(MsgId newId) {
void HistoryItem::clipCallback(ClipReaderNotification notification) {
HistoryMedia *media = getMedia();
if (!media) return;
ClipReader *reader = media ? media->getClipReader() : 0;
if (!reader) return;
@ -4040,7 +4040,7 @@ HistoryDocument::HistoryDocument(DocumentData *document, const QString &caption,
, _namew(st::semiboldFont->width(_name))
, _caption(st::msgFileMinWidth - st::msgPadding.left() - st::msgPadding.right()) {
setLinks(new DocumentOpenLink(_data), new DocumentSaveLink(_data), new DocumentCancelLink(_data));
setStatusSize(FileStatusSizeReady);
if (!caption.isEmpty()) {
@ -4152,7 +4152,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
statustop = st::msgFileThumbStatusTop;
linktop = st::msgFileThumbLinkTop;
bottom = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width));
if (_data->thumb->loaded()) {
QPixmap thumb = loaded ? _data->thumb->pixSingle(_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize);
@ -4432,6 +4432,7 @@ HistoryGif::HistoryGif(DocumentData *document, const QString &caption, const His
}
HistoryGif::HistoryGif(const HistoryGif &other) : HistoryFileMedia()
, _parent(0)
, _data(other._data)
, _thumbw(other._thumbw)
, _thumbh(other._thumbh)
@ -4442,6 +4443,7 @@ HistoryGif::HistoryGif(const HistoryGif &other) : HistoryFileMedia()
}
void HistoryGif::initDimensions(const HistoryItem *parent) {
_parent = parent;
if (_caption.hasSkipBlock()) {
_caption.setSkipBlock(parent->skipBlockWidth(), parent->skipBlockHeight());
}
@ -4556,7 +4558,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
_data->automaticLoad(parent);
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
bool loaded = _data->loaded(), displayLoading = (parent->id < 0) || _data->displayLoading();
if (loaded && !gif() && _gif != BadClipReader && cAutoPlayGif()) {
const_cast<HistoryGif*>(this)->playInline(const_cast<HistoryItem*>(parent));
if (gif()) _gif->setAutoplay();
@ -4570,11 +4572,11 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
bool animating = (gif() && _gif->started());
if (!animating || _data->uploading()) {
if (!animating || parent->id < 0) {
if (displayLoading) {
ensureAnimation(parent);
if (!_animation->radial.animating()) {
_animation->radial.start(_data->progress());
_animation->radial.start(dataProgress());
}
}
updateStatusText(parent);
@ -4606,7 +4608,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
}
if (radial || (!_gif && ((!loaded && !_data->loading()) || !cAutoPlayGif())) || (_gif == BadClipReader)) {
float64 radialOpacity = (radial && loaded && !_data->uploading()) ? _animation->radial.opacity() : 1;
float64 radialOpacity = (radial && loaded && parent->id > 0) ? _animation->radial.opacity() : 1;
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
p.setPen(Qt::NoPen);
if (selected) {
@ -4641,7 +4643,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
_animation->radial.draw(p, rinner, st::msgFileRadialLine, selected ? st::msgInBgSelected : st::msgInBg);
}
if (!animating || _data->uploading()) {
if (!animating || parent->id < 0) {
int32 statusX = skipx + st::msgDateImgDelta + st::msgDateImgPadding.x(), statusY = skipy + st::msgDateImgDelta + st::msgDateImgPadding.y();
int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
int32 statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
@ -4784,6 +4786,18 @@ HistoryGif::~HistoryGif() {
}
}
float64 HistoryGif::dataProgress() const {
return (_data->uploading() || !_parent || _parent->id > 0) ? _data->progress() : 0;
}
bool HistoryGif::dataFinished() const {
return (!_parent || _parent->id > 0) ? (!_data->loading() && !_data->uploading()) : false;
}
bool HistoryGif::dataLoaded() const {
return (!_parent || _parent->id > 0) ? _data->loaded() : false;
}
HistorySticker::HistorySticker(DocumentData *document) : HistoryMedia()
, _pixw(1)
, _pixh(1)
@ -5392,7 +5406,7 @@ void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, const QRect &r,
if (_asArticle || (_attach && _attach->customInfoLayout() && _attach->currentWidth() + parent->skipBlockWidth() > width + bubble.left() + bubble.right())) {
bshift += st::msgDateFont->height;
}
QRect bar(rtlrect(st::msgPadding.left(), 0, st::webPageBar, _height - bshift, _width));
p.fillRect(bar, barfg);
@ -5455,7 +5469,7 @@ void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, const QRect &r,
_attach->draw(p, parent, r.translated(-attachLeft, -attachTop), selected, ms);
int32 pixwidth = _attach->currentWidth(), pixheight = _attach->height();
if (_data->type == WebPageVideo) {
if (_data->siteName == qstr("YouTube")) {
p.drawPixmap(QPoint((pixwidth - st::youtubeIcon.pxWidth()) / 2, (pixheight - st::youtubeIcon.pxHeight()) / 2), App::sprite(), st::youtubeIcon);
@ -5807,12 +5821,39 @@ int32 HistoryImageLink::fullHeight() const {
return st::minPhotoSize;
}
void ViaInlineBotLink::onClick(Qt::MouseButton button) const {
App::insertBotCommand('@' + _bot->username);
}
HistoryMessageVia::HistoryMessageVia(int32 userId)
: bot(App::userLoaded(peerFromUser(userId)))
, width(0)
, fullWidth(st::msgServiceNameFont->width(qsl("via @") + bot->username))
, lnk(new ViaInlineBotLink(bot)) {
}
bool HistoryMessageVia::isNull() const {
return !bot || bot->username.isEmpty();
}
void HistoryMessageVia::resize(int32 availw) {
if (width < fullWidth && availw > width) {
if (availw < fullWidth) {
text = st::msgServiceNameFont->elided(qsl("via @") + bot->username, availw);
width = st::msgServiceNameFont->width(text);
} else {
text = qsl("via @") + bot->username;
width = fullWidth;
}
}
}
HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, const MTPDmessage &msg) :
HistoryItem(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0)
, _text(st::msgMinWidth)
, _textWidth(0)
, _textHeight(0)
, _viaBot(msg.has_via_bot_id() ? App::userLoaded(peerFromUser(msg.vvia_bot_id)) : 0)
, _via(msg.has_via_bot_id() ? new HistoryMessageVia(msg.vvia_bot_id.v) : 0)
, _media(0)
, _views(msg.has_views() ? msg.vviews.v : -1) {
QString text(textClean(qs(msg.vmessage)));
@ -5826,7 +5867,7 @@ HistoryItem(history, block, msgId, flags, date, from)
, _text(st::msgMinWidth)
, _textWidth(0)
, _textHeight(0)
, _viaBot(viaBotId ? App::userLoaded(peerFromUser(viaBotId)) : 0)
, _via(viaBotId ? new HistoryMessageVia(viaBotId) : 0)
, _media(0)
, _views(fromChannel() ? 1 : -1) {
initTime();
@ -5842,7 +5883,7 @@ HistoryItem(history, block, msgId, flags, date, from)
, _text(st::msgMinWidth)
, _textWidth(0)
, _textHeight(0)
, _viaBot(viaBotId ? App::userLoaded(peerFromUser(viaBotId)) : 0)
, _via(viaBotId ? new HistoryMessageVia(viaBotId) : 0)
, _media(0)
, _views(fromChannel() ? 1 : -1) {
initTime();
@ -5855,7 +5896,7 @@ HistoryItem(history, block, msgId, flags, date, from)
, _text(st::msgMinWidth)
, _textWidth(0)
, _textHeight(0)
, _viaBot(viaBotId ? App::userLoaded(peerFromUser(viaBotId)) : 0)
, _via(viaBotId ? new HistoryMessageVia(viaBotId) : 0)
, _media(0)
, _views(fromChannel() ? 1 : -1) {
initTime();
@ -5994,6 +6035,11 @@ void HistoryMessage::initDimensions() {
if (maxw > _maxw) _maxw = maxw;
_minh += _media->minHeight();
}
if (via()) {
if (st::msgPadding.left() + via()->fullWidth + st::msgPadding.right() > _maxw) {
_maxw = st::msgPadding.left() + via()->fullWidth + st::msgPadding.right() > _maxw;
}
}
} else {
_media->initDimensions(this);
_maxw = _media->maxWidth();
@ -6251,7 +6297,7 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m
App::roundRect(p, r, bg, cors, &sh);
if (displayFromName()) {
p.setFont(st::msgNameFont->f);
p.setFont(st::msgNameFont);
if (fromChannel()) {
p.setPen(selected ? st::msgInServiceFgSelected : st::msgInServiceFg);
} else {
@ -6260,6 +6306,7 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m
_from->nameText.drawElided(p, r.left() + st::msgPadding.left(), r.top() + st::msgPadding.top(), width - st::msgPadding.left() - st::msgPadding.right());
r.setTop(r.top() + st::msgNameFont->height);
}
QRect trect(r.marginsAdded(-st::msgPadding));
drawMessageText(p, trect, selection);
@ -6286,7 +6333,15 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m
textstyleRestore();
}
void HistoryMessage::drawMessageText(Painter &p, const QRect &trect, uint32 selection) const {
void HistoryMessage::drawMessageText(Painter &p, QRect trect, uint32 selection) const {
bool outbg = out() && !fromChannel(), selected = (selection == FullSelection);
if (via()) {
p.setFont(st::msgServiceNameFont);
p.setPen((selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg))->p);
p.drawTextLeft(trect.left(), trect.top(), _history->width, via()->text);
trect.setY(trect.y() + st::msgServiceNameFont->height);
}
p.setPen(st::msgColor->p);
p.setFont(st::msgFont->f);
uint16 selectedFrom = (selection == FullSelection) ? 0 : (selection >> 16) & 0xFFFF;
@ -6330,6 +6385,14 @@ int32 HistoryMessage::resize(int32 width) {
_height += st::msgNameFont->height;
}
}
if (via()) {
via()->resize(width - st::msgPadding.left() - st::msgPadding.right());
if (emptyText() && !displayFromName()) {
_height += st::msgPadding.top() + st::msgNameFont->height + st::mediaHeaderSkip;
} else {
_height += st::msgNameFont->height;
}
}
} else {
_height = _media->resize(width, this);
}
@ -6390,7 +6453,6 @@ void HistoryMessage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32
}
r.setTop(r.top() + st::msgNameFont->height);
}
getStateFromMessageText(lnk, state, x, y, r);
} else {
_media->getState(lnk, state, x - left, y - st::msgMargin.top(), this);
@ -6401,6 +6463,15 @@ void HistoryMessage::getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorStat
bool inDate = false;
QRect trect(r.marginsAdded(-st::msgPadding));
if (via()) {
if (x >= trect.left() && y >= trect.top() && y < trect.top() + st::msgNameFont->height && x < trect.left() + via()->width) {
lnk = via()->lnk;
return;
}
trect.setTop(trect.top() + st::msgNameFont->height);
}
TextLinkPtr medialnk;
if (_media && _media->isDisplayed()) {
if (!_media->customInfoLayout()) {
@ -6443,6 +6514,9 @@ void HistoryMessage::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x,
if (displayFromName()) { // from user left name
r.setTop(r.top() + st::msgNameFont->height);
}
if (via()) {
r.setTop(r.top() + st::msgNameFont->height);
}
QRect trect(r.marginsAdded(-st::msgPadding));
if (_media && _media->isDisplayed()) {
trect.setBottom(trect.bottom() - _media->height());
@ -6489,8 +6563,9 @@ QString HistoryMessage::notificationText() const {
HistoryMessage::~HistoryMessage() {
if (_media) {
_media->unregItem(this);
delete _media;
deleteAndMark(_media);
}
deleteAndMark(_via);
if (_flags & MTPDmessage::flag_reply_markup) {
App::clearReplyMarkup(channelId(), id);
}
@ -6506,7 +6581,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const
}
HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, QDateTime date, int32 from, HistoryMessage *msg)
: HistoryMessage(history, block, id, newMessageFlags(history->peer) | (!history->peer->isChannel() && msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage::flag_media_unread : 0), msg->viaBot() ? peerToUser(msg->viaBot()->id) : 0, date, from, msg->HistoryMessage::originalText(), msg->HistoryMessage::originalEntities(), msg->getMedia())
: HistoryMessage(history, block, id, newMessageFlags(history->peer) | (!history->peer->isChannel() && msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage::flag_media_unread : 0), msg->via() ? peerToUser(msg->viaBot()->id) : 0, date, from, msg->HistoryMessage::originalText(), msg->HistoryMessage::originalEntities(), msg->getMedia())
, fwdDate(msg->dateForwarded())
, fwdFrom(msg->fromForwarded())
, fwdFromVersion(fwdFrom->nameVersion)
@ -6548,7 +6623,7 @@ void HistoryForwarded::drawForwardedFrom(Painter &p, int32 x, int32 y, int32 w,
bool outbg = out() && !fromChannel();
p.setPen((selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg))->p);
p.setFont(serviceFont->f);
p.setFont(serviceFont);
if (w >= fromWidth) {
p.drawText(x, y + serviceFont->ascent, lang(lng_forwarded_from));
@ -6560,22 +6635,23 @@ void HistoryForwarded::drawForwardedFrom(Painter &p, int32 x, int32 y, int32 w,
}
}
void HistoryForwarded::drawMessageText(Painter &p, const QRect &trect, uint32 selection) const {
QRect realtrect(trect);
void HistoryForwarded::drawMessageText(Painter &p, QRect trect, uint32 selection) const {
if (displayForwardedFrom()) {
drawForwardedFrom(p, realtrect.x(), realtrect.y(), realtrect.width(), (selection == FullSelection));
realtrect.setY(trect.y() + st::msgServiceNameFont->height);
drawForwardedFrom(p, trect.x(), trect.y(), trect.width(), (selection == FullSelection));
trect.setY(trect.y() + st::msgServiceNameFont->height);
}
HistoryMessage::drawMessageText(p, realtrect, selection);
HistoryMessage::drawMessageText(p, trect, selection);
}
int32 HistoryForwarded::resize(int32 width) {
HistoryMessage::resize(width);
if (drawBubble() && displayForwardedFrom()) {
if (emptyText() && !displayFromName()) {
_height += st::msgPadding.top() + st::msgServiceNameFont->height + st::mediaHeaderSkip;
} else {
_height += st::msgServiceNameFont->height;
if (drawBubble()) {
if (displayForwardedFrom()) {
if (emptyText() && !displayFromName() && !via()) {
_height += st::msgPadding.top() + st::msgServiceNameFont->height + st::mediaHeaderSkip;
} else {
_height += st::msgServiceNameFont->height;
}
}
}
return _height;
@ -6719,7 +6795,7 @@ bool HistoryReply::updateReplyTo(bool force) {
replyToText.setText(st::msgFont, replyToMsg->inReplyText(), _textDlgOptions);
replyToNameUpdated();
replyToLnk = TextLinkPtr(new MessageLink(replyToMsg->history()->peer->id, replyToMsg->id));
} else if (force) {
replyToMsgId = 0;
@ -6836,21 +6912,20 @@ void HistoryReply::drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selec
}
}
void HistoryReply::drawMessageText(Painter &p, const QRect &trect, uint32 selection) const {
void HistoryReply::drawMessageText(Painter &p, QRect trect, uint32 selection) const {
int32 h = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
drawReplyTo(p, trect.x(), trect.y(), trect.width(), (selection == FullSelection));
QRect realtrect(trect);
realtrect.setY(trect.y() + h);
HistoryMessage::drawMessageText(p, realtrect, selection);
trect.setY(trect.y() + h);
HistoryMessage::drawMessageText(p, trect, selection);
}
int32 HistoryReply::resize(int32 width) {
HistoryMessage::resize(width);
if (drawBubble()) {
if (emptyText() && !displayFromName()) {
if (emptyText() && !displayFromName() && !via()) {
_height += st::msgPadding.top() + st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom() + st::mediaHeaderSkip;
} else {
_height += st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();

View File

@ -807,6 +807,10 @@ public:
virtual int32 resize(int32 width) = 0; // return new height
virtual void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const = 0;
virtual UserData *viaBot() const {
return 0;
}
History *history() const {
return _history;
}
@ -1066,7 +1070,7 @@ public:
CommentsLink(HistoryItem *item) : _item(item) {
}
void onClick(Qt::MouseButton button) const;
private:
HistoryItem *_item;
};
@ -1243,7 +1247,7 @@ protected:
}
bool isThumbAnimation(uint64 ms) const {
if (!_animation || !_animation->_a_thumbOver.animating()) return false;
_animation->_a_thumbOver.step(ms);
return _animation && _animation->_a_thumbOver.animating();
}
@ -1311,7 +1315,7 @@ public:
return _caption.original();
}
bool needsBubble(const HistoryItem *parent) const {
return !_caption.isEmpty() || parent->toHistoryReply();
return !_caption.isEmpty() || parent->toHistoryReply() || parent->viaBot();
}
bool customInfoLayout() const {
return _caption.isEmpty();
@ -1380,7 +1384,7 @@ public:
ImagePtr replyPreview();
bool needsBubble(const HistoryItem *parent) const {
return !_caption.isEmpty() || parent->toHistoryReply();
return !_caption.isEmpty() || parent->toHistoryReply() || parent->viaBot();
}
bool customInfoLayout() const {
return _caption.isEmpty();
@ -1616,7 +1620,7 @@ public:
return _caption.original();
}
bool needsBubble(const HistoryItem *parent) const {
return !_caption.isEmpty() || parent->toHistoryReply();
return !_caption.isEmpty() || parent->toHistoryReply() || parent->viaBot();
}
bool customInfoLayout() const {
return _caption.isEmpty();
@ -1632,18 +1636,13 @@ public:
protected:
float64 dataProgress() const {
return _data->progress();
}
bool dataFinished() const {
return !_data->loading() && !_data->uploading();
}
bool dataLoaded() const {
return _data->loaded();
}
float64 dataProgress() const;
bool dataFinished() const;
bool dataLoaded() const;
private:
const HistoryItem *_parent;
DocumentData *_data;
int32 _thumbw, _thumbh;
Text _caption;
@ -1840,7 +1839,7 @@ public:
HistoryMedia *attach() const {
return _attach;
}
~HistoryWebPage();
private:
@ -1885,7 +1884,7 @@ public:
}
bool needsBubble(const HistoryItem *parent) const {
return !_title.isEmpty() || !_description.isEmpty() || parent->toHistoryForwarded() || parent->toHistoryReply();
return !_title.isEmpty() || !_description.isEmpty() || parent->toHistoryForwarded() || parent->toHistoryReply() || parent->viaBot();
}
bool customInfoLayout() const {
return true;
@ -1901,6 +1900,33 @@ private:
};
class ViaInlineBotLink : public ITextLink {
TEXT_LINK_CLASS(ViaInlineBotLink)
public:
ViaInlineBotLink(UserData *bot) : _bot(bot) {
}
void onClick(Qt::MouseButton button) const;
private:
UserData *_bot;
};
class HistoryMessageVia {
public:
HistoryMessageVia(int32 userId);
bool isNull() const;
void resize(int32 availw);
UserData *bot;
QString text;
int32 width, fullWidth;
TextLinkPtr lnk;
};
class HistoryMessage : public HistoryItem {
public:
@ -1915,8 +1941,11 @@ public:
void initDimensions();
void fromNameUpdated() const;
UserData *viaBot() const {
return _viaBot;
virtual HistoryMessageVia *via() const {
return (_via && !_via->isNull()) ? _via : 0;
}
virtual UserData *viaBot() const {
return via() ? via()->bot : 0;
}
int32 plainMaxWidth() const;
@ -1932,7 +1961,7 @@ public:
return drawBubble();
}
bool displayFromName() const {
return hasFromName() && (!emptyText() || !_media || !_media->isDisplayed() || toHistoryReply() || !_media->hideFromName());
return hasFromName() && (!emptyText() || !_media || !_media->isDisplayed() || toHistoryReply() || viaBot() || !_media->hideFromName());
}
bool uploading() const {
return _media && _media->uploading();
@ -1943,7 +1972,7 @@ public:
void setId(MsgId newId);
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
virtual void drawMessageText(Painter &p, const QRect &trect, uint32 selection) const;
virtual void drawMessageText(Painter &p, QRect trect, uint32 selection) const;
int32 resize(int32 width);
bool hasPoint(int32 x, int32 y) const;
@ -1966,7 +1995,7 @@ public:
void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const;
QString notificationHeader() const;
QString notificationText() const;
void updateMedia(const MTPMessageMedia *media, bool allowEmitResize) {
if (media && _media && _media->type() != MediaTypeWebPage) {
_media->updateFrom(*media, this, allowEmitResize);
@ -2036,12 +2065,12 @@ protected:
Text _text;
int32 _textWidth, _textHeight;
UserData *_viaBot;
HistoryMessageVia *_via;
HistoryMedia *_media;
QString _timeText;
int32 _timeWidth;
QString _viewsText;
int32 _views, _viewsWidth;
@ -2058,7 +2087,7 @@ public:
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
void drawForwardedFrom(Painter &p, int32 x, int32 y, int32 w, bool selected) const;
void drawMessageText(Painter &p, const QRect &trect, uint32 selection) const;
void drawMessageText(Painter &p, QRect trect, uint32 selection) const;
int32 resize(int32 width);
bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const;
@ -2115,7 +2144,7 @@ public:
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
void drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selected, bool likeService = false) const;
void drawMessageText(Painter &p, const QRect &trect, uint32 selection) const;
void drawMessageText(Painter &p, QRect trect, uint32 selection) const;
int32 resize(int32 width);
bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const;

View File

@ -357,7 +357,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
_touchPrevPos = _touchPos;
_touchPos = e->touchPoints().cbegin()->screenPos().toPoint();
}
switch (e->type()) {
case QEvent::TouchBegin:
if (_menu) {
@ -682,7 +682,7 @@ void HistoryInner::itemRemoved(HistoryItem *item) {
}
if (_dragAction == NoDrag) return;
if (_dragItem == item) {
dragActionCancel();
}
@ -956,7 +956,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}
}
QString contextMenuText = item->selectedText(FullSelection);
if (!contextMenuText.isEmpty() && (!msg || !msg->getMedia() || _dragCursorState == HistoryInTextCursorState)) {
if (!contextMenuText.isEmpty() && (!msg || !msg->getMedia() || (msg->getMedia()->type() != MediaTypeSticker && msg->getMedia()->type() != MediaTypeGif))) {
_menu->addAction(lang(lng_context_copy_text), this, SLOT(copyContextText()))->setEnabled(true);
}
}
@ -1044,7 +1044,7 @@ void HistoryInner::copyContextUrl() {
void HistoryInner::saveContextImage() {
PhotoLink *lnk = dynamic_cast<PhotoLink*>(_contextMenuLnk.data());
if (!lnk) return;
PhotoData *photo = lnk->photo();
if (!photo || !photo->date || !photo->loaded()) return;
@ -1059,7 +1059,7 @@ void HistoryInner::saveContextImage() {
void HistoryInner::copyContextImage() {
PhotoLink *lnk = dynamic_cast<PhotoLink*>(_contextMenuLnk.data());
if (!lnk) return;
PhotoData *photo = lnk->photo();
if (!photo || !photo->date || !photo->loaded()) return;
@ -1640,7 +1640,7 @@ void HistoryInner::onUpdateSelected() {
} else if (_dragCursorState == HistoryInDateCursorState) {
// cur = style::cur_cross;
}
} else if (item) {
} else if (item) {
if (item != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) {
if (_dragAction == PrepareDrag) {
_dragAction = Dragging;
@ -1742,7 +1742,7 @@ void HistoryInner::updateDragSelection(HistoryItem *dragSelFrom, HistoryItem *dr
force = true;
}
if (!force) return;
update();
}
@ -2568,7 +2568,7 @@ bool HistoryHider::offerPeer(PeerId peer) {
if (toTextWidth > box.width() - st::boxPadding.left() - st::boxButtonPadding.right()) {
toTextWidth = box.width() - st::boxPadding.left() - st::boxButtonPadding.right();
}
resizeEvent(0);
update();
setFocus();
@ -3458,7 +3458,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
}
App::main()->peerUpdated(_peer);
if (_history->draftToId > 0 || !_history->draft.isEmpty()) {
applyDraft(false);
_replyToId = readyToForward() ? 0 : _history->draftToId;
@ -3823,11 +3823,10 @@ void HistoryWidget::updateControlsVisibility() {
}
if (hasBroadcastToggle()) {
_broadcast.show();
_field.setPlaceholder(lang(_broadcast.checked() ? lng_broadcast_ph : lng_comment_ph));
} else {
_broadcast.hide();
_field.setPlaceholder(lang((_history && _history->isChannel() && !_history->isMegagroup()) ? (_peer->asChannel()->canPublish() ? lng_broadcast_ph : lng_comment_ph) : lng_message_ph));
}
updateFieldPlaceholder();
}
if (_replyToId || readyToForward() || (_previewData && _previewData->pendingTill >= 0) || _kbReplyTo) {
if (_replyForwardPreviewCancel.isHidden()) {
@ -4187,7 +4186,7 @@ void HistoryWidget::loadMessagesDown() {
if (_history->isEmpty() && _migrated && _migrated->isEmpty()) {
return firstLoadMessages();
}
bool loadMigrated = _migrated && !(_migrated->isEmpty() || _migrated->loadedAtBottom() || (!_history->isEmpty() && !_history->loadedAtTop()));
History *from = loadMigrated ? _migrated : _history;
if (from->loadedAtBottom()) {
@ -4277,7 +4276,7 @@ void HistoryWidget::onListScroll() {
updateToEndVisibility();
updateCollapseCommentsVisibility();
int st = _scroll.scrollTop(), stm = _scroll.scrollTopMax(), sh = _scroll.height();
if (st + PreloadHeightsCount * sh > stm) {
loadMessagesDown();
@ -4442,7 +4441,7 @@ void HistoryWidget::onMuteUnmute() {
}
void HistoryWidget::onBroadcastChange() {
_field.setPlaceholder(lang(_broadcast.checked() ? lng_broadcast_ph : lng_comment_ph));
updateFieldPlaceholder();
}
void HistoryWidget::onShareContact(const PeerId &peer, UserData *contact) {
@ -4465,7 +4464,7 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const
PeerData *p = App::peer(peer);
int32 flags = newMessageFlags(p) | MTPDmessage::flag_media; // unread, out
bool lastKeyboardUsed = lastForceReplyReplied(FullMsgId(peerToChannel(peer), replyTo));
int32 sendFlags = 0;
@ -4666,7 +4665,7 @@ void HistoryWidget::onPhotoSelect() {
}
QStringList photoExtensions(cPhotoExtensions());
QStringList imgExtensions(cImgExtensions());
QStringList imgExtensions(cImgExtensions());
QString filter(qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(");;Photo files (*") + photoExtensions.join(qsl(" *")) + qsl(");;All files (*.*)"));
QStringList files;
@ -4694,7 +4693,7 @@ void HistoryWidget::onDocumentSelect() {
}
QStringList photoExtensions(cPhotoExtensions());
QStringList imgExtensions(cImgExtensions());
QStringList imgExtensions(cImgExtensions());
QString filter(qsl("All files (*.*);;Image files (*") + imgExtensions.join(qsl(" *")) + qsl(");;Photo files (*") + photoExtensions.join(qsl(" *")) + qsl(")"));
QStringList files;
@ -4838,23 +4837,27 @@ void HistoryWidget::insertBotCommand(const QString &cmd) {
if (!bot->isUser() || !bot->asUser()->botInfo) bot = 0;
QString username = bot ? bot->asUser()->username : QString();
int32 botStatus = _peer->isChat() ? _peer->asChat()->botStatus : (_peer->isMegagroup() ? _peer->asChannel()->mgInfo->botStatus : -1);
if (toInsert.indexOf('@') < 2 && !username.isEmpty() && (botStatus == 0 || botStatus == 2)) {
if (toInsert.indexOf('@') < 0 && !username.isEmpty() && (botStatus == 0 || botStatus == 2)) {
toInsert += '@' + username;
}
toInsert += ' ';
QString text = _field.getLastText();
QRegularExpressionMatch m = QRegularExpression(qsl("^/[A-Za-z_0-9]{0,64}(@[A-Za-z_0-9]{0,32})?(\\s|$)")).match(text);
if (m.hasMatch()) {
text = toInsert + text.mid(m.capturedLength());
} else {
text = toInsert + text;
}
_field.setText(text);
if (toInsert.at(0) != '@') {
QString text = _field.getLastText();
QRegularExpressionMatch m = QRegularExpression(qsl("^/[A-Za-z_0-9]{0,64}(@[A-Za-z_0-9]{0,32})?(\\s|$)")).match(text);
if (m.hasMatch()) {
text = toInsert + text.mid(m.capturedLength());
} else {
text = toInsert + text;
}
_field.setTextFast(text);
QTextCursor cur(_field.textCursor());
cur.movePosition(QTextCursor::End);
_field.setTextCursor(cur);
QTextCursor cur(_field.textCursor());
cur.movePosition(QTextCursor::End);
_field.setTextCursor(cur);
} else {
_field.setTextFast(toInsert, true);
}
}
bool HistoryWidget::eventFilter(QObject *obj, QEvent *e) {
@ -4951,23 +4954,21 @@ bool HistoryWidget::hasBroadcastToggle() const {
}
void HistoryWidget::inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result) {
_inlineBot = 0;
_inlineBotUsername = QString();
if (result.type() == mtpc_contacts_resolvedPeer) {
const MTPDcontacts_resolvedPeer &d(result.c_contacts_resolvedPeer());
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
PeerId peerId = peerFromMTP(d.vpeer);
if (peerId && peerIsUser(peerId)) {
_inlineBot = App::user(peerId);
}
}
onCheckMentionDropdown();
}
bool HistoryWidget::inlineBotResolveFail(const RPCError &error) {
bool HistoryWidget::inlineBotResolveFail(QString name, const RPCError &error) {
if (mtpIsFlood(error)) return false;
_inlineBot = 0;
onCheckMentionDropdown();
if (name == _inlineBotUsername) {
_inlineBot = 0;
onCheckMentionDropdown();
}
return true;
}
@ -5299,7 +5300,7 @@ void HistoryWidget::onFieldResize() {
_cmdStart.move(_attachEmoji.x() - _cmdStart.width(), height() - kbh - _cmdStart.height());
_attachType.move(0, _attachDocument.y() - _attachType.height());
_emojiPan.move(width() - _emojiPan.width(), _attachEmoji.y() - _emojiPan.height());
_emojiPan.moveBottom(_attachEmoji.y());
updateListSize();
updateField();
@ -5312,6 +5313,7 @@ void HistoryWidget::onFieldFocused() {
void HistoryWidget::onCheckMentionDropdown() {
if (!_history || _a_show.animating()) return;
UserData *bot = _inlineBot;
QString start, inlineBotUsername(_inlineBotUsername);
_field.getMentionHashtagBotCommandStart(start, _inlineBot, _inlineBotUsername);
if (inlineBotUsername != _inlineBotUsername) {
@ -5320,8 +5322,7 @@ void HistoryWidget::onCheckMentionDropdown() {
_inlineBotResolveRequestId = 0;
}
if (_inlineBot == InlineBotLookingUpData) {
LOG(("Inline bot unknown! resolving @%1").arg(_inlineBotUsername));
_inlineBotResolveRequestId = MTP::send(MTPcontacts_ResolveUsername(MTP_string(_inlineBotUsername)), rpcDone(&HistoryWidget::inlineBotResolveDone), rpcFail(&HistoryWidget::inlineBotResolveFail));
_inlineBotResolveRequestId = MTP::send(MTPcontacts_ResolveUsername(MTP_string(_inlineBotUsername)), rpcDone(&HistoryWidget::inlineBotResolveDone), rpcFail(&HistoryWidget::inlineBotResolveFail, _inlineBotUsername));
return;
}
} else if (_inlineBot == InlineBotLookingUpData) {
@ -5329,12 +5330,19 @@ void HistoryWidget::onCheckMentionDropdown() {
}
if (_inlineBot) {
if (_inlineBot != bot) {
updateFieldPlaceholder();
}
_emojiPan.queryInlineBot(_inlineBot, start);
if (!_attachMention.isHidden()) {
_attachMention.hideStart();
}
} else {
_emojiPan.inlineBotChanged();
if (_inlineBot != bot) {
updateFieldPlaceholder();
_field.finishPlaceholder();
}
_emojiPan.clearInlineBot();
if (!start.isEmpty()) {
if (start.at(0) == '#' && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) Local::readRecentHashtags();
if (start.at(0) == '@' && _peer->isUser()) return;
@ -5348,6 +5356,16 @@ void HistoryWidget::onCheckMentionDropdown() {
}
}
void HistoryWidget::updateFieldPlaceholder() {
if (_inlineBot && _inlineBot != InlineBotLookingUpData) {
_field.setPlaceholder(_inlineBot->botInfo->inlinePlaceholder.mid(1), _inlineBot->username.size() + 2);
} else if (hasBroadcastToggle()) {
_field.setPlaceholder(lang(_broadcast.checked() ? lng_broadcast_ph : lng_comment_ph));
} else {
_field.setPlaceholder(lang((_history && _history->isChannel() && !_history->isMegagroup()) ? (_peer->asChannel()->canPublish() ? lng_broadcast_ph : lng_comment_ph) : lng_message_ph));
}
}
void HistoryWidget::uploadImage(const QImage &img, PrepareMediaType type, FileLoadForceConfirmType confirm, const QString &source, bool withText) {
if (!_history) return;
@ -5790,6 +5808,10 @@ void HistoryWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
}
}
void HistoryWidget::notify_automaticLoadSettingsChangedGif() {
_emojiPan.notify_automaticLoadSettingsChangedGif();
}
void HistoryWidget::resizeEvent(QResizeEvent *e) {
_reportSpamPanel.resize(width(), _reportSpamPanel.height());
@ -5828,7 +5850,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
_attachType.move(0, _attachDocument.y() - _attachType.height());
_emojiPan.setMaxHeight(height() - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom() - _attachEmoji.height());
_emojiPan.move(width() - _emojiPan.width(), _attachEmoji.y() - _emojiPan.height());
_emojiPan.moveBottom(_attachEmoji.y());
switch (_attachDrag) {
case DragStateFiles:
@ -6341,18 +6363,21 @@ void HistoryWidget::onInlineResultSend(InlineResult *result, UserData *bot) {
} else if (result->type == qstr("photo")) {
QImage fileThumb(result->thumb->pix().toImage());
PreparedPhotoThumbs photoThumbs;
QVector<MTPPhotoSize> photoSizes;
QPixmap thumb = (fileThumb.width() > 100 || fileThumb.height() > 100) ? QPixmap::fromImage(fileThumb.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fileThumb);
photoThumbs.insert('s', thumb);
ImagePtr thumbPtr = ImagePtr(thumb, "JPG");
photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));
QPixmap medium = (fileThumb.width() > 320 || fileThumb.height() > 320) ? QPixmap::fromImage(fileThumb.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fileThumb);
photoThumbs.insert('m', medium);
QSize medium = resizeKeepAspect(result->width, result->height, 320, 320);
photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));
MTPPhoto photo = MTP_photo(MTP_long(MTP::nonce<uint64>()), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes));
photoSizes.push_back(MTP_photoSize(MTP_string("x"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(result->width), MTP_int(result->height), MTP_int(0)));
uint64 photoId = MTP::nonce<uint64>();
PhotoData *ph = App::photoSet(photoId, 0, 0, unixtime(), thumbPtr, ImagePtr(medium.width(), medium.height()), ImagePtr(result->width, result->height));
MTPPhoto photo = MTP_photo(MTP_long(photoId), MTP_long(0), MTP_int(ph->date), MTP_vector<MTPPhotoSize>(photoSizes));
_history->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(_history->peer->id), MTPPeer(), MTPint(), MTP_int(bot ? peerToUser(bot->id) : 0), MTP_int(replyToId()), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(photo, MTP_string(result->caption)), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
}
} else {

View File

@ -98,7 +98,7 @@ public:
void notifyMigrateUpdated();
~HistoryInner();
public slots:
void onUpdateSelected();
@ -186,7 +186,7 @@ private:
bool _touchScroll, _touchSelect, _touchInProgress;
QPoint _touchStart, _touchPrevPos, _touchPos;
QTimer _touchSelectTimer;
TouchScrollState _touchScrollState;
bool _touchPrevPosValid, _touchWaitingAcceleration;
QPoint _touchSpeed;
@ -445,6 +445,8 @@ public:
void destroyData();
void updateFieldPlaceholder();
void uploadImage(const QImage &img, PrepareMediaType type, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, const QString &source = QString(), bool withText = false);
void uploadFile(const QString &file, PrepareMediaType type, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, bool withText = false); // with confirmation
void uploadFiles(const QStringList &files, PrepareMediaType type);
@ -484,7 +486,7 @@ public:
void noSelectingScroll();
bool touchScroll(const QPoint &delta);
uint64 animActiveTimeStart(const HistoryItem *msg) const;
void stopAnimActive();
@ -564,6 +566,7 @@ public:
bool ui_isInlineItemBeingChosen();
void notify_historyItemLayoutChanged(const HistoryItem *item);
void notify_automaticLoadSettingsChangedGif();
void notify_botCommandsChanged(UserData *user);
void notify_userIsBotChanged(UserData *user);
void notify_migrateUpdated(PeerData *peer);
@ -769,7 +772,7 @@ private:
QString _inlineBotUsername;
mtpRequestId _inlineBotResolveRequestId;
void inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result);
bool inlineBotResolveFail(const RPCError &error);
bool inlineBotResolveFail(QString name, const RPCError &error);
bool isBotStart() const;
bool isBlocked() const;

View File

@ -504,7 +504,7 @@ void LayoutOverviewVideo::paint(Painter &p, const QRect &clip, uint32 selection,
void LayoutOverviewVideo::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const {
bool loaded = _data->loaded();
if (hasPoint(x, y)) {
link = loaded ? _openl : (_data->loading() ? _cancell : _savel);
}
@ -1275,7 +1275,7 @@ void LayoutOverviewLink::getState(TextLinkPtr &link, HistoryCursorState &cursor,
}
}
LayoutOverviewLink::Link::Link(const QString &url, const QString &text)
LayoutOverviewLink::Link::Link(const QString &url, const QString &text)
: text(text)
, width(st::normalFont->width(text))
, lnk(linkFromUrl(url)) {
@ -1371,7 +1371,7 @@ void DeleteSavedGifLink::onClick(Qt::MouseButton button) const {
}
void LayoutInlineGif::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
// content_automaticLoad();
content_automaticLoad();
bool loaded = content_loaded(), loading = content_loading(), displayLoading = content_displayLoading();
if (loaded && !gif() && _gif != BadClipReader) {
@ -1832,23 +1832,20 @@ void LayoutInlineWebVideo::initDimensions() {
}
void LayoutInlineWebVideo::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
int32 left = 0;
if (!_result->thumb->isNull()) {
left = st::inlineThumbSize + st::inlineThumbSkip;
prepareThumb(st::inlineThumbSize, st::inlineThumbSize);
if (_thumb.isNull()) {
p.fillRect(rtlrect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize, _width), _result->thumb->isNull() ? st::black : st::overviewPhotoBg);
} else {
p.drawPixmapLeft(0, st::inlineRowMargin, _width, _thumb);
}
int32 left = st::inlineThumbSize + st::inlineThumbSkip;
prepareThumb(st::inlineThumbSize, st::inlineThumbSize);
if (_thumb.isNull()) {
p.fillRect(rtlrect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize, _width), _result->thumb->isNull() ? st::black : st::overviewPhotoBg);
} else {
p.drawPixmapLeft(0, st::inlineRowMargin, _width, _thumb);
}
if (!_duration.isEmpty()) {
int32 durationTop = st::inlineRowMargin + st::inlineThumbSize - st::normalFont->height - st::inlineDurationMargin;
p.fillRect(rtlrect(0, durationTop - st::inlineDurationMargin, st::inlineThumbSize, st::normalFont->height + 2 * st::inlineDurationMargin, _width), st::msgDateImgBg);
p.setPen(st::white);
p.setFont(st::normalFont);
p.drawTextRight(_width - st::inlineThumbSize + st::inlineDurationMargin, durationTop, _width, _duration);
}
if (!_duration.isEmpty()) {
int32 durationTop = st::inlineRowMargin + st::inlineThumbSize - st::normalFont->height - st::inlineDurationMargin;
p.fillRect(rtlrect(0, durationTop - st::inlineDurationMargin, st::inlineThumbSize, st::normalFont->height + 2 * st::inlineDurationMargin, _width), st::msgDateImgBg);
p.setPen(st::white);
p.setFont(st::normalFont);
p.drawTextRight(_width - st::inlineThumbSize + st::inlineDurationMargin, durationTop, _width, _duration);
}
p.setPen(st::black);
@ -1951,7 +1948,7 @@ int32 LayoutInlineArticle::resizeGetHeight(int32 width) {
}
void LayoutInlineArticle::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
int32 left = 0;
int32 left = st::emojiPanHeaderLeft - st::inlineResultsLeft;
if (_withThumb) {
left = st::inlineThumbSize + st::inlineThumbSkip;
prepareThumb(st::inlineThumbSize, st::inlineThumbSize);

View File

@ -367,7 +367,7 @@ namespace {
bool fileExists(const FileKey &fkey, int options = UserPath | SafePath) {
return fileExists(toFilePart(fkey), options);
}
bool readFile(FileReadDescriptor &result, const QString &name, int options = UserPath | SafePath) {
if (options & UserPath) {
if (!_userWorking()) return false;
@ -561,6 +561,8 @@ namespace {
typedef QMap<PeerId, bool> DraftsNotReadMap;
DraftsNotReadMap _draftsNotReadMap;
typedef QPair<FileKey, qint32> FileDesc; // file, size
typedef QMultiMap<MediaKey, FileLocation> FileLocations;
FileLocations _fileLocations;
typedef QPair<MediaKey, FileLocation> FileLocationPair;
@ -568,10 +570,13 @@ namespace {
FileLocationPairs _fileLocationPairs;
typedef QMap<MediaKey, MediaKey> FileLocationAliases;
FileLocationAliases _fileLocationAliases;
typedef QMap<QString, FileDesc> WebFilesMap;
WebFilesMap _webFilesMap;
uint64 _storageWebFilesSize = 0;
FileKey _locationsKey = 0, _reportSpamStatusesKey = 0;
FileKey _recentStickersKeyOld = 0, _stickersKey = 0, _savedGifsKey = 0;
FileKey _backgroundKey = 0;
bool _backgroundWasRead = false;
@ -581,7 +586,6 @@ namespace {
FileKey _savedPeersKey = 0;
typedef QPair<FileKey, qint32> FileDesc; // file, size
typedef QMap<StorageKey, FileDesc> StorageMap;
StorageMap _imagesMap, _stickerImagesMap, _audiosMap;
int32 _storageImagesSize = 0, _storageStickersSize = 0, _storageAudiosSize = 0;
@ -643,6 +647,12 @@ namespace {
size += sizeof(quint64) * 2 + sizeof(quint64) * 2;
}
size += sizeof(quint32); // web files count
for (WebFilesMap::const_iterator i = _webFilesMap.cbegin(), e = _webFilesMap.cend(); i != e; ++i) {
// url + filekey + size
size += _stringSize(i.key()) + sizeof(quint64) + sizeof(qint32);
}
EncryptedDescriptor data(size);
for (FileLocations::const_iterator i = _fileLocations.cbegin(); i != _fileLocations.cend(); ++i) {
data.stream << quint64(i.key().first) << quint64(i.key().second) << quint32(i.value().type) << i.value().name();
@ -663,6 +673,11 @@ namespace {
data.stream << quint64(i.key().first) << quint64(i.key().second) << quint64(i.value().first) << quint64(i.value().second);
}
data.stream << quint32(_webFilesMap.size());
for (WebFilesMap::const_iterator i = _webFilesMap.cbegin(), e = _webFilesMap.cend(); i != e; ++i) {
data.stream << i.key() << quint64(i.value().first) << qint32(i.value().second);
}
FileWriteDescriptor file(_locationsKey);
file.writeEncrypted(data);
}
@ -710,6 +725,20 @@ namespace {
locations.stream >> kfirst >> ksecond >> vfirst >> vsecond;
_fileLocationAliases.insert(MediaKey(kfirst, ksecond), MediaKey(vfirst, vsecond));
}
_storageWebFilesSize = 0;
_webFilesMap.clear();
quint32 webLocationsCount;
locations.stream >> webLocationsCount;
for (quint32 i = 0; i < webLocationsCount; ++i) {
QString url;
quint64 key;
qint32 size;
locations.stream >> url >> key >> size;
_webFilesMap.insert(url, FileDesc(key, size));
_storageWebFilesSize += size;
}
}
}
@ -2114,7 +2143,7 @@ namespace Local {
data.stream << quint32(dbiDcOption) << quint32(i.key());
data.stream << quint32(i->flags) << QString::fromUtf8(i->ip.data(), i->ip.size());
data.stream << quint32(i->port);
}
}
data.stream << quint32(dbiLangFile) << cLangFile();
data.stream << quint32(dbiConnectionType) << qint32(cConnectionType());
@ -2154,6 +2183,8 @@ namespace Local {
_stickerImagesMap.clear();
_audiosMap.clear();
_storageImagesSize = _storageStickersSize = _storageAudiosSize = 0;
_webFilesMap.clear();
_storageWebFilesSize = 0;
_locationsKey = _reportSpamStatusesKey = 0;
_recentStickersKeyOld = _stickersKey = _savedGifsKey = 0;
_backgroundKey = _userSettingsKey = _recentHashtagsKey = _savedPeersKey = 0;
@ -2437,9 +2468,10 @@ namespace Local {
quint32 imageType;
readFromStream(image.stream, locFirst, locSecond, imageType, imageData);
if (locFirst != _location.first || locSecond != _location.second) {
return;
}
// we're saving files now before we have actual location
//if (locFirst != _location.first || locSecond != _location.second) {
// return;
//}
_result = new Result(StorageFileType(imageType), imageData, _readImageFlag);
}
@ -2652,6 +2684,110 @@ namespace Local {
return _storageAudiosSize;
}
qint32 _storageWebFileSize(const QString &url, qint32 rawlen) {
// fulllen + url + len + data
qint32 result = sizeof(uint32) + _stringSize(url) + sizeof(quint32) + rawlen;
if (result & 0x0F) result += 0x10 - (result & 0x0F);
result += tdfMagicLen + sizeof(qint32) + sizeof(quint32) + 0x10 + 0x10; // magic + version + len of encrypted + part of sha1 + md5
return result;
}
void writeWebFile(const QString &url, const QByteArray &content, bool overwrite) {
if (!_working()) return;
qint32 size = _storageWebFileSize(url, content.size());
WebFilesMap::const_iterator i = _webFilesMap.constFind(url);
if (i == _webFilesMap.cend()) {
i = _webFilesMap.insert(url, FileDesc(genKey(UserPath), size));
_storageWebFilesSize += size;
_writeLocations();
} else if (!overwrite) {
return;
}
EncryptedDescriptor data(_stringSize(url) + sizeof(quint32) + sizeof(quint32) + content.size());
data.stream << url << content;
FileWriteDescriptor file(i.value().first, UserPath);
file.writeEncrypted(data);
if (i.value().second != size) {
_storageWebFilesSize += size;
_storageWebFilesSize -= i.value().second;
_webFilesMap[url].second = size;
}
}
class WebFileLoadTask : public Task {
public:
WebFileLoadTask(const FileKey &key, const QString &url, webFileLoader *loader)
: _key(key)
, _url(url)
, _loader(loader)
, _result(0) {
}
void process() {
FileReadDescriptor image;
if (!readEncryptedFile(image, _key, UserPath)) {
return;
}
QByteArray imageData;
QString url;
image.stream >> url >> imageData;
_result = new Result(StorageFilePartial, imageData);
}
void finish() {
if (_result) {
_loader->localLoaded(_result->image, _result->format, _result->pixmap);
} else {
WebFilesMap::iterator j = _webFilesMap.find(_url);
if (j != _webFilesMap.cend() && j->first == _key) {
clearKey(j.value().first, UserPath);
_storageWebFilesSize -= j.value().second;
_webFilesMap.erase(j);
}
_loader->localLoaded(StorageImageSaved());
}
}
virtual ~WebFileLoadTask() {
deleteAndMark(_result);
}
protected:
FileKey _key;
QString _url;
struct Result {
Result(StorageFileType type, const QByteArray &data) : image(type, data) {
QByteArray guessFormat;
pixmap = QPixmap::fromImage(App::readImage(data, &guessFormat, false), Qt::ColorOnly);
if (!pixmap.isNull()) {
format = guessFormat;
}
}
StorageImageSaved image;
QByteArray format;
QPixmap pixmap;
};
webFileLoader *_loader;
Result *_result;
};
TaskId startWebFileLoad(const QString &url, webFileLoader *loader) {
WebFilesMap::const_iterator j = _webFilesMap.constFind(url);
if (j == _webFilesMap.cend() || !_localLoader) {
return 0;
}
return _localLoader->addTask(new WebFileLoadTask(j->first, url, loader));
}
int32 hasWebFiles() {
return _webFilesMap.size();
}
qint64 storageWebFilesSize() {
return _storageWebFilesSize;
}
void cancelTask(TaskId id) {
if (_localLoader) {
_localLoader->cancelTask(id);
@ -3003,7 +3139,7 @@ namespace Local {
data.stream << quint32(saved.size());
for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) {
DocumentData *doc = *i;
data.stream << quint64(doc->id) << quint64(doc->access) << qint32(doc->date) << doc->name << doc->mime << qint32(doc->dc) << qint32(doc->size) << qint32(doc->dimensions.width()) << qint32(doc->dimensions.height()) << qint32(doc->type) << qint32(doc->duration());
_writeStorageImageLocation(data.stream, doc->thumb->location());
}
@ -3056,7 +3192,7 @@ namespace Local {
DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, thumb.isNull() ? ImagePtr() : ImagePtr(thumb), dc, size, thumb);
if (!doc->isAnimation()) continue;
saved.push_back(doc);
}
}
@ -3185,7 +3321,7 @@ namespace Local {
QString tag;
quint16 count;
RecentHashtagPack write, search;
if (writeCount) {
write.reserve(writeCount);
@ -3416,7 +3552,7 @@ namespace Local {
QDateTime t;
saved.stream >> t;
cRefSavedPeers().insert(peer, t);
cRefSavedPeersByTime().insert(t, peer);
peers.push_back(peer);

View File

@ -65,7 +65,7 @@ namespace Local {
bool checkPasscode(const QByteArray &passcode);
void setPasscode(const QByteArray &passcode);
enum ClearManagerTask {
ClearManagerAll = 0xFFFF,
ClearManagerDownloads = 0x01,
@ -139,6 +139,11 @@ namespace Local {
int32 hasAudios();
qint64 storageAudiosSize();
void writeWebFile(const QString &url, const QByteArray &data, bool overwrite = true);
TaskId startWebFileLoad(const QString &url, webFileLoader *loader);
int32 hasWebFiles();
qint64 storageWebFilesSize();
void cancelTask(TaskId id);
void writeStickers();

View File

@ -601,7 +601,7 @@ void MainWidget::cancelForwarding() {
void MainWidget::finishForwarding(History *hist, bool broadcast) {
if (!hist) return;
bool fromChannelName = hist->peer->isChannel() && !hist->peer->isMegagroup() && hist->peer->asChannel()->canPublish() && (hist->peer->asChannel()->isBroadcast() || broadcast);
if (!_toForward.isEmpty()) {
bool genClientSideMessage = (_toForward.size() < 2);
@ -815,6 +815,10 @@ void MainWidget::notify_historyItemLayoutChanged(const HistoryItem *item) {
if (overview) overview->notify_historyItemLayoutChanged(item);
}
void MainWidget::notify_automaticLoadSettingsChangedGif() {
history.notify_automaticLoadSettingsChangedGif();
}
void MainWidget::notify_historyItemResized(const HistoryItem *item, bool scrollToIt) {
if (!item || ((history.peer() == item->history()->peer || (history.peer() && history.peer() == item->history()->peer->migrateTo())) && !item->detached())) {
history.notify_historyItemResized(item, scrollToIt);
@ -1355,7 +1359,7 @@ void MainWidget::saveRecentHashtags(const QString &text) {
void MainWidget::readServerHistory(History *hist, bool force) {
if (!hist || (!force && !hist->unreadCount)) return;
MsgId upTo = hist->inboxRead(0);
if (hist->isChannel() && !hist->peer->asChannel()->amIn()) {
return; // no read request for channels that I didn't koin
@ -2988,7 +2992,7 @@ void MainWidget::updSetState(int32 pts, int32 date, int32 qts, int32 seq) {
void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff) {
_channelFailDifferenceTimeout.remove(channel);
int32 timeout = 0;
bool isFinal = true;
switch (diff.type()) {
@ -3041,7 +3045,7 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
App::feedUsers(d.vusers);
App::feedChats(d.vchats, false);
_handlingChannelDifference = true;
feedMessageIds(d.vother_updates);
@ -3194,7 +3198,7 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
noUpdatesTimer.start(NoUpdatesTimeout);
_ptsWaiter.setRequesting(false);
App::emitPeerUpdated();
} break;
case mtpc_updates_differenceSlice: {
@ -3995,7 +3999,7 @@ void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
if (end <= from || !MTP::authedId()) return;
App::wnd()->checkAutoLock();
if (mtpTypeId(*from) == mtpc_new_session_created) {
MTPNewSession newSession(from, end);
updSeq = 0;
@ -4135,7 +4139,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
}
}
}
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, updates)) {
return;
}

View File

@ -94,7 +94,7 @@ private:
bool _canDelete;
QString _selStr;
int32 _selStrLeft, _selStrWidth;
bool _animating;
FlatButton _clearSelection;
@ -317,10 +317,10 @@ public:
DialogsIndexed &contactsList();
DialogsIndexed &dialogsList();
void sendMessage(History *hist, const QString &text, MsgId replyTo, bool broadcast, WebPageId webPageId = 0);
void saveRecentHashtags(const QString &text);
void readServerHistory(History *history, bool force = true);
uint64 animActiveTimeStart(const HistoryItem *msg) const;
@ -364,7 +364,7 @@ public:
void updateBotKeyboard(History *h);
void pushReplyReturn(HistoryItem *item);
bool hasForwardingItems();
void fillForwardingInfo(Text *&from, Text *&text, bool &serviceColor, ImagePtr &preview);
void updateForwardingTexts();
@ -422,6 +422,7 @@ public:
void notify_clipStopperHidden(ClipStopperType type);
void notify_historyItemResized(const HistoryItem *row, bool scrollToIt);
void notify_historyItemLayoutChanged(const HistoryItem *item);
void notify_automaticLoadSettingsChangedGif();
~MainWidget();
@ -615,7 +616,7 @@ private:
QSet<PeerData*> updateNotifySettingPeers;
SingleTimer updateNotifySettingTimer;
typedef QMap<PeerData*, QPair<mtpRequestId, MsgId> > ReadRequests;
ReadRequests _readRequests;
typedef QMap<PeerData*, MsgId> ReadRequestsPending;

View File

@ -628,7 +628,7 @@ void webFileLoader::onFinished(const QByteArray &data) {
emit App::wnd()->imageLoaded();
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
//Local::writeWebFile(_url, StorageImageSaved(mtpToStorageType(_type), _data));
Local::writeWebFile(_url, _data);
}
emit progress(this);
loadNext();
@ -646,7 +646,7 @@ bool webFileLoader::tryLoadLocal() {
return true;
}
_localTaskId = 0;// Local::startWebFileLoad(_url, this);
_localTaskId = Local::startWebFileLoad(_url, this);
if (_localStatus != LocalNotTried) {
return _complete;
} else if (_localTaskId) {

View File

@ -279,7 +279,7 @@ protected:
uint64 _id; // for other locations
uint64 _access;
};
class webFileLoaderPrivate;

View File

@ -283,7 +283,7 @@ void UserData::setBotInfo(const MTPBotInfo &info) {
case mtpc_botInfo: {
const MTPDbotInfo &d(info.c_botInfo());
if (peerFromUser(d.vuser_id.v) != id) return;
if (botInfo) {
botInfo->version = d.vversion.v;
} else {
@ -296,7 +296,7 @@ void UserData::setBotInfo(const MTPBotInfo &info) {
botInfo->text = Text(st::msgMinWidth);
}
botInfo->shareText = qs(d.vshare_text);
const QVector<MTPBotCommand> &v(d.vcommands.c_vector().v);
botInfo->commands.reserve(v.size());
bool changedCommands = false;
@ -681,7 +681,7 @@ void PhotoSaveLink::onClick(Qt::MouseButton button) const {
void PhotoCancelLink::onClick(Qt::MouseButton button) const {
if (button != Qt::LeftButton) return;
PhotoData *data = photo();
if (!data->date) return;
@ -2050,6 +2050,11 @@ void InlineResult::automaticLoadGif() {
}
}
void InlineResult::automaticLoadSettingsChangedGif() {
if (loaded() || _loader != CancelledWebFileLoader) return;
_loader = 0;
}
void InlineResult::saveFile(const QString &toFile, LoadFromCloudSetting fromCloud, bool autoLoading) {
if (loaded()) {
return;

View File

@ -1273,7 +1273,7 @@ inline WebPageType toWebPageType(const QString &type) {
struct WebPageData {
WebPageData(const WebPageId &id, WebPageType type = WebPageArticle, const QString &url = QString(), const QString &displayUrl = QString(), const QString &siteName = QString(), const QString &title = QString(), const QString &description = QString(), PhotoData *photo = 0, DocumentData *doc = 0, int32 duration = 0, const QString &author = QString(), int32 pendingTill = -1);
void forget() {
if (photo) photo->forget();
}
@ -1365,6 +1365,7 @@ public:
ImagePtr thumb;
void automaticLoadGif();
void automaticLoadSettingsChangedGif();
void saveFile(const QString &toFile, LoadFromCloudSetting fromCloud, bool autoLoading);
void cancelFile();