mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Encapsulated unreadCount and mute fields in History.
Support for hiding all muted chats from the list.
This commit is contained in:
parent
03bbb2269d
commit
e0d6a68554
26 changed files with 1323 additions and 962 deletions
|
@ -886,6 +886,8 @@ dlgPaddingVer: 8px;
|
|||
dlgHeight: 62px;
|
||||
dlgPhotoPadding: 12px;
|
||||
|
||||
dlgImportantHeight: 37px;
|
||||
|
||||
noContactsHeight: 100px;
|
||||
noContactsFont: font(fsize);
|
||||
noContactsColor: #777;
|
||||
|
|
|
@ -245,7 +245,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
|||
if (!h->isEmpty()) {
|
||||
h->clear(true);
|
||||
}
|
||||
if (hto->inChatList() && h->inChatList()) {
|
||||
if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) {
|
||||
App::removeDialog(h);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -557,7 +557,7 @@ namespace {
|
|||
if (!h->isEmpty()) {
|
||||
h->clear(true);
|
||||
}
|
||||
if (hto->inChatList() && h->inChatList()) {
|
||||
if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) {
|
||||
App::removeDialog(h);
|
||||
}
|
||||
}
|
||||
|
@ -1137,8 +1137,8 @@ namespace {
|
|||
} else {
|
||||
if (channelHistory) {
|
||||
channelHistory->messageWithIdDeleted(i->v);
|
||||
if (channelHistory->unreadCount > 0 && i->v >= channelHistory->inboxReadBefore) {
|
||||
channelHistory->setUnreadCount(channelHistory->unreadCount - 1);
|
||||
if (channelHistory->unreadCount() > 0 && i->v >= channelHistory->inboxReadBefore) {
|
||||
channelHistory->setUnreadCount(channelHistory->unreadCount() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
if (cTestMode()) {
|
||||
QFile(cWorkingDir() + qsl("tdata/withtestmode")).remove();
|
||||
|
|
|
@ -195,6 +195,7 @@ public slots:
|
|||
void photoUpdated(const FullMsgId &msgId, bool silent, const MTPInputFile &file);
|
||||
|
||||
void onSwitchDebugMode();
|
||||
void onSwitchWorkMode();
|
||||
void onSwitchTestMode();
|
||||
|
||||
void killDownloadSessions();
|
||||
|
|
|
@ -1183,7 +1183,7 @@ EditChannelBox::EditChannelBox(ChannelData *channel) : AbstractBox()
|
|||
, _saveTitleRequestId(0)
|
||||
, _saveDescriptionRequestId(0)
|
||||
, _saveSignRequestId(0) {
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
|
||||
|
||||
setMouseTracking(true);
|
||||
|
||||
|
|
|
@ -1757,7 +1757,7 @@ MembersInner::MembersInner(ChannelData *channel, MembersFilter filter) : TWidget
|
|||
, _about(_aboutWidth)
|
||||
, _aboutHeight(0) {
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
|
||||
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||
|
||||
refresh();
|
||||
|
|
|
@ -26,9 +26,14 @@ class Row;
|
|||
using RowsByLetter = QMap<QChar, Row*>;
|
||||
|
||||
enum class SortMode {
|
||||
Date,
|
||||
Name,
|
||||
Add
|
||||
Date = 0x00,
|
||||
Name = 0x01,
|
||||
Add = 0x02,
|
||||
};
|
||||
|
||||
enum class Mode {
|
||||
All = 0x00,
|
||||
Important = 0x01,
|
||||
};
|
||||
|
||||
} // namespace Dialogs
|
||||
|
|
|
@ -71,72 +71,85 @@ void IndexedList::adjustByPos(const RowsByLetter &links) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
|
||||
t_assert(_sortMode != SortMode::Date);
|
||||
if (_sortMode == SortMode::Name) {
|
||||
Row *mainRow = _list.adjustByName(peer);
|
||||
if (!mainRow) return;
|
||||
|
||||
History *history = mainRow->history();
|
||||
|
||||
PeerData::NameFirstChars toRemove = oldChars, toAdd;
|
||||
for_const (auto ch, peer->chars) {
|
||||
auto j = toRemove.find(ch);
|
||||
if (j == toRemove.cend()) {
|
||||
toAdd.insert(ch);
|
||||
} else {
|
||||
toRemove.erase(j);
|
||||
if (auto list = _index.value(ch)) {
|
||||
list->adjustByName(peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
for_const (auto ch, toRemove) {
|
||||
if (auto list = _index.value(ch)) {
|
||||
list->del(peer->id, mainRow);
|
||||
}
|
||||
}
|
||||
if (!toAdd.isEmpty()) {
|
||||
for_const (auto ch, toAdd) {
|
||||
auto j = _index.find(ch);
|
||||
if (j == _index.cend()) {
|
||||
j = _index.insert(ch, new List(_sortMode));
|
||||
}
|
||||
j.value()->addByName(history);
|
||||
}
|
||||
}
|
||||
adjustByName(peer, oldNames, oldChars);
|
||||
} else {
|
||||
auto mainRow = _list.getRow(peer->id);
|
||||
if (!mainRow) return;
|
||||
adjustNames(Dialogs::Mode::All, peer, oldNames, oldChars);
|
||||
}
|
||||
}
|
||||
|
||||
History *history = mainRow->history();
|
||||
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);
|
||||
}
|
||||
|
||||
PeerData::NameFirstChars toRemove = oldChars, toAdd;
|
||||
for_const (auto ch, peer->chars) {
|
||||
auto j = toRemove.find(ch);
|
||||
if (j == toRemove.cend()) {
|
||||
toAdd.insert(ch);
|
||||
} else {
|
||||
toRemove.erase(j);
|
||||
}
|
||||
}
|
||||
for_const (auto ch, toRemove) {
|
||||
if (_sortMode == SortMode::Date) {
|
||||
history->removeChatListEntryByLetter(ch);
|
||||
}
|
||||
void IndexedList::adjustByName(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
|
||||
Row *mainRow = _list.adjustByName(peer);
|
||||
if (!mainRow) return;
|
||||
|
||||
History *history = mainRow->history();
|
||||
|
||||
PeerData::NameFirstChars toRemove = oldChars, toAdd;
|
||||
for_const (auto ch, peer->chars) {
|
||||
auto j = toRemove.find(ch);
|
||||
if (j == toRemove.cend()) {
|
||||
toAdd.insert(ch);
|
||||
} else {
|
||||
toRemove.erase(j);
|
||||
if (auto list = _index.value(ch)) {
|
||||
list->del(peer->id, mainRow);
|
||||
list->adjustByName(peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
for_const (auto ch, toRemove) {
|
||||
if (auto list = _index.value(ch)) {
|
||||
list->del(peer->id, mainRow);
|
||||
}
|
||||
}
|
||||
if (!toAdd.isEmpty()) {
|
||||
for_const (auto ch, toAdd) {
|
||||
auto j = _index.find(ch);
|
||||
if (j == _index.cend()) {
|
||||
j = _index.insert(ch, new List(_sortMode));
|
||||
}
|
||||
Row *row = j.value()->addToEnd(history);
|
||||
if (_sortMode == SortMode::Date) {
|
||||
history->addChatListEntryByLetter(ch, row);
|
||||
}
|
||||
j.value()->addByName(history);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IndexedList::adjustNames(Mode list, PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
|
||||
auto mainRow = _list.getRow(peer->id);
|
||||
if (!mainRow) return;
|
||||
|
||||
History *history = mainRow->history();
|
||||
|
||||
PeerData::NameFirstChars toRemove = oldChars, toAdd;
|
||||
for_const (auto ch, peer->chars) {
|
||||
auto j = toRemove.find(ch);
|
||||
if (j == toRemove.cend()) {
|
||||
toAdd.insert(ch);
|
||||
} else {
|
||||
toRemove.erase(j);
|
||||
}
|
||||
}
|
||||
for_const (auto ch, toRemove) {
|
||||
if (_sortMode == SortMode::Date) {
|
||||
history->removeChatListEntryByLetter(list, ch);
|
||||
}
|
||||
if (auto list = _index.value(ch)) {
|
||||
list->del(peer->id, mainRow);
|
||||
}
|
||||
}
|
||||
for_const (auto ch, toAdd) {
|
||||
auto j = _index.find(ch);
|
||||
if (j == _index.cend()) {
|
||||
j = _index.insert(ch, new List(_sortMode));
|
||||
}
|
||||
Row *row = j.value()->addToEnd(history);
|
||||
if (_sortMode == SortMode::Date) {
|
||||
history->addChatListEntryByLetter(list, ch, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,13 @@ public:
|
|||
RowsByLetter addToEnd(History *history);
|
||||
Row *addByName(History *history);
|
||||
void adjustByPos(const RowsByLetter &links);
|
||||
|
||||
// For sortMode != SortMode::Date
|
||||
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 clear();
|
||||
|
||||
|
@ -71,6 +77,9 @@ public:
|
|||
iterator find(int y, int h) { return all().find(y, h); }
|
||||
|
||||
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;
|
||||
List _list;
|
||||
using Index = QMap<QChar, List*>;
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground) {
|
||||
auto history = row->history();
|
||||
auto item = history->lastMsg;
|
||||
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 *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;
|
||||
if (unread) {
|
||||
QString unreadStr = QString::number(unread);
|
||||
int unreadWidth = st::dlgUnreadFont->width(unreadStr);
|
||||
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);
|
||||
int unreadTop = texttop + st::dlgHistFont->ascent - st::dlgUnreadFont->ascent - st::dlgUnreadTop;
|
||||
paintUnreadCount(p, QString::number(unread), unreadTop, w, active, history->mute(), &availableWidth);
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
|
||||
using StyleSheets = OrderedSet<StyleSheet**>;
|
||||
|
|
|
@ -33,6 +33,8 @@ public:
|
|||
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.
|
||||
class StyleSheet {
|
||||
public:
|
||||
|
|
|
@ -40,6 +40,9 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p
|
|||
, contacts(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
|
||||
, _addContactLnk(this, lang(lng_add_contact_button))
|
||||
, _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(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*)));
|
||||
|
@ -50,16 +53,20 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p
|
|||
refresh();
|
||||
}
|
||||
|
||||
int32 DialogsInner::filteredOffset() const {
|
||||
int DialogsInner::dialogsOffset() const {
|
||||
return importantDialogs ? st::dlgImportantHeight : 0;
|
||||
}
|
||||
|
||||
int DialogsInner::filteredOffset() const {
|
||||
return _hashtagResults.size() * st::mentionHeight;
|
||||
}
|
||||
|
||||
int32 DialogsInner::peopleOffset() const {
|
||||
int DialogsInner::peopleOffset() const {
|
||||
return filteredOffset() + (_filterResults.size() * st::dlgHeight) + st::searchedBarHeight;
|
||||
}
|
||||
|
||||
int32 DialogsInner::searchedOffset() const {
|
||||
int32 result = peopleOffset() + (_peopleResults.isEmpty() ? 0 : ((_peopleResults.size() * st::dlgHeight) + st::searchedBarHeight));
|
||||
int DialogsInner::searchedOffset() const {
|
||||
int result = peopleOffset() + (_peopleResults.isEmpty() ? 0 : ((_peopleResults.size() * st::dlgHeight) + st::searchedBarHeight));
|
||||
if (_searchInPeer) result += st::dlgHeight;
|
||||
return result;
|
||||
}
|
||||
|
@ -76,16 +83,22 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO
|
|||
}
|
||||
|
||||
if (_state == DefaultState) {
|
||||
int32 otherStart = dialogs->size() * st::dlgHeight;
|
||||
PeerData *active = App::main()->activePeer(), *selected = _menuPeer ? _menuPeer : (sel ? sel->history()->peer : 0);
|
||||
QRect dialogsClip = r;
|
||||
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) {
|
||||
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) {
|
||||
p.fillRect(r, st::white->b);
|
||||
p.fillRect(dialogsClip, st::white);
|
||||
if (!paintingOther) {
|
||||
p.setFont(st::noContactsFont->f);
|
||||
p.setPen(st::noContactsColor->p);
|
||||
p.setFont(st::noContactsFont);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -223,13 +236,11 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, 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);
|
||||
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;
|
||||
|
||||
History *history = App::history(peer->id);
|
||||
|
||||
PeerData *userpicPeer = (peer->migrateTo() ? peer->migrateTo() : peer);
|
||||
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
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
if (peer->isVerified()) {
|
||||
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);
|
||||
p.setFont(st::dlgHistFont->f);
|
||||
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());
|
||||
int32 w = st::dlgHistFont->width(first);
|
||||
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));
|
||||
}
|
||||
} 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.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());
|
||||
}
|
||||
|
||||
|
@ -308,24 +319,26 @@ void DialogsInner::activate() {
|
|||
|
||||
void DialogsInner::mouseMoveEvent(QMouseEvent *e) {
|
||||
lastMousePos = mapToGlobal(e->pos());
|
||||
selByMouse = true;
|
||||
_selByMouse = true;
|
||||
onUpdateSelected(true);
|
||||
}
|
||||
|
||||
void DialogsInner::onUpdateSelected(bool force) {
|
||||
QPoint mouse(mapFromGlobal(lastMousePos));
|
||||
if ((!force && !rect().contains(mouse)) || !selByMouse) return;
|
||||
if ((!force && !rect().contains(mouse)) || !_selByMouse) return;
|
||||
|
||||
int w = width(), mouseY = mouse.y();
|
||||
_overDelete = false;
|
||||
if (_state == DefaultState) {
|
||||
auto newSel = dialogs->rowAtY(mouseY, st::dlgHeight);
|
||||
int otherStart = dialogs->size() * st::dlgHeight;
|
||||
if (newSel != sel) {
|
||||
auto newImportantSwitchSel = (importantDialogs && mouseY >= 0 && mouseY < dialogsOffset());
|
||||
mouseY -= dialogsOffset();
|
||||
auto newSel = newImportantSwitchSel ? nullptr : shownDialogs()->rowAtY(mouseY, st::dlgHeight);
|
||||
if (newSel != _sel || newImportantSwitchSel != _importantSwitchSel) {
|
||||
updateSelectedRow();
|
||||
sel = newSel;
|
||||
_sel = newSel;
|
||||
_importantSwitchSel = newImportantSwitchSel;
|
||||
updateSelectedRow();
|
||||
setCursor(sel ? style::cur_pointer : style::cur_default);
|
||||
setCursor(_sel ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
} else if (_state == FilteredState || _state == SearchedState) {
|
||||
if (!_hashtagResults.isEmpty()) {
|
||||
|
@ -384,7 +397,7 @@ void DialogsInner::onUpdateSelected(bool force) {
|
|||
|
||||
void DialogsInner::mousePressEvent(QMouseEvent *e) {
|
||||
lastMousePos = mapToGlobal(e->pos());
|
||||
selByMouse = true;
|
||||
_selByMouse = true;
|
||||
onUpdateSelected(true);
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
choosePeer();
|
||||
|
@ -411,25 +424,46 @@ void DialogsInner::onDialogRowReplaced(Dialogs::Row *oldRow, Dialogs::Row *newRo
|
|||
}
|
||||
}
|
||||
}
|
||||
if (sel == oldRow) {
|
||||
sel = newRow;
|
||||
if (_sel == oldRow) {
|
||||
_sel = newRow;
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsInner::createDialog(History *history) {
|
||||
bool creating = !history->inChatList();
|
||||
bool creating = !history->inChatList(Dialogs::Mode::All);
|
||||
if (creating) {
|
||||
Dialogs::Row *mainRow = history->addToChatList(dialogs.get());
|
||||
Dialogs::Row *mainRow = history->addToChatList(Dialogs::Mode::All, dialogs.get());
|
||||
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);
|
||||
|
||||
if (creating) {
|
||||
refresh();
|
||||
} 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) {
|
||||
_menu->deleteLater();
|
||||
}
|
||||
if (sel && sel->history() == history) {
|
||||
sel = nullptr;
|
||||
if (_sel && _sel->history() == history) {
|
||||
_sel = nullptr;
|
||||
}
|
||||
history->removeFromChatList(Dialogs::Mode::All, dialogs.get());
|
||||
if (importantDialogs) {
|
||||
history->removeFromChatList(Dialogs::Mode::Important, importantDialogs.get());
|
||||
}
|
||||
history->removeFromChatList(dialogs.get());
|
||||
history->clearNotifications();
|
||||
if (App::wnd()) App::wnd()->notifyClear(history);
|
||||
if (contacts->contains(history->peer->id)) {
|
||||
|
@ -457,14 +494,18 @@ void DialogsInner::removeDialog(History *history) {
|
|||
refresh();
|
||||
}
|
||||
|
||||
void DialogsInner::dlgUpdated(Dialogs::Row *row) {
|
||||
void DialogsInner::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) {
|
||||
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) {
|
||||
for (int32 i = 0, l = _filterResults.size(); i < l; ++i) {
|
||||
if (_filterResults.at(i)->history() == row->history()) {
|
||||
update(0, i * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
break;
|
||||
if (list == Dialogs::Mode::All) {
|
||||
for (int32 i = 0, l = _filterResults.size(); i < l; ++i) {
|
||||
if (_filterResults.at(i)->history() == row->history()) {
|
||||
update(0, i * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -472,8 +513,8 @@ void DialogsInner::dlgUpdated(Dialogs::Row *row) {
|
|||
|
||||
void DialogsInner::dlgUpdated(History *history, MsgId msgId) {
|
||||
if (_state == DefaultState) {
|
||||
if (auto row = dialogs->getRow(history->peer->id)) {
|
||||
update(0, row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
if (auto row = shownDialogs()->getRow(history->peer->id)) {
|
||||
update(0, dialogsOffset() + row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
}
|
||||
} else if (_state == FilteredState || _state == SearchedState) {
|
||||
int32 cnt = 0, add = filteredOffset();
|
||||
|
@ -517,12 +558,14 @@ void DialogsInner::updateSelectedRow(PeerData *peer) {
|
|||
if (_state == DefaultState) {
|
||||
if (peer) {
|
||||
if (History *h = App::historyLoaded(peer->id)) {
|
||||
if (h->inChatList()) {
|
||||
update(0, h->posInChatList() * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
if (h->inChatList(Global::DialogsMode())) {
|
||||
update(0, dialogsOffset() + h->posInChatList(Global::DialogsMode()) * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
}
|
||||
}
|
||||
} else if (sel) {
|
||||
update(0, sel->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
} else if (_sel) {
|
||||
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) {
|
||||
if (peer) {
|
||||
|
@ -547,10 +590,15 @@ void DialogsInner::updateSelectedRow(PeerData *peer) {
|
|||
|
||||
void DialogsInner::leaveEvent(QEvent *e) {
|
||||
setMouseTracking(false);
|
||||
selByMouse = false;
|
||||
if (sel || _filteredSel >= 0 || _hashtagSel >= 0 || _searchedSel >= 0 || _peopleSel >= 0) {
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
void DialogsInner::clearSelection() {
|
||||
_selByMouse = false;
|
||||
if (_sel || _filteredSel >= 0 || _hashtagSel >= 0 || _searchedSel >= 0 || _peopleSel >= 0) {
|
||||
updateSelectedRow();
|
||||
sel = 0;
|
||||
_sel = nullptr;
|
||||
_importantSwitchSel = false;
|
||||
_filteredSel = _searchedSel = _peopleSel = _hashtagSel = -1;
|
||||
setCursor(style::cur_default);
|
||||
}
|
||||
|
@ -569,13 +617,13 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
|
|||
|
||||
if (e->reason() == QContextMenuEvent::Mouse) {
|
||||
lastMousePos = e->globalPos();
|
||||
selByMouse = true;
|
||||
_selByMouse = true;
|
||||
onUpdateSelected(true);
|
||||
}
|
||||
|
||||
History *history = 0;
|
||||
if (_state == DefaultState) {
|
||||
if (sel) history = sel->history();
|
||||
if (_sel) history = _sel->history();
|
||||
} else if (_state == FilteredState || _state == SearchedState) {
|
||||
if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) {
|
||||
history = _filterResults[_filteredSel]->history();
|
||||
|
@ -691,7 +739,7 @@ void DialogsInner::onMenuDestroyed(QObject *obj) {
|
|||
}
|
||||
lastMousePos = QCursor::pos();
|
||||
if (rect().contains(mapFromGlobal(lastMousePos))) {
|
||||
selByMouse = true;
|
||||
_selByMouse = true;
|
||||
setMouseTracking(true);
|
||||
onUpdateSelected(true);
|
||||
}
|
||||
|
@ -707,7 +755,10 @@ void DialogsInner::onParentGeometryChanged() {
|
|||
}
|
||||
|
||||
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);
|
||||
contacts->peerNameChanged(peer, oldNames, oldChars);
|
||||
update();
|
||||
|
@ -889,10 +940,10 @@ void DialogsInner::peerUpdated(PeerData *peer) {
|
|||
|
||||
PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) {
|
||||
lastMousePos = globalPos;
|
||||
selByMouse = true;
|
||||
_selByMouse = true;
|
||||
onUpdateSelected(true);
|
||||
if (_state == DefaultState) {
|
||||
if (sel) return sel->history()->peer;
|
||||
if (_sel) return _sel->history()->peer;
|
||||
} else if (_state == FilteredState || _state == SearchedState) {
|
||||
if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) {
|
||||
return _filterResults[_filteredSel]->history()->peer;
|
||||
|
@ -976,8 +1027,9 @@ void DialogsInner::dialogsReceived(const QVector<MTPDialog> &added) {
|
|||
}
|
||||
|
||||
if (App::wnd()) App::wnd()->updateCounter();
|
||||
if (!sel && !dialogs->isEmpty()) {
|
||||
sel = *dialogs->cbegin();
|
||||
if (!_sel && !shownDialogs()->isEmpty()) {
|
||||
_sel = *shownDialogs()->cbegin();
|
||||
_importantSwitchSel = false;
|
||||
}
|
||||
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) {
|
||||
PeerId peerId = peerFromMTP(*i);
|
||||
if (History *h = App::historyLoaded(peerId)) {
|
||||
if (h->inChatList()) {
|
||||
if (h->inChatList(Dialogs::Mode::All)) {
|
||||
continue; // skip existing chats
|
||||
}
|
||||
}
|
||||
|
@ -1069,16 +1121,17 @@ void DialogsInner::notify_userIsContactChanged(UserData *user, bool fromThisApp)
|
|||
if (user->contact > 0) {
|
||||
History *history = App::history(user->id);
|
||||
contacts->addByName(history);
|
||||
if (auto row = dialogs->getRow(user->id)) {
|
||||
if (auto row = shownDialogs()->getRow(user->id)) {
|
||||
if (fromThisApp) {
|
||||
sel = row;
|
||||
_sel = row;
|
||||
_importantSwitchSel = false;
|
||||
}
|
||||
} else {
|
||||
} else if (!dialogs->contains(user->id)) {
|
||||
contactsNoDialogs->addByName(history);
|
||||
}
|
||||
} else {
|
||||
if (sel && sel->history()->peer == user) {
|
||||
sel = nullptr;
|
||||
if (_sel && _sel->history()->peer == user) {
|
||||
_sel = nullptr;
|
||||
}
|
||||
contactsNoDialogs->del(user);
|
||||
contacts->del(user);
|
||||
|
@ -1086,19 +1139,54 @@ void DialogsInner::notify_userIsContactChanged(UserData *user, bool fromThisApp)
|
|||
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) {
|
||||
int32 h = 0;
|
||||
if (_state == DefaultState) {
|
||||
h = (dialogs->size()/* + contactsNoDialogs->size()*/) * st::dlgHeight;
|
||||
if (h) {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
} else {
|
||||
if (shownDialogs()->isEmpty()) {
|
||||
h = st::noContactsHeight;
|
||||
if (cContactsReceived()) {
|
||||
if (_addContactLnk.isHidden()) _addContactLnk.show();
|
||||
} else {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
}
|
||||
} else {
|
||||
h = dialogsOffset() + shownDialogs()->size() * st::dlgHeight;
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
}
|
||||
} else {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
|
@ -1117,10 +1205,11 @@ void DialogsInner::refresh(bool toTop) {
|
|||
}
|
||||
|
||||
void DialogsInner::setMouseSel(bool msel, bool toTop) {
|
||||
selByMouse = msel;
|
||||
if (!selByMouse && toTop) {
|
||||
_selByMouse = msel;
|
||||
if (!_selByMouse && toTop) {
|
||||
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
|
||||
_filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1;
|
||||
setCursor(style::cur_default);
|
||||
|
@ -1182,25 +1271,39 @@ void DialogsInner::clearFilter() {
|
|||
|
||||
void DialogsInner::selectSkip(int32 direction) {
|
||||
if (_state == DefaultState) {
|
||||
if (!sel) {
|
||||
if (!dialogs->isEmpty() && direction > 0) {
|
||||
sel = *dialogs->cbegin();
|
||||
if (_importantSwitchSel) {
|
||||
if (!shownDialogs()->isEmpty() && direction > 0) {
|
||||
_sel = *shownDialogs()->cbegin();
|
||||
_importantSwitchSel = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (!_sel) {
|
||||
if (importantDialogs) {
|
||||
_importantSwitchSel = true;
|
||||
} else if (!shownDialogs()->isEmpty() && direction > 0) {
|
||||
_sel = *shownDialogs()->cbegin();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (direction > 0) {
|
||||
auto next = dialogs->cfind(sel);
|
||||
if (++next != dialogs->cend()) {
|
||||
sel = *next;
|
||||
auto next = shownDialogs()->cfind(_sel);
|
||||
if (++next != shownDialogs()->cend()) {
|
||||
_sel = *next;
|
||||
}
|
||||
} else {
|
||||
auto prev = dialogs->cfind(sel);
|
||||
if (prev != dialogs->cbegin()) {
|
||||
sel = *(--prev);
|
||||
auto prev = shownDialogs()->cfind(_sel);
|
||||
if (prev != shownDialogs()->cbegin()) {
|
||||
_sel = *(--prev);
|
||||
} else if (importantDialogs) {
|
||||
_importantSwitchSel = true;
|
||||
_sel = nullptr;
|
||||
}
|
||||
}
|
||||
int32 fromY = sel->pos() * st::dlgHeight;
|
||||
emit mustScrollTo(fromY, fromY + st::dlgHeight);
|
||||
if (_importantSwitchSel || _sel) {
|
||||
int fromY = _importantSwitchSel ? 0 : (dialogsOffset() + _sel->pos() * st::dlgHeight);
|
||||
emit mustScrollTo(fromY, fromY + st::dlgHeight);
|
||||
}
|
||||
} else if (_state == FilteredState || _state == SearchedState) {
|
||||
if (_hashtagResults.isEmpty() && _filterResults.isEmpty() && _peopleResults.isEmpty() && _searchResults.isEmpty()) return;
|
||||
if ((_hashtagSel < 0 || _hashtagSel >= _hashtagResults.size()) &&
|
||||
|
@ -1249,8 +1352,8 @@ void DialogsInner::selectSkip(int32 direction) {
|
|||
void DialogsInner::scrollToPeer(const PeerId &peer, MsgId msgId) {
|
||||
int32 fromY = -1;
|
||||
if (_state == DefaultState) {
|
||||
if (auto row = dialogs->getRow(peer)) {
|
||||
fromY = row->pos() * st::dlgHeight;
|
||||
if (auto row = shownDialogs()->getRow(peer)) {
|
||||
fromY = dialogsOffset() + row->pos() * st::dlgHeight;
|
||||
}
|
||||
} else if (_state == FilteredState || _state == SearchedState) {
|
||||
if (msgId) {
|
||||
|
@ -1278,24 +1381,31 @@ void DialogsInner::scrollToPeer(const PeerId &peer, MsgId msgId) {
|
|||
void DialogsInner::selectSkipPage(int32 pixels, int32 direction) {
|
||||
int toSkip = pixels / int(st::dlgHeight);
|
||||
if (_state == DefaultState) {
|
||||
if (!sel) {
|
||||
if (direction > 0 && !dialogs->isEmpty()) {
|
||||
sel = *dialogs->cbegin();
|
||||
if (!_sel) {
|
||||
if (direction > 0 && !shownDialogs()->isEmpty()) {
|
||||
_sel = *shownDialogs()->cbegin();
|
||||
_importantSwitchSel = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (direction > 0) {
|
||||
for (auto i = dialogs->cfind(sel), end = dialogs->cend(); i != end && (toSkip--); ++i) {
|
||||
sel = *i;
|
||||
for (auto i = shownDialogs()->cfind(_sel), end = shownDialogs()->cend(); i != end && (toSkip--); ++i) {
|
||||
_sel = *i;
|
||||
}
|
||||
} else {
|
||||
for (auto i = dialogs->cfind(sel), b = dialogs->cbegin(); i != b && (toSkip--); --i) {
|
||||
sel = *i;
|
||||
for (auto i = shownDialogs()->cfind(_sel), b = shownDialogs()->cbegin(); i != b && (toSkip--); --i) {
|
||||
_sel = *i;
|
||||
}
|
||||
if (toSkip && importantDialogs) {
|
||||
_importantSwitchSel = true;
|
||||
_sel = nullptr;
|
||||
}
|
||||
}
|
||||
int fromY = sel->pos() * st::dlgHeight;
|
||||
emit mustScrollTo(fromY, fromY + st::dlgHeight);
|
||||
if (_importantSwitchSel || _sel) {
|
||||
int fromY = (_importantSwitchSel ? 0 : (dialogsOffset() + _sel->pos() * st::dlgHeight));
|
||||
emit mustScrollTo(fromY, fromY + st::dlgHeight);
|
||||
}
|
||||
} else {
|
||||
return selectSkip(direction * toSkip);
|
||||
}
|
||||
|
@ -1308,9 +1418,9 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
|||
int32 yTo = yFrom + parentWidget()->height() * 5;
|
||||
MTP::clearLoaderPriorities();
|
||||
if (_state == DefaultState) {
|
||||
int32 otherStart = dialogs->size() * st::dlgHeight;
|
||||
int32 otherStart = shownDialogs()->size() * st::dlgHeight;
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
|
@ -1357,10 +1467,23 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
|||
}
|
||||
|
||||
bool DialogsInner::choosePeer() {
|
||||
History *history = 0;
|
||||
History *history = nullptr;
|
||||
MsgId msgId = ShowAtUnreadMsgId;
|
||||
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) {
|
||||
if (_hashtagSel >= 0 && _hashtagSel < _hashtagResults.size()) {
|
||||
QString hashtag = _hashtagResults.at(_hashtagSel);
|
||||
|
@ -1379,7 +1502,7 @@ bool DialogsInner::choosePeer() {
|
|||
Local::writeRecentHashtagsAndBots();
|
||||
emit refreshHashtags();
|
||||
|
||||
selByMouse = true;
|
||||
_selByMouse = true;
|
||||
onUpdateSelected(true);
|
||||
} else {
|
||||
saveRecentHashtags('#' + hashtag);
|
||||
|
@ -1406,7 +1529,7 @@ bool DialogsInner::choosePeer() {
|
|||
emit searchResultChosen();
|
||||
}
|
||||
updateSelectedRow();
|
||||
sel = 0;
|
||||
_sel = nullptr;
|
||||
_filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1;
|
||||
return true;
|
||||
}
|
||||
|
@ -1442,7 +1565,7 @@ void DialogsInner::saveRecentHashtags(const QString &text) {
|
|||
}
|
||||
|
||||
void DialogsInner::destroyData() {
|
||||
sel = nullptr;
|
||||
_sel = nullptr;
|
||||
_hashtagSel = -1;
|
||||
_hashtagResults.clear();
|
||||
_filteredSel = -1;
|
||||
|
@ -1453,6 +1576,9 @@ void DialogsInner::destroyData() {
|
|||
contacts = nullptr;
|
||||
contactsNoDialogs = nullptr;
|
||||
dialogs = nullptr;
|
||||
if (importantDialogs) {
|
||||
importantDialogs = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (_state == DefaultState) {
|
||||
if (auto row = dialogs->getRow(inPeer->id)) {
|
||||
auto i = dialogs->cfind(row);
|
||||
if (i != dialogs->cbegin()) {
|
||||
if (auto row = shownDialogs()->getRow(inPeer->id)) {
|
||||
auto i = shownDialogs()->cfind(row);
|
||||
if (i != shownDialogs()->cbegin()) {
|
||||
outPeer = (*(--i))->history()->peer;
|
||||
outMsg = ShowAtUnreadMsgId;
|
||||
return;
|
||||
|
@ -1536,9 +1662,9 @@ void DialogsInner::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&out
|
|||
return;
|
||||
}
|
||||
if (_state == DefaultState) {
|
||||
if (auto row = dialogs->getRow(inPeer->id)) {
|
||||
auto i = dialogs->cfind(row) + 1;
|
||||
if (i != dialogs->cend()) {
|
||||
if (auto row = shownDialogs()->getRow(inPeer->id)) {
|
||||
auto i = shownDialogs()->cfind(row) + 1;
|
||||
if (i != shownDialogs()->cend()) {
|
||||
outPeer = (*i)->history()->peer;
|
||||
outMsg = ShowAtUnreadMsgId;
|
||||
return;
|
||||
|
@ -1697,19 +1823,19 @@ void DialogsWidget::activate() {
|
|||
}
|
||||
|
||||
void DialogsWidget::createDialog(History *history) {
|
||||
bool creating = !history->inChatList();
|
||||
bool creating = !history->inChatList(Dialogs::Mode::All);
|
||||
_inner.createDialog(history);
|
||||
if (creating && history->peer->migrateFrom()) {
|
||||
if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) {
|
||||
if (h->inChatList()) {
|
||||
if (h->inChatList(Dialogs::Mode::All)) {
|
||||
removeDialog(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsWidget::dlgUpdated(Dialogs::Row *row) {
|
||||
_inner.dlgUpdated(row);
|
||||
void DialogsWidget::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) {
|
||||
_inner.dlgUpdated(list, row);
|
||||
}
|
||||
|
||||
void DialogsWidget::dlgUpdated(History *row, MsgId msgId) {
|
||||
|
@ -1795,6 +1921,10 @@ void DialogsWidget::notify_userIsContactChanged(UserData *user, bool fromThisApp
|
|||
_inner.notify_userIsContactChanged(user, fromThisApp);
|
||||
}
|
||||
|
||||
void DialogsWidget::notify_historyMuteUpdated(History *history) {
|
||||
_inner.notify_historyMuteUpdated(history);
|
||||
}
|
||||
|
||||
void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
|
||||
for (QVector<MTPDialog>::const_iterator i = dialogs.cbegin(), e = dialogs.cend(); i != e; ++i) {
|
||||
switch (i->type()) {
|
||||
|
@ -1802,7 +1932,7 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
|
|||
const auto &d(i->c_dialog());
|
||||
if (History *h = App::historyLoaded(peerFromMTP(d.vpeer))) {
|
||||
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->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);
|
||||
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->inboxReadBefore = d.vread_inbox_max_id.v + 1;
|
||||
}
|
||||
|
|
|
@ -54,10 +54,6 @@ public:
|
|||
|
||||
void contactsReceived(const QVector<MTPContact> &contacts);
|
||||
|
||||
int32 filteredOffset() const;
|
||||
int32 peopleOffset() const;
|
||||
int32 searchedOffset() const;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
@ -65,14 +61,11 @@ public:
|
|||
void leaveEvent(QEvent *e);
|
||||
void contextMenuEvent(QContextMenuEvent *e);
|
||||
|
||||
void peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool act, bool sel, bool onlyBackground) const;
|
||||
void searchInPeerPaint(Painter &p, int32 w, bool onlyBackground) const;
|
||||
|
||||
void selectSkip(int32 direction);
|
||||
void selectSkipPage(int32 pixels, int32 direction);
|
||||
|
||||
void createDialog(History *history);
|
||||
void dlgUpdated(Dialogs::Row *row);
|
||||
void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
|
||||
void dlgUpdated(History *row, MsgId msgId);
|
||||
void removeDialog(History *history);
|
||||
|
||||
|
@ -125,6 +118,7 @@ public:
|
|||
void updateNotifySettings(PeerData *peer);
|
||||
|
||||
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
|
||||
void notify_historyMuteUpdated(History *history);
|
||||
|
||||
~DialogsInner();
|
||||
|
||||
|
@ -165,17 +159,34 @@ protected:
|
|||
|
||||
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 updateSelectedRow(PeerData *peer = 0);
|
||||
bool menuPeerMuted();
|
||||
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>;
|
||||
DialogsList dialogs;
|
||||
DialogsList importantDialogs;
|
||||
|
||||
DialogsList contactsNoDialogs;
|
||||
DialogsList contacts;
|
||||
Dialogs::Row *sel = nullptr;
|
||||
bool selByMouse = false;
|
||||
|
||||
bool _importantSwitchSel = false;
|
||||
Dialogs::Row *_sel = nullptr;
|
||||
bool _selByMouse = false;
|
||||
|
||||
QString _filter, _hashtagFilter;
|
||||
|
||||
|
@ -244,7 +255,7 @@ public:
|
|||
|
||||
void loadDialogs();
|
||||
void createDialog(History *history);
|
||||
void dlgUpdated(Dialogs::Row *row);
|
||||
void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
|
||||
void dlgUpdated(History *row, MsgId msgId);
|
||||
|
||||
void dialogsToUp();
|
||||
|
@ -276,6 +287,7 @@ public:
|
|||
}
|
||||
|
||||
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
|
||||
void notify_historyMuteUpdated(History *history);
|
||||
|
||||
signals:
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,23 +24,23 @@ class LayeredWidget;
|
|||
|
||||
namespace App {
|
||||
|
||||
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo = 0);
|
||||
bool insertBotCommand(const QString &cmd, bool specialGif = false);
|
||||
void activateBotCommand(const HistoryItem *msg, int row, int col);
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer);
|
||||
void openPeerByName(const QString &username, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
|
||||
void joinGroupByHash(const QString &hash);
|
||||
void stickersBox(const QString &name);
|
||||
void openLocalUrl(const QString &url);
|
||||
bool forward(const PeerId &peer, ForwardWhatMessages what);
|
||||
void removeDialog(History *history);
|
||||
void showSettings();
|
||||
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo = 0);
|
||||
bool insertBotCommand(const QString &cmd, bool specialGif = false);
|
||||
void activateBotCommand(const HistoryItem *msg, int row, int col);
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer);
|
||||
void openPeerByName(const QString &username, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
|
||||
void joinGroupByHash(const QString &hash);
|
||||
void stickersBox(const QString &name);
|
||||
void openLocalUrl(const QString &url);
|
||||
bool forward(const PeerId &peer, ForwardWhatMessages what);
|
||||
void removeDialog(History *history);
|
||||
void showSettings();
|
||||
|
||||
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
|
||||
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
|
||||
|
||||
void logOutDelayed();
|
||||
void logOutDelayed();
|
||||
|
||||
};
|
||||
} // namespace App
|
||||
|
||||
namespace InlineBots {
|
||||
namespace Layout {
|
||||
|
@ -52,43 +52,43 @@ class ItemBase;
|
|||
|
||||
namespace Ui {
|
||||
|
||||
void showMediaPreview(DocumentData *document);
|
||||
void showMediaPreview(PhotoData *photo);
|
||||
void hideMediaPreview();
|
||||
void showMediaPreview(DocumentData *document);
|
||||
void showMediaPreview(PhotoData *photo);
|
||||
void hideMediaPreview();
|
||||
|
||||
void showLayer(LayeredWidget *box, ShowLayerOptions options = CloseOtherLayers);
|
||||
void hideLayer(bool fast = false);
|
||||
bool isLayerShown();
|
||||
bool isMediaViewShown();
|
||||
bool isInlineItemBeingChosen();
|
||||
void showLayer(LayeredWidget *box, ShowLayerOptions options = CloseOtherLayers);
|
||||
void hideLayer(bool fast = false);
|
||||
bool isLayerShown();
|
||||
bool isMediaViewShown();
|
||||
bool isInlineItemBeingChosen();
|
||||
|
||||
void repaintHistoryItem(const HistoryItem *item);
|
||||
void repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
|
||||
bool isInlineItemVisible(const InlineBots::Layout::ItemBase *reader);
|
||||
void autoplayMediaInlineAsync(const FullMsgId &msgId);
|
||||
void repaintHistoryItem(const HistoryItem *item);
|
||||
void repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
|
||||
bool isInlineItemVisible(const InlineBots::Layout::ItemBase *reader);
|
||||
void autoplayMediaInlineAsync(const FullMsgId &msgId);
|
||||
|
||||
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false);
|
||||
inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) {
|
||||
showPeerHistory(peer->id, msgId, back);
|
||||
}
|
||||
inline void showPeerHistory(const History *history, MsgId msgId, bool back = false) {
|
||||
showPeerHistory(history->peer->id, msgId, back);
|
||||
}
|
||||
inline void showPeerHistoryAtItem(const HistoryItem *item) {
|
||||
showPeerHistory(item->history()->peer->id, item->id);
|
||||
}
|
||||
void showPeerHistoryAsync(const PeerId &peer, MsgId msgId);
|
||||
inline void showChatsList() {
|
||||
showPeerHistory(PeerId(0), 0);
|
||||
}
|
||||
inline void showChatsListAsync() {
|
||||
showPeerHistoryAsync(PeerId(0), 0);
|
||||
}
|
||||
PeerData *getPeerForMouseAction();
|
||||
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false);
|
||||
inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) {
|
||||
showPeerHistory(peer->id, msgId, back);
|
||||
}
|
||||
inline void showPeerHistory(const History *history, MsgId msgId, bool back = false) {
|
||||
showPeerHistory(history->peer->id, msgId, back);
|
||||
}
|
||||
inline void showPeerHistoryAtItem(const HistoryItem *item) {
|
||||
showPeerHistory(item->history()->peer->id, item->id);
|
||||
}
|
||||
void showPeerHistoryAsync(const PeerId &peer, MsgId msgId);
|
||||
inline void showChatsList() {
|
||||
showPeerHistory(PeerId(0), 0);
|
||||
}
|
||||
inline void showChatsListAsync() {
|
||||
showPeerHistoryAsync(PeerId(0), 0);
|
||||
}
|
||||
PeerData *getPeerForMouseAction();
|
||||
|
||||
bool hideWindowNoQuit();
|
||||
bool hideWindowNoQuit();
|
||||
|
||||
};
|
||||
} // namespace Ui
|
||||
|
||||
enum ClipStopperType {
|
||||
ClipStopperMediaview,
|
||||
|
@ -97,26 +97,27 @@ enum ClipStopperType {
|
|||
|
||||
namespace Notify {
|
||||
|
||||
void userIsBotChanged(UserData *user);
|
||||
void userIsContactChanged(UserData *user, bool fromThisApp = false);
|
||||
void botCommandsChanged(UserData *user);
|
||||
void userIsBotChanged(UserData *user);
|
||||
void userIsContactChanged(UserData *user, bool fromThisApp = false);
|
||||
void botCommandsChanged(UserData *user);
|
||||
|
||||
void inlineBotRequesting(bool requesting);
|
||||
void replyMarkupUpdated(const HistoryItem *item);
|
||||
void inlineKeyboardMoved(const HistoryItem *item, int oldKeyboardTop, int newKeyboardTop);
|
||||
bool switchInlineBotButtonReceived(const QString &query);
|
||||
void inlineBotRequesting(bool requesting);
|
||||
void replyMarkupUpdated(const HistoryItem *item);
|
||||
void inlineKeyboardMoved(const HistoryItem *item, int oldKeyboardTop, int newKeyboardTop);
|
||||
bool switchInlineBotButtonReceived(const QString &query);
|
||||
|
||||
void migrateUpdated(PeerData *peer);
|
||||
void migrateUpdated(PeerData *peer);
|
||||
|
||||
void clipStopperHidden(ClipStopperType type);
|
||||
void clipStopperHidden(ClipStopperType type);
|
||||
|
||||
void historyItemLayoutChanged(const HistoryItem *item);
|
||||
void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
|
||||
void historyItemLayoutChanged(const HistoryItem *item);
|
||||
void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
|
||||
void historyMuteUpdated(History *history);
|
||||
|
||||
// handle pending resize() / paint() on history items
|
||||
void handlePendingHistoryUpdate();
|
||||
// handle pending resize() / paint() on history items
|
||||
void handlePendingHistoryUpdate();
|
||||
|
||||
};
|
||||
} // namespace Notify
|
||||
|
||||
#define DeclareReadOnlyVar(Type, Name) const Type &Name();
|
||||
#define DeclareRefVar(Type, Name) DeclareReadOnlyVar(Type, Name) \
|
||||
|
@ -126,115 +127,123 @@ namespace Notify {
|
|||
|
||||
namespace Sandbox {
|
||||
|
||||
bool CheckBetaVersionDir();
|
||||
void WorkingDirReady();
|
||||
bool CheckBetaVersionDir();
|
||||
void WorkingDirReady();
|
||||
|
||||
void start();
|
||||
void finish();
|
||||
void start();
|
||||
void finish();
|
||||
|
||||
uint64 UserTag();
|
||||
uint64 UserTag();
|
||||
|
||||
DeclareReadOnlyVar(QString, LangSystemISO);
|
||||
DeclareReadOnlyVar(int32, LangSystem);
|
||||
DeclareVar(QByteArray, LastCrashDump);
|
||||
DeclareVar(ConnectionProxy, PreLaunchProxy);
|
||||
DeclareReadOnlyVar(QString, LangSystemISO);
|
||||
DeclareReadOnlyVar(int32, LangSystem);
|
||||
DeclareVar(QByteArray, LastCrashDump);
|
||||
DeclareVar(ConnectionProxy, PreLaunchProxy);
|
||||
|
||||
}
|
||||
} // namespace Sandbox
|
||||
|
||||
namespace Adaptive {
|
||||
enum Layout {
|
||||
OneColumnLayout,
|
||||
NormalLayout,
|
||||
WideLayout,
|
||||
};
|
||||
enum Layout {
|
||||
OneColumnLayout,
|
||||
NormalLayout,
|
||||
WideLayout,
|
||||
};
|
||||
} // namespace Adaptive
|
||||
|
||||
namespace DebugLogging {
|
||||
enum Flags {
|
||||
FileLoaderFlag = 0x00000001,
|
||||
};
|
||||
}
|
||||
enum Flags {
|
||||
FileLoaderFlag = 0x00000001,
|
||||
};
|
||||
} // namespace DebugLogging
|
||||
|
||||
namespace Stickers {
|
||||
static const uint64 DefaultSetId = 0; // for backward compatibility
|
||||
static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL;
|
||||
static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel
|
||||
struct Set {
|
||||
Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags) : id(id), access(access), title(title), shortName(shortName), count(count), hash(hash), flags(flags) {
|
||||
}
|
||||
uint64 id, access;
|
||||
QString title, shortName;
|
||||
int32 count, hash;
|
||||
MTPDstickerSet::Flags flags;
|
||||
StickerPack stickers;
|
||||
StickersByEmojiMap emoji;
|
||||
};
|
||||
typedef QMap<uint64, Set> Sets;
|
||||
typedef QList<uint64> Order;
|
||||
}
|
||||
|
||||
static const uint64 DefaultSetId = 0; // for backward compatibility
|
||||
static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL;
|
||||
static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel
|
||||
struct Set {
|
||||
Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags) : id(id), access(access), title(title), shortName(shortName), count(count), hash(hash), flags(flags) {
|
||||
}
|
||||
uint64 id, access;
|
||||
QString title, shortName;
|
||||
int32 count, hash;
|
||||
MTPDstickerSet::Flags flags;
|
||||
StickerPack stickers;
|
||||
StickersByEmojiMap emoji;
|
||||
};
|
||||
using Sets = QMap<uint64, Set>;
|
||||
using Order = QList<uint64>;
|
||||
|
||||
} // namespace Stickers
|
||||
|
||||
namespace Global {
|
||||
|
||||
bool started();
|
||||
void start();
|
||||
void finish();
|
||||
bool started();
|
||||
void start();
|
||||
void finish();
|
||||
|
||||
DeclareReadOnlyVar(uint64, LaunchId);
|
||||
DeclareRefVar(SingleDelayedCall, HandleHistoryUpdate);
|
||||
DeclareReadOnlyVar(uint64, LaunchId);
|
||||
DeclareRefVar(SingleDelayedCall, HandleHistoryUpdate);
|
||||
|
||||
DeclareVar(Adaptive::Layout, AdaptiveLayout);
|
||||
DeclareVar(bool, AdaptiveForWide);
|
||||
DeclareVar(Adaptive::Layout, AdaptiveLayout);
|
||||
DeclareVar(bool, AdaptiveForWide);
|
||||
DeclareVar(bool, DialogsModeEnabled);
|
||||
DeclareVar(Dialogs::Mode, DialogsMode);
|
||||
|
||||
DeclareVar(int32, DebugLoggingFlags);
|
||||
DeclareVar(int32, DebugLoggingFlags);
|
||||
|
||||
// config
|
||||
DeclareVar(int32, ChatSizeMax);
|
||||
DeclareVar(int32, MegagroupSizeMax);
|
||||
DeclareVar(int32, ForwardedCountMax);
|
||||
DeclareVar(int32, OnlineUpdatePeriod);
|
||||
DeclareVar(int32, OfflineBlurTimeout);
|
||||
DeclareVar(int32, OfflineIdleTimeout);
|
||||
DeclareVar(int32, OnlineFocusTimeout); // not from config
|
||||
DeclareVar(int32, OnlineCloudTimeout);
|
||||
DeclareVar(int32, NotifyCloudDelay);
|
||||
DeclareVar(int32, NotifyDefaultDelay);
|
||||
DeclareVar(int32, ChatBigSize);
|
||||
DeclareVar(int32, PushChatPeriod);
|
||||
DeclareVar(int32, PushChatLimit);
|
||||
DeclareVar(int32, SavedGifsLimit);
|
||||
DeclareVar(int32, EditTimeLimit);
|
||||
// config
|
||||
DeclareVar(int32, ChatSizeMax);
|
||||
DeclareVar(int32, MegagroupSizeMax);
|
||||
DeclareVar(int32, ForwardedCountMax);
|
||||
DeclareVar(int32, OnlineUpdatePeriod);
|
||||
DeclareVar(int32, OfflineBlurTimeout);
|
||||
DeclareVar(int32, OfflineIdleTimeout);
|
||||
DeclareVar(int32, OnlineFocusTimeout); // not from config
|
||||
DeclareVar(int32, OnlineCloudTimeout);
|
||||
DeclareVar(int32, NotifyCloudDelay);
|
||||
DeclareVar(int32, NotifyDefaultDelay);
|
||||
DeclareVar(int32, ChatBigSize);
|
||||
DeclareVar(int32, PushChatPeriod);
|
||||
DeclareVar(int32, PushChatLimit);
|
||||
DeclareVar(int32, SavedGifsLimit);
|
||||
DeclareVar(int32, EditTimeLimit);
|
||||
|
||||
typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap;
|
||||
DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages);
|
||||
typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap;
|
||||
DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages);
|
||||
|
||||
typedef OrderedSet<HistoryItem*> PendingItemsMap;
|
||||
DeclareRefVar(PendingItemsMap, PendingRepaintItems);
|
||||
typedef OrderedSet<HistoryItem*> PendingItemsMap;
|
||||
DeclareRefVar(PendingItemsMap, PendingRepaintItems);
|
||||
|
||||
DeclareVar(Stickers::Sets, StickerSets);
|
||||
DeclareVar(Stickers::Order, StickerSetsOrder);
|
||||
DeclareVar(uint64, LastStickersUpdate);
|
||||
DeclareVar(Stickers::Sets, StickerSets);
|
||||
DeclareVar(Stickers::Order, StickerSetsOrder);
|
||||
DeclareVar(uint64, LastStickersUpdate);
|
||||
|
||||
DeclareVar(MTP::DcOptions, DcOptions);
|
||||
DeclareVar(MTP::DcOptions, DcOptions);
|
||||
|
||||
typedef QMap<uint64, QPixmap> CircleMasksMap;
|
||||
DeclareRefVar(CircleMasksMap, CircleMasks);
|
||||
typedef QMap<uint64, QPixmap> CircleMasksMap;
|
||||
DeclareRefVar(CircleMasksMap, CircleMasks);
|
||||
|
||||
};
|
||||
} // namespace Global
|
||||
|
||||
namespace Adaptive {
|
||||
inline bool OneColumn() {
|
||||
return Global::AdaptiveLayout() == OneColumnLayout;
|
||||
}
|
||||
inline bool Normal() {
|
||||
return Global::AdaptiveLayout() == NormalLayout;
|
||||
}
|
||||
inline bool Wide() {
|
||||
return Global::AdaptiveForWide() && (Global::AdaptiveLayout() == WideLayout);
|
||||
}
|
||||
|
||||
inline bool OneColumn() {
|
||||
return Global::AdaptiveLayout() == OneColumnLayout;
|
||||
}
|
||||
inline bool Normal() {
|
||||
return Global::AdaptiveLayout() == NormalLayout;
|
||||
}
|
||||
inline bool Wide() {
|
||||
return Global::AdaptiveForWide() && (Global::AdaptiveLayout() == WideLayout);
|
||||
}
|
||||
|
||||
} // namespace Adaptive
|
||||
|
||||
namespace DebugLogging {
|
||||
inline bool FileLoader() {
|
||||
return (Global::DebugLoggingFlags() | FileLoaderFlag) != 0;
|
||||
}
|
||||
|
||||
inline bool FileLoader() {
|
||||
return (Global::DebugLoggingFlags() | FileLoaderFlag) != 0;
|
||||
}
|
||||
|
||||
} // namespace DebugLogging
|
||||
|
|
|
@ -104,7 +104,7 @@ void historyInit() {
|
|||
|
||||
History::History(const PeerId &peerId)
|
||||
: peer(App::peer(peerId))
|
||||
, mute(isNotifyMuted(peer->notify)) {
|
||||
, _mute(isNotifyMuted(peer->notify)) {
|
||||
if (peer->isChannel() || (peer->isUser() && peer->asUser()->botInfo)) {
|
||||
outboxReadBefore = INT_MAX;
|
||||
}
|
||||
|
@ -1683,7 +1683,7 @@ void History::updateShowFrom() {
|
|||
|
||||
MsgId History::inboxRead(MsgId upTo) {
|
||||
if (upTo < 0) return upTo;
|
||||
if (unreadCount) {
|
||||
if (unreadCount()) {
|
||||
if (upTo && loadedAtBottom()) App::main()->historyToDown(this);
|
||||
setUnreadCount(upTo ? countUnread(upTo) : 0);
|
||||
}
|
||||
|
@ -1739,7 +1739,7 @@ HistoryItem *History::lastImportantMessage() const {
|
|||
}
|
||||
|
||||
void History::setUnreadCount(int newUnreadCount, bool psUpdate) {
|
||||
if (unreadCount != newUnreadCount) {
|
||||
if (_unreadCount != newUnreadCount) {
|
||||
if (newUnreadCount == 1) {
|
||||
if (loadedAtBottom()) showFrom = lastImportantMessage();
|
||||
inboxReadBefore = qMax(inboxReadBefore, msgIdForRead());
|
||||
|
@ -1747,18 +1747,18 @@ void History::setUnreadCount(int newUnreadCount, bool psUpdate) {
|
|||
showFrom = nullptr;
|
||||
inboxReadBefore = qMax(inboxReadBefore, msgIdForRead() + 1);
|
||||
}
|
||||
if (inChatList()) {
|
||||
App::histories().unreadIncrement(newUnreadCount - unreadCount, mute);
|
||||
if (psUpdate && (!mute || cIncludeMuted()) && App::wnd()) {
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
App::histories().unreadIncrement(newUnreadCount - _unreadCount, mute());
|
||||
if (psUpdate && (!mute() || cIncludeMuted()) && App::wnd()) {
|
||||
App::wnd()->updateCounter();
|
||||
}
|
||||
}
|
||||
unreadCount = newUnreadCount;
|
||||
_unreadCount = newUnreadCount;
|
||||
if (unreadBar) {
|
||||
int32 count = unreadCount;
|
||||
int32 count = _unreadCount;
|
||||
if (peer->migrateTo()) {
|
||||
if (History *h = App::historyLoaded(peer->migrateTo()->id)) {
|
||||
count += h->unreadCount;
|
||||
count += h->unreadCount();
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
|
@ -1771,11 +1771,14 @@ void History::setUnreadCount(int newUnreadCount, bool psUpdate) {
|
|||
}
|
||||
|
||||
void History::setMute(bool newMute) {
|
||||
if (mute != newMute) {
|
||||
mute = newMute;
|
||||
if (inChatList() && unreadCount) {
|
||||
App::histories().unreadMuteChanged(unreadCount, newMute);
|
||||
if (App::wnd()) App::wnd()->updateCounter();
|
||||
if (_mute != newMute) {
|
||||
_mute = newMute;
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
if (_unreadCount) {
|
||||
App::histories().unreadMuteChanged(_unreadCount, newMute);
|
||||
if (App::wnd()) App::wnd()->updateCounter();
|
||||
}
|
||||
Notify::historyMuteUpdated(this);
|
||||
}
|
||||
updateChatListEntry();
|
||||
}
|
||||
|
@ -1881,12 +1884,12 @@ void History::getNextScrollTopItem(HistoryBlock *block, int32 i) {
|
|||
}
|
||||
|
||||
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 (History *h = App::historyLoaded(peer->migrateTo()->id)) {
|
||||
count += h->unreadCount;
|
||||
count += h->unreadCount();
|
||||
}
|
||||
}
|
||||
showFrom->setUnreadBarCount(count);
|
||||
|
@ -2014,12 +2017,12 @@ bool History::isReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScrol
|
|||
if (msgId == ShowAtUnreadMsgId) {
|
||||
if (peer->migrateFrom()) { // old group history
|
||||
if (History *h = App::historyLoaded(peer->migrateFrom()->id)) {
|
||||
if (h->unreadCount) {
|
||||
if (h->unreadCount()) {
|
||||
return h->isReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unreadCount) {
|
||||
if (unreadCount()) {
|
||||
if (!isEmpty()) {
|
||||
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 (History *h = App::historyLoaded(peer->migrateFrom()->id)) {
|
||||
if (h->unreadCount) {
|
||||
if (h->unreadCount()) {
|
||||
clear(true);
|
||||
h->getReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop);
|
||||
return;
|
||||
|
@ -2084,12 +2087,12 @@ void History::setLastMessage(HistoryItem *msg) {
|
|||
}
|
||||
|
||||
void History::setChatsListDate(const QDateTime &date) {
|
||||
bool updateDialog = (App::main() && (!peer->isChannel() || peer->asChannel()->amIn() || !_chatListLinks.isEmpty()));
|
||||
if (peer->migrateTo() && _chatListLinks.isEmpty()) {
|
||||
bool updateDialog = (App::main() && (!peer->isChannel() || peer->asChannel()->amIn() || inChatList(Dialogs::Mode::All)));
|
||||
if (peer->migrateTo() && !inChatList(Dialogs::Mode::All)) {
|
||||
updateDialog = false;
|
||||
}
|
||||
if (!lastMsgDate.isNull() && lastMsgDate >= date) {
|
||||
if (!updateDialog || !_chatListLinks.isEmpty()) {
|
||||
if (!updateDialog || !inChatList(Dialogs::Mode::All)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2225,61 +2228,64 @@ void History::clearOnDestroy() {
|
|||
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);
|
||||
Dialogs::Row *lnk = mainChatListLink();
|
||||
Dialogs::Row *lnk = mainChatListLink(list);
|
||||
int32 movedFrom = lnk->pos() * st::dlgHeight;
|
||||
indexed->adjustByPos(_chatListLinks);
|
||||
indexed->adjustByPos(chatListLinks(list));
|
||||
int32 movedTo = lnk->pos() * st::dlgHeight;
|
||||
return qMakePair(movedFrom, movedTo);
|
||||
}
|
||||
|
||||
int History::posInChatList() const {
|
||||
return mainChatListLink()->pos();
|
||||
int History::posInChatList(Dialogs::Mode list) const {
|
||||
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);
|
||||
if (!inChatList()) {
|
||||
_chatListLinks = indexed->addToEnd(this);
|
||||
if (unreadCount) {
|
||||
App::histories().unreadIncrement(unreadCount, mute);
|
||||
if (!inChatList(list)) {
|
||||
chatListLinks(list) = indexed->addToEnd(this);
|
||||
if (list == Dialogs::Mode::All && unreadCount()) {
|
||||
App::histories().unreadIncrement(unreadCount(), mute());
|
||||
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);
|
||||
if (inChatList()) {
|
||||
if (inChatList(list)) {
|
||||
indexed->del(peer);
|
||||
_chatListLinks.clear();
|
||||
if (unreadCount) {
|
||||
App::histories().unreadIncrement(-unreadCount, mute);
|
||||
chatListLinks(list).clear();
|
||||
if (list == Dialogs::Mode::All && unreadCount()) {
|
||||
App::histories().unreadIncrement(-unreadCount(), mute());
|
||||
if (App::wnd()) App::wnd()->updateCounter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void History::removeChatListEntryByLetter(QChar letter) {
|
||||
void History::removeChatListEntryByLetter(Dialogs::Mode list, QChar letter) {
|
||||
t_assert(letter != 0);
|
||||
if (inChatList()) {
|
||||
_chatListLinks.remove(letter);
|
||||
if (inChatList(list)) {
|
||||
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);
|
||||
if (inChatList()) {
|
||||
_chatListLinks.insert(letter, row);
|
||||
if (inChatList(list)) {
|
||||
chatListLinks(list).insert(letter, row);
|
||||
}
|
||||
}
|
||||
|
||||
void History::updateChatListEntry() const {
|
||||
if (MainWidget *m = App::main()) {
|
||||
if (inChatList()) {
|
||||
m->dlgUpdated(mainChatListLink());
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
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();
|
||||
if (App::main()) App::main()->updateBotKeyboard(history());
|
||||
}
|
||||
if ((!out() || isPost()) && unread() && history()->unreadCount > 0) {
|
||||
history()->setUnreadCount(history()->unreadCount - 1);
|
||||
if ((!out() || isPost()) && unread() && history()->unreadCount() > 0) {
|
||||
history()->setUnreadCount(history()->unreadCount() - 1);
|
||||
}
|
||||
Global::RefPendingRepaintItems().remove(this);
|
||||
delete this;
|
||||
|
|
|
@ -65,6 +65,9 @@ public:
|
|||
int32 unreadBadge() const {
|
||||
return _unreadFull - (cIncludeMuted() ? 0 : _unreadMuted);
|
||||
}
|
||||
int32 unreadMutedCount() const {
|
||||
return _unreadMuted;
|
||||
}
|
||||
bool unreadOnlyMuted() const {
|
||||
return cIncludeMuted() ? (_unreadMuted >= _unreadFull) : false;
|
||||
}
|
||||
|
@ -249,7 +252,13 @@ public:
|
|||
|
||||
HistoryItem *lastImportantMessage() const;
|
||||
|
||||
int unreadCount() const {
|
||||
return _unreadCount;
|
||||
}
|
||||
void setUnreadCount(int newUnreadCount, bool psUpdate = true);
|
||||
bool mute() const {
|
||||
return _mute;
|
||||
}
|
||||
void setMute(bool newMute);
|
||||
void getNextShowFrom(HistoryBlock *block, int i);
|
||||
void addUnreadBar();
|
||||
|
@ -266,18 +275,18 @@ public:
|
|||
void fixLastMessage(bool wasAtBottom);
|
||||
|
||||
void setChatsListDate(const QDateTime &date);
|
||||
QPair<int32, int32> adjustByPosInChatsList(Dialogs::IndexedList *indexed);
|
||||
uint64 sortKeyInChatList() const {
|
||||
return _sortKeyInChatList;
|
||||
}
|
||||
bool inChatList() const {
|
||||
return !_chatListLinks.isEmpty();
|
||||
QPair<int32, int32> adjustByPosInChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed);
|
||||
bool inChatList(Dialogs::Mode list) const {
|
||||
return !chatListLinks(list).isEmpty();
|
||||
}
|
||||
int posInChatList() const;
|
||||
Dialogs::Row *addToChatList(Dialogs::IndexedList *indexed);
|
||||
void removeFromChatList(Dialogs::IndexedList *indexed);
|
||||
void removeChatListEntryByLetter(QChar letter);
|
||||
void addChatListEntryByLetter(QChar letter, Dialogs::Row *row);
|
||||
int posInChatList(Dialogs::Mode list) const;
|
||||
Dialogs::Row *addToChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed);
|
||||
void removeFromChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed);
|
||||
void removeChatListEntryByLetter(Dialogs::Mode list, QChar letter);
|
||||
void addChatListEntryByLetter(Dialogs::Mode list, QChar letter, Dialogs::Row *row);
|
||||
void updateChatListEntry() const;
|
||||
|
||||
MsgId minMsgId() const;
|
||||
|
@ -334,7 +343,6 @@ public:
|
|||
int width = 0;
|
||||
int height = 0;
|
||||
int32 msgCount = 0;
|
||||
int32 unreadCount = 0;
|
||||
MsgId inboxReadBefore = 1;
|
||||
MsgId outboxReadBefore = 1;
|
||||
HistoryItem *showFrom = nullptr;
|
||||
|
@ -412,8 +420,6 @@ protected:
|
|||
|
||||
public:
|
||||
|
||||
bool mute;
|
||||
|
||||
bool lastKeyboardInited = false;
|
||||
bool lastKeyboardUsed = false;
|
||||
MsgId lastKeyboardId = 0;
|
||||
|
@ -536,11 +542,19 @@ private:
|
|||
return ~QFlags<Flags::enum_type>(f);
|
||||
}
|
||||
Flags _flags;
|
||||
bool _mute;
|
||||
int32 _unreadCount = 0;
|
||||
|
||||
Dialogs::RowsByLetter _chatListLinks;
|
||||
Dialogs::Row *mainChatListLink() const {
|
||||
auto it = _chatListLinks.constFind(0);
|
||||
t_assert(it != _chatListLinks.cend());
|
||||
Dialogs::RowsByLetter _chatListLinks[2];
|
||||
Dialogs::RowsByLetter &chatListLinks(Dialogs::Mode list) {
|
||||
return _chatListLinks[static_cast<int>(list)];
|
||||
}
|
||||
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();
|
||||
}
|
||||
uint64 _sortKeyInChatList = 0; // like ((unixtime) << 32) | (incremented counter)
|
||||
|
|
|
@ -3270,7 +3270,7 @@ void HistoryWidget::notify_migrateUpdated(PeerData *peer) {
|
|||
showHistory(peer->migrateTo()->id, (_showAtMsgId > 0) ? (-_showAtMsgId) : _showAtMsgId, true);
|
||||
} else if ((_migrated ? _migrated->peer : 0) != peer->migrateFrom()) {
|
||||
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);
|
||||
} else {
|
||||
_migrated = migrated;
|
||||
|
@ -3831,7 +3831,7 @@ void HistoryWidget::updateFieldSubmitSettings() {
|
|||
void HistoryWidget::updateNotifySettings() {
|
||||
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) {
|
||||
_silent.setChecked(_peer->notify != EmptyNotifySettings && (_peer->notify->flags & MTPDpeerNotifySettings::Flag::f_silent));
|
||||
if (_silent.isHidden() && hasSilentToggle()) {
|
||||
|
@ -4211,7 +4211,7 @@ void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) {
|
|||
}
|
||||
} else {
|
||||
App::wnd()->notifySchedule(history, item);
|
||||
history->setUnreadCount(history->unreadCount + 1);
|
||||
history->setUnreadCount(history->unreadCount() + 1);
|
||||
}
|
||||
} else {
|
||||
if (_history == history) {
|
||||
|
@ -4220,7 +4220,7 @@ void HistoryWidget::newUnreadMsg(History *history, HistoryItem *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;
|
||||
if (_history->loadedAtTop()) {
|
||||
if (_history->unreadCount > count) {
|
||||
if (_history->unreadCount() > count) {
|
||||
_history->setUnreadCount(count);
|
||||
}
|
||||
if (_history->isEmpty() && count > 0) {
|
||||
|
@ -4373,7 +4373,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
|
|||
}
|
||||
_firstLoadRequest = 0;
|
||||
if (_history->loadedAtTop()) {
|
||||
if (_history->unreadCount > count) {
|
||||
if (_history->unreadCount() > count) {
|
||||
_history->setUnreadCount(count);
|
||||
}
|
||||
if (_history->isEmpty() && count > 0) {
|
||||
|
@ -4429,12 +4429,12 @@ void HistoryWidget::firstLoadMessages() {
|
|||
PeerData *from = _peer;
|
||||
int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage;
|
||||
if (_showAtMsgId == ShowAtUnreadMsgId) {
|
||||
if (_migrated && _migrated->unreadCount) {
|
||||
if (_migrated && _migrated->unreadCount()) {
|
||||
_history->getReadyFor(_showAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop);
|
||||
from = _migrated->peer;
|
||||
offset = -loadCount / 2;
|
||||
offset_id = _migrated->inboxReadBefore;
|
||||
} else if (_history->unreadCount) {
|
||||
} else if (_history->unreadCount()) {
|
||||
_history->getReadyFor(_showAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop);
|
||||
offset = -loadCount / 2;
|
||||
offset_id = _history->inboxReadBefore;
|
||||
|
@ -4552,11 +4552,11 @@ void HistoryWidget::delayedShowAt(MsgId showAtMsgId) {
|
|||
PeerData *from = _peer;
|
||||
int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage;
|
||||
if (_delayedShowAtMsgId == ShowAtUnreadMsgId) {
|
||||
if (_migrated && _migrated->unreadCount) {
|
||||
if (_migrated && _migrated->unreadCount()) {
|
||||
from = _migrated->peer;
|
||||
offset = -loadCount / 2;
|
||||
offset_id = _migrated->inboxReadBefore;
|
||||
} else if (_history->unreadCount) {
|
||||
} else if (_history->unreadCount()) {
|
||||
offset = -loadCount / 2;
|
||||
offset_id = _history->inboxReadBefore;
|
||||
} else {
|
||||
|
@ -4872,7 +4872,7 @@ bool HistoryWidget::joinFail(const RPCError &error, mtpRequestId req) {
|
|||
}
|
||||
|
||||
void HistoryWidget::onMuteUnmute() {
|
||||
App::main()->updateNotifySetting(_peer, _history->mute ? NotifySettingSetNotify : NotifySettingSetMuted);
|
||||
App::main()->updateNotifySetting(_peer, _history->mute() ? NotifySettingSetNotify : NotifySettingSetMuted);
|
||||
}
|
||||
|
||||
void HistoryWidget::onBroadcastSilentChange() {
|
||||
|
@ -6720,10 +6720,10 @@ void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector<MTPMessage>
|
|||
}
|
||||
|
||||
void HistoryWidget::countHistoryShowFrom() {
|
||||
if (_migrated && _showAtMsgId == ShowAtUnreadMsgId && _migrated->unreadCount) {
|
||||
if (_migrated && _showAtMsgId == ShowAtUnreadMsgId && _migrated->unreadCount()) {
|
||||
_migrated->updateShowFrom();
|
||||
}
|
||||
if ((_migrated && _migrated->showFrom) || _showAtMsgId != ShowAtUnreadMsgId || !_history->unreadCount) {
|
||||
if ((_migrated && _migrated->showFrom) || _showAtMsgId != ShowAtUnreadMsgId || !_history->unreadCount()) {
|
||||
_history->showFrom = 0;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ private:
|
|||
Gif,
|
||||
Article,
|
||||
Contact,
|
||||
Geo,
|
||||
Venue,
|
||||
};
|
||||
|
||||
|
|
|
@ -552,65 +552,66 @@ namespace {
|
|||
};
|
||||
|
||||
enum {
|
||||
dbiKey = 0x00,
|
||||
dbiUser = 0x01,
|
||||
dbiDcOptionOld = 0x02,
|
||||
dbiChatSizeMax = 0x03,
|
||||
dbiMutePeer = 0x04,
|
||||
dbiSendKey = 0x05,
|
||||
dbiAutoStart = 0x06,
|
||||
dbiStartMinimized = 0x07,
|
||||
dbiSoundNotify = 0x08,
|
||||
dbiWorkMode = 0x09,
|
||||
dbiSeenTrayTooltip = 0x0a,
|
||||
dbiDesktopNotify = 0x0b,
|
||||
dbiAutoUpdate = 0x0c,
|
||||
dbiLastUpdateCheck = 0x0d,
|
||||
dbiWindowPosition = 0x0e,
|
||||
dbiConnectionType = 0x0f,
|
||||
dbiKey = 0x00,
|
||||
dbiUser = 0x01,
|
||||
dbiDcOptionOld = 0x02,
|
||||
dbiChatSizeMax = 0x03,
|
||||
dbiMutePeer = 0x04,
|
||||
dbiSendKey = 0x05,
|
||||
dbiAutoStart = 0x06,
|
||||
dbiStartMinimized = 0x07,
|
||||
dbiSoundNotify = 0x08,
|
||||
dbiWorkMode = 0x09,
|
||||
dbiSeenTrayTooltip = 0x0a,
|
||||
dbiDesktopNotify = 0x0b,
|
||||
dbiAutoUpdate = 0x0c,
|
||||
dbiLastUpdateCheck = 0x0d,
|
||||
dbiWindowPosition = 0x0e,
|
||||
dbiConnectionType = 0x0f,
|
||||
// 0x10 reserved
|
||||
dbiDefaultAttach = 0x11,
|
||||
dbiCatsAndDogs = 0x12,
|
||||
dbiReplaceEmojis = 0x13,
|
||||
dbiAskDownloadPath = 0x14,
|
||||
dbiDownloadPathOld = 0x15,
|
||||
dbiScale = 0x16,
|
||||
dbiEmojiTabOld = 0x17,
|
||||
dbiRecentEmojisOld = 0x18,
|
||||
dbiLoggedPhoneNumber = 0x19,
|
||||
dbiMutedPeers = 0x1a,
|
||||
dbiDefaultAttach = 0x11,
|
||||
dbiCatsAndDogs = 0x12,
|
||||
dbiReplaceEmojis = 0x13,
|
||||
dbiAskDownloadPath = 0x14,
|
||||
dbiDownloadPathOld = 0x15,
|
||||
dbiScale = 0x16,
|
||||
dbiEmojiTabOld = 0x17,
|
||||
dbiRecentEmojisOld = 0x18,
|
||||
dbiLoggedPhoneNumber = 0x19,
|
||||
dbiMutedPeers = 0x1a,
|
||||
// 0x1b reserved
|
||||
dbiNotifyView = 0x1c,
|
||||
dbiSendToMenu = 0x1d,
|
||||
dbiCompressPastedImage = 0x1e,
|
||||
dbiLang = 0x1f,
|
||||
dbiLangFile = 0x20,
|
||||
dbiTileBackground = 0x21,
|
||||
dbiAutoLock = 0x22,
|
||||
dbiDialogLastPath = 0x23,
|
||||
dbiRecentEmojis = 0x24,
|
||||
dbiEmojiVariants = 0x25,
|
||||
dbiRecentStickers = 0x26,
|
||||
dbiDcOption = 0x27,
|
||||
dbiTryIPv6 = 0x28,
|
||||
dbiSongVolume = 0x29,
|
||||
dbiNotifyView = 0x1c,
|
||||
dbiSendToMenu = 0x1d,
|
||||
dbiCompressPastedImage = 0x1e,
|
||||
dbiLang = 0x1f,
|
||||
dbiLangFile = 0x20,
|
||||
dbiTileBackground = 0x21,
|
||||
dbiAutoLock = 0x22,
|
||||
dbiDialogLastPath = 0x23,
|
||||
dbiRecentEmojis = 0x24,
|
||||
dbiEmojiVariants = 0x25,
|
||||
dbiRecentStickers = 0x26,
|
||||
dbiDcOption = 0x27,
|
||||
dbiTryIPv6 = 0x28,
|
||||
dbiSongVolume = 0x29,
|
||||
dbiWindowsNotifications = 0x30,
|
||||
dbiIncludeMuted = 0x31,
|
||||
dbiMegagroupSizeMax = 0x32,
|
||||
dbiDownloadPath = 0x33,
|
||||
dbiAutoDownload = 0x34,
|
||||
dbiSavedGifsLimit = 0x35,
|
||||
dbiShowingSavedGifs = 0x36,
|
||||
dbiAutoPlay = 0x37,
|
||||
dbiAdaptiveForWide = 0x38,
|
||||
dbiIncludeMuted = 0x31,
|
||||
dbiMegagroupSizeMax = 0x32,
|
||||
dbiDownloadPath = 0x33,
|
||||
dbiAutoDownload = 0x34,
|
||||
dbiSavedGifsLimit = 0x35,
|
||||
dbiShowingSavedGifs = 0x36,
|
||||
dbiAutoPlay = 0x37,
|
||||
dbiAdaptiveForWide = 0x38,
|
||||
dbiHiddenPinnedMessages = 0x39,
|
||||
dbiDialogsMode = 0x40,
|
||||
|
||||
dbiEncryptedWithSalt = 333,
|
||||
dbiEncrypted = 444,
|
||||
dbiEncryptedWithSalt = 333,
|
||||
dbiEncrypted = 444,
|
||||
|
||||
// 500-600 reserved
|
||||
|
||||
dbiVersion = 666,
|
||||
dbiVersion = 666,
|
||||
};
|
||||
|
||||
|
||||
|
@ -981,6 +982,22 @@ namespace {
|
|||
cSetAutoPlayGif(gif == 1);
|
||||
} 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: {
|
||||
qint32 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) + Serialize::stringSize(cDialogLastPath());
|
||||
size += sizeof(quint32) + 3 * sizeof(qint32);
|
||||
size += sizeof(quint32) + 2 * sizeof(qint32);
|
||||
if (!Global::HiddenPinnedMessages().isEmpty()) {
|
||||
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(dbiSongVolume) << qint32(qRound(cSongVolume() * 1e6));
|
||||
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);
|
||||
|
||||
{
|
||||
|
|
|
@ -844,6 +844,10 @@ void MainWidget::notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBa
|
|||
history.notify_inlineItemLayoutChanged(layout);
|
||||
}
|
||||
|
||||
void MainWidget::notify_historyMuteUpdated(History *history) {
|
||||
dialogs.notify_historyMuteUpdated(history);
|
||||
}
|
||||
|
||||
void MainWidget::notify_handlePendingHistoryUpdate() {
|
||||
history.notify_handlePendingHistoryUpdate();
|
||||
}
|
||||
|
@ -1509,7 +1513,7 @@ void MainWidget::saveRecentHashtags(const QString &text) {
|
|||
}
|
||||
|
||||
void MainWidget::readServerHistory(History *hist, bool force) {
|
||||
if (!hist || (!force && !hist->unreadCount)) return;
|
||||
if (!hist || (!force && !hist->unreadCount())) return;
|
||||
|
||||
MsgId upTo = hist->inboxRead(0);
|
||||
if (hist->isChannel() && !hist->peer->asChannel()->amIn()) {
|
||||
|
@ -2665,14 +2669,18 @@ QRect MainWidget::historyRect() const {
|
|||
return r;
|
||||
}
|
||||
|
||||
void MainWidget::dlgUpdated(Dialogs::Row *row) {
|
||||
if (row) {
|
||||
dialogs.dlgUpdated(row);
|
||||
} else if (_peerInStack) {
|
||||
void MainWidget::dlgUpdated() {
|
||||
if (_peerInStack) {
|
||||
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) {
|
||||
if (!row) return;
|
||||
if (msgId < 0 && -msgId < ServerMaxMsgId && row->peer->migrateFrom()) {
|
||||
|
@ -3113,7 +3121,7 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
|
|||
h->setLastMessage(item);
|
||||
}
|
||||
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->inboxReadBefore = d.vread_inbox_max_id.v + 1;
|
||||
}
|
||||
|
|
|
@ -260,7 +260,8 @@ public:
|
|||
|
||||
void createDialog(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 windowShown();
|
||||
|
@ -467,6 +468,7 @@ public:
|
|||
void notify_clipStopperHidden(ClipStopperType type);
|
||||
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
||||
void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
|
||||
void notify_historyMuteUpdated(History *history);
|
||||
void notify_handlePendingHistoryUpdate();
|
||||
|
||||
void cmd_search();
|
||||
|
|
|
@ -823,14 +823,22 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
|
|||
} else {
|
||||
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")) {
|
||||
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 (
|
||||
qsl("debugmode").startsWith(str) ||
|
||||
qsl("testmode").startsWith(str) ||
|
||||
qsl("loadlang").startsWith(str) ||
|
||||
qsl("debugfiles").startsWith(str) ||
|
||||
qsl("workmode").startsWith(str) ||
|
||||
qsl("crashplease").startsWith(str)) {
|
||||
break;
|
||||
}
|
||||
|
|
35
Telegram/ui/buttons/peer_avatar_button.cpp
Normal file
35
Telegram/ui/buttons/peer_avatar_button.cpp
Normal 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);
|
||||
}
|
||||
}
|
40
Telegram/ui/buttons/peer_avatar_button.h
Normal file
40
Telegram/ui/buttons/peer_avatar_button.h
Normal 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;
|
||||
|
||||
};
|
Loading…
Add table
Reference in a new issue