Encapsulated unreadCount and mute fields in History.

Support for hiding all muted chats from the list.
This commit is contained in:
John Preston 2016-04-11 14:59:01 +04:00
parent 03bbb2269d
commit e0d6a68554
26 changed files with 1323 additions and 962 deletions

View file

@ -886,6 +886,8 @@ dlgPaddingVer: 8px;
dlgHeight: 62px; dlgHeight: 62px;
dlgPhotoPadding: 12px; dlgPhotoPadding: 12px;
dlgImportantHeight: 37px;
noContactsHeight: 100px; noContactsHeight: 100px;
noContactsFont: font(fsize); noContactsFont: font(fsize);
noContactsColor: #777; noContactsColor: #777;

View file

@ -245,7 +245,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
if (!h->isEmpty()) { if (!h->isEmpty()) {
h->clear(true); h->clear(true);
} }
if (hto->inChatList() && h->inChatList()) { if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) {
App::removeDialog(h); App::removeDialog(h);
} }
} }

View file

@ -557,7 +557,7 @@ namespace {
if (!h->isEmpty()) { if (!h->isEmpty()) {
h->clear(true); h->clear(true);
} }
if (hto->inChatList() && h->inChatList()) { if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) {
App::removeDialog(h); App::removeDialog(h);
} }
} }
@ -1137,8 +1137,8 @@ namespace {
} else { } else {
if (channelHistory) { if (channelHistory) {
channelHistory->messageWithIdDeleted(i->v); channelHistory->messageWithIdDeleted(i->v);
if (channelHistory->unreadCount > 0 && i->v >= channelHistory->inboxReadBefore) { if (channelHistory->unreadCount() > 0 && i->v >= channelHistory->inboxReadBefore) {
channelHistory->setUnreadCount(channelHistory->unreadCount - 1); channelHistory->setUnreadCount(channelHistory->unreadCount() - 1);
} }
} }
} }

View file

@ -962,6 +962,15 @@ void AppClass::onSwitchDebugMode() {
} }
} }
void AppClass::onSwitchWorkMode() {
Global::SetDialogsModeEnabled(!Global::DialogsModeEnabled());
Global::SetDialogsMode(Dialogs::Mode::All);
Local::writeUserSettings();
cSetRestarting(true);
cSetRestartingToSettings(true);
App::quit();
}
void AppClass::onSwitchTestMode() { void AppClass::onSwitchTestMode() {
if (cTestMode()) { if (cTestMode()) {
QFile(cWorkingDir() + qsl("tdata/withtestmode")).remove(); QFile(cWorkingDir() + qsl("tdata/withtestmode")).remove();

View file

@ -195,6 +195,7 @@ public slots:
void photoUpdated(const FullMsgId &msgId, bool silent, const MTPInputFile &file); void photoUpdated(const FullMsgId &msgId, bool silent, const MTPInputFile &file);
void onSwitchDebugMode(); void onSwitchDebugMode();
void onSwitchWorkMode();
void onSwitchTestMode(); void onSwitchTestMode();
void killDownloadSessions(); void killDownloadSessions();

View file

@ -26,9 +26,14 @@ class Row;
using RowsByLetter = QMap<QChar, Row*>; using RowsByLetter = QMap<QChar, Row*>;
enum class SortMode { enum class SortMode {
Date, Date = 0x00,
Name, Name = 0x01,
Add Add = 0x02,
};
enum class Mode {
All = 0x00,
Important = 0x01,
}; };
} // namespace Dialogs } // namespace Dialogs

View file

@ -71,9 +71,21 @@ void IndexedList::adjustByPos(const RowsByLetter &links) {
} }
} }
void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) { void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
t_assert(_sortMode != SortMode::Date);
if (_sortMode == SortMode::Name) { if (_sortMode == SortMode::Name) {
adjustByName(peer, oldNames, oldChars);
} else {
adjustNames(Dialogs::Mode::All, peer, oldNames, oldChars);
}
}
void IndexedList::peerNameChanged(Mode list, PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
t_assert(_sortMode == SortMode::Date);
adjustNames(list, peer, oldNames, oldChars);
}
void IndexedList::adjustByName(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
Row *mainRow = _list.adjustByName(peer); Row *mainRow = _list.adjustByName(peer);
if (!mainRow) return; if (!mainRow) return;
@ -105,7 +117,9 @@ void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldName
j.value()->addByName(history); j.value()->addByName(history);
} }
} }
} else { }
void IndexedList::adjustNames(Mode list, PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
auto mainRow = _list.getRow(peer->id); auto mainRow = _list.getRow(peer->id);
if (!mainRow) return; if (!mainRow) return;
@ -122,7 +136,7 @@ void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldName
} }
for_const (auto ch, toRemove) { for_const (auto ch, toRemove) {
if (_sortMode == SortMode::Date) { if (_sortMode == SortMode::Date) {
history->removeChatListEntryByLetter(ch); history->removeChatListEntryByLetter(list, ch);
} }
if (auto list = _index.value(ch)) { if (auto list = _index.value(ch)) {
list->del(peer->id, mainRow); list->del(peer->id, mainRow);
@ -135,8 +149,7 @@ void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldName
} }
Row *row = j.value()->addToEnd(history); Row *row = j.value()->addToEnd(history);
if (_sortMode == SortMode::Date) { if (_sortMode == SortMode::Date) {
history->addChatListEntryByLetter(ch, row); history->addChatListEntryByLetter(list, ch, row);
}
} }
} }
} }

View file

