From c786a2bf9cf8277a1418c11f6e429b6cd7365d06 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 17 Jul 2015 22:17:37 +0300 Subject: [PATCH] new history loading (one-request loading always), fixed audio unlistened status on media send, fixed flac playing, fixed os x crashes, version 0.8.40.dev --- MSVC.md | 2 +- QTCREATOR.md | 2 +- Telegram/PrepareWin.bat | 8 +- Telegram/SourceFiles/application.cpp | 4 +- Telegram/SourceFiles/audio.cpp | 2 + Telegram/SourceFiles/boxes/addcontactbox.cpp | 2 +- Telegram/SourceFiles/boxes/contactsbox.cpp | 8 +- Telegram/SourceFiles/config.h | 4 +- Telegram/SourceFiles/dialogswidget.cpp | 36 +- Telegram/SourceFiles/dialogswidget.h | 2 - Telegram/SourceFiles/gui/scrollarea.cpp | 27 +- Telegram/SourceFiles/gui/scrollarea.h | 1 + Telegram/SourceFiles/gui/twidget.cpp | 12 +- Telegram/SourceFiles/gui/twidget.h | 1 + Telegram/SourceFiles/history.cpp | 116 +- Telegram/SourceFiles/history.h | 8 +- Telegram/SourceFiles/historywidget.cpp | 1393 ++++++++---------- Telegram/SourceFiles/historywidget.h | 64 +- Telegram/SourceFiles/mainwidget.cpp | 351 ++--- Telegram/SourceFiles/mainwidget.h | 27 +- Telegram/SourceFiles/mediaview.cpp | 2 +- Telegram/SourceFiles/overviewwidget.cpp | 2 +- Telegram/SourceFiles/profilewidget.cpp | 10 +- Telegram/SourceFiles/pspecific_mac.cpp | 2 +- Telegram/SourceFiles/structs.cpp | 2 +- Telegram/SourceFiles/structs.h | 3 + Telegram/SourceFiles/window.cpp | 2 +- Telegram/Telegram.plist | 2 +- Telegram/Telegram.rc | Bin 5540 -> 5540 bytes Telegram/Telegram.xcodeproj/project.pbxproj | 12 +- Telegram/Version.sh | 2 +- XCODE.md | 2 +- 32 files changed, 1014 insertions(+), 1097 deletions(-) diff --git a/MSVC.md b/MSVC.md index d73c9e671..395c4ebdf 100644 --- a/MSVC.md +++ b/MSVC.md @@ -134,7 +134,7 @@ Open **VS2013 x86 Native Tools Command Prompt.bat** (should be in **\\Program Fi PKG_CONFIG_PATH="/mingw64/lib/pkgconfig:$PKG_CONFIG_PATH" - ./configure --toolchain=msvc --disable-programs --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=wavpack --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-encoder=libopus --enable-parser=aac --enable-parser=aac_latm --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-demuxer=aac --enable-demuxer=wav --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=mov --enable-muxer=ogg --enable-muxer=opus --extra-ldflags="-libpath:/d/TBuild/Libraries/opus/win32/VS2010/Win32/Release celt.lib silk_common.lib silk_float.lib" + ./configure --toolchain=msvc --disable-programs --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=wavpack --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-decoder=flac --enable-encoder=libopus --enable-parser=aac --enable-parser=aac_latm --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-parser=flac --enable-demuxer=aac --enable-demuxer=wav --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=mov --enable-demuxer=flac --enable-muxer=ogg --enable-muxer=opus --extra-ldflags="-libpath:/d/TBuild/Libraries/opus/win32/VS2010/Win32/Release celt.lib silk_common.lib silk_float.lib" make make install diff --git a/QTCREATOR.md b/QTCREATOR.md index dc15b0cf5..20d7a9fb0 100644 --- a/QTCREATOR.md +++ b/QTCREATOR.md @@ -50,7 +50,7 @@ Download sources [ffmpeg-2.6.3.tar.bz2](http://ffmpeg.org/releases/ffmpeg-2.6.3. sudo apt-get -y --force-yes install autoconf automake build-essential libass-dev libfreetype6-dev libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texi2html zlib1g-dev sudo apt-get install yasm - ./configure --prefix=/usr/local --disable-programs --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=wavpack --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-encoder=libopus --enable-parser=aac --enable-parser=aac_latm --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-demuxer=aac --enable-demuxer=wav --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=mov --enable-muxer=ogg --enable-muxer=opus + ./configure --prefix=/usr/local --disable-programs --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=wavpack --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-decoder=flac --enable-encoder=libopus --enable-parser=aac --enable-parser=aac_latm --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-parser=flac --enable-demuxer=aac --enable-demuxer=wav --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=mov --enable-demuxer=flac --enable-muxer=ogg --enable-muxer=opus make sudo make install diff --git a/Telegram/PrepareWin.bat b/Telegram/PrepareWin.bat index b0eee4e0f..1ea544eb8 100644 --- a/Telegram/PrepareWin.bat +++ b/Telegram/PrepareWin.bat @@ -1,10 +1,10 @@ @echo OFF set "AppVersionStrMajor=0.8" -set "AppVersion=8039" -set "AppVersionStrSmall=0.8.39" -set "AppVersionStr=0.8.39" -set "AppVersionStrFull=0.8.39.0" +set "AppVersion=8040" +set "AppVersionStrSmall=0.8.40" +set "AppVersionStr=0.8.40" +set "AppVersionStrFull=0.8.40.0" set "DevChannel=1" if %DevChannel% neq 0 goto preparedev diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 76e8a4bc1..e6665a0b8 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -654,8 +654,8 @@ void Application::checkMapVersion() { psRegisterCustomScheme(); if (Local::oldMapVersion()) { QString versionFeatures; - if (DevChannel && Local::oldMapVersion() < 8039) { - versionFeatures = QString::fromUtf8("\xe2\x80\x94 Moved to Qt 5.5\n\xe2\x80\x94 Some bugfixes and optimizations\n\xe2\x80\x94 In OS X 10.10.3 location marks sent from mobile should be displayed now");// .replace('@', qsl("@") + QChar(0x200D)); + if (DevChannel && Local::oldMapVersion() < 8040) { + versionFeatures = QString::fromUtf8("\xe2\x80\x94 Fixed critical Qt bug in image scale\n\xe2\x80\x94 Huge amount of unread messages are loaded much faster\n\xe2\x80\x94 Flac audio files are played in-app\n\xe2\x80\x94 Some bugfixes and optimizations");// .replace('@', qsl("@") + QChar(0x200D)); } else if (!DevChannel && Local::oldMapVersion() < 8038) { versionFeatures = lang(lng_new_version_text).trimmed(); } diff --git a/Telegram/SourceFiles/audio.cpp b/Telegram/SourceFiles/audio.cpp index ac7988a17..407d3a1af 100644 --- a/Telegram/SourceFiles/audio.cpp +++ b/Telegram/SourceFiles/audio.cpp @@ -1072,6 +1072,8 @@ public: int res = 0; char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; if ((res = avformat_open_input(&fmtContext, 0, 0, 0)) < 0) { + ioBuffer = 0; + LOG(("Audio Error: Unable to avformat_open_input for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); return false; } diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp index 7f65d428b..75353e55e 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.cpp +++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp @@ -285,7 +285,7 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) { } if (uid) { App::main()->addNewContact(uid); - App::main()->showPeer(App::peerFromUser(uid)); + App::main()->choosePeer(App::peerFromUser(uid), ShowAtUnreadMsgId); App::wnd()->hideLayer(); } else { _addButton.hide(); diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp index 4ade8efa1..311b26b6b 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.cpp +++ b/Telegram/SourceFiles/boxes/contactsbox.cpp @@ -96,7 +96,7 @@ void ContactsInner::onAddBot() { MTP::send(MTPmessages_StartBot(_bot->inputUser, MTP_int(App::chatFromPeer(_addToChat->id)), MTP_long(randomId), MTP_string(_bot->botInfo->startGroupToken)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, _bot)); App::wnd()->hideLayer(); - App::main()->showPeer(_addToChat->id, 0, false); + App::main()->showPeerHistory(_addToChat->id, ShowAtUnreadMsgId); } else { App::main()->addParticipants(_addToChat, QVector(1, _bot)); } @@ -461,7 +461,7 @@ void ContactsInner::chooseParticipant() { App::wnd()->replaceLayer(box); } else { App::wnd()->hideSettings(true); - App::main()->showPeer(peer->id, 0, false, true); + App::main()->choosePeer(peer->id, ShowAtUnreadMsgId); App::wnd()->hideLayer(); } } @@ -1149,7 +1149,7 @@ void ContactsBox::onNext() { _filter.setFocus(); _filter.notaBene(); } else if (v.size() == 1) { - App::main()->showPeer(_inner.selectedUser()->id); + App::main()->showPeerHistory(_inner.selectedUser()->id, ShowAtUnreadMsgId); } else { App::wnd()->replaceLayer(new CreateGroupBox(users)); } @@ -1258,7 +1258,7 @@ void CreateGroupBox::created(const MTPUpdates &updates) { } break; } if (v && !v->isEmpty() && v->front().type() == mtpc_chat) { - App::main()->showPeer(App::peerFromChat(v->front().c_chat().vid.v)); + App::main()->choosePeer(App::peerFromChat(v->front().c_chat().vid.v), ShowAtUnreadMsgId); } } diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 336274926..98268bf6d 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -static const int32 AppVersion = 8039; -static const wchar_t *AppVersionStr = L"0.8.39"; +static const int32 AppVersion = 8040; +static const wchar_t *AppVersionStr = L"0.8.40"; static const bool DevChannel = true; static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)"; diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index b346267d1..8ae54f92e 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -1094,7 +1094,7 @@ void DialogsListWidget::loadPeerPhotos(int32 yFrom) { bool DialogsListWidget::choosePeer() { History *history = 0; - MsgId msgId = 0; + MsgId msgId = ShowAtUnreadMsgId; if (_state == DefaultState) { if (sel) history = sel->history; } else if (_state == FilteredState || _state == SearchedState) { @@ -1133,11 +1133,11 @@ bool DialogsListWidget::choosePeer() { } } if (history) { - if (msgId) { + if (msgId > 0) { saveRecentHashtags(filter); } bool chosen = (!App::main()->selectingPeer(true) && (_state == FilteredState || _state == SearchedState) && filteredSel >= 0 && filteredSel < filterResults.size()); - App::main()->showPeer(history->peer->id, msgId); + App::main()->choosePeer(history->peer->id, msgId); if (chosen) { emit searchResultChosen(); } @@ -1204,11 +1204,11 @@ void DialogsListWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData } if (i.value()->prev) { outPeer = i.value()->prev->history->peer; - outMsg = 0; + outMsg = ShowAtUnreadMsgId; return; } else if (dialogs.list.count) { outPeer = dialogs.list.end->prev->history->peer; - outMsg = 0; + outMsg = ShowAtUnreadMsgId; return; } outPeer = 0; @@ -1217,7 +1217,7 @@ void DialogsListWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData } if (i.value()->prev) { outPeer = i.value()->prev->history->peer; - outMsg = 0; + outMsg = ShowAtUnreadMsgId; return; } } else if (_state == FilteredState || _state == SearchedState) { @@ -1231,7 +1231,7 @@ void DialogsListWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData } } if (searchResults.at(0)->_item->history()->peer == inPeer && searchResults.at(0)->_item->id == inMsg) { - outMsg = 0; + outMsg = ShowAtUnreadMsgId; if (peopleResults.isEmpty()) { if (filterResults.isEmpty()) { outPeer = 0; @@ -1246,14 +1246,14 @@ void DialogsListWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData } if (!peopleResults.isEmpty() && peopleResults.at(0) == inPeer) { outPeer = filterResults.isEmpty() ? 0 : filterResults.back()->history->peer; - outMsg = 0; + outMsg = ShowAtUnreadMsgId; return; } if (!peopleResults.isEmpty()) { for (PeopleResults::const_iterator b = peopleResults.cbegin(), i = b + 1, e = peopleResults.cend(); i != e; ++i) { if ((*i) == inPeer) { outPeer = (*(i - 1)); - outMsg = 0; + outMsg = ShowAtUnreadMsgId; return; } } @@ -1267,7 +1267,7 @@ void DialogsListWidget::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData for (FilteredDialogs::const_iterator b = filterResults.cbegin(), i = b + 1, e = filterResults.cend(); i != e; ++i) { if ((*i)->history->peer == inPeer) { outPeer = (*(i - 1))->history->peer; - outMsg = 0; + outMsg = ShowAtUnreadMsgId; return; } } @@ -1288,7 +1288,7 @@ void DialogsListWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData } if (i.value()->next != contactsNoDialogs.list.end) { outPeer = i.value()->next->history->peer; - outMsg = 0; + outMsg = ShowAtUnreadMsgId; return; } outPeer = 0; @@ -1298,11 +1298,11 @@ void DialogsListWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData if (i.value()->next != dialogs.list.end) { outPeer = i.value()->next->history->peer; - outMsg = 0; + outMsg = ShowAtUnreadMsgId; return; } else if (contactsNoDialogs.list.count) { outPeer = contactsNoDialogs.list.begin->history->peer; - outMsg = 0; + outMsg = ShowAtUnreadMsgId; return; } } else if (_state == FilteredState || _state == SearchedState) { @@ -1324,7 +1324,7 @@ void DialogsListWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData outMsg = searchResults.front()->_item->id; } else { outPeer = (i == e) ? 0 : (*i); - outMsg = 0; + outMsg = ShowAtUnreadMsgId; } return; } @@ -1334,13 +1334,13 @@ void DialogsListWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData ++i; if (i == e && !peopleResults.isEmpty()) { outPeer = peopleResults.front(); - outMsg = 0; + outMsg = ShowAtUnreadMsgId; } else if (i == e && !searchResults.isEmpty()) { outPeer = searchResults.front()->_item->history()->peer; outMsg = searchResults.front()->_item->id; } else { outPeer = (i == e) ? 0 : (*i)->history->peer; - outMsg = 0; + outMsg = ShowAtUnreadMsgId; } return; } @@ -1454,10 +1454,6 @@ void DialogsWidget::dialogsToUp() { } } -void DialogsWidget::setInnerFocus() { - _filter.setFocus(); -} - void DialogsWidget::animShow(const QPixmap &bgAnimCache) { _bgAnimCache = bgAnimCache; _animCache = myGrab(this, rect()); diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 1d1cf6661..922f2a813 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -193,8 +193,6 @@ public: void animShow(const QPixmap &bgAnimCache); bool animStep(float64 ms); - void setInnerFocus(); - void destroyData(); void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const; diff --git a/Telegram/SourceFiles/gui/scrollarea.cpp b/Telegram/SourceFiles/gui/scrollarea.cpp index d7ecbceec..dbca10ff9 100644 --- a/Telegram/SourceFiles/gui/scrollarea.cpp +++ b/Telegram/SourceFiles/gui/scrollarea.cpp @@ -47,7 +47,7 @@ ScrollBar::ScrollBar(ScrollArea *parent, bool vert, const style::flatScroll *st) _hideTimer.setSingleShot(true); connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(onHideTimer())); - connect(_connected, SIGNAL(valueChanged(int)), this, SLOT(updateBar())); + connect(_connected, SIGNAL(valueChanged(int)), this, SLOT(onValueChanged())); connect(_connected, SIGNAL(rangeChanged(int, int)), this, SLOT(updateBar())); updateBar(); @@ -57,6 +57,11 @@ void ScrollBar::recountSize() { setGeometry(_vertical ? QRect(rtl() ? 0 : (_area->width() - _st->width), _st->deltat, _st->width, _area->height() - _st->deltat - _st->deltab) : QRect(_st->deltat, _area->height() - _st->width, _area->width() - _st->deltat - _st->deltab, _st->width)); } +void ScrollBar::onValueChanged() { + _area->onScrolled(); + updateBar(); +} + void ScrollBar::updateBar(bool force) { QRect newBar; if (_connected->maximum() != _scrollMax) { @@ -266,8 +271,6 @@ _touchScrollState(TouchScrollManual), _touchPrevPosValid(false), _touchWaitingAc _touchSpeedTime(0), _touchAccelerationTime(0), _touchTime(0), _widgetAcceptsTouch(false) { setLayoutDirection(cLangDir()); - connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(onScrolled())); - connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(onScrolled())); connect(&vert, SIGNAL(topShadowVisibility(bool)), &topSh, SLOT(changeVisibility(bool))); connect(&vert, SIGNAL(bottomShadowVisibility(bool)), &bottomSh, SLOT(changeVisibility(bool))); vert.updateBar(true); @@ -297,6 +300,8 @@ void ScrollArea::touchDeaccelerate(int32 elapsed) { } void ScrollArea::onScrolled() { + myEnsureResized(widget()); + bool em = false; int32 horValue = horizontalScrollBar()->value(), vertValue = verticalScrollBar()->value(); if (_horValue != horValue) { @@ -325,27 +330,29 @@ void ScrollArea::onScrolled() { } int ScrollArea::scrollWidth() const { - return scrollLeftMax() + width(); + QWidget *w(widget()); + return w ? qMax(w->width(), width()) : width(); } int ScrollArea::scrollHeight() const { - return scrollTopMax() + height(); + QWidget *w(widget()); + return w ? qMax(w->height(), height()) : height(); } int ScrollArea::scrollLeftMax() const { - return horizontalScrollBar()->maximum(); + return scrollWidth() - width(); } int ScrollArea::scrollTopMax() const { - return verticalScrollBar()->maximum(); + return scrollHeight() - height(); } int ScrollArea::scrollLeft() const { - return horizontalScrollBar()->value(); + return _horValue; } int ScrollArea::scrollTop() const { - return verticalScrollBar()->value(); + return _vertValue; } void ScrollArea::onTouchTimer() { @@ -612,6 +619,8 @@ void ScrollArea::leaveEvent(QEvent *e) { } void ScrollArea::scrollToY(int toTop, int toBottom) { + myEnsureResized(widget()); + int toMin = 0, toMax = scrollTopMax(); if (toTop < toMin) { toTop = toMin; diff --git a/Telegram/SourceFiles/gui/scrollarea.h b/Telegram/SourceFiles/gui/scrollarea.h index 5408d52a5..e88f5e9b1 100644 --- a/Telegram/SourceFiles/gui/scrollarea.h +++ b/Telegram/SourceFiles/gui/scrollarea.h @@ -70,6 +70,7 @@ public: public slots: + void onValueChanged(); void updateBar(bool force = false); void onHideTimer(); diff --git a/Telegram/SourceFiles/gui/twidget.cpp b/Telegram/SourceFiles/gui/twidget.cpp index 7cbcf90d1..8583ccba6 100644 --- a/Telegram/SourceFiles/gui/twidget.cpp +++ b/Telegram/SourceFiles/gui/twidget.cpp @@ -34,12 +34,16 @@ namespace { } } +void myEnsureResized(QWidget *target) { + if (target && (target->testAttribute(Qt::WA_PendingResizeEvent) || !target->testAttribute(Qt::WA_WState_Created))) { + _sendResizeEvents(target); + } +} + QPixmap myGrab(QWidget *target, const QRect &rect) { if (!cRetina()) return target->grab(rect); - - if (target->testAttribute(Qt::WA_PendingResizeEvent) || !target->testAttribute(Qt::WA_WState_Created)) { - _sendResizeEvents(target); - } + + myEnsureResized(target); qreal dpr = App::app()->devicePixelRatio(); QPixmap result(rect.size() * dpr); diff --git a/Telegram/SourceFiles/gui/twidget.h b/Telegram/SourceFiles/gui/twidget.h index 36da53381..b79f824e4 100644 --- a/Telegram/SourceFiles/gui/twidget.h +++ b/Telegram/SourceFiles/gui/twidget.h @@ -174,4 +174,5 @@ private: }; +void myEnsureResized(QWidget *target); QPixmap myGrab(QWidget *target, const QRect &rect); diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 09d8c204a..1157f1391 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -305,10 +305,10 @@ History::History(const PeerId &peerId) : width(0), height(0) , oldLoaded(false) , newLoaded(true) , lastMsg(0) -, activeMsgId(0) , draftToId(0) , lastWidth(0) , lastScrollTop(History::ScrollMax) +, lastShowAtMsgId(ShowAtUnreadMsgId) , mute(isNotifyMuted(peer->notify)) , lastKeyboardInited(false) , lastKeyboardUsed(false) @@ -1010,7 +1010,7 @@ void History::addToFront(const QVector &slice) { block->height += dayItem->resize(width); } if (block->size()) { - if (wasMsgCount < unreadCount && msgCount >= unreadCount && !activeMsgId) { + if (loadedAtBottom() && wasMsgCount < unreadCount && msgCount >= unreadCount) { for (int32 i = block->size(); i > 0; --i) { if ((*block)[i - 1]->itemType() == HistoryItem::MsgType) { ++wasMsgCount; @@ -1233,6 +1233,7 @@ void History::inboxRead(int32 upTo) { if (!dialogs.isEmpty()) { if (App::main()) App::main()->dlgUpdated(dialogs[0]); } + showFrom = 0; App::wnd()->notifyClear(this); clearNotifications(); } @@ -1254,7 +1255,7 @@ void History::outboxRead(HistoryItem *wasRead) { void History::setUnreadCount(int32 newUnreadCount, bool psUpdate) { if (unreadCount != newUnreadCount) { - if (!unreadCount && newUnreadCount == 1 && loadedAtBottom()) { + if (newUnreadCount == 1 && loadedAtBottom()) { showFrom = isEmpty() ? 0 : back()->back(); } else if (!newUnreadCount) { showFrom = 0; @@ -1283,10 +1284,6 @@ void History::setMsgCount(int32 newMsgCount) { } void History::getNextShowFrom(HistoryBlock *block, int32 i) { - if (!loadedAtBottom()) { - showFrom = 0; - return; - } if (i >= 0) { int32 l = block->size(); for (++i; i < l; ++i) { @@ -1313,7 +1310,7 @@ void History::getNextShowFrom(HistoryBlock *block, int32 i) { } void History::addUnreadBar() { - if (unreadBar || !showFrom || !unreadCount || !loadedAtBottom()) return; + if (unreadBar || !showFrom || showFrom->detached() || !unreadCount) return; HistoryBlock *block = showFrom->block(); int32 i = block->indexOf(showFrom); @@ -1341,10 +1338,6 @@ void History::clearNotifications() { notifies.clear(); } -bool History::readyForWork() const { - return activeMsgId ? !isEmpty() : (unreadCount <= msgCount); -} - bool History::loadedAtBottom() const { return newLoaded; } @@ -1353,6 +1346,28 @@ bool History::loadedAtTop() const { return oldLoaded; } +bool History::isReadyFor(MsgId msgId, bool check) const { + if (msgId == ShowAtTheEndMsgId) { + return loadedAtBottom(); + } else if (msgId == ShowAtUnreadMsgId) { + return check ? (loadedAtBottom() && (msgCount >= unreadCount)) : !isEmpty(); + } else if (check) { + HistoryItem *item = App::histItemById(msgId); + return item && item->history() == this && !item->detached(); + } + return !isEmpty(); +} + +void History::getReadyFor(MsgId msgId) { + if (!isReadyFor(msgId, true)) { + clear(true); + newLoaded = (msgId == ShowAtTheEndMsgId) || (lastMsg && !lastMsg->detached()); + oldLoaded = false; + lastWidth = 0; + lastShowAtMsgId = msgId; + } +} + void History::fixLastMessage(bool wasAtBottom) { if (wasAtBottom && isEmpty()) { wasAtBottom = false; @@ -1367,37 +1382,6 @@ void History::fixLastMessage(bool wasAtBottom) { } } -void History::loadAround(MsgId msgId) { - if (activeMsgId != msgId) { - activeMsgId = msgId; - lastWidth = 0; - if (activeMsgId) { - HistoryItem *item = App::histItemById(activeMsgId); - if (!item || !item->block()) { - clear(true); - } - newLoaded = lastMsg && !lastMsg->detached(); - } else { - if (!loadedAtBottom()) { - clear(true); - } - newLoaded = isEmpty() || (lastMsg && !lastMsg->detached()); - } - } -} - -bool History::canShowAround(MsgId msgId) const { - if (activeMsgId != msgId) { - if (msgId) { - HistoryItem *item = App::histItemById(msgId); - return item && item->block(); - } else { - return loadedAtBottom(); - } - } - return true; -} - MsgId History::minMsgId() const { for (const_iterator i = cbegin(), e = cend(); i != e; ++i) { for (HistoryBlock::const_iterator j = (*i)->cbegin(), en = (*i)->cend(); j != en; ++j) { @@ -5184,18 +5168,16 @@ void HistoryMessage::setMedia(const MTPmessageMedia &media) { void HistoryMessage::draw(QPainter &p, uint32 selection) const { textstyleSet(&(out() ? st::outTextStyle : st::inTextStyle)); - if (id == _history->activeMsgId) { - uint64 ms = App::main() ? App::main()->animActiveTime() : 0; - if (ms) { - if (ms > st::activeFadeInDuration + st::activeFadeOutDuration) { - App::main()->stopAnimActive(); - } else { - float64 dt = (ms > st::activeFadeInDuration) ? (1 - (ms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (ms / float64(st::activeFadeInDuration)); - float64 o = p.opacity(); - p.setOpacity(o * dt); - p.fillRect(0, 0, _history->width, _height, textstyleCurrent()->selectOverlay->b); - p.setOpacity(o); - } + uint64 ms = App::main() ? App::main()->animActiveTime(id) : 0; + if (ms) { + if (ms > st::activeFadeInDuration + st::activeFadeOutDuration) { + App::main()->stopAnimActive(); + } else { + float64 dt = (ms > st::activeFadeInDuration) ? (1 - (ms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (ms / float64(st::activeFadeInDuration)); + float64 o = p.opacity(); + p.setOpacity(o * dt); + p.fillRect(0, 0, _history->width, _height, textstyleCurrent()->selectOverlay->b); + p.setOpacity(o); } } @@ -6108,19 +6090,17 @@ QString HistoryServiceMsg::inReplyText() const { } void HistoryServiceMsg::draw(QPainter &p, uint32 selection) const { - if (id == _history->activeMsgId) { - uint64 ms = App::main() ? App::main()->animActiveTime() : 0; - if (ms) { - if (ms > st::activeFadeInDuration + st::activeFadeOutDuration) { - App::main()->stopAnimActive(); - } else { - textstyleSet(&st::inTextStyle); - float64 dt = (ms > st::activeFadeInDuration) ? (1 - (ms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (ms / float64(st::activeFadeInDuration)); - float64 o = p.opacity(); - p.setOpacity(o * dt); - p.fillRect(0, 0, _history->width, _height, textstyleCurrent()->selectOverlay->b); - p.setOpacity(o); - } + uint64 ms = App::main() ? App::main()->animActiveTime(id) : 0; + if (ms) { + if (ms > st::activeFadeInDuration + st::activeFadeOutDuration) { + App::main()->stopAnimActive(); + } else { + textstyleSet(&st::inTextStyle); + float64 dt = (ms > st::activeFadeInDuration) ? (1 - (ms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (ms / float64(st::activeFadeInDuration)); + float64 o = p.opacity(); + p.setOpacity(o * dt); + p.fillRect(0, 0, _history->width, _height, textstyleCurrent()->selectOverlay->b); + p.setOpacity(o); } } diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index ae6c04193..0c92dcc6f 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -180,15 +180,13 @@ struct History : public QList { void addUnreadBar(); void clearNotifications(); - bool readyForWork() const; // all unread loaded or loaded around activeMsgId bool loadedAtBottom() const; // last message is in the list bool loadedAtTop() const; // nothing was added after loading history back + bool isReadyFor(MsgId msgId, bool check = false) const; // has messages for showing history at msgId + void getReadyFor(MsgId msgId); void fixLastMessage(bool wasAtBottom); - void loadAround(MsgId msgId); - bool canShowAround(MsgId msgId) const; - MsgId minMsgId() const; MsgId maxMsgId() const; @@ -201,7 +199,6 @@ struct History : public QList { PeerData *peer; bool oldLoaded, newLoaded; HistoryItem *lastMsg; - MsgId activeMsgId; typedef QList NotifyQueue; NotifyQueue notifies; @@ -251,6 +248,7 @@ struct History : public QList { MessageCursor draftCursor; bool draftPreviewCancelled; int32 lastWidth, lastScrollTop; + MsgId lastShowAtMsgId; bool mute; bool lastKeyboardInited, lastKeyboardUsed; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 349054189..0b987b752 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -43,6 +43,7 @@ HistoryList::HistoryList(HistoryWidget *historyWidget, ScrollArea *scroll, Histo , scrollArea(scroll) , currentBlock(0) , currentItem(0) + , _firstLoading(false) , _cursor(style::cur_default) , _dragAction(NoDrag) , _dragSelType(TextSelectLetters) @@ -101,7 +102,7 @@ void HistoryList::paintEvent(QPaintEvent *e) { p.setClipRect(r); } - if (botInfo && !botInfo->text.isEmpty() && botDescHeight > 0) { + if (!_firstLoading && botInfo && !botInfo->text.isEmpty() && botDescHeight > 0) { if (r.top() < botDescRect.y() + botDescRect.height() && r.bottom() > botDescRect.y()) { textstyleSet(&st::inTextStyle); App::roundRect(p, botDescRect, st::msgInBg, MessageInCorners, &st::msgInShadow); @@ -114,11 +115,11 @@ void HistoryList::paintEvent(QPaintEvent *e) { textstyleRestore(); } - } else if (hist->isEmpty()) { + } else if (_firstLoading || hist->isEmpty()) { QPoint dogPos((width() - st::msgDogImg.pxWidth()) / 2, ((height() - st::msgDogImg.pxHeight()) * 4) / 9); p.drawPixmap(dogPos, *cChatDogImage()); } - if (!hist->isEmpty()) { + if (!_firstLoading && !hist->isEmpty()) { adjustCurrent(r.top()); HistoryBlock *block = (*hist)[currentBlock]; HistoryItem *item = (*block)[currentItem]; @@ -1060,6 +1061,14 @@ void HistoryList::keyPressEvent(QKeyEvent *e) { int32 HistoryList::recountHeight(bool dontRecountText) { int32 st = hist->lastScrollTop; + + int32 ph = scrollArea->height(), minadd = 0; + int32 wasYSkip = ph - (hist->height + st::historyPadding); + if (botInfo && !botInfo->text.isEmpty()) { + minadd = st::msgMargin.top() + st::msgMargin.bottom() + st::msgPadding.top() + st::msgPadding.bottom() + st::msgNameFont->height + st::botDescSkip + botDescHeight; + } + if (wasYSkip < minadd) wasYSkip = minadd; + hist->geomResize(scrollArea->width(), &st, dontRecountText); updateBotInfo(false); if (botInfo && !botInfo->text.isEmpty()) { @@ -1081,7 +1090,14 @@ int32 HistoryList::recountHeight(bool dontRecountText) { botDescWidth = botDescHeight = 0; botDescRect = QRect(); } - return st; + + int32 newYSkip = ph - (hist->height + st::historyPadding); + if (botInfo && !botInfo->text.isEmpty()) { + minadd = st::msgMargin.top() + st::msgMargin.bottom() + st::msgPadding.top() + st::msgPadding.bottom() + st::msgNameFont->height + st::botDescSkip + botDescHeight; + } + if (newYSkip < minadd) newYSkip = minadd; + + return st + (newYSkip - wasYSkip); } void HistoryList::updateBotInfo(bool recount) { @@ -1125,22 +1141,30 @@ bool HistoryList::wasSelectedText() const { return _wasSelectedText; } +void HistoryList::setFirstLoading(bool loading) { + _firstLoading = loading; + update(); +} + void HistoryList::updateSize() { int32 ph = scrollArea->height(), minadd = 0; - ySkip = ph - (hist->height + st::historyPadding); + int32 newYSkip = ph - (hist->height + st::historyPadding); if (botInfo && !botInfo->text.isEmpty()) { minadd = st::msgMargin.top() + st::msgMargin.bottom() + st::msgPadding.top() + st::msgPadding.bottom() + st::msgNameFont->height + st::botDescSkip + botDescHeight; } - if (ySkip < minadd) ySkip = minadd; + if (newYSkip < minadd) newYSkip = minadd; if (botDescHeight > 0) { int32 descH = st::msgMargin.top() + st::msgPadding.top() + st::msgNameFont->height + st::botDescSkip + botDescHeight + st::msgPadding.bottom() + st::msgMargin.bottom(); int32 descAtX = (scrollArea->width() - botDescWidth) / 2 - st::msgPadding.left(); - int32 descAtY = qMin(ySkip - descH, (scrollArea->height() - descH) / 2) + st::msgMargin.top(); + int32 descAtY = qMin(newYSkip - descH, (scrollArea->height() - descH) / 2) + st::msgMargin.top(); botDescRect = QRect(descAtX, descAtY, botDescWidth + st::msgPadding.left() + st::msgPadding.right(), descH - st::msgMargin.top() - st::msgMargin.bottom()); } + int32 yAdded = newYSkip - ySkip; + ySkip = newYSkip; + int32 nh = hist->height + st::historyPadding + ySkip; if (width() != scrollArea->width() || height() != nh) { resize(scrollArea->width(), nh); @@ -2161,17 +2185,16 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) , _replyForwardPressed(false) , _replyReturn(0) , _stickersUpdateRequest(0) -, _loadingMessages(false) -, histRequestsCount(0) -, histPeer(0) -, _activeHist(0) -, histPreloading(0) -, _loadingAroundId(-1) -, _loadingAroundRequest(0) +, _peer(0) +, _showAtMsgId(0) +, _preloadRequest(0), _preloadDownRequest(0) +, _delayedShowAtMsgId(-1) +, _delayedShowAtRequest(0) +, _activeAnimMsgId(0) , _scroll(this, st::historyScroll, false) , _list(0) -, hist(0) -, _histInited(false), _histNeedUpdate(false) +, _history(0) +, _histInited(false) , _toHistoryEnd(this, st::historyToEnd) , _attachMention(this) , _send(this, lang(lng_send_button), st::btnSend) @@ -2200,13 +2223,12 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) , _attachDrag(DragStateNone) , _attachDragDocument(this) , _attachDragPhoto(this) -, imageLoader(this) +, _imageLoader(this) , _synthedTextUpdate(false) -, serviceImageCacheSize(0) -, confirmImageId(0) -, confirmWithText(false) -, titlePeerTextWidth(0) -, hiderOffered(false) +, _serviceImageCacheSize(0) +, _confirmImageId(0) +, _confirmWithText(false) +, _titlePeerTextWidth(0) , _showAnim(animFunc(this, &HistoryWidget::showStep)) , _scrollDelta(0) , _typingRequest(0) @@ -2228,8 +2250,8 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) connect(&_field, SIGNAL(tabbed()), this, SLOT(onFieldTabbed())); connect(&_field, SIGNAL(resized()), this, SLOT(onFieldResize())); connect(&_field, SIGNAL(focused()), this, SLOT(onFieldFocused())); - connect(&imageLoader, SIGNAL(imageReady()), this, SLOT(onPhotoReady())); - connect(&imageLoader, SIGNAL(imageFailed(quint64)), this, SLOT(onPhotoFailed(quint64))); + connect(&_imageLoader, SIGNAL(imageReady()), this, SLOT(onPhotoReady())); + connect(&_imageLoader, SIGNAL(imageFailed(quint64)), this, SLOT(onPhotoFailed(quint64))); connect(&_field, SIGNAL(changed()), this, SLOT(onTextChange())); connect(&_field, SIGNAL(spacedReturnedPasted()), this, SLOT(onPreviewParse())); connect(&_field, SIGNAL(linksChanged()), this, SLOT(onPreviewCheck())); @@ -2349,21 +2371,21 @@ void HistoryWidget::onTextChange() { update(); } - if (!hist || _synthedTextUpdate) return; + if (!_history || _synthedTextUpdate) return; _saveDraftText = true; onDraftSave(true); } void HistoryWidget::onDraftSaveDelayed() { - if (!hist || _synthedTextUpdate) return; + if (!_history || _synthedTextUpdate) return; if (!_field.textCursor().anchor() && !_field.textCursor().position() && !_field.verticalScrollBar()->value()) { - if (!Local::hasDraftPositions(hist->peer->id)) return; + if (!Local::hasDraftPositions(_history->peer->id)) return; } onDraftSave(true); } void HistoryWidget::onDraftSave(bool delayed) { - if (!hist) return; + if (!_history) return; if (delayed) { uint64 ms = getms(); if (!_saveDraftStart) { @@ -2377,14 +2399,14 @@ void HistoryWidget::onDraftSave(bool delayed) { } void HistoryWidget::writeDraft(MsgId *replyTo, const QString *text, const MessageCursor *cursor, bool *previewCancelled) { - bool save = hist && (_saveDraftStart > 0); + bool save = _history && (_saveDraftStart > 0); _saveDraftStart = 0; _saveDraftTimer.stop(); if (_saveDraftText) { - if (save) Local::writeDraft(hist->peer->id, Local::MessageDraft(replyTo ? (*replyTo) : _replyToId, text ? (*text) : _field.getLastText(), previewCancelled ? (*previewCancelled) : _previewCancelled)); + if (save) Local::writeDraft(_history->peer->id, Local::MessageDraft(replyTo ? (*replyTo) : _replyToId, text ? (*text) : _field.getLastText(), previewCancelled ? (*previewCancelled) : _previewCancelled)); _saveDraftText = false; } - if (save) Local::writeDraftPositions(hist->peer->id, cursor ? (*cursor) : MessageCursor(_field)); + if (save) Local::writeDraftPositions(_history->peer->id, cursor ? (*cursor) : MessageCursor(_field)); } void HistoryWidget::cancelTyping() { @@ -2396,12 +2418,12 @@ void HistoryWidget::cancelTyping() { void HistoryWidget::updateTyping(bool typing) { uint64 ms = getms(true) + 10000; - if (_synthedTextUpdate || !hist || (typing && (hist->myTyping + 5000 > ms)) || (!typing && (hist->myTyping + 5000 <= ms))) return; + if (_synthedTextUpdate || !_history || (typing && (_history->myTyping + 5000 > ms)) || (!typing && (_history->myTyping + 5000 <= ms))) return; - hist->myTyping = typing ? ms : 0; + _history->myTyping = typing ? ms : 0; cancelTyping(); if (typing) { - _typingRequest = MTP::send(MTPmessages_SetTyping(histPeer->input, typing ? MTP_sendMessageTypingAction() : MTP_sendMessageCancelAction()), rpcDone(&HistoryWidget::typingDone)); + _typingRequest = MTP::send(MTPmessages_SetTyping(_peer->input, typing ? MTP_sendMessageTypingAction() : MTP_sendMessageCancelAction()), rpcDone(&HistoryWidget::typingDone)); _typingStopTimer.start(5000); } } @@ -2421,19 +2443,7 @@ void HistoryWidget::typingDone(const MTPBool &result, mtpRequestId req) { } void HistoryWidget::activate() { - if (hist) { - if (!_histInited) checkUnreadLoaded(); - if (_histNeedUpdate) updateListSize(); - } - if (App::main()->selectingPeer()) { - if (hiderOffered) { - App::main()->focusPeerSelect(); - return; - } else { - App::main()->dialogsActivate(); - return; - } - } + if (_history) updateListSize(0, true); if (_list) { if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) { _list->setFocus(); @@ -2450,7 +2460,7 @@ void HistoryWidget::onRecordError() { void HistoryWidget::onRecordDone(QByteArray result, qint32 samples) { App::wnd()->activateWindow(); int32 duration = samples / AudioVoiceMsgFrequency; - imageLoader.append(result, duration, histPeer->id, replyToId(), ToPrepareAudio); + _imageLoader.append(result, duration, _peer->id, replyToId(), ToPrepareAudio); cancelReply(lastForceReplyReplied()); } @@ -2476,7 +2486,7 @@ void HistoryWidget::updateStickers() { } void HistoryWidget::botCommandsChanged(UserData *user) { - if (histPeer && (histPeer == user || histPeer->chat)) { + if (_peer && (_peer == user || _peer->chat)) { if (_attachMention.clearFilteredCommands()) { checkMentionDropdown(); } @@ -2568,14 +2578,6 @@ bool HistoryWidget::stickersFailed(const RPCError &error) { return true; } -void HistoryWidget::clearLoadingAround() { - _loadingAroundId = -1; - if (_loadingAroundRequest) { - MTP::cancel(_loadingAroundRequest); - _loadingAroundRequest = 0; - } -} - void HistoryWidget::clearReplyReturns() { _replyReturns.clear(); _replyReturn = 0; @@ -2593,7 +2595,8 @@ QList HistoryWidget::replyReturns() { } void HistoryWidget::setReplyReturns(PeerId peer, const QList &replyReturns) { - if (!histPeer || histPeer->id != peer) return; + if (!_peer || _peer->id != peer) return; + _replyReturns = replyReturns; _replyReturn = _replyReturns.isEmpty() ? 0 : App::histItemById(_replyReturns.back()); while (!_replyReturns.isEmpty() && !_replyReturn) { @@ -2637,73 +2640,74 @@ void HistoryWidget::setKbWasHidden() { update(); } -void HistoryWidget::showPeer(const PeerId &peer, MsgId msgId, bool force, bool leaveActive) { - if (App::main()->selectingPeer() && !force) { - hiderOffered = true; - App::main()->offerPeer(peer); - return; +void HistoryWidget::fastShowAtEnd(History *h) { + h->getReadyFor(ShowAtTheEndMsgId); + + if (_history != h) return; + + clearAllLoadRequests(); + + _showAtMsgId = ShowAtTheEndMsgId; + _histInited = false; + + if (h->isReadyFor(_showAtMsgId)) { + historyLoaded(); + } else { + firstLoadMessages(); + doneShow(); } - if (hist) { - if (histPeer->id == peer) { - if (msgId != hist->activeMsgId) { - bool canShowNow = hist->canShowAround(msgId); - if (!force && !canShowNow) { - if (_loadingAroundId != msgId) { - clearLoadingAround(); - _loadingAroundId = msgId; - loadMessagesAround(); - } - return; - } - hist->loadAround(msgId); - if (!canShowNow) { - histPreload.clear(); - histPreloadDown.clear(); - if (histPreloading) MTP::cancel(histPreloading); - if (histPreloadingDown) MTP::cancel(histPreloadingDown); - histPreloading = histPreloadingDown = 0; - } +} + +void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) { + if (_history) { + if (_peer->id == peerId) { + _history->lastWidth = 0; + + bool canShowNow = _history->isReadyFor(showAtMsgId, true); + if (!canShowNow) { + delayedShowAt(showAtMsgId); + return; } - if (_replyReturn && _replyReturn->id == msgId) calcNextReplyReturn(); - if (hist->unreadBar) hist->unreadBar->destroy(); - checkUnreadLoaded(); + clearDelayedShowAt(); + if (_replyReturn && _replyReturn->id == showAtMsgId) { + calcNextReplyReturn(); + } - clearLoadingAround(); - emit peerShown(histPeer); - return App::wnd()->setInnerFocus(); + _showAtMsgId = showAtMsgId; + _histInited = false; + + historyLoaded(); + return; } updateTyping(false); } + stopGif(); - clearLoadingAround(); clearReplyReturns(); - if (_list) { - if (!histPreload.isEmpty()) { - _list->messagesReceived(histPreload); - updateBotKeyboard(); - histPreload.clear(); - } - if (!histPreloadDown.isEmpty()) { - _list->messagesReceivedDown(histPreloadDown); - histPreloadDown.clear(); - } - } - if (hist) { - hist->draft = _field.getLastText(); - hist->draftCursor.fillFrom(_field); - hist->draftToId = _replyToId; - hist->draftPreviewCancelled = _previewCancelled; - writeDraft(&hist->draftToId, &hist->draft, &hist->draftCursor, &hist->draftPreviewCancelled); + clearAllLoadRequests(); - if (hist->readyForWork() && _scroll.scrollTop() + 1 <= _scroll.scrollTopMax()) { - hist->lastWidth = _list->width(); + if (_history) { + _history->draft = _field.getLastText(); + _history->draftCursor.fillFrom(_field); + _history->draftToId = _replyToId; + _history->draftPreviewCancelled = _previewCancelled; + + writeDraft(&_history->draftToId, &_history->draft, &_history->draftCursor, &_history->draftPreviewCancelled); + + if (_scroll.scrollTop() + 1 <= _scroll.scrollTopMax()) { + _history->lastWidth = _list->width(); + _history->lastShowAtMsgId = _showAtMsgId; } else { - hist->lastWidth = 0; + _history->lastWidth = 0; + _history->lastShowAtMsgId = ShowAtUnreadMsgId; } - hist->lastScrollTop = _scroll.scrollTop(); - if (hist->unreadBar) hist->unreadBar->destroy(); + _history->lastScrollTop = _scroll.scrollTop(); + if (_history->unreadBar) { + _history->unreadBar->destroy(); + } + _history = 0; } if (_replyToId) { @@ -2721,35 +2725,17 @@ void HistoryWidget::showPeer(const PeerId &peer, MsgId msgId, bool force, bool l _list = 0; updateTopBarSelection(); - if (_activeHist && _activeHist->peer->id != peer && (!leaveActive || _activeHist != hist)) { - if (!_activeHist->peer->chat && _activeHist->peer->asUser()->botInfo) { - _activeHist->peer->asUser()->botInfo->startToken = QString(); - } + _showAtMsgId = showAtMsgId; + _histInited = false; + if (_history) { + App::main()->dlgUpdated(_history); } - if (leaveActive && hist) { - _activeHist = hist; - } else { - if (!leaveActive) { - _activeHist = 0; - } - if (hist) { - App::main()->dlgUpdated(hist); - if (!hist->peer->chat && hist->peer->asUser()->botInfo) { - hist->peer->asUser()->botInfo->startToken = QString(); - } - } - } - histPeer = peer ? App::peer(peer) : 0; - titlePeerText = QString(); - titlePeerTextWidth = 0; - histRequestsCount = 0; - histPreload.clear(); - histPreloadDown.clear(); - if (histPreloading) MTP::cancel(histPreloading); - if (histPreloadingDown) MTP::cancel(histPreloadingDown); - histPreloading = histPreloadingDown = 0; - hist = 0; - _histInited = _histNeedUpdate = false; + + _peer = peerId ? App::peer(peerId) : 0; + + _titlePeerText = QString(); + _titlePeerTextWidth = 0; + noSelectingScroll(); _selCount = 0; App::main()->topBar()->showSelected(0); @@ -2763,52 +2749,55 @@ void HistoryWidget::showPeer(const PeerId &peer, MsgId msgId, bool force, bool l _kbWasHidden = false; - if (peer) { + if (_peer) { App::forgetMedia(); - serviceImageCacheSize = imageCacheSize(); + _serviceImageCacheSize = imageCacheSize(); MTP::clearLoaderPriorities(); - histInputPeer = histPeer->input; - if (histInputPeer.type() == mtpc_inputPeerEmpty) { // maybe should load user - } - Histories::iterator i = App::histories().find(peer); - if (i == App::histories().end()) { - hist = new History(peer); - i = App::histories().insert(peer, hist); - } else { - hist = i.value(); - } - if (hist->readyForWork()) { - _scroll.show(); - } - if (hist) { - App::main()->dlgUpdated(hist); - } - _list = new HistoryList(this, &_scroll, hist); - hist->loadAround(msgId); + if (_peer->input.type() == mtpc_inputPeerEmpty) { // maybe should load user + } + _history = App::history(_peer->id); + + if (_showAtMsgId == ShowAtUnreadMsgId) { + if (_history->lastWidth) { + _showAtMsgId = _history->lastShowAtMsgId; + } + } else { + _history->lastWidth = 0; + } + + _list = new HistoryList(this, &_scroll, _history); _list->hide(); + _scroll.hide(); _scroll.setWidget(_list); _list->show(); - updateBotKeyboard(); - checkUnreadLoaded(); + if (_history->lastWidth || _history->isReadyFor(_showAtMsgId, true)) { + historyLoaded(); + } else { + firstLoadMessages(); + doneShow(); + } + if (_history) { + App::main()->dlgUpdated(_history); + } - App::main()->peerUpdated(histPeer); + App::main()->peerUpdated(_peer); - if (hist->draftToId > 0 || !hist->draft.isEmpty()) { - setFieldText(hist->draft); + if (_history->draftToId > 0 || !_history->draft.isEmpty()) { + setFieldText(_history->draft); _field.setFocus(); - hist->draftCursor.applyTo(_field, &_synthedTextUpdate); - _replyToId = App::main()->hasForwardingItems() ? 0 : hist->draftToId; - if (hist->draftPreviewCancelled) { + _history->draftCursor.applyTo(_field, &_synthedTextUpdate); + _replyToId = App::main()->hasForwardingItems() ? 0 : _history->draftToId; + if (_history->draftPreviewCancelled) { _previewCancelled = true; } } else { - Local::MessageDraft draft = Local::readDraft(hist->peer->id); + Local::MessageDraft draft = Local::readDraft(_peer->id); setFieldText(draft.text); _field.setFocus(); if (!draft.text.isEmpty()) { - MessageCursor cur = Local::readDraftPositions(hist->peer->id); + MessageCursor cur = Local::readDraftPositions(_peer->id); cur.applyTo(_field, &_synthedTextUpdate); } _replyToId = App::main()->hasForwardingItems() ? 0 : draft.replyTo; @@ -2828,42 +2817,32 @@ void HistoryWidget::showPeer(const PeerId &peer, MsgId msgId, bool force, bool l connect(&_scroll, SIGNAL(geometryChanged()), _list, SLOT(onParentGeometryChanged())); connect(&_scroll, SIGNAL(scrolled()), _list, SLOT(onUpdateSelected())); } else { - updateBotKeyboard(); - updateControlsVisibility(); + doneShow(); } - emit peerShown(histPeer); + emit peerShown(_peer); App::main()->topBar()->update(); update(); } -void HistoryWidget::checkUnreadLoaded(bool checkOnlyShow) { - if (!hist) return; - if (hist->readyForWork()) { - if (checkOnlyShow && !_scroll.isHidden()) return; - if (!_showAnim.animating()) { - if (_scroll.isHidden()) { - _scroll.show(); - if (!_field.isHidden()) update(); - } - } - updateBotKeyboard(); - } else if (checkOnlyShow) { - return; - } - updateListSize(0, true); - if (!_showAnim.animating()) updateControlsVisibility(); - if (hist->readyForWork()) { - if (!_scroll.isHidden() && !_list->isHidden()) { - onListScroll(); - } - } else { - loadMessages(); +void HistoryWidget::clearDelayedShowAt() { + _delayedShowAtMsgId = -1; + if (_delayedShowAtRequest) { + MTP::cancel(_delayedShowAtRequest); + _delayedShowAtRequest = 0; } } +void HistoryWidget::clearAllLoadRequests() { + clearDelayedShowAt(); + if (_firstLoadRequest) MTP::cancel(_firstLoadRequest); + if (_preloadRequest) MTP::cancel(_preloadRequest); + if (_preloadDownRequest) MTP::cancel(_preloadDownRequest); + _preloadRequest = _preloadDownRequest = _firstLoadRequest = 0; +} + void HistoryWidget::updateControlsVisibility() { - if (!hist || _showAnim.animating()) { + if (!_history || _showAnim.animating()) { _scroll.hide(); _kbScroll.hide(); _send.hide(); @@ -2884,16 +2863,43 @@ void HistoryWidget::updateControlsVisibility() { } updateToEndVisibility(); - if (hist->readyForWork()) { - if (!histPeer->chat || !histPeer->asChat()->forbidden) { - checkMentionDropdown(); - if (isBotStart()) { - if (_botStart.isHidden()) { - _botStart.clearState(); - _botStart.show(); - _kbShown = false; - } + if (_firstLoadRequest) { + _scroll.hide(); + } else { + _scroll.show(); + } + if (!_peer->chat || !_peer->asChat()->forbidden) { + checkMentionDropdown(); + if (isBotStart()) { + if (_botStart.isHidden()) { + _botStart.clearState(); + _botStart.show(); + _kbShown = false; + } + _send.hide(); + _field.hide(); + _attachEmoji.hide(); + _kbShow.hide(); + _kbHide.hide(); + _cmdStart.hide(); + _attachDocument.hide(); + _attachPhoto.hide(); + _kbScroll.hide(); + _replyForwardPreviewCancel.hide(); + } else { + _botStart.hide(); + if (cHasAudioCapture() && _field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) { _send.hide(); + setMouseTracking(true); + mouseMoveEvent(0); + } else { + _send.show(); + setMouseTracking(false); + _recordAnim.stop(); + _inRecord = _inField = false; + a_recordOver = anim::fvalue(0, 0); + } + if (_recording) { _field.hide(); _attachEmoji.hide(); _kbShow.hide(); @@ -2901,167 +2907,114 @@ void HistoryWidget::updateControlsVisibility() { _cmdStart.hide(); _attachDocument.hide(); _attachPhoto.hide(); - _kbScroll.hide(); - _replyForwardPreviewCancel.hide(); - } else { - _botStart.hide(); - if (cHasAudioCapture() && _field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) { - _send.hide(); - setMouseTracking(true); - mouseMoveEvent(0); + if (_kbShown) { + _kbScroll.show(); } else { - _send.show(); - setMouseTracking(false); - _recordAnim.stop(); - _inRecord = _inField = false; - a_recordOver = anim::fvalue(0, 0); + _kbScroll.hide(); } - if (_recording) { - _field.hide(); + } else { + _field.show(); + if (_kbShown) { + _kbScroll.show(); _attachEmoji.hide(); + _kbHide.show(); + _kbShow.hide(); + _cmdStart.hide(); + } else if (_kbReplyTo) { + _kbScroll.hide(); + _attachEmoji.show(); + _kbHide.hide(); _kbShow.hide(); - _kbHide.hide(); _cmdStart.hide(); - _attachDocument.hide(); - _attachPhoto.hide(); - if (_kbShown) { - _kbScroll.show(); - } else { - _kbScroll.hide(); - } } else { - _field.show(); - if (_kbShown) { - _kbScroll.show(); - _attachEmoji.hide(); - _kbHide.show(); - _kbShow.hide(); - _cmdStart.hide(); - } else if (_kbReplyTo) { - _kbScroll.hide(); - _attachEmoji.show(); - _kbHide.hide(); - _kbShow.hide(); + _kbScroll.hide(); + _attachEmoji.show(); + _kbHide.hide(); + if (_keyboard.hasMarkup()) { + _kbShow.show(); _cmdStart.hide(); } else { - _kbScroll.hide(); - _attachEmoji.show(); - _kbHide.hide(); - if (_keyboard.hasMarkup()) { - _kbShow.show(); - _cmdStart.hide(); + _kbShow.hide(); + if (_cmdStartShown) { + _cmdStart.show(); } else { - _kbShow.hide(); - if (_cmdStartShown) { - _cmdStart.show(); - } else { - _cmdStart.hide(); - } + _cmdStart.hide(); } } - if (cDefaultAttach() == dbidaPhoto) { - _attachDocument.hide(); - _attachPhoto.show(); - } else { - _attachDocument.show(); - _attachPhoto.hide(); - } } - if (_replyToId || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0) || _kbReplyTo) { - if (_replyForwardPreviewCancel.isHidden()) { - _replyForwardPreviewCancel.show(); - resizeEvent(0); - update(); - } + if (cDefaultAttach() == dbidaPhoto) { + _attachDocument.hide(); + _attachPhoto.show(); } else { - _replyForwardPreviewCancel.hide(); + _attachDocument.show(); + _attachPhoto.hide(); } } - } else { - _attachMention.hide(); - _send.hide(); - _botStart.hide(); - _attachDocument.hide(); - _attachPhoto.hide(); - _attachEmoji.hide(); - _kbShow.hide(); - _kbHide.hide(); - _cmdStart.hide(); - _attachType.hide(); - _emojiPan.hide(); - if (!_field.isHidden()) { - _field.hide(); - resizeEvent(0); - update(); + if (_replyToId || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0) || _kbReplyTo) { + if (_replyForwardPreviewCancel.isHidden()) { + _replyForwardPreviewCancel.show(); + resizeEvent(0); + update(); + } + } else { + _replyForwardPreviewCancel.hide(); } } - - if (hist->unreadCount && App::wnd()->historyIsActive()) { - historyWasRead(); - } } else { - loadMessages(); - if (!hist->readyForWork()) { - _scroll.hide(); - _kbScroll.hide(); - _attachMention.hide(); - _send.hide(); - _botStart.hide(); - _attachDocument.hide(); - _attachPhoto.hide(); - _attachEmoji.hide(); - _kbShow.hide(); - _kbHide.hide(); - _cmdStart.hide(); - _attachType.hide(); - _emojiPan.hide(); - _replyForwardPreviewCancel.hide(); - if (!_field.isHidden()) { - _field.hide(); - update(); - } + _attachMention.hide(); + _send.hide(); + _botStart.hide(); + _attachDocument.hide(); + _attachPhoto.hide(); + _attachEmoji.hide(); + _kbShow.hide(); + _kbHide.hide(); + _cmdStart.hide(); + _attachType.hide(); + _emojiPan.hide(); + if (!_field.isHidden()) { + _field.hide(); + resizeEvent(0); + update(); } } } void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) { if (App::wnd()->historyIsActive()) { - if (hist == history && hist->readyForWork()) { + if (_history == history) { historyWasRead(); if (_scroll.scrollTop() + 1 > _scroll.scrollTopMax()) { if (history->unreadBar) history->unreadBar->destroy(); } } else { - if (hist != history) { - App::wnd()->notifySchedule(history, item); - } + App::wnd()->notifySchedule(history, item); history->setUnreadCount(history->unreadCount + 1); } } else { - if (hist == history && hist->readyForWork()) { + if (_history == history) { if (_scroll.scrollTop() + 1 > _scroll.scrollTopMax()) { if (history->unreadBar) history->unreadBar->destroy(); } } App::wnd()->notifySchedule(history, item); history->setUnreadCount(history->unreadCount + 1); - history->lastWidth = 0; } } void HistoryWidget::historyToDown(History *history) { history->lastScrollTop = History::ScrollMax; - if (history == hist) { + if (history == _history) { _scroll.scrollToY(_scroll.scrollTopMax()); } } void HistoryWidget::historyWasRead(bool force) { - App::main()->readServerHistory(hist, force); + App::main()->readServerHistory(_history, force); } void HistoryWidget::historyCleared(History *history) { - if (history == hist) { + if (history == _history) { _list->dragActionCancel(); } } @@ -3070,25 +3023,25 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false; LOG(("RPC Error: %1 %2: %3").arg(error.code()).arg(error.type()).arg(error.description())); - if (histPreloading == requestId) { - histPreloading = 0; - } else if (histPreloadingDown == requestId) { - histPreloadingDown = 0; - } else if (_loadingAroundRequest == requestId) { - _loadingAroundRequest = 0; + if (_preloadRequest == requestId) { + _preloadRequest = 0; + } else if (_preloadDownRequest == requestId) { + _preloadDownRequest = 0; + } else if (_firstLoadRequest == requestId) { + _firstLoadRequest = 0; + App::main()->showDialogs(); + } else if (_delayedShowAtRequest == requestId) { + _delayedShowAtRequest = 0; } return true; } void HistoryWidget::messagesReceived(const MTPmessages_Messages &messages, mtpRequestId requestId) { - if (!hist) { - histPreloading = histPreloadingDown = _loadingAroundRequest = 0; - histPreload.clear(); - histPreloadDown.clear(); + if (!_history) { + _preloadRequest = _preloadDownRequest = _firstLoadRequest = _delayedShowAtRequest = 0; return; } - PeerId peer = 0; int32 count = 0; const QVector *histList = 0; switch (messages.type()) { @@ -3107,214 +3060,158 @@ void HistoryWidget::messagesReceived(const MTPmessages_Messages &messages, mtpRe count = data.vcount.v; } break; } - if (histList && !histList->isEmpty()) { - const MTPmessage &msg(histList->front()); - PeerId from_id(0), to_id(0); - switch (msg.type()) { - case mtpc_message: - from_id = App::peerFromUser(msg.c_message().vfrom_id); - to_id = App::peerFromMTP(msg.c_message().vto_id); - break; - case mtpc_messageService: - from_id = App::peerFromUser(msg.c_messageService().vfrom_id); - to_id = App::peerFromMTP(msg.c_messageService().vto_id); - break; - } - peer = (to_id == App::peerFromUser(MTP::authedId())) ? from_id : to_id; - } - - bool down = false; - if (histPreloading == requestId) { - histPreloading = 0; - } else if (histPreloadingDown == requestId) { - histPreloadingDown = 0; - down = true; - } else { - if (_loadingAroundRequest == requestId) { - _loadingAroundRequest = 0; - hist->loadAround(_loadingAroundId); - if (hist->isEmpty()) { - histPreload.clear(); - histPreloadDown.clear(); - if (histPreloading) MTP::cancel(histPreloading); - if (histPreloadingDown) MTP::cancel(histPreloadingDown); - histPreloading = histPreloadingDown = 0; - addMessagesToFront(*histList); - } - showPeer(hist->peer->id, _loadingAroundId, true); - } - return; - } - - if (peer && peer != histPeer->id) return; - - if (histList) { - if (!hist->minMsgId() || histList->isEmpty()) { - if (down) { - addMessagesToBack(*histList); - histPreloadDown.clear(); - } else { - addMessagesToFront(*histList); - histPreload.clear(); - } - } else { - if (down) { - histPreloadDown = *histList; - } else { - histPreload = *histList; - } - } - } else { - if (down) { - addMessagesToBack(QVector()); - } else { - addMessagesToFront(QVector()); - } - if (!hist->readyForWork()) { - if (hist->activeMsgId) { - hist->activeMsgId = 0; - } - if (!hist->readyForWork()) { - hist->setUnreadCount(hist->msgCount); - } - } - checkUnreadLoaded(true); - return; - } - - if (down && hist->loadedAtBottom() && histPreloadDown.size()) { - addMessagesToBack(histPreloadDown); - histPreloadDown.clear(); - loadMessagesDown(); - } else if (!down && hist->loadedAtTop() && histPreload.size()) { - addMessagesToFront(histPreload); - histPreload.clear(); - loadMessages(); - } else if ((down && histPreloadDown.size()) || (!down && histPreload.size())) { + + if (_preloadRequest == requestId) { + addMessagesToFront(*histList); + _preloadRequest = 0; onListScroll(); - } else if (down) { - loadMessagesDown(); - } else { - loadMessages(); + } else if (_preloadDownRequest == requestId) { + addMessagesToBack(*histList); + _preloadDownRequest = 0; + onListScroll(); + if (_history->loadedAtBottom() && App::wnd()) App::wnd()->checkHistoryActivation(); + } else if (_firstLoadRequest == requestId) { + addMessagesToFront(*histList); + _firstLoadRequest = 0; + if (_history->loadedAtTop()) { + if (_history->unreadCount > count) { + _history->setUnreadCount(count); + } + if (_history->isEmpty() && count > 0) { + firstLoadMessages(); + return; + } + } + + historyLoaded(); + } else if (_delayedShowAtRequest == requestId) { + _delayedShowAtRequest = 0; + _history->getReadyFor(_delayedShowAtMsgId); + if (_history->isEmpty()) { + if (_preloadRequest) MTP::cancel(_preloadRequest); + if (_preloadDownRequest) MTP::cancel(_preloadDownRequest); + if (_firstLoadRequest) MTP::cancel(_firstLoadRequest); + _preloadRequest = _preloadDownRequest = 0; + _firstLoadRequest = -1; // hack - don't updateListSize yet + addMessagesToFront(*histList); + _firstLoadRequest = 0; + if (_history->loadedAtTop()) { + if (_history->unreadCount > count) { + _history->setUnreadCount(count); + } + if (_history->isEmpty() && count > 0) { + firstLoadMessages(); + return; + } + } + } + if (_replyReturn && _replyReturn->id == _delayedShowAtMsgId) { + calcNextReplyReturn(); + } + + _showAtMsgId = _delayedShowAtMsgId; + _histInited = false; + + historyLoaded(); } } -void HistoryWidget::windowShown() { - if (hist) { - if (!_histInited) checkUnreadLoaded(); - if (_histNeedUpdate) updateListSize(); +void HistoryWidget::historyLoaded() { + countHistoryShowFrom(); + if (_history->unreadBar) { + _history->unreadBar->destroy(); } + doneShow(); +} + +void HistoryWidget::windowShown() { resizeEvent(0); } bool HistoryWidget::isActive() const { - return !hist || hist->loadedAtBottom(); + if (!_history) return true; + if (_firstLoadRequest || _showAnim.animating()) return false; + if (_history->loadedAtBottom()) return true; + if (_history->showFrom && !_history->showFrom->detached() && _history->unreadBar) return true; + return false; +} + +void HistoryWidget::firstLoadMessages() { + if (!_history || _firstLoadRequest) return; + + int32 from = 0, offset = 0, loadCount = MessagesPerPage; + if (_showAtMsgId == ShowAtUnreadMsgId) { + if (_history->unreadCount > loadCount) { + _history->getReadyFor(_showAtMsgId); + offset = _history->unreadCount - loadCount / 2; + } else { + _history->getReadyFor(ShowAtTheEndMsgId); + } + } else if (_showAtMsgId == ShowAtTheEndMsgId) { + _history->getReadyFor(_showAtMsgId); + loadCount = MessagesFirstLoad; + } else if (_showAtMsgId > 0) { + _history->getReadyFor(_showAtMsgId); + offset = -loadCount / 2; + from = _showAtMsgId; + } + _firstLoadRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(offset), MTP_int(from), MTP_int(loadCount)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed)); } void HistoryWidget::loadMessages() { - if (!hist || _loadingMessages) return; - if (hist->loadedAtTop()) { - if (!hist->readyForWork()) { - if (hist->activeMsgId) { - hist->activeMsgId = 0; - } - if (!hist->readyForWork()) { - hist->setUnreadCount(hist->msgCount); - } - } - checkUnreadLoaded(true); - return; - } + if (!_history || _history->loadedAtTop() || _preloadRequest) return; - _loadingMessages = true; - if (histPreload.size()) { - bool loaded = hist->readyForWork(); - addMessagesToFront(histPreload); - histPreload.clear(); - checkUnreadLoaded(true); - if (!loaded && hist->readyForWork()) { - _loadingMessages = false; - return; - } - } - if (!histPreloading && (!hist->readyForWork() || _scroll.scrollTop() < PreloadHeightsCount * _scroll.height())) { - MsgId min = hist->minMsgId(); - int32 offset = 0, loadCount = min ? MessagesPerPage : MessagesFirstLoad; - if (!min && hist->activeMsgId) { - min = hist->activeMsgId; - offset = -loadCount / 2; - } - histPreloading = MTP::send(MTPmessages_GetHistory(histInputPeer, MTP_int(offset), MTP_int(min), MTP_int(loadCount)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed)); - ++histRequestsCount; - if (!hist->readyForWork()) update(); - } else { - checkUnreadLoaded(true); - } - _loadingMessages = false; + MsgId min = _history->minMsgId(); + int32 offset = 0, loadCount = min ? MessagesPerPage : MessagesFirstLoad; + _preloadRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(offset), MTP_int(min), MTP_int(loadCount)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed)); } void HistoryWidget::loadMessagesDown() { - if (!hist) return; - if (hist->loadedAtBottom()) { - return; - } + if (!_history || _history->loadedAtBottom() || _preloadDownRequest) return; - int32 dh = 0; - if (histPreloadDown.size()) { - bool loaded = hist->readyForWork(); - addMessagesToBack(histPreloadDown); - histPreloadDown.clear(); - checkUnreadLoaded(true); - if (!loaded && hist->readyForWork()) { - return; - } - } - if (!histPreloadingDown && hist->readyForWork() && (_scroll.scrollTop() + PreloadHeightsCount * _scroll.height() > _scroll.scrollTopMax())) { - MsgId max = hist->maxMsgId(); - if (max) { - int32 loadCount = MessagesPerPage, offset = -loadCount; - histPreloadingDown = MTP::send(MTPmessages_GetHistory(histInputPeer, MTP_int(offset), MTP_int(max + 1), MTP_int(loadCount)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed)); - ++histRequestsCount; - if (!hist->readyForWork()) update(); - } - } else { - checkUnreadLoaded(true); - } + MsgId max = _history->maxMsgId(); + if (!max) return; + + int32 loadCount = MessagesPerPage, offset = -loadCount - 1; + _preloadDownRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(offset), MTP_int(max + 1), MTP_int(loadCount)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed)); } -void HistoryWidget::loadMessagesAround() { - if (!hist || _loadingAroundRequest || _loadingAroundId < 0) return; +void HistoryWidget::delayedShowAt(MsgId showAtMsgId) { + if (!_history || (_delayedShowAtRequest && _delayedShowAtMsgId == showAtMsgId)) return; - int32 offset = 0, loadCount = MessagesPerPage; - if (_loadingAroundId) { + clearDelayedShowAt(); + _delayedShowAtMsgId = showAtMsgId; + + int32 from = _delayedShowAtMsgId, offset = 0, loadCount = MessagesPerPage; + if (_delayedShowAtMsgId == ShowAtUnreadMsgId) { + offset = qMax(_history->unreadCount - loadCount / 2, 0); + from = 0; + } else if (_delayedShowAtMsgId == ShowAtTheEndMsgId) { + loadCount = MessagesFirstLoad; + from = 0; + } else if (_delayedShowAtMsgId > 0) { offset = -loadCount / 2; } - _loadingAroundRequest = MTP::send(MTPmessages_GetHistory(histInputPeer, MTP_int(offset), MTP_int(_loadingAroundId), MTP_int(loadCount)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed)); + _delayedShowAtRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(offset), MTP_int(from), MTP_int(loadCount)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed)); } void HistoryWidget::onListScroll() { App::checkImageCacheSize(); - - if (histPreloading || !hist || ((_list->isHidden() || _scroll.isHidden() || _showAnim.animating() || !App::wnd()->windowHandle()->isVisible()) && hist->readyForWork())) { - checkUnreadLoaded(true); - return; - } + if (_firstLoadRequest || _scroll.isHidden()) return; updateToEndVisibility(); int st = _scroll.scrollTop(), stm = _scroll.scrollTopMax(), sh = _scroll.height(); - if (hist->readyForWork() && (st + PreloadHeightsCount * sh > stm)) { + if (st + PreloadHeightsCount * sh > stm) { loadMessagesDown(); } - if (!hist->readyForWork() || st < PreloadHeightsCount * sh) { + if (st < PreloadHeightsCount * sh) { loadMessages(); - } else { - checkUnreadLoaded(true); } while (_replyReturn) { - bool below = (_replyReturn->detached() && !hist->isEmpty() && _replyReturn->id < hist->back()->back()->id); + bool below = (_replyReturn->detached() && !_history->isEmpty() && _replyReturn->id < _history->back()->back()->id); if (!below && !_replyReturn->detached()) below = (st >= stm) || (_replyReturn->y + _replyReturn->block()->y < st + sh / 2); if (below) { calcNextReplyReturn(); @@ -3341,23 +3238,23 @@ QString HistoryWidget::prepareMessage(QString result) { void HistoryWidget::onHistoryToEnd() { if (_replyReturn) { - showPeer(histPeer->id, _replyReturn->id); - } else if (hist) { - showPeer(histPeer->id, 0); + showPeerHistory(_peer->id, _replyReturn->id); + } else if (_peer) { + showPeerHistory(_peer->id, ShowAtUnreadMsgId); } } void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) { - if (!hist) return; + if (!_history) return; bool lastKeyboardUsed = lastForceReplyReplied(replyTo); QString text = prepareMessage(_field.getLastText()); if (!text.isEmpty()) { - App::main()->readServerHistory(hist, false); - hist->loadAround(0); + App::main()->readServerHistory(_history, false); + fastShowAtEnd(_history); WebPageId webPageId = _previewCancelled ? 0xFFFFFFFFFFFFFFFFULL : ((_previewData && _previewData->pendingTill >= 0) ? _previewData->id : 0); - App::main()->sendPreparedText(hist, text, replyTo, webPageId); + App::main()->sendPreparedText(_history, text, replyTo, webPageId); setFieldText(QString()); _saveDraftText = true; @@ -3369,10 +3266,9 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) { if (!_emojiPan.isHidden()) _emojiPan.hideStart(); } else if (App::main()->hasForwardingItems()) { - App::main()->readServerHistory(hist, false); - hist->loadAround(0); - - App::main()->finishForwarding(hist); + App::main()->readServerHistory(_history, false); + fastShowAtEnd(_history); + App::main()->finishForwarding(_history); } if (replyTo < 0) cancelReply(lastKeyboardUsed); if (_previewData && _previewData->pendingTill) previewCancel(); @@ -3382,20 +3278,23 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) { } void HistoryWidget::onBotStart() { - if (histPeer->chat || !histPeer->asUser()->botInfo) { + if (!_peer || _peer->chat || !_peer->asUser()->botInfo) { updateControlsVisibility(); return; } - QString token = histPeer->asUser()->botInfo->startToken; + + QString token = _peer->asUser()->botInfo->startToken; if (token.isEmpty()) { sendBotCommand(qsl("/start"), 0); } else { uint64 randomId = MTP::nonce(); - MTP::send(MTPmessages_StartBot(histPeer->asUser()->inputUser, MTP_int(0), MTP_long(randomId), MTP_string(token)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, histPeer->asUser())); + MTP::send(MTPmessages_StartBot(_peer->asUser()->inputUser, MTP_int(0), MTP_long(randomId), MTP_string(token)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, _peer->asUser())); - histPeer->asUser()->botInfo->startToken = QString(); + _peer->asUser()->botInfo->startToken = QString(); if (_keyboard.hasMarkup()) { - if (_keyboard.singleUse() && _keyboard.forMsgId() == hist->lastKeyboardId && hist->lastKeyboardUsed) _kbWasHidden = true; + if (_keyboard.singleUse() && _keyboard.forMsgId() == _history->lastKeyboardId && _history->lastKeyboardUsed) { + _kbWasHidden = true; + } if (!_kbWasHidden) _kbShown = _keyboard.hasMarkup(); } } @@ -3406,20 +3305,20 @@ void HistoryWidget::onBotStart() { void HistoryWidget::onShareContact(const PeerId &peer, UserData *contact) { if (!contact || contact->phone.isEmpty()) return; - App::main()->showPeer(peer, 0, false, true); - if (!hist) return; + App::main()->showPeerHistory(peer, ShowAtTheEndMsgId); + if (!_history) return; shareContact(peer, contact->phone, contact->firstName, contact->lastName, replyToId(), int32(contact->id & 0xFFFFFFFF)); } void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, int32 userId) { History *h = App::history(peer); - App::main()->readServerHistory(h, false); uint64 randomId = MTP::nonce(); MsgId newId = clientMsgId(); - h->loadAround(0); + App::main()->readServerHistory(h, false); + fastShowAtEnd(h); PeerData *p = App::peer(peer); int32 flags = newMessageFlags(p); // unread, out @@ -3432,7 +3331,7 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id; } h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(peer), MTPint(), MTPint(), MTP_int(replyToId()), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)), MTPnullMarkup)); - h->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + h->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, h->sendRequestId); App::historyRegRandom(randomId, newId); @@ -3441,30 +3340,18 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const } void HistoryWidget::onSendPaths(const PeerId &peer) { - App::main()->showPeer(peer, 0, false, true); - if (!hist) return; + App::main()->showPeerHistory(peer, ShowAtTheEndMsgId); + if (!_history) return; uploadMedias(cSendPaths(), ToPrepareDocument); } PeerData *HistoryWidget::peer() const { - return histPeer; + return _peer; } -PeerData *HistoryWidget::activePeer() const { - return histPeer ? histPeer : (_activeHist ? _activeHist->peer : 0); -} - -MsgId HistoryWidget::activeMsgId() const { - return (_loadingAroundId >= 0) ? _loadingAroundId : (hist ? hist->activeMsgId : (_activeHist ? _activeHist->activeMsgId : 0)); -} - -int32 HistoryWidget::lastWidth() const { - return width(); -} - -int32 HistoryWidget::lastScrollTop() const { - return _scroll.scrollTop(); +MsgId HistoryWidget::msgId() const { + return _showAtMsgId; } void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTopBarCache, bool back) { @@ -3523,19 +3410,11 @@ bool HistoryWidget::showStep(float64 ms) { } void HistoryWidget::doneShow() { - if (hist && hist->readyForWork()) { - _scroll.show(); - if (hist->lastScrollTop == History::ScrollMax) { - _scroll.scrollToY(hist->lastScrollTop); - } - - onListScroll(); - } - if (hist) { - if (!_histInited) checkUnreadLoaded(); - if (_histNeedUpdate) updateListSize(); - } + updateBotKeyboard(); updateControlsVisibility(); + updateListSize(0, true); + onListScroll(); + if (App::wnd()) App::wnd()->checkHistoryActivation(); App::wnd()->setInnerFocus(); } @@ -3579,7 +3458,7 @@ bool HistoryWidget::recordingStep(float64 ms) { } void HistoryWidget::onPhotoSelect() { - if (!hist) return; + if (!_history) return; _attachDocument.clearState(); _attachDocument.hide(); @@ -3607,7 +3486,7 @@ void HistoryWidget::onPhotoSelect() { } void HistoryWidget::onDocumentSelect() { - if (!hist) return; + if (!_history) return; _attachPhoto.clearState(); _attachPhoto.hide(); @@ -3636,7 +3515,7 @@ void HistoryWidget::onDocumentSelect() { void HistoryWidget::dragEnterEvent(QDragEnterEvent *e) { - if (!hist) return; + if (!_history) return; _attachDrag = getDragState(e->mimeData()); updateDragAreas(); @@ -3727,27 +3606,27 @@ void HistoryWidget::stopRecording(bool send) { } void HistoryWidget::sendBotCommand(const QString &cmd, MsgId replyTo) { // replyTo != 0 from ReplyKeyboardMarkup, == 0 from cmd links - if (!hist) return; + if (!_history) return; - App::main()->readServerHistory(hist, false); - hist->loadAround(0); + App::main()->readServerHistory(_history, false); + fastShowAtEnd(_history); - bool lastKeyboardUsed = (_keyboard.forMsgId() == hist->lastKeyboardId) && (_keyboard.forMsgId() == replyTo); + bool lastKeyboardUsed = (_keyboard.forMsgId() == _history->lastKeyboardId) && (_keyboard.forMsgId() == replyTo); QString toSend = cmd; - UserData *bot = histPeer->chat ? (App::hoveredLinkItem() ? (App::hoveredLinkItem()->toHistoryForwarded() ? App::hoveredLinkItem()->toHistoryForwarded()->fromForwarded() : App::hoveredLinkItem()->from()) : 0) : histPeer->asUser(); + UserData *bot = _peer->chat ? (App::hoveredLinkItem() ? (App::hoveredLinkItem()->toHistoryForwarded() ? App::hoveredLinkItem()->toHistoryForwarded()->fromForwarded() : App::hoveredLinkItem()->from()) : 0) : _peer->asUser(); QString username = (bot && bot->botInfo) ? bot->username : QString(); - if (!replyTo && toSend.indexOf('@') < 2 && histPeer->chat && !username.isEmpty() && (histPeer->asChat()->botStatus == 0 || histPeer->asChat()->botStatus == 2)) { + if (!replyTo && toSend.indexOf('@') < 2 && _peer->chat && !username.isEmpty() && (_peer->asChat()->botStatus == 0 || _peer->asChat()->botStatus == 2)) { toSend += '@' + username; } - int32 botStatus = histPeer->chat ? histPeer->asChat()->botStatus : -1; - App::main()->sendPreparedText(hist, toSend, replyTo ? ((histPeer->chat/* && (botStatus == 0 || botStatus == 2)*/) ? replyTo : -1) : 0); + int32 botStatus = _peer->chat ? _peer->asChat()->botStatus : -1; + App::main()->sendPreparedText(_history, toSend, replyTo ? ((_peer->chat/* && (botStatus == 0 || botStatus == 2)*/) ? replyTo : -1) : 0); if (replyTo) { cancelReply(); if (_keyboard.singleUse() && _keyboard.hasMarkup() && lastKeyboardUsed) { if (_kbShown) onKbToggle(false); - hist->lastKeyboardUsed = true; + _history->lastKeyboardUsed = true; } } @@ -3755,12 +3634,12 @@ void HistoryWidget::sendBotCommand(const QString &cmd, MsgId replyTo) { // reply } void HistoryWidget::insertBotCommand(const QString &cmd) { - if (!hist) return; + if (!_history) return; QString toInsert = cmd; - UserData *bot = histPeer->chat ? (App::hoveredLinkItem() ? (App::hoveredLinkItem()->toHistoryForwarded() ? App::hoveredLinkItem()->toHistoryForwarded()->fromForwarded() : App::hoveredLinkItem()->from()) : 0) : histPeer->asUser(); + UserData *bot = _peer->chat ? (App::hoveredLinkItem() ? (App::hoveredLinkItem()->toHistoryForwarded() ? App::hoveredLinkItem()->toHistoryForwarded()->fromForwarded() : App::hoveredLinkItem()->from()) : 0) : _peer->asUser(); QString username = (bot && bot->botInfo) ? bot->username : QString(); - if (toInsert.indexOf('@') < 2 && histPeer->chat && !username.isEmpty() && (histPeer->asChat()->botStatus == 0 || histPeer->asChat()->botStatus == 2)) { + if (toInsert.indexOf('@') < 2 && _peer->chat && !username.isEmpty() && (_peer->asChat()->botStatus == 0 || _peer->asChat()->botStatus == 2)) { toInsert += '@' + username; } toInsert += ' '; @@ -3858,13 +3737,13 @@ void HistoryWidget::updateDragAreas() { } bool HistoryWidget::isBotStart() const { - if (!hist || !histPeer || histPeer->chat || !histPeer->asUser()->botInfo) return false; - return !histPeer->asUser()->botInfo->startToken.isEmpty() || (hist->isEmpty() && !hist->lastMsg); + if (!_peer || _peer->chat || !_peer->asUser()->botInfo) return false; + return !_peer->asUser()->botInfo->startToken.isEmpty() || (_history->isEmpty() && !_history->lastMsg); } bool HistoryWidget::updateCmdStartShown() { bool cmdStartShown = false; - if (hist && histPeer && ((histPeer->chat && histPeer->asChat()->botStatus > 0) || (!histPeer->chat && histPeer->asUser()->botInfo))) { + if (_history && _peer && ((_peer->chat && _peer->asChat()->botStatus > 0) || (!_peer->chat && _peer->asUser()->botInfo))) { if (!isBotStart() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) { if (_field.getLastText().isEmpty()) { cmdStartShown = true; @@ -3885,7 +3764,7 @@ void HistoryWidget::dropEvent(QDropEvent *e) { } void HistoryWidget::onPhotoDrop(const QMimeData *data) { - if (!hist) return; + if (!_history) return; if (data->hasImage()) { QImage image = qvariant_cast(data->imageData()); @@ -3901,7 +3780,7 @@ void HistoryWidget::onPhotoDrop(const QMimeData *data) { } void HistoryWidget::onDocumentDrop(const QMimeData *data) { - if (!hist) return; + if (!_history) return; QStringList files = getMediasFromMime(data); if (files.isEmpty()) return; @@ -3940,8 +3819,8 @@ void HistoryWidget::onKbToggle(bool manual) { _replyForwardPreviewCancel.hide(); } } else { - if (hist) { - hist->clearLastKeyboard(); + if (_history) { + _history->clearLastKeyboard(); } updateBotKeyboard(); } @@ -3954,7 +3833,7 @@ void HistoryWidget::onKbToggle(bool manual) { _field.setMaxHeight(st::maxFieldHeight); - _kbReplyTo = (hist->peer->chat || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0; + _kbReplyTo = (_history->peer->chat || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0; if (_kbReplyTo && !_replyToId) { updateReplyToName(); _replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions); @@ -3970,7 +3849,7 @@ void HistoryWidget::onKbToggle(bool manual) { int32 maxh = qMin(_keyboard.height(), int(st::maxFieldHeight) - (int(st::maxFieldHeight) / 2)); _field.setMaxHeight(st::maxFieldHeight - maxh); - _kbReplyTo = (hist->peer->chat || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0; + _kbReplyTo = (_history->peer->chat || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0; if (_kbReplyTo && !_replyToId) { updateReplyToName(); _replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions); @@ -4029,22 +3908,22 @@ void HistoryWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth) return; } - if (!hist) return; + if (!_history) return; int32 increaseLeft = cWideMode() ? 0 : (st::topBarForwardPadding.right() - st::topBarForwardPadding.left()); decreaseWidth += increaseLeft; QRect rectForName(st::topBarForwardPadding.left() + increaseLeft, st::topBarForwardPadding.top(), width() - decreaseWidth - st::topBarForwardPadding.left() - st::topBarForwardPadding.right(), st::msgNameFont->height); p.setFont(st::dlgHistFont->f); - if (hist->typing.isEmpty()) { + if (_history->typing.isEmpty()) { p.setPen(st::titleStatusColor->p); - p.drawText(rectForName.x(), st::topBarHeight - st::topBarForwardPadding.bottom() - st::dlgHistFont->height + st::dlgHistFont->ascent, titlePeerText); + p.drawText(rectForName.x(), st::topBarHeight - st::topBarForwardPadding.bottom() - st::dlgHistFont->height + st::dlgHistFont->ascent, _titlePeerText); } else { p.setPen(st::titleTypingColor->p); - hist->typingText.drawElided(p, rectForName.x(), st::topBarHeight - st::topBarForwardPadding.bottom() - st::dlgHistFont->height, rectForName.width()); + _history->typingText.drawElided(p, rectForName.x(), st::topBarHeight - st::topBarForwardPadding.bottom() - st::dlgHistFont->height, rectForName.width()); } p.setPen(st::dlgNameColor->p); - hist->nameText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); + _history->nameText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); if (cWideMode()) { p.setOpacity(st::topBarForwardAlpha + (1 - st::topBarForwardAlpha) * over); @@ -4064,23 +3943,23 @@ void HistoryWidget::topBarShadowParams(int32 &x, float64 &o) { void HistoryWidget::topBarClick() { if (cWideMode()) { - if (hist) App::main()->showPeerProfile(histPeer); + if (_history) App::main()->showPeerProfile(_peer); } else { - App::main()->onShowDialogs(); + App::main()->showDialogs(); } } void HistoryWidget::updateOnlineDisplay(int32 x, int32 w) { - if (!hist) return; + if (!_history) return; QString text; int32 t = unixtime(); - if (histPeer->chat) { - ChatData *chat = histPeer->asChat(); + if (_peer->chat) { + ChatData *chat = _peer->asChat(); if (chat->forbidden) { text = lang(lng_chat_status_unaccessible); } else if (chat->participants.isEmpty()) { - text = titlePeerText.isEmpty() ? lng_chat_status_members(lt_count, chat->count < 0 ? 0 : chat->count) : titlePeerText; + text = _titlePeerText.isEmpty() ? lng_chat_status_members(lt_count, chat->count < 0 ? 0 : chat->count) : _titlePeerText; } else { int32 onlineCount = 0; bool onlyMe = true; @@ -4097,11 +3976,11 @@ void HistoryWidget::updateOnlineDisplay(int32 x, int32 w) { } } } else { - text = App::onlineText(histPeer->asUser(), t); + text = App::onlineText(_peer->asUser(), t); } - if (titlePeerText != text) { - titlePeerText = text; - titlePeerTextWidth = st::dlgHistFont->m.width(titlePeerText); + if (_titlePeerText != text) { + _titlePeerText = text; + _titlePeerTextWidth = st::dlgHistFont->m.width(_titlePeerText); if (App::main()) { App::main()->topBar()->update(); } @@ -4110,11 +3989,11 @@ void HistoryWidget::updateOnlineDisplay(int32 x, int32 w) { } void HistoryWidget::updateOnlineDisplayTimer() { - if (!hist) return; + if (!_history) return; int32 t = unixtime(), minIn = 86400; - if (histPeer->chat) { - ChatData *chat = histPeer->asChat(); + if (_peer->chat) { + ChatData *chat = _peer->asChat(); if (chat->participants.isEmpty()) return; for (ChatData::Participants::const_iterator i = chat->participants.cbegin(), e = chat->participants.cend(); i != e; ++i) { @@ -4124,7 +4003,7 @@ void HistoryWidget::updateOnlineDisplayTimer() { } } } else { - minIn = App::onlineWillChangeIn(histPeer->asUser(), t); + minIn = App::onlineWillChangeIn(_peer->asUser(), t); } App::main()->updateOnlineDisplayIn(minIn * 1000); } @@ -4162,15 +4041,15 @@ void HistoryWidget::onFieldFocused() { } void HistoryWidget::checkMentionDropdown() { - if (!hist || _showAnim.animating()) return; + if (!_history || _showAnim.animating()) return; QString start; _field.getMentionHashtagBotCommandStart(start); if (!start.isEmpty()) { if (start.at(0) == '#' && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) Local::readRecentHashtags(); - if (start.at(0) == '@' && !hist->peer->chat) return; - if (start.at(0) == '/' && !hist->peer->chat && !hist->peer->asUser()->botInfo) return; - _attachMention.showFiltered(hist->peer, start); + if (start.at(0) == '@' && !_history->peer->chat) return; + if (start.at(0) == '/' && !_history->peer->chat && !_history->peer->asUser()->botInfo) return; + _attachMention.showFiltered(_history->peer, start); } else if (!_attachMention.isHidden()) { _attachMention.hideStart(); } @@ -4182,70 +4061,70 @@ void HistoryWidget::onFieldCursorChanged() { } void HistoryWidget::uploadImage(const QImage &img, bool withText, const QString &source) { - if (!hist || confirmImageId) return; + if (!_history || _confirmImageId) return; App::wnd()->activateWindow(); - confirmImage = img; - confirmWithText = withText; - confirmSource = source; - confirmImageId = imageLoader.append(img, histPeer->id, replyToId(), ToPreparePhoto); + _confirmImage = img; + _confirmWithText = withText; + _confirmSource = source; + _confirmImageId = _imageLoader.append(img, _peer->id, replyToId(), ToPreparePhoto); } void HistoryWidget::uploadFile(const QString &file, bool withText) { - if (!hist || confirmImageId) return; + if (!_history || _confirmImageId) return; App::wnd()->activateWindow(); - confirmWithText = withText; - confirmImageId = imageLoader.append(file, histPeer->id, replyToId(), ToPrepareDocument); + _confirmWithText = withText; + _confirmImageId = _imageLoader.append(file, _peer->id, replyToId(), ToPrepareDocument); } void HistoryWidget::shareContactConfirmation(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, bool withText) { - if (!hist || confirmImageId) return; + if (!_history || _confirmImageId) return; App::wnd()->activateWindow(); - confirmWithText = withText; - confirmImageId = 0xFFFFFFFFFFFFFFFFL; + _confirmWithText = withText; + _confirmImageId = 0xFFFFFFFFFFFFFFFFL; App::wnd()->showLayer(new PhotoSendBox(phone, fname, lname, replyTo)); } void HistoryWidget::uploadConfirmImageUncompressed(bool ctrlShiftEnter, MsgId replyTo) { - if (!hist || !confirmImageId || confirmImage.isNull()) return; + if (!_history || !_confirmImageId || _confirmImage.isNull()) return; App::wnd()->activateWindow(); - PeerId peerId = histPeer->id; - if (confirmWithText) { + PeerId peerId = _peer->id; + if (_confirmWithText) { onSend(ctrlShiftEnter, replyTo); } bool lastKeyboardUsed = lastForceReplyReplied(replyTo); - imageLoader.append(confirmImage, peerId, replyTo, ToPrepareDocument, ctrlShiftEnter); - confirmImageId = 0; - confirmWithText = false; - confirmImage = QImage(); + _imageLoader.append(_confirmImage, peerId, replyTo, ToPrepareDocument, ctrlShiftEnter); + _confirmImageId = 0; + _confirmWithText = false; + _confirmImage = QImage(); cancelReply(lastKeyboardUsed); } void HistoryWidget::uploadMedias(const QStringList &files, ToPrepareMediaType type) { - if (!hist) return; + if (!_history) return; App::wnd()->activateWindow(); - imageLoader.append(files, histPeer->id, replyToId(), type); + _imageLoader.append(files, _peer->id, replyToId(), type); cancelReply(lastForceReplyReplied()); } void HistoryWidget::uploadMedia(const QByteArray &fileContent, ToPrepareMediaType type, PeerId peer) { - if (!peer && !hist) return; + if (!peer && !_history) return; App::wnd()->activateWindow(); - imageLoader.append(fileContent, peer ? peer : histPeer->id, replyToId(), type); + _imageLoader.append(fileContent, peer ? peer : _peer->id, replyToId(), type); cancelReply(lastForceReplyReplied()); } void HistoryWidget::onPhotoReady() { - QMutexLocker lock(imageLoader.readyMutex()); - ReadyLocalMedias &list(imageLoader.readyList()); + QMutexLocker lock(_imageLoader.readyMutex()); + ReadyLocalMedias &list(_imageLoader.readyList()); for (ReadyLocalMedias::const_iterator i = list.cbegin(), e = list.cend(); i != e; ++i) { - if (i->id == confirmImageId) { + if (i->id == _confirmImageId) { PhotoSendBox *box = new PhotoSendBox(*i); connect(box, SIGNAL(confirmed()), this, SLOT(onSendConfirmed())); connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onSendCancelled())); @@ -4258,13 +4137,13 @@ void HistoryWidget::onPhotoReady() { } void HistoryWidget::onSendConfirmed() { - if (!confirmSource.isEmpty()) confirmSource = QString(); + if (!_confirmSource.isEmpty()) _confirmSource = QString(); } void HistoryWidget::onSendCancelled() { - if (!confirmSource.isEmpty()) { - _field.textCursor().insertText(confirmSource); - confirmSource = QString(); + if (!_confirmSource.isEmpty()) { + _field.textCursor().insertText(_confirmSource); + _confirmSource = QString(); } } @@ -4272,28 +4151,28 @@ void HistoryWidget::onPhotoFailed(quint64 id) { } void HistoryWidget::confirmShareContact(bool ctrlShiftEnter, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo) { - if (!histPeer) return; + if (!_peer) return; - PeerId peerId = histPeer->id; - if (0xFFFFFFFFFFFFFFFFL == confirmImageId) { - if (confirmWithText) { + PeerId peerId = _peer->id; + if (0xFFFFFFFFFFFFFFFFL == _confirmImageId) { + if (_confirmWithText) { onSend(ctrlShiftEnter, replyTo); } - confirmImageId = 0; - confirmWithText = false; - confirmImage = QImage(); + _confirmImageId = 0; + _confirmWithText = false; + _confirmImage = QImage(); } shareContact(peerId, phone, fname, lname, replyTo); } void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) { - if (img.id == confirmImageId) { - if (confirmWithText) { + if (img.id == _confirmImageId) { + if (_confirmWithText) { onSend(img.ctrlShiftEnter, img.replyTo); } - confirmImageId = 0; - confirmWithText = false; - confirmImage = QImage(); + _confirmImageId = 0; + _confirmWithText = false; + _confirmImage = QImage(); } MsgId newId = clientMsgId(); @@ -4311,7 +4190,9 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) { App::uploader()->uploadMedia(newId, img); History *h = App::history(img.peer); - h->loadAround(0); + + fastShowAtEnd(h); + int32 flags = newMessageFlags(h->peer); // unread, out if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id; if (img.type == ToPreparePhoto) { @@ -4319,29 +4200,27 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) { } else if (img.type == ToPrepareDocument) { h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup)); } else if (img.type == ToPrepareAudio) { - h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup)); + h->addToBack(MTP_message(MTP_int(flags | MTPDmessage_flag_media_unread), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup)); } - if (hist && histPeer && img.peer == histPeer->id) { - App::main()->historyToDown(hist); + if (_peer && img.peer == _peer->id) { + App::main()->historyToDown(_history); } App::main()->dialogsToUp(); peerMessagesUpdated(img.peer); } void HistoryWidget::cancelSendImage() { - if (confirmImageId && confirmWithText) setFieldText(QString()); - confirmImageId = 0; - confirmWithText = false; - confirmImage = QImage(); + if (_confirmImageId && _confirmWithText) setFieldText(QString()); + _confirmImageId = 0; + _confirmWithText = false; + _confirmImage = QImage(); } void HistoryWidget::onPhotoUploaded(MsgId newId, const MTPInputFile &file) { if (!MTP::authedId()) return; HistoryItem *item = App::histItemById(newId); if (item) { - //App::main()->readServerHistory(item->history(), false); - uint64 randomId = MTP::nonce(); App::historyRegRandom(randomId, newId); History *hist = item->history(); @@ -4382,8 +4261,6 @@ void HistoryWidget::onDocumentUploaded(MsgId newId, const MTPInputFile &file) { document = media->document(); } if (document) { - //App::main()->readServerHistory(item->history(), false); - uint64 randomId = MTP::nonce(); App::historyRegRandom(randomId, newId); History *hist = item->history(); @@ -4408,8 +4285,6 @@ void HistoryWidget::onThumbDocumentUploaded(MsgId newId, const MTPInputFile &fil document = media->document(); } if (document) { - //App::main()->readServerHistory(item->history(), false); - uint64 randomId = MTP::nonce(); App::historyRegRandom(randomId, newId); History *hist = item->history(); @@ -4432,8 +4307,6 @@ void HistoryWidget::onAudioUploaded(MsgId newId, const MTPInputFile &file) { audio = media->audio(); } if (audio) { - //App::main()->readServerHistory(item->history(), false); - uint64 randomId = MTP::nonce(); App::historyRegRandom(randomId, newId); History *hist = item->history(); @@ -4480,7 +4353,7 @@ void HistoryWidget::onAudioFailed(MsgId newId) { } void HistoryWidget::peerMessagesUpdated(PeerId peer) { - if (histPeer && _list && peer == histPeer->id) { + if (_peer && _list && peer == _peer->id) { updateListSize(); updateBotKeyboard(); if (!_scroll.isHidden() && _botStart.isHidden() == isBotStart()) { @@ -4491,11 +4364,11 @@ void HistoryWidget::peerMessagesUpdated(PeerId peer) { } void HistoryWidget::peerMessagesUpdated() { - if (_list) updateListSize(); + if (_list) peerMessagesUpdated(_peer->id); } void HistoryWidget::msgUpdated(PeerId peer, const HistoryItem *msg) { - if (histPeer && _list && peer == histPeer->id) { + if (_peer && _list && peer == _peer->id) { _list->updateMsg(msg); } } @@ -4517,7 +4390,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) { _replyForwardPreviewCancel.move(width() - _replyForwardPreviewCancel.width(), _field.y() - st::sendPadding - _replyForwardPreviewCancel.height()); updateListSize(App::main() ? App::main()->contentScrollAddToY() : 0); - bool kbShowShown = hist && !_kbShown && _keyboard.hasMarkup(); + bool kbShowShown = _history && !_kbShown && _keyboard.hasMarkup(); _field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width() - (kbShowShown ? _kbShow.width() : 0) - (_cmdStartShown ? _cmdStart.width() : 0), _field.height()); _toHistoryEnd.move((width() - _toHistoryEnd.width()) / 2, _scroll.y() + _scroll.height() - _toHistoryEnd.height() - st::historyToEndSkip); @@ -4586,14 +4459,8 @@ MsgId HistoryWidget::replyToId() const { } void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown, HistoryItem *resizedItem, bool scrollToIt) { - if (!hist || (!_histInited && !initial)) return; - - if (!isVisible() || _showAnim.animating()) { - if (initial) { - _histInited = false; - } else { - _histNeedUpdate = true; - } + if (!_history || (initial && _histInited) || (!initial && !_histInited)) return; + if (_firstLoadRequest) { if (resizedItem) _list->recountHeight(true); return; // scrollTopMax etc are not working after recountHeight() } @@ -4602,7 +4469,7 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown, if (isBotStart()) { newScrollHeight -= _botStart.height(); } else { - if (hist->readyForWork() && (!histPeer->chat || !histPeer->asChat()->forbidden)) { + if (!_peer->chat || !_peer->asChat()->forbidden) { newScrollHeight -= (_field.height() + 2 * st::sendPadding); } if (replyToId() || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0)) { @@ -4620,7 +4487,7 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown, } if (!initial) { - hist->lastScrollTop = _scroll.scrollTop(); + _history->lastScrollTop = _scroll.scrollTop(); } int32 newSt = _list->recountHeight(!!resizedItem); bool washidden = _scroll.isHidden(); @@ -4628,8 +4495,8 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown, _scroll.show(); } _list->updateSize(); + int32 firstItemY = _list->height() - _history->height - st::historyPadding; if (resizedItem && !resizedItem->detached() && scrollToIt) { - int32 firstItemY = _list->height() - hist->height - st::historyPadding; if (newSt + _scroll.height() < firstItemY + resizedItem->block()->y + resizedItem->y + resizedItem->height()) { newSt = firstItemY + resizedItem->block()->y + resizedItem->y + resizedItem->height() - _scroll.height(); } @@ -4641,7 +4508,6 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown, if (washidden) { _scroll.hide(); } - if (!hist->readyForWork()) return; if ((!initial && !wasAtBottom) || loadedDown) { _scroll.scrollToY(newSt + addToY); @@ -4651,69 +4517,94 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown, if (initial) { _histInited = true; } - _histNeedUpdate = false; int32 toY = History::ScrollMax; - if (initial && hist->activeMsgId && !hist->lastWidth) { - HistoryItem *item = App::histItemById(hist->activeMsgId); + if (initial && _history->lastWidth) { + toY = newSt; + _history->lastWidth = 0; + } else if (initial && _showAtMsgId > 0) { + HistoryItem *item = App::histItemById(_showAtMsgId); if (!item || item->detached()) { - hist->activeMsgId = 0; + _showAtMsgId = 0; + _histInited = false; return updateListSize(addToY, initial); } else { - toY = (_scroll.height() > item->height()) ? qMax(item->y + item->block()->y - (_scroll.height() - item->height()) / 2, 0) : (item->y + item->block()->y); + toY = (_scroll.height() > item->height()) ? qMax(firstItemY + item->y + item->block()->y - (_scroll.height() - item->height()) / 2, 0) : (firstItemY + item->y + item->block()->y); _animActiveStart = getms(); _animActiveTimer.start(AnimationTimerDelta); + _activeAnimMsgId = _showAtMsgId; } - } else if (initial && hist->unreadBar) { - toY = hist->unreadBar->y + hist->unreadBar->block()->y; - } else if (hist->showFrom) { - toY = hist->showFrom->y + hist->showFrom->block()->y; + } else if (initial && _history->unreadBar) { + toY = firstItemY + _history->unreadBar->y + _history->unreadBar->block()->y; + } else if (_history->showFrom) { + toY = firstItemY + _history->showFrom->y + _history->showFrom->block()->y; if (toY < _scroll.scrollTopMax() + st::unreadBarHeight) { - hist->addUnreadBar(); - if (hist->unreadBar) { - hist->activeMsgId = 0; + _history->addUnreadBar(); + if (_history->unreadBar) { + _showAtMsgId = ShowAtUnreadMsgId; + _histInited = false; return updateListSize(0, true); } } - } else if (initial && hist->lastWidth) { - toY = newSt; - hist->lastWidth = 0; } else { } _scroll.scrollToY(toY); } void HistoryWidget::addMessagesToFront(const QVector &messages) { - int32 oldH = hist->height; + int32 oldH = _history->height; _list->messagesReceived(messages); - updateListSize(hist->height - oldH); - updateBotKeyboard(); - checkUnreadLoaded(true); + if (!_firstLoadRequest) { + updateListSize(_history->height - oldH); + updateBotKeyboard(); + } } void HistoryWidget::addMessagesToBack(const QVector &messages) { - int32 sliceFrom = 0; _list->messagesReceivedDown(messages); - updateListSize(0, false, true); - checkUnreadLoaded(true); + if (!_firstLoadRequest) { + updateListSize(0, false, true); + } +} + +void HistoryWidget::countHistoryShowFrom() { + if (_showAtMsgId != ShowAtUnreadMsgId || !_history->unreadCount) { + _history->showFrom = 0; + return; + } + if (_history->showFrom) return; + + int32 skip = qMin(MessagesPerPage / 2, _history->unreadCount); + for (History::const_iterator i = _history->cend(); i != _history->cbegin();) { + --i; + for (HistoryBlock::const_iterator j = (*i)->cend(); j != (*i)->cbegin();) { + --j; + if ((*j)->itemType() == HistoryItem::MsgType) { + if (!--skip) { + _history->showFrom = *j; + return; + } + } + } + } } void HistoryWidget::updateBotKeyboard() { bool changed = false; bool wasVisible = _kbShown || _kbReplyTo; - if ((_replyToId && !_replyTo) || !hist) { + if ((_replyToId && !_replyTo) || !_history) { changed = _keyboard.updateMarkup(0); } else if (_replyTo) { changed = _keyboard.updateMarkup(_replyTo); } else { - changed = _keyboard.updateMarkup(hist->lastKeyboardId ? App::histItemById(hist->lastKeyboardId) : 0); + changed = _keyboard.updateMarkup(_history->lastKeyboardId ? App::histItemById(_history->lastKeyboardId) : 0); } updateCmdStartShown(); if (!changed) return; bool hasMarkup = _keyboard.hasMarkup(), forceReply = _keyboard.forceReply() && !_replyTo; if (hasMarkup || forceReply) { - if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == hist->lastKeyboardId && hist->lastKeyboardUsed) _kbWasHidden = true; + if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == _history->lastKeyboardId && _history->lastKeyboardUsed) _kbWasHidden = true; if (!isBotStart() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) { if (!_showAnim.animating()) { if (hasMarkup) { @@ -4731,7 +4622,7 @@ void HistoryWidget::updateBotKeyboard() { int32 maxh = hasMarkup ? qMin(_keyboard.height(), int(st::maxFieldHeight) - (int(st::maxFieldHeight) / 2)) : 0; _field.setMaxHeight(st::maxFieldHeight - maxh); _kbShown = hasMarkup; - _kbReplyTo = (hist->peer->chat || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0; + _kbReplyTo = (_history->peer->chat || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0; if (_kbReplyTo && !_replyToId) { updateReplyToName(); _replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions); @@ -4772,7 +4663,7 @@ void HistoryWidget::updateBotKeyboard() { } void HistoryWidget::updateToEndVisibility() { - bool toEndVisible = !_showAnim.animating() && hist && hist->readyForWork() && (!hist->loadedAtBottom() || _replyReturn || _scroll.scrollTop() + st::wndMinHeight < _scroll.scrollTopMax()); + bool toEndVisible = !_showAnim.animating() && _history && !_firstLoadRequest && (!_history->loadedAtBottom() || _replyReturn || _scroll.scrollTop() + st::wndMinHeight < _scroll.scrollTopMax()); if (toEndVisible && _toHistoryEnd.isHidden()) { _toHistoryEnd.show(); } else if (!toEndVisible && !_toHistoryEnd.isHidden()) { @@ -4797,13 +4688,14 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) { a_recordOver.restart(); _recordAnim.start(); } else if (_inReply) { - App::main()->showPeer(histPeer->id, replyToId()); + App::main()->showPeerHistory(_peer->id, replyToId()); } } void HistoryWidget::keyPressEvent(QKeyEvent *e) { - if (!hist) return; + if (!_history) return; + MsgId msgid = qMax(_showAtMsgId, 0); if (e->key() == Qt::Key_Escape) { e->ignore(); } else if (e->key() == Qt::Key_Back) { @@ -4812,8 +4704,8 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::MetaModifier)) { PeerData *after = 0; MsgId afterMsgId = 0; - App::main()->peerAfter(histPeer, hist ? hist->activeMsgId : 0, after, afterMsgId); - if (after) App::main()->showPeer(after->id, afterMsgId); + App::main()->peerAfter(_peer, msgid, after, afterMsgId); + if (after) App::main()->showPeerHistory(after->id, afterMsgId); } else { _scroll.keyPressEvent(e); } @@ -4821,8 +4713,8 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::MetaModifier)) { PeerData *before = 0; MsgId beforeMsgId = 0; - App::main()->peerBefore(histPeer, hist ? hist->activeMsgId : 0, before, beforeMsgId); - if (before) App::main()->showPeer(before->id, beforeMsgId); + App::main()->peerBefore(_peer, msgid, before, beforeMsgId); + if (before) App::main()->showPeerHistory(before->id, beforeMsgId); } else { _scroll.keyPressEvent(e); } @@ -4830,8 +4722,8 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { if (e->modifiers() & Qt::AltModifier) { PeerData *after = 0; MsgId afterMsgId = 0; - App::main()->peerAfter(histPeer, hist ? hist->activeMsgId : 0, after, afterMsgId); - if (after) App::main()->showPeer(after->id, afterMsgId); + App::main()->peerAfter(_peer, msgid, after, afterMsgId); + if (after) App::main()->showPeerHistory(after->id, afterMsgId); } else if (!(e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier))) { _scroll.keyPressEvent(e); } @@ -4839,8 +4731,8 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { if (e->modifiers() & Qt::AltModifier) { PeerData *before = 0; MsgId beforeMsgId = 0; - App::main()->peerBefore(histPeer, hist ? hist->activeMsgId : 0, before, beforeMsgId); - if (before) App::main()->showPeer(before->id, beforeMsgId); + App::main()->peerBefore(_peer, msgid, before, beforeMsgId); + if (before) App::main()->showPeerHistory(before->id, beforeMsgId); } else if (!(e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier))) { _scroll.keyPressEvent(e); } @@ -4848,11 +4740,11 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { PeerData *p = 0; MsgId m = 0; if ((e->modifiers() & Qt::ShiftModifier) || e->key() == Qt::Key_Backtab) { - App::main()->peerBefore(histPeer, hist ? hist->activeMsgId : 0, p, m); + App::main()->peerBefore(_peer, msgid, p, m); } else { - App::main()->peerAfter(histPeer, hist ? hist->activeMsgId : 0, p, m); + App::main()->peerAfter(_peer, msgid, p, m); } - if (p) App::main()->showPeer(p->id, m); + if (p) App::main()->showPeerHistory(p->id, m); } else { e->ignore(); } @@ -4866,37 +4758,36 @@ void HistoryWidget::onFieldTabbed() { } void HistoryWidget::onStickerSend(DocumentData *sticker) { - if (!hist || !sticker) return; + if (!_history || !sticker) return; - App::main()->readServerHistory(hist, false); + App::main()->readServerHistory(_history, false); + fastShowAtEnd(_history); uint64 randomId = MTP::nonce(); MsgId newId = clientMsgId(); - hist->loadAround(0); - bool lastKeyboardUsed = lastForceReplyReplied(); - bool out = (histPeer->input.type() != mtpc_inputPeerSelf), unread = (histPeer->input.type() != mtpc_inputPeerSelf); - int32 flags = newMessageFlags(histPeer); // unread, out + bool out = (_peer->input.type() != mtpc_inputPeerSelf), unread = (_peer->input.type() != mtpc_inputPeerSelf); + int32 flags = newMessageFlags(_peer); // unread, out int32 sendFlags = 0; if (replyToId()) { flags |= MTPDmessage::flag_reply_to_msg_id; sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id; } - hist->addToBackDocument(newId, flags, replyToId(), date(MTP_int(unixtime())), MTP::authedId(), sticker); + _history->addToBackDocument(newId, flags, replyToId(), date(MTP_int(unixtime())), MTP::authedId(), sticker); - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), histPeer->input, MTP_int(replyToId()), MTP_inputMediaDocument(MTP_inputDocument(MTP_long(sticker->id), MTP_long(sticker->access))), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); - App::main()->finishForwarding(hist); + _history->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), _peer->input, MTP_int(replyToId()), MTP_inputMediaDocument(MTP_inputDocument(MTP_long(sticker->id), MTP_long(sticker->access))), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, _history->sendRequestId); + App::main()->finishForwarding(_history); cancelReply(lastKeyboardUsed); if (sticker->sticker()) App::main()->incrementSticker(sticker); App::historyRegRandom(randomId, newId); - App::main()->historyToDown(hist); + App::main()->historyToDown(_history); App::main()->dialogsToUp(); - peerMessagesUpdated(histPeer->id); + peerMessagesUpdated(_peer->id); if (!_attachMention.isHidden()) _attachMention.hideStart(); if (!_attachType.isHidden()) _attachType.hideStart(); @@ -4944,7 +4835,7 @@ void HistoryWidget::onReplyToMessage() { } bool HistoryWidget::lastForceReplyReplied(MsgId replyTo) const { - return _keyboard.forceReply() && _keyboard.forMsgId() == hist->lastKeyboardId && _keyboard.forMsgId() == (replyTo < 0 ? replyToId() : replyTo); + return _keyboard.forceReply() && _keyboard.forMsgId() == _history->lastKeyboardId && _keyboard.forMsgId() == (replyTo < 0 ? replyToId() : replyTo); } void HistoryWidget::cancelReply(bool lastKeyboardUsed) { @@ -5114,24 +5005,34 @@ void HistoryWidget::updatePreview() { } void HistoryWidget::onCancel() { - if (App::main()) App::main()->showPeer(0); + if (App::main()) App::main()->showDialogs(); emit cancelled(); } void HistoryWidget::onFullPeerUpdated(PeerData *data) { - if (_list && data == histPeer) { + int32 newScrollTop = _scroll.scrollTop(); + if (_list && data == _peer) { checkMentionDropdown(); + int32 lh = _list->height(), st = _scroll.scrollTop(); _list->updateBotInfo(); + newScrollTop = st + _list->height() - lh; } if (updateCmdStartShown()) { updateControlsVisibility(); resizeEvent(0); update(); } + if (newScrollTop != _scroll.scrollTop()) { + if (_scroll.isVisible()) { + _scroll.scrollToY(newScrollTop); + } else { + _history->lastScrollTop = newScrollTop; + } + } } void HistoryWidget::peerUpdated(PeerData *data) { - if (data && data == histPeer) { + if (data && data == _peer) { updateListSize(); if (!_showAnim.animating()) updateControlsVisibility(); if (data->chat && data->asChat()->count > 0 && data->asChat()->participants.isEmpty()) { @@ -5213,19 +5114,25 @@ void HistoryWidget::onClearSelected() { } void HistoryWidget::onAnimActiveStep() { - if (!hist || !hist->activeMsgId) return _animActiveTimer.stop(); - HistoryItem *item = App::histItemById(hist->activeMsgId); + if (!_history || _activeAnimMsgId <= 0) return _animActiveTimer.stop(); + + HistoryItem *item = App::histItemById(_activeAnimMsgId); if (!item || item->detached()) return _animActiveTimer.stop(); - App::main()->msgUpdated(histPeer->id, item); + if (getms() - _animActiveStart > st::activeFadeInDuration + st::activeFadeOutDuration) { + stopAnimActive(); + } else { + App::main()->msgUpdated(_peer->id, item); + } } -uint64 HistoryWidget::animActiveTime() const { - return _animActiveTimer.isActive() ? (getms() - _animActiveStart) : 0; +uint64 HistoryWidget::animActiveTime(MsgId id) const { + return (id == _activeAnimMsgId && _animActiveTimer.isActive()) ? (getms() - _animActiveStart) : 0; } void HistoryWidget::stopAnimActive() { _animActiveTimer.stop(); + _activeAnimMsgId = 0; } void HistoryWidget::fillSelectedItems(SelectedItemSet &sel, bool forDelete) { @@ -5458,32 +5365,16 @@ void HistoryWidget::paintEvent(QPaintEvent *e) { } if (_list) { - if (!_scroll.isHidden()) { - if (!_field.isHidden() || _recording) { - drawField(p); - if (_send.isHidden()) { - drawRecordButton(p); - if (_recording) drawRecording(p); - } + if (!_field.isHidden() || _recording) { + drawField(p); + if (_send.isHidden()) { + drawRecordButton(p); + if (_recording) drawRecording(p); } - } else { + } + if (_scroll.isHidden()) { QPoint dogPos((width() - st::msgDogImg.pxWidth()) / 2, ((height() - _field.height() - 2 * st::sendPadding - st::msgDogImg.pxHeight()) * 4) / 9); p.drawPixmap(dogPos, *cChatDogImage()); - - int32 pointsCount = 8, w = pointsCount * (st::introPointWidth + 2 * st::introPointDelta), h = st::introPointHeight; - int32 pointsLeft = (width() - w) / 2 + st::introPointDelta - st::introPointLeft, pointsTop = dogPos.y() + (st::msgDogImg.pxHeight() * 6) / 5; - - int32 curPoint = histRequestsCount % pointsCount; - - p.fillRect(pointsLeft + curPoint * (st::introPointWidth + 2 * st::introPointDelta), pointsTop, st::introPointHoverWidth, st::introPointHoverHeight, App::introPointHoverColor()->b); - - // points - p.setOpacity(st::introPointAlpha); - int32 x = pointsLeft + st::introPointLeft; - for (int32 i = 0; i < pointsCount; ++i) { - p.fillRect(x, pointsTop + st::introPointTop, st::introPointWidth, st::introPointHeight, st::introPointColor->b); - x += (st::introPointWidth + 2 * st::introPointDelta); - } } } else { style::font font(st::msgServiceFont); @@ -5502,7 +5393,7 @@ QRect HistoryWidget::historyRect() const { } void HistoryWidget::destroyData() { - showPeer(0); + showPeerHistory(0, 0); } QStringList HistoryWidget::getMediasFromMime(const QMimeData *d) { diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 099271162..32cab7e05 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -82,6 +82,7 @@ public: void updateBotInfo(bool recount = true); bool wasSelectedText() const; + void setFirstLoading(bool loading); ~HistoryList(); @@ -130,6 +131,8 @@ private: ScrollArea *scrollArea; int32 currentBlock, currentItem; + bool _firstLoading; + QTimer linkTipTimer; Qt::CursorShape _cursor; @@ -343,6 +346,7 @@ public: void start(); void messagesReceived(const MTPmessages_Messages &messages, mtpRequestId requestId); + void historyLoaded(); void windowShown(); bool isActive() const; @@ -369,7 +373,8 @@ public: void loadMessages(); void loadMessagesDown(); - void loadMessagesAround(); + void firstLoadMessages(); + void delayedShowAt(MsgId showAtMsgId); void peerMessagesUpdated(PeerId peer); void peerMessagesUpdated(); @@ -397,7 +402,6 @@ public: void confirmSendImage(const ReadyLocalMedia &img); void cancelSendImage(); - void checkUnreadLoaded(bool checkOnlyShow = false); void updateControlsVisibility(); void updateOnlineDisplay(int32 x, int32 w); void updateOnlineDisplayTimer(); @@ -408,10 +412,7 @@ public: void shareContact(const PeerId &peer, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, int32 userId = 0); PeerData *peer() const; - PeerData *activePeer() const; - MsgId activeMsgId() const; - int32 lastWidth() const; - int32 lastScrollTop() const; + MsgId msgId() const; void animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTopBarCache, bool back = false); bool showStep(float64 ms); @@ -427,7 +428,7 @@ public: QString prepareMessage(QString text); - uint64 animActiveTime() const; + uint64 animActiveTime(MsgId id) const; void stopAnimActive(); void fillSelectedItems(SelectedItemSet &sel, bool forDelete = true); @@ -470,6 +471,11 @@ public: DragState getDragState(const QMimeData *d); + void fastShowAtEnd(History *h); + void showPeerHistory(const PeerId &peer, MsgId showAtMsgId); + void clearDelayedShowAt(); + void clearAllLoadRequests(); + ~HistoryWidget(); signals: @@ -523,8 +529,7 @@ public slots: void onSendConfirmed(); void onSendCancelled(); void onPhotoFailed(quint64 id); - void showPeer(const PeerId &peer, MsgId msgId = 0, bool force = false, bool leaveActive = false); - void clearLoadingAround(); + void activate(); void onMentionHashtagOrBotCommandInsert(QString str); void onTextChange(); @@ -595,6 +600,8 @@ private: void addMessagesToFront(const QVector &messages); void addMessagesToBack(const QVector &messages); + void countHistoryShowFrom(); + void updateToEndVisibility(); void stickersGot(const MTPmessages_AllStickers &stickers); @@ -609,21 +616,20 @@ private: void updateDragAreas(); - bool _loadingMessages; - int32 histRequestsCount; - PeerData *histPeer; - History *_activeHist; - MTPinputPeer histInputPeer; - mtpRequestId histPreloading, histPreloadingDown; - QVector histPreload, histPreloadDown; + PeerData *_peer; + MsgId _showAtMsgId; - int32 _loadingAroundId; - mtpRequestId _loadingAroundRequest; + mtpRequestId _firstLoadRequest, _preloadRequest, _preloadDownRequest; + + MsgId _delayedShowAtMsgId; + mtpRequestId _delayedShowAtRequest; + + MsgId _activeAnimMsgId; ScrollArea _scroll; HistoryList *_list; - History *hist; - bool _histInited, _histNeedUpdate; // initial updateListSize() called + History *_history; + bool _histInited; // initial updateListSize() called IconedButton _toHistoryEnd; @@ -656,19 +662,17 @@ private: int32 _selCount; // < 0 - text selected, focus list, not _field - LocalImageLoader imageLoader; + LocalImageLoader _imageLoader; bool _synthedTextUpdate; - int64 serviceImageCacheSize; - QImage confirmImage; - PhotoId confirmImageId; - bool confirmWithText; - QString confirmSource; + int64 _serviceImageCacheSize; + QImage _confirmImage; + PhotoId _confirmImageId; + bool _confirmWithText; + QString _confirmSource; - QString titlePeerText; - int32 titlePeerTextWidth; - - bool hiderOffered; + QString _titlePeerText; + int32 _titlePeerTextWidth; Animation _showAnim; QPixmap _animCache, _bgAnimCache, _animTopBarCache, _bgAnimTopBarCache; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 4ee53656a..f92f163fd 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -100,7 +100,7 @@ void TopBarWidget::onDeleteContactSure() { PeerData *p = App::main() ? App::main()->profilePeer() : 0; UserData *u = (p && !p->chat) ? p->asUser() : 0; if (u) { - App::main()->showPeer(0, 0, true); + App::main()->showDialogs(); App::wnd()->hideLayer(); MTP::send(MTPcontacts_DeleteContact(u->inputUser), App::main()->rpcDone(&MainWidget::deletedContact, u)); } @@ -120,7 +120,7 @@ void TopBarWidget::onDeleteAndExitSure() { PeerData *p = App::main() ? App::main()->profilePeer() : 0; ChatData *c = (p && p->chat) ? p->asChat() : 0; if (c) { - App::main()->showPeer(0, 0, true); + App::main()->showDialogs(); App::wnd()->hideLayer(); MTP::send(MTPmessages_DeleteChatUser(MTP_int(p->id & 0xFFFFFFFF), App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistory, p), App::main()->rpcFail(&MainWidget::leaveChatFailed, p)); } @@ -353,7 +353,8 @@ MainWidget *TopBarWidget::main() { MainWidget::MainWidget(Window *window) : QWidget(window), _started(0), failedObjId(0), _toForwardNameVersion(0), _dialogsWidth(st::dlgMinWidth), dialogs(this), history(this), profile(0), overview(0), _player(this), _topBar(this), -_forwardConfirm(0), hider(0), _playerHeight(0), _contentScrollAddToY(0), _mediaType(this), _mediaTypeMask(0), +_forwardConfirm(0), _hider(0), _peerInStack(0), _msgIdInStack(0), +_playerHeight(0), _contentScrollAddToY(0), _mediaType(this), _mediaTypeMask(0), updGoodPts(0), updLastPts(0), updPtsCount(0), updDate(0), updQts(-1), updSeq(0), updInited(false), updSkipPtsUpdateLevel(0), _onlineRequest(0), _lastWasOnline(false), _lastSetOnline(0), _isIdle(false), _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _background(0), _api(new ApiWrap(this)) { @@ -377,7 +378,7 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr connect(&_topBar, SIGNAL(clicked()), this, SLOT(onTopBarClick())); connect(&history, SIGNAL(peerShown(PeerData*)), this, SLOT(onPeerShown(PeerData*))); connect(&updateNotifySettingTimer, SIGNAL(timeout()), this, SLOT(onUpdateNotifySettings())); - connect(this, SIGNAL(showPeerAsync(quint64,qint32,bool,bool)), this, SLOT(showPeer(quint64,qint32,bool,bool)), Qt::QueuedConnection); + connect(this, SIGNAL(showPeerAsync(quint64,qint32)), this, SLOT(showPeerHistory(quint64,qint32)), Qt::QueuedConnection); if (audioPlayer()) { connect(audioPlayer(), SIGNAL(updated(const AudioMsgId&)), this, SLOT(audioPlayProgress(const AudioMsgId&))); connect(audioPlayer(), SIGNAL(stopped(const AudioMsgId&)), this, SLOT(audioPlayProgress(const AudioMsgId&))); @@ -402,10 +403,7 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr _player.hide(); - _topBar.raise(); - _player.raise(); - dialogs.raise(); - _mediaType.raise(); + orderWidgets(); MTP::setGlobalFailHandler(rpcFail(&MainWidget::updateFail)); @@ -441,7 +439,7 @@ void MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) { } } updateForwardingTexts(); - showPeer(peer, 0, false, true); + showPeerHistory(peer, ShowAtUnreadMsgId); history.onClearSelected(); history.updateForwarding(); } @@ -602,14 +600,14 @@ void MainWidget::onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data) } else if (data->hasFormat(qsl("application/x-td-forward-pressed"))) { onForward(peer, ForwardPressedMessage); } else { - showPeer(peer, 0, false, true); + showPeerHistory(peer, ShowAtTheEndMsgId); history.onFilesDrop(data); } } void MainWidget::noHider(HistoryHider *destroyed) { - if (hider == destroyed) { - hider = 0; + if (_hider == destroyed) { + _hider = 0; if (cWideMode()) { if (_forwardConfirm) { _forwardConfirm->deleteLater(); @@ -650,16 +648,16 @@ void MainWidget::hiderLayer(HistoryHider *h) { return; } - hider = h; - connect(hider, SIGNAL(forwarded()), &dialogs, SLOT(onCancelSearch())); + _hider = h; + connect(_hider, SIGNAL(forwarded()), &dialogs, SLOT(onCancelSearch())); if (cWideMode()) { - hider->show(); + _hider->show(); resizeEvent(0); dialogs.activate(); } else { dialogsToUp(); - hider->hide(); + _hider->hide(); dialogs.enableShadow(false); QPixmap animCache = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight)); dialogs.enableShadow(); @@ -700,13 +698,14 @@ void MainWidget::shareContactLayer(UserData *contact) { } bool MainWidget::selectingPeer(bool withConfirm) { - return hider ? (withConfirm ? hider->withConfirm() : true) : false; + return _hider ? (withConfirm ? _hider->withConfirm() : true) : false; } void MainWidget::offerPeer(PeerId peer) { - if (hider->offerPeer(peer) && !cWideMode()) { - _forwardConfirm = new ConfirmBox(hider->offeredText(), lang(lng_forward)); - connect(_forwardConfirm, SIGNAL(confirmed()), hider, SLOT(forward())); + App::wnd()->hideLayer(); + if (_hider->offerPeer(peer) && !cWideMode()) { + _forwardConfirm = new ConfirmBox(_hider->offeredText(), lang(lng_forward)); + connect(_forwardConfirm, SIGNAL(confirmed()), _hider, SLOT(forward())); connect(_forwardConfirm, SIGNAL(cancelled()), this, SLOT(onForwardCancel())); connect(_forwardConfirm, SIGNAL(destroyed(QObject*)), this, SLOT(onForwardCancel(QObject*))); App::wnd()->showLayer(_forwardConfirm); @@ -719,14 +718,10 @@ void MainWidget::onForwardCancel(QObject *obj) { if (!obj) _forwardConfirm->startHide(); _forwardConfirm = 0; } - if (hider) hider->offerPeer(0); + if (_hider) _hider->offerPeer(0); } } -void MainWidget::focusPeerSelect() { - hider->setFocus(); -} - void MainWidget::dialogsActivate() { dialogs.activate(); } @@ -740,7 +735,7 @@ bool MainWidget::leaveChatFailed(PeerData *peer, const RPCError &error) { if (error.type() == "CHAT_ID_INVALID") { // left this chat already if ((profile && profile->peer() == peer) || (overview && overview->peer() == peer) || _stack.contains(peer) || history.peer() == peer) { - showPeer(0, 0, false, true); + showDialogs(); } dialogs.removePeer(peer); App::histories().remove(peer->id); @@ -753,7 +748,7 @@ bool MainWidget::leaveChatFailed(PeerData *peer, const RPCError &error) { void MainWidget::deleteHistory(PeerData *peer, const MTPUpdates &updates) { sentUpdatesReceived(updates); if ((profile && profile->peer() == peer) || (overview && overview->peer() == peer) || _stack.contains(peer) || history.peer() == peer) { - showPeer(0, 0, false, true); + showDialogs(); } dialogs.removePeer(peer); App::histories().remove(peer->id); @@ -788,7 +783,7 @@ void MainWidget::deleteHistoryAndContact(UserData *user, const MTPcontacts_Link App::emitPeerUpdated(); if ((profile && profile->peer() == user) || (overview && overview->peer() == user) || _stack.contains(user) || history.peer() == user) { - showPeer(0); + showDialogs(); } dialogs.removePeer(user); MTP::send(MTPmessages_DeleteHistory(user->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, (PeerData*)user)); @@ -813,7 +808,7 @@ void MainWidget::addParticipants(ChatData *chat, const QVector &users MTP::send(MTPmessages_AddChatUser(MTP_int(chat->id & 0xFFFFFFFF), (*i)->inputUser, MTP_int(ForwardOnAdd)), rpcDone(&MainWidget::sentUpdatesReceived), rpcFail(&MainWidget::addParticipantFail, *i), 0, 5); } App::wnd()->hideLayer(); - showPeer(chat->id, 0, false); + showPeerHistory(chat->id, ShowAtTheEndMsgId); } bool MainWidget::addParticipantFail(UserData *user, const RPCError &error) { @@ -831,7 +826,7 @@ bool MainWidget::addParticipantFail(UserData *user, const RPCError &error) { void MainWidget::kickParticipant(ChatData *chat, UserData *user) { MTP::send(MTPmessages_DeleteChatUser(MTP_int(chat->id & 0xFFFFFFFF), user->inputUser), rpcDone(&MainWidget::sentUpdatesReceived), rpcFail(&MainWidget::kickParticipantFail, chat)); App::wnd()->hideLayer(); - showPeer(chat->id, 0, false); + showPeerHistory(chat->id, ShowAtTheEndMsgId); } bool MainWidget::kickParticipantFail(ChatData *chat, const RPCError &error) { @@ -862,7 +857,7 @@ void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &resu if (v->isEmpty()) { if ((profile && profile->peer() == peer) || (overview && overview->peer() == peer) || _stack.contains(peer) || history.peer() == peer) { - showPeer(0); + showDialogs(); } dialogs.removePeer(peer); } else { @@ -1015,9 +1010,8 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl } void MainWidget::sendMessage(History *hist, const QString &text, MsgId replyTo) { + hist->getReadyFor(ShowAtTheEndMsgId); readServerHistory(hist, false); - hist->loadAround(0); - if (history.peer()) sendPreparedText(hist, history.prepareMessage(text), replyTo); } @@ -1050,7 +1044,7 @@ void MainWidget::saveRecentHashtags(const QString &text) { } void MainWidget::readServerHistory(History *hist, bool force) { - if (!hist || (!force && (!hist->unreadCount || !hist->readyForWork()))) return; + if (!hist || (!force && !hist->unreadCount)) return; ReadRequests::const_iterator i = _readRequests.constFind(hist->peer); if (i == _readRequests.cend()) { @@ -1059,8 +1053,8 @@ void MainWidget::readServerHistory(History *hist, bool force) { } } -uint64 MainWidget::animActiveTime() const { - return history.animActiveTime(); +uint64 MainWidget::animActiveTime(MsgId id) const { + return history.animActiveTime(id); } void MainWidget::stopAnimActive() { @@ -1078,7 +1072,7 @@ void MainWidget::insertBotCommand(const QString &cmd) { void MainWidget::searchMessages(const QString &query) { App::wnd()->hideMediaview(); dialogs.searchMessages(query); - if (!cWideMode()) onShowDialogs(); + if (!cWideMode()) showDialogs(); } void MainWidget::preloadOverviews(PeerData *peer) { @@ -1724,13 +1718,11 @@ void MainWidget::cancelSendImage() { } void MainWidget::dialogsCancelled() { - if (hider) { - hider->startHide(); - noHider(hider); - history.activate(); - } else { - history.activate(); + if (_hider) { + _hider->startHide(); + noHider(_hider); } + history.activate(); } void MainWidget::serviceNotification(const QString &msg, const MTPMessageMedia &media, bool unread) { @@ -1870,15 +1862,15 @@ void MainWidget::pushReplyReturn(HistoryItem *item) { } void MainWidget::setInnerFocus() { - if (hider || !history.peer()) { - if (hider && hider->wasOffered()) { - hider->setFocus(); + if (_hider || !history.peer()) { + if (_hider && _hider->wasOffered()) { + _hider->setFocus(); } else if (overview) { overview->activate(); } else if (profile) { profile->activate(); } else { - dialogs.setInnerFocus(); + dialogsActivate(); } } else if (profile) { profile->setFocus(); @@ -1891,88 +1883,104 @@ void MainWidget::createDialogAtTop(History *history, int32 unreadCount) { dialogs.createDialogAtTop(history, unreadCount); } -void MainWidget::showPeer(quint64 peerId, qint32 msgId, bool back, bool force) { - if (!back && _stack.size() == 1 && _stack[0]->type() == HistoryStackItem && _stack[0]->peer->id == peerId) { - if (cWideMode() || !selectingPeer()) { - back = true; - } +void MainWidget::choosePeer(PeerId peerId, MsgId showAtMsgId) { + if (selectingPeer()) { + offerPeer(peerId); + } else { + showPeerHistory(peerId, showAtMsgId); } +} + +void MainWidget::clearBotStartToken(PeerData *peer) { + if (peer && !peer->chat && peer->asUser()->botInfo) { + peer->asUser()->botInfo->startToken = QString(); + } +} + +void MainWidget::showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool back) { + if (!back && (!peerId || (_stack.size() == 1 && _stack[0]->type() == HistoryStackItem && _stack[0]->peer->id == peerId))) { + back = true; + } + App::wnd()->hideLayer(); + if (_hider) { + _hider->startHide(); + _hider = 0; + } + QPixmap animCache, animTopBarCache; - if (force && hider) { - hider->startHide(); - hider = 0; - } - if (force || !selectingPeer()) { - if (!animating() && ((history.isHidden() && history.activePeer() && (profile || overview)) || (!cWideMode() && (history.isHidden() || !peerId)))) { - dialogs.enableShadow(false); - if (peerId) { - _topBar.enableShadow(false); - if (cWideMode()) { - animCache = myGrab(this, QRect(_dialogsWidth, _playerHeight + st::topBarHeight, width() - _dialogsWidth, height() - _playerHeight - st::topBarHeight)); - } else { - animCache = myGrab(this, QRect(0, _playerHeight + st::topBarHeight, _dialogsWidth, height() - _playerHeight - st::topBarHeight)); - } - } else if (cWideMode()) { - animCache = myGrab(this, QRect(_dialogsWidth, _playerHeight, width() - _dialogsWidth, height() - _playerHeight)); + if (!animating() && ((history.isHidden() && (profile || overview)) || (!cWideMode() && (history.isHidden() || !peerId)))) { + dialogs.enableShadow(false); + if (peerId) { + _topBar.enableShadow(false); + if (cWideMode()) { + animCache = myGrab(this, QRect(_dialogsWidth, _playerHeight + st::topBarHeight, width() - _dialogsWidth, height() - _playerHeight - st::topBarHeight)); } else { - animCache = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight)); - } - if (peerId || cWideMode()) { - animTopBarCache = myGrab(this, QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight)); - } - dialogs.enableShadow(); - _topBar.enableShadow(); - history.show(); - } - } - history.showPeer(peerId, msgId, force); - if (force || !selectingPeer()) { - bool noPeer = (!history.peer() || !history.peer()->id), onlyDialogs = noPeer && !cWideMode(); - if (profile || overview) { - if (profile) { - profile->hide(); - profile->clear(); - profile->deleteLater(); - profile->rpcInvalidate(); - profile = 0; - } - if (overview) { - overview->hide(); - overview->clear(); - overview->deleteLater(); - overview->rpcInvalidate(); - overview = 0; - } - _stack.clear(); - } - if (onlyDialogs) { - _topBar.hide(); - history.hide(); - if (!animating()) { - dialogs.show(); - if (!animCache.isNull()) { - dialogs.animShow(animCache); - } + animCache = myGrab(this, QRect(0, _playerHeight + st::topBarHeight, _dialogsWidth, height() - _playerHeight - st::topBarHeight)); } + } else if (cWideMode()) { + animCache = myGrab(this, QRect(_dialogsWidth, _playerHeight, width() - _dialogsWidth, height() - _playerHeight)); } else { - if (noPeer) { - _topBar.hide(); - resizeEvent(0); + animCache = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight)); + } + if (peerId || cWideMode()) { + animTopBarCache = myGrab(this, QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight)); + } + dialogs.enableShadow(); + _topBar.enableShadow(); + history.show(); + } + if (history.peer() && history.peer()->id != peerId) clearBotStartToken(history.peer()); + history.showPeerHistory(peerId, showAtMsgId); + + bool noPeer = (!history.peer() || !history.peer()->id), onlyDialogs = noPeer && !cWideMode(); + if (profile || overview) { + if (profile) { + profile->hide(); + profile->clear(); + profile->deleteLater(); + profile->rpcInvalidate(); + profile = 0; + } + if (overview) { + overview->hide(); + overview->clear(); + overview->deleteLater(); + overview->rpcInvalidate(); + overview = 0; + } + clearBotStartToken(_peerInStack); + _peerInStack = 0; + _msgIdInStack = 0; + _stack.clear(); + } + if (onlyDialogs) { + _topBar.hide(); + history.hide(); + if (!animating()) { + dialogs.show(); + if (!animCache.isNull()) { + dialogs.animShow(animCache); } - if (!cWideMode()) dialogs.hide(); - if (!animating()) { - history.show(); - if (!animCache.isNull()) { - history.animShow(animCache, animTopBarCache, back); - } else { - QTimer::singleShot(0, this, SLOT(setInnerFocus())); - } + } + } else { + if (noPeer) { + _topBar.hide(); + resizeEvent(0); + } + if (!cWideMode() && !dialogs.isHidden()) dialogs.hide(); + if (!animating()) { + if (history.isHidden()) history.show(); + if (!animCache.isNull()) { + history.animShow(animCache, animTopBarCache, back); + } else { + QTimer::singleShot(0, this, SLOT(setInnerFocus())); } } } + if (!dialogs.isHidden()) { - dialogs.scrollToPeer(peerId, msgId); + dialogs.scrollToPeer(peerId, showAtMsgId); dialogs.update(); } App::wnd()->getTitle()->updateBackButton(); @@ -2005,11 +2013,11 @@ PeerData *MainWidget::peer() { } PeerData *MainWidget::activePeer() { - return history.activePeer(); + return history.peer() ? history.peer() : _peerInStack; } MsgId MainWidget::activeMsgId() { - return history.activeMsgId(); + return history.peer() ? history.msgId() : _msgIdInStack; } PeerData *MainWidget::profilePeer() { @@ -2059,7 +2067,9 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool } else if (profile) { _stack.push_back(new StackItemProfile(profile->peer(), profile->lastScrollTop(), profile->allMediaShown())); } else if (history.peer()) { - _stack.push_back(new StackItemHistory(history.peer(), history.lastWidth(), history.lastScrollTop(), history.replyReturns(), history.kbWasHidden())); + _peerInStack = history.peer(); + _msgIdInStack = history.msgId(); + _stack.push_back(new StackItemHistory(_peerInStack, _msgIdInStack, history.replyReturns(), history.kbWasHidden())); } } if (overview) { @@ -2086,14 +2096,13 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool overview->fastShow(); } history.animStop(); - history.showPeer(0, 0, false, true); + if (back) clearBotStartToken(history.peer()); + history.showPeerHistory(0, 0); history.hide(); if (!cWideMode()) dialogs.hide(); - _topBar.raise(); - _player.raise(); - dialogs.raise(); - _mediaType.raise(); - if (hider) hider->raise(); + + orderWidgets(); + App::wnd()->getTitle()->updateBackButton(); } @@ -2112,7 +2121,9 @@ void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop, } else if (profile) { _stack.push_back(new StackItemProfile(profile->peer(), profile->lastScrollTop(), profile->allMediaShown())); } else { - _stack.push_back(new StackItemHistory(history.peer(), history.lastWidth(), history.lastScrollTop(), history.replyReturns(), history.kbWasHidden())); + _peerInStack = history.peer(); + _msgIdInStack = history.msgId(); + _stack.push_back(new StackItemHistory(_peerInStack, _msgIdInStack, history.replyReturns(), history.kbWasHidden())); } } if (overview) { @@ -2133,32 +2144,36 @@ void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop, resizeEvent(0); profile->animShow(animCache, animTopBarCache, back, lastScrollTop, allMediaShown); history.animStop(); - history.showPeer(0, 0, false, true); + if (back) clearBotStartToken(history.peer()); + history.showPeerHistory(0, 0); history.hide(); - _topBar.raise(); - _player.raise(); - dialogs.raise(); - _mediaType.raise(); - if (hider) hider->raise(); + + orderWidgets(); + App::wnd()->getTitle()->updateBackButton(); } void MainWidget::showBackFromStack() { if (selectingPeer()) return; if (_stack.isEmpty()) { - if (cWideMode()) { - showPeer(0, 0, false, true); - QTimer::singleShot(0, this, SLOT(setInnerFocus())); - } else { - onShowDialogs(); - } + showDialogs(); + QTimer::singleShot(0, this, SLOT(setInnerFocus())); return; } StackItem *item = _stack.back(); _stack.pop_back(); if (item->type() == HistoryStackItem) { + _peerInStack = 0; + _msgIdInStack = 0; + for (int32 i = _stack.size(); i > 0;) { + if (_stack.at(--i)->type() == HistoryStackItem) { + _peerInStack = static_cast(_stack.at(i))->peer; + _msgIdInStack = static_cast(_stack.at(i))->msgId; + break; + } + } StackItemHistory *histItem = static_cast(item); - showPeer(histItem->peer->id, App::main()->activeMsgId(), true); + showPeerHistory(histItem->peer->id, App::main()->activeMsgId(), true); history.setReplyReturns(histItem->peer->id, histItem->replyReturns); if (histItem->kbWasHidden) history.setKbWasHidden(); } else if (item->type() == ProfileStackItem) { @@ -2171,6 +2186,14 @@ void MainWidget::showBackFromStack() { delete item; } +void MainWidget::orderWidgets() { + _topBar.raise(); + _player.raise(); + dialogs.raise(); + _mediaType.raise(); + if (_hider) _hider->raise(); +} + QRect MainWidget::historyRect() const { QRect r(history.historyRect()); r.moveLeft(r.left() + history.x()); @@ -2340,8 +2363,8 @@ void MainWidget::showAll() { App::wnd()->showLayer(new ConfirmBox(lang(lng_signin_password_removed), true, lang(lng_continue))); } if (cWideMode()) { - if (hider) { - hider->show(); + if (_hider) { + _hider->show(); if (_forwardConfirm) { App::wnd()->hideLayer(true); _forwardConfirm = 0; @@ -2360,11 +2383,11 @@ void MainWidget::showAll() { _topBar.show(); } } else { - if (hider) { - hider->hide(); - if (!_forwardConfirm && hider->wasOffered()) { - _forwardConfirm = new ConfirmBox(hider->offeredText(), lang(lng_forward)); - connect(_forwardConfirm, SIGNAL(confirmed()), hider, SLOT(forward())); + if (_hider) { + _hider->hide(); + if (!_forwardConfirm && _hider->wasOffered()) { + _forwardConfirm = new ConfirmBox(_hider->offeredText(), lang(lng_forward)); + connect(_forwardConfirm, SIGNAL(confirmed()), _hider, SLOT(forward())); connect(_forwardConfirm, SIGNAL(cancelled()), this, SLOT(onForwardCancel())); App::wnd()->showLayer(_forwardConfirm, true); } @@ -2402,14 +2425,14 @@ void MainWidget::resizeEvent(QResizeEvent *e) { _player.setGeometry(_dialogsWidth, 0, width() - _dialogsWidth, _player.height()); _topBar.setGeometry(_dialogsWidth, _playerHeight, width() - _dialogsWidth, st::topBarHeight + st::titleShadow); history.setGeometry(_dialogsWidth, _playerHeight + tbh, width() - _dialogsWidth, height() - _playerHeight - tbh); - if (hider) hider->setGeometry(QRect(_dialogsWidth, 0, width() - _dialogsWidth, height())); + if (_hider) _hider->setGeometry(QRect(_dialogsWidth, 0, width() - _dialogsWidth, height())); } else { _dialogsWidth = width(); _player.setGeometry(0, 0, _dialogsWidth, _player.height()); dialogs.setGeometry(0, _playerHeight, _dialogsWidth + st::dlgShadow, height() - _playerHeight); _topBar.setGeometry(0, _playerHeight, _dialogsWidth, st::topBarHeight + st::titleShadow); history.setGeometry(0, _playerHeight + tbh, _dialogsWidth, height() - _playerHeight - tbh); - if (hider) hider->setGeometry(QRect(0, 0, _dialogsWidth, height())); + if (_hider) _hider->setGeometry(QRect(0, 0, _dialogsWidth, height())); } _mediaType.move(width() - _mediaType.width(), _playerHeight + st::topBarHeight); if (profile) profile->setGeometry(history.geometry()); @@ -2433,8 +2456,8 @@ bool MainWidget::needBackButton() { return overview || profile || (history.peer() && history.peer()->id); } -void MainWidget::onShowDialogs() { - showPeer(0, 0, false, true); +void MainWidget::showDialogs() { + showPeerHistory(0, 0); } void MainWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth) { @@ -2450,9 +2473,9 @@ void MainWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth) { void MainWidget::topBarShadowParams(int32 &x, float64 &o) { if (!cWideMode() && dialogs.isHidden()) { if (profile) { - if (!history.activePeer()) profile->topBarShadowParams(x, o); + if (!_peerInStack) profile->topBarShadowParams(x, o); } else if (overview) { - if (!history.activePeer()) overview->topBarShadowParams(x, o); + if (!_peerInStack) overview->topBarShadowParams(x, o); } else { history.topBarShadowParams(x, o); } @@ -2787,7 +2810,7 @@ void MainWidget::openUserByName(const QString &username, bool toProfile, const Q history.resizeEvent(0); } } - emit showPeerAsync(user->id, 0, false, true); + emit showPeerAsync(user->id, 0); } } else { MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone, qMakePair(toProfile, startToken)), rpcFail(&MainWidget::usernameResolveFail, username)); @@ -2829,7 +2852,7 @@ void MainWidget::usernameResolveDone(QPair toProfileStartToken, c history.resizeEvent(0); } } - showPeer(user->id, 0, false, true); + showPeerHistory(user->id, ShowAtUnreadMsgId); } } @@ -2862,7 +2885,7 @@ void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) { connect(box, SIGNAL(confirmed()), this, SLOT(onInviteImport())); App::wnd()->showLayer(box); } else { - showPeer(chat->id, 0, false, true); + showPeerHistory(chat->id, ShowAtUnreadMsgId); } } } break; @@ -2906,7 +2929,7 @@ void MainWidget::inviteImportDone(const MTPUpdates &updates) { } break; } if (v && !v->isEmpty() && v->front().type() == mtpc_chat) { - App::main()->showPeer(App::peerFromChat(v->front().c_chat().vid.v)); + App::main()->showPeerHistory(App::peerFromChat(v->front().c_chat().vid.v), ShowAtTheEndMsgId); } } @@ -3114,9 +3137,9 @@ void MainWidget::incrementSticker(DocumentData *sticker) { void MainWidget::activate() { if (!profile && !overview) { - if (hider) { - if (hider->wasOffered()) { - hider->setFocus(); + if (_hider) { + if (_hider->wasOffered()) { + _hider->setFocus(); } else { dialogs.activate(); } @@ -3144,7 +3167,7 @@ void MainWidget::updateOnlineDisplayIn(int32 msecs) { void MainWidget::addNewContact(int32 uid, bool show) { if (dialogs.addNewContact(uid, show)) { - showPeer(App::peerFromUser(uid)); + showPeerHistory(App::peerFromUser(uid), ShowAtTheEndMsgId); } } @@ -3169,11 +3192,11 @@ int32 MainWidget::dlgsWidth() const { } MainWidget::~MainWidget() { - if (App::main() == this) history.showPeer(0, 0, true); + if (App::main() == this) history.showPeerHistory(0, 0); delete _background; - delete hider; + delete _hider; MTP::clearGlobalHandlers(); delete _api; if (App::wnd()) App::wnd()->noMain(this); diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index ab2a4ef03..c0503be5e 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -111,13 +111,14 @@ public: class StackItemHistory : public StackItem { public: - StackItemHistory(PeerData *peer, int32 lastWidth, int32 lastScrollTop, QList replyReturns, bool kbWasHidden) : StackItem(peer), replyReturns(replyReturns), lastWidth(lastWidth), lastScrollTop(lastScrollTop), kbWasHidden(kbWasHidden) { + StackItemHistory(PeerData *peer, MsgId msgId, QList replyReturns, bool kbWasHidden) : StackItem(peer), +msgId(msgId), replyReturns(replyReturns), kbWasHidden(kbWasHidden) { } StackItemType type() const { return HistoryStackItem; } + MsgId msgId; QList replyReturns; - int32 lastWidth, lastScrollTop; bool kbWasHidden; }; @@ -184,7 +185,7 @@ public: void updateWideMode(); bool needBackButton(); - void onShowDialogs(); + void showDialogs(); void paintTopBar(QPainter &p, float64 over, int32 decreaseWidth); void topBarShadowParams(int32 &x, float64 &o); @@ -234,14 +235,17 @@ public: void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg); PeerData *historyPeer(); PeerData *peer(); + PeerData *activePeer(); MsgId activeMsgId(); + PeerData *profilePeer(); PeerData *overviewPeer(); bool mediaTypeSwitch(); void showPeerProfile(PeerData *peer, bool back = false, int32 lastScrollTop = -1, bool allMediaShown = false); void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1); void showBackFromStack(); + void orderWidgets(); QRect historyRect() const; void confirmShareContact(bool ctrlShiftEnter, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo); @@ -272,7 +276,6 @@ public: void onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data); bool selectingPeer(bool withConfirm = false); void offerPeer(PeerId peer); - void focusPeerSelect(); void dialogsActivate(); DragState getDragState(const QMimeData *mime); @@ -310,7 +313,7 @@ public: void readServerHistory(History *history, bool force = true); - uint64 animActiveTime() const; + uint64 animActiveTime(MsgId id) const; void stopAnimActive(); void sendBotCommand(const QString &cmd, MsgId msgId); @@ -369,6 +372,9 @@ public: void updateStickers(); void botCommandsChanged(UserData *bot); + void choosePeer(PeerId peerId, MsgId showAtMsgId); // does offerPeer or showPeerHistory + void clearBotStartToken(PeerData *peer); + ~MainWidget(); signals: @@ -379,7 +385,7 @@ signals: void dialogRowReplaced(DialogRow *oldRow, DialogRow *newRow); void dialogToTop(const History::DialogLinks &links); void dialogsUpdated(); - void showPeerAsync(quint64 peer, qint32 msgId, bool back, bool force); + void showPeerAsync(quint64 peerId, qint32 showAtMsgId); void stickersUpdated(); public slots: @@ -411,7 +417,7 @@ public slots: void checkIdleFinish(); void updateOnlineDisplay(); - void showPeer(quint64 peer, qint32 msgId = 0, bool back = false, bool force = false); // PeerId, MsgId + void showPeerHistory(quint64 peer, qint32 msgId, bool back = false); void onTopBarClick(); void onPeerShown(PeerData *peer); @@ -500,10 +506,11 @@ private: PlayerWidget _player; TopBarWidget _topBar; ConfirmBox *_forwardConfirm; // for narrow mode - HistoryHider *hider; + HistoryHider *_hider; StackItems _stack; - QPixmap profileAnimCache; - + PeerData *_peerInStack; + MsgId _msgIdInStack; + int32 _playerHeight; int32 _contentScrollAddToY; diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index d49a10105..66c3118f7 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -446,7 +446,7 @@ void MediaView::onToMessage() { if (HistoryItem *item = _msgid ? App::histItemById(_msgid) : 0) { if (App::wnd()) { close(); - if (App::main()) App::main()->showPeer(item->history()->peer->id, _msgid, false, true); + if (App::main()) App::main()->showPeerHistory(item->history()->peer->id, _msgid); } } } diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 5610dd1d1..cbc3d25f9 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -1367,7 +1367,7 @@ void OverviewInner::goToMessage() { HistoryItem *item = App::contextItem(); if (!item) return; - App::main()->showPeer(item->history()->peer->id, item->id, true, true); + App::main()->showPeerHistory(item->history()->peer->id, item->id); } void OverviewInner::forwardMessage() { diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index a0221743b..f75e0b914 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -178,7 +178,7 @@ void ProfileInner::onInviteToGroup() { } void ProfileInner::onSendMessage() { - App::main()->showPeer(_peer->id); + App::main()->showPeerHistory(_peer->id, ShowAtUnreadMsgId); } void ProfileInner::onEnableNotifications() { @@ -250,7 +250,7 @@ void ProfileInner::onClearHistory() { } void ProfileInner::onClearHistorySure() { - App::main()->showPeer(0, 0, true); + App::main()->showDialogs(); App::wnd()->hideLayer(); App::main()->clearHistory(_peer); } @@ -358,7 +358,7 @@ void ProfileInner::onBotSettings() { for (int32 i = 0, l = _peerUser->botInfo->commands.size(); i != l; ++i) { QString cmd = _peerUser->botInfo->commands.at(i).command; if (!cmd.compare(qsl("settings"), Qt::CaseInsensitive)) { - App::main()->showPeer(_peer->id); + App::main()->showPeerHistory(_peer->id, ShowAtTheEndMsgId); App::main()->sendBotCommand('/' + cmd, 0); return; } @@ -370,7 +370,7 @@ void ProfileInner::onBotHelp() { for (int32 i = 0, l = _peerUser->botInfo->commands.size(); i != l; ++i) { QString cmd = _peerUser->botInfo->commands.at(i).command; if (!cmd.compare(qsl("help"), Qt::CaseInsensitive)) { - App::main()->showPeer(_peer->id); + App::main()->showPeerHistory(_peer->id, ShowAtTheEndMsgId); App::main()->sendBotCommand('/' + cmd, 0); return; } @@ -766,7 +766,7 @@ void ProfileInner::mouseReleaseEvent(QMouseEvent *e) { textlnkDown(TextLinkPtr()); if (lnk == textlnkOver()) { if (reBotCommand().match(lnk->encoded()).hasMatch()) { - App::main()->showPeer(_peer->id); + App::main()->showPeerHistory(_peer->id, ShowAtTheEndMsgId); } lnk->onClick(e->button()); } diff --git a/Telegram/SourceFiles/pspecific_mac.cpp b/Telegram/SourceFiles/pspecific_mac.cpp index b7fc57214..c782e6687 100644 --- a/Telegram/SourceFiles/pspecific_mac.cpp +++ b/Telegram/SourceFiles/pspecific_mac.cpp @@ -76,7 +76,7 @@ void MacPrivate::notifyClicked(unsigned long long peer, int msgid) { tomsg = false; } } - App::main()->showPeer(history->peer->id, tomsg ? msgid : 0, false, true); + App::main()->showPeerHistory(history->peer->id, tomsg ? msgid : ShowAtUnreadMsgId); App::wnd()->notifyClear(history); } } diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index bc8228867..d60be556e 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -775,7 +775,7 @@ void MessageLink::onClick(Qt::MouseButton button) const { if (current && current->history()->peer->id == peer()) { App::main()->pushReplyReturn(current); } - App::main()->showPeer(peer(), msgid()); + App::main()->showPeerHistory(peer(), msgid()); } } diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index f218adc24..4a9a9555d 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -25,6 +25,9 @@ typedef uint64 DocumentId; typedef uint64 WebPageId; typedef int32 MsgId; +static const MsgId ShowAtTheEndMsgId = -0x40000000; +static const MsgId ShowAtUnreadMsgId = 0; + struct NotifySettings { NotifySettings() : mute(0), sound("default"), previews(true), events(1) { } diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index ffdab7f45..c42a73ccd 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -287,7 +287,7 @@ void NotifyWindow::mousePressEvent(QMouseEvent *e) { App::wnd()->notifyClear(); } else { App::wnd()->hideSettings(); - App::main()->showPeer(peer, (history->peer->chat && item && item->notifyByFrom() && item->id > 0) ? item->id : 0, false, true); + App::main()->showPeerHistory(peer, (history->peer->chat && item && item->notifyByFrom() && item->id > 0) ? item->id : ShowAtUnreadMsgId); } e->ignore(); } diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist index 939c89ea4..ec2de66d7 100644 --- a/Telegram/Telegram.plist +++ b/Telegram/Telegram.plist @@ -11,7 +11,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.8.39 + 0.8.40 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) CFBundleSignature diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc index f7b4fba3dd00abc8e486487617843ec75577422e..804a6f3acfd6e026cb66eb52329eda538a477a60 100644 GIT binary patch delta 61 zcmZ3Yy+nIM0WY%&gTdrtUPBPQc{y)C6FZQ>pa&G(D4@GJOMr_JNkDw^5<#KGO9WW} D<;@R5 delta 61 zcmZ3Yy+nIM0WY&LgXQF6UPBPQc{y)C6FZQ>pvPb^d82^t<}3j&MkE38$x8%<7B3NG F0RZYv4`KiS diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj index 8defca432..7b06d0e49 100644 --- a/Telegram/Telegram.xcodeproj/project.pbxproj +++ b/Telegram/Telegram.xcodeproj/project.pbxproj @@ -1705,7 +1705,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.8.39; + CURRENT_PROJECT_VERSION = 0.8.40; DEBUG_INFORMATION_FORMAT = dwarf; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -1723,7 +1723,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 0.8.39; + CURRENT_PROJECT_VERSION = 0.8.40; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = fast; GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h; @@ -1749,10 +1749,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.8.39; + CURRENT_PROJECT_VERSION = 0.8.40; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 0.8; - DYLIB_CURRENT_VERSION = 0.8.39; + DYLIB_CURRENT_VERSION = 0.8.40; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; @@ -1886,10 +1886,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.8.39; + CURRENT_PROJECT_VERSION = 0.8.40; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 0.8; - DYLIB_CURRENT_VERSION = 0.8.39; + DYLIB_CURRENT_VERSION = 0.8.40; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; diff --git a/Telegram/Version.sh b/Telegram/Version.sh index 6f9f1534a..e6f3290b4 100755 --- a/Telegram/Version.sh +++ b/Telegram/Version.sh @@ -1,2 +1,2 @@ -echo 0.8 8039 0.8.39 1 +echo 0.8 8040 0.8.40 1 # AppVersionStrMajor AppVersion AppVersionStr DevChannel diff --git a/XCODE.md b/XCODE.md index a7db5bee2..d68c98408 100644 --- a/XCODE.md +++ b/XCODE.md @@ -131,7 +131,7 @@ Then in Terminal go to **/Users/user/TBuild/Libraries/ffmpeg-2.6.3** and run LDFLAGS=`freetype-config --libs` PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig:/usr/lib/pkgconfig:/usr/X11/lib/pkgconfig - ./configure --prefix=/usr/local --disable-programs --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=wavpack --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-encoder=libopus --enable-parser=aac --enable-parser=aac_latm --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-demuxer=aac --enable-demuxer=wav --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=mov --enable-muxer=ogg --enable-muxer=opus --extra-cflags="-mmacosx-version-min=10.7" --extra-cxxflags="-mmacosx-version-min=10.7" --extra-ldflags="-mmacosx-version-min=10.7" + ./configure --prefix=/usr/local --disable-programs --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=wavpack --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-decoder=flac --enable-encoder=libopus --enable-parser=aac --enable-parser=aac_latm --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-parser=flac --enable-demuxer=aac --enable-demuxer=wav --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=mov --enable-demuxer=flac --enable-muxer=ogg --enable-muxer=opus --extra-cflags="-mmacosx-version-min=10.7" --extra-cxxflags="-mmacosx-version-min=10.7" --extra-ldflags="-mmacosx-version-min=10.7" make sudo make install