diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index 70f558db5b..96e8c37337 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -581,6 +581,11 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org "lng_stickers_not_found" = "Sticker pack not found."; "lng_stickers_copied" = "Sticker pack link copied to clipboard."; "lng_stickers_default_set" = "Great Minds"; +"lng_stickers_you_have" = "Manage and reorder sticker packs"; +"lng_stickers_packs" = "Sticker Packs"; +"lng_stickers_remove" = "Remove"; +"lng_stickers_return" = "Return"; +"lng_stickers_count" = "{count:Loading..|# sticker|# stickers}"; "lng_in_dlg_photo" = "Photo"; "lng_in_dlg_video" = "Video"; @@ -658,6 +663,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org "lng_duration_and_size" = "{duration}, {size}"; "lng_choose_images" = "Choose images"; +"lng_context_view_profile" = "View profile"; +"lng_context_view_group" = "View group info"; +"lng_context_view_channel" = "View channel info"; + "lng_context_open_link" = "Open Link"; "lng_context_copy_link" = "Copy Link"; "lng_context_open_email" = "Write to this address"; diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index f8ce9b4e53..8113088989 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -323,7 +323,7 @@ titleBG: #6389a8; titleColor: #0f8dcc;//rgb(20, 136, 210); titleHeight: 39px; titleIconPos: point(7px, 7px); -titleIconImg: sprite(160px, 100px, 26px, 26px); +titleIconImg: sprite(161px, 100px, 26px, 26px); titleFont: font(17px); titlePos: point(44px, 29px); titleMenuOffset: 36px; @@ -1794,6 +1794,8 @@ stickersScroll: flatScroll(boxScroll) { deltat: 23px; deltab: 9px; } +stickersRowDisabledOpacity: 0.4; +stickersRowDuration: 200; emojiScroll: flatScroll(solidScroll) { deltat: 48px; @@ -1814,6 +1816,7 @@ emojiObjectsOver: sprite(147px, 196px, 21px, 22px); emojiObjectsActive: sprite(308px, 264px, 21px, 22px); emojiSymbolsOver: sprite(84px, 196px, 21px, 22px); emojiSymbolsActive: sprite(287px, 286px, 21px, 22px); +stickersSettings: sprite(140px, 124px, 21px, 22px); emojiPanCategories: #f7f7f7; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 4461772be1..3e002ab8e6 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -726,29 +726,19 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) it->access = s.vaccess_hash.v; it->hash = s.vhash.v; it->shortName = qs(s.vshort_name); - QString title = qs(s.vtitle); - if ((it->flags & MTPDstickerSet::flag_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) { - title = lang(lng_stickers_default_set); - } - it->title = title; + it->title = stickerSetTitle(s); it->flags = s.vflags.v; const QVector &d_docs(d.vdocuments.c_vector().v); StickerSets::iterator custom = sets.find(CustomStickerSetId); - QSet found; - int32 wasCount = -1; + StickerPack pack; + pack.reserve(d_docs.size()); for (int32 i = 0, l = d_docs.size(); i != l; ++i) { DocumentData *doc = App::feedDocument(d_docs.at(i)); if (!doc || !doc->sticker()) continue; - if (wasCount < 0) wasCount = it->stickers.size(); - if (it->stickers.indexOf(doc) < 0) { - it->stickers.push_back(doc); - } else { - found.insert(doc); - } - + pack.push_back(doc); if (custom != sets.cend()) { int32 index = custom->stickers.indexOf(doc); if (index >= 0) { @@ -763,39 +753,19 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) bool writeRecent = false; RecentStickerPack &recent(cGetRecentStickers()); - - if (wasCount < 0) { // no stickers received - for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { - if (it->stickers.indexOf(i->first) >= 0) { - i = recent.erase(i); - writeRecent = true; - } else { - ++i; - } + for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { + if (it->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) { + i = recent.erase(i); + writeRecent = true; + } else { + ++i; } + } + if (pack.isEmpty()) { cRefStickerSetsOrder().removeOne(setId); sets.erase(it); } else { - for (int32 j = 0, l = wasCount; j < l;) { - if (found.contains(it->stickers.at(j))) { - ++j; - } else { - for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { - if (it->stickers.at(j) == i->first) { - i = recent.erase(i); - writeRecent = true; - } else { - ++i; - } - } - it->stickers.removeAt(j); - --l; - } - } - if (it->stickers.isEmpty()) { - cRefStickerSetsOrder().removeOne(setId); - sets.erase(it); - } + it->stickers = pack; } if (writeRecent) { diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index d9c79c5c39..c478c0ff63 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -1985,7 +1985,7 @@ namespace App { webPagesData.clear(); if (api()) api()->clearWebPageRequests(); cSetRecentStickers(RecentStickerPack()); - cSetStickersHash(QByteArray()); + cSetStickersHash(0); cSetStickerSets(StickerSets()); cSetStickerSetsOrder(StickerSetsOrder()); cSetLastStickersUpdate(0); diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index dd6c07c7f7..506eca63f7 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -323,3 +323,24 @@ namespace Notify { void migrateUpdated(PeerData *peer); }; + +inline int32 stickersCountHash(bool checkOfficial = false) { + uint32 acc = 0; + bool foundOfficial = false, foundBad = false;; + const StickerSets &sets(cStickerSets()); + const StickerSetsOrder &order(cStickerSetsOrder()); + for (StickerSetsOrder::const_iterator i = order.cbegin(), e = order.cend(); i != e; ++i) { + StickerSets::const_iterator j = sets.constFind(*i); + if (j != sets.cend()) { + if (j->id == 0) { + foundBad = true; + } else if (j->flags & MTPDstickerSet::flag_official) { + foundOfficial = true; + } + if (!(j->flags & MTPDstickerSet::flag_disabled)) { + acc = (acc * 20261) + j->hash; + } + } + } + return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0; +} diff --git a/Telegram/SourceFiles/art/sprite.png b/Telegram/SourceFiles/art/sprite.png index 076589d1e2..29c40d4520 100644 Binary files a/Telegram/SourceFiles/art/sprite.png and b/Telegram/SourceFiles/art/sprite.png differ diff --git a/Telegram/SourceFiles/art/sprite_200x.png b/Telegram/SourceFiles/art/sprite_200x.png index a62038a7ef..54a166f610 100644 Binary files a/Telegram/SourceFiles/art/sprite_200x.png and b/Telegram/SourceFiles/art/sprite_200x.png differ diff --git a/Telegram/SourceFiles/boxes/stickersetbox.cpp b/Telegram/SourceFiles/boxes/stickersetbox.cpp index a0ab14ccd8..64908c66e6 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.cpp +++ b/Telegram/SourceFiles/boxes/stickersetbox.cpp @@ -38,7 +38,6 @@ _input(set), _installRequest(0) { case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break; } MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&StickerSetInner::gotSet), rpcFail(&StickerSetInner::failedSet)); - cSetLastStickersUpdate(0); App::main()->updateStickers(); } @@ -56,7 +55,7 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) { } if (d.vset.type() == mtpc_stickerSet) { const MTPDstickerSet &s(d.vset.c_stickerSet()); - _setTitle = qs(s.vtitle); + _setTitle = stickerSetTitle(s); _title = st::boxTitleFont->elided(_setTitle, width() - st::boxTitlePosition.x() - st::boxTitleHeight); _setShortName = qs(s.vshort_name); _setId = s.vid.v; @@ -91,23 +90,14 @@ bool StickerSetInner::failedSet(const RPCError &error) { void StickerSetInner::installDone(const MTPBool &result) { StickerSets &sets(cRefStickerSets()); + _setFlags &= ~MTPDstickerSet::flag_disabled; sets.insert(_setId, StickerSet(_setId, _setAccess, _setTitle, _setShortName, _setCount, _setHash, _setFlags)).value().stickers = _pack; - int32 insertAtIndex = 0; StickerSetsOrder &order(cRefStickerSetsOrder()); - for (int32 s = order.size(); insertAtIndex < s; ++insertAtIndex) { - StickerSets::const_iterator i = sets.constFind(order.at(insertAtIndex)); - if (i == sets.cend() || !(i->flags & MTPDstickerSet::flag_official)) { - break; - } - } - int32 currentIndex = cStickerSetsOrder().indexOf(_setId); + int32 insertAtIndex = 0, currentIndex = order.indexOf(_setId); if (currentIndex != insertAtIndex) { if (currentIndex > 0) { order.removeAt(currentIndex); - if (currentIndex < insertAtIndex) { - --insertAtIndex; - } } order.insert(insertAtIndex, _setId); } @@ -121,7 +111,7 @@ void StickerSetInner::installDone(const MTPBool &result) { sets.erase(custom); } } - cSetStickersHash(QByteArray()); + cSetStickersHash(stickersCountHash()); Local::writeStickers(); emit installed(_setId); App::wnd()->hideLayer(); @@ -195,7 +185,10 @@ bool StickerSetInner::loaded() const { } int32 StickerSetInner::notInstalled() const { - return (_loaded && (cStickerSets().constFind(_setId) == cStickerSets().cend())) ? _pack.size() : 0; + if (!_loaded) return 0; + StickerSets::const_iterator it = cStickerSets().constFind(_setId); + if (it == cStickerSets().cend() || (it->flags & MTPDstickerSet::flag_disabled)) return _pack.size(); + return 0; } bool StickerSetInner::official() const { @@ -285,16 +278,16 @@ void StickerSetBox::showAll() { int32 cnt = _inner.notInstalled(); if (_inner.loaded()) { _shadow.show(); - if (_inner.official()) { - _add.hide(); - _share.hide(); - _cancel.hide(); - _done.show(); - } else if (_inner.notInstalled()) { + if (_inner.notInstalled()) { _add.show(); _cancel.show(); _share.hide(); _done.hide(); + } else if (_inner.official()) { + _add.hide(); + _share.hide(); + _cancel.hide(); + _done.show(); } else { _share.show(); _cancel.show(); @@ -334,3 +327,589 @@ void StickerSetBox::resizeEvent(QResizeEvent *e) { _cancel.moveToRight(st::boxButtonPadding.right() + _add.width() + st::boxButtonPadding.left(), _add.y()); } } + +StickersInner::StickersInner() : TWidget() +, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) +, _aboveShadowFadeStart(0) +, _aboveShadowFadeOpacity(0, 0) +, _a_shifting(animFunc(this, &StickersInner::animStep_shifting)) +, _saving(false) +, _removeSel(-1) +, _removeDown(-1) +, _removeWidth(st::normalFont->width(lang(lng_stickers_remove))) +, _returnWidth(st::normalFont->width(lang(lng_stickers_return))) +, _selected(-1) +, _started(-1) +, _dragging(-1) +, _above(-1) +, _aboveShadow(st::boxShadow) +, _scrollbar(0) { + connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); + setMouseTracking(true); +} + +void StickersInner::paintEvent(QPaintEvent *e) { + QRect r(e->rect()); + Painter p(this); + + p.fillRect(r, st::white); + p.setClipRect(r); + + int32 yFrom = r.y() - st::membersPadding.top(), yTo = r.y() + r.height() - st::membersPadding.top(); + p.translate(0, st::membersPadding.top()); + if (_rows.isEmpty()) { + p.setFont(st::noContactsFont->f); + p.setPen(st::noContactsColor->p); + p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center); + } else { + int32 from = floorclamp(yFrom - _rowHeight, _rowHeight, 0, _rows.size()); + int32 to = ceilclamp(yTo + _rowHeight, _rowHeight, 0, _rows.size()); + p.translate(0, from * _rowHeight); + for (int32 i = from; i < to; ++i) { + if (i != _above) { + paintRow(p, i); + } + p.translate(0, _rowHeight); + } + if (from <= _above && _above < to) { + p.translate(0, (_above - to) * _rowHeight); + paintRow(p, _above); + } + } +} + +void StickersInner::paintRow(Painter &p, int32 index) { + const StickerSetRow *s(_rows.at(index)); + + int32 xadd = s->xadd.current(), yadd = s->yadd.current(); + if (xadd || yadd) p.translate(xadd, yadd); + + bool removeSel = (index == _removeSel && (_removeDown < 0 || index == _removeDown)); + bool removeDown = removeSel && (index == _removeDown); + + p.setFont((removeSel ? st::linkOverFont : st::linkFont)->f); + if (removeDown) { + p.setPen(st::btnDefLink.downColor->p); + } else { + p.setPen(st::btnDefLink.color->p); + } + p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), lang(s->disabled ? lng_stickers_return : lng_stickers_remove), s->disabled ? _returnWidth : _removeWidth); + + if (index == _above) { + float64 current = _aboveShadowFadeOpacity.current(); + if (_started >= 0) { + float64 o = aboveShadowOpacity(); + if (o > current) { + _aboveShadowFadeOpacity = anim::fvalue(o, o); + current = o; + } + } + p.setOpacity(current); + QRect row(myrtlrect(_aboveShadow.getDimensions(st::boxShadowShift).left(), st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - _aboveShadow.getDimensions(st::boxShadowShift).right(), _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2))); + _aboveShadow.paint(p, row, st::boxShadowShift); + p.fillRect(row, st::white); + p.setOpacity(1); + } + + if (s->disabled) p.setOpacity(st::stickersRowDisabledOpacity); + if (s->sticker) { + s->sticker->thumb->load(); + QPixmap pix(s->sticker->thumb->pix(s->pixw, s->pixh)); + p.drawPixmapLeft(st::contactsPadding.left() + (st::contactsPhotoSize - s->pixw) / 2, st::contactsPadding.top() + (st::contactsPhotoSize - s->pixh) / 2, width(), pix); + } + p.setFont(st::contactsNameFont); + p.setPen(st::black); + + int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(); + p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsNameTop, width(), s->title); + + p.setFont(st::contactsStatusFont); + p.setPen(st::contactsStatusFg); + p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), lng_stickers_count(lt_count, s->count)); + + p.setOpacity(1); + if (xadd || yadd) p.translate(-xadd, -yadd); +} + +void StickersInner::mousePressEvent(QMouseEvent *e) { + if (_saving) return; + if (_dragging >= 0) mouseReleaseEvent(e); + _mouse = e->globalPos(); + onUpdateSelected(); + if (_removeSel >= 0) { + _removeDown = _removeSel; + update(0, st::membersPadding.top() + _removeSel * _rowHeight, width(), _rowHeight); + } else if (_selected >= 0) { + _above = _dragging = _started = _selected; + _dragStart = mapFromGlobal(_mouse); + } +} + +void StickersInner::mouseMoveEvent(QMouseEvent *e) { + if (_saving) return; + _mouse = e->globalPos(); + onUpdateSelected(); +} + +void StickersInner::onUpdateSelected() { + if (_saving) return; + QPoint local(mapFromGlobal(_mouse)); + if (_dragging >= 0) { + int32 shift = 0; + uint64 ms = getms(); + if (_dragStart.y() > local.y() && _dragging > 0) { + shift = -floorclamp(_dragStart.y() - local.y() + (_rowHeight / 2), _rowHeight, 0, _dragging); + for (int32 from = _dragging, to = _dragging + shift; from > to; --from) { + qSwap(_rows[from], _rows[from - 1]); + _rows.at(from)->yadd = anim::ivalue(_rows.at(from)->yadd.current() - _rowHeight, 0); + _animStartTimes[from] = ms; + } + } else if (_dragStart.y() < local.y() && _dragging + 1 < _rows.size()) { + shift = floorclamp(local.y() - _dragStart.y() + (_rowHeight / 2), _rowHeight, 0, _rows.size() - _dragging - 1); + for (int32 from = _dragging, to = _dragging + shift; from < to; ++from) { + qSwap(_rows[from], _rows[from + 1]); + _rows.at(from)->yadd = anim::ivalue(_rows.at(from)->yadd.current() + _rowHeight, 0); + _animStartTimes[from] = ms; + } + } + if (shift) { + _dragging += shift; + _above = _dragging; + _dragStart.setY(_dragStart.y() + shift * _rowHeight); + if (!_a_shifting.animating()) { + _a_shifting.start(); + } + } +// _rows.at(_dragging)->xadd = anim::ivalue(local.x() - _dragStart.x(), local.x() - _dragStart.x()); + _rows.at(_dragging)->yadd = anim::ivalue(local.y() - _dragStart.y(), local.y() - _dragStart.y()); + _animStartTimes[_dragging] = 0; + update(0, st::membersPadding.top() + _rowHeight * (_dragging + qMin(shift, 0) - 1), width(), _rowHeight * (qMax(shift, 0) - qMin(shift, 0) + 3)); + + emit checkDraggingScroll(local.y()); + } else { + bool in = rect().marginsRemoved(QMargins(0, st::membersPadding.top(), 0, st::membersPadding.bottom())).contains(local); + _selected = in ? floorclamp(local.y() - st::membersPadding.top(), _rowHeight, 0, _rows.size() - 1) : -1; + int32 removeSel = -1; + + if (_selected >= 0) { + int32 remw = _rows.at(_selected)->disabled ? _returnWidth : _removeWidth; + QRect rem(myrtlrect(width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - remw, st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, remw, st::normalFont->height)); + removeSel = rem.contains(local.x(), local.y() - st::membersPadding.top() - _selected * _rowHeight) ? _selected : -1; + } + setRemoveSel(removeSel); + emit noDraggingScroll(); + } +} + +float64 StickersInner::aboveShadowOpacity() const { + if (_above < 0) return 0; + + int32 dx = qAbs(_above * _rowHeight + _rows.at(_above)->yadd.current() - _started * _rowHeight); + int32 dy = qAbs(_rows.at(_above)->xadd.current()); + return qMin((dx + dy) * 2. / _rowHeight, 1.); +} + +void StickersInner::mouseReleaseEvent(QMouseEvent *e) { + if (_saving) return; + _mouse = e->globalPos(); + onUpdateSelected(); + if (_removeDown == _removeSel && _removeSel >= 0) { + _rows[_removeDown]->disabled = !_rows[_removeDown]->disabled; + } else if (_dragging >= 0) { + QPoint local(mapFromGlobal(_mouse)); + _rows[_dragging]->xadd.start(0); + _rows[_dragging]->yadd.start(0); + _aboveShadowFadeStart = _animStartTimes[_dragging] = getms(); + _aboveShadowFadeOpacity = anim::fvalue(aboveShadowOpacity(), 0); + if (!_a_shifting.animating()) { + _a_shifting.start(); + } + + _dragging = _started = -1; + } + if (_removeDown >= 0) { + update(0, st::membersPadding.top() + _removeDown * _rowHeight, width(), _rowHeight); + _removeDown = -1; + } +} + +bool StickersInner::animStep_shifting(float64) { + uint64 ms = getms(); + bool animating = false; + int32 updateMin = -1, updateMax = 0; + for (int32 i = 0, l = _animStartTimes.size(); i < l; ++i) { + uint64 start = _animStartTimes.at(i); + if (start) { + if (updateMin < 0) updateMin = i; + updateMax = i; + if (start + st::stickersRowDuration > ms && ms > start) { + _rows.at(i)->xadd.update((ms - start) / st::stickersRowDuration, anim::sineInOut); + _rows.at(i)->yadd.update((ms - start) / st::stickersRowDuration, anim::sineInOut); + animating = true; + } else { + _rows.at(i)->xadd.finish(); + _rows.at(i)->yadd.finish(); + _animStartTimes[i] = 0; + } + } + } + if (_aboveShadowFadeStart) { + if (updateMin < 0 || updateMin > _above) updateMin = _above; + if (updateMax < _above) updateMin = _above; + if (_aboveShadowFadeStart + st::stickersRowDuration > ms && ms > _aboveShadowFadeStart) { + _aboveShadowFadeOpacity.update((ms - _aboveShadowFadeStart) / st::stickersRowDuration, anim::sineInOut); + animating = true; + } else { + _aboveShadowFadeOpacity.finish(); + _aboveShadowFadeStart = 0; + } + } + if (updateMin >= 0) { + update(0, st::membersPadding.top() + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3)); + } + if (!animating) { + _above = _dragging; + } + return animating; +} + +void StickersInner::clear() { + for (int32 i = 0, l = _rows.size(); i < l; ++i) { + delete _rows.at(i); + } + _rows.clear(); + _animStartTimes.clear(); + _aboveShadowFadeStart = 0; + _aboveShadowFadeOpacity = anim::fvalue(0, 0); + _a_shifting.stop(); + _above = _dragging = _started = -1; + _selected = -1; + _removeDown = -1; + setRemoveSel(-1); + update(); +} + +void StickersInner::setRemoveSel(int32 removeSel) { + if (removeSel != _removeSel) { + if (_removeSel >= 0) update(0, st::membersPadding.top() + _removeSel * _rowHeight, width(), _rowHeight); + _removeSel = removeSel; + if (_removeSel >= 0) update(0, st::membersPadding.top() + _removeSel * _rowHeight, width(), _rowHeight); + setCursor((_removeSel >= 0 && (_removeDown < 0 || _removeDown == _removeSel)) ? style::cur_pointer : style::cur_default); + } +} + +void StickersInner::rebuild() { + QList rows, rowsDisabled; + + int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(); + int32 namew = st::boxWideWidth - namex - st::contactsPadding.right() - st::contactsCheckPosition.x() - qMax(_returnWidth, _removeWidth); + + clear(); + const StickerSetsOrder &order(cStickerSetsOrder()); + _animStartTimes.reserve(order.size()); + + const StickerSets &sets(cStickerSets()); + for (int32 i = 0, l = order.size(); i < l; ++i) { + StickerSets::const_iterator it = sets.constFind(order.at(i)); + if (it != sets.cend()) { + bool disabled = (it->flags & MTPDstickerSet::flag_disabled); + + DocumentData *sticker = it->stickers.isEmpty() ? 0 : it->stickers.at(0); + int32 pixw = 0, pixh = 0; + if (sticker) { + pixw = sticker->thumb->width(); + pixh = sticker->thumb->height(); + if (pixw > st::contactsPhotoSize) { + if (pixw > pixh) { + pixh = (pixh * st::contactsPhotoSize) / pixw; + pixw = st::contactsPhotoSize; + } else { + pixw = (pixw * st::contactsPhotoSize) / pixh; + pixh = st::contactsPhotoSize; + } + } else if (pixh > st::contactsPhotoSize) { + pixw = (pixw * st::contactsPhotoSize) / pixh; + pixh = st::contactsPhotoSize; + } + } + QString title = it->title; + int32 titleWidth = st::contactsNameFont->width(title); + if (titleWidth > namew) { + title = st::contactsNameFont->elided(title, namew); + } + (disabled ? rowsDisabled : rows).push_back(new StickerSetRow(it->id, sticker, it->stickers.size(), title, disabled, pixw, pixh)); + _animStartTimes.push_back(0); + if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_flag_NOT_LOADED)) { + App::api()->scheduleStickerSetRequest(it->id, it->access); + } + } + } + App::api()->requestStickerSets(); + _rows = rows + rowsDisabled; + resize(width(), st::membersPadding.top() + _rows.size() * _rowHeight + st::membersPadding.bottom()); +} + +QVector StickersInner::getOrder() const { + QVector result; + result.reserve(_rows.size()); + for (int32 i = 0, l = _rows.size(); i < l; ++i) { + if (_rows.at(i)->disabled) { + StickerSets::const_iterator it = cStickerSets().constFind(_rows.at(i)->id); + if (it == cStickerSets().cend() || !(it->flags & MTPDstickerSet::flag_official)) { + continue; + } + } + result.push_back(_rows.at(i)->id); + } + return result; +} + +QVector StickersInner::getDisabledSets() const { + QVector result; + result.reserve(_rows.size()); + for (int32 i = 0, l = _rows.size(); i < l; ++i) { + if (_rows.at(i)->disabled) { + result.push_back(_rows.at(i)->id); + } + } + return result; +} + +void StickersInner::setVisibleScrollbar(int32 width) { + _scrollbar = width; +} + +StickersInner::~StickersInner() { + clear(); +} + +StickersBox::StickersBox() : ItemListBox(st::boxScroll) +, _save(this, lang(lng_settings_save), st::defaultBoxButton) +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) +, _reorderRequest(0) +, _bottomShadow(this) { + ItemListBox::init(&_inner, st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom()); + setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight))); + + connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated())); + + connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + connect(&_save, SIGNAL(clicked()), this, SLOT(onSave())); + + connect(&_inner, SIGNAL(checkDraggingScroll(int)), this, SLOT(onCheckDraggingScroll(int))); + connect(&_inner, SIGNAL(noDraggingScroll()), this, SLOT(onNoDraggingScroll())); + connect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(onUpdateSelected())); + connect(&_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimer())); + _scrollTimer.setSingleShot(false); + + onStickersUpdated(); + + prepare(); +} + +int32 StickersBox::countHeight() const { + return st::boxTitleHeight + _inner.height() + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom(); +} + +void StickersBox::disenableDone(const MTPBool & result, mtpRequestId req) { + _disenableRequests.remove(req); + if (_disenableRequests.isEmpty()) { + saveOrder(); + } +} + +bool StickersBox::disenableFail(const RPCError &error, mtpRequestId req) { + if (mtpIsFlood(error)) return false; + _disenableRequests.remove(req); + if (_disenableRequests.isEmpty()) { + saveOrder(); + } + return true; +} + +void StickersBox::saveOrder() { + QVector order = _inner.getOrder(); + if (order.size() > 1) { + QVector mtpOrder; + mtpOrder.reserve(order.size()); + for (int32 i = 0, l = order.size(); i < l; ++i) { + mtpOrder.push_back(MTP_long(order.at(i))); + } + _reorderRequest = MTP::send(MTPmessages_ReorderStickerSets(MTP_vector(mtpOrder)), rpcDone(&StickersBox::reorderDone), rpcFail(&StickersBox::reorderFail)); + } else { + reorderDone(MTP_boolTrue()); + } +} + +void StickersBox::reorderDone(const MTPBool &result) { + _reorderRequest = 0; + onClose(); +} + +bool StickersBox::reorderFail(const RPCError &result) { + if (mtpIsFlood(result)) return false; + _reorderRequest = 0; + cSetLastStickersUpdate(0); + App::main()->updateStickers(); + onClose(); + return true; +} + +void StickersBox::paintEvent(QPaintEvent *e) { + Painter p(this); + if (paint(p)) return; + + paintTitle(p, lang(lng_stickers_packs)); + p.translate(0, st::boxTitleHeight); +} + +void StickersBox::closePressed() { + if (!_disenableRequests.isEmpty()) { + for (QMap::const_iterator i = _disenableRequests.cbegin(), e = _disenableRequests.cend(); i != e; ++i) { + MTP::cancel(i.key()); + } + _disenableRequests.clear(); + cSetLastStickersUpdate(0); + App::main()->updateStickers(); + } else if (_reorderRequest) { + MTP::cancel(_reorderRequest); + _reorderRequest = 0; + cSetLastStickersUpdate(0); + App::main()->updateStickers(); + } +} + +void StickersBox::resizeEvent(QResizeEvent *e) { + ItemListBox::resizeEvent(e); + _save.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save.height()); + _cancel.moveToRight(st::boxButtonPadding.right() + _save.width() + st::boxButtonPadding.left(), _save.y()); + _inner.resize(width(), _inner.height()); + _bottomShadow.setGeometry(0, height() - st::boxButtonPadding.bottom() - _save.height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth); + _inner.setVisibleScrollbar((_scroll.scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); +} + +void StickersBox::onStickersUpdated() { + _inner.rebuild(); + setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight))); + _inner.setVisibleScrollbar((_scroll.scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); +} + +void StickersBox::onCheckDraggingScroll(int localY) { + if (localY < _scroll.scrollTop()) { + _scrollDelta = localY - _scroll.scrollTop(); + } else if (localY >= _scroll.scrollTop() + _scroll.height()) { + _scrollDelta = localY - _scroll.scrollTop() - _scroll.height() + 1; + } else { + _scrollDelta = 0; + } + if (_scrollDelta) { + _scrollTimer.start(15); + } else { + _scrollTimer.stop(); + } +} + +void StickersBox::onNoDraggingScroll() { + _scrollTimer.stop(); +} + +void StickersBox::onScrollTimer() { + int32 d = (_scrollDelta > 0) ? qMin(_scrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_scrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed)); + _scroll.scrollToY(_scroll.scrollTop() + d); +} + +void StickersBox::onSave() { + if (!_inner.savingStart()) { + return; + } + + bool writeRecent = false; + RecentStickerPack &recent(cGetRecentStickers()); + StickerSets &sets(cRefStickerSets()); + + QVector reorder = _inner.getOrder(), disabled = _inner.getDisabledSets(); + for (int32 i = 0, l = disabled.size(); i < l; ++i) { + StickerSets::iterator it = sets.find(disabled.at(i)); + if (it != sets.cend()) { + for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { + if (it->stickers.indexOf(i->first) >= 0) { + i = recent.erase(i); + writeRecent = true; + } else { + ++i; + } + } + if (!(it->flags & MTPDstickerSet::flag_disabled)) { + MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName)); + if (it->flags & MTPDstickerSet::flag_official) { + _disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolTrue()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType()); + it->flags |= MTPDstickerSet::flag_disabled; + } else { + _disenableRequests.insert(MTP::send(MTPmessages_UninstallStickerSet(setId), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType()); + cRefStickerSetsOrder().removeOne(it->id); + sets.erase(it); + } + } + } + } + StickerSetsOrder &order(cRefStickerSetsOrder()); + order.clear(); + for (int32 i = 0, l = reorder.size(); i < l; ++i) { + StickerSets::iterator it = sets.find(reorder.at(i)); + if (it != sets.cend()) { + if ((it->flags & MTPDstickerSet::flag_disabled) && !disabled.contains(it->id)) { + MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName)); + _disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolFalse()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType()); + it->flags &= ~MTPDstickerSet::flag_disabled; + } + order.push_back(reorder.at(i)); + } + } + for (StickerSets::iterator it = sets.begin(); it != sets.cend();) { + if (it->id == CustomStickerSetId || it->id == RecentStickerSetId || order.contains(it->id)) { + ++it; + } else { + it = sets.erase(it); + } + } + + cSetStickersHash(stickersCountHash()); + Local::writeStickers(); + if (writeRecent) Local::writeUserSettings(); + emit App::main()->stickersUpdated(); + + if (_disenableRequests.isEmpty()) { + saveOrder(); + } else { + MTP::sendAnything(); + } +} + +void StickersBox::hideAll() { + _save.hide(); + _cancel.hide(); + _bottomShadow.hide(); + ItemListBox::hideAll(); +} + +void StickersBox::showAll() { + _save.show(); + _cancel.show(); + _bottomShadow.show(); + ItemListBox::showAll(); +} + +int32 stickerPacksCount(bool includeDisabledOfficial) { + int32 result = 0; + const StickerSetsOrder &order(cStickerSetsOrder()); + const StickerSets &sets(cStickerSets()); + for (int32 i = 0, l = order.size(); i < l; ++i) { + StickerSets::const_iterator it = sets.constFind(order.at(i)); + if (it != sets.cend()) { + if (!(it->flags & MTPDstickerSet::flag_disabled) || ((it->flags & MTPDstickerSet::flag_official) && includeDisabledOfficial)) { + ++result; + } + } + } + return result; +} diff --git a/Telegram/SourceFiles/boxes/stickersetbox.h b/Telegram/SourceFiles/boxes/stickersetbox.h index c57e32bfd3..0f766cd59f 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.h +++ b/Telegram/SourceFiles/boxes/stickersetbox.h @@ -106,3 +106,136 @@ private: BoxButton _add, _share, _cancel, _done; QString _title; }; + +class StickersInner : public TWidget { + Q_OBJECT + +public: + + StickersInner(); + + void paintEvent(QPaintEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + + void rebuild(); + bool savingStart() { + if (_saving) return false; + _saving = true; + return true; + } + + QVector getOrder() const; + QVector getDisabledSets() const; + + void setVisibleScrollbar(int32 width); + + ~StickersInner(); + +signals: + + void checkDraggingScroll(int localY); + void noDraggingScroll(); + +public slots: + + void onUpdateSelected(); + +private: + + bool animStep_shifting(float64 ms); + void paintRow(Painter &p, int32 index); + void clear(); + void setRemoveSel(int32 removeSel); + float64 aboveShadowOpacity() const; + + int32 _rowHeight; + struct StickerSetRow { + StickerSetRow(uint64 id, DocumentData *sticker, int32 count, const QString &title, bool disabled, int32 pixw, int32 pixh) : id(id) + , sticker(sticker) + , count(count) + , title(title) + , disabled(disabled) + , pixw(pixw) + , pixh(pixh) + , xadd(0, 0) + , yadd(0, 0) { + } + uint64 id; + DocumentData *sticker; + int32 count; + QString title; + bool disabled; + int32 pixw, pixh; + anim::ivalue xadd, yadd; + }; + typedef QList StickerSetRows; + StickerSetRows _rows; + QList _animStartTimes; + uint64 _aboveShadowFadeStart; + anim::fvalue _aboveShadowFadeOpacity; + Animation _a_shifting; + + bool _saving; + + int32 _removeSel, _removeDown, _removeWidth, _returnWidth; + + QPoint _mouse; + int32 _selected; + QPoint _dragStart; + int32 _started, _dragging, _above; + + BoxShadow _aboveShadow; + + int32 _scrollbar; +}; + +class StickersBox : public ItemListBox, public RPCSender { + Q_OBJECT + +public: + + StickersBox(); + void resizeEvent(QResizeEvent *e); + void paintEvent(QPaintEvent *e); + + void closePressed(); + +public slots: + + void onStickersUpdated(); + + void onCheckDraggingScroll(int localY); + void onNoDraggingScroll(); + void onScrollTimer(); + + void onSave(); + +protected: + + void hideAll(); + void showAll(); + +private: + + int32 countHeight() const; + + void disenableDone(const MTPBool &result, mtpRequestId req); + bool disenableFail(const RPCError &error, mtpRequestId req); + void reorderDone(const MTPBool &result); + bool reorderFail(const RPCError &result); + void saveOrder(); + + StickersInner _inner; + BoxButton _save, _cancel; + QMap _disenableRequests; + mtpRequestId _reorderRequest; + ScrollableBoxShadow _bottomShadow; + + QTimer _scrollTimer; + int32 _scrollDelta; + +}; + +int32 stickerPacksCount(bool includeDisabledOfficial = false); diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index e45797acc0..bf7d794a74 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -28,6 +28,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "mainwidget.h" #include "boxes/addcontactbox.h" #include "boxes/contactsbox.h" +#include "boxes/confirmbox.h" #include "localstorage.h" @@ -53,7 +54,9 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p , _cancelSearchInPeer(this, st::btnCancelSearch) , _overDelete(false) , _searchInPeer(0) -, _searchInMigrated(0) { +, _searchInMigrated(0) +, _menuPeer(0) +, _menu(0) { connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); connect(main, SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&))); connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*))); @@ -91,7 +94,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO if (_state == DefaultState) { int32 otherStart = dialogs.list.count * st::dlgHeight; - PeerData *active = App::main()->activePeer(), *selected = sel ? sel->history->peer : 0; + PeerData *active = App::main()->activePeer(), *selected = _menuPeer ? _menuPeer : (sel ? sel->history->peer : 0); if (otherStart) { dialogs.list.paint(p, fullWidth(), r.top(), r.top() + r.height(), active, selected, paintingOther); } @@ -160,7 +163,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO MsgId actId = App::main()->activeMsgId(); for (; from < to; ++from) { bool active = ((_filterResults[from]->history->peer == act) || (_filterResults[from]->history->peer->migrateTo() && _filterResults[from]->history->peer->migrateTo() == act)) && !actId; - bool selected = (from == _filteredSel); + bool selected = (from == _filteredSel) || (_filterResults[from]->history->peer == _menuPeer); _filterResults[from]->paint(p, w, active, selected, paintingOther); p.translate(0, st::dlgHeight); } @@ -461,6 +464,9 @@ void DialogsInner::createDialog(History *history) { void DialogsInner::removeDialog(History *history) { if (!history) return; + if (history->peer == _menuPeer && _menu) { + _menu->deleteLater(); + } if (sel && sel->history == history) { sel = 0; } @@ -549,13 +555,26 @@ void DialogsInner::enterEvent(QEvent *e) { onUpdateSelected(true); } -void DialogsInner::updateSelectedRow() { +void DialogsInner::updateSelectedRow(PeerData *peer) { if (_state == DefaultState) { - if (sel) { + if (peer) { + if (History *h = App::historyLoaded(peer->id)) { + if (h->dialogs.contains(0)) { + update(0, h->dialogs.value(0)->pos * st::dlgHeight, fullWidth(), st::dlgHeight); + } + } + } else if (sel) { update(0, sel->pos * st::dlgHeight, fullWidth(), st::dlgHeight); } } else if (_state == FilteredState || _state == SearchedState) { - if (_hashtagSel >= 0) { + if (peer) { + for (int32 i = 0, l = _filterResults.size(); i != l; ++i) { + if (_filterResults.at(i)->history->peer == peer) { + update(0, filteredOffset() + i * st::dlgHeight, fullWidth(), st::dlgHeight); + break; + } + } + } else if (_hashtagSel >= 0) { update(0, _hashtagSel * st::mentionHeight, fullWidth(), st::mentionHeight); } else if (_filteredSel >= 0) { update(0, filteredOffset() + _filteredSel * st::dlgHeight, fullWidth(), st::dlgHeight); @@ -579,6 +598,142 @@ void DialogsInner::leaveEvent(QEvent *e) { } } +void DialogsInner::contextMenuEvent(QContextMenuEvent *e) { + if (_menu) { + _menu->deleteLater(); + _menu = 0; + } + if (_menuPeer) { + updateSelectedRow(_menuPeer); + _menuPeer = 0; + disconnect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData*))); + } + if (e->reason() == QContextMenuEvent::Mouse) { + lastMousePos = e->globalPos(); + selByMouse = true; + onUpdateSelected(true); + } + + History *history = 0; + if (_state == DefaultState) { + if (sel) history = sel->history; + } else if (_state == FilteredState || _state == SearchedState) { + if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) { + history = _filterResults[_filteredSel]->history; + } + } + if (!history) return; + _menuPeer = history->peer; + + _menu = new PopupMenu(); + _menu->addAction(lang((_menuPeer->isChat() || _menuPeer->isMegagroup()) ? lng_context_view_group : (_menuPeer->isUser() ? lng_context_view_profile : lng_context_view_channel)), this, SLOT(onContextProfile()))->setEnabled(true); + _menu->addAction(lang(menuPeerMuted() ? lng_enable_notifications_from_tray : lng_disable_notifications_from_tray), this, SLOT(onContextToggleNotifications()))->setEnabled(true); + _menu->addAction(lang(lng_profile_search_messages), this, SLOT(onContextSearch()))->setEnabled(true); + if (_menuPeer->isUser()) { + _menu->addAction(lang(lng_profile_clear_history), this, SLOT(onContextClearHistory()))->setEnabled(true); + _menu->addAction(lang(lng_profile_delete_conversation), this, SLOT(onContextDeleteAndLeave()))->setEnabled(true); + _menu->addAction(lang((_menuPeer->asUser()->blocked == UserIsBlocked) ? (_menuPeer->asUser()->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user) : (_menuPeer->asUser()->botInfo ? lng_profile_block_bot : lng_profile_block_user)), this, SLOT(onContextToggleBlock()))->setEnabled(true); + connect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData*))); + } else if (_menuPeer->isChat()) { + _menu->addAction(lang(lng_profile_clear_history), this, SLOT(onContextClearHistory()))->setEnabled(true); + _menu->addAction(lang(lng_profile_clear_and_exit), this, SLOT(onContextDeleteAndLeave()))->setEnabled(true); + } else if (_menuPeer->isChannel() && _menuPeer->asChannel()->amIn() && !_menuPeer->asChannel()->amCreator()) { + _menu->addAction(lang(_menuPeer->isMegagroup() ? lng_profile_leave_group : lng_profile_leave_channel), this, SLOT(onContextDeleteAndLeave()))->setEnabled(true); + } + + connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroyed(QObject*))); + _menu->popup(e->globalPos()); + e->accept(); +} + +bool DialogsInner::menuPeerMuted() { + return _menuPeer && _menuPeer->notify != EmptyNotifySettings && _menuPeer->notify != UnknownNotifySettings && _menuPeer->notify->mute >= unixtime(); +} + +void DialogsInner::onContextProfile() { + if (!_menuPeer) return; + App::main()->showPeerProfile(_menuPeer); +} + +void DialogsInner::onContextToggleNotifications() { + if (!_menuPeer) return; + App::main()->updateNotifySetting(_menuPeer, menuPeerMuted()); +} + +void DialogsInner::onContextSearch() { + if (!_menuPeer) return; + App::main()->searchInPeer(_menuPeer); +} + +void DialogsInner::onContextClearHistory() { + if (!_menuPeer || _menuPeer->isChannel()) return; + ConfirmBox *box = new ConfirmBox(_menuPeer->isUser() ? lng_sure_delete_history(lt_contact, _menuPeer->name) : lng_sure_delete_group_history(lt_group, _menuPeer->name), lang(lng_box_delete), st::attentionBoxButton); + connect(box, SIGNAL(confirmed()), this, SLOT(onContextClearHistorySure())); + App::showLayer(box); +} + +void DialogsInner::onContextClearHistorySure() { + if (!_menuPeer || _menuPeer->isChannel()) return; + App::wnd()->hideLayer(); + App::main()->clearHistory(_menuPeer); +} + +void DialogsInner::onContextDeleteAndLeave() { + if (!_menuPeer) return; + ConfirmBox *box = new ConfirmBox(_menuPeer->isUser() ? lng_sure_delete_history(lt_contact, _menuPeer->name) : (_menuPeer->isChat() ? lng_sure_delete_and_exit(lt_group, _menuPeer->name) : lang(_menuPeer->isMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel)), lang(_menuPeer->isUser() ? lng_box_delete : lng_box_leave), _menuPeer->isChannel() ? st::defaultBoxButton : st::attentionBoxButton); + connect(box, SIGNAL(confirmed()), this, SLOT(onContextDeleteAndLeaveSure())); + App::wnd()->showLayer(box); +} + +void DialogsInner::onContextDeleteAndLeaveSure() { + if (!_menuPeer) return; + if (_menuPeer->isUser()) { + App::main()->deleteConversation(_menuPeer); + } else if (_menuPeer->isChat()) { + App::wnd()->hideLayer(); + App::main()->showDialogs(); + MTP::send(MTPmessages_DeleteChatUser(_menuPeer->asChat()->inputChat, App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _menuPeer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _menuPeer)); + } else if (_menuPeer->isChannel()) { + App::wnd()->hideLayer(); + App::main()->showDialogs(); + if (_menuPeer->migrateFrom()) { + App::main()->deleteConversation(_menuPeer->migrateFrom()); + } + MTP::send(MTPchannels_LeaveChannel(_menuPeer->asChannel()->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived)); + } +} + +void DialogsInner::onContextToggleBlock() { + if (!_menuPeer || !_menuPeer->isUser()) return; + if (_menuPeer->asUser()->blocked == UserIsBlocked) { + MTP::send(MTPcontacts_Unblock(_menuPeer->asUser()->inputUser), rpcDone(&DialogsInner::contextBlockDone, qMakePair(_menuPeer->asUser(), false))); + } else { + MTP::send(MTPcontacts_Block(_menuPeer->asUser()->inputUser), rpcDone(&DialogsInner::contextBlockDone, qMakePair(_menuPeer->asUser(), true))); + } +} + +void DialogsInner::contextBlockDone(QPair data, const MTPBool &result) { + data.first->blocked = data.second ? UserIsBlocked : UserIsNotBlocked; + emit App::main()->peerUpdated(data.first); +} + +void DialogsInner::onMenuDestroyed(QObject *obj) { + if (_menu == obj) { + _menu = 0; + if (_menuPeer) { + updateSelectedRow(_menuPeer); + _menuPeer = 0; + disconnect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData*))); + } + lastMousePos = QCursor::pos(); + if (rect().contains(mapFromGlobal(lastMousePos))) { + selByMouse = true; + setMouseTracking(true); + onUpdateSelected(true); + } + } +} + void DialogsInner::onParentGeometryChanged() { lastMousePos = QCursor::pos(); if (rect().contains(mapFromGlobal(lastMousePos))) { @@ -763,6 +918,18 @@ void DialogsInner::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem) { } } +void DialogsInner::updateNotifySettings(PeerData *peer) { + if (_menu && _menuPeer == peer) { + _menu->actions().at(1)->setText(lang(menuPeerMuted() ? lng_enable_notifications_from_tray : lng_disable_notifications_from_tray)); + } +} + +void DialogsInner::peerUpdated(PeerData *peer) { + if (_menu && _menuPeer == peer && _menuPeer->isUser()) { + _menu->actions().at(5)->setText(lang((_menuPeer->asUser()->blocked == UserIsBlocked) ? (_menuPeer->asUser()->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user) : (_menuPeer->asUser()->botInfo ? lng_profile_block_bot : lng_profile_block_user))); + } +} + PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) { lastMousePos = globalPos; selByMouse = true; @@ -1708,6 +1875,10 @@ void DialogsWidget::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem) { _inner.itemReplaced(oldItem, newItem); } +void DialogsWidget::updateNotifySettings(PeerData *peer) { + _inner.updateNotifySettings(peer); +} + void DialogsWidget::unreadCountsReceived(const QVector &dialogs) { for (QVector::const_iterator i = dialogs.cbegin(), e = dialogs.cend(); i != e; ++i) { switch (i->type()) { diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 89d0f008ac..eaea775e76 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -31,7 +31,7 @@ enum DialogsSearchRequestType { DialogsSearchMigratedFromOffset, }; -class DialogsInner : public SplittedWidget { +class DialogsInner : public SplittedWidget, public RPCSender { Q_OBJECT public: @@ -59,6 +59,7 @@ public: void resizeEvent(QResizeEvent *e); void enterEvent(QEvent *e); void leaveEvent(QEvent *e); + void contextMenuEvent(QContextMenuEvent *e); void peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool act, bool sel, bool onlyBackground) const; void searchInPeerPaint(Painter &p, int32 w, bool onlyBackground) const; @@ -120,6 +121,8 @@ public: PeerData *updateFromParentDrag(QPoint globalPos); + void updateNotifySettings(PeerData *peer); + ~DialogsInner(); public slots: @@ -130,6 +133,19 @@ public slots: void onPeerPhotoChanged(PeerData *peer); void onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow); + void onContextProfile(); + void onContextToggleNotifications(); + void onContextSearch(); + void onContextClearHistory(); + void onContextClearHistorySure(); + void onContextDeleteAndLeave(); + void onContextDeleteAndLeaveSure(); + void onContextToggleBlock(); + + void onMenuDestroyed(QObject*); + + void peerUpdated(PeerData *peer); + signals: void mustScrollTo(int scrollToTop, int scrollToBottom); @@ -147,7 +163,9 @@ protected: private: void clearSearchResults(bool clearPeople = true); - void updateSelectedRow(); + void updateSelectedRow(PeerData *peer = 0); + bool menuPeerMuted(); + void contextBlockDone(QPair data, const MTPBool &result); DialogsIndexed dialogs; DialogsIndexed contactsNoDialogs; @@ -186,7 +204,9 @@ private: bool _overDelete; - PeerData *_searchInPeer, *_searchInMigrated; + PeerData *_searchInPeer, *_searchInMigrated, *_menuPeer; + + PopupMenu *_menu; }; @@ -242,6 +262,8 @@ public: void itemRemoved(HistoryItem *item); void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem); + void updateNotifySettings(PeerData *peer); + signals: void cancelled(); diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index 51a3d2dcfd..bd11940e58 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -30,6 +30,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "apiwrap.h" #include "boxes/confirmbox.h" +#include "boxes/stickersetbox.h" Dropdown::Dropdown(QWidget *parent, const style::dropdown &st) : TWidget(parent), _ignore(false), _selected(-1), _st(st), _width(_st.width), _hiding(false), a_opacity(0), _shadow(_st.shadow) { @@ -1195,15 +1196,19 @@ void EmojiPanInner::showEmojiPack(DBIEmojiTab packIndex) { update(); } -StickerPanInner::StickerPanInner() : _maxHeight(st::emojiPanMaxHeight), -_top(0), _selected(-1), _pressedSel(-1) { - resize(st::emojiPanWidth - st::emojiScroll.width, countHeight()); +StickerPanInner::StickerPanInner() : TWidget() +, _top(0) +, _selected(-1) +, _pressedSel(-1) +, _settings(this, lang(lng_stickers_you_have)) { + setMaxHeight(st::emojiPanMaxHeight); setMouseTracking(true); setFocusPolicy(Qt::NoFocus); setAttribute(Qt::WA_OpaquePaintEvent); connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); + connect(&_settings, SIGNAL(clicked()), this, SLOT(onSettings())); refreshStickers(); } @@ -1211,6 +1216,7 @@ _top(0), _selected(-1), _pressedSel(-1) { void StickerPanInner::setMaxHeight(int32 h) { _maxHeight = h; resize(st::emojiPanWidth - st::emojiScroll.width, countHeight()); + _settings.moveToLeft((st::emojiPanWidth - _settings.width()) / 2, height() / 3); } void StickerPanInner::setScrollTop(int top) { @@ -1228,7 +1234,7 @@ int StickerPanInner::countHeight() { if (i == _sets.size() - 1 && h < minLastH) h = minLastH; result += h; } - return result + st::stickerPanPadding; + return qMax(minLastH, result) + st::stickerPanPadding; } QRect StickerPanInner::stickerRect(int tab, int sel) { @@ -1461,6 +1467,8 @@ void StickerPanInner::refreshStickers() { int32 h = countHeight(); if (h != height()) resize(width(), h); + _settings.setVisible(_sets.isEmpty()); + emit refreshIcons(); updateSelected(); @@ -1512,7 +1520,7 @@ uint64 StickerPanInner::currentSet(int yOffset) const { void StickerPanInner::appendSet(uint64 setId) { const StickerSets &sets(cStickerSets()); StickerSets::const_iterator it = sets.constFind(setId); - if (it == sets.cend() || it->stickers.isEmpty()) return; + if (it == sets.cend() || (it->flags & MTPDstickerSet::flag_disabled) || it->stickers.isEmpty()) return; StickerPack pack; pack.reserve(it->stickers.size()); @@ -1710,6 +1718,10 @@ void StickerPanInner::updateSelected() { if (startanim) anim::start(this); } +void StickerPanInner::onSettings() { + App::showLayer(new StickersBox()); +} + bool StickerPanInner::animStep(float64 ms) { uint64 now = getms(); QRegion toUpdate; @@ -1976,6 +1988,8 @@ void EmojiPan::paintEvent(QPaintEvent *e) { p.fillRect(myrtlrect(r.x() + r.width() - st::emojiScroll.width, r.y(), st::emojiScroll.width, e_scroll.height()), st::white->b); if (_stickersShown) { 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); + if (!_icons.isEmpty()) { int32 x = _iconsLeft, i = 0, selxrel = _iconSelX.current(), selx = x + selxrel - _iconsX.current(); if (!_icons.at(i).sticker) { @@ -1996,13 +2010,13 @@ void EmojiPan::paintEvent(QPaintEvent *e) { ++i; } - QRect clip(x, _iconsTop, _iconsLeft + 8 * st::rbEmoji.width - x, st::rbEmoji.height); + QRect clip(x, _iconsTop, _iconsLeft + 7 * st::rbEmoji.width - x, st::rbEmoji.height); if (rtl()) clip.moveLeft(width() - x - clip.width()); p.setClipRect(clip); i += _iconsX.current() / int(st::rbEmoji.width); x -= _iconsX.current() % int(st::rbEmoji.width); - for (int32 l = qMin(_icons.size(), i + 8 + (_icons.at(0).sticker ? 1 : 0)); i < l; ++i) { + for (int32 l = qMin(_icons.size(), i + 7 + (_icons.at(0).sticker ? 1 : 0)); i < l; ++i) { const StickerIcon &s(_icons.at(i)); s.sticker->thumb->load(); QPixmap pix(s.sticker->thumb->pix(s.pixw, s.pixh)); @@ -2028,7 +2042,7 @@ void EmojiPan::paintEvent(QPaintEvent *e) { float64 o_right = snap(float64(_iconsMax - _iconsX.current()) / st::stickerIconRight.pxWidth(), 0., 1.); if (o_right > 0) { p.setOpacity(o_right); - p.drawSpriteRight(QRect(width() - _iconsLeft - 8 * st::rbEmoji.width, _iconsTop, st::stickerIconRight.pxWidth(), st::rbEmoji.height), width(), st::stickerIconRight); + p.drawSpriteRight(QRect(width() - _iconsLeft - 7 * st::rbEmoji.width, _iconsTop, st::stickerIconRight.pxWidth(), st::rbEmoji.height), width(), st::stickerIconRight); } } } else { @@ -2100,27 +2114,31 @@ void EmojiPan::otherLeave() { } void EmojiPan::mousePressEvent(QMouseEvent *e) { - if (!_stickersShown || _icons.isEmpty()) return; + if (!_stickersShown) return; _iconsMousePos = e ? e->globalPos() : QCursor::pos(); updateSelected(); - _iconDown = _iconOver; - _iconsMouseDown = _iconsMousePos; - _iconsStartX = _iconsX.current(); + if (_iconOver == _icons.size()) { + App::showLayer(new StickersBox()); + } else { + _iconDown = _iconOver; + _iconsMouseDown = _iconsMousePos; + _iconsStartX = _iconsX.current(); + } } void EmojiPan::mouseMoveEvent(QMouseEvent *e) { - if (!_stickersShown || _icons.isEmpty()) return; + if (!_stickersShown) return; _iconsMousePos = e ? e->globalPos() : QCursor::pos(); updateSelected(); - if (!_iconsDragging && _iconDown >= (_icons.at(0).sticker ? 0 : 1)) { + if (!_iconsDragging && !_icons.isEmpty() && _iconDown >= (_icons.at(0).sticker ? 0 : 1)) { if ((_iconsMousePos - _iconsMouseDown).manhattanLength() >= QApplication::startDragDistance()) { _iconsDragging = true; } } if (_iconsDragging) { - int32 newX = snap(_iconsStartX + _iconsMouseDown.x() - _iconsMousePos.x(), 0, _iconsMax); + int32 newX = snap(_iconsStartX + (rtl() ? -1 : 1) * (_iconsMouseDown.x() - _iconsMousePos.x()), 0, _iconsMax); if (newX != _iconsX.current()) { _iconsX = anim::ivalue(newX, newX); _iconsStartAnim = 0; @@ -2150,7 +2168,7 @@ void EmojiPan::mouseReleaseEvent(QMouseEvent *e) { } else { updateSelected(); - if (wasDown == _iconOver && _iconOver >= 0) { + if (wasDown == _iconOver && _iconOver >= 0 && _iconOver < _icons.size()) { _iconSelX = anim::ivalue(_iconOver * st::rbEmoji.width, _iconOver * st::rbEmoji.width); s_inner.showStickerSet(_icons.at(_iconOver).setId); } @@ -2160,7 +2178,7 @@ void EmojiPan::mouseReleaseEvent(QMouseEvent *e) { bool EmojiPan::event(QEvent *e) { if (e->type() == QEvent::TouchBegin) { int a = 0; - } else if (e->type() == QEvent::Wheel && _iconOver >= ((_icons.isEmpty() || _icons.at(0).sticker) ? 0 : 1) && _iconDown < 0) { + } else if (e->type() == QEvent::Wheel && !_icons.isEmpty() && _iconOver >= (_icons.at(0).sticker ? 0 : 1) && _iconOver < _icons.size() && _iconDown < 0) { QWheelEvent *ev = static_cast(e); bool hor = (ev->angleDelta().x() != 0 || ev->orientation() == Qt::Horizontal); bool ver = (ev->angleDelta().y() != 0 || ev->orientation() == Qt::Vertical); @@ -2213,7 +2231,7 @@ void EmojiPan::onRefreshIcons() { _iconsMax = 0; } else { _iconHovers = QVector(_icons.size(), 0); - _iconsMax = qMax(int((_icons.size() - 8) * st::rbEmoji.width), 0); + _iconsMax = qMax(int((_icons.size() - 7) * st::rbEmoji.width), 0); } updatePanelsPositions(s_panels, s_scroll.scrollTop()); updateSelected(); @@ -2237,23 +2255,29 @@ void EmojiPan::leaveToChildEvent(QEvent *e) { } void EmojiPan::updateSelected() { - if (_icons.isEmpty() || _iconDown >= 0) return; + if (_iconDown >= 0) { + return; + } QPoint p(mapFromGlobal(_iconsMousePos)); int32 x = p.x(), y = p.y(), newOver = -1; if (rtl()) x = width() - x; x -= _iconsLeft; - if (y >= _iconsTop && y < _iconsTop + st::rbEmoji.height && x >= 0 && x < 8 * st::rbEmoji.width && x < _icons.size() * st::rbEmoji.width) { - if (!_icons.at(0).sticker) { - if (x < st::rbEmoji.width) { - newOver = 0; - } else { - x -= st::rbEmoji.width; + if (x >= st::rbEmoji.width * 7 && x < st::rbEmoji.width * 8 && y >= _iconsTop && y < _iconsTop + st::rbEmoji.height) { + newOver = _icons.size(); + } else if (!_icons.isEmpty()) { + if (y >= _iconsTop && y < _iconsTop + st::rbEmoji.height && x >= 0 && x < 7 * st::rbEmoji.width && x < _icons.size() * st::rbEmoji.width) { + if (!_icons.at(0).sticker) { + if (x < st::rbEmoji.width) { + newOver = 0; + } else { + x -= st::rbEmoji.width; + } + } + if (newOver < 0) { + x += _iconsX.current(); + newOver = qFloor(x / st::rbEmoji.width) + (_icons.at(0).sticker ? 0 : 1); } - } - if (newOver < 0) { - x += _iconsX.current(); - newOver = qFloor(x / st::rbEmoji.width) + (_icons.at(0).sticker ? 0 : 1); } } if (newOver != _iconOver) { @@ -2263,7 +2287,7 @@ void EmojiPan::updateSelected() { setCursor(style::cur_pointer); } bool startanim = false; - if (_iconOver >= 0) { + if (_iconOver >= 0 && _iconOver < _icons.size()) { _iconAnimations.remove(_iconOver + 1); if (_iconAnimations.find(-_iconOver - 1) == _iconAnimations.end()) { if (_iconAnimations.isEmpty() && !_iconsStartAnim) startanim = true; @@ -2271,7 +2295,7 @@ void EmojiPan::updateSelected() { } } _iconOver = newOver; - if (_iconOver >= 0) { + if (_iconOver >= 0 && _iconOver < _icons.size()) { _iconAnimations.remove(-_iconOver - 1); if (_iconAnimations.find(_iconOver + 1) == _iconAnimations.end()) { if (_iconAnimations.isEmpty() && !_iconsStartAnim) startanim = true; @@ -2645,7 +2669,7 @@ void EmojiPan::onRemoveSetSure() { } cRefStickerSets().erase(it); cRefStickerSetsOrder().removeOne(_removingSetId); - cSetStickersHash(QByteArray()); + cSetStickersHash(stickersCountHash()); refreshStickers(); Local::writeStickers(); if (writeRecent) Local::writeUserSettings(); diff --git a/Telegram/SourceFiles/dropdown.h b/Telegram/SourceFiles/dropdown.h index c2d0404b3c..1d6e77e919 100644 --- a/Telegram/SourceFiles/dropdown.h +++ b/Telegram/SourceFiles/dropdown.h @@ -348,6 +348,7 @@ public: public slots: void updateSelected(); + void onSettings(); signals: @@ -391,6 +392,8 @@ private: int32 _selected, _pressedSel; QPoint _lastMousePos; + + LinkButton _settings; }; class EmojiPanel : public TWidget { diff --git a/Telegram/SourceFiles/gui/countryinput.h b/Telegram/SourceFiles/gui/countryinput.h index ff6c7e2340..457c177e44 100644 --- a/Telegram/SourceFiles/gui/countryinput.h +++ b/Telegram/SourceFiles/gui/countryinput.h @@ -151,98 +151,3 @@ private: ScrollableBoxShadow _topShadow; }; - -/** / -class CountryList : public QWidget { - Q_OBJECT - -public: - - CountryList(QWidget *parent, const style::countryList &st = st::countryList); - - void paintEvent(QPaintEvent *e); - void mouseMoveEvent(QMouseEvent *e); - void mousePressEvent(QMouseEvent *e); - void enterEvent(QEvent *e); - void leaveEvent(QEvent *e); - - void selectSkip(int delta); - void selectSkipPage(int h, int delta); - - void updateFiltered(); - - QString getSelectedCountry() const; - -public slots: - - void onUpdateSelected(bool force = false); - void onParentGeometryChanged(); - -signals: - - void countrySelected(); - void mustScrollTo(int scrollToTop, int scrollToBottom); - -private: - - void resetList(); - void setSelected(int newSelected); - - int _sel; - style::countryList _st; - QPoint _mousePos; - - bool _mouseSel; - -}; - -class CountrySelect : public QWidget, public Animated { - Q_OBJECT - -public: - - CountrySelect(); - - void paintEvent(QPaintEvent *e); - void keyPressEvent(QKeyEvent *e); - void mousePressEvent(QMouseEvent *e); - void resizeEvent(QResizeEvent *e); - - bool animStep(float64 ms); - - ~CountrySelect(); - -signals: - - void countryChosen(const QString &country = QString()); - void countryFinished(); - -public slots: - - void onParentResize(const QSize &newSize); - void onCountryChoose(); - void onCountryCancel(); - void onScrollFinished(); - void onFilterUpdate(); - -private: - - void finish(const QString &res); - void prepareAnimation(int to); - - QString _result; - FlatInput _filter; - ScrollArea _scroll; - CountryList _list; - BoxButton _doneButton, _cancelButton; - int32 _innerLeft, _innerTop, _innerWidth, _innerHeight; - - anim::fvalue a_alpha, a_bgAlpha; - anim::ivalue a_coord; - anim::transition af_alpha, af_bgAlpha, af_coord; - QPixmap _cache; - - BoxShadow _shadow; - -}; -*/ \ No newline at end of file diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 7cb850fec1..f360eb16c7 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -2943,7 +2943,8 @@ void HistoryWidget::updateStickers() { if (cLastStickersUpdate() && getms(true) < cLastStickersUpdate() + StickersUpdateTimeout) return; if (_stickersUpdateRequest) return; - _stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_string(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed)); + cSetStickersHash(stickersCountHash(true)); + _stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed)); } void HistoryWidget::notifyBotCommandsChanged(UserData *user) { @@ -2993,9 +2994,6 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) { const QVector &d_sets(d.vsets.c_vector().v); - QByteArray wasHash = cStickersHash(); - cSetStickersHash(qba(d.vhash)); - StickerSetsOrder &setsOrder(cRefStickerSetsOrder()); setsOrder.clear(); @@ -3008,21 +3006,9 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) { if (d_sets.at(i).type() == mtpc_stickerSet) { const MTPDstickerSet &set(d_sets.at(i).c_stickerSet()); StickerSets::iterator i = sets.find(set.vid.v); - QString title = qs(set.vtitle); - if (set.vflags.v & MTPDstickerSet::flag_official) { - if (!title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) { - title = lang(lng_stickers_default_set); - } - setsOrder.push_front(set.vid.v); - } else { - setsOrder.push_back(set.vid.v); - } - + QString title = stickerSetTitle(set); if (i == sets.cend()) { i = sets.insert(set.vid.v, StickerSet(set.vid.v, set.vaccess_hash.v, title, qs(set.vshort_name), set.vcount.v, set.vhash.v, set.vflags.v | MTPDstickerSet_flag_NOT_LOADED)); - if (!(i->flags & MTPDstickerSet::flag_disabled)) { - setsToRequest.insert(set.vid.v, set.vaccess_hash.v); - } } else { i->access = set.vaccess_hash.v; i->title = title; @@ -3032,21 +3018,40 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) { i->count = set.vcount.v; i->hash = set.vhash.v; i->flags |= MTPDstickerSet_flag_NOT_LOADED; // need to request this set - if (!(i->flags & MTPDstickerSet::flag_disabled)) { - setsToRequest.insert(set.vid.v, set.vaccess_hash.v); - } + } + } + if (!(i->flags & MTPDstickerSet::flag_disabled) || (i->flags & MTPDstickerSet::flag_official)) { + setsOrder.push_back(set.vid.v); + if (i->stickers.isEmpty() || (i->flags & MTPDstickerSet_flag_NOT_LOADED)) { + setsToRequest.insert(set.vid.v, set.vaccess_hash.v); } } } } - for (StickerSets::iterator i = sets.begin(), e = sets.end(); i != e;) { - if (i->id == CustomStickerSetId || i->access != 0) { - ++i; + bool writeRecent = false; + RecentStickerPack &recent(cGetRecentStickers()); + for (StickerSets::iterator it = sets.begin(), e = sets.end(); it != e;) { + if (it->id == CustomStickerSetId || it->access != 0) { + ++it; } else { - i = sets.erase(i); + for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { + if (it->stickers.indexOf(i->first) >= 0) { + i = recent.erase(i); + writeRecent = true; + } else { + ++i; + } + } + it = sets.erase(it); } } + int32 countedHash = stickersCountHash(); + cSetStickersHash(countedHash); + if (countedHash != d.vhash.v) { + LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(countedHash)); + } + if (!setsToRequest.isEmpty() && App::api()) { for (QMap::const_iterator i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) { App::api()->scheduleStickerSetRequest(i.key(), i.value()); @@ -3055,6 +3060,7 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) { } Local::writeStickers(); + if (writeRecent) Local::writeUserSettings(); if (App::main()) emit App::main()->stickersUpdated(); } diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index 4834fdcba6..e5e395c19c 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -2608,11 +2608,12 @@ namespace Local { _writeMap(); } else { int32 setsCount = 0; - quint32 size = sizeof(quint32) + _bytearraySize(cStickersHash()); + QByteArray hashToWrite = (qsl("%d:") + QString::number(cStickersHash())).toUtf8(); + quint32 size = sizeof(quint32) + _bytearraySize(hashToWrite); for (StickerSets::const_iterator i = sets.cbegin(); i != sets.cend(); ++i) { bool notLoaded = (i->flags & MTPDstickerSet_flag_NOT_LOADED); if (notLoaded) { - if (!(i->flags & MTPDstickerSet::flag_disabled)) { // waiting to receive + if (!(i->flags & MTPDstickerSet::flag_disabled) || (i->flags & MTPDstickerSet::flag_official)) { // waiting to receive return; } } else { @@ -2639,7 +2640,7 @@ namespace Local { _writeMap(WriteMapFast); } EncryptedDescriptor data(size); - data.stream << quint32(setsCount) << cStickersHash(); + data.stream << quint32(setsCount) << hashToWrite; _writeStickerSet(data.stream, CustomStickerSetId); for (StickerSetsOrder::const_iterator i = cStickerSetsOrder().cbegin(), e = cStickerSetsOrder().cend(); i != e; ++i) { _writeStickerSet(data.stream, *i); @@ -2669,7 +2670,7 @@ namespace Local { RecentStickerPack &recent(cRefRecentStickers()); recent.clear(); - cSetStickersHash(QByteArray()); + cSetStickersHash(0); StickerSet &def(sets.insert(DefaultStickerSetId, StickerSet(DefaultStickerSetId, 0, lang(lng_stickers_default_set), QString(), 0, 0, MTPDstickerSet::flag_official)).value()); StickerSet &custom(sets.insert(CustomStickerSetId, StickerSet(CustomStickerSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0)).value()); @@ -2827,7 +2828,11 @@ namespace Local { } } - cSetStickersHash(hash); + if (hash.startsWith(qsl("%d:").toUtf8())) { + cSetStickersHash(QString::fromUtf8(hash.mid(3)).toInt()); + } else { + cSetStickersHash(0); + } } void writeBackground(int32 id, const QImage &img) { diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 1fb04b95f6..d0c7bad896 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -3688,6 +3688,7 @@ void MainWidget::startFull(const MTPVector &users) { } void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *h) { + PeerData *updatePeer = 0; switch (settings.type()) { case mtpc_peerNotifySettingsEmpty: switch (peer.type()) { @@ -3695,18 +3696,15 @@ void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNoti case mtpc_notifyUsers: globalNotifyUsersPtr = EmptyNotifySettings; break; case mtpc_notifyChats: globalNotifyChatsPtr = EmptyNotifySettings; break; case mtpc_notifyPeer: { - PeerData *data = App::peerLoaded(peerFromMTP(peer.c_notifyPeer().vpeer)); - if (data && data->notify != EmptyNotifySettings) { - if (data->notify != UnknownNotifySettings) { - delete data->notify; + updatePeer = App::peerLoaded(peerFromMTP(peer.c_notifyPeer().vpeer)); + if (updatePeer && updatePeer->notify != EmptyNotifySettings) { + if (updatePeer->notify != UnknownNotifySettings) { + delete updatePeer->notify; } - data->notify = EmptyNotifySettings; - App::unregMuted(data); - if (!h) h = App::history(data->id); + updatePeer->notify = EmptyNotifySettings; + App::unregMuted(updatePeer); + if (!h) h = App::history(updatePeer->id); h->setMute(false); - if (history.peer() == data) { - history.updateNotifySettings(); - } } } break; } @@ -3714,19 +3712,18 @@ void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNoti case mtpc_peerNotifySettings: { const MTPDpeerNotifySettings &d(settings.c_peerNotifySettings()); NotifySettingsPtr setTo = UnknownNotifySettings; - PeerData *data = 0; switch (peer.type()) { case mtpc_notifyAll: setTo = globalNotifyAllPtr = &globalNotifyAll; break; case mtpc_notifyUsers: setTo = globalNotifyUsersPtr = &globalNotifyUsers; break; case mtpc_notifyChats: setTo = globalNotifyChatsPtr = &globalNotifyChats; break; case mtpc_notifyPeer: { - data = App::peerLoaded(peerFromMTP(peer.c_notifyPeer().vpeer)); - if (!data) break; + updatePeer = App::peerLoaded(peerFromMTP(peer.c_notifyPeer().vpeer)); + if (!updatePeer) break; - if (data->notify == UnknownNotifySettings || data->notify == EmptyNotifySettings) { - data->notify = new NotifySettings(); + if (updatePeer->notify == UnknownNotifySettings || updatePeer->notify == EmptyNotifySettings) { + updatePeer->notify = new NotifySettings(); } - setTo = data->notify; + setTo = updatePeer->notify; } break; } if (setTo == UnknownNotifySettings) break; @@ -3735,25 +3732,28 @@ void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNoti setTo->sound = d.vsound.c_string().v; setTo->previews = mtpIsTrue(d.vshow_previews); setTo->events = d.vevents_mask.v; - if (data) { - if (!h) h = App::history(data->id); + if (updatePeer) { + if (!h) h = App::history(updatePeer->id); int32 changeIn = 0; if (isNotifyMuted(setTo, &changeIn)) { App::wnd()->notifyClear(h); h->setMute(true); - App::regMuted(data, changeIn); + App::regMuted(updatePeer, changeIn); } else { h->setMute(false); } - if (history.peer() == data) { - history.updateNotifySettings(); - } } } break; } - if (profile) { - profile->updateNotifySettings(); + if (updatePeer) { + if (history.peer() == updatePeer) { + history.updateNotifySettings(); + } + dialogs.updateNotifySettings(updatePeer); + if (profile && profile->peer() == updatePeer) { + profile->updateNotifySettings(); + } } } @@ -4593,5 +4593,80 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { } } break; + case mtpc_updateNewStickerSet: { + const MTPDupdateNewStickerSet &d(update.c_updateNewStickerSet()); + if (d.vstickerset.type() == mtpc_messages_stickerSet) { + const MTPDmessages_stickerSet &set(d.vstickerset.c_messages_stickerSet()); + if (set.vset.type() == mtpc_stickerSet) { + const QVector &v(set.vdocuments.c_vector().v); + StickerPack pack; + pack.reserve(v.size()); + for (int32 i = 0, l = v.size(); i < l; ++i) { + DocumentData *doc = App::feedDocument(v.at(i)); + if (!doc || !doc->sticker()) continue; + + pack.push_back(doc); + } + + const MTPDstickerSet &s(set.vset.c_stickerSet()); + + StickerSets &sets(cRefStickerSets()); + + sets.insert(s.vid.v, StickerSet(s.vid.v, s.vaccess_hash.v, stickerSetTitle(s), qs(s.vshort_name), s.vcount.v, s.vhash.v, s.vflags.v)).value().stickers = pack; + + StickerSetsOrder &order(cRefStickerSetsOrder()); + int32 insertAtIndex = 0, currentIndex = order.indexOf(s.vid.v); + if (currentIndex != insertAtIndex) { + if (currentIndex > 0) { + order.removeAt(currentIndex); + } + order.insert(insertAtIndex, s.vid.v); + } + + StickerSets::iterator custom = sets.find(CustomStickerSetId); + if (custom != sets.cend()) { + for (int32 i = 0, l = pack.size(); i < l; ++i) { + custom->stickers.removeOne(pack.at(i)); + } + if (custom->stickers.isEmpty()) { + sets.erase(custom); + } + } + cSetStickersHash(stickersCountHash()); + Local::writeStickers(); + emit stickersUpdated(); + } + } + } break; + + case mtpc_updateStickerSetsOrder: { + const MTPDupdateStickerSetsOrder &d(update.c_updateStickerSetsOrder()); + const QVector &order(d.vorder.c_vector().v); + const StickerSets &sets(cStickerSets()); + StickerSetsOrder result; + for (int32 i = 0, l = order.size(); i < l; ++i) { + if (sets.constFind(order.at(i).v) == sets.cend()) { + break; + } + result.push_back(order.at(i).v); + } + if (result.size() != cStickerSetsOrder().size() || result.size() != order.size()) { + cSetLastStickersUpdate(0); + cSetStickersHash(0); + App::main()->updateStickers(); + } else { + cSetStickerSetsOrder(result); + cSetStickersHash(stickersCountHash()); + Local::writeStickers(); + emit stickersUpdated(); + } + } break; + + case mtpc_updateStickerSets: { + cSetLastStickersUpdate(0); + cSetStickersHash(0); + App::main()->updateStickers(); + } break; + } } diff --git a/Telegram/SourceFiles/mtproto/mtpCoreTypes.cpp b/Telegram/SourceFiles/mtproto/mtpCoreTypes.cpp index 57904985c5..b1d00fb1ea 100644 --- a/Telegram/SourceFiles/mtproto/mtpCoreTypes.cpp +++ b/Telegram/SourceFiles/mtproto/mtpCoreTypes.cpp @@ -21,6 +21,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "mtpCoreTypes.h" +#include "lang.h" + #if defined _DEBUG || defined _WITH_DEBUG QString mtpWrapNumber(float64 number) { @@ -150,3 +152,11 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP } #endif + +QString stickerSetTitle(const MTPDstickerSet &s) { + QString title = qs(s.vtitle); + if ((s.vflags.v & MTPDstickerSet::flag_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) { + return lang(lng_stickers_default_set); + } + return title; +} diff --git a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h index d240b34e2e..290c7716c1 100644 --- a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h +++ b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h @@ -368,7 +368,7 @@ static const mtpTypeId mtpLayers[] = { mtpTypeId(mtpc_invokeWithLayer18), }; static const uint32 mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]); -static const mtpPrime mtpCurrentLayer = 42; +static const mtpPrime mtpCurrentLayer = 43; template class MTPBoxed : public bareT { @@ -990,3 +990,5 @@ enum { // client side flags static const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_int(0), MTP_vector(0)); static const MTPVector MTPnullEntities = MTP_vector(0); + +QString stickerSetTitle(const MTPDstickerSet &s); \ No newline at end of file diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.cpp b/Telegram/SourceFiles/mtproto/mtpScheme.cpp index fb6962cb54..627f9d69ca 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.cpp +++ b/Telegram/SourceFiles/mtproto/mtpScheme.cpp @@ -2082,6 +2082,31 @@ void _serialize_wallPaperSolid(MTPStringLogger &to, int32 stage, int32 lev, Type } } +void _serialize_inputReportReasonSpam(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + to.add("{ inputReportReasonSpam }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + +void _serialize_inputReportReasonViolence(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + to.add("{ inputReportReasonViolence }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + +void _serialize_inputReportReasonPornography(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + to.add("{ inputReportReasonPornography }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + +void _serialize_inputReportReasonOther(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ inputReportReasonOther"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_userFull(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -2966,6 +2991,36 @@ void _serialize_updateChatParticipantAdmin(MTPStringLogger &to, int32 stage, int } } +void _serialize_updateNewStickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ updateNewStickerSet"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" stickerset: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_updateStickerSetsOrder(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ updateStickerSetsOrder"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" order: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_updateStickerSets(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + to.add("{ updateStickerSets }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); +} + void _serialize_updates_state(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -4052,7 +4107,7 @@ void _serialize_messages_allStickers(MTPStringLogger &to, int32 stage, int32 lev to.add("\n").addSpaces(lev); } switch (stage) { - case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" sets: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } @@ -4970,6 +5025,19 @@ void _serialize_channels_channelParticipant(MTPStringLogger &to, int32 stage, in } } +void _serialize_help_termsOfService(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ help_termsOfService"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_req_pq(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -5229,6 +5297,20 @@ void _serialize_account_updateStatus(MTPStringLogger &to, int32 stage, int32 lev } } +void _serialize_account_reportPeer(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_reportPeer"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" reason: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_account_checkUsername(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -5457,6 +5539,19 @@ void _serialize_messages_editChatAdmin(MTPStringLogger &to, int32 stage, int32 l } } +void _serialize_messages_reorderStickerSets(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_reorderStickerSets"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" order: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_upload_saveFilePart(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -6835,7 +6930,7 @@ void _serialize_messages_getAllStickers(MTPStringLogger &to, int32 stage, int32 to.add("\n").addSpaces(lev); } switch (stage) { - case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } @@ -7058,6 +7153,19 @@ void _serialize_help_getAppChangelog(MTPStringLogger &to, int32 stage, int32 lev } } +void _serialize_help_getTermsOfService(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ help_getTermsOfService"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" lang_code: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_channels_getParticipants(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -7305,6 +7413,10 @@ namespace { _serializers.insert(mtpc_peerNotifySettings, _serialize_peerNotifySettings); _serializers.insert(mtpc_wallPaper, _serialize_wallPaper); _serializers.insert(mtpc_wallPaperSolid, _serialize_wallPaperSolid); + _serializers.insert(mtpc_inputReportReasonSpam, _serialize_inputReportReasonSpam); + _serializers.insert(mtpc_inputReportReasonViolence, _serialize_inputReportReasonViolence); + _serializers.insert(mtpc_inputReportReasonPornography, _serialize_inputReportReasonPornography); + _serializers.insert(mtpc_inputReportReasonOther, _serialize_inputReportReasonOther); _serializers.insert(mtpc_userFull, _serialize_userFull); _serializers.insert(mtpc_contact, _serialize_contact); _serializers.insert(mtpc_importedContact, _serialize_importedContact); @@ -7372,6 +7484,9 @@ namespace { _serializers.insert(mtpc_updateChannelMessageViews, _serialize_updateChannelMessageViews); _serializers.insert(mtpc_updateChatAdmins, _serialize_updateChatAdmins); _serializers.insert(mtpc_updateChatParticipantAdmin, _serialize_updateChatParticipantAdmin); + _serializers.insert(mtpc_updateNewStickerSet, _serialize_updateNewStickerSet); + _serializers.insert(mtpc_updateStickerSetsOrder, _serialize_updateStickerSetsOrder); + _serializers.insert(mtpc_updateStickerSets, _serialize_updateStickerSets); _serializers.insert(mtpc_updates_state, _serialize_updates_state); _serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty); _serializers.insert(mtpc_updates_difference, _serialize_updates_difference); @@ -7536,6 +7651,7 @@ namespace { _serializers.insert(mtpc_channelRoleEditor, _serialize_channelRoleEditor); _serializers.insert(mtpc_channels_channelParticipants, _serialize_channels_channelParticipants); _serializers.insert(mtpc_channels_channelParticipant, _serialize_channels_channelParticipant); + _serializers.insert(mtpc_help_termsOfService, _serialize_help_termsOfService); _serializers.insert(mtpc_req_pq, _serialize_req_pq); _serializers.insert(mtpc_req_DH_params, _serialize_req_DH_params); @@ -7557,6 +7673,7 @@ namespace { _serializers.insert(mtpc_account_updateNotifySettings, _serialize_account_updateNotifySettings); _serializers.insert(mtpc_account_resetNotifySettings, _serialize_account_resetNotifySettings); _serializers.insert(mtpc_account_updateStatus, _serialize_account_updateStatus); + _serializers.insert(mtpc_account_reportPeer, _serialize_account_reportPeer); _serializers.insert(mtpc_account_checkUsername, _serialize_account_checkUsername); _serializers.insert(mtpc_account_deleteAccount, _serialize_account_deleteAccount); _serializers.insert(mtpc_account_setAccountTTL, _serialize_account_setAccountTTL); @@ -7574,6 +7691,7 @@ namespace { _serializers.insert(mtpc_messages_installStickerSet, _serialize_messages_installStickerSet); _serializers.insert(mtpc_messages_uninstallStickerSet, _serialize_messages_uninstallStickerSet); _serializers.insert(mtpc_messages_editChatAdmin, _serialize_messages_editChatAdmin); + _serializers.insert(mtpc_messages_reorderStickerSets, _serialize_messages_reorderStickerSets); _serializers.insert(mtpc_upload_saveFilePart, _serialize_upload_saveFilePart); _serializers.insert(mtpc_upload_saveBigFilePart, _serialize_upload_saveBigFilePart); _serializers.insert(mtpc_help_saveAppLog, _serialize_help_saveAppLog); @@ -7693,6 +7811,7 @@ namespace { _serializers.insert(mtpc_help_getInviteText, _serialize_help_getInviteText); _serializers.insert(mtpc_help_getSupport, _serialize_help_getSupport); _serializers.insert(mtpc_help_getAppChangelog, _serialize_help_getAppChangelog); + _serializers.insert(mtpc_help_getTermsOfService, _serialize_help_getTermsOfService); _serializers.insert(mtpc_channels_getParticipants, _serialize_channels_getParticipants); _serializers.insert(mtpc_channels_getParticipant, _serialize_channels_getParticipant); diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.h b/Telegram/SourceFiles/mtproto/mtpScheme.h index f53568ead7..6b0d1c3a1f 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.h +++ b/Telegram/SourceFiles/mtproto/mtpScheme.h @@ -205,6 +205,10 @@ enum { mtpc_peerNotifySettings = 0x8d5e11ee, mtpc_wallPaper = 0xccb03657, mtpc_wallPaperSolid = 0x63117f24, + mtpc_inputReportReasonSpam = 0x58dbcab8, + mtpc_inputReportReasonViolence = 0x1e22c78d, + mtpc_inputReportReasonPornography = 0x2e59d922, + mtpc_inputReportReasonOther = 0xe1746d0a, mtpc_userFull = 0x5a89ac5b, mtpc_contact = 0xf911c994, mtpc_importedContact = 0xd0028438, @@ -272,6 +276,9 @@ enum { mtpc_updateChannelMessageViews = 0x98a12b4b, mtpc_updateChatAdmins = 0x6e947941, mtpc_updateChatParticipantAdmin = 0xb6901959, + mtpc_updateNewStickerSet = 0x688a30aa, + mtpc_updateStickerSetsOrder = 0xf0dfb451, + mtpc_updateStickerSets = 0x43ae3dec, mtpc_updates_state = 0xa56c2a3e, mtpc_updates_differenceEmpty = 0x5d75a138, mtpc_updates_difference = 0xf49ca0, @@ -362,7 +369,7 @@ enum { mtpc_messages_stickers = 0x8a8ecd32, mtpc_stickerPack = 0x12b299d4, mtpc_messages_allStickersNotModified = 0xe86602c3, - mtpc_messages_allStickers = 0xd51dafdb, + mtpc_messages_allStickers = 0xedfd405f, mtpc_disabledFeature = 0xae636f24, mtpc_messages_affectedMessages = 0x84d19185, mtpc_contactLinkUnknown = 0x5f4f9247, @@ -436,6 +443,7 @@ enum { mtpc_channelRoleEditor = 0x820bfe8c, mtpc_channels_channelParticipants = 0xf56ee2a8, mtpc_channels_channelParticipant = 0xd0d9b163, + mtpc_help_termsOfService = 0xf1ee3e90, mtpc_invokeAfterMsg = 0xcb9f372d, mtpc_invokeAfterMsgs = 0x3dc4b4f0, mtpc_initConnection = 0x69796de9, @@ -465,6 +473,7 @@ enum { mtpc_account_updateProfile = 0xf0888d68, mtpc_account_updateStatus = 0x6628562c, mtpc_account_getWallPapers = 0xc04cfac2, + mtpc_account_reportPeer = 0xae189d5f, mtpc_account_checkUsername = 0x2714d86c, mtpc_account_updateUsername = 0x3e0bdd7c, mtpc_account_getPrivacy = 0xdadbc950, @@ -529,7 +538,7 @@ enum { mtpc_messages_receivedQueue = 0x55a5bb66, mtpc_messages_readMessageContents = 0x36a73f77, mtpc_messages_getStickers = 0xae22e045, - mtpc_messages_getAllStickers = 0xaa3bc868, + mtpc_messages_getAllStickers = 0x1c9618b1, mtpc_messages_getWebPagePreview = 0x25223e24, mtpc_messages_exportChatInvite = 0x7d885289, mtpc_messages_checkChatInvite = 0x3eadb1bb, @@ -543,6 +552,7 @@ enum { mtpc_messages_editChatAdmin = 0xa9e69f2e, mtpc_messages_migrateChat = 0x15a3b8e3, mtpc_messages_searchGlobal = 0x9e3cacb0, + mtpc_messages_reorderStickerSets = 0x9fcfbc30, mtpc_updates_getState = 0xedd4882a, mtpc_updates_getDifference = 0xa041495, mtpc_updates_getChannelDifference = 0xbb32d7c0, @@ -560,6 +570,7 @@ enum { mtpc_help_getInviteText = 0xa4a95186, mtpc_help_getSupport = 0x9cdf08cd, mtpc_help_getAppChangelog = 0x5bab7fb2, + mtpc_help_getTermsOfService = 0x37d78f83, mtpc_channels_getDialogs = 0xa9d3d249, mtpc_channels_getImportantHistory = 0xddb929cb, mtpc_channels_readHistory = 0xcc104937, @@ -843,6 +854,9 @@ class MTPwallPaper; class MTPDwallPaper; class MTPDwallPaperSolid; +class MTPreportReason; +class MTPDinputReportReasonOther; + class MTPuserFull; class MTPDuserFull; @@ -935,6 +949,8 @@ class MTPDupdateDeleteChannelMessages; class MTPDupdateChannelMessageViews; class MTPDupdateChatAdmins; class MTPDupdateChatParticipantAdmin; +class MTPDupdateNewStickerSet; +class MTPDupdateStickerSetsOrder; class MTPupdates_state; class MTPDupdates_state; @@ -1196,6 +1212,9 @@ class MTPDchannels_channelParticipants; class MTPchannels_channelParticipant; class MTPDchannels_channelParticipant; +class MTPhelp_termsOfService; +class MTPDhelp_termsOfService; + // Boxed types definitions typedef MTPBoxed MTPResPQ; @@ -1264,6 +1283,7 @@ typedef MTPBoxed MTPInputPeerNotifySettings; typedef MTPBoxed MTPPeerNotifyEvents; typedef MTPBoxed MTPPeerNotifySettings; typedef MTPBoxed MTPWallPaper; +typedef MTPBoxed MTPReportReason; typedef MTPBoxed MTPUserFull; typedef MTPBoxed MTPContact; typedef MTPBoxed MTPImportedContact; @@ -1353,6 +1373,7 @@ typedef MTPBoxed MTPChannelParticipantsFilter; typedef MTPBoxed MTPChannelParticipantRole; typedef MTPBoxed MTPchannels_ChannelParticipants; typedef MTPBoxed MTPchannels_ChannelParticipant; +typedef MTPBoxed MTPhelp_TermsOfService; // Type classes definitions @@ -4503,6 +4524,46 @@ private: }; typedef MTPBoxed MTPWallPaper; +class MTPreportReason : private mtpDataOwner { +public: + MTPreportReason() : mtpDataOwner(0), _type(0) { + } + MTPreportReason(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { + read(from, end, cons); + } + + MTPDinputReportReasonOther &_inputReportReasonOther() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_inputReportReasonOther) throw mtpErrorWrongTypeId(_type, mtpc_inputReportReasonOther); + split(); + return *(MTPDinputReportReasonOther*)data; + } + const MTPDinputReportReasonOther &c_inputReportReasonOther() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_inputReportReasonOther) throw mtpErrorWrongTypeId(_type, mtpc_inputReportReasonOther); + return *(const MTPDinputReportReasonOther*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPreportReason(mtpTypeId type); + explicit MTPreportReason(MTPDinputReportReasonOther *_data); + + friend MTPreportReason MTP_inputReportReasonSpam(); + friend MTPreportReason MTP_inputReportReasonViolence(); + friend MTPreportReason MTP_inputReportReasonPornography(); + friend MTPreportReason MTP_inputReportReasonOther(const MTPstring &_text); + + mtpTypeId _type; +}; +typedef MTPBoxed MTPReportReason; + class MTPuserFull : private mtpDataOwner { public: MTPuserFull(); @@ -5564,6 +5625,30 @@ public: return *(const MTPDupdateChatParticipantAdmin*)data; } + MTPDupdateNewStickerSet &_updateNewStickerSet() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateNewStickerSet) throw mtpErrorWrongTypeId(_type, mtpc_updateNewStickerSet); + split(); + return *(MTPDupdateNewStickerSet*)data; + } + const MTPDupdateNewStickerSet &c_updateNewStickerSet() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateNewStickerSet) throw mtpErrorWrongTypeId(_type, mtpc_updateNewStickerSet); + return *(const MTPDupdateNewStickerSet*)data; + } + + MTPDupdateStickerSetsOrder &_updateStickerSetsOrder() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateStickerSetsOrder) throw mtpErrorWrongTypeId(_type, mtpc_updateStickerSetsOrder); + split(); + return *(MTPDupdateStickerSetsOrder*)data; + } + const MTPDupdateStickerSetsOrder &c_updateStickerSetsOrder() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateStickerSetsOrder) throw mtpErrorWrongTypeId(_type, mtpc_updateStickerSetsOrder); + return *(const MTPDupdateStickerSetsOrder*)data; + } + uint32 innerLength() const; mtpTypeId type() const; void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); @@ -5610,6 +5695,8 @@ private: explicit MTPupdate(MTPDupdateChannelMessageViews *_data); explicit MTPupdate(MTPDupdateChatAdmins *_data); explicit MTPupdate(MTPDupdateChatParticipantAdmin *_data); + explicit MTPupdate(MTPDupdateNewStickerSet *_data); + explicit MTPupdate(MTPDupdateStickerSetsOrder *_data); friend MTPupdate MTP_updateNewMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count); friend MTPupdate MTP_updateMessageID(MTPint _id, const MTPlong &_random_id); @@ -5648,6 +5735,9 @@ private: friend MTPupdate MTP_updateChannelMessageViews(MTPint _channel_id, MTPint _id, MTPint _views); friend MTPupdate MTP_updateChatAdmins(MTPint _chat_id, MTPBool _enabled, MTPint _version); friend MTPupdate MTP_updateChatParticipantAdmin(MTPint _chat_id, MTPint _user_id, MTPBool _is_admin, MTPint _version); + friend MTPupdate MTP_updateNewStickerSet(const MTPmessages_StickerSet &_stickerset); + friend MTPupdate MTP_updateStickerSetsOrder(const MTPVector &_order); + friend MTPupdate MTP_updateStickerSets(); mtpTypeId _type; }; @@ -7318,7 +7408,7 @@ private: explicit MTPmessages_allStickers(MTPDmessages_allStickers *_data); friend MTPmessages_allStickers MTP_messages_allStickersNotModified(); - friend MTPmessages_allStickers MTP_messages_allStickers(const MTPstring &_hash, const MTPVector &_sets); + friend MTPmessages_allStickers MTP_messages_allStickers(MTPint _hash, const MTPVector &_sets); mtpTypeId _type; }; @@ -8786,6 +8876,37 @@ private: }; typedef MTPBoxed MTPchannels_ChannelParticipant; +class MTPhelp_termsOfService : private mtpDataOwner { +public: + MTPhelp_termsOfService(); + MTPhelp_termsOfService(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_termsOfService) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDhelp_termsOfService &_help_termsOfService() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDhelp_termsOfService*)data; + } + const MTPDhelp_termsOfService &c_help_termsOfService() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDhelp_termsOfService*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_termsOfService); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPhelp_termsOfService(MTPDhelp_termsOfService *_data); + + friend MTPhelp_termsOfService MTP_help_termsOfService(const MTPstring &_text); +}; +typedef MTPBoxed MTPhelp_TermsOfService; + // Type constructors with data class MTPDresPQ : public mtpDataImpl { @@ -10403,6 +10524,16 @@ public: MTPint vcolor; }; +class MTPDinputReportReasonOther : public mtpDataImpl { +public: + MTPDinputReportReasonOther() { + } + MTPDinputReportReasonOther(const MTPstring &_text) : vtext(_text) { + } + + MTPstring vtext; +}; + class MTPDuserFull : public mtpDataImpl { public: MTPDuserFull() { @@ -11082,6 +11213,26 @@ public: MTPint vversion; }; +class MTPDupdateNewStickerSet : public mtpDataImpl { +public: + MTPDupdateNewStickerSet() { + } + MTPDupdateNewStickerSet(const MTPmessages_StickerSet &_stickerset) : vstickerset(_stickerset) { + } + + MTPmessages_StickerSet vstickerset; +}; + +class MTPDupdateStickerSetsOrder : public mtpDataImpl { +public: + MTPDupdateStickerSetsOrder() { + } + MTPDupdateStickerSetsOrder(const MTPVector &_order) : vorder(_order) { + } + + MTPVector vorder; +}; + class MTPDupdates_state : public mtpDataImpl { public: MTPDupdates_state() { @@ -11914,10 +12065,10 @@ class MTPDmessages_allStickers : public mtpDataImpl { public: MTPDmessages_allStickers() { } - MTPDmessages_allStickers(const MTPstring &_hash, const MTPVector &_sets) : vhash(_hash), vsets(_sets) { + MTPDmessages_allStickers(MTPint _hash, const MTPVector &_sets) : vhash(_hash), vsets(_sets) { } - MTPstring vhash; + MTPint vhash; MTPVector vsets; }; @@ -12696,6 +12847,16 @@ public: MTPVector vusers; }; +class MTPDhelp_termsOfService : public mtpDataImpl { +public: + MTPDhelp_termsOfService() { + } + MTPDhelp_termsOfService(const MTPstring &_text) : vtext(_text) { + } + + MTPstring vtext; +}; + // RPC methods class MTPreq_pq { // RPC method 'req_pq' @@ -14287,6 +14448,48 @@ public: } }; +class MTPaccount_reportPeer { // RPC method 'account.reportPeer' +public: + MTPInputPeer vpeer; + MTPReportReason vreason; + + MTPaccount_reportPeer() { + } + MTPaccount_reportPeer(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_reportPeer) { + read(from, end, cons); + } + MTPaccount_reportPeer(const MTPInputPeer &_peer, const MTPReportReason &_reason) : vpeer(_peer), vreason(_reason) { + } + + uint32 innerLength() const { + return vpeer.innerLength() + vreason.innerLength(); + } + mtpTypeId type() const { + return mtpc_account_reportPeer; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_reportPeer) { + vpeer.read(from, end); + vreason.read(from, end); + } + void write(mtpBuffer &to) const { + vpeer.write(to); + vreason.write(to); + } + + typedef MTPBool ResponseType; +}; +class MTPaccount_ReportPeer : public MTPBoxed { +public: + MTPaccount_ReportPeer() { + } + MTPaccount_ReportPeer(const MTPaccount_reportPeer &v) : MTPBoxed(v) { + } + MTPaccount_ReportPeer(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPaccount_ReportPeer(const MTPInputPeer &_peer, const MTPReportReason &_reason) : MTPBoxed(MTPaccount_reportPeer(_peer, _reason)) { + } +}; + class MTPaccount_checkUsername { // RPC method 'account.checkUsername' public: MTPstring vusername; @@ -16982,14 +17185,14 @@ public: class MTPmessages_getAllStickers { // RPC method 'messages.getAllStickers' public: - MTPstring vhash; + MTPint vhash; MTPmessages_getAllStickers() { } MTPmessages_getAllStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getAllStickers) { read(from, end, cons); } - MTPmessages_getAllStickers(const MTPstring &_hash) : vhash(_hash) { + MTPmessages_getAllStickers(MTPint _hash) : vhash(_hash) { } uint32 innerLength() const { @@ -17015,7 +17218,7 @@ public: } MTPmessages_GetAllStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { } - MTPmessages_GetAllStickers(const MTPstring &_hash) : MTPBoxed(MTPmessages_getAllStickers(_hash)) { + MTPmessages_GetAllStickers(MTPint _hash) : MTPBoxed(MTPmessages_getAllStickers(_hash)) { } }; @@ -17565,6 +17768,45 @@ public: } }; +class MTPmessages_reorderStickerSets { // RPC method 'messages.reorderStickerSets' +public: + MTPVector vorder; + + MTPmessages_reorderStickerSets() { + } + MTPmessages_reorderStickerSets(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_reorderStickerSets) { + read(from, end, cons); + } + MTPmessages_reorderStickerSets(const MTPVector &_order) : vorder(_order) { + } + + uint32 innerLength() const { + return vorder.innerLength(); + } + mtpTypeId type() const { + return mtpc_messages_reorderStickerSets; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_reorderStickerSets) { + vorder.read(from, end); + } + void write(mtpBuffer &to) const { + vorder.write(to); + } + + typedef MTPBool ResponseType; +}; +class MTPmessages_ReorderStickerSets : public MTPBoxed { +public: + MTPmessages_ReorderStickerSets() { + } + MTPmessages_ReorderStickerSets(const MTPmessages_reorderStickerSets &v) : MTPBoxed(v) { + } + MTPmessages_ReorderStickerSets(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPmessages_ReorderStickerSets(const MTPVector &_order) : MTPBoxed(MTPmessages_reorderStickerSets(_order)) { + } +}; + class MTPupdates_getState { // RPC method 'updates.getState' public: MTPupdates_getState() { @@ -18271,6 +18513,45 @@ public: } }; +class MTPhelp_getTermsOfService { // RPC method 'help.getTermsOfService' +public: + MTPstring vlang_code; + + MTPhelp_getTermsOfService() { + } + MTPhelp_getTermsOfService(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_getTermsOfService) { + read(from, end, cons); + } + MTPhelp_getTermsOfService(const MTPstring &_lang_code) : vlang_code(_lang_code) { + } + + uint32 innerLength() const { + return vlang_code.innerLength(); + } + mtpTypeId type() const { + return mtpc_help_getTermsOfService; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_getTermsOfService) { + vlang_code.read(from, end); + } + void write(mtpBuffer &to) const { + vlang_code.write(to); + } + + typedef MTPhelp_TermsOfService ResponseType; +}; +class MTPhelp_GetTermsOfService : public MTPBoxed { +public: + MTPhelp_GetTermsOfService() { + } + MTPhelp_GetTermsOfService(const MTPhelp_getTermsOfService &v) : MTPBoxed(v) { + } + MTPhelp_GetTermsOfService(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPhelp_GetTermsOfService(const MTPstring &_lang_code) : MTPBoxed(MTPhelp_getTermsOfService(_lang_code)) { + } +}; + class MTPchannels_getDialogs { // RPC method 'channels.getDialogs' public: MTPint voffset; @@ -23627,6 +23908,65 @@ inline MTPwallPaper MTP_wallPaperSolid(MTPint _id, const MTPstring &_title, MTPi return MTPwallPaper(new MTPDwallPaperSolid(_id, _title, _bg_color, _color)); } +inline uint32 MTPreportReason::innerLength() const { + switch (_type) { + case mtpc_inputReportReasonOther: { + const MTPDinputReportReasonOther &v(c_inputReportReasonOther()); + return v.vtext.innerLength(); + } + } + return 0; +} +inline mtpTypeId MTPreportReason::type() const { + if (!_type) throw mtpErrorUninitialized(); + return _type; +} +inline void MTPreportReason::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != _type) setData(0); + switch (cons) { + case mtpc_inputReportReasonSpam: _type = cons; break; + case mtpc_inputReportReasonViolence: _type = cons; break; + case mtpc_inputReportReasonPornography: _type = cons; break; + case mtpc_inputReportReasonOther: _type = cons; { + if (!data) setData(new MTPDinputReportReasonOther()); + MTPDinputReportReasonOther &v(_inputReportReasonOther()); + v.vtext.read(from, end); + } break; + default: throw mtpErrorUnexpected(cons, "MTPreportReason"); + } +} +inline void MTPreportReason::write(mtpBuffer &to) const { + switch (_type) { + case mtpc_inputReportReasonOther: { + const MTPDinputReportReasonOther &v(c_inputReportReasonOther()); + v.vtext.write(to); + } break; + } +} +inline MTPreportReason::MTPreportReason(mtpTypeId type) : mtpDataOwner(0), _type(type) { + switch (type) { + case mtpc_inputReportReasonSpam: break; + case mtpc_inputReportReasonViolence: break; + case mtpc_inputReportReasonPornography: break; + case mtpc_inputReportReasonOther: setData(new MTPDinputReportReasonOther()); break; + default: throw mtpErrorBadTypeId(type, "MTPreportReason"); + } +} +inline MTPreportReason::MTPreportReason(MTPDinputReportReasonOther *_data) : mtpDataOwner(_data), _type(mtpc_inputReportReasonOther) { +} +inline MTPreportReason MTP_inputReportReasonSpam() { + return MTPreportReason(mtpc_inputReportReasonSpam); +} +inline MTPreportReason MTP_inputReportReasonViolence() { + return MTPreportReason(mtpc_inputReportReasonViolence); +} +inline MTPreportReason MTP_inputReportReasonPornography() { + return MTPreportReason(mtpc_inputReportReasonPornography); +} +inline MTPreportReason MTP_inputReportReasonOther(const MTPstring &_text) { + return MTPreportReason(new MTPDinputReportReasonOther(_text)); +} + inline MTPuserFull::MTPuserFull() : mtpDataOwner(new MTPDuserFull()) { } @@ -24507,6 +24847,14 @@ inline uint32 MTPupdate::innerLength() const { const MTPDupdateChatParticipantAdmin &v(c_updateChatParticipantAdmin()); return v.vchat_id.innerLength() + v.vuser_id.innerLength() + v.vis_admin.innerLength() + v.vversion.innerLength(); } + case mtpc_updateNewStickerSet: { + const MTPDupdateNewStickerSet &v(c_updateNewStickerSet()); + return v.vstickerset.innerLength(); + } + case mtpc_updateStickerSetsOrder: { + const MTPDupdateStickerSetsOrder &v(c_updateStickerSetsOrder()); + return v.vorder.innerLength(); + } } return 0; } @@ -24764,6 +25112,17 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI v.vis_admin.read(from, end); v.vversion.read(from, end); } break; + case mtpc_updateNewStickerSet: _type = cons; { + if (!data) setData(new MTPDupdateNewStickerSet()); + MTPDupdateNewStickerSet &v(_updateNewStickerSet()); + v.vstickerset.read(from, end); + } break; + case mtpc_updateStickerSetsOrder: _type = cons; { + if (!data) setData(new MTPDupdateStickerSetsOrder()); + MTPDupdateStickerSetsOrder &v(_updateStickerSetsOrder()); + v.vorder.read(from, end); + } break; + case mtpc_updateStickerSets: _type = cons; break; default: throw mtpErrorUnexpected(cons, "MTPupdate"); } } @@ -24979,6 +25338,14 @@ inline void MTPupdate::write(mtpBuffer &to) const { v.vis_admin.write(to); v.vversion.write(to); } break; + case mtpc_updateNewStickerSet: { + const MTPDupdateNewStickerSet &v(c_updateNewStickerSet()); + v.vstickerset.write(to); + } break; + case mtpc_updateStickerSetsOrder: { + const MTPDupdateStickerSetsOrder &v(c_updateStickerSetsOrder()); + v.vorder.write(to); + } break; } } inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) { @@ -25020,6 +25387,9 @@ inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) { case mtpc_updateChannelMessageViews: setData(new MTPDupdateChannelMessageViews()); break; case mtpc_updateChatAdmins: setData(new MTPDupdateChatAdmins()); break; case mtpc_updateChatParticipantAdmin: setData(new MTPDupdateChatParticipantAdmin()); break; + case mtpc_updateNewStickerSet: setData(new MTPDupdateNewStickerSet()); break; + case mtpc_updateStickerSetsOrder: setData(new MTPDupdateStickerSetsOrder()); break; + case mtpc_updateStickerSets: break; default: throw mtpErrorBadTypeId(type, "MTPupdate"); } } @@ -25097,6 +25467,10 @@ inline MTPupdate::MTPupdate(MTPDupdateChatAdmins *_data) : mtpDataOwner(_data), } inline MTPupdate::MTPupdate(MTPDupdateChatParticipantAdmin *_data) : mtpDataOwner(_data), _type(mtpc_updateChatParticipantAdmin) { } +inline MTPupdate::MTPupdate(MTPDupdateNewStickerSet *_data) : mtpDataOwner(_data), _type(mtpc_updateNewStickerSet) { +} +inline MTPupdate::MTPupdate(MTPDupdateStickerSetsOrder *_data) : mtpDataOwner(_data), _type(mtpc_updateStickerSetsOrder) { +} inline MTPupdate MTP_updateNewMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count) { return MTPupdate(new MTPDupdateNewMessage(_message, _pts, _pts_count)); } @@ -25208,6 +25582,15 @@ inline MTPupdate MTP_updateChatAdmins(MTPint _chat_id, MTPBool _enabled, MTPint inline MTPupdate MTP_updateChatParticipantAdmin(MTPint _chat_id, MTPint _user_id, MTPBool _is_admin, MTPint _version) { return MTPupdate(new MTPDupdateChatParticipantAdmin(_chat_id, _user_id, _is_admin, _version)); } +inline MTPupdate MTP_updateNewStickerSet(const MTPmessages_StickerSet &_stickerset) { + return MTPupdate(new MTPDupdateNewStickerSet(_stickerset)); +} +inline MTPupdate MTP_updateStickerSetsOrder(const MTPVector &_order) { + return MTPupdate(new MTPDupdateStickerSetsOrder(_order)); +} +inline MTPupdate MTP_updateStickerSets() { + return MTPupdate(mtpc_updateStickerSets); +} inline MTPupdates_state::MTPupdates_state() : mtpDataOwner(new MTPDupdates_state()) { } @@ -27495,7 +27878,7 @@ inline MTPmessages_allStickers::MTPmessages_allStickers(MTPDmessages_allStickers inline MTPmessages_allStickers MTP_messages_allStickersNotModified() { return MTPmessages_allStickers(mtpc_messages_allStickersNotModified); } -inline MTPmessages_allStickers MTP_messages_allStickers(const MTPstring &_hash, const MTPVector &_sets) { +inline MTPmessages_allStickers MTP_messages_allStickers(MTPint _hash, const MTPVector &_sets) { return MTPmessages_allStickers(new MTPDmessages_allStickers(_hash, _sets)); } @@ -29383,6 +29766,33 @@ inline MTPchannels_channelParticipant MTP_channels_channelParticipant(const MTPC return MTPchannels_channelParticipant(new MTPDchannels_channelParticipant(_participant, _users)); } +inline MTPhelp_termsOfService::MTPhelp_termsOfService() : mtpDataOwner(new MTPDhelp_termsOfService()) { +} + +inline uint32 MTPhelp_termsOfService::innerLength() const { + const MTPDhelp_termsOfService &v(c_help_termsOfService()); + return v.vtext.innerLength(); +} +inline mtpTypeId MTPhelp_termsOfService::type() const { + return mtpc_help_termsOfService; +} +inline void MTPhelp_termsOfService::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_help_termsOfService) throw mtpErrorUnexpected(cons, "MTPhelp_termsOfService"); + + if (!data) setData(new MTPDhelp_termsOfService()); + MTPDhelp_termsOfService &v(_help_termsOfService()); + v.vtext.read(from, end); +} +inline void MTPhelp_termsOfService::write(mtpBuffer &to) const { + const MTPDhelp_termsOfService &v(c_help_termsOfService()); + v.vtext.write(to); +} +inline MTPhelp_termsOfService::MTPhelp_termsOfService(MTPDhelp_termsOfService *_data) : mtpDataOwner(_data) { +} +inline MTPhelp_termsOfService MTP_help_termsOfService(const MTPstring &_text) { + return MTPhelp_termsOfService(new MTPDhelp_termsOfService(_text)); +} + // Human-readable text serialization #if (defined _DEBUG || defined _WITH_DEBUG) diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl index ee1e796980..db9481ad04 100644 --- a/Telegram/SourceFiles/mtproto/scheme.tl +++ b/Telegram/SourceFiles/mtproto/scheme.tl @@ -305,6 +305,11 @@ peerNotifySettings#8d5e11ee mute_until:int sound:string show_previews:Bool event wallPaper#ccb03657 id:int title:string sizes:Vector color:int = WallPaper; wallPaperSolid#63117f24 id:int title:string bg_color:int color:int = WallPaper; +inputReportReasonSpam#58dbcab8 = ReportReason; +inputReportReasonViolence#1e22c78d = ReportReason; +inputReportReasonPornography#2e59d922 = ReportReason; +inputReportReasonOther#e1746d0a text:string = ReportReason; + userFull#5a89ac5b user:User link:contacts.Link profile_photo:Photo notify_settings:PeerNotifySettings blocked:Bool bot_info:BotInfo = UserFull; contact#f911c994 user_id:int mutual:Bool = Contact; @@ -389,6 +394,9 @@ updateDeleteChannelMessages#c37521c9 channel_id:int messages:Vector pts:int updateChannelMessageViews#98a12b4b channel_id:int id:int views:int = Update; updateChatAdmins#6e947941 chat_id:int enabled:Bool version:int = Update; updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool version:int = Update; +updateNewStickerSet#688a30aa stickerset:messages.StickerSet = Update; +updateStickerSetsOrder#f0dfb451 order:Vector = Update; +updateStickerSets#43ae3dec = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -516,7 +524,7 @@ messages.stickers#8a8ecd32 hash:string stickers:Vector = messages.Stic stickerPack#12b299d4 emoticon:string documents:Vector = StickerPack; messages.allStickersNotModified#e86602c3 = messages.AllStickers; -messages.allStickers#d51dafdb hash:string sets:Vector = messages.AllStickers; +messages.allStickers#edfd405f hash:int sets:Vector = messages.AllStickers; disabledFeature#ae636f24 feature:string description:string = DisabledFeature; @@ -625,6 +633,8 @@ channels.channelParticipants#f56ee2a8 count:int participants:Vector = channels.ChannelParticipant; +help.termsOfService#f1ee3e90 text:string = help.TermsOfService; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -658,6 +668,7 @@ account.resetNotifySettings#db7e1747 = Bool; account.updateProfile#f0888d68 first_name:string last_name:string = User; account.updateStatus#6628562c offline:Bool = Bool; account.getWallPapers#c04cfac2 = Vector; +account.reportPeer#ae189d5f peer:InputPeer reason:ReportReason = Bool; account.checkUsername#2714d86c username:string = Bool; account.updateUsername#3e0bdd7c username:string = User; account.getPrivacy#dadbc950 key:InputPrivacyKey = account.PrivacyRules; @@ -725,7 +736,7 @@ messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long da messages.receivedQueue#55a5bb66 max_qts:int = Vector; messages.readMessageContents#36a73f77 id:Vector = messages.AffectedMessages; messages.getStickers#ae22e045 emoticon:string hash:string = messages.Stickers; -messages.getAllStickers#aa3bc868 hash:string = messages.AllStickers; +messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers; messages.getWebPagePreview#25223e24 message:string = MessageMedia; messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite; messages.checkChatInvite#3eadb1bb hash:string = ChatInvite; @@ -739,6 +750,7 @@ messages.toggleChatAdmins#ec8bd9e1 chat_id:int enabled:Bool = Updates; messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool; messages.migrateChat#15a3b8e3 chat_id:int = Updates; messages.searchGlobal#9e3cacb0 q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; +messages.reorderStickerSets#9fcfbc30 order:Vector = Bool; updates.getState#edd4882a = updates.State; updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference; @@ -760,6 +772,7 @@ help.saveAppLog#6f02f748 events:Vector = Bool; help.getInviteText#a4a95186 lang_code:string = help.InviteText; help.getSupport#9cdf08cd = help.Support; help.getAppChangelog#5bab7fb2 device_model:string system_version:string app_version:string lang_code:string = help.AppChangelog; +help.getTermsOfService#37d78f83 lang_code:string = help.TermsOfService; channels.getDialogs#a9d3d249 offset:int limit:int = messages.Dialogs; channels.getImportantHistory#ddb929cb channel:InputChannel offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages; diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index 54daae714f..c4b8d69947 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -104,7 +104,7 @@ RecentEmojiPack gRecentEmojis; RecentEmojisPreload gRecentEmojisPreload; EmojiColorVariants gEmojiVariants; -QByteArray gStickersHash; +int32 gStickersHash = 0; RecentStickerPreload gRecentStickersPreload; RecentStickerPack gRecentStickers; diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h index 4c0267edc7..02f401e5e3 100644 --- a/Telegram/SourceFiles/settings.h +++ b/Telegram/SourceFiles/settings.h @@ -195,7 +195,7 @@ RecentEmojiPack &cGetRecentEmojis(); struct DocumentData; typedef QVector StickerPack; -DeclareSetting(QByteArray, StickersHash); +DeclareSetting(int32, StickersHash); typedef QList > RecentStickerPackOld; typedef QVector > RecentStickerPreload; diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp index 4b3b8264a2..a68ea35541 100644 --- a/Telegram/SourceFiles/settingswidget.cpp +++ b/Telegram/SourceFiles/settingswidget.cpp @@ -38,6 +38,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "boxes/passcodebox.h" #include "boxes/autolockbox.h" #include "boxes/sessionsbox.h" +#include "boxes/stickersetbox.h" #include "langloaderplain.h" #include "gui/filedialog.h" @@ -156,6 +157,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), // chat options _replaceEmojis(this, lang(lng_settings_replace_emojis), cReplaceEmojis()), _viewEmojis(this, lang(lng_settings_view_emojis)), + _stickers(this, lang(lng_stickers_you_have)), _enterSend(this, qsl("send_key"), 0, lang(lng_settings_send_enter), !cCtrlEnter()), _ctrlEnterSend(this, qsl("send_key"), 1, lang((cPlatform() == dbipMac) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), cCtrlEnter()), @@ -269,6 +271,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), // chat options connect(&_replaceEmojis, SIGNAL(changed()), this, SLOT(onReplaceEmojis())); connect(&_viewEmojis, SIGNAL(clicked()), this, SLOT(onViewEmojis())); + connect(&_stickers, SIGNAL(clicked()), this, SLOT(onStickers())); connect(&_enterSend, SIGNAL(changed()), this, SLOT(onEnterSend())); connect(&_ctrlEnterSend, SIGNAL(changed()), this, SLOT(onCtrlEnterSend())); @@ -515,7 +518,8 @@ void SettingsInner::paintEvent(QPaintEvent *e) { p.drawText(_left + st::setHeaderLeft, top + st::setHeaderTop + st::setHeaderFont->ascent, lang(lng_settings_section_chat)); top += st::setHeaderSkip; - top += _replaceEmojis.height() + st::setSectionSkip; + top += _replaceEmojis.height() + st::setLittleSkip; + top += _stickers.height() + st::setSectionSkip; top += _enterSend.height() + st::setLittleSkip; top += _ctrlEnterSend.height() + st::setSectionSkip; @@ -706,7 +710,8 @@ void SettingsInner::resizeEvent(QResizeEvent *e) { if (self()) { top += st::setHeaderSkip; _viewEmojis.move(_left + st::setWidth - _viewEmojis.width(), top + st::cbDefFlat.textTop); - _replaceEmojis.move(_left, top); top += _replaceEmojis.height() + st::setSectionSkip; + _replaceEmojis.move(_left, top); top += _replaceEmojis.height() + st::setLittleSkip; + _stickers.move(_left + st::cbDefFlat.textLeft, top); top += _stickers.height() + st::setSectionSkip; _enterSend.move(_left, top); top += _enterSend.height() + st::setLittleSkip; _ctrlEnterSend.move(_left, top); top += _ctrlEnterSend.height() + st::setSectionSkip; _dontAskDownloadPath.move(_left, top); top += _dontAskDownloadPath.height(); @@ -1040,6 +1045,7 @@ void SettingsInner::showAll() { } else { _viewEmojis.hide(); } + _stickers.show(); _enterSend.show(); _ctrlEnterSend.show(); _dontAskDownloadPath.show(); @@ -1058,6 +1064,7 @@ void SettingsInner::showAll() { } else { _replaceEmojis.hide(); _viewEmojis.hide(); + _stickers.hide(); _enterSend.hide(); _ctrlEnterSend.hide(); _dontAskDownloadPath.hide(); @@ -1521,7 +1528,11 @@ void SettingsInner::onReplaceEmojis() { } void SettingsInner::onViewEmojis() { - App::wnd()->showLayer(new EmojiBox()); + App::showLayer(new EmojiBox()); +} + +void SettingsInner::onStickers() { + App::showLayer(new StickersBox()); } void SettingsInner::onEnterSend() { diff --git a/Telegram/SourceFiles/settingswidget.h b/Telegram/SourceFiles/settingswidget.h index 234d1563d0..08092e1e06 100644 --- a/Telegram/SourceFiles/settingswidget.h +++ b/Telegram/SourceFiles/settingswidget.h @@ -138,6 +138,7 @@ public slots: void onReplaceEmojis(); void onViewEmojis(); + void onStickers(); void onEnterSend(); void onCtrlEnterSend(); @@ -242,7 +243,7 @@ private: // chat options FlatCheckbox _replaceEmojis; - LinkButton _viewEmojis; + LinkButton _viewEmojis, _stickers; FlatRadiobutton _enterSend, _ctrlEnterSend; FlatCheckbox _dontAskDownloadPath; int32 _downloadPathWidth; diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 4731fd57e0..b7c3bfed0a 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -807,12 +807,15 @@ void AudioCancelLink::onClick(Qt::MouseButton button) const { bool StickerData::setInstalled() const { switch (set.type()) { case mtpc_inputStickerSetID: { - return (cStickerSets().constFind(set.c_inputStickerSetID().vid.v) != cStickerSets().cend()); + StickerSets::const_iterator it = cStickerSets().constFind(set.c_inputStickerSetID().vid.v); + return (it != cStickerSets().cend()) && !(it->flags & MTPDstickerSet::flag_disabled); } break; case mtpc_inputStickerSetShortName: { QString name = qs(set.c_inputStickerSetShortName().vshort_name).toLower(); - for (StickerSets::const_iterator i = cStickerSets().cbegin(), e = cStickerSets().cend(); i != e; ++i) { - if (i->shortName.toLower() == name) return true; + for (StickerSets::const_iterator it = cStickerSets().cbegin(), e = cStickerSets().cend(); it != e; ++it) { + if (it->shortName.toLower() == name) { + return !(it->flags & MTPDstickerSet::flag_disabled); + } } } break; }