@ -34,7 +34,13 @@ public:
RowsByLetter addToEnd(History *history); RowsByLetter addToEnd(History *history);
Row *addByName(History *history); Row *addByName(History *history);
void adjustByPos(const RowsByLetter &links); void adjustByPos(const RowsByLetter &links);
// For sortMode != SortMode::Date
void peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars); void peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
//For sortMode == SortMode::Date
void peerNameChanged(Mode list, PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void del(const PeerData *peer, Row *replacedBy = nullptr); void del(const PeerData *peer, Row *replacedBy = nullptr);
void clear(); void clear();
@ -71,6 +77,9 @@ public:
iterator find(int y, int h) { return all().find(y, h); } iterator find(int y, int h) { return all().find(y, h); }
private: private:
void adjustByName(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void adjustNames(Mode list, PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
SortMode _sortMode; SortMode _sortMode;
List _list; List _list;
using Index = QMap<QChar, List*>; using Index = QMap<QChar, List*>;

View file

@ -170,41 +170,48 @@ void paintUnreadBadge(Painter &p, const QRect &rect, bool active, bool muted) {
p.drawPixmap(rect.x() + sizehalf + bar, rect.y(), unreadBadgeStyle->right[index]); p.drawPixmap(rect.x() + sizehalf + bar, rect.y(), unreadBadgeStyle->right[index]);
} }
void paintUnreadCount(Painter &p, const QString &text, int top, int w, bool active, bool muted, int *outAvailableWidth) {
int unreadWidth = st::dlgUnreadFont->width(text);
int unreadRectWidth = unreadWidth + 2 * st::dlgUnreadPaddingHor;
int unreadRectHeight = st::dlgUnreadHeight;
accumulate_max(unreadRectWidth, unreadRectHeight);
int unreadRectLeft = w - st::dlgPaddingHor - unreadRectWidth;
int unreadRectTop =top;
if (outAvailableWidth) {
*outAvailableWidth -= unreadRectWidth + st::dlgUnreadPaddingHor;
}
paintUnreadBadge(p, QRect(unreadRectLeft, unreadRectTop, unreadRectWidth, unreadRectHeight), active, muted);
p.setFont(st::dlgUnreadFont);
p.setPen(active ? st::dlgActiveUnreadColor : st::dlgUnreadColor);
p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + st::dlgUnreadTop + st::dlgUnreadFont->ascent, text);
}
} // namepsace } // namepsace
void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground) { void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground) {
auto history = row->history(); auto history = row->history();
auto item = history->lastMsg; auto item = history->lastMsg;
paintRow(p, history, item, w, active, selected, onlyBackground, [&p, w, active, history, item](int nameleft, int namewidth) { paintRow(p, history, item, w, active, selected, onlyBackground, [&p, w, active, history, item](int nameleft, int namewidth) {
int32 lastWidth = namewidth, unread = history->unreadCount; int32 unread = history->unreadCount();
if (history->peer->migrateFrom()) { if (history->peer->migrateFrom()) {
if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) { if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) {
unread += h->unreadCount; unread += h->unreadCount();
} }
} }
int availableWidth = namewidth;
int texttop = st::dlgPaddingVer + st::dlgFont->height + st::dlgSep; int texttop = st::dlgPaddingVer + st::dlgFont->height + st::dlgSep;
if (unread) { if (unread) {
QString unreadStr = QString::number(unread); int unreadTop = texttop + st::dlgHistFont->ascent - st::dlgUnreadFont->ascent - st::dlgUnreadTop;
int unreadWidth = st::dlgUnreadFont->width(unreadStr); paintUnreadCount(p, QString::number(unread), unreadTop, w, active, history->mute(), &availableWidth);
int unreadRectWidth = unreadWidth + 2 * st::dlgUnreadPaddingHor;
int unreadRectHeight = st::dlgUnreadHeight;
accumulate_max(unreadRectWidth, unreadRectHeight);
int unreadRectLeft = w - st::dlgPaddingHor - unreadRectWidth;
int unreadRectTop = texttop + st::dlgHistFont->ascent - st::dlgUnreadFont->ascent - st::dlgUnreadTop;
lastWidth -= unreadRectWidth + st::dlgUnreadPaddingHor;
paintUnreadBadge(p, QRect(unreadRectLeft, unreadRectTop, unreadRectWidth, unreadRectHeight), active, history->mute);
p.setFont(st::dlgUnreadFont);
p.setPen(active ? st::dlgActiveUnreadColor : st::dlgUnreadColor);
p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + st::dlgUnreadTop + st::dlgUnreadFont->ascent, unreadStr);
} }
if (history->typing.isEmpty() && history->sendActions.isEmpty()) { if (history->typing.isEmpty() && history->sendActions.isEmpty()) {
item->drawInDialog(p, QRect(nameleft, texttop, lastWidth, st::dlgFont->height), active, history->textCachedFor, history->lastItemTextCache); item->drawInDialog(p, QRect(nameleft, texttop, availableWidth, st::dlgFont->height), active, history->textCachedFor, history->lastItemTextCache);
} else { } else {
p.setPen(active ? st::dlgActiveColor : st::dlgSystemColor); p.setPen(active ? st::dlgActiveColor : st::dlgSystemColor);
history->typingText.drawElided(p, nameleft, texttop, lastWidth); history->typingText.drawElided(p, nameleft, texttop, availableWidth);
} }
}); });
} }
@ -218,6 +225,28 @@ void RowPainter::paint(Painter &p, const FakeRow *row, int w, bool active, bool
}); });
} }
void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool onlyBackground) {
p.fillRect(0, 0, w, st::dlgImportantHeight, selected ? st::dlgHoverBG : st::white);
if (onlyBackground) {
return;
}
p.setFont(st::semiboldFont);
p.setPen(st::black);
int unreadTop = (st::dlgImportantHeight - st::dlgUnreadHeight) / 2;
bool mutedHidden = (current == Dialogs::Mode::Important);
QString text = mutedHidden ? qsl("Show all chats") : qsl("Hide muted chats");
int textBaseline = unreadTop + st::dlgUnreadTop + st::dlgUnreadFont->ascent;
p.drawText(st::dlgPaddingHor, textBaseline, text);
if (mutedHidden) {
if (int32 unread = App::histories().unreadMutedCount()) {
paintUnreadCount(p, QString::number(unread), unreadTop, w, false, true, nullptr);
}
}
}
namespace { namespace {
using StyleSheets = OrderedSet<StyleSheet**>; using StyleSheets = OrderedSet<StyleSheet**>;

View file

@ -33,6 +33,8 @@ public:
static void paint(Painter &p, const FakeRow *row, int w, bool active, bool selected, bool onlyBackground); static void paint(Painter &p, const FakeRow *row, int w, bool active, bool selected, bool onlyBackground);
}; };
void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool onlyBackground);
// This will be moved somewhere outside as soon as anyone starts using that. // This will be moved somewhere outside as soon as anyone starts using that.
class StyleSheet { class StyleSheet {
public: public:

View file

@ -40,6 +40,9 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p
, contacts(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name)) , contacts(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
, _addContactLnk(this, lang(lng_add_contact_button)) , _addContactLnk(this, lang(lng_add_contact_button))
, _cancelSearchInPeer(this, st::btnCancelSearch) { , _cancelSearchInPeer(this, st::btnCancelSearch) {
if (Global::DialogsModeEnabled()) {
importantDialogs = std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date);
}
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
connect(main, SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&))); connect(main, SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*))); connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*)));
@ -50,16 +53,20 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p
refresh(); refresh();
} }
int32 DialogsInner::filteredOffset() const { int DialogsInner::dialogsOffset() const {
return importantDialogs ? st::dlgImportantHeight : 0;
}
int DialogsInner::filteredOffset() const {
return _hashtagResults.size() * st::mentionHeight; return _hashtagResults.size() * st::mentionHeight;
} }
int32 DialogsInner::peopleOffset() const { int DialogsInner::peopleOffset() const {
return filteredOffset() + (_filterResults.size() * st::dlgHeight) + st::searchedBarHeight; return filteredOffset() + (_filterResults.size() * st::dlgHeight) + st::searchedBarHeight;
} }
int32 DialogsInner::searchedOffset() const { int DialogsInner::searchedOffset() const {
int32 result = peopleOffset() + (_peopleResults.isEmpty() ? 0 : ((_peopleResults.size() * st::dlgHeight) + st::searchedBarHeight)); int result = peopleOffset() + (_peopleResults.isEmpty() ? 0 : ((_peopleResults.size() * st::dlgHeight) + st::searchedBarHeight));
if (_searchInPeer) result += st::dlgHeight; if (_searchInPeer) result += st::dlgHeight;
return result; return result;
} }
@ -76,16 +83,22 @@ void DialogsInner::paintRegion(Painter &p, const QRegion &region, bool paintingO
} }
if (_state == DefaultState) { if (_state == DefaultState) {
int32 otherStart = dialogs->size() * st::dlgHeight; QRect dialogsClip = r;
PeerData *active = App::main()->activePeer(), *selected = _menuPeer ? _menuPeer : (sel ? sel->history()->peer : 0); if (importantDialogs) {
Dialogs::Layout::paintImportantSwitch(p, Global::DialogsMode(), fullWidth(), _importantSwitchSel, paintingOther);
dialogsClip.translate(0, -st::dlgImportantHeight);
p.translate(0, st::dlgImportantHeight);
}
int32 otherStart = shownDialogs()->size() * st::dlgHeight;
PeerData *active = App::main()->activePeer(), *selected = _menuPeer ? _menuPeer : (_sel ? _sel->history()->peer : 0);
if (otherStart) { if (otherStart) {
dialogs->all().paint(p, fullWidth(), r.top(), r.top() + r.height(), active, selected, paintingOther); shownDialogs()->all().paint(p, fullWidth(), dialogsClip.top(), dialogsClip.top() + dialogsClip.height(), active, selected, paintingOther);
} }
if (!otherStart) { if (!otherStart) {
p.fillRect(r, st::white->b); p.fillRect(dialogsClip, st::white);
if (!paintingOther) { if (!paintingOther) {
p.setFont(st::noContactsFont->f); p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor->p); p.setPen(st::noContactsColor);
p.drawText(QRect(0, 0, fullWidth(), st::noContactsHeight - (cContactsReceived() ? st::noContactsFont->height : 0)), lang(cContactsReceived() ? lng_no_chats : lng_contacts_loading), style::al_center); p.drawText(QRect(0, 0, fullWidth(), st::noContactsHeight - (cContactsReceived() ? st::noContactsFont->height : 0)), lang(cContactsReceived() ? lng_no_chats : lng_contacts_loading), style::al_center);
} }
} }
@ -223,13 +236,11 @@ void DialogsInner::paintRegion(Painter &p, const QRegion &region, bool paintingO
} }
} }
void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool act, bool sel, bool onlyBackground) const { void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool active, bool selected, bool onlyBackground) const {
QRect fullRect(0, 0, w, st::dlgHeight); QRect fullRect(0, 0, w, st::dlgHeight);
p.fillRect(fullRect, (act ? st::dlgActiveBG : (sel ? st::dlgHoverBG : st::dlgBG))->b); p.fillRect(fullRect, active ? st::dlgActiveBG : (selected ? st::dlgHoverBG : st::dlgBG));
if (onlyBackground) return; if (onlyBackground) return;
History *history = App::history(peer->id);
PeerData *userpicPeer = (peer->migrateTo() ? peer->migrateTo() : peer); PeerData *userpicPeer = (peer->migrateTo() ? peer->migrateTo() : peer);
userpicPeer->paintUserpicLeft(p, st::dlgPhotoSize, st::dlgPaddingHor, st::dlgPaddingVer, fullWidth()); userpicPeer->paintUserpicLeft(p, st::dlgPhotoSize, st::dlgPaddingHor, st::dlgPaddingVer, fullWidth());
@ -239,21 +250,21 @@ void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool a
// draw chat icon // draw chat icon
if (peer->isChat() || peer->isMegagroup()) { if (peer->isChat() || peer->isMegagroup()) {
p.drawPixmap(QPoint(rectForName.left() + st::dlgChatImgPos.x(), rectForName.top() + st::dlgChatImgPos.y()), App::sprite(), (act ? st::dlgActiveChatImg : st::dlgChatImg)); p.drawSprite(QPoint(rectForName.left() + st::dlgChatImgPos.x(), rectForName.top() + st::dlgChatImgPos.y()), (active ? st::dlgActiveChatImg : st::dlgChatImg));
rectForName.setLeft(rectForName.left() + st::dlgImgSkip); rectForName.setLeft(rectForName.left() + st::dlgImgSkip);
} else if (peer->isChannel()) { } else if (peer->isChannel()) {
p.drawPixmap(QPoint(rectForName.left() + st::dlgChannelImgPos.x(), rectForName.top() + st::dlgChannelImgPos.y()), App::sprite(), (act ? st::dlgActiveChannelImg : st::dlgChannelImg)); p.drawSprite(QPoint(rectForName.left() + st::dlgChannelImgPos.x(), rectForName.top() + st::dlgChannelImgPos.y()), (active ? st::dlgActiveChannelImg : st::dlgChannelImg));
rectForName.setLeft(rectForName.left() + st::dlgImgSkip); rectForName.setLeft(rectForName.left() + st::dlgImgSkip);
} }
if (peer->isVerified()) { if (peer->isVerified()) {
rectForName.setWidth(rectForName.width() - st::verifiedCheck.pxWidth() - st::verifiedCheckPos.x()); rectForName.setWidth(rectForName.width() - st::verifiedCheck.pxWidth() - st::verifiedCheckPos.x());
p.drawSprite(rectForName.topLeft() + QPoint(qMin(peer->dialogName().maxWidth(), rectForName.width()), 0) + st::verifiedCheckPos, (act ? st::verifiedCheckInv : st::verifiedCheck)); p.drawSprite(rectForName.topLeft() + QPoint(qMin(peer->dialogName().maxWidth(), rectForName.width()), 0) + st::verifiedCheckPos, (active ? st::verifiedCheckInv : st::verifiedCheck));
} }
QRect tr(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, namewidth, st::dlgFont->height); QRect tr(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, namewidth, st::dlgFont->height);
p.setFont(st::dlgHistFont->f); p.setFont(st::dlgHistFont->f);
QString username = peer->userName(); QString username = peer->userName();
if (!act && username.toLower().startsWith(_peopleQuery)) { if (!active && username.toLower().startsWith(_peopleQuery)) {
QString first = '@' + username.mid(0, _peopleQuery.size()), second = username.mid(_peopleQuery.size()); QString first = '@' + username.mid(0, _peopleQuery.size()), second = username.mid(_peopleQuery.size());
int32 w = st::dlgHistFont->width(first); int32 w = st::dlgHistFont->width(first);
if (w >= tr.width()) { if (w >= tr.width()) {
@ -266,11 +277,11 @@ void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool a
p.drawText(tr.left() + w, tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->elided(second, tr.width() - w)); p.drawText(tr.left() + w, tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->elided(second, tr.width() - w));
} }
} else { } else {
p.setPen((act ? st::dlgActiveColor : st::dlgSystemColor)->p); p.setPen((active ? st::dlgActiveColor : st::dlgSystemColor)->p);
p.drawText(tr.left(), tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->elided('@' + username, tr.width())); p.drawText(tr.left(), tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->elided('@' + username, tr.width()));
} }
p.setPen((act ? st::dlgActiveColor : st::dlgNameColor)->p); p.setPen((active ? st::dlgActiveColor : st::dlgNameColor)->p);
peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
} }
@ -308,24 +319,26 @@ void DialogsInner::activate() {
void DialogsInner::mouseMoveEvent(QMouseEvent *e) { void DialogsInner::mouseMoveEvent(QMouseEvent *e) {
lastMousePos = mapToGlobal(e->pos()); lastMousePos = mapToGlobal(e->pos());
selByMouse = true; _selByMouse = true;
onUpdateSelected(true); onUpdateSelected(true);
} }
void DialogsInner::onUpdateSelected(bool force) { void DialogsInner::onUpdateSelected(bool force) {
QPoint mouse(mapFromGlobal(lastMousePos)); QPoint mouse(mapFromGlobal(lastMousePos));
if ((!force && !rect().contains(mouse)) || !selByMouse) return; if ((!force && !rect().contains(mouse)) || !_selByMouse) return;
int w = width(), mouseY = mouse.y(); int w = width(), mouseY = mouse.y();
_overDelete = false; _overDelete = false;
if (_state == DefaultState) { if (_state == DefaultState) {
auto newSel = dialogs->rowAtY(mouseY, st::dlgHeight); auto newImportantSwitchSel = (importantDialogs && mouseY >= 0 && mouseY < dialogsOffset());
int otherStart = dialogs->size() * st::dlgHeight; mouseY -= dialogsOffset();
if (newSel != sel) { auto newSel = newImportantSwitchSel ? nullptr : shownDialogs()->rowAtY(mouseY, st::dlgHeight);
if (newSel != _sel || newImportantSwitchSel != _importantSwitchSel) {
updateSelectedRow(); updateSelectedRow();
sel = newSel; _sel = newSel;
_importantSwitchSel = newImportantSwitchSel;
updateSelectedRow(); updateSelectedRow();
setCursor(sel ? style::cur_pointer : style::cur_default); setCursor(_sel ? style::cur_pointer : style::cur_default);
} }
} else if (_state == FilteredState || _state == SearchedState) { } else if (_state == FilteredState || _state == SearchedState) {
if (!_hashtagResults.isEmpty()) { if (!_hashtagResults.isEmpty()) {
@ -384,7 +397,7 @@ void DialogsInner::onUpdateSelected(bool force) {
void DialogsInner::mousePressEvent(QMouseEvent *e) { void DialogsInner::mousePressEvent(QMouseEvent *e) {
lastMousePos = mapToGlobal(e->pos()); lastMousePos = mapToGlobal(e->pos());
selByMouse = true; _selByMouse = true;
onUpdateSelected(true); onUpdateSelected(true);
if (e->button() == Qt::LeftButton) { if (e->button() == Qt::LeftButton) {
choosePeer(); choosePeer();
@ -411,25 +424,46 @@ void DialogsInner::onDialogRowReplaced(Dialogs::Row *oldRow, Dialogs::Row *newRo
} }
} }
} }
if (sel == oldRow) { if (_sel == oldRow) {
sel = newRow; _sel = newRow;
} }
} }
void DialogsInner::createDialog(History *history) { void DialogsInner::createDialog(History *history) {
bool creating = !history->inChatList(); bool creating = !history->inChatList(Dialogs::Mode::All);
if (creating) { if (creating) {
Dialogs::Row *mainRow = history->addToChatList(dialogs.get()); Dialogs::Row *mainRow = history->addToChatList(Dialogs::Mode::All, dialogs.get());
contactsNoDialogs->del(history->peer, mainRow); contactsNoDialogs->del(history->peer, mainRow);
} }
RefPair(int32, movedFrom, int32, movedTo) = history->adjustByPosInChatsList(dialogs.get()); if (importantDialogs && !history->inChatList(Dialogs::Mode::Important) && !history->mute()) {
if (Global::DialogsMode() == Dialogs::Mode::Important) {
creating = true;
}
history->addToChatList(Dialogs::Mode::Important, importantDialogs.get());
}
auto changed = history->adjustByPosInChatList(Dialogs::Mode::All, dialogs.get());
if (importantDialogs) {
if (history->mute()) {
if (Global::DialogsMode() == Dialogs::Mode::Important) {
return;
}
} else {
auto importantChanged = history->adjustByPosInChatList(Dialogs::Mode::Important, importantDialogs.get());
if (Global::DialogsMode() == Dialogs::Mode::Important) {
changed = importantChanged;
}
}
}
RefPair(int32, movedFrom, int32, movedTo) = changed;
emit dialogMoved(movedFrom, movedTo); emit dialogMoved(movedFrom, movedTo);
if (creating) { if (creating) {
refresh(); refresh();
} else if (_state == DefaultState && movedFrom != movedTo) { } else if (_state == DefaultState && movedFrom != movedTo) {
update(0, qMin(movedFrom, movedTo), fullWidth(), qAbs(movedFrom - movedTo) + st::dlgHeight); update(0, dialogsOffset() + qMin(movedFrom, movedTo), fullWidth(), qAbs(movedFrom - movedTo) + st::dlgHeight);
} }
} }
@ -438,10 +472,13 @@ void DialogsInner::removeDialog(History *history) {
if (history->peer == _menuPeer && _menu) { if (history->peer == _menuPeer && _menu) {
_menu->deleteLater(); _menu->deleteLater();
} }
if (sel && sel->history() == history) { if (_sel && _sel->history() == history) {
sel = nullptr; _sel = nullptr;
}
history->removeFromChatList(Dialogs::Mode::All, dialogs.get());
if (importantDialogs) {
history->removeFromChatList(Dialogs::Mode::Important, importantDialogs.get());
} }
history->removeFromChatList(dialogs.get());
history->clearNotifications(); history->clearNotifications();
if (App::wnd()) App::wnd()->notifyClear(history); if (App::wnd()) App::wnd()->notifyClear(history);
if (contacts->contains(history->peer->id)) { if (contacts->contains(history->peer->id)) {
@ -457,10 +494,13 @@ void DialogsInner::removeDialog(History *history) {
refresh(); refresh();
} }
void DialogsInner::dlgUpdated(Dialogs::Row *row) { void DialogsInner::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) {
if (_state == DefaultState) { if (_state == DefaultState) {
update(0, row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight); if (Global::DialogsMode() == list) {
update(0, dialogsOffset() + row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
}
} else if (_state == FilteredState || _state == SearchedState) { } else if (_state == FilteredState || _state == SearchedState) {
if (list == Dialogs::Mode::All) {
for (int32 i = 0, l = _filterResults.size(); i < l; ++i) { for (int32 i = 0, l = _filterResults.size(); i < l; ++i) {
if (_filterResults.at(i)->history() == row->history()) { if (_filterResults.at(i)->history() == row->history()) {
update(0, i * st::dlgHeight, fullWidth(), st::dlgHeight); update(0, i * st::dlgHeight, fullWidth(), st::dlgHeight);
@ -469,11 +509,12 @@ void DialogsInner::dlgUpdated(Dialogs::Row *row) {
} }
} }
} }
}
void DialogsInner::dlgUpdated(History *history, MsgId msgId) { void DialogsInner::dlgUpdated(History *history, MsgId msgId) {
if (_state == DefaultState) { if (_state == DefaultState) {
if (auto row = dialogs->getRow(history->peer->id)) { if (auto row = shownDialogs()->getRow(history->peer->id)) {
update(0, row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight); update(0, dialogsOffset() + row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
} }
} else if (_state == FilteredState || _state == SearchedState) { } else if (_state == FilteredState || _state == SearchedState) {
int32 cnt = 0, add = filteredOffset(); int32 cnt = 0, add = filteredOffset();
@ -517,12 +558,14 @@ void DialogsInner::updateSelectedRow(PeerData *peer) {
if (_state == DefaultState) { if (_state == DefaultState) {
if (peer) { if (peer) {
if (History *h = App::historyLoaded(peer->id)) { if (History *h = App::historyLoaded(peer->id)) {
if (h->inChatList()) { if (h->inChatList(Global::DialogsMode())) {
update(0, h->posInChatList() * st::dlgHeight, fullWidth(), st::dlgHeight); update(0, dialogsOffset() + h->posInChatList(Global::DialogsMode()) * st::dlgHeight, fullWidth(), st::dlgHeight);
} }
} }
} else if (sel) { } else if (_sel) {
update(0, sel->pos() * st::dlgHeight, fullWidth(), st::dlgHeight); update(0, dialogsOffset() + _sel->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
} else if (_importantSwitchSel) {
update(0, 0, fullWidth(), st::dlgImportantHeight);
} }
} else if (_state == FilteredState || _state == SearchedState) { } else if (_state == FilteredState || _state == SearchedState) {
if (peer) { if (peer) {
@ -547,10 +590,15 @@ void DialogsInner::updateSelectedRow(PeerData *peer) {
void DialogsInner::leaveEvent(QEvent *e) { void DialogsInner::leaveEvent(QEvent *e) {
setMouseTracking(false); setMouseTracking(false);
selByMouse = false; clearSelection();
if (sel || _filteredSel >= 0 || _hashtagSel >= 0 || _searchedSel >= 0 || _peopleSel >= 0) { }
void DialogsInner::clearSelection() {
_selByMouse = false;
if (_sel || _filteredSel >= 0 || _hashtagSel >= 0 || _searchedSel >= 0 || _peopleSel >= 0) {
updateSelectedRow(); updateSelectedRow();
sel = 0; _sel = nullptr;
_importantSwitchSel = false;
_filteredSel = _searchedSel = _peopleSel = _hashtagSel = -1; _filteredSel = _searchedSel = _peopleSel = _hashtagSel = -1;
setCursor(style::cur_default); setCursor(style::cur_default);
} }
@ -569,13 +617,13 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
if (e->reason() == QContextMenuEvent::Mouse) { if (e->reason() == QContextMenuEvent::Mouse) {
lastMousePos = e->globalPos(); lastMousePos = e->globalPos();
selByMouse = true; _selByMouse = true;
onUpdateSelected(true); onUpdateSelected(true);
} }
History *history = 0; History *history = 0;
if (_state == DefaultState) { if (_state == DefaultState) {
if (sel) history = sel->history(); if (_sel) history = _sel->history();
} else if (_state == FilteredState || _state == SearchedState) { } else if (_state == FilteredState || _state == SearchedState) {
if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) { if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) {
history = _filterResults[_filteredSel]->history(); history = _filterResults[_filteredSel]->history();
@ -691,7 +739,7 @@ void DialogsInner::onMenuDestroyed(QObject *obj) {
} }
lastMousePos = QCursor::pos(); lastMousePos = QCursor::pos();
if (rect().contains(mapFromGlobal(lastMousePos))) { if (rect().contains(mapFromGlobal(lastMousePos))) {
selByMouse = true; _selByMouse = true;
setMouseTracking(true); setMouseTracking(true);
onUpdateSelected(true); onUpdateSelected(true);
} }
@ -707,7 +755,10 @@ void DialogsInner::onParentGeometryChanged() {
} }
void DialogsInner::onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) { void DialogsInner::onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
dialogs->peerNameChanged(peer, oldNames, oldChars); dialogs->peerNameChanged(Dialogs::Mode::All, peer, oldNames, oldChars);
if (importantDialogs) {
importantDialogs->peerNameChanged(Dialogs::Mode::Important, peer, oldNames, oldChars);
}
contactsNoDialogs->peerNameChanged(peer, oldNames, oldChars); contactsNoDialogs->peerNameChanged(peer, oldNames, oldChars);
contacts->peerNameChanged(peer, oldNames, oldChars); contacts->peerNameChanged(peer, oldNames, oldChars);
update(); update();
@ -889,10 +940,10 @@ void DialogsInner::peerUpdated(PeerData *peer) {
PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) { PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) {
lastMousePos = globalPos; lastMousePos = globalPos;
selByMouse = true; _selByMouse = true;
onUpdateSelected(true); onUpdateSelected(true);
if (_state == DefaultState) { if (_state == DefaultState) {
if (sel) return sel->history()->peer; if (_sel) return _sel->history()->peer;
} else if (_state == FilteredState || _state == SearchedState) { } else if (_state == FilteredState || _state == SearchedState) {
if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) { if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) {
return _filterResults[_filteredSel]->history()->peer; return _filterResults[_filteredSel]->history()->peer;
@ -976,8 +1027,9 @@ void DialogsInner::dialogsReceived(const QVector<MTPDialog> &added) {
} }
if (App::wnd()) App::wnd()->updateCounter(); if (App::wnd()) App::wnd()->updateCounter();
if (!sel && !dialogs->isEmpty()) { if (!_sel && !shownDialogs()->isEmpty()) {
sel = *dialogs->cbegin(); _sel = *shownDialogs()->cbegin();
_importantSwitchSel = false;
} }
refresh(); refresh();
} }
@ -1042,7 +1094,7 @@ void DialogsInner::peopleReceived(const QString &query, const QVector<MTPPeer> &
for (QVector<MTPPeer>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) { for (QVector<MTPPeer>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) {
PeerId peerId = peerFromMTP(*i); PeerId peerId = peerFromMTP(*i);
if (History *h = App::historyLoaded(peerId)) { if (History *h = App::historyLoaded(peerId)) {
if (h->inChatList()) { if (h->inChatList(Dialogs::Mode::All)) {
continue; // skip existing chats continue; // skip existing chats
} }
} }
@ -1069,16 +1121,17 @@ void DialogsInner::notify_userIsContactChanged(UserData *user, bool fromThisApp)
if (user->contact > 0) { if (user->contact > 0) {
History *history = App::history(user->id); History *history = App::history(user->id);
contacts->addByName(history); contacts->addByName(history);
if (auto row = dialogs->getRow(user->id)) { if (auto row = shownDialogs()->getRow(user->id)) {
if (fromThisApp) { if (fromThisApp) {
sel = row; _sel = row;
_importantSwitchSel = false;
} }
} else { } else if (!dialogs->contains(user->id)) {
contactsNoDialogs->addByName(history); contactsNoDialogs->addByName(history);
} }
} else { } else {
if (sel && sel->history()->peer == user) { if (_sel && _sel->history()->peer == user) {
sel = nullptr; _sel = nullptr;
} }
contactsNoDialogs->del(user); contactsNoDialogs->del(user);
contacts->del(user); contacts->del(user);
@ -1086,19 +1139,54 @@ void DialogsInner::notify_userIsContactChanged(UserData *user, bool fromThisApp)
refresh(); refresh();
} }
void DialogsInner::notify_historyMuteUpdated(History *history) {
if (!importantDialogs || !history->inChatList(Dialogs::Mode::All)) return;
if (history->mute()) {
if (_sel && _sel->history() == history && Global::DialogsMode() == Dialogs::Mode::Important) {
_sel = nullptr;
}
history->removeFromChatList(Dialogs::Mode::Important, importantDialogs.get());
if (Global::DialogsMode() != Dialogs::Mode::Important) {
return;
}
refresh();
} else {
bool creating = !history->inChatList(Dialogs::Mode::Important);
if (creating) {
history->addToChatList(Dialogs::Mode::Important, importantDialogs.get());
}
auto changed = history->adjustByPosInChatList(Dialogs::Mode::All, dialogs.get());
if (Global::DialogsMode() != Dialogs::Mode::Important) {
return;
}
RefPair(int32, movedFrom, int32, movedTo) = changed;
emit dialogMoved(movedFrom, movedTo);
if (creating) {
refresh();
} else if (_state == DefaultState && movedFrom != movedTo) {
update(0, dialogsOffset() + qMin(movedFrom, movedTo), fullWidth(), qAbs(movedFrom - movedTo) + st::dlgHeight);
}
}
}
void DialogsInner::refresh(bool toTop) { void DialogsInner::refresh(bool toTop) {
int32 h = 0; int32 h = 0;
if (_state == DefaultState) { if (_state == DefaultState) {
h = (dialogs->size()/* + contactsNoDialogs->size()*/) * st::dlgHeight; if (shownDialogs()->isEmpty()) {
if (h) {
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
} else {
h = st::noContactsHeight; h = st::noContactsHeight;
if (cContactsReceived()) { if (cContactsReceived()) {
if (_addContactLnk.isHidden()) _addContactLnk.show(); if (_addContactLnk.isHidden()) _addContactLnk.show();
} else { } else {
if (!_addContactLnk.isHidden()) _addContactLnk.hide(); if (!_addContactLnk.isHidden()) _addContactLnk.hide();
} }
} else {
h = dialogsOffset() + shownDialogs()->size() * st::dlgHeight;
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
} }
} else { } else {
if (!_addContactLnk.isHidden()) _addContactLnk.hide(); if (!_addContactLnk.isHidden()) _addContactLnk.hide();
@ -1117,10 +1205,11 @@ void DialogsInner::refresh(bool toTop) {
} }
void DialogsInner::setMouseSel(bool msel, bool toTop) { void DialogsInner::setMouseSel(bool msel, bool toTop) {
selByMouse = msel; _selByMouse = msel;
if (!selByMouse && toTop) { if (!_selByMouse && toTop) {
if (_state == DefaultState) { if (_state == DefaultState) {
sel = !dialogs->isEmpty() ? *dialogs->cbegin() : nullptr; _sel = !shownDialogs()->isEmpty() ? *shownDialogs()->cbegin() : nullptr;
_importantSwitchSel = false;
} else if (_state == FilteredState || _state == SearchedState) { // don't select first elem in search } else if (_state == FilteredState || _state == SearchedState) { // don't select first elem in search
_filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1; _filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1;
setCursor(style::cur_default); setCursor(style::cur_default);
@ -1182,25 +1271,39 @@ void DialogsInner::clearFilter() {
void DialogsInner::selectSkip(int32 direction) { void DialogsInner::selectSkip(int32 direction) {
if (_state == DefaultState) { if (_state == DefaultState) {
if (!sel) { if (_importantSwitchSel) {
if (!dialogs->isEmpty() && direction > 0) { if (!shownDialogs()->isEmpty() && direction > 0) {
sel = *dialogs->cbegin(); _sel = *shownDialogs()->cbegin();
_importantSwitchSel = false;
} else {
return;
}
} else if (!_sel) {
if (importantDialogs) {
_importantSwitchSel = true;
} else if (!shownDialogs()->isEmpty() && direction > 0) {
_sel = *shownDialogs()->cbegin();
} else { } else {
return; return;
} }
} else if (direction > 0) { } else if (direction > 0) {
auto next = dialogs->cfind(sel); auto next = shownDialogs()->cfind(_sel);
if (++next != dialogs->cend()) { if (++next != shownDialogs()->cend()) {
sel = *next; _sel = *next;
} }
} else { } else {
auto prev = dialogs->cfind(sel); auto prev = shownDialogs()->cfind(_sel);
if (prev != dialogs->cbegin()) { if (prev != shownDialogs()->cbegin()) {
sel = *(--prev); _sel = *(--prev);
} else if (importantDialogs) {
_importantSwitchSel = true;
_sel = nullptr;
} }
} }
int32 fromY = sel->pos() * st::dlgHeight; if (_importantSwitchSel || _sel) {
int fromY = _importantSwitchSel ? 0 : (dialogsOffset() + _sel->pos() * st::dlgHeight);
emit mustScrollTo(fromY, fromY + st::dlgHeight); emit mustScrollTo(fromY, fromY + st::dlgHeight);
}
} else if (_state == FilteredState || _state == SearchedState) { } else if (_state == FilteredState || _state == SearchedState) {
if (_hashtagResults.isEmpty() && _filterResults.isEmpty() && _peopleResults.isEmpty() && _searchResults.isEmpty()) return; if (_hashtagResults.isEmpty() && _filterResults.isEmpty() && _peopleResults.isEmpty() && _searchResults.isEmpty()) return;
if ((_hashtagSel < 0 || _hashtagSel >= _hashtagResults.size()) && if ((_hashtagSel < 0 || _hashtagSel >= _hashtagResults.size()) &&
@ -1249,8 +1352,8 @@ void DialogsInner::selectSkip(int32 direction) {
void DialogsInner::scrollToPeer(const PeerId &peer, MsgId msgId) { void DialogsInner::scrollToPeer(const PeerId &peer, MsgId msgId) {
int32 fromY = -1; int32 fromY = -1;
if (_state == DefaultState) { if (_state == DefaultState) {
if (auto row = dialogs->getRow(peer)) { if (auto row = shownDialogs()->getRow(peer)) {
fromY = row->pos() * st::dlgHeight; fromY = dialogsOffset() + row->pos() * st::dlgHeight;
} }
} else if (_state == FilteredState || _state == SearchedState) { } else if (_state == FilteredState || _state == SearchedState) {
if (msgId) { if (msgId) {
@ -1278,24 +1381,31 @@ void DialogsInner::scrollToPeer(const PeerId &peer, MsgId msgId) {
void DialogsInner::selectSkipPage(int32 pixels, int32 direction) { void DialogsInner::selectSkipPage(int32 pixels, int32 direction) {
int toSkip = pixels / int(st::dlgHeight); int toSkip = pixels / int(st::dlgHeight);
if (_state == DefaultState) { if (_state == DefaultState) {
if (!sel) { if (!_sel) {
if (direction > 0 && !dialogs->isEmpty()) { if (direction > 0 && !shownDialogs()->isEmpty()) {
sel = *dialogs->cbegin(); _sel = *shownDialogs()->cbegin();
_importantSwitchSel = false;
} else { } else {
return; return;
} }
} }
if (direction > 0) { if (direction > 0) {
for (auto i = dialogs->cfind(sel), end = dialogs->cend(); i != end && (toSkip--); ++i) { for (auto i = shownDialogs()->cfind(_sel), end = shownDialogs()->cend(); i != end && (toSkip--); ++i) {
sel = *i; _sel = *i;
} }
} else { } else {
for (auto i = dialogs->cfind(sel), b = dialogs->cbegin(); i != b && (toSkip--); --i) { for (auto i = shownDialogs()->cfind(_sel), b = shownDialogs()->cbegin(); i != b && (toSkip--); --i) {
sel = *i; _sel = *i;
}
if (toSkip && importantDialogs) {
_importantSwitchSel = true;
_sel = nullptr;
} }
} }
int fromY = sel->pos() * st::dlgHeight; if (_importantSwitchSel || _sel) {
int fromY = (_importantSwitchSel ? 0 : (dialogsOffset() + _sel->pos() * st::dlgHeight));
emit mustScrollTo(fromY, fromY + st::dlgHeight); emit mustScrollTo(fromY, fromY + st::dlgHeight);
}
} else { } else {
return selectSkip(direction * toSkip); return selectSkip(direction * toSkip);
} }
@ -1308,9 +1418,9 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
int32 yTo = yFrom + parentWidget()->height() * 5; int32 yTo = yFrom + parentWidget()->height() * 5;
MTP::clearLoaderPriorities(); MTP::clearLoaderPriorities();
if (_state == DefaultState) { if (_state == DefaultState) {
int32 otherStart = dialogs->size() * st::dlgHeight; int32 otherStart = shownDialogs()->size() * st::dlgHeight;
if (yFrom < otherStart) { if (yFrom < otherStart) {
for (auto i = dialogs->cfind(yFrom, st::dlgHeight), end = dialogs->cend(); i != end; ++i) { for (auto i = shownDialogs()->cfind(yFrom, st::dlgHeight), end = shownDialogs()->cend(); i != end; ++i) {
if (((*i)->pos() * st::dlgHeight) >= yTo) { if (((*i)->pos() * st::dlgHeight) >= yTo) {
break; break;
} }
@ -1357,10 +1467,23 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
} }
bool DialogsInner::choosePeer() { bool DialogsInner::choosePeer() {
History *history = 0; History *history = nullptr;
MsgId msgId = ShowAtUnreadMsgId; MsgId msgId = ShowAtUnreadMsgId;
if (_state == DefaultState) { if (_state == DefaultState) {
if (sel) history = sel->history(); if (_importantSwitchSel && importantDialogs) {
clearSelection();
if (Global::DialogsMode() == Dialogs::Mode::All) {
Global::SetDialogsMode(Dialogs::Mode::Important);
} else {
Global::SetDialogsMode(Dialogs::Mode::All);
}
Local::writeUserSettings();
refresh();
_importantSwitchSel = true;
return true;
} else if (_sel) {
history = _sel->history();
}
} else if (_state == FilteredState || _state == SearchedState) { } else if (_state == FilteredState || _state == SearchedState) {
if (_hashtagSel >= 0 && _hashtagSel < _hashtagResults.size()) { if (_hashtagSel >= 0 && _hashtagSel < _hashtagResults.size()) {
QString hashtag = _hashtagResults.at(_hashtagSel); QString hashtag = _hashtagResults.at(_hashtagSel);
@ -1379,7 +1502,7 @@ bool DialogsInner::choosePeer() {
Local::writeRecentHashtagsAndBots(); Local::writeRecentHashtagsAndBots();
emit refreshHashtags(); emit refreshHashtags();
selByMouse = true; _selByMouse = true;
onUpdateSelected(true); onUpdateSelected(true);
} else { } else {
saveRecentHashtags('#' + hashtag); saveRecentHashtags('#' + hashtag);
@ -1406,7 +1529,7 @@ bool DialogsInner::choosePeer() {
emit searchResultChosen(); emit searchResultChosen();
} }
updateSelectedRow(); updateSelectedRow();
sel = 0; _sel = nullptr;
_filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1; _filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1;
return true; return true;
} }
@ -1442,7 +1565,7 @@ void DialogsInner::saveRecentHashtags(const QString &text) {
} }
void DialogsInner::destroyData() { void DialogsInner::destroyData() {
sel = nullptr; _sel = nullptr;
_hashtagSel = -1; _hashtagSel = -1;
_hashtagResults.clear(); _hashtagResults.clear();
_filteredSel = -1; _filteredSel = -1;
@ -1453,6 +1576,9 @@ void DialogsInner::destroyData() {
contacts = nullptr; contacts = nullptr;
contactsNoDialogs = nullptr; contactsNoDialogs = nullptr;
dialogs = nullptr; dialogs = nullptr;
if (importantDialogs) {
importantDialogs = nullptr;
}
} }
void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const { void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const {
@ -1462,9 +1588,9 @@ void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&ou
return; return;
} }
if (_state == DefaultState) { if (_state == DefaultState) {
if (auto row = dialogs->getRow(inPeer->id)) { if (auto row = shownDialogs()->getRow(inPeer->id)) {
auto i = dialogs->cfind(row); auto i = shownDialogs()->cfind(row);
if (i != dialogs->cbegin()) { if (i != shownDialogs()->cbegin()) {
outPeer = (*(--i))->history()->peer; outPeer = (*(--i))->history()->peer;
outMsg = ShowAtUnreadMsgId; outMsg = ShowAtUnreadMsgId;
return; return;
@ -1536,9 +1662,9 @@ void DialogsInner::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&out
return; return;
} }
if (_state == DefaultState) { if (_state == DefaultState) {
if (auto row = dialogs->getRow(inPeer->id)) { if (auto row = shownDialogs()->getRow(inPeer->id)) {
auto i = dialogs->cfind(row) + 1; auto i = shownDialogs()->cfind(row) + 1;
if (i != dialogs->cend()) { if (i != shownDialogs()->cend()) {
outPeer = (*i)->history()->peer; outPeer = (*i)->history()->peer;
outMsg = ShowAtUnreadMsgId; outMsg = ShowAtUnreadMsgId;
return; return;
@ -1697,19 +1823,19 @@ void DialogsWidget::activate() {
} }
void DialogsWidget::createDialog(History *history) { void DialogsWidget::createDialog(History *history) {
bool creating = !history->inChatList(); bool creating = !history->inChatList(Dialogs::Mode::All);
_inner.createDialog(history); _inner.createDialog(history);
if (creating && history->peer->migrateFrom()) { if (creating && history->peer->migrateFrom()) {
if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) { if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) {
if (h->inChatList()) { if (h->inChatList(Dialogs::Mode::All)) {
removeDialog(h); removeDialog(h);
} }
} }
} }
} }
void DialogsWidget::dlgUpdated(Dialogs::Row *row) { void DialogsWidget::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) {
_inner.dlgUpdated(row); _inner.dlgUpdated(list, row);
} }
void DialogsWidget::dlgUpdated(History *row, MsgId msgId) { void DialogsWidget::dlgUpdated(History *row, MsgId msgId) {
@ -1795,6 +1921,10 @@ void DialogsWidget::notify_userIsContactChanged(UserData *user, bool fromThisApp
_inner.notify_userIsContactChanged(user, fromThisApp); _inner.notify_userIsContactChanged(user, fromThisApp);
} }
void DialogsWidget::notify_historyMuteUpdated(History *history) {
_inner.notify_historyMuteUpdated(history);
}
void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) { void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
for (QVector<MTPDialog>::const_iterator i = dialogs.cbegin(), e = dialogs.cend(); i != e; ++i) { for (QVector<MTPDialog>::const_iterator i = dialogs.cbegin(), e = dialogs.cend(); i != e; ++i) {
switch (i->type()) { switch (i->type()) {
@ -1802,7 +1932,7 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
const auto &d(i->c_dialog()); const auto &d(i->c_dialog());
if (History *h = App::historyLoaded(peerFromMTP(d.vpeer))) { if (History *h = App::historyLoaded(peerFromMTP(d.vpeer))) {
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h); App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h);
if (d.vunread_count.v >= h->unreadCount) { if (d.vunread_count.v >= h->unreadCount()) {
h->setUnreadCount(d.vunread_count.v, false); h->setUnreadCount(d.vunread_count.v, false);
h->inboxReadBefore = d.vread_inbox_max_id.v + 1; h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
} }
@ -1820,7 +1950,7 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
} }
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h); App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h);
int32 unreadCount = h->isMegagroup() ? d.vunread_count.v : d.vunread_important_count.v; int32 unreadCount = h->isMegagroup() ? d.vunread_count.v : d.vunread_important_count.v;
if (unreadCount >= h->unreadCount) { if (unreadCount >= h->unreadCount()) {
h->setUnreadCount(unreadCount, false); h->setUnreadCount(unreadCount, false);
h->inboxReadBefore = d.vread_inbox_max_id.v + 1; h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
} }

View file

@ -54,10 +54,6 @@ public:
void contactsReceived(const QVector<MTPContact> &contacts); void contactsReceived(const QVector<MTPContact> &contacts);
int32 filteredOffset() const;
int32 peopleOffset() const;
int32 searchedOffset() const;
void mouseMoveEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e); void mousePressEvent(QMouseEvent *e);
void resizeEvent(QResizeEvent *e); void resizeEvent(QResizeEvent *e);
@ -65,14 +61,11 @@ public:
void leaveEvent(QEvent *e); void leaveEvent(QEvent *e);
void contextMenuEvent(QContextMenuEvent *e); void contextMenuEvent(QContextMenuEvent *e);
void peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool act, bool sel, bool onlyBackground) const;
void searchInPeerPaint(Painter &p, int32 w, bool onlyBackground) const;
void selectSkip(int32 direction); void selectSkip(int32 direction);
void selectSkipPage(int32 pixels, int32 direction); void selectSkipPage(int32 pixels, int32 direction);
void createDialog(History *history); void createDialog(History *history);
void dlgUpdated(Dialogs::Row *row); void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
void dlgUpdated(History *row, MsgId msgId); void dlgUpdated(History *row, MsgId msgId);
void removeDialog(History *history); void removeDialog(History *history);
@ -125,6 +118,7 @@ public:
void updateNotifySettings(PeerData *peer); void updateNotifySettings(PeerData *peer);
void notify_userIsContactChanged(UserData *user, bool fromThisApp); void notify_userIsContactChanged(UserData *user, bool fromThisApp);
void notify_historyMuteUpdated(History *history);
~DialogsInner(); ~DialogsInner();
@ -165,17 +159,34 @@ protected:
private: private:
int dialogsOffset() const;
int filteredOffset() const;
int peopleOffset() const;
int searchedOffset() const;
void peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool active, bool selected, bool onlyBackground) const;
void searchInPeerPaint(Painter &p, int32 w, bool onlyBackground) const;
void clearSelection();
void clearSearchResults(bool clearPeople = true); void clearSearchResults(bool clearPeople = true);
void updateSelectedRow(PeerData *peer = 0); void updateSelectedRow(PeerData *peer = 0);
bool menuPeerMuted(); bool menuPeerMuted();
void contextBlockDone(QPair<UserData*, bool> data, const MTPBool &result); void contextBlockDone(QPair<UserData*, bool> data, const MTPBool &result);
Dialogs::IndexedList *shownDialogs() const {
return (Global::DialogsMode() == Dialogs::Mode::Important) ? importantDialogs.get() : dialogs.get();
}
using DialogsList = std_::unique_ptr<Dialogs::IndexedList>; using DialogsList = std_::unique_ptr<Dialogs::IndexedList>;
DialogsList dialogs; DialogsList dialogs;
DialogsList importantDialogs;
DialogsList contactsNoDialogs; DialogsList contactsNoDialogs;
DialogsList contacts; DialogsList contacts;
Dialogs::Row *sel = nullptr;
bool selByMouse = false; bool _importantSwitchSel = false;
Dialogs::Row *_sel = nullptr;
bool _selByMouse = false;
QString _filter, _hashtagFilter; QString _filter, _hashtagFilter;
@ -244,7 +255,7 @@ public:
void loadDialogs(); void loadDialogs();
void createDialog(History *history); void createDialog(History *history);
void dlgUpdated(Dialogs::Row *row); void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
void dlgUpdated(History *row, MsgId msgId); void dlgUpdated(History *row, MsgId msgId);
void dialogsToUp(); void dialogsToUp();
@ -276,6 +287,7 @@ public:
} }
void notify_userIsContactChanged(UserData *user, bool fromThisApp); void notify_userIsContactChanged(UserData *user, bool fromThisApp);
void notify_historyMuteUpdated(History *history);
signals: signals:

View file

@ -155,7 +155,7 @@ namespace App {
} }
} }
} } // namespace App
namespace Ui { namespace Ui {
@ -258,7 +258,7 @@ namespace Ui {
return false; return false;
} }
} } // namespace Ui
namespace Notify { namespace Notify {
@ -313,6 +313,10 @@ namespace Notify {
if (MainWidget *m = App::main()) m->notify_inlineItemLayoutChanged(layout); if (MainWidget *m = App::main()) m->notify_inlineItemLayoutChanged(layout);
} }
void historyMuteUpdated(History *history) {
if (MainWidget *m = App::main()) m->notify_historyMuteUpdated(history);
}
void handlePendingHistoryUpdate() { void handlePendingHistoryUpdate() {
if (MainWidget *m = App::main()) { if (MainWidget *m = App::main()) {
m->notify_handlePendingHistoryUpdate(); m->notify_handlePendingHistoryUpdate();
@ -323,7 +327,7 @@ namespace Notify {
Global::RefPendingRepaintItems().clear(); Global::RefPendingRepaintItems().clear();
} }
} } // namespace Notify
#define DefineReadOnlyVar(Namespace, Type, Name) const Type &Name() { \ #define DefineReadOnlyVar(Namespace, Type, Name) const Type &Name() { \
t_assert_full(Namespace##Data != 0, #Namespace "Data != nullptr in " #Namespace "::" #Name, __FILE__, __LINE__); \ t_assert_full(Namespace##Data != 0, #Namespace "Data != nullptr in " #Namespace "::" #Name, __FILE__, __LINE__); \
@ -341,7 +345,6 @@ void Set##Name(const Type &Name) { \
} }
namespace Sandbox { namespace Sandbox {
namespace internal { namespace internal {
struct Data { struct Data {
@ -352,10 +355,10 @@ namespace Sandbox {
ConnectionProxy PreLaunchProxy; ConnectionProxy PreLaunchProxy;
}; };
} } // namespace internal
} // namespace Sandbox
} Sandbox::internal::Data *SandboxData = nullptr;
Sandbox::internal::Data *SandboxData = 0;
uint64 SandboxUserTag = 0; uint64 SandboxUserTag = 0;
namespace Sandbox { namespace Sandbox {
@ -469,7 +472,7 @@ namespace Sandbox {
DefineVar(Sandbox, QByteArray, LastCrashDump); DefineVar(Sandbox, QByteArray, LastCrashDump);
DefineVar(Sandbox, ConnectionProxy, PreLaunchProxy); DefineVar(Sandbox, ConnectionProxy, PreLaunchProxy);
} } // namespace Sandbox
namespace Global { namespace Global {
namespace internal { namespace internal {
@ -480,6 +483,8 @@ namespace Global {
Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout; Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout;
bool AdaptiveForWide = true; bool AdaptiveForWide = true;
bool DialogsModeEnabled = false;
Dialogs::Mode DialogsMode = Dialogs::Mode::All;
int32 DebugLoggingFlags = 0; int32 DebugLoggingFlags = 0;
@ -513,15 +518,15 @@ namespace Global {
CircleMasksMap CircleMasks; CircleMasksMap CircleMasks;
}; };
} } // namespace internal
} } // namespace Global
Global::internal::Data *GlobalData = 0; Global::internal::Data *GlobalData = nullptr;
namespace Global { namespace Global {
bool started() { bool started() {
return GlobalData != 0; return GlobalData != nullptr;
} }
void start() { void start() {
@ -532,7 +537,7 @@ namespace Global {
void finish() { void finish() {
delete GlobalData; delete GlobalData;
GlobalData = 0; GlobalData = nullptr;
} }
DefineReadOnlyVar(Global, uint64, LaunchId); DefineReadOnlyVar(Global, uint64, LaunchId);
@ -540,6 +545,8 @@ namespace Global {
DefineVar(Global, Adaptive::Layout, AdaptiveLayout); DefineVar(Global, Adaptive::Layout, AdaptiveLayout);
DefineVar(Global, bool, AdaptiveForWide); DefineVar(Global, bool, AdaptiveForWide);
DefineVar(Global, bool, DialogsModeEnabled);
DefineVar(Global, Dialogs::Mode, DialogsMode);
DefineVar(Global, int32, DebugLoggingFlags); DefineVar(Global, int32, DebugLoggingFlags);
@ -572,4 +579,4 @@ namespace Global {
DefineRefVar(Global, CircleMasksMap, CircleMasks); DefineRefVar(Global, CircleMasksMap, CircleMasks);
}; } // namespace Global

View file

@ -40,7 +40,7 @@ namespace App {
void logOutDelayed(); void logOutDelayed();
}; } // namespace App
namespace InlineBots { namespace InlineBots {
namespace Layout { namespace Layout {
@ -88,7 +88,7 @@ namespace Ui {
bool hideWindowNoQuit(); bool hideWindowNoQuit();
}; } // namespace Ui
enum ClipStopperType { enum ClipStopperType {
ClipStopperMediaview, ClipStopperMediaview,
@ -112,11 +112,12 @@ namespace Notify {
void historyItemLayoutChanged(const HistoryItem *item); void historyItemLayoutChanged(const HistoryItem *item);
void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout); void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
void historyMuteUpdated(History *history);
// handle pending resize() / paint() on history items // handle pending resize() / paint() on history items
void handlePendingHistoryUpdate(); void handlePendingHistoryUpdate();
}; } // namespace Notify
#define DeclareReadOnlyVar(Type, Name) const Type &Name(); #define DeclareReadOnlyVar(Type, Name) const Type &Name();
#define DeclareRefVar(Type, Name) DeclareReadOnlyVar(Type, Name) \ #define DeclareRefVar(Type, Name) DeclareReadOnlyVar(Type, Name) \
@ -139,7 +140,7 @@ namespace Sandbox {
DeclareVar(QByteArray, LastCrashDump); DeclareVar(QByteArray, LastCrashDump);
DeclareVar(ConnectionProxy, PreLaunchProxy); DeclareVar(ConnectionProxy, PreLaunchProxy);
} } // namespace Sandbox
namespace Adaptive { namespace Adaptive {
enum Layout { enum Layout {
@ -147,15 +148,16 @@ namespace Adaptive {
NormalLayout, NormalLayout,
WideLayout, WideLayout,
}; };
}; } // namespace Adaptive
namespace DebugLogging { namespace DebugLogging {
enum Flags { enum Flags {
FileLoaderFlag = 0x00000001, FileLoaderFlag = 0x00000001,
}; };
} } // namespace DebugLogging
namespace Stickers { namespace Stickers {
static const uint64 DefaultSetId = 0; // for backward compatibility static const uint64 DefaultSetId = 0; // for backward compatibility
static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL; static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL;
static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel
@ -169,9 +171,10 @@ namespace Stickers {
StickerPack stickers; StickerPack stickers;
StickersByEmojiMap emoji; StickersByEmojiMap emoji;
}; };
typedef QMap<uint64, Set> Sets; using Sets = QMap<uint64, Set>;
typedef QList<uint64> Order; using Order = QList<uint64>;
}
} // namespace Stickers
namespace Global { namespace Global {
@ -184,6 +187,8 @@ namespace Global {
DeclareVar(Adaptive::Layout, AdaptiveLayout); DeclareVar(Adaptive::Layout, AdaptiveLayout);
DeclareVar(bool, AdaptiveForWide); DeclareVar(bool, AdaptiveForWide);
DeclareVar(bool, DialogsModeEnabled);
DeclareVar(Dialogs::Mode, DialogsMode);
DeclareVar(int32, DebugLoggingFlags); DeclareVar(int32, DebugLoggingFlags);
@ -219,9 +224,10 @@ namespace Global {
typedef QMap<uint64, QPixmap> CircleMasksMap; typedef QMap<uint64, QPixmap> CircleMasksMap;
DeclareRefVar(CircleMasksMap, CircleMasks); DeclareRefVar(CircleMasksMap, CircleMasks);
}; } // namespace Global
namespace Adaptive { namespace Adaptive {
inline bool OneColumn() { inline bool OneColumn() {
return Global::AdaptiveLayout() == OneColumnLayout; return Global::AdaptiveLayout() == OneColumnLayout;
} }
@ -231,10 +237,13 @@ namespace Adaptive {
inline bool Wide() { inline bool Wide() {
return Global::AdaptiveForWide() && (Global::AdaptiveLayout() == WideLayout); return Global::AdaptiveForWide() && (Global::AdaptiveLayout() == WideLayout);
} }
}
} // namespace Adaptive
namespace DebugLogging { namespace DebugLogging {
inline bool FileLoader() { inline bool FileLoader() {
return (Global::DebugLoggingFlags() | FileLoaderFlag) != 0; return (Global::DebugLoggingFlags() | FileLoaderFlag) != 0;
} }
}
} // namespace DebugLogging

View file

@ -104,7 +104,7 @@ void historyInit() {
History::History(const PeerId &peerId) History::History(const PeerId &peerId)
: peer(App::peer(peerId)) : peer(App::peer(peerId))
, mute(isNotifyMuted(peer->notify)) { , _mute(isNotifyMuted(peer->notify)) {
if (peer->isChannel() || (peer->isUser() && peer->asUser()->botInfo)) { if (peer->isChannel() || (peer->isUser() && peer->asUser()->botInfo)) {
outboxReadBefore = INT_MAX; outboxReadBefore = INT_MAX;
} }
@ -1683,7 +1683,7 @@ void History::updateShowFrom() {
MsgId History::inboxRead(MsgId upTo) { MsgId History::inboxRead(MsgId upTo) {
if (upTo < 0) return upTo; if (upTo < 0) return upTo;
if (unreadCount) { if (unreadCount()) {
if (upTo && loadedAtBottom()) App::main()->historyToDown(this); if (upTo && loadedAtBottom()) App::main()->historyToDown(this);
setUnreadCount(upTo ? countUnread(upTo) : 0); setUnreadCount(upTo ? countUnread(upTo) : 0);
} }
@ -1739,7 +1739,7 @@ HistoryItem *History::lastImportantMessage() const {
} }
void History::setUnreadCount(int newUnreadCount, bool psUpdate) { void History::setUnreadCount(int newUnreadCount, bool psUpdate) {
if (unreadCount != newUnreadCount) { if (_unreadCount != newUnreadCount) {
if (newUnreadCount == 1) { if (newUnreadCount == 1) {
if (loadedAtBottom()) showFrom = lastImportantMessage(); if (loadedAtBottom()) showFrom = lastImportantMessage();
inboxReadBefore = qMax(inboxReadBefore, msgIdForRead()); inboxReadBefore = qMax(inboxReadBefore, msgIdForRead());
@ -1747,18 +1747,18 @@ void History::setUnreadCount(int newUnreadCount, bool psUpdate) {
showFrom = nullptr; showFrom = nullptr;
inboxReadBefore = qMax(inboxReadBefore, msgIdForRead() + 1); inboxReadBefore = qMax(inboxReadBefore, msgIdForRead() + 1);
} }
if (inChatList()) { if (inChatList(Dialogs::Mode::All)) {
App::histories().unreadIncrement(newUnreadCount - unreadCount, mute); App::histories().unreadIncrement(newUnreadCount - _unreadCount, mute());
if (psUpdate && (!mute || cIncludeMuted()) && App::wnd()) { if (psUpdate && (!mute() || cIncludeMuted()) && App::wnd()) {
App::wnd()->updateCounter(); App::wnd()->updateCounter();
} }
} }
unreadCount = newUnreadCount; _unreadCount = newUnreadCount;
if (unreadBar) { if (unreadBar) {
int32 count = unreadCount; int32 count = _unreadCount;
if (peer->migrateTo()) { if (peer->migrateTo()) {
if (History *h = App::historyLoaded(peer->migrateTo()->id)) { if (History *h = App::historyLoaded(peer->migrateTo()->id)) {
count += h->unreadCount; count += h->unreadCount();
} }
} }
if (count > 0) { if (count > 0) {
@ -1771,12 +1771,15 @@ void History::setUnreadCount(int newUnreadCount, bool psUpdate) {
} }
void History::setMute(bool newMute) { void History::setMute(bool newMute) {
if (mute != newMute) { if (_mute != newMute) {
mute = newMute; _mute = newMute;
if (inChatList() && unreadCount) { if (inChatList(Dialogs::Mode::All)) {
App::histories().unreadMuteChanged(unreadCount, newMute); if (_unreadCount) {
App::histories().unreadMuteChanged(_unreadCount, newMute);
if (App::wnd()) App::wnd()->updateCounter(); if (App::wnd()) App::wnd()->updateCounter();
} }
Notify::historyMuteUpdated(this);
}
updateChatListEntry(); updateChatListEntry();
} }
} }
@ -1881,12 +1884,12 @@ void History::getNextScrollTopItem(HistoryBlock *block, int32 i) {
} }
void History::addUnreadBar() { void History::addUnreadBar() {
if (unreadBar || !showFrom || showFrom->detached() || !unreadCount) return; if (unreadBar || !showFrom || showFrom->detached() || !unreadCount()) return;
int32 count = unreadCount; int32 count = unreadCount();
if (peer->migrateTo()) { if (peer->migrateTo()) {
if (History *h = App::historyLoaded(peer->migrateTo()->id)) { if (History *h = App::historyLoaded(peer->migrateTo()->id)) {
count += h->unreadCount; count += h->unreadCount();
} }
} }
showFrom->setUnreadBarCount(count); showFrom->setUnreadBarCount(count);
@ -2014,12 +2017,12 @@ bool History::isReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScrol
if (msgId == ShowAtUnreadMsgId) { if (msgId == ShowAtUnreadMsgId) {
if (peer->migrateFrom()) { // old group history if (peer->migrateFrom()) { // old group history
if (History *h = App::historyLoaded(peer->migrateFrom()->id)) { if (History *h = App::historyLoaded(peer->migrateFrom()->id)) {
if (h->unreadCount) { if (h->unreadCount()) {
return h->isReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop); return h->isReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop);
} }
} }
} }
if (unreadCount) { if (unreadCount()) {
if (!isEmpty()) { if (!isEmpty()) {
return (loadedAtTop() || minMsgId() <= inboxReadBefore) && (loadedAtBottom() || maxMsgId() >= inboxReadBefore); return (loadedAtTop() || minMsgId() <= inboxReadBefore) && (loadedAtBottom() || maxMsgId() >= inboxReadBefore);
} }
@ -2045,7 +2048,7 @@ void History::getReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScro
} }
if (msgId == ShowAtUnreadMsgId && peer->migrateFrom()) { if (msgId == ShowAtUnreadMsgId && peer->migrateFrom()) {
if (History *h = App::historyLoaded(peer->migrateFrom()->id)) { if (History *h = App::historyLoaded(peer->migrateFrom()->id)) {
if (h->unreadCount) { if (h->unreadCount()) {
clear(true); clear(true);
h->getReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop); h->getReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop);
return; return;
@ -2084,12 +2087,12 @@ void History::setLastMessage(HistoryItem *msg) {
} }
void History::setChatsListDate(const QDateTime &date) { void History::setChatsListDate(const QDateTime &date) {
bool updateDialog = (App::main() && (!peer->isChannel() || peer->asChannel()->amIn() || !_chatListLinks.isEmpty())); bool updateDialog = (App::main() && (!peer->isChannel() || peer->asChannel()->amIn() || inChatList(Dialogs::Mode::All)));
if (peer->migrateTo() && _chatListLinks.isEmpty()) { if (peer->migrateTo() && !inChatList(Dialogs::Mode::All)) {
updateDialog = false; updateDialog = false;
} }
if (!lastMsgDate.isNull() && lastMsgDate >= date) { if (!lastMsgDate.isNull() && lastMsgDate >= date) {
if (!updateDialog || !_chatListLinks.isEmpty()) { if (!updateDialog || !inChatList(Dialogs::Mode::All)) {
return; return;
} }
} }
@ -2225,61 +2228,64 @@ void History::clearOnDestroy() {
clearBlocks(false); clearBlocks(false);
} }
QPair<int32, int32> History::adjustByPosInChatsList(Dialogs::IndexedList *indexed) { QPair<int32, int32> History::adjustByPosInChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed) {
t_assert(indexed != nullptr); t_assert(indexed != nullptr);
Dialogs::Row *lnk = mainChatListLink(); Dialogs::Row *lnk = mainChatListLink(list);
int32 movedFrom = lnk->pos() * st::dlgHeight; int32 movedFrom = lnk->pos() * st::dlgHeight;
indexed->adjustByPos(_chatListLinks); indexed->adjustByPos(chatListLinks(list));
int32 movedTo = lnk->pos() * st::dlgHeight; int32 movedTo = lnk->pos() * st::dlgHeight;
return qMakePair(movedFrom, movedTo); return qMakePair(movedFrom, movedTo);
} }
int History::posInChatList() const { int History::posInChatList(Dialogs::Mode list) const {
return mainChatListLink()->pos(); return mainChatListLink(list)->pos();
} }
Dialogs::Row *History::addToChatList(Dialogs::IndexedList *indexed) { Dialogs::Row *History::addToChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed) {
t_assert(indexed != nullptr); t_assert(indexed != nullptr);
if (!inChatList()) { if (!inChatList(list)) {
_chatListLinks = indexed->addToEnd(this); chatListLinks(list) = indexed->addToEnd(this);
if (unreadCount) { if (list == Dialogs::Mode::All && unreadCount()) {
App::histories().unreadIncrement(unreadCount, mute); App::histories().unreadIncrement(unreadCount(), mute());
if (App::wnd()) App::wnd()->updateCounter(); if (App::wnd()) App::wnd()->updateCounter();
} }
} }
return mainChatListLink(); return mainChatListLink(list);
} }
void History::removeFromChatList(Dialogs::IndexedList *indexed) { void History::removeFromChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed) {
t_assert(indexed != nullptr); t_assert(indexed != nullptr);
if (inChatList()) { if (inChatList(list)) {
indexed->del(peer); indexed->del(peer);
_chatListLinks.clear(); chatListLinks(list).clear();
if (unreadCount) { if (list == Dialogs::Mode::All && unreadCount()) {
App::histories().unreadIncrement(-unreadCount, mute); App::histories().unreadIncrement(-unreadCount(), mute());
if (App::wnd()) App::wnd()->updateCounter(); if (App::wnd()) App::wnd()->updateCounter();
} }
} }
} }
void History::removeChatListEntryByLetter(QChar letter) { void History::removeChatListEntryByLetter(Dialogs::Mode list, QChar letter) {
t_assert(letter != 0); t_assert(letter != 0);
if (inChatList()) { if (inChatList(list)) {
_chatListLinks.remove(letter); chatListLinks(list).remove(letter);
} }
} }
void History::addChatListEntryByLetter(QChar letter, Dialogs::Row *row) { void History::addChatListEntryByLetter(Dialogs::Mode list, QChar letter, Dialogs::Row *row) {
t_assert(letter != 0); t_assert(letter != 0);
if (inChatList()) { if (inChatList(list)) {
_chatListLinks.insert(letter, row); chatListLinks(list).insert(letter, row);
} }
} }
void History::updateChatListEntry() const { void History::updateChatListEntry() const {
if (MainWidget *m = App::main()) { if (MainWidget *m = App::main()) {
if (inChatList()) { if (inChatList(Dialogs::Mode::All)) {
m->dlgUpdated(mainChatListLink()); m->dlgUpdated(Dialogs::Mode::All, mainChatListLink(Dialogs::Mode::All));
if (inChatList(Dialogs::Mode::Important)) {
m->dlgUpdated(Dialogs::Mode::Important, mainChatListLink(Dialogs::Mode::Important));
}
} }
} }
} }
@ -2986,8 +2992,8 @@ void HistoryItem::destroy() {
history()->clearLastKeyboard(); history()->clearLastKeyboard();
if (App::main()) App::main()->updateBotKeyboard(history()); if (App::main()) App::main()->updateBotKeyboard(history());
} }
if ((!out() || isPost()) && unread() && history()->unreadCount > 0) { if ((!out() || isPost()) && unread() && history()->unreadCount() > 0) {
history()->setUnreadCount(history()->unreadCount - 1); history()->setUnreadCount(history()->unreadCount() - 1);
} }
Global::RefPendingRepaintItems().remove(this); Global::RefPendingRepaintItems().remove(this);
delete this; delete this;

View file

@ -65,6 +65,9 @@ public:
int32 unreadBadge() const { int32 unreadBadge() const {
return _unreadFull - (cIncludeMuted() ? 0 : _unreadMuted); return _unreadFull - (cIncludeMuted() ? 0 : _unreadMuted);
} }
int32 unreadMutedCount() const {
return _unreadMuted;
}
bool unreadOnlyMuted() const { bool unreadOnlyMuted() const {
return cIncludeMuted() ? (_unreadMuted >= _unreadFull) : false; return cIncludeMuted() ? (_unreadMuted >= _unreadFull) : false;
} }
@ -249,7 +252,13 @@ public:
HistoryItem *lastImportantMessage() const; HistoryItem *lastImportantMessage() const;
int unreadCount() const {
return _unreadCount;
}
void setUnreadCount(int newUnreadCount, bool psUpdate = true); void setUnreadCount(int newUnreadCount, bool psUpdate = true);
bool mute() const {
return _mute;
}
void setMute(bool newMute); void setMute(bool newMute);
void getNextShowFrom(HistoryBlock *block, int i); void getNextShowFrom(HistoryBlock *block, int i);
void addUnreadBar(); void addUnreadBar();
@ -266,18 +275,18 @@ public:
void fixLastMessage(bool wasAtBottom); void fixLastMessage(bool wasAtBottom);
void setChatsListDate(const QDateTime &date); void setChatsListDate(const QDateTime &date);
QPair<int32, int32> adjustByPosInChatsList(Dialogs::IndexedList *indexed);
uint64 sortKeyInChatList() const { uint64 sortKeyInChatList() const {
return _sortKeyInChatList; return _sortKeyInChatList;
} }
bool inChatList() const { QPair<int32, int32> adjustByPosInChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed);
return !_chatListLinks.isEmpty(); bool inChatList(Dialogs::Mode list) const {
return !chatListLinks(list).isEmpty();
} }
int posInChatList() const; int posInChatList(Dialogs::Mode list) const;
Dialogs::Row *addToChatList(Dialogs::IndexedList *indexed); Dialogs::Row *addToChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed);
void removeFromChatList(Dialogs::IndexedList *indexed); void removeFromChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed);
void removeChatListEntryByLetter(QChar letter); void removeChatListEntryByLetter(Dialogs::Mode list, QChar letter);
void addChatListEntryByLetter(QChar letter, Dialogs::Row *row); void addChatListEntryByLetter(Dialogs::Mode list, QChar letter, Dialogs::Row *row);
void updateChatListEntry() const; void updateChatListEntry() const;
MsgId minMsgId() const; MsgId minMsgId() const;
@ -334,7 +343,6 @@ public:
int width = 0; int width = 0;
int height = 0; int height = 0;
int32 msgCount = 0; int32 msgCount = 0;
int32 unreadCount = 0;
MsgId inboxReadBefore = 1; MsgId inboxReadBefore = 1;
MsgId outboxReadBefore = 1; MsgId outboxReadBefore = 1;
HistoryItem *showFrom = nullptr; HistoryItem *showFrom = nullptr;
@ -412,8 +420,6 @@ protected:
public: public:
bool mute;
bool lastKeyboardInited = false; bool lastKeyboardInited = false;
bool lastKeyboardUsed = false; bool lastKeyboardUsed = false;
MsgId lastKeyboardId = 0; MsgId lastKeyboardId = 0;
@ -536,11 +542,19 @@ private:
return ~QFlags<Flags::enum_type>(f); return ~QFlags<Flags::enum_type>(f);
} }
Flags _flags; Flags _flags;
bool _mute;
int32 _unreadCount = 0;
Dialogs::RowsByLetter _chatListLinks; Dialogs::RowsByLetter _chatListLinks[2];
Dialogs::Row *mainChatListLink() const { Dialogs::RowsByLetter &chatListLinks(Dialogs::Mode list) {
auto it = _chatListLinks.constFind(0); return _chatListLinks[static_cast<int>(list)];
t_assert(it != _chatListLinks.cend()); }
const Dialogs::RowsByLetter &chatListLinks(Dialogs::Mode list) const {
return _chatListLinks[static_cast<int>(list)];
}
Dialogs::Row *mainChatListLink(Dialogs::Mode list) const {
auto it = chatListLinks(list).constFind(0);
t_assert(it != chatListLinks(list).cend());
return it.value(); return it.value();
} }
uint64 _sortKeyInChatList = 0; // like ((unixtime) << 32) | (incremented counter) uint64 _sortKeyInChatList = 0; // like ((unixtime) << 32) | (incremented counter)

View file

@ -3270,7 +3270,7 @@ void HistoryWidget::notify_migrateUpdated(PeerData *peer) {
showHistory(peer->migrateTo()->id, (_showAtMsgId > 0) ? (-_showAtMsgId) : _showAtMsgId, true); showHistory(peer->migrateTo()->id, (_showAtMsgId > 0) ? (-_showAtMsgId) : _showAtMsgId, true);
} else if ((_migrated ? _migrated->peer : 0) != peer->migrateFrom()) { } else if ((_migrated ? _migrated->peer : 0) != peer->migrateFrom()) {
History *migrated = peer->migrateFrom() ? App::history(peer->migrateFrom()->id) : 0; History *migrated = peer->migrateFrom() ? App::history(peer->migrateFrom()->id) : 0;
if (_migrated || (migrated && migrated->unreadCount > 0)) { if (_migrated || (migrated && migrated->unreadCount() > 0)) {
showHistory(peer->id, peer->migrateFrom() ? _showAtMsgId : ((_showAtMsgId < 0 && -_showAtMsgId < ServerMaxMsgId) ? ShowAtUnreadMsgId : _showAtMsgId), true); showHistory(peer->id, peer->migrateFrom() ? _showAtMsgId : ((_showAtMsgId < 0 && -_showAtMsgId < ServerMaxMsgId) ? ShowAtUnreadMsgId : _showAtMsgId), true);
} else { } else {
_migrated = migrated; _migrated = migrated;
@ -3831,7 +3831,7 @@ void HistoryWidget::updateFieldSubmitSettings() {
void HistoryWidget::updateNotifySettings() { void HistoryWidget::updateNotifySettings() {
if (!_peer || !_peer->isChannel()) return; if (!_peer || !_peer->isChannel()) return;
_muteUnmute.setText(lang(_history->mute ? lng_channel_unmute : lng_channel_mute)); _muteUnmute.setText(lang(_history->mute() ? lng_channel_unmute : lng_channel_mute));
if (_peer->notify != UnknownNotifySettings) { if (_peer->notify != UnknownNotifySettings) {
_silent.setChecked(_peer->notify != EmptyNotifySettings && (_peer->notify->flags & MTPDpeerNotifySettings::Flag::f_silent)); _silent.setChecked(_peer->notify != EmptyNotifySettings && (_peer->notify->flags & MTPDpeerNotifySettings::Flag::f_silent));
if (_silent.isHidden() && hasSilentToggle()) { if (_silent.isHidden() && hasSilentToggle()) {
@ -4211,7 +4211,7 @@ void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) {
} }
} else { } else {
App::wnd()->notifySchedule(history, item); App::wnd()->notifySchedule(history, item);
history->setUnreadCount(history->unreadCount + 1); history->setUnreadCount(history->unreadCount() + 1);
} }
} else { } else {
if (_history == history) { if (_history == history) {
@ -4220,7 +4220,7 @@ void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) {
} }
} }
App::wnd()->notifySchedule(history, item); App::wnd()->notifySchedule(history, item);
history->setUnreadCount(history->unreadCount + 1); history->setUnreadCount(history->unreadCount() + 1);
} }
} }
@ -4339,7 +4339,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
} }
_firstLoadRequest = 0; _firstLoadRequest = 0;
if (_history->loadedAtTop()) { if (_history->loadedAtTop()) {
if (_history->unreadCount > count) { if (_history->unreadCount() > count) {
_history->setUnreadCount(count); _history->setUnreadCount(count);
} }
if (_history->isEmpty() && count > 0) { if (_history->isEmpty() && count > 0) {
@ -4373,7 +4373,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
} }
_firstLoadRequest = 0; _firstLoadRequest = 0;
if (_history->loadedAtTop()) { if (_history->loadedAtTop()) {
if (_history->unreadCount > count) { if (_history->unreadCount() > count) {
_history->setUnreadCount(count); _history->setUnreadCount(count);
} }
if (_history->isEmpty() && count > 0) { if (_history->isEmpty() && count > 0) {
@ -4429,12 +4429,12 @@ void HistoryWidget::firstLoadMessages() {
PeerData *from = _peer; PeerData *from = _peer;
int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage; int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage;
if (_showAtMsgId == ShowAtUnreadMsgId) { if (_showAtMsgId == ShowAtUnreadMsgId) {
if (_migrated && _migrated->unreadCount) { if (_migrated && _migrated->unreadCount()) {
_history->getReadyFor(_showAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop); _history->getReadyFor(_showAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop);
from = _migrated->peer; from = _migrated->peer;
offset = -loadCount / 2; offset = -loadCount / 2;
offset_id = _migrated->inboxReadBefore; offset_id = _migrated->inboxReadBefore;
} else if (_history->unreadCount) { } else if (_history->unreadCount()) {
_history->getReadyFor(_showAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop); _history->getReadyFor(_showAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop);
offset = -loadCount / 2; offset = -loadCount / 2;
offset_id = _history->inboxReadBefore; offset_id = _history->inboxReadBefore;
@ -4552,11 +4552,11 @@ void HistoryWidget::delayedShowAt(MsgId showAtMsgId) {
PeerData *from = _peer; PeerData *from = _peer;
int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage; int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage;
if (_delayedShowAtMsgId == ShowAtUnreadMsgId) { if (_delayedShowAtMsgId == ShowAtUnreadMsgId) {
if (_migrated && _migrated->unreadCount) { if (_migrated && _migrated->unreadCount()) {
from = _migrated->peer; from = _migrated->peer;
offset = -loadCount / 2; offset = -loadCount / 2;
offset_id = _migrated->inboxReadBefore; offset_id = _migrated->inboxReadBefore;
} else if (_history->unreadCount) { } else if (_history->unreadCount()) {
offset = -loadCount / 2; offset = -loadCount / 2;
offset_id = _history->inboxReadBefore; offset_id = _history->inboxReadBefore;
} else { } else {
@ -4872,7 +4872,7 @@ bool HistoryWidget::joinFail(const RPCError &error, mtpRequestId req) {
} }
void HistoryWidget::onMuteUnmute() { void HistoryWidget::onMuteUnmute() {
App::main()->updateNotifySetting(_peer, _history->mute ? NotifySettingSetNotify : NotifySettingSetMuted); App::main()->updateNotifySetting(_peer, _history->mute() ? NotifySettingSetNotify : NotifySettingSetMuted);
} }
void HistoryWidget::onBroadcastSilentChange() { void HistoryWidget::onBroadcastSilentChange() {
@ -6720,10 +6720,10 @@ void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector<MTPMessage>
} }
void HistoryWidget::countHistoryShowFrom() { void HistoryWidget::countHistoryShowFrom() {
if (_migrated && _showAtMsgId == ShowAtUnreadMsgId && _migrated->unreadCount) { if (_migrated && _showAtMsgId == ShowAtUnreadMsgId && _migrated->unreadCount()) {
_migrated->updateShowFrom(); _migrated->updateShowFrom();
} }
if ((_migrated && _migrated->showFrom) || _showAtMsgId != ShowAtUnreadMsgId || !_history->unreadCount) { if ((_migrated && _migrated->showFrom) || _showAtMsgId != ShowAtUnreadMsgId || !_history->unreadCount()) {
_history->showFrom = 0; _history->showFrom = 0;
return; return;
} }

View file

@ -90,6 +90,7 @@ private:
Gif, Gif,
Article, Article,
Contact, Contact,
Geo,
Venue, Venue,
}; };

View file

@ -604,6 +604,7 @@ namespace {
dbiAutoPlay = 0x37, dbiAutoPlay = 0x37,
dbiAdaptiveForWide = 0x38, dbiAdaptiveForWide = 0x38,
dbiHiddenPinnedMessages = 0x39, dbiHiddenPinnedMessages = 0x39,
dbiDialogsMode = 0x40,
dbiEncryptedWithSalt = 333, dbiEncryptedWithSalt = 333,
dbiEncrypted = 444, dbiEncrypted = 444,
@ -981,6 +982,22 @@ namespace {
cSetAutoPlayGif(gif == 1); cSetAutoPlayGif(gif == 1);
} break; } break;
case dbiDialogsMode: {
qint32 enabled, modeInt;
stream >> enabled >> modeInt;
if (!_checkStreamStatus(stream)) return false;
Global::SetDialogsModeEnabled(enabled == 1);
Dialogs::Mode mode = Dialogs::Mode::All;
if (enabled) {
mode = static_cast<Dialogs::Mode>(modeInt);
if (mode != Dialogs::Mode::All && mode != Dialogs::Mode::Important) {
mode = Dialogs::Mode::All;
}
}
Global::SetDialogsMode(mode);
} break;
case dbiIncludeMuted: { case dbiIncludeMuted: {
qint32 v; qint32 v;
stream >> v; stream >> v;
@ -1578,6 +1595,7 @@ namespace {
size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? cGetRecentStickers().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort)); size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? cGetRecentStickers().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + Serialize::stringSize(cDialogLastPath()); size += sizeof(quint32) + Serialize::stringSize(cDialogLastPath());
size += sizeof(quint32) + 3 * sizeof(qint32); size += sizeof(quint32) + 3 * sizeof(qint32);
size += sizeof(quint32) + 2 * sizeof(qint32);
if (!Global::HiddenPinnedMessages().isEmpty()) { if (!Global::HiddenPinnedMessages().isEmpty()) {
size += sizeof(quint32) + sizeof(qint32) + Global::HiddenPinnedMessages().size() * (sizeof(PeerId) + sizeof(MsgId)); size += sizeof(quint32) + sizeof(qint32) + Global::HiddenPinnedMessages().size() * (sizeof(PeerId) + sizeof(MsgId));
} }
@ -1601,6 +1619,7 @@ namespace {
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath(); data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
data.stream << quint32(dbiSongVolume) << qint32(qRound(cSongVolume() * 1e6)); data.stream << quint32(dbiSongVolume) << qint32(qRound(cSongVolume() * 1e6));
data.stream << quint32(dbiAutoDownload) << qint32(cAutoDownloadPhoto()) << qint32(cAutoDownloadAudio()) << qint32(cAutoDownloadGif()); data.stream << quint32(dbiAutoDownload) << qint32(cAutoDownloadPhoto()) << qint32(cAutoDownloadAudio()) << qint32(cAutoDownloadGif());
data.stream << quint32(dbiDialogsMode) << qint32(Global::DialogsModeEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsMode());
data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0); data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0);
{ {

View file

@ -844,6 +844,10 @@ void MainWidget::notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBa
history.notify_inlineItemLayoutChanged(layout); history.notify_inlineItemLayoutChanged(layout);
} }
void MainWidget::notify_historyMuteUpdated(History *history) {
dialogs.notify_historyMuteUpdated(history);
}
void MainWidget::notify_handlePendingHistoryUpdate() { void MainWidget::notify_handlePendingHistoryUpdate() {
history.notify_handlePendingHistoryUpdate(); history.notify_handlePendingHistoryUpdate();
} }
@ -1509,7 +1513,7 @@ void MainWidget::saveRecentHashtags(const QString &text) {
} }
void MainWidget::readServerHistory(History *hist, bool force) { void MainWidget::readServerHistory(History *hist, bool force) {
if (!hist || (!force && !hist->unreadCount)) return; if (!hist || (!force && !hist->unreadCount())) return;
MsgId upTo = hist->inboxRead(0); MsgId upTo = hist->inboxRead(0);
if (hist->isChannel() && !hist->peer->asChannel()->amIn()) { if (hist->isChannel() && !hist->peer->asChannel()->amIn()) {
@ -2665,14 +2669,18 @@ QRect MainWidget::historyRect() const {
return r; return r;
} }
void MainWidget::dlgUpdated(Dialogs::Row *row) { void MainWidget::dlgUpdated() {
if (row) { if (_peerInStack) {
dialogs.dlgUpdated(row);
} else if (_peerInStack) {
dialogs.dlgUpdated(App::history(_peerInStack->id), _msgIdInStack); dialogs.dlgUpdated(App::history(_peerInStack->id), _msgIdInStack);
} }
} }
void MainWidget::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) {
if (row) {
dialogs.dlgUpdated(list, row);
}
}
void MainWidget::dlgUpdated(History *row, MsgId msgId) { void MainWidget::dlgUpdated(History *row, MsgId msgId) {
if (!row) return; if (!row) return;
if (msgId < 0 && -msgId < ServerMaxMsgId && row->peer->migrateFrom()) { if (msgId < 0 && -msgId < ServerMaxMsgId && row->peer->migrateFrom()) {
@ -3113,7 +3121,7 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
h->setLastMessage(item); h->setLastMessage(item);
} }
int32 unreadCount = h->isMegagroup() ? d.vunread_count.v : d.vunread_important_count.v; int32 unreadCount = h->isMegagroup() ? d.vunread_count.v : d.vunread_important_count.v;
if (unreadCount >= h->unreadCount) { if (unreadCount >= h->unreadCount()) {
h->setUnreadCount(unreadCount, false); h->setUnreadCount(unreadCount, false);
h->inboxReadBefore = d.vread_inbox_max_id.v + 1; h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
} }

View file

@ -260,7 +260,8 @@ public:
void createDialog(History *history); void createDialog(History *history);
void removeDialog(History *history); void removeDialog(History *history);
void dlgUpdated(Dialogs::Row *row = nullptr); void dlgUpdated();
void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
void dlgUpdated(History *row, MsgId msgId); void dlgUpdated(History *row, MsgId msgId);
void windowShown(); void windowShown();
@ -467,6 +468,7 @@ public:
void notify_clipStopperHidden(ClipStopperType type); void notify_clipStopperHidden(ClipStopperType type);
void notify_historyItemLayoutChanged(const HistoryItem *item); void notify_historyItemLayoutChanged(const HistoryItem *item);
void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout); void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
void notify_historyMuteUpdated(History *history);
void notify_handlePendingHistoryUpdate(); void notify_handlePendingHistoryUpdate();
void cmd_search(); void cmd_search();

View file

@ -823,14 +823,22 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
} else { } else {
Global::RefDebugLoggingFlags() |= DebugLogging::FileLoaderFlag; Global::RefDebugLoggingFlags() |= DebugLogging::FileLoaderFlag;
} }
Ui::showLayer(new InformBox(DebugLogging::FileLoader() ? "Enabled file download logging" : "Disabled file download logging")); Ui::showLayer(new InformBox(DebugLogging::FileLoader() ? qsl("Enabled file download logging") : qsl("Disabled file download logging")));
} else if (str == qstr("crashplease")) { } else if (str == qstr("crashplease")) {
t_assert(!"Crashed in Settings!"); t_assert(!"Crashed in Settings!");
} else if (str == qstr("workmode")) {
QString text = Global::DialogsModeEnabled() ? qsl("Disable work mode?") : qsl("Enable work mode?");
auto box = std_::make_unique<ConfirmBox>(text);
connect(box.get(), SIGNAL(confirmed()), App::app(), SLOT(onSwitchWorkMode()));
Ui::showLayer(box.release());
from = size;
break;
} else if ( } else if (
qsl("debugmode").startsWith(str) || qsl("debugmode").startsWith(str) ||
qsl("testmode").startsWith(str) || qsl("testmode").startsWith(str) ||
qsl("loadlang").startsWith(str) || qsl("loadlang").startsWith(str) ||
qsl("debugfiles").startsWith(str) || qsl("debugfiles").startsWith(str) ||
qsl("workmode").startsWith(str) ||
qsl("crashplease").startsWith(str)) { qsl("crashplease").startsWith(str)) {
break; break;
} }

View file

@ -0,0 +1,35 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "ui/buttons/peer_avatar_button.h"
PeerAvatarButton::PeerAvatarButton(QWidget *parent, PeerData *peer, const style::PeerAvatarButton &st) : Button(parent)
, _peer(peer)
, _st(st) {
resize(_st.size, _st.size);
}
void PeerAvatarButton::paintEvent(QPaintEvent *e) {
if (_peer) {
Painter p(this);
_peer->paintUserpic(p, _st.photoSize, (_st.size - _st.photoSize) / 2, (_st.size - _st.photoSize) / 2);
}
}

View file

@ -0,0 +1,40 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/button.h"
#include "ui/style.h"
#include "structs.h"
class PeerAvatarButton : public Button {
public:
PeerAvatarButton(QWidget *parent, PeerData *peer, const style::PeerAvatarButton &st);
void setPeer(PeerData *peer) {
_peer = peer;
update();
}
void paintEvent(QPaintEvent *e);
private:
PeerData *_peer;
const style::PeerAvatarButton &_st;
};