mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Request dialog list entries when needed.
Also save the original server-side int32 date in HistoryItems.
This commit is contained in:
parent
0c5efb935d
commit
8bacc74d8b
50 changed files with 719 additions and 549 deletions
|
@ -377,24 +377,6 @@ void ApiWrap::requestDialogEntry(not_null<Data::Feed*> feed) {
|
||||||
auto peers = QVector<MTPInputDialogPeer>(
|
auto peers = QVector<MTPInputDialogPeer>(
|
||||||
1,
|
1,
|
||||||
MTP_inputDialogPeerFeed(MTP_int(feed->id())));
|
MTP_inputDialogPeerFeed(MTP_int(feed->id())));
|
||||||
if (feed->channelsLoaded()) {
|
|
||||||
const auto &channels = feed->channels();
|
|
||||||
peers.reserve(channels.size() + 1);
|
|
||||||
for (const auto history : feed->channels()) {
|
|
||||||
peers.push_back(MTP_inputDialogPeer(history->peer->input));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
request(MTPmessages_GetDialogs(
|
|
||||||
MTP_flags(MTPmessages_GetDialogs::Flag::f_feed_id),
|
|
||||||
MTP_int(feed->id()),
|
|
||||||
MTP_int(0), // offset_date
|
|
||||||
MTP_int(0), // offset_id
|
|
||||||
MTP_inputPeerEmpty(), // offset_peer
|
|
||||||
MTP_int(Data::Feed::kChannelsLimit)
|
|
||||||
)).done([=](const MTPmessages_Dialogs &result) {
|
|
||||||
// applyFeedChannels(result);
|
|
||||||
}).send();
|
|
||||||
}
|
|
||||||
request(MTPmessages_GetPeerDialogs(
|
request(MTPmessages_GetPeerDialogs(
|
||||||
MTP_vector(std::move(peers))
|
MTP_vector(std::move(peers))
|
||||||
)).done([=](const MTPmessages_PeerDialogs &result) {
|
)).done([=](const MTPmessages_PeerDialogs &result) {
|
||||||
|
@ -405,6 +387,27 @@ void ApiWrap::requestDialogEntry(not_null<Data::Feed*> feed) {
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void ApiWrap::requestFeedDialogsEntries(not_null<Data::Feed*> feed) {
|
||||||
|
// if (_dialogFeedRequests.contains(feed)) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// _dialogFeedRequests.emplace(feed);
|
||||||
|
//
|
||||||
|
// request(MTPmessages_GetDialogs(
|
||||||
|
// MTP_flags(MTPmessages_GetDialogs::Flag::f_feed_id),
|
||||||
|
// MTP_int(feed->id()),
|
||||||
|
// MTP_int(0), // offset_date
|
||||||
|
// MTP_int(0), // offset_id
|
||||||
|
// MTP_inputPeerEmpty(), // offset_peer
|
||||||
|
// MTP_int(Data::Feed::kChannelsLimit)
|
||||||
|
// )).done([=](const MTPmessages_Dialogs &result) {
|
||||||
|
// applyFeedDialogs(feed, result);
|
||||||
|
// _dialogFeedRequests.remove(feed);
|
||||||
|
// }).fail([=](const RPCError &error) {
|
||||||
|
// _dialogFeedRequests.remove(feed);
|
||||||
|
// }).send();
|
||||||
|
//}
|
||||||
|
|
||||||
void ApiWrap::requestDialogEntry(not_null<History*> history) {
|
void ApiWrap::requestDialogEntry(not_null<History*> history) {
|
||||||
if (_dialogRequests.contains(history)) {
|
if (_dialogRequests.contains(history)) {
|
||||||
return;
|
return;
|
||||||
|
@ -417,43 +420,7 @@ void ApiWrap::requestDialogEntry(not_null<History*> history) {
|
||||||
MTP_vector(std::move(peers))
|
MTP_vector(std::move(peers))
|
||||||
)).done([=](const MTPmessages_PeerDialogs &result) {
|
)).done([=](const MTPmessages_PeerDialogs &result) {
|
||||||
applyPeerDialogs(result);
|
applyPeerDialogs(result);
|
||||||
|
historyDialogEntryApplied(history);
|
||||||
if (history->lastMessage()) {
|
|
||||||
if (!history->chatsListDate().isNull()
|
|
||||||
&& history->loadedAtBottom()) {
|
|
||||||
if (const auto channel = history->peer->asChannel()) {
|
|
||||||
const auto inviter = channel->inviter;
|
|
||||||
if (inviter != 0
|
|
||||||
&& history->chatsListDate() <= channel->inviteDate
|
|
||||||
&& channel->amIn()) {
|
|
||||||
if (const auto from = App::userLoaded(inviter)) {
|
|
||||||
history->insertJoinedMessage(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
history->updateChatListExistence();
|
|
||||||
} else {
|
|
||||||
if (const auto chat = history->peer->asChat()) {
|
|
||||||
if (!chat->haveLeft()) {
|
|
||||||
Local::addSavedPeer(
|
|
||||||
history->peer,
|
|
||||||
history->chatsListDate());
|
|
||||||
}
|
|
||||||
} else if (const auto channel = history->peer->asChannel()) {
|
|
||||||
const auto inviter = channel->inviter;
|
|
||||||
if (inviter != 0 && channel->amIn()) {
|
|
||||||
if (const auto from = App::userLoaded(inviter)) {
|
|
||||||
history->unloadBlocks();
|
|
||||||
history->addNewerSlice(QVector<MTPMessage>());
|
|
||||||
history->insertJoinedMessage(
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
App::main()->deleteConversation(history->peer, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_dialogRequests.remove(history);
|
_dialogRequests.remove(history);
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
_dialogRequests.remove(history);
|
_dialogRequests.remove(history);
|
||||||
|
@ -486,6 +453,95 @@ void ApiWrap::applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs) {
|
||||||
_session->data().sendHistoryChangeNotifications();
|
_session->data().sendHistoryChangeNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiWrap::historyDialogEntryApplied(not_null<History*> history) {
|
||||||
|
if (!history->lastMessage()) {
|
||||||
|
if (const auto chat = history->peer->asChat()) {
|
||||||
|
if (!chat->haveLeft()) {
|
||||||
|
Local::addSavedPeer(
|
||||||
|
history->peer,
|
||||||
|
history->chatsListDate());
|
||||||
|
}
|
||||||
|
} else if (const auto channel = history->peer->asChannel()) {
|
||||||
|
const auto inviter = channel->inviter;
|
||||||
|
if (inviter != 0 && channel->amIn()) {
|
||||||
|
if (const auto from = App::userLoaded(inviter)) {
|
||||||
|
history->unloadBlocks();
|
||||||
|
history->addNewerSlice(QVector<MTPMessage>());
|
||||||
|
history->insertJoinedMessage(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
App::main()->deleteConversation(history->peer, false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!history->chatsListDate().isNull()
|
||||||
|
&& history->loadedAtBottom()) {
|
||||||
|
if (const auto channel = history->peer->asChannel()) {
|
||||||
|
const auto inviter = channel->inviter;
|
||||||
|
if (inviter != 0
|
||||||
|
&& history->chatsListDate() <= ParseDateTime(channel->inviteDate)
|
||||||
|
&& channel->amIn()) {
|
||||||
|
if (const auto from = App::userLoaded(inviter)) {
|
||||||
|
history->insertJoinedMessage(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
history->updateChatListExistence();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiWrap::applyFeedDialogs(
|
||||||
|
not_null<Data::Feed*> feed,
|
||||||
|
const MTPmessages_Dialogs &dialogs) {
|
||||||
|
const auto [dialogsList, messagesList] = [&] {
|
||||||
|
const auto process = [&](const auto &data) {
|
||||||
|
App::feedUsers(data.vusers);
|
||||||
|
App::feedChats(data.vchats);
|
||||||
|
return std::make_tuple(&data.vdialogs.v, &data.vmessages.v);
|
||||||
|
};
|
||||||
|
switch (dialogs.type()) {
|
||||||
|
case mtpc_messages_dialogs:
|
||||||
|
return process(dialogs.c_messages_dialogs());
|
||||||
|
|
||||||
|
case mtpc_messages_dialogsSlice:
|
||||||
|
LOG(("API Error: "
|
||||||
|
"Unexpected dialogsSlice in feed dialogs list."));
|
||||||
|
return process(dialogs.c_messages_dialogsSlice());
|
||||||
|
}
|
||||||
|
Unexpected("Type in DialogsWidget::dialogsReceived");
|
||||||
|
}();
|
||||||
|
|
||||||
|
App::feedMsgs(*messagesList, NewMessageLast);
|
||||||
|
|
||||||
|
auto channels = std::vector<not_null<ChannelData*>>();
|
||||||
|
channels.reserve(dialogsList->size());
|
||||||
|
for (const auto &dialog : *dialogsList) {
|
||||||
|
switch (dialog.type()) {
|
||||||
|
case mtpc_dialog: {
|
||||||
|
if (const auto peerId = peerFromMTP(dialog.c_dialog().vpeer)) {
|
||||||
|
if (peerIsChannel(peerId)) {
|
||||||
|
const auto history = App::history(peerId);
|
||||||
|
history->applyDialog(dialog.c_dialog());
|
||||||
|
channels.push_back(history->peer->asChannel());
|
||||||
|
} else {
|
||||||
|
LOG(("API Error: "
|
||||||
|
"Unexpected non-channel in feed dialogs list."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case mtpc_dialogFeed: {
|
||||||
|
LOG(("API Error: Unexpected dialogFeed in feed dialogs list."));
|
||||||
|
} break;
|
||||||
|
default: Unexpected("Type in DialogsInner::dialogsReceived");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
feed->setChannels(channels);
|
||||||
|
_session->data().sendHistoryChangeNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
void ApiWrap::requestFullPeer(PeerData *peer) {
|
void ApiWrap::requestFullPeer(PeerData *peer) {
|
||||||
if (!peer || _fullPeerRequests.contains(peer)) return;
|
if (!peer || _fullPeerRequests.contains(peer)) return;
|
||||||
|
|
||||||
|
@ -1118,12 +1174,12 @@ void ApiWrap::requestSelfParticipant(ChannelData *channel) {
|
||||||
case mtpc_channelParticipantSelf: {
|
case mtpc_channelParticipantSelf: {
|
||||||
auto &d = p.vparticipant.c_channelParticipantSelf();
|
auto &d = p.vparticipant.c_channelParticipantSelf();
|
||||||
channel->inviter = d.vinviter_id.v;
|
channel->inviter = d.vinviter_id.v;
|
||||||
channel->inviteDate = date(d.vdate);
|
channel->inviteDate = d.vdate.v;
|
||||||
} break;
|
} break;
|
||||||
case mtpc_channelParticipantCreator: {
|
case mtpc_channelParticipantCreator: {
|
||||||
auto &d = p.vparticipant.c_channelParticipantCreator();
|
auto &d = p.vparticipant.c_channelParticipantCreator();
|
||||||
channel->inviter = _session->userId();
|
channel->inviter = _session->userId();
|
||||||
channel->inviteDate = date(MTP_int(channel->date));
|
channel->inviteDate = channel->date;
|
||||||
if (channel->mgInfo) {
|
if (channel->mgInfo) {
|
||||||
channel->mgInfo->creator = App::self();
|
channel->mgInfo->creator = App::self();
|
||||||
}
|
}
|
||||||
|
@ -1131,7 +1187,7 @@ void ApiWrap::requestSelfParticipant(ChannelData *channel) {
|
||||||
case mtpc_channelParticipantAdmin: {
|
case mtpc_channelParticipantAdmin: {
|
||||||
auto &d = p.vparticipant.c_channelParticipantAdmin();
|
auto &d = p.vparticipant.c_channelParticipantAdmin();
|
||||||
channel->inviter = d.vinviter_id.v;
|
channel->inviter = d.vinviter_id.v;
|
||||||
channel->inviteDate = date(d.vdate);
|
channel->inviteDate = d.vdate.v;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1670,7 +1726,7 @@ void ApiWrap::clearHistory(not_null<PeerData*> peer) {
|
||||||
if (auto history = App::historyLoaded(peer->id)) {
|
if (auto history = App::historyLoaded(peer->id)) {
|
||||||
if (const auto last = history->lastMessage()) {
|
if (const auto last = history->lastMessage()) {
|
||||||
deleteTillId = last->id;
|
deleteTillId = last->id;
|
||||||
Local::addSavedPeer(history->peer, last->date);
|
Local::addSavedPeer(history->peer, ItemDateTime(last));
|
||||||
}
|
}
|
||||||
history->clear();
|
history->clear();
|
||||||
history->newLoaded = history->oldLoaded = true;
|
history->newLoaded = history->oldLoaded = true;
|
||||||
|
@ -2909,8 +2965,10 @@ void ApiWrap::requestFeedChannels(not_null<Data::Feed*> feed) {
|
||||||
|
|
||||||
case mtpc_channels_feedSources: {
|
case mtpc_channels_feedSources: {
|
||||||
const auto &data = result.c_channels_feedSources();
|
const auto &data = result.c_channels_feedSources();
|
||||||
App::feedUsers(data.vusers);
|
|
||||||
App::feedChats(data.vchats);
|
// First we set channels without reading them from data.
|
||||||
|
// This allows us to apply them all at once without registering
|
||||||
|
// them one by one.
|
||||||
for (const auto &broadcasts : data.vfeeds.v) {
|
for (const auto &broadcasts : data.vfeeds.v) {
|
||||||
if (broadcasts.type() == mtpc_feedBroadcasts) {
|
if (broadcasts.type() == mtpc_feedBroadcasts) {
|
||||||
const auto &list = broadcasts.c_feedBroadcasts();
|
const auto &list = broadcasts.c_feedBroadcasts();
|
||||||
|
@ -2923,6 +2981,10 @@ void ApiWrap::requestFeedChannels(not_null<Data::Feed*> feed) {
|
||||||
feed->setChannels(std::move(channels));
|
feed->setChannels(std::move(channels));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
App::feedUsers(data.vusers);
|
||||||
|
App::feedChats(data.vchats);
|
||||||
|
|
||||||
if (feed->channelsLoaded()) {
|
if (feed->channelsLoaded()) {
|
||||||
feedChannelsDone(feed);
|
feedChannelsDone(feed);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3198,7 +3260,7 @@ void ApiWrap::forwardMessages(
|
||||||
history->addNewForwarded(
|
history->addNewForwarded(
|
||||||
newId.msg,
|
newId.msg,
|
||||||
flags,
|
flags,
|
||||||
date(MTP_int(unixtime())),
|
unixtime(),
|
||||||
messageFromId,
|
messageFromId,
|
||||||
messagePostAuthor,
|
messagePostAuthor,
|
||||||
message);
|
message);
|
||||||
|
|
|
@ -69,6 +69,7 @@ public:
|
||||||
|
|
||||||
void requestContacts();
|
void requestContacts();
|
||||||
void requestDialogEntry(not_null<Data::Feed*> feed);
|
void requestDialogEntry(not_null<Data::Feed*> feed);
|
||||||
|
//void requestFeedDialogsEntries(not_null<Data::Feed*> feed);
|
||||||
void requestDialogEntry(not_null<History*> history);
|
void requestDialogEntry(not_null<History*> history);
|
||||||
|
|
||||||
void requestFullPeer(PeerData *peer);
|
void requestFullPeer(PeerData *peer);
|
||||||
|
@ -282,6 +283,10 @@ private:
|
||||||
QVector<MTPint> collectMessageIds(const MessageDataRequests &requests);
|
QVector<MTPint> collectMessageIds(const MessageDataRequests &requests);
|
||||||
MessageDataRequests *messageDataRequests(ChannelData *channel, bool onlyExisting = false);
|
MessageDataRequests *messageDataRequests(ChannelData *channel, bool onlyExisting = false);
|
||||||
void applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs);
|
void applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs);
|
||||||
|
void historyDialogEntryApplied(not_null<History*> history);
|
||||||
|
void applyFeedDialogs(
|
||||||
|
not_null<Data::Feed*> feed,
|
||||||
|
const MTPmessages_Dialogs &dialogs);
|
||||||
|
|
||||||
void gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mtpRequestId req);
|
void gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mtpRequestId req);
|
||||||
void gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestId req);
|
void gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestId req);
|
||||||
|
|
|
@ -460,7 +460,7 @@ void DeleteMessagesBox::prepare() {
|
||||||
} else {
|
} else {
|
||||||
text = _singleItem ? lang(lng_selected_delete_sure_this) : lng_selected_delete_sure(lt_count, _ids.size());
|
text = _singleItem ? lang(lng_selected_delete_sure_this) : lng_selected_delete_sure(lt_count, _ids.size());
|
||||||
auto canDeleteAllForEveryone = true;
|
auto canDeleteAllForEveryone = true;
|
||||||
auto now = ::date(unixtime());
|
auto now = unixtime();
|
||||||
auto deleteForUser = (UserData*)nullptr;
|
auto deleteForUser = (UserData*)nullptr;
|
||||||
auto peer = (PeerData*)nullptr;
|
auto peer = (PeerData*)nullptr;
|
||||||
auto forEveryoneText = lang(lng_delete_for_everyone_check);
|
auto forEveryoneText = lang(lng_delete_for_everyone_check);
|
||||||
|
@ -588,7 +588,7 @@ void DeleteMessagesBox::deleteAndClear() {
|
||||||
|
|
||||||
if (wasOnServer) {
|
if (wasOnServer) {
|
||||||
idsByPeer[history->peer].push_back(MTP_int(itemId.msg));
|
idsByPeer[history->peer].push_back(MTP_int(itemId.msg));
|
||||||
} else if (wasLast) {
|
} else if (wasLast && !history->lastMessageKnown()) {
|
||||||
Auth().api().requestDialogEntry(history);
|
Auth().api().requestDialogEntry(history);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -415,7 +415,7 @@ MTPChannelBannedRights EditRestrictedBox::DefaultRights(not_null<ChannelData*> c
|
||||||
|
|
||||||
void EditRestrictedBox::showRestrictUntil() {
|
void EditRestrictedBox::showRestrictUntil() {
|
||||||
auto tomorrow = QDate::currentDate().addDays(1);
|
auto tomorrow = QDate::currentDate().addDays(1);
|
||||||
auto highlighted = isUntilForever() ? tomorrow : date(getRealUntilValue()).date();
|
auto highlighted = isUntilForever() ? tomorrow : ParseDateTime(getRealUntilValue()).date();
|
||||||
auto month = highlighted;
|
auto month = highlighted;
|
||||||
_restrictUntilBox = Ui::show(
|
_restrictUntilBox = Ui::show(
|
||||||
Box<CalendarBox>(
|
Box<CalendarBox>(
|
||||||
|
@ -471,7 +471,11 @@ void EditRestrictedBox::createUntilVariants() {
|
||||||
};
|
};
|
||||||
auto addCustomVariant = [this, addVariant](TimeId until, TimeId from, TimeId to) {
|
auto addCustomVariant = [this, addVariant](TimeId until, TimeId from, TimeId to) {
|
||||||
if (!ChannelData::IsRestrictedForever(until) && until > from && until <= to) {
|
if (!ChannelData::IsRestrictedForever(until) && until > from && until <= to) {
|
||||||
addVariant(until, lng_rights_chat_banned_custom_date(lt_date, langDayOfMonthFull(date(until).date())));
|
addVariant(
|
||||||
|
until,
|
||||||
|
lng_rights_chat_banned_custom_date(
|
||||||
|
lt_date,
|
||||||
|
langDayOfMonthFull(ParseDateTime(until).date())));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto addCurrentVariant = [this, addCustomVariant](TimeId from, TimeId to) {
|
auto addCurrentVariant = [this, addCustomVariant](TimeId from, TimeId to) {
|
||||||
|
|
|
@ -364,15 +364,15 @@ void ContactsBoxController::checkForEmptyRows() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> ContactsBoxController::createSearchRow(not_null<PeerData*> peer) {
|
std::unique_ptr<PeerListRow> ContactsBoxController::createSearchRow(
|
||||||
if (auto user = peer->asUser()) {
|
not_null<PeerData*> peer) {
|
||||||
|
if (const auto user = peer->asUser()) {
|
||||||
return createRow(user);
|
return createRow(user);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
void ContactsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
Auth().api().requestDialogEntry(App::history(row->peer()));
|
|
||||||
Ui::showPeerHistory(row->peer(), ShowAtUnreadMsgId);
|
Ui::showPeerHistory(row->peer(), ShowAtUnreadMsgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -784,7 +784,11 @@ void SingleFilePreview::preparePreview(const Storage::PreparedFile &file) {
|
||||||
prepareThumb(preview);
|
prepareThumb(preview);
|
||||||
const auto filepath = file.path;
|
const auto filepath = file.path;
|
||||||
if (filepath.isEmpty()) {
|
if (filepath.isEmpty()) {
|
||||||
auto filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
|
auto filename = filedialogDefaultName(
|
||||||
|
qsl("image"),
|
||||||
|
qsl(".png"),
|
||||||
|
QString(),
|
||||||
|
true);
|
||||||
_nameText.setText(
|
_nameText.setText(
|
||||||
st::semiboldTextStyle,
|
st::semiboldTextStyle,
|
||||||
filename,
|
filename,
|
||||||
|
|
|
@ -119,8 +119,9 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
||||||
//CountriesByISO2::const_iterator j = countries.constFind(country);
|
//CountriesByISO2::const_iterator j = countries.constFind(country);
|
||||||
//if (j != countries.cend()) country = QString::fromUtf8(j.value()->name);
|
//if (j != countries.cend()) country = QString::fromUtf8(j.value()->name);
|
||||||
|
|
||||||
MTPint active = d.vdate_active.v ? d.vdate_active : d.vdate_created;
|
const auto active = data.activeTime = d.vdate_active.v
|
||||||
data.activeTime = active.v;
|
? d.vdate_active.v
|
||||||
|
: d.vdate_created.v;
|
||||||
|
|
||||||
data.info = qs(d.vdevice_model) + qstr(", ") + (platform.isEmpty() ? QString() : platform + ' ') + qs(d.vsystem_version);
|
data.info = qs(d.vdevice_model) + qstr(", ") + (platform.isEmpty() ? QString() : platform + ' ') + qs(d.vsystem_version);
|
||||||
data.ip = qs(d.vip) + (country.isEmpty() ? QString() : QString::fromUtf8(" \xe2\x80\x93 ") + country);
|
data.ip = qs(d.vip) + (country.isEmpty() ? QString() : QString::fromUtf8(" \xe2\x80\x93 ") + country);
|
||||||
|
@ -144,12 +145,15 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
||||||
}
|
}
|
||||||
_current = data;
|
_current = data;
|
||||||
} else {
|
} else {
|
||||||
QDateTime now(QDateTime::currentDateTime()), lastTime(date(active));
|
const auto now = QDateTime::currentDateTime();
|
||||||
QDate nowDate(now.date()), lastDate(lastTime.date());
|
const auto lastTime = ParseDateTime(active);
|
||||||
|
const auto nowDate = now.date();
|
||||||
|
const auto lastDate = lastTime.date();
|
||||||
QString dt;
|
QString dt;
|
||||||
if (lastDate == nowDate) {
|
if (lastDate == nowDate) {
|
||||||
data.active = lastTime.toString(cTimeFormat());
|
data.active = lastTime.toString(cTimeFormat());
|
||||||
} else if (lastDate.year() == nowDate.year() && lastDate.weekNumber() == nowDate.weekNumber()) {
|
} else if (lastDate.year() == nowDate.year()
|
||||||
|
&& lastDate.weekNumber() == nowDate.weekNumber()) {
|
||||||
data.active = langDayOfWeek(lastDate);
|
data.active = langDayOfWeek(lastDate);
|
||||||
} else {
|
} else {
|
||||||
data.active = lastDate.toString(qsl("d.MM.yy"));
|
data.active = lastDate.toString(qsl("d.MM.yy"));
|
||||||
|
|
|
@ -39,7 +39,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
bool canAddItem(not_null<const HistoryItem*> item) const {
|
bool canAddItem(not_null<const HistoryItem*> item) const {
|
||||||
return (ComputeType(item) == _type && item->date.date() == _date);
|
return (ComputeType(item) == _type)
|
||||||
|
&& (ItemDateTime(item).date() == _date);
|
||||||
}
|
}
|
||||||
void addItem(not_null<HistoryItem*> item) {
|
void addItem(not_null<HistoryItem*> item) {
|
||||||
Expects(canAddItem(item));
|
Expects(canAddItem(item));
|
||||||
|
@ -117,7 +118,7 @@ private:
|
||||||
BoxController::Row::Row(not_null<HistoryItem*> item)
|
BoxController::Row::Row(not_null<HistoryItem*> item)
|
||||||
: PeerListRow(item->history()->peer, item->id)
|
: PeerListRow(item->history()->peer, item->id)
|
||||||
, _items(1, item)
|
, _items(1, item)
|
||||||
, _date(item->date.date())
|
, _date(ItemDateTime(item).date())
|
||||||
, _type(ComputeType(item)) {
|
, _type(ComputeType(item)) {
|
||||||
refreshStatus();
|
refreshStatus();
|
||||||
}
|
}
|
||||||
|
@ -162,7 +163,7 @@ void BoxController::Row::refreshStatus() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto text = [this] {
|
auto text = [this] {
|
||||||
auto time = _items.front()->date.time().toString(cTimeFormat());
|
auto time = ItemDateTime(_items.front()).time().toString(cTimeFormat());
|
||||||
auto today = QDateTime::currentDateTime().date();
|
auto today = QDateTime::currentDateTime().date();
|
||||||
if (_date == today) {
|
if (_date == today) {
|
||||||
return lng_call_box_status_today(lt_time, time);
|
return lng_call_box_status_today(lt_time, time);
|
||||||
|
|
|
@ -29,7 +29,7 @@ QString filedialogDefaultName(
|
||||||
const QString &extension,
|
const QString &extension,
|
||||||
const QString &path,
|
const QString &path,
|
||||||
bool skipExistance,
|
bool skipExistance,
|
||||||
int fileTime) {
|
TimeId fileTime) {
|
||||||
auto directoryPath = path;
|
auto directoryPath = path;
|
||||||
if (directoryPath.isEmpty()) {
|
if (directoryPath.isEmpty()) {
|
||||||
if (cDialogLastPath().isEmpty()) {
|
if (cDialogLastPath().isEmpty()) {
|
||||||
|
@ -40,7 +40,8 @@ QString filedialogDefaultName(
|
||||||
|
|
||||||
QString base;
|
QString base;
|
||||||
if (fileTime) {
|
if (fileTime) {
|
||||||
base = prefix + ::date(fileTime).toString("_yyyy-MM-dd_HH-mm-ss");
|
const auto date = ParseDateTime(fileTime);
|
||||||
|
base = prefix + date.toString("_yyyy-MM-dd_HH-mm-ss");
|
||||||
} else {
|
} else {
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
|
|
|
@ -21,7 +21,7 @@ QString filedialogDefaultName(
|
||||||
const QString &extension,
|
const QString &extension,
|
||||||
const QString &path = QString(),
|
const QString &path = QString(),
|
||||||
bool skipExistance = false,
|
bool skipExistance = false,
|
||||||
int fileTime = 0);
|
TimeId fileTime = TimeId(0));
|
||||||
QString filedialogNextFilename(
|
QString filedialogNextFilename(
|
||||||
const QString &name,
|
const QString &name,
|
||||||
const QString &cur,
|
const QString &cur,
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeId myunixtime() {
|
TimeId LocalUnixtime() {
|
||||||
return (TimeId)time(NULL);
|
return (TimeId)time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,31 +103,25 @@ void unixtimeSet(int32 serverTime, bool force) {
|
||||||
DEBUG_LOG(("MTP Info: setting client unixtime to %1").arg(serverTime));
|
DEBUG_LOG(("MTP Info: setting client unixtime to %1").arg(serverTime));
|
||||||
}
|
}
|
||||||
unixtimeWasSet = true;
|
unixtimeWasSet = true;
|
||||||
unixtimeDelta = serverTime + 1 - myunixtime();
|
unixtimeDelta = serverTime + 1 - LocalUnixtime();
|
||||||
DEBUG_LOG(("MTP Info: now unixtimeDelta is %1").arg(unixtimeDelta));
|
DEBUG_LOG(("MTP Info: now unixtimeDelta is %1").arg(unixtimeDelta));
|
||||||
}
|
}
|
||||||
_initMsgIdConstants();
|
_initMsgIdConstants();
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeId unixtime() {
|
TimeId unixtime() {
|
||||||
auto result = myunixtime();
|
auto result = LocalUnixtime();
|
||||||
|
|
||||||
QReadLocker locker(&unixtimeLock);
|
QReadLocker locker(&unixtimeLock);
|
||||||
return result + unixtimeDelta;
|
return result + unixtimeDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeId fromServerTime(const MTPint &serverTime) {
|
QDateTime ParseDateTime(TimeId serverTime) {
|
||||||
|
if (serverTime <= 0) {
|
||||||
|
return QDateTime();
|
||||||
|
}
|
||||||
QReadLocker locker(&unixtimeLock);
|
QReadLocker locker(&unixtimeLock);
|
||||||
return serverTime.v - unixtimeDelta;
|
return QDateTime::fromTime_t(serverTime - unixtimeDelta);
|
||||||
}
|
|
||||||
|
|
||||||
MTPint toServerTime(const TimeId &clientTime) {
|
|
||||||
QReadLocker locker(&unixtimeLock);
|
|
||||||
return MTP_int(clientTime + unixtimeDelta);
|
|
||||||
}
|
|
||||||
|
|
||||||
QDateTime dateFromServerTime(TimeId time) {
|
|
||||||
return dateFromServerTime(MTP_int(time));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Precise timing functions / rand init
|
// Precise timing functions / rand init
|
||||||
|
@ -224,7 +218,7 @@ namespace {
|
||||||
_msgIdCoef = float64(0xFFFF0000L) / 1000000000.;
|
_msgIdCoef = float64(0xFFFF0000L) / 1000000000.;
|
||||||
_msStart = 1000LL * static_cast<TimeMs>(ts.tv_sec) + (static_cast<TimeMs>(ts.tv_nsec) / 1000000LL);
|
_msStart = 1000LL * static_cast<TimeMs>(ts.tv_sec) + (static_cast<TimeMs>(ts.tv_nsec) / 1000000LL);
|
||||||
#endif
|
#endif
|
||||||
_timeStart = myunixtime();
|
_timeStart = LocalUnixtime();
|
||||||
srand((uint32)(_msStart & 0xFFFFFFFFL));
|
srand((uint32)(_msStart & 0xFFFFFFFFL));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -310,7 +304,7 @@ namespace ThirdParty {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkms() {
|
bool checkms() {
|
||||||
auto unixms = (myunixtime() - _timeStart) * 1000LL + _msAddToUnixtime;
|
auto unixms = (LocalUnixtime() - _timeStart) * 1000LL + _msAddToUnixtime;
|
||||||
auto ms = getms(true);
|
auto ms = getms(true);
|
||||||
if (ms > unixms + 1000LL) {
|
if (ms > unixms + 1000LL) {
|
||||||
_msAddToUnixtime = ((ms - unixms) / 1000LL) * 1000LL;
|
_msAddToUnixtime = ((ms - unixms) / 1000LL) * 1000LL;
|
||||||
|
|
|
@ -225,32 +225,14 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MTPint;
|
|
||||||
using TimeId = int32;
|
using TimeId = int32;
|
||||||
TimeId myunixtime();
|
|
||||||
void unixtimeInit();
|
void unixtimeInit();
|
||||||
void unixtimeSet(TimeId servertime, bool force = false);
|
void unixtimeSet(TimeId serverTime, bool force = false);
|
||||||
TimeId unixtime();
|
TimeId unixtime();
|
||||||
TimeId fromServerTime(const MTPint &serverTime);
|
|
||||||
MTPint toServerTime(const TimeId &clientTime);
|
|
||||||
uint64 msgid();
|
uint64 msgid();
|
||||||
int32 reqid();
|
int32 reqid();
|
||||||
|
|
||||||
inline QDateTime date(int32 time = -1) {
|
QDateTime ParseDateTime(TimeId serverTime);
|
||||||
QDateTime result;
|
|
||||||
if (time >= 0) result.setTime_t(time);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDateTime dateFromServerTime(const MTPint &time) {
|
|
||||||
return date(fromServerTime(time));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDateTime date(const MTPint &time) {
|
|
||||||
return dateFromServerTime(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
QDateTime dateFromServerTime(TimeId time);
|
|
||||||
|
|
||||||
inline void mylocaltime(struct tm * _Tm, const time_t * _Time) {
|
inline void mylocaltime(struct tm * _Tm, const time_t * _Time) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|
|
@ -19,11 +19,28 @@ namespace {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Draft::Draft(const Ui::FlatTextarea *field, MsgId msgId, bool previewCancelled, mtpRequestId saveRequestId)
|
Draft::Draft(
|
||||||
: textWithTags(field->getTextWithTags())
|
const TextWithTags &textWithTags,
|
||||||
, msgId(msgId)
|
MsgId msgId,
|
||||||
, cursor(field)
|
const MessageCursor &cursor,
|
||||||
, previewCancelled(previewCancelled) {
|
bool previewCancelled,
|
||||||
|
mtpRequestId saveRequestId)
|
||||||
|
: textWithTags(textWithTags)
|
||||||
|
, msgId(msgId)
|
||||||
|
, cursor(cursor)
|
||||||
|
, previewCancelled(previewCancelled)
|
||||||
|
, saveRequestId(saveRequestId) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Draft::Draft(
|
||||||
|
not_null<const Ui::FlatTextarea*> field,
|
||||||
|
MsgId msgId,
|
||||||
|
bool previewCancelled,
|
||||||
|
mtpRequestId saveRequestId)
|
||||||
|
: textWithTags(field->getTextWithTags())
|
||||||
|
, msgId(msgId)
|
||||||
|
, cursor(field)
|
||||||
|
, previewCancelled(previewCancelled) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
|
void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
|
||||||
|
@ -32,7 +49,7 @@ void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
|
||||||
auto textWithTags = TextWithTags { TextUtilities::ApplyEntities(text), ConvertEntitiesToTextTags(text.entities) };
|
auto textWithTags = TextWithTags { TextUtilities::ApplyEntities(text), ConvertEntitiesToTextTags(text.entities) };
|
||||||
auto replyTo = draft.has_reply_to_msg_id() ? draft.vreply_to_msg_id.v : MsgId(0);
|
auto replyTo = draft.has_reply_to_msg_id() ? draft.vreply_to_msg_id.v : MsgId(0);
|
||||||
auto cloudDraft = std::make_unique<Draft>(textWithTags, replyTo, MessageCursor(QFIXED_MAX, QFIXED_MAX, QFIXED_MAX), draft.is_no_webpage());
|
auto cloudDraft = std::make_unique<Draft>(textWithTags, replyTo, MessageCursor(QFIXED_MAX, QFIXED_MAX, QFIXED_MAX), draft.is_no_webpage());
|
||||||
cloudDraft->date = ::date(draft.vdate);
|
cloudDraft->date = draft.vdate.v;
|
||||||
|
|
||||||
history->setCloudDraft(std::move(cloudDraft));
|
history->setCloudDraft(std::move(cloudDraft));
|
||||||
history->createLocalDraftFromCloud();
|
history->createLocalDraftFromCloud();
|
||||||
|
|
|
@ -17,18 +17,20 @@ void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft);
|
||||||
void clearPeerCloudDraft(PeerId peerId);
|
void clearPeerCloudDraft(PeerId peerId);
|
||||||
|
|
||||||
struct Draft {
|
struct Draft {
|
||||||
Draft() {
|
Draft() = default;
|
||||||
}
|
Draft(
|
||||||
Draft(const TextWithTags &textWithTags, MsgId msgId, const MessageCursor &cursor, bool previewCancelled, mtpRequestId saveRequestId = 0)
|
const TextWithTags &textWithTags,
|
||||||
: textWithTags(textWithTags)
|
MsgId msgId,
|
||||||
, msgId(msgId)
|
const MessageCursor &cursor,
|
||||||
, cursor(cursor)
|
bool previewCancelled,
|
||||||
, previewCancelled(previewCancelled)
|
mtpRequestId saveRequestId = 0);
|
||||||
, saveRequestId(saveRequestId) {
|
Draft(
|
||||||
}
|
not_null<const Ui::FlatTextarea*> field,
|
||||||
Draft(const Ui::FlatTextarea *field, MsgId msgId, bool previewCancelled, mtpRequestId saveRequestId = 0);
|
MsgId msgId,
|
||||||
|
bool previewCancelled,
|
||||||
|
mtpRequestId saveRequestId = 0);
|
||||||
|
|
||||||
QDateTime date;
|
TimeId date = 0;
|
||||||
TextWithTags textWithTags;
|
TextWithTags textWithTags;
|
||||||
MsgId msgId = 0; // replyToId for message draft, editMsgId for edit draft
|
MsgId msgId = 0; // replyToId for message draft, editMsgId for edit draft
|
||||||
MessageCursor cursor;
|
MessageCursor cursor;
|
||||||
|
|
|
@ -74,7 +74,7 @@ void Feed::registerOne(not_null<ChannelData*> channel) {
|
||||||
_channels.push_back(history);
|
_channels.push_back(history);
|
||||||
if (history->lastMessageKnown()) {
|
if (history->lastMessageKnown()) {
|
||||||
recountLastMessage();
|
recountLastMessage();
|
||||||
} else if (_channelsLoaded) {
|
} else if (lastMessageKnown()) {
|
||||||
_parent->session().api().requestDialogEntry(history);
|
_parent->session().api().requestDialogEntry(history);
|
||||||
}
|
}
|
||||||
_parent->session().storage().remove(
|
_parent->session().storage().remove(
|
||||||
|
@ -121,7 +121,7 @@ void Feed::unregisterOne(not_null<ChannelData*> channel) {
|
||||||
void Feed::updateLastMessage(not_null<HistoryItem*> item) {
|
void Feed::updateLastMessage(not_null<HistoryItem*> item) {
|
||||||
if (justUpdateLastMessage(item)) {
|
if (justUpdateLastMessage(item)) {
|
||||||
if (_lastMessage && *_lastMessage) {
|
if (_lastMessage && *_lastMessage) {
|
||||||
setChatsListDate((*_lastMessage)->date);
|
setChatsListDate(ItemDateTime(*_lastMessage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,15 +192,22 @@ void Feed::setChannels(std::vector<not_null<ChannelData*>> channels) {
|
||||||
_channels,
|
_channels,
|
||||||
channel.get(),
|
channel.get(),
|
||||||
[](auto history) { return history->peer->asChannel(); }
|
[](auto history) { return history->peer->asChannel(); }
|
||||||
) != end(_channels);
|
) == end(_channels);
|
||||||
}) | ranges::to_vector;
|
}) | ranges::to_vector;
|
||||||
|
|
||||||
for (const auto channel : remove) {
|
for (const auto channel : remove) {
|
||||||
channel->clearFeed();
|
channel->clearFeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We assume the last message was correct before requesting the list.
|
||||||
|
// So we save it and don't allow channels from the list to change it.
|
||||||
|
// After that we restore it.
|
||||||
|
const auto oldLastMessage = base::take(_lastMessage);
|
||||||
for (const auto channel : add) {
|
for (const auto channel : add) {
|
||||||
|
_lastMessage = base::none;
|
||||||
channel->setFeed(this);
|
channel->setFeed(this);
|
||||||
}
|
}
|
||||||
|
_lastMessage = oldLastMessage;
|
||||||
|
|
||||||
_channels.clear();
|
_channels.clear();
|
||||||
for (const auto channel : channels) {
|
for (const auto channel : channels) {
|
||||||
|
@ -256,7 +263,7 @@ void Feed::recountLastMessage() {
|
||||||
|
|
||||||
void Feed::updateChatsListDate() {
|
void Feed::updateChatsListDate() {
|
||||||
if (_lastMessage && *_lastMessage) {
|
if (_lastMessage && *_lastMessage) {
|
||||||
setChatsListDate((*_lastMessage)->date);
|
setChatsListDate(ItemDateTime(*_lastMessage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +275,14 @@ bool Feed::lastMessageKnown() const {
|
||||||
return !!_lastMessage;
|
return !!_lastMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Feed::unreadCount() const {
|
||||||
|
return _unreadCount ? *_unreadCount : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Feed::unreadCountKnown() const {
|
||||||
|
return !!_unreadCount;
|
||||||
|
}
|
||||||
|
|
||||||
void Feed::applyDialog(const MTPDdialogFeed &data) {
|
void Feed::applyDialog(const MTPDdialogFeed &data) {
|
||||||
const auto addChannel = [&](ChannelId channelId) {
|
const auto addChannel = [&](ChannelId channelId) {
|
||||||
if (const auto channel = App::channelLoaded(channelId)) {
|
if (const auto channel = App::channelLoaded(channelId)) {
|
||||||
|
@ -299,8 +314,14 @@ void Feed::applyDialog(const MTPDdialogFeed &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Feed::setUnreadCounts(int unreadNonMutedCount, int unreadMutedCount) {
|
void Feed::setUnreadCounts(int unreadNonMutedCount, int unreadMutedCount) {
|
||||||
|
if (unreadCountKnown()
|
||||||
|
&& (*_unreadCount == unreadNonMutedCount + unreadMutedCount)
|
||||||
|
&& (_unreadMutedCount == unreadMutedCount)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_unreadCount = unreadNonMutedCount + unreadMutedCount;
|
_unreadCount = unreadNonMutedCount + unreadMutedCount;
|
||||||
_unreadMutedCount = unreadMutedCount;
|
_unreadMutedCount = unreadMutedCount;
|
||||||
|
updateChatListEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Feed::setUnreadPosition(const MessagePosition &position) {
|
void Feed::setUnreadPosition(const MessagePosition &position) {
|
||||||
|
@ -312,7 +333,7 @@ void Feed::setUnreadPosition(const MessagePosition &position) {
|
||||||
void Feed::unreadCountChanged(
|
void Feed::unreadCountChanged(
|
||||||
base::optional<int> unreadCountDelta,
|
base::optional<int> unreadCountDelta,
|
||||||
int mutedCountDelta) {
|
int mutedCountDelta) {
|
||||||
if (!_unreadCount) {
|
if (!unreadCountKnown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (unreadCountDelta) {
|
if (unreadCountDelta) {
|
||||||
|
@ -323,6 +344,9 @@ void Feed::unreadCountChanged(
|
||||||
*_unreadCount);
|
*_unreadCount);
|
||||||
updateChatListEntry();
|
updateChatListEntry();
|
||||||
} else {
|
} else {
|
||||||
|
// _parent->session().api().requestFeedDialogsEntries(this);
|
||||||
|
// Happens once for each channel with unknown unread count.
|
||||||
|
// Requesting all feed dialogs could be huge and even have slicing.
|
||||||
_parent->session().api().requestDialogEntry(this);
|
_parent->session().api().requestDialogEntry(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,7 +368,7 @@ bool Feed::shouldBeInChatList() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Feed::chatListUnreadCount() const {
|
int Feed::chatListUnreadCount() const {
|
||||||
return _unreadCount ? *_unreadCount : 0;
|
return unreadCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Feed::chatListMutedBadge() const {
|
bool Feed::chatListMutedBadge() const {
|
||||||
|
|
|
@ -55,6 +55,8 @@ public:
|
||||||
|
|
||||||
HistoryItem *lastMessage() const;
|
HistoryItem *lastMessage() const;
|
||||||
bool lastMessageKnown() const;
|
bool lastMessageKnown() const;
|
||||||
|
int unreadCount() const;
|
||||||
|
bool unreadCountKnown() const;
|
||||||
|
|
||||||
bool toImportant() const override;
|
bool toImportant() const override;
|
||||||
bool shouldBeInChatList() const override;
|
bool shouldBeInChatList() const override;
|
||||||
|
|
|
@ -946,8 +946,8 @@ public:
|
||||||
|| amCreator();
|
|| amCreator();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 inviter = 0; // > 0 - user who invited me to channel, < 0 - not in channel
|
UserId inviter = 0; // > 0 - user who invited me to channel, < 0 - not in channel
|
||||||
QDateTime inviteDate;
|
TimeId inviteDate = 0;
|
||||||
|
|
||||||
void ptsInit(int32 pts) {
|
void ptsInit(int32 pts) {
|
||||||
_ptsWaiter.init(pts);
|
_ptsWaiter.init(pts);
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace {
|
||||||
|
|
||||||
constexpr auto kMinOnlineChangeTimeout = TimeMs(1000);
|
constexpr auto kMinOnlineChangeTimeout = TimeMs(1000);
|
||||||
constexpr auto kMaxOnlineChangeTimeout = 86400 * TimeMs(1000);
|
constexpr auto kMaxOnlineChangeTimeout = 86400 * TimeMs(1000);
|
||||||
|
constexpr auto kSecondsInDay = 86400;
|
||||||
|
|
||||||
int OnlinePhraseChangeInSeconds(TimeId online, TimeId now) {
|
int OnlinePhraseChangeInSeconds(TimeId online, TimeId now) {
|
||||||
if (online <= 0) {
|
if (online <= 0) {
|
||||||
|
@ -33,7 +34,7 @@ int OnlinePhraseChangeInSeconds(TimeId online, TimeId now) {
|
||||||
if (hours < 12) {
|
if (hours < 12) {
|
||||||
return (hours + 1) * 3600 - (now - online);
|
return (hours + 1) * 3600 - (now - online);
|
||||||
}
|
}
|
||||||
const auto nowFull = ::date(now);
|
const auto nowFull = ParseDateTime(now);
|
||||||
const auto tomorrow = QDateTime(nowFull.date().addDays(1));
|
const auto tomorrow = QDateTime(nowFull.date().addDays(1));
|
||||||
return static_cast<int32>(nowFull.secsTo(tomorrow));
|
return static_cast<int32>(nowFull.secsTo(tomorrow));
|
||||||
}
|
}
|
||||||
|
@ -175,27 +176,21 @@ TimeId SortByOnlineValue(not_null<UserData*> user, TimeId now) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
const auto online = user->onlineTill;
|
const auto online = user->onlineTill;
|
||||||
const auto fromDate = [](const QDate &date) {
|
|
||||||
return toServerTime(QDateTime(date).toTime_t()).v;
|
|
||||||
};
|
|
||||||
if (online <= 0) {
|
if (online <= 0) {
|
||||||
switch (online) {
|
switch (online) {
|
||||||
case 0:
|
case 0:
|
||||||
case -1: return online;
|
case -1: return online;
|
||||||
|
|
||||||
case -2: {
|
case -2: {
|
||||||
const auto recently = date(now).date().addDays(-3);
|
return now - 3 * kSecondsInDay;
|
||||||
return fromDate(recently);
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case -3: {
|
case -3: {
|
||||||
const auto weekago = date(now).date().addDays(-7);
|
return now - 7 * kSecondsInDay;
|
||||||
return fromDate(weekago);
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case -4: {
|
case -4: {
|
||||||
const auto monthago = date(now).date().addDays(-30);
|
return now - 30 * kSecondsInDay;
|
||||||
return fromDate(monthago);
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
return -online;
|
return -online;
|
||||||
|
@ -233,8 +228,8 @@ QString OnlineText(TimeId online, TimeId now) {
|
||||||
if (hours < 12) {
|
if (hours < 12) {
|
||||||
return lng_status_lastseen_hours(lt_count, hours);
|
return lng_status_lastseen_hours(lt_count, hours);
|
||||||
}
|
}
|
||||||
const auto onlineFull = ::date(online);
|
const auto onlineFull = ParseDateTime(online);
|
||||||
const auto nowFull = ::date(now);
|
const auto nowFull = ParseDateTime(now);
|
||||||
if (onlineFull.date() == nowFull.date()) {
|
if (onlineFull.date() == nowFull.date()) {
|
||||||
const auto onlineTime = onlineFull.time().toString(cTimeFormat());
|
const auto onlineTime = onlineFull.time().toString(cTimeFormat());
|
||||||
return lng_status_lastseen_today(lt_time, onlineTime);
|
return lng_status_lastseen_today(lt_time, onlineTime);
|
||||||
|
@ -259,8 +254,8 @@ QString OnlineTextFull(not_null<UserData*> user, TimeId now) {
|
||||||
} else if (const auto common = OnlineTextCommon(user->onlineTill, now)) {
|
} else if (const auto common = OnlineTextCommon(user->onlineTill, now)) {
|
||||||
return *common;
|
return *common;
|
||||||
}
|
}
|
||||||
const auto onlineFull = ::date(user->onlineTill);
|
const auto onlineFull = ParseDateTime(user->onlineTill);
|
||||||
const auto nowFull = ::date(now);
|
const auto nowFull = ParseDateTime(now);
|
||||||
if (onlineFull.date() == nowFull.date()) {
|
if (onlineFull.date() == nowFull.date()) {
|
||||||
const auto onlineTime = onlineFull.time().toString(cTimeFormat());
|
const auto onlineTime = onlineFull.time().toString(cTimeFormat());
|
||||||
return lng_status_lastseen_today(lt_time, onlineTime);
|
return lng_status_lastseen_today(lt_time, onlineTime);
|
||||||
|
|
|
@ -32,22 +32,6 @@ uint64 PinnedDialogPos(int pinnedIndex) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool MessageIsLess(not_null<HistoryItem*> a, not_null<HistoryItem*> b) {
|
|
||||||
if (a->date < b->date) {
|
|
||||||
return true;
|
|
||||||
} else if (b->date < a->date) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto apeer = a->history()->peer->bareId();
|
|
||||||
const auto bpeer = b->history()->peer->bareId();
|
|
||||||
if (apeer < bpeer) {
|
|
||||||
return true;
|
|
||||||
} else if (bpeer < apeer) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return a->id < b->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry::Entry(const Key &key)
|
Entry::Entry(const Key &key)
|
||||||
: lastItemTextCache(st::dialogsTextWidthMin)
|
: lastItemTextCache(st::dialogsTextWidthMin)
|
||||||
, _key(key) {
|
, _key(key) {
|
||||||
|
@ -127,7 +111,7 @@ PositionChange Entry::adjustByPosInChatList(
|
||||||
return { movedFrom, movedTo };
|
return { movedFrom, movedTo };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::setChatsListDate(const QDateTime &date) {
|
void Entry::setChatsListDate(QDateTime date) {
|
||||||
if (!_lastMessageDate.isNull() && _lastMessageDate >= date) {
|
if (!_lastMessageDate.isNull() && _lastMessageDate >= date) {
|
||||||
if (!inChatList(Dialogs::Mode::All)) {
|
if (!inChatList(Dialogs::Mode::All)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -33,8 +33,6 @@ struct PositionChange {
|
||||||
int movedTo;
|
int movedTo;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool MessageIsLess(not_null<HistoryItem*> a, not_null<HistoryItem*> b);
|
|
||||||
|
|
||||||
class Entry {
|
class Entry {
|
||||||
public:
|
public:
|
||||||
Entry(const Key &key);
|
Entry(const Key &key);
|
||||||
|
@ -62,7 +60,7 @@ public:
|
||||||
return _sortKeyInChatList;
|
return _sortKeyInChatList;
|
||||||
}
|
}
|
||||||
void updateChatListSortPosition();
|
void updateChatListSortPosition();
|
||||||
void setChatsListDate(const QDateTime &date);
|
void setChatsListDate(QDateTime date);
|
||||||
virtual void updateChatListExistence();
|
virtual void updateChatListExistence();
|
||||||
bool needUpdateInChatList() const;
|
bool needUpdateInChatList() const;
|
||||||
|
|
||||||
|
|
|
@ -1716,7 +1716,6 @@ void DialogsInner::dialogsReceived(const QVector<MTPDialog> &added) {
|
||||||
default: Unexpected("Type in DialogsInner::dialogsReceived");
|
default: Unexpected("Type in DialogsInner::dialogsReceived");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Notify::unreadCounterUpdated();
|
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1729,8 +1728,11 @@ void DialogsInner::applyDialog(const MTPDdialog &dialog) {
|
||||||
const auto history = App::history(peerId);
|
const auto history = App::history(peerId);
|
||||||
history->applyDialog(dialog);
|
history->applyDialog(dialog);
|
||||||
|
|
||||||
if (!history->isPinnedDialog() && !history->chatsListDate().isNull()) {
|
if (!history->isPinnedDialog()) {
|
||||||
addSavedPeersAfter(history->chatsListDate());
|
const auto date = history->chatsListDate();
|
||||||
|
if (!date.isNull()) {
|
||||||
|
addSavedPeersAfter(date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_contactsNoDialogs->del(history);
|
_contactsNoDialogs->del(history);
|
||||||
if (const auto from = history->peer->migrateFrom()) {
|
if (const auto from = history->peer->migrateFrom()) {
|
||||||
|
@ -1749,8 +1751,11 @@ void DialogsInner::applyFeedDialog(const MTPDdialogFeed &dialog) {
|
||||||
const auto feed = Auth().data().feed(feedId);
|
const auto feed = Auth().data().feed(feedId);
|
||||||
feed->applyDialog(dialog);
|
feed->applyDialog(dialog);
|
||||||
|
|
||||||
if (!feed->isPinnedDialog() && !feed->chatsListDate().isNull()) {
|
if (!feed->isPinnedDialog()) {
|
||||||
addSavedPeersAfter(feed->chatsListDate());
|
const auto date = feed->chatsListDate();
|
||||||
|
if (!date.isNull()) {
|
||||||
|
addSavedPeersAfter(date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace {
|
||||||
// Show all dates that are in the last 20 hours in time format.
|
// Show all dates that are in the last 20 hours in time format.
|
||||||
constexpr int kRecentlyInSeconds = 20 * 3600;
|
constexpr int kRecentlyInSeconds = 20 * 3600;
|
||||||
|
|
||||||
void paintRowDate(Painter &p, const QDateTime &date, QRect &rectForName, bool active, bool selected) {
|
void paintRowDate(Painter &p, QDateTime date, QRect &rectForName, bool active, bool selected) {
|
||||||
auto now = QDateTime::currentDateTime();
|
auto now = QDateTime::currentDateTime();
|
||||||
auto lastTime = date;
|
auto lastTime = date;
|
||||||
auto nowDate = now.date();
|
auto nowDate = now.date();
|
||||||
|
@ -389,13 +389,13 @@ void RowPainter::paint(
|
||||||
const auto displayDate = [item, cloudDraft] {
|
const auto displayDate = [item, cloudDraft] {
|
||||||
if (item) {
|
if (item) {
|
||||||
if (cloudDraft) {
|
if (cloudDraft) {
|
||||||
return (item->date > cloudDraft->date)
|
return (item->date() > cloudDraft->date)
|
||||||
? item->date
|
? ItemDateTime(item)
|
||||||
: cloudDraft->date;
|
: ParseDateTime(cloudDraft->date);
|
||||||
}
|
}
|
||||||
return item->date;
|
return ItemDateTime(item);
|
||||||
}
|
}
|
||||||
return cloudDraft ? cloudDraft->date : QDateTime();
|
return cloudDraft ? ParseDateTime(cloudDraft->date) : QDateTime();
|
||||||
}();
|
}();
|
||||||
|
|
||||||
const auto from = history
|
const auto from = history
|
||||||
|
@ -581,7 +581,7 @@ void RowPainter::paint(
|
||||||
from,
|
from,
|
||||||
item,
|
item,
|
||||||
cloudDraft,
|
cloudDraft,
|
||||||
item->date,
|
ItemDateTime(item),
|
||||||
fullWidth,
|
fullWidth,
|
||||||
flags,
|
flags,
|
||||||
ms,
|
ms,
|
||||||
|
|
|
@ -455,7 +455,7 @@ QString InnerWidget::tooltipText() const {
|
||||||
if (_mouseCursorState == CursorState::Date
|
if (_mouseCursorState == CursorState::Date
|
||||||
&& _mouseAction == MouseAction::None) {
|
&& _mouseAction == MouseAction::None) {
|
||||||
if (const auto view = App::hoveredItem()) {
|
if (const auto view = App::hoveredItem()) {
|
||||||
auto dateText = view->data()->date.toString(
|
auto dateText = view->dateTime().toString(
|
||||||
QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
||||||
return dateText;
|
return dateText;
|
||||||
}
|
}
|
||||||
|
@ -666,7 +666,7 @@ void InnerWidget::itemsAdded(Direction direction, int addedCount) {
|
||||||
const auto view = _items[i - 1].get();
|
const auto view = _items[i - 1].get();
|
||||||
if (i < _items.size()) {
|
if (i < _items.size()) {
|
||||||
const auto previous = _items[i].get();
|
const auto previous = _items[i].get();
|
||||||
view->setDisplayDate(view->data()->date.date() != previous->data()->date.date());
|
view->setDisplayDate(view->dateTime().date() != previous->dateTime().date());
|
||||||
const auto attach = view->computeIsAttachToPrevious(previous);
|
const auto attach = view->computeIsAttachToPrevious(previous);
|
||||||
view->setAttachToPrevious(attach);
|
view->setAttachToPrevious(attach);
|
||||||
previous->setAttachToNext(attach);
|
previous->setAttachToNext(attach);
|
||||||
|
@ -796,7 +796,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
||||||
} else {
|
} else {
|
||||||
HistoryView::ServiceMessagePainter::paintDate(
|
HistoryView::ServiceMessagePainter::paintDate(
|
||||||
p,
|
p,
|
||||||
view->data()->date,
|
view->dateTime(),
|
||||||
dateY,
|
dateY,
|
||||||
width);
|
width);
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ TextWithEntities ExtractEditedText(const MTPMessage &message) {
|
||||||
return { text, entities };
|
return { text, entities };
|
||||||
}
|
}
|
||||||
|
|
||||||
PhotoData *GenerateChatPhoto(ChannelId channelId, uint64 logEntryId, MTPint date, const MTPDchatPhoto &photo) {
|
PhotoData *GenerateChatPhoto(ChannelId channelId, uint64 logEntryId, TimeId date, const MTPDchatPhoto &photo) {
|
||||||
// We try to make a unique photoId that will stay the same for each pair (channelId, logEntryId).
|
// We try to make a unique photoId that will stay the same for each pair (channelId, logEntryId).
|
||||||
static const auto RandomIdPart = rand_value<uint64>();
|
static const auto RandomIdPart = rand_value<uint64>();
|
||||||
auto mixinIdPart = (static_cast<uint64>(static_cast<uint32>(channelId)) << 32) ^ logEntryId;
|
auto mixinIdPart = (static_cast<uint64>(static_cast<uint32>(channelId)) << 32) ^ logEntryId;
|
||||||
|
@ -119,7 +119,7 @@ PhotoData *GenerateChatPhoto(ChannelId channelId, uint64 logEntryId, MTPint date
|
||||||
MTP_flags(0),
|
MTP_flags(0),
|
||||||
MTP_long(photoId),
|
MTP_long(photoId),
|
||||||
MTP_long(0),
|
MTP_long(0),
|
||||||
date,
|
MTP_int(date),
|
||||||
MTP_vector<MTPPhotoSize>(photoSizes)));
|
MTP_vector<MTPPhotoSize>(photoSizes)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,13 +184,21 @@ auto GenerateBannedChangeText(const TextWithEntities &user, const MTPChannelBann
|
||||||
Expects(!prevRights || prevRights->type() == mtpc_channelBannedRights);
|
Expects(!prevRights || prevRights->type() == mtpc_channelBannedRights);
|
||||||
auto newFlags = newRights ? newRights->c_channelBannedRights().vflags.v : MTPDchannelBannedRights::Flags(0);
|
auto newFlags = newRights ? newRights->c_channelBannedRights().vflags.v : MTPDchannelBannedRights::Flags(0);
|
||||||
auto prevFlags = prevRights ? prevRights->c_channelBannedRights().vflags.v : MTPDchannelBannedRights::Flags(0);
|
auto prevFlags = prevRights ? prevRights->c_channelBannedRights().vflags.v : MTPDchannelBannedRights::Flags(0);
|
||||||
auto newUntil = newRights ? newRights->c_channelBannedRights().vuntil_date : MTP_int(0);
|
auto newUntil = newRights ? newRights->c_channelBannedRights().vuntil_date.v : TimeId(0);
|
||||||
auto indefinitely = ChannelData::IsRestrictedForever(newUntil.v);
|
auto indefinitely = ChannelData::IsRestrictedForever(newUntil);
|
||||||
if (newFlags & Flag::f_view_messages) {
|
if (newFlags & Flag::f_view_messages) {
|
||||||
return lng_admin_log_banned__generic(lt_user, user);
|
return lng_admin_log_banned__generic(lt_user, user);
|
||||||
}
|
}
|
||||||
auto untilText = indefinitely ? lang(lng_admin_log_restricted_forever) : lng_admin_log_restricted_until(lt_date, langDateTime(::date(newUntil)));
|
auto untilText = indefinitely
|
||||||
auto result = lng_admin_log_restricted__generic(lt_user, user, lt_until, TextWithEntities { untilText });
|
? lang(lng_admin_log_restricted_forever)
|
||||||
|
: lng_admin_log_restricted_until(
|
||||||
|
lt_date,
|
||||||
|
langDateTime(ParseDateTime(newUntil)));
|
||||||
|
auto result = lng_admin_log_restricted__generic(
|
||||||
|
lt_user,
|
||||||
|
user,
|
||||||
|
lt_until,
|
||||||
|
TextWithEntities { untilText });
|
||||||
|
|
||||||
static auto phraseMap = std::map<Flags, LangKey> {
|
static auto phraseMap = std::map<Flags, LangKey> {
|
||||||
{ Flag::f_view_messages, lng_admin_log_banned_view_messages },
|
{ Flag::f_view_messages, lng_admin_log_banned_view_messages },
|
||||||
|
@ -321,7 +329,7 @@ void GenerateItems(
|
||||||
auto from = App::user(event.vuser_id.v);
|
auto from = App::user(event.vuser_id.v);
|
||||||
auto channel = history->peer->asChannel();
|
auto channel = history->peer->asChannel();
|
||||||
auto &action = event.vaction;
|
auto &action = event.vaction;
|
||||||
auto date = event.vdate;
|
auto date = event.vdate.v;
|
||||||
auto addPart = [&](not_null<HistoryItem*> item) {
|
auto addPart = [&](not_null<HistoryItem*> item) {
|
||||||
return callback(OwnedItem(delegate, item));
|
return callback(OwnedItem(delegate, item));
|
||||||
};
|
};
|
||||||
|
@ -334,7 +342,7 @@ void GenerateItems(
|
||||||
auto addSimpleServiceMessage = [&](const QString &text, PhotoData *photo = nullptr) {
|
auto addSimpleServiceMessage = [&](const QString &text, PhotoData *photo = nullptr) {
|
||||||
auto message = HistoryService::PreparedText { text };
|
auto message = HistoryService::PreparedText { text };
|
||||||
message.links.push_back(fromLink);
|
message.links.push_back(fromLink);
|
||||||
addPart(new HistoryService(history, idManager->next(), ::date(date), message, 0, peerToUser(from->id), photo));
|
addPart(new HistoryService(history, idManager->next(), date, message, 0, peerToUser(from->id), photo));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createChangeTitle = [&](const MTPDchannelAdminLogEventActionChangeTitle &action) {
|
auto createChangeTitle = [&](const MTPDchannelAdminLogEventActionChangeTitle &action) {
|
||||||
|
@ -355,7 +363,7 @@ void GenerateItems(
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto newDescription = PrepareText(newValue, QString());
|
auto newDescription = PrepareText(newValue, QString());
|
||||||
auto body = new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), newDescription);
|
auto body = new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, date, peerToUser(from->id), QString(), newDescription);
|
||||||
if (!oldValue.isEmpty()) {
|
if (!oldValue.isEmpty()) {
|
||||||
auto oldDescription = PrepareText(oldValue, QString());
|
auto oldDescription = PrepareText(oldValue, QString());
|
||||||
body->addLogEntryOriginal(id, lang(lng_admin_log_previous_description), oldDescription);
|
body->addLogEntryOriginal(id, lang(lng_admin_log_previous_description), oldDescription);
|
||||||
|
@ -376,7 +384,7 @@ void GenerateItems(
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto newLink = newValue.isEmpty() ? TextWithEntities() : PrepareText(Messenger::Instance().createInternalLinkFull(newValue), QString());
|
auto newLink = newValue.isEmpty() ? TextWithEntities() : PrepareText(Messenger::Instance().createInternalLinkFull(newValue), QString());
|
||||||
auto body = new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), newLink);
|
auto body = new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, date, peerToUser(from->id), QString(), newLink);
|
||||||
if (!oldValue.isEmpty()) {
|
if (!oldValue.isEmpty()) {
|
||||||
auto oldLink = PrepareText(Messenger::Instance().createInternalLinkFull(oldValue), QString());
|
auto oldLink = PrepareText(Messenger::Instance().createInternalLinkFull(oldValue), QString());
|
||||||
body->addLogEntryOriginal(id, lang(lng_admin_log_previous_link), oldLink);
|
body->addLogEntryOriginal(id, lang(lng_admin_log_previous_link), oldLink);
|
||||||
|
@ -428,7 +436,7 @@ void GenerateItems(
|
||||||
PrepareLogMessage(
|
PrepareLogMessage(
|
||||||
action.vmessage,
|
action.vmessage,
|
||||||
idManager->next(),
|
idManager->next(),
|
||||||
date.v),
|
date),
|
||||||
detachExistingItem));
|
detachExistingItem));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -448,7 +456,7 @@ void GenerateItems(
|
||||||
PrepareLogMessage(
|
PrepareLogMessage(
|
||||||
action.vnew_message,
|
action.vnew_message,
|
||||||
idManager->next(),
|
idManager->next(),
|
||||||
date.v),
|
date),
|
||||||
detachExistingItem);
|
detachExistingItem);
|
||||||
if (oldValue.text.isEmpty()) {
|
if (oldValue.text.isEmpty()) {
|
||||||
oldValue = PrepareText(QString(), lang(lng_admin_log_empty_text));
|
oldValue = PrepareText(QString(), lang(lng_admin_log_empty_text));
|
||||||
|
@ -463,7 +471,7 @@ void GenerateItems(
|
||||||
|
|
||||||
auto detachExistingItem = false;
|
auto detachExistingItem = false;
|
||||||
addPart(history->createItem(
|
addPart(history->createItem(
|
||||||
PrepareLogMessage(action.vmessage, idManager->next(), date.v),
|
PrepareLogMessage(action.vmessage, idManager->next(), date),
|
||||||
detachExistingItem));
|
detachExistingItem));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -486,7 +494,7 @@ void GenerateItems(
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto bodyText = GenerateParticipantChangeText(channel, action.vparticipant);
|
auto bodyText = GenerateParticipantChangeText(channel, action.vparticipant);
|
||||||
addPart(new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), bodyText));
|
addPart(new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, date, peerToUser(from->id), QString(), bodyText));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createParticipantToggleBan = [&](const MTPDchannelAdminLogEventActionParticipantToggleBan &action) {
|
auto createParticipantToggleBan = [&](const MTPDchannelAdminLogEventActionParticipantToggleBan &action) {
|
||||||
|
@ -494,7 +502,7 @@ void GenerateItems(
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant, &action.vprev_participant);
|
auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant, &action.vprev_participant);
|
||||||
addPart(new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), bodyText));
|
addPart(new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, date, peerToUser(from->id), QString(), bodyText));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createParticipantToggleAdmin = [&](const MTPDchannelAdminLogEventActionParticipantToggleAdmin &action) {
|
auto createParticipantToggleAdmin = [&](const MTPDchannelAdminLogEventActionParticipantToggleAdmin &action) {
|
||||||
|
@ -502,7 +510,7 @@ void GenerateItems(
|
||||||
auto bodyReplyTo = 0;
|
auto bodyReplyTo = 0;
|
||||||
auto bodyViaBotId = 0;
|
auto bodyViaBotId = 0;
|
||||||
auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant, &action.vprev_participant);
|
auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant, &action.vprev_participant);
|
||||||
addPart(new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(from->id), QString(), bodyText));
|
addPart(new HistoryMessage(history, idManager->next(), bodyFlags, bodyReplyTo, bodyViaBotId, date, peerToUser(from->id), QString(), bodyText));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto createChangeStickerSet = [&](const MTPDchannelAdminLogEventActionChangeStickerSet &action) {
|
auto createChangeStickerSet = [&](const MTPDchannelAdminLogEventActionChangeStickerSet &action) {
|
||||||
|
@ -523,7 +531,7 @@ void GenerateItems(
|
||||||
auto message = HistoryService::PreparedText { text };
|
auto message = HistoryService::PreparedText { text };
|
||||||
message.links.push_back(fromLink);
|
message.links.push_back(fromLink);
|
||||||
message.links.push_back(setLink);
|
message.links.push_back(setLink);
|
||||||
addPart(new HistoryService(history, idManager->next(), ::date(date), message, 0, peerToUser(from->id)));
|
addPart(new HistoryService(history, idManager->next(), date, message, 0, peerToUser(from->id)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -322,12 +322,18 @@ void History::takeLocalDraft(History *from) {
|
||||||
|
|
||||||
void History::createLocalDraftFromCloud() {
|
void History::createLocalDraftFromCloud() {
|
||||||
auto draft = cloudDraft();
|
auto draft = cloudDraft();
|
||||||
if (Data::draftIsNull(draft) || !draft->date.isValid()) return;
|
if (Data::draftIsNull(draft) || !draft->date) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto existing = localDraft();
|
auto existing = localDraft();
|
||||||
if (Data::draftIsNull(existing) || !existing->date.isValid() || draft->date >= existing->date) {
|
if (Data::draftIsNull(existing) || !existing->date || draft->date >= existing->date) {
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
setLocalDraft(std::make_unique<Data::Draft>(draft->textWithTags, draft->msgId, draft->cursor, draft->previewCancelled));
|
setLocalDraft(std::make_unique<Data::Draft>(
|
||||||
|
draft->textWithTags,
|
||||||
|
draft->msgId,
|
||||||
|
draft->cursor,
|
||||||
|
draft->previewCancelled));
|
||||||
existing = localDraft();
|
existing = localDraft();
|
||||||
} else if (existing != draft) {
|
} else if (existing != draft) {
|
||||||
existing->textWithTags = draft->textWithTags;
|
existing->textWithTags = draft->textWithTags;
|
||||||
|
@ -351,11 +357,15 @@ Data::Draft *History::createCloudDraft(Data::Draft *fromDraft) {
|
||||||
0,
|
0,
|
||||||
MessageCursor(),
|
MessageCursor(),
|
||||||
false));
|
false));
|
||||||
cloudDraft()->date = QDateTime();
|
cloudDraft()->date = TimeId(0);
|
||||||
} else {
|
} else {
|
||||||
auto existing = cloudDraft();
|
auto existing = cloudDraft();
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
setCloudDraft(std::make_unique<Data::Draft>(fromDraft->textWithTags, fromDraft->msgId, fromDraft->cursor, fromDraft->previewCancelled));
|
setCloudDraft(std::make_unique<Data::Draft>(
|
||||||
|
fromDraft->textWithTags,
|
||||||
|
fromDraft->msgId,
|
||||||
|
fromDraft->cursor,
|
||||||
|
fromDraft->previewCancelled));
|
||||||
existing = cloudDraft();
|
existing = cloudDraft();
|
||||||
} else if (existing != fromDraft) {
|
} else if (existing != fromDraft) {
|
||||||
existing->textWithTags = fromDraft->textWithTags;
|
existing->textWithTags = fromDraft->textWithTags;
|
||||||
|
@ -363,7 +373,7 @@ Data::Draft *History::createCloudDraft(Data::Draft *fromDraft) {
|
||||||
existing->cursor = fromDraft->cursor;
|
existing->cursor = fromDraft->cursor;
|
||||||
existing->previewCancelled = fromDraft->previewCancelled;
|
existing->previewCancelled = fromDraft->previewCancelled;
|
||||||
}
|
}
|
||||||
existing->date = ::date(myunixtime());
|
existing->date = unixtime();
|
||||||
}
|
}
|
||||||
|
|
||||||
cloudDraftTextCache.clear();
|
cloudDraftTextCache.clear();
|
||||||
|
@ -623,99 +633,9 @@ std::vector<not_null<HistoryItem*>> History::createItems(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<HistoryItem*> History::createItemForwarded(
|
|
||||||
MsgId id,
|
|
||||||
MTPDmessage::Flags flags,
|
|
||||||
QDateTime date,
|
|
||||||
UserId from,
|
|
||||||
const QString &postAuthor,
|
|
||||||
HistoryMessage *original) {
|
|
||||||
return new HistoryMessage(
|
|
||||||
this,
|
|
||||||
id,
|
|
||||||
flags,
|
|
||||||
date,
|
|
||||||
from,
|
|
||||||
postAuthor,
|
|
||||||
original);
|
|
||||||
}
|
|
||||||
|
|
||||||
not_null<HistoryItem*> History::createItemDocument(
|
|
||||||
MsgId id,
|
|
||||||
MTPDmessage::Flags flags,
|
|
||||||
UserId viaBotId,
|
|
||||||
MsgId replyTo,
|
|
||||||
QDateTime date,
|
|
||||||
UserId from,
|
|
||||||
const QString &postAuthor,
|
|
||||||
DocumentData *document,
|
|
||||||
const TextWithEntities &caption,
|
|
||||||
const MTPReplyMarkup &markup) {
|
|
||||||
return new HistoryMessage(
|
|
||||||
this,
|
|
||||||
id,
|
|
||||||
flags,
|
|
||||||
replyTo,
|
|
||||||
viaBotId,
|
|
||||||
date,
|
|
||||||
from,
|
|
||||||
postAuthor,
|
|
||||||
document,
|
|
||||||
caption,
|
|
||||||
markup);
|
|
||||||
}
|
|
||||||
|
|
||||||
not_null<HistoryItem*> History::createItemPhoto(
|
|
||||||
MsgId id,
|
|
||||||
MTPDmessage::Flags flags,
|
|
||||||
UserId viaBotId,
|
|
||||||
MsgId replyTo,
|
|
||||||
QDateTime date,
|
|
||||||
UserId from,
|
|
||||||
const QString &postAuthor,
|
|
||||||
PhotoData *photo,
|
|
||||||
const TextWithEntities &caption,
|
|
||||||
const MTPReplyMarkup &markup) {
|
|
||||||
return new HistoryMessage(
|
|
||||||
this,
|
|
||||||
id,
|
|
||||||
flags,
|
|
||||||
replyTo,
|
|
||||||
viaBotId,
|
|
||||||
date,
|
|
||||||
from,
|
|
||||||
postAuthor,
|
|
||||||
photo,
|
|
||||||
caption,
|
|
||||||
markup);
|
|
||||||
}
|
|
||||||
|
|
||||||
not_null<HistoryItem*> History::createItemGame(
|
|
||||||
MsgId id,
|
|
||||||
MTPDmessage::Flags flags,
|
|
||||||
UserId viaBotId,
|
|
||||||
MsgId replyTo,
|
|
||||||
QDateTime date,
|
|
||||||
UserId from,
|
|
||||||
const QString &postAuthor,
|
|
||||||
GameData *game,
|
|
||||||
const MTPReplyMarkup &markup) {
|
|
||||||
return new HistoryMessage(
|
|
||||||
this,
|
|
||||||
id,
|
|
||||||
flags,
|
|
||||||
replyTo,
|
|
||||||
viaBotId,
|
|
||||||
date,
|
|
||||||
from,
|
|
||||||
postAuthor,
|
|
||||||
game,
|
|
||||||
markup);
|
|
||||||
}
|
|
||||||
|
|
||||||
not_null<HistoryItem*> History::addNewService(
|
not_null<HistoryItem*> History::addNewService(
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
const QString &text,
|
const QString &text,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
bool unread) {
|
bool unread) {
|
||||||
|
@ -781,12 +701,19 @@ HistoryItem *History::addToHistory(const MTPMessage &msg) {
|
||||||
not_null<HistoryItem*> History::addNewForwarded(
|
not_null<HistoryItem*> History::addNewForwarded(
|
||||||
MsgId id,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
HistoryMessage *original) {
|
not_null<HistoryMessage*> original) {
|
||||||
return addNewItem(
|
return addNewItem(
|
||||||
createItemForwarded(id, flags, date, from, postAuthor, original),
|
new HistoryMessage(
|
||||||
|
this,
|
||||||
|
id,
|
||||||
|
flags,
|
||||||
|
date,
|
||||||
|
from,
|
||||||
|
postAuthor,
|
||||||
|
original),
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,18 +722,19 @@ not_null<HistoryItem*> History::addNewDocument(
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
DocumentData *document,
|
not_null<DocumentData*> document,
|
||||||
const TextWithEntities &caption,
|
const TextWithEntities &caption,
|
||||||
const MTPReplyMarkup &markup) {
|
const MTPReplyMarkup &markup) {
|
||||||
return addNewItem(
|
return addNewItem(
|
||||||
createItemDocument(
|
new HistoryMessage(
|
||||||
|
this,
|
||||||
id,
|
id,
|
||||||
flags,
|
flags,
|
||||||
viaBotId,
|
|
||||||
replyTo,
|
replyTo,
|
||||||
|
viaBotId,
|
||||||
date,
|
date,
|
||||||
from,
|
from,
|
||||||
postAuthor,
|
postAuthor,
|
||||||
|
@ -821,18 +749,19 @@ not_null<HistoryItem*> History::addNewPhoto(
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
PhotoData *photo,
|
not_null<PhotoData*> photo,
|
||||||
const TextWithEntities &caption,
|
const TextWithEntities &caption,
|
||||||
const MTPReplyMarkup &markup) {
|
const MTPReplyMarkup &markup) {
|
||||||
return addNewItem(
|
return addNewItem(
|
||||||
createItemPhoto(
|
new HistoryMessage(
|
||||||
|
this,
|
||||||
id,
|
id,
|
||||||
flags,
|
flags,
|
||||||
viaBotId,
|
|
||||||
replyTo,
|
replyTo,
|
||||||
|
viaBotId,
|
||||||
date,
|
date,
|
||||||
from,
|
from,
|
||||||
postAuthor,
|
postAuthor,
|
||||||
|
@ -847,17 +776,18 @@ not_null<HistoryItem*> History::addNewGame(
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
GameData *game,
|
not_null<GameData*> game,
|
||||||
const MTPReplyMarkup &markup) {
|
const MTPReplyMarkup &markup) {
|
||||||
return addNewItem(
|
return addNewItem(
|
||||||
createItemGame(
|
new HistoryMessage(
|
||||||
|
this,
|
||||||
id,
|
id,
|
||||||
flags,
|
flags,
|
||||||
viaBotId,
|
|
||||||
replyTo,
|
replyTo,
|
||||||
|
viaBotId,
|
||||||
date,
|
date,
|
||||||
from,
|
from,
|
||||||
postAuthor,
|
postAuthor,
|
||||||
|
@ -1291,8 +1221,7 @@ void History::newItemAdded(not_null<HistoryItem*> item) {
|
||||||
if (from == item->author()) {
|
if (from == item->author()) {
|
||||||
clearSendAction(from);
|
clearSendAction(from);
|
||||||
}
|
}
|
||||||
auto itemServerTime = toServerTime(item->date.toTime_t());
|
from->madeAction(item->date());
|
||||||
from->madeAction(itemServerTime.v);
|
|
||||||
}
|
}
|
||||||
if (item->out()) {
|
if (item->out()) {
|
||||||
destroyUnreadBar();
|
destroyUnreadBar();
|
||||||
|
@ -1670,6 +1599,10 @@ int History::unreadCount() const {
|
||||||
return _unreadCount ? *_unreadCount : 0;
|
return _unreadCount ? *_unreadCount : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool History::unreadCountKnown() const {
|
||||||
|
return !!_unreadCount;
|
||||||
|
}
|
||||||
|
|
||||||
void History::setUnreadCount(int newUnreadCount) {
|
void History::setUnreadCount(int newUnreadCount) {
|
||||||
if (!_unreadCount || *_unreadCount != newUnreadCount) {
|
if (!_unreadCount || *_unreadCount != newUnreadCount) {
|
||||||
const auto unreadCountDelta = _unreadCount | [&](int count) {
|
const auto unreadCountDelta = _unreadCount | [&](int count) {
|
||||||
|
@ -1805,8 +1738,11 @@ std::shared_ptr<AdminLog::LocalIdManager> History::adminLogIdManager() {
|
||||||
QDateTime History::adjustChatListDate() const {
|
QDateTime History::adjustChatListDate() const {
|
||||||
const auto result = chatsListDate();
|
const auto result = chatsListDate();
|
||||||
if (const auto draft = cloudDraft()) {
|
if (const auto draft = cloudDraft()) {
|
||||||
if (!Data::draftIsNull(draft) && draft->date > result) {
|
if (!Data::draftIsNull(draft)) {
|
||||||
return draft->date;
|
const auto draftResult = ParseDateTime(draft->date);
|
||||||
|
if (draftResult > result) {
|
||||||
|
return draftResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -2123,7 +2059,7 @@ void History::setLastMessage(HistoryItem *item) {
|
||||||
if (const auto feed = peer->feed()) {
|
if (const auto feed = peer->feed()) {
|
||||||
feed->updateLastMessage(item);
|
feed->updateLastMessage(item);
|
||||||
}
|
}
|
||||||
setChatsListDate(item->date);
|
setChatsListDate(ItemDateTime(item));
|
||||||
} else if (!_lastMessage || *_lastMessage) {
|
} else if (!_lastMessage || *_lastMessage) {
|
||||||
_lastMessage = nullptr;
|
_lastMessage = nullptr;
|
||||||
updateChatListEntry();
|
updateChatListEntry();
|
||||||
|
@ -2140,7 +2076,7 @@ bool History::lastMessageKnown() const {
|
||||||
|
|
||||||
void History::updateChatListExistence() {
|
void History::updateChatListExistence() {
|
||||||
Entry::updateChatListExistence();
|
Entry::updateChatListExistence();
|
||||||
if (!lastMessageKnown() || !_unreadCount) {
|
if (!lastMessageKnown() || !unreadCountKnown()) {
|
||||||
if (const auto channel = peer->asChannel()) {
|
if (const auto channel = peer->asChannel()) {
|
||||||
if (!channel->feed()) {
|
if (!channel->feed()) {
|
||||||
// After ungrouping from a feed we need to load dialog.
|
// After ungrouping from a feed we need to load dialog.
|
||||||
|
@ -2197,7 +2133,7 @@ void History::applyDialog(const MTPDdialog &data) {
|
||||||
peerToChannel(channel->id),
|
peerToChannel(channel->id),
|
||||||
data.vtop_message.v);
|
data.vtop_message.v);
|
||||||
if (const auto item = App::histItemById(topMessageId)) {
|
if (const auto item = App::histItemById(topMessageId)) {
|
||||||
if (item->date <= date(channel->date)) {
|
if (item->date() <= channel->date) {
|
||||||
Auth().api().requestSelfParticipant(channel);
|
Auth().api().requestSelfParticipant(channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2384,7 +2320,7 @@ HistoryService *History::insertJoinedMessage(bool unread) {
|
||||||
// flags |= MTPDmessage::Flag::f_unread;
|
// flags |= MTPDmessage::Flag::f_unread;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto inviteDate = peer->asChannel()->inviteDate;
|
const auto inviteDate = peer->asChannel()->inviteDate;
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
_joinedMessage = GenerateJoinedMessage(
|
_joinedMessage = GenerateJoinedMessage(
|
||||||
this,
|
this,
|
||||||
|
@ -2409,7 +2345,7 @@ HistoryService *History::insertJoinedMessage(bool unread) {
|
||||||
peer->asChannel()->mgInfo->joinedMessageFound = true;
|
peer->asChannel()->mgInfo->joinedMessageFound = true;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (item->date <= inviteDate) {
|
if (item->date() <= inviteDate) {
|
||||||
++itemIndex;
|
++itemIndex;
|
||||||
_joinedMessage = GenerateJoinedMessage(
|
_joinedMessage = GenerateJoinedMessage(
|
||||||
this,
|
this,
|
||||||
|
@ -2418,7 +2354,7 @@ HistoryService *History::insertJoinedMessage(bool unread) {
|
||||||
flags);
|
flags);
|
||||||
addNewInTheMiddle(_joinedMessage, blockIndex, itemIndex);
|
addNewInTheMiddle(_joinedMessage, blockIndex, itemIndex);
|
||||||
const auto lastDate = chatsListDate();
|
const auto lastDate = chatsListDate();
|
||||||
if (lastDate.isNull() || inviteDate >= lastDate) {
|
if (lastDate.isNull() || ParseDateTime(inviteDate) >= lastDate) {
|
||||||
setLastMessage(_joinedMessage);
|
setLastMessage(_joinedMessage);
|
||||||
if (unread) {
|
if (unread) {
|
||||||
newItemAdded(_joinedMessage);
|
newItemAdded(_joinedMessage);
|
||||||
|
@ -2456,14 +2392,15 @@ void History::checkJoinedMessage(bool createUnread) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime inviteDate = peer->asChannel()->inviteDate;
|
const auto inviteDate = peer->asChannel()->inviteDate;
|
||||||
QDateTime firstDate, lastDate;
|
auto firstDate = TimeId(0);
|
||||||
|
auto lastDate = TimeId(0);
|
||||||
if (!blocks.empty()) {
|
if (!blocks.empty()) {
|
||||||
firstDate = blocks.front()->messages.front()->data()->date;
|
firstDate = blocks.front()->messages.front()->data()->date();
|
||||||
lastDate = blocks.back()->messages.back()->data()->date;
|
lastDate = blocks.back()->messages.back()->data()->date();
|
||||||
}
|
}
|
||||||
if (!firstDate.isNull()
|
if (firstDate
|
||||||
&& !lastDate.isNull()
|
&& lastDate
|
||||||
&& (firstDate <= inviteDate || loadedAtTop())
|
&& (firstDate <= inviteDate || loadedAtTop())
|
||||||
&& (lastDate > inviteDate || loadedAtBottom())) {
|
&& (lastDate > inviteDate || loadedAtBottom())) {
|
||||||
const auto willBeLastMsg = (inviteDate >= lastDate);
|
const auto willBeLastMsg = (inviteDate >= lastDate);
|
||||||
|
@ -2596,7 +2533,7 @@ void History::clearUpTill(MsgId availableMinId) {
|
||||||
MTP_int(fromId),
|
MTP_int(fromId),
|
||||||
peerToMTP(peer->id),
|
peerToMTP(peer->id),
|
||||||
MTP_int(replyToId),
|
MTP_int(replyToId),
|
||||||
toServerTime(item->date.toTime_t()),
|
MTP_int(item->date()),
|
||||||
MTP_messageActionHistoryClear()
|
MTP_messageActionHistoryClear()
|
||||||
).c_messageService());
|
).c_messageService());
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,15 +148,56 @@ public:
|
||||||
void unloadBlocks();
|
void unloadBlocks();
|
||||||
void clearUpTill(MsgId availableMinId);
|
void clearUpTill(MsgId availableMinId);
|
||||||
|
|
||||||
void applyGroupAdminChanges(const base::flat_map<UserId, bool> &changes);
|
void applyGroupAdminChanges(
|
||||||
|
const base::flat_map<UserId, bool> &changes);
|
||||||
|
|
||||||
HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type);
|
HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type);
|
||||||
HistoryItem *addToHistory(const MTPMessage &msg);
|
HistoryItem *addToHistory(const MTPMessage &msg);
|
||||||
not_null<HistoryItem*> addNewService(MsgId msgId, QDateTime date, const QString &text, MTPDmessage::Flags flags = 0, bool newMsg = true);
|
not_null<HistoryItem*> addNewService(
|
||||||
not_null<HistoryItem*> addNewForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, UserId from, const QString &postAuthor, HistoryMessage *item);
|
MsgId msgId,
|
||||||
not_null<HistoryItem*> addNewDocument(MsgId id, MTPDmessage::Flags flags, UserId viaBotId, MsgId replyTo, QDateTime date, UserId from, const QString &postAuthor, DocumentData *doc, const TextWithEntities &caption, const MTPReplyMarkup &markup);
|
TimeId date,
|
||||||
not_null<HistoryItem*> addNewPhoto(MsgId id, MTPDmessage::Flags flags, UserId viaBotId, MsgId replyTo, QDateTime date, UserId from, const QString &postAuthor, PhotoData *photo, const TextWithEntities &caption, const MTPReplyMarkup &markup);
|
const QString &text,
|
||||||
not_null<HistoryItem*> addNewGame(MsgId id, MTPDmessage::Flags flags, UserId viaBotId, MsgId replyTo, QDateTime date, UserId from, const QString &postAuthor, GameData *game, const MTPReplyMarkup &markup);
|
MTPDmessage::Flags flags = 0,
|
||||||
|
bool newMsg = true);
|
||||||
|
not_null<HistoryItem*> addNewForwarded(
|
||||||
|
MsgId id,
|
||||||
|
MTPDmessage::Flags flags,
|
||||||
|
TimeId date,
|
||||||
|
UserId from,
|
||||||
|
const QString &postAuthor,
|
||||||
|
not_null<HistoryMessage*> original);
|
||||||
|
not_null<HistoryItem*> addNewDocument(
|
||||||
|
MsgId id,
|
||||||
|
MTPDmessage::Flags flags,
|
||||||
|
UserId viaBotId,
|
||||||
|
MsgId replyTo,
|
||||||
|
TimeId date,
|
||||||
|
UserId from,
|
||||||
|
const QString &postAuthor,
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
const TextWithEntities &caption,
|
||||||
|
const MTPReplyMarkup &markup);
|
||||||
|
not_null<HistoryItem*> addNewPhoto(
|
||||||
|
MsgId id,
|
||||||
|
MTPDmessage::Flags flags,
|
||||||
|
UserId viaBotId,
|
||||||
|
MsgId replyTo,
|
||||||
|
TimeId date,
|
||||||
|
UserId from,
|
||||||
|
const QString &postAuthor,
|
||||||
|
not_null<PhotoData*> photo,
|
||||||
|
const TextWithEntities &caption,
|
||||||
|
const MTPReplyMarkup &markup);
|
||||||
|
not_null<HistoryItem*> addNewGame(
|
||||||
|
MsgId id,
|
||||||
|
MTPDmessage::Flags flags,
|
||||||
|
UserId viaBotId,
|
||||||
|
MsgId replyTo,
|
||||||
|
TimeId date,
|
||||||
|
UserId from,
|
||||||
|
const QString &postAuthor,
|
||||||
|
not_null<GameData*> game,
|
||||||
|
const MTPReplyMarkup &markup);
|
||||||
|
|
||||||
// Used only internally and for channel admin log.
|
// Used only internally and for channel admin log.
|
||||||
HistoryItem *createItem(
|
HistoryItem *createItem(
|
||||||
|
@ -180,6 +221,7 @@ public:
|
||||||
MsgId loadAroundId() const;
|
MsgId loadAroundId() const;
|
||||||
|
|
||||||
int unreadCount() const;
|
int unreadCount() const;
|
||||||
|
bool unreadCountKnown() const;
|
||||||
void setUnreadCount(int newUnreadCount);
|
void setUnreadCount(int newUnreadCount);
|
||||||
bool mute() const;
|
bool mute() const;
|
||||||
bool changeMute(bool newMute);
|
bool changeMute(bool newMute);
|
||||||
|
@ -376,11 +418,6 @@ private:
|
||||||
|
|
||||||
void clearBlocks(bool leaveItems);
|
void clearBlocks(bool leaveItems);
|
||||||
|
|
||||||
not_null<HistoryItem*> createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, UserId from, const QString &postAuthor, HistoryMessage *msg);
|
|
||||||
not_null<HistoryItem*> createItemDocument(MsgId id, MTPDmessage::Flags flags, UserId viaBotId, MsgId replyTo, QDateTime date, UserId from, const QString &postAuthor, DocumentData *doc, const TextWithEntities &caption, const MTPReplyMarkup &markup);
|
|
||||||
not_null<HistoryItem*> createItemPhoto(MsgId id, MTPDmessage::Flags flags, UserId viaBotId, MsgId replyTo, QDateTime date, UserId from, const QString &postAuthor, PhotoData *photo, const TextWithEntities &caption, const MTPReplyMarkup &markup);
|
|
||||||
not_null<HistoryItem*> createItemGame(MsgId id, MTPDmessage::Flags flags, UserId viaBotId, MsgId replyTo, QDateTime date, UserId from, const QString &postAuthor, GameData *game, const MTPReplyMarkup &markup);
|
|
||||||
|
|
||||||
not_null<HistoryItem*> addNewItem(
|
not_null<HistoryItem*> addNewItem(
|
||||||
not_null<HistoryItem*> item,
|
not_null<HistoryItem*> item,
|
||||||
bool unread);
|
bool unread);
|
||||||
|
|
|
@ -731,7 +731,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||||
} else {
|
} else {
|
||||||
HistoryView::ServiceMessagePainter::paintDate(
|
HistoryView::ServiceMessagePainter::paintDate(
|
||||||
p,
|
p,
|
||||||
view->data()->date,
|
view->dateTime(),
|
||||||
dateY,
|
dateY,
|
||||||
_contentWidth);
|
_contentWidth);
|
||||||
}
|
}
|
||||||
|
@ -1430,7 +1430,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
_widget->replyToMessage(itemId);
|
_widget->replyToMessage(itemId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (item->allowsEdit(::date(unixtime()))) {
|
if (item->allowsEdit(unixtime())) {
|
||||||
_menu->addAction(lang(lng_context_edit_msg), [=] {
|
_menu->addAction(lang(lng_context_edit_msg), [=] {
|
||||||
_widget->editMessage(itemId);
|
_widget->editMessage(itemId);
|
||||||
});
|
});
|
||||||
|
@ -1693,11 +1693,17 @@ void HistoryInner::savePhotoToFile(not_null<PhotoData*> photo) {
|
||||||
if (!photo->date || !photo->loaded()) return;
|
if (!photo->date || !photo->loaded()) return;
|
||||||
|
|
||||||
auto filter = qsl("JPEG Image (*.jpg);;") + FileDialog::AllFilesFilter();
|
auto filter = qsl("JPEG Image (*.jpg);;") + FileDialog::AllFilesFilter();
|
||||||
FileDialog::GetWritePath(lang(lng_save_photo), filter, filedialogDefaultName(qsl("photo"), qsl(".jpg")), base::lambda_guarded(this, [this, photo](const QString &result) {
|
FileDialog::GetWritePath(
|
||||||
if (!result.isEmpty()) {
|
lang(lng_save_photo),
|
||||||
photo->full->pix().toImage().save(result, "JPG");
|
filter,
|
||||||
}
|
filedialogDefaultName(
|
||||||
}));
|
qsl("photo"),
|
||||||
|
qsl(".jpg")),
|
||||||
|
base::lambda_guarded(this, [this, photo](const QString &result) {
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
photo->full->pix().toImage().save(result, "JPG");
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::copyContextImage(not_null<PhotoData*> photo) {
|
void HistoryInner::copyContextImage(not_null<PhotoData*> photo) {
|
||||||
|
@ -1797,7 +1803,7 @@ TextWithEntities HistoryInner::getSelectedText() const {
|
||||||
const auto wrapItem = [&](
|
const auto wrapItem = [&](
|
||||||
not_null<HistoryItem*> item,
|
not_null<HistoryItem*> item,
|
||||||
TextWithEntities &&unwrapped) {
|
TextWithEntities &&unwrapped) {
|
||||||
auto time = item->date.toString(timeFormat);
|
auto time = ItemDateTime(item).toString(timeFormat);
|
||||||
auto part = TextWithEntities();
|
auto part = TextWithEntities();
|
||||||
auto size = item->author()->name.size()
|
auto size = item->author()->name.size()
|
||||||
+ time.size()
|
+ time.size()
|
||||||
|
@ -1886,7 +1892,7 @@ void HistoryInner::recountHistoryGeometry() {
|
||||||
_historySkipHeight = 0;
|
_historySkipHeight = 0;
|
||||||
if (_migrated) {
|
if (_migrated) {
|
||||||
if (!_migrated->isEmpty() && !_history->isEmpty() && _migrated->loadedAtBottom() && _history->loadedAtTop()) {
|
if (!_migrated->isEmpty() && !_history->isEmpty() && _migrated->loadedAtBottom() && _history->loadedAtTop()) {
|
||||||
if (_migrated->blocks.back()->messages.back()->data()->date.date() == _history->blocks.front()->messages.front()->data()->date.date()) {
|
if (_migrated->blocks.back()->messages.back()->dateTime().date() == _history->blocks.front()->messages.front()->dateTime().date()) {
|
||||||
if (_migrated->blocks.back()->messages.back()->data()->isGroupMigrate() && _history->blocks.front()->messages.front()->data()->isGroupMigrate()) {
|
if (_migrated->blocks.back()->messages.back()->data()->isGroupMigrate() && _history->blocks.front()->messages.front()->data()->isGroupMigrate()) {
|
||||||
_historySkipHeight += _history->blocks.front()->messages.front()->height();
|
_historySkipHeight += _history->blocks.front()->messages.front()->height();
|
||||||
} else {
|
} else {
|
||||||
|
@ -2379,7 +2385,7 @@ void HistoryInner::mouseActionUpdate() {
|
||||||
if (const auto date = view->Get<HistoryView::DateBadge>()) {
|
if (const auto date = view->Get<HistoryView::DateBadge>()) {
|
||||||
dateWidth = date->width;
|
dateWidth = date->width;
|
||||||
} else {
|
} else {
|
||||||
dateWidth = st::msgServiceFont->width(langDayOfMonthFull(item->date.date()));
|
dateWidth = st::msgServiceFont->width(langDayOfMonthFull(view->dateTime().date()));
|
||||||
}
|
}
|
||||||
dateWidth += st::msgServicePadding.left() + st::msgServicePadding.right();
|
dateWidth += st::msgServicePadding.left() + st::msgServicePadding.right();
|
||||||
auto dateLeft = st::msgServiceMargin.left();
|
auto dateLeft = st::msgServiceMargin.left();
|
||||||
|
@ -2393,9 +2399,9 @@ void HistoryInner::mouseActionUpdate() {
|
||||||
|
|
||||||
if (point.x() >= dateLeft && point.x() < dateLeft + dateWidth) {
|
if (point.x() >= dateLeft && point.x() < dateLeft + dateWidth) {
|
||||||
if (!_scrollDateLink) {
|
if (!_scrollDateLink) {
|
||||||
_scrollDateLink = std::make_shared<DateClickHandler>(item->history()->peer, item->date.date());
|
_scrollDateLink = std::make_shared<DateClickHandler>(item->history()->peer, view->dateTime().date());
|
||||||
} else {
|
} else {
|
||||||
static_cast<DateClickHandler*>(_scrollDateLink.get())->setDate(item->date.date());
|
static_cast<DateClickHandler*>(_scrollDateLink.get())->setDate(view->dateTime().date());
|
||||||
}
|
}
|
||||||
dragState = TextState(
|
dragState = TextState(
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -2924,14 +2930,21 @@ QString HistoryInner::tooltipText() const {
|
||||||
if (_mouseCursorState == CursorState::Date
|
if (_mouseCursorState == CursorState::Date
|
||||||
&& _mouseAction == MouseAction::None) {
|
&& _mouseAction == MouseAction::None) {
|
||||||
if (const auto view = App::hoveredItem()) {
|
if (const auto view = App::hoveredItem()) {
|
||||||
auto dateText = view->data()->date.toString(
|
auto dateText = view->dateTime().toString(
|
||||||
QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
||||||
auto editedDate = view->displayedEditDate();
|
if (const auto editedDate = view->displayedEditDate()) {
|
||||||
if (!editedDate.isNull()) {
|
dateText += '\n' + lng_edited_date(
|
||||||
dateText += '\n' + lng_edited_date(lt_date, editedDate.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat)));
|
lt_date,
|
||||||
|
ParseDateTime(editedDate).toString(
|
||||||
|
QLocale::system().dateTimeFormat(
|
||||||
|
QLocale::LongFormat)));
|
||||||
}
|
}
|
||||||
if (const auto forwarded = view->data()->Get<HistoryMessageForwarded>()) {
|
if (const auto forwarded = view->data()->Get<HistoryMessageForwarded>()) {
|
||||||
dateText += '\n' + lng_forwarded_date(lt_date, forwarded->originalDate.toString(QLocale::system().dateTimeFormat(QLocale::LongFormat)));
|
dateText += '\n' + lng_forwarded_date(
|
||||||
|
lt_date,
|
||||||
|
ParseDateTime(forwarded->originalDate).toString(
|
||||||
|
QLocale::system().dateTimeFormat(
|
||||||
|
QLocale::LongFormat)));
|
||||||
}
|
}
|
||||||
return dateText;
|
return dateText;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ not_null<HistoryItem*> CreateUnsupportedMessage(
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from) {
|
UserId from) {
|
||||||
const auto siteLink = qsl("https://desktop.telegram.org");
|
const auto siteLink = qsl("https://desktop.telegram.org");
|
||||||
auto text = TextWithEntities{
|
auto text = TextWithEntities{
|
||||||
|
@ -75,16 +75,20 @@ HistoryItem::HistoryItem(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId id,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from)
|
UserId from)
|
||||||
: id(id)
|
: id(id)
|
||||||
, date(date)
|
, _date(date)
|
||||||
, _history(history)
|
, _history(history)
|
||||||
, _from(from ? App::user(from) : history->peer)
|
, _from(from ? App::user(from) : history->peer)
|
||||||
, _flags(flags) {
|
, _flags(flags) {
|
||||||
App::historyRegItem(this);
|
App::historyRegItem(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimeId HistoryItem::date() const {
|
||||||
|
return _date;
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryItem::finishEdition(int oldKeyboardTop) {
|
void HistoryItem::finishEdition(int oldKeyboardTop) {
|
||||||
Auth().data().requestItemViewRefresh(this);
|
Auth().data().requestItemViewRefresh(this);
|
||||||
invalidateChatsListEntry();
|
invalidateChatsListEntry();
|
||||||
|
@ -153,8 +157,7 @@ void HistoryItem::finishEditionToEmpty() {
|
||||||
|
|
||||||
bool HistoryItem::isMediaUnread() const {
|
bool HistoryItem::isMediaUnread() const {
|
||||||
if (!mentionsMe() && _history->peer->isChannel()) {
|
if (!mentionsMe() && _history->peer->isChannel()) {
|
||||||
auto now = ::date(unixtime());
|
auto passed = unixtime() - date();
|
||||||
auto passed = date.secsTo(now);
|
|
||||||
if (passed >= Global::ChannelsReadMediaPeriod()) {
|
if (passed >= Global::ChannelsReadMediaPeriod()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -332,7 +335,7 @@ bool HistoryItem::allowsForward() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryItem::allowsEdit(const QDateTime &now) const {
|
bool HistoryItem::allowsEdit(TimeId now) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,9 +360,11 @@ bool HistoryItem::canDelete() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryItem::canDeleteForEveryone(const QDateTime &cur) const {
|
bool HistoryItem::canDeleteForEveryone(TimeId now) const {
|
||||||
auto messageToMyself = _history->peer->isSelf();
|
auto messageToMyself = _history->peer->isSelf();
|
||||||
auto messageTooOld = messageToMyself ? false : (date.secsTo(cur) >= Global::EditTimeLimit());
|
auto messageTooOld = messageToMyself
|
||||||
|
? false
|
||||||
|
: (now >= date() + Global::EditTimeLimit());
|
||||||
if (id < 0 || messageToMyself || messageTooOld || isPost()) {
|
if (id < 0 || messageToMyself || messageTooOld || isPost()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -443,7 +448,7 @@ ChannelId HistoryItem::channelId() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Data::MessagePosition HistoryItem::position() const {
|
Data::MessagePosition HistoryItem::position() const {
|
||||||
return Data::MessagePosition(toServerTime(date.toTime_t()).v, fullId());
|
return Data::MessagePosition(date(), fullId());
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgId HistoryItem::replyToId() const {
|
MsgId HistoryItem::replyToId() const {
|
||||||
|
@ -457,11 +462,11 @@ not_null<PeerData*> HistoryItem::author() const {
|
||||||
return isPost() ? history()->peer : from();
|
return isPost() ? history()->peer : from();
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime HistoryItem::dateOriginal() const {
|
TimeId HistoryItem::dateOriginal() const {
|
||||||
if (const auto forwarded = Get<HistoryMessageForwarded>()) {
|
if (const auto forwarded = Get<HistoryMessageForwarded>()) {
|
||||||
return forwarded->originalDate;
|
return forwarded->originalDate;
|
||||||
}
|
}
|
||||||
return date;
|
return date();
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<PeerData*> HistoryItem::senderOriginal() const {
|
not_null<PeerData*> HistoryItem::senderOriginal() const {
|
||||||
|
@ -621,6 +626,10 @@ HistoryItem::~HistoryItem() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDateTime ItemDateTime(not_null<const HistoryItem*> item) {
|
||||||
|
return ParseDateTime(item->date());
|
||||||
|
}
|
||||||
|
|
||||||
ClickHandlerPtr goToMessageClickHandler(
|
ClickHandlerPtr goToMessageClickHandler(
|
||||||
not_null<HistoryItem*> item,
|
not_null<HistoryItem*> item,
|
||||||
FullMsgId returnToId) {
|
FullMsgId returnToId) {
|
||||||
|
@ -658,7 +667,7 @@ not_null<HistoryItem*> HistoryItem::Create(
|
||||||
const auto text = HistoryService::PreparedText {
|
const auto text = HistoryService::PreparedText {
|
||||||
lang(lng_message_empty)
|
lang(lng_message_empty)
|
||||||
};
|
};
|
||||||
return new HistoryService(history, data.vid.v, ::date(), text);
|
return new HistoryService(history, data.vid.v, TimeId(0), text);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_message: {
|
case mtpc_message: {
|
||||||
|
@ -750,7 +759,7 @@ not_null<HistoryItem*> HistoryItem::Create(
|
||||||
data.vflags.v,
|
data.vflags.v,
|
||||||
data.vreply_to_msg_id.v,
|
data.vreply_to_msg_id.v,
|
||||||
data.vvia_bot_id.v,
|
data.vvia_bot_id.v,
|
||||||
::date(data.vdate),
|
data.vdate.v,
|
||||||
data.vfrom_id.v);
|
data.vfrom_id.v);
|
||||||
} else if (badMedia == MediaCheckResult::Empty) {
|
} else if (badMedia == MediaCheckResult::Empty) {
|
||||||
const auto text = HistoryService::PreparedText {
|
const auto text = HistoryService::PreparedText {
|
||||||
|
@ -759,7 +768,7 @@ not_null<HistoryItem*> HistoryItem::Create(
|
||||||
return new HistoryService(
|
return new HistoryService(
|
||||||
history,
|
history,
|
||||||
data.vid.v,
|
data.vid.v,
|
||||||
::date(data.vdate),
|
data.vdate.v,
|
||||||
text,
|
text,
|
||||||
data.vflags.v,
|
data.vflags.v,
|
||||||
data.has_from_id() ? data.vfrom_id.v : UserId(0));
|
data.has_from_id() ? data.vfrom_id.v : UserId(0));
|
||||||
|
|
|
@ -207,9 +207,9 @@ public:
|
||||||
bool isPinned() const;
|
bool isPinned() const;
|
||||||
bool canPin() const;
|
bool canPin() const;
|
||||||
virtual bool allowsForward() const;
|
virtual bool allowsForward() const;
|
||||||
virtual bool allowsEdit(const QDateTime &now) const;
|
virtual bool allowsEdit(TimeId now) const;
|
||||||
bool canDelete() const;
|
bool canDelete() const;
|
||||||
bool canDeleteForEveryone(const QDateTime &cur) const;
|
bool canDeleteForEveryone(TimeId now) const;
|
||||||
bool suggestBanReport() const;
|
bool suggestBanReport() const;
|
||||||
bool suggestDeleteAllReport() const;
|
bool suggestDeleteAllReport() const;
|
||||||
|
|
||||||
|
@ -217,13 +217,13 @@ public:
|
||||||
QString directLink() const;
|
QString directLink() const;
|
||||||
|
|
||||||
MsgId id;
|
MsgId id;
|
||||||
QDateTime date;
|
|
||||||
|
|
||||||
ChannelId channelId() const;
|
ChannelId channelId() const;
|
||||||
FullMsgId fullId() const {
|
FullMsgId fullId() const {
|
||||||
return FullMsgId(channelId(), id);
|
return FullMsgId(channelId(), id);
|
||||||
}
|
}
|
||||||
Data::MessagePosition position() const;
|
Data::MessagePosition position() const;
|
||||||
|
TimeId date() const;
|
||||||
|
|
||||||
Data::Media *media() const {
|
Data::Media *media() const {
|
||||||
return _media.get();
|
return _media.get();
|
||||||
|
@ -244,7 +244,7 @@ public:
|
||||||
|
|
||||||
not_null<PeerData*> author() const;
|
not_null<PeerData*> author() const;
|
||||||
|
|
||||||
QDateTime dateOriginal() const;
|
TimeId dateOriginal() const;
|
||||||
not_null<PeerData*> senderOriginal() const;
|
not_null<PeerData*> senderOriginal() const;
|
||||||
not_null<PeerData*> fromOriginal() const;
|
not_null<PeerData*> fromOriginal() const;
|
||||||
QString authorOriginal() const;
|
QString authorOriginal() const;
|
||||||
|
@ -264,7 +264,7 @@ protected:
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId id,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from);
|
UserId from);
|
||||||
|
|
||||||
virtual void markMediaAsReadHook() {
|
virtual void markMediaAsReadHook() {
|
||||||
|
@ -296,6 +296,8 @@ protected:
|
||||||
std::unique_ptr<Data::Media> _media;
|
std::unique_ptr<Data::Media> _media;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
TimeId _date = 0;
|
||||||
|
|
||||||
HistoryView::Element *_mainView = nullptr;
|
HistoryView::Element *_mainView = nullptr;
|
||||||
friend class HistoryView::Element;
|
friend class HistoryView::Element;
|
||||||
|
|
||||||
|
@ -303,6 +305,8 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QDateTime ItemDateTime(not_null<const HistoryItem*> item);
|
||||||
|
|
||||||
ClickHandlerPtr goToMessageClickHandler(
|
ClickHandlerPtr goToMessageClickHandler(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
MsgId msgId,
|
MsgId msgId,
|
||||||
|
|
|
@ -45,14 +45,14 @@ struct HistoryMessageEdited : public RuntimeComponent<HistoryMessageEdited, Hist
|
||||||
void refresh(const QString &date, bool displayed);
|
void refresh(const QString &date, bool displayed);
|
||||||
int maxWidth() const;
|
int maxWidth() const;
|
||||||
|
|
||||||
QDateTime date;
|
TimeId date = 0;
|
||||||
Text text;
|
Text text;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HistoryMessageForwarded : public RuntimeComponent<HistoryMessageForwarded, HistoryItem> {
|
struct HistoryMessageForwarded : public RuntimeComponent<HistoryMessageForwarded, HistoryItem> {
|
||||||
void create(const HistoryMessageVia *via) const;
|
void create(const HistoryMessageVia *via) const;
|
||||||
|
|
||||||
QDateTime originalDate;
|
TimeId originalDate = 0;
|
||||||
PeerData *originalSender = nullptr;
|
PeerData *originalSender = nullptr;
|
||||||
QString originalAuthor;
|
QString originalAuthor;
|
||||||
MsgId originalId = 0;
|
MsgId originalId = 0;
|
||||||
|
|
|
@ -3144,7 +3144,7 @@ HistoryCall::HistoryCall(
|
||||||
|
|
||||||
const auto item = parent->data();
|
const auto item = parent->data();
|
||||||
_text = Data::MediaCall::Text(item, _reason);
|
_text = Data::MediaCall::Text(item, _reason);
|
||||||
_status = item->date.time().toString(cTimeFormat());
|
_status = parent->dateTime().time().toString(cTimeFormat());
|
||||||
if (_duration) {
|
if (_duration) {
|
||||||
if (_reason != FinishReason::Missed
|
if (_reason != FinishReason::Missed
|
||||||
&& _reason != FinishReason::Busy) {
|
&& _reason != FinishReason::Busy) {
|
||||||
|
|
|
@ -271,8 +271,8 @@ struct HistoryMessage::CreateConfig {
|
||||||
PeerId savedFromPeer = 0;
|
PeerId savedFromPeer = 0;
|
||||||
MsgId savedFromMsgId = 0;
|
MsgId savedFromMsgId = 0;
|
||||||
QString authorOriginal;
|
QString authorOriginal;
|
||||||
QDateTime originalDate;
|
TimeId originalDate = 0;
|
||||||
QDateTime editDate;
|
TimeId editDate = 0;
|
||||||
|
|
||||||
// For messages created from MTP structs.
|
// For messages created from MTP structs.
|
||||||
const MTPReplyMarkup *mtpMarkup = nullptr;
|
const MTPReplyMarkup *mtpMarkup = nullptr;
|
||||||
|
@ -283,13 +283,18 @@ struct HistoryMessage::CreateConfig {
|
||||||
|
|
||||||
HistoryMessage::HistoryMessage(
|
HistoryMessage::HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
const MTPDmessage &msg)
|
const MTPDmessage &data)
|
||||||
: HistoryItem(history, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) {
|
: HistoryItem(
|
||||||
|
history,
|
||||||
|
data.vid.v,
|
||||||
|
data.vflags.v,
|
||||||
|
data.vdate.v,
|
||||||
|
data.has_from_id() ? data.vfrom_id.v : UserId(0)) {
|
||||||
CreateConfig config;
|
CreateConfig config;
|
||||||
|
|
||||||
if (msg.has_fwd_from() && msg.vfwd_from.type() == mtpc_messageFwdHeader) {
|
if (data.has_fwd_from() && data.vfwd_from.type() == mtpc_messageFwdHeader) {
|
||||||
auto &f = msg.vfwd_from.c_messageFwdHeader();
|
auto &f = data.vfwd_from.c_messageFwdHeader();
|
||||||
config.originalDate = ::date(f.vdate);
|
config.originalDate = f.vdate.v;
|
||||||
if (f.has_from_id() || f.has_channel_id()) {
|
if (f.has_from_id() || f.has_channel_id()) {
|
||||||
config.senderOriginal = f.has_channel_id()
|
config.senderOriginal = f.has_channel_id()
|
||||||
? peerFromChannel(f.vchannel_id)
|
? peerFromChannel(f.vchannel_id)
|
||||||
|
@ -302,45 +307,50 @@ HistoryMessage::HistoryMessage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msg.has_reply_to_msg_id()) config.replyTo = msg.vreply_to_msg_id.v;
|
if (data.has_reply_to_msg_id()) config.replyTo = data.vreply_to_msg_id.v;
|
||||||
if (msg.has_via_bot_id()) config.viaBotId = msg.vvia_bot_id.v;
|
if (data.has_via_bot_id()) config.viaBotId = data.vvia_bot_id.v;
|
||||||
if (msg.has_views()) config.viewsCount = msg.vviews.v;
|
if (data.has_views()) config.viewsCount = data.vviews.v;
|
||||||
if (msg.has_reply_markup()) config.mtpMarkup = &msg.vreply_markup;
|
if (data.has_reply_markup()) config.mtpMarkup = &data.vreply_markup;
|
||||||
if (msg.has_edit_date()) config.editDate = ::date(msg.vedit_date);
|
if (data.has_edit_date()) config.editDate = data.vedit_date.v;
|
||||||
if (msg.has_post_author()) config.author = qs(msg.vpost_author);
|
if (data.has_post_author()) config.author = qs(data.vpost_author);
|
||||||
|
|
||||||
createComponents(config);
|
createComponents(config);
|
||||||
|
|
||||||
if (msg.has_media()) {
|
if (data.has_media()) {
|
||||||
setMedia(msg.vmedia);
|
setMedia(data.vmedia);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto text = TextUtilities::Clean(qs(msg.vmessage));
|
auto text = TextUtilities::Clean(qs(data.vmessage));
|
||||||
auto entities = msg.has_entities()
|
auto entities = data.has_entities()
|
||||||
? TextUtilities::EntitiesFromMTP(msg.ventities.v)
|
? TextUtilities::EntitiesFromMTP(data.ventities.v)
|
||||||
: EntitiesInText();
|
: EntitiesInText();
|
||||||
setText({ text, entities });
|
setText({ text, entities });
|
||||||
|
|
||||||
if (msg.has_grouped_id()) {
|
if (data.has_grouped_id()) {
|
||||||
setGroupId(MessageGroupId::FromRaw(msg.vgrouped_id.v));
|
setGroupId(MessageGroupId::FromRaw(data.vgrouped_id.v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryMessage::HistoryMessage(
|
HistoryMessage::HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
const MTPDmessageService &msg)
|
const MTPDmessageService &data)
|
||||||
: HistoryItem(history, msg.vid.v, mtpCastFlags(msg.vflags.v), ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) {
|
: HistoryItem(
|
||||||
|
history,
|
||||||
|
data.vid.v,
|
||||||
|
mtpCastFlags(data.vflags.v),
|
||||||
|
data.vdate.v,
|
||||||
|
data.has_from_id() ? data.vfrom_id.v : UserId(0)) {
|
||||||
CreateConfig config;
|
CreateConfig config;
|
||||||
|
|
||||||
if (msg.has_reply_to_msg_id()) config.replyTo = msg.vreply_to_msg_id.v;
|
if (data.has_reply_to_msg_id()) config.replyTo = data.vreply_to_msg_id.v;
|
||||||
|
|
||||||
createComponents(config);
|
createComponents(config);
|
||||||
|
|
||||||
switch (msg.vaction.type()) {
|
switch (data.vaction.type()) {
|
||||||
case mtpc_messageActionPhoneCall: {
|
case mtpc_messageActionPhoneCall: {
|
||||||
_media = std::make_unique<Data::MediaCall>(
|
_media = std::make_unique<Data::MediaCall>(
|
||||||
this,
|
this,
|
||||||
msg.vaction.c_messageActionPhoneCall());
|
data.vaction.c_messageActionPhoneCall());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: Unexpected("Service message action type in HistoryMessage.");
|
default: Unexpected("Service message action type in HistoryMessage.");
|
||||||
|
@ -353,21 +363,26 @@ HistoryMessage::HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId id,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
not_null<HistoryMessage*> fwd)
|
not_null<HistoryMessage*> original)
|
||||||
: HistoryItem(history, id, NewForwardedFlags(history->peer, from, fwd) | flags, date, from) {
|
: HistoryItem(
|
||||||
|
history,
|
||||||
|
id,
|
||||||
|
NewForwardedFlags(history->peer, from, original) | flags,
|
||||||
|
date,
|
||||||
|
from) {
|
||||||
CreateConfig config;
|
CreateConfig config;
|
||||||
|
|
||||||
if (fwd->Has<HistoryMessageForwarded>() || !fwd->history()->peer->isSelf()) {
|
if (original->Has<HistoryMessageForwarded>() || !original->history()->peer->isSelf()) {
|
||||||
// Server doesn't add "fwd_from" to non-forwarded messages from chat with yourself.
|
// Server doesn't add "fwd_from" to non-forwarded messages from chat with yourself.
|
||||||
config.originalDate = fwd->dateOriginal();
|
config.originalDate = original->dateOriginal();
|
||||||
auto senderOriginal = fwd->senderOriginal();
|
auto senderOriginal = original->senderOriginal();
|
||||||
config.senderOriginal = senderOriginal->id;
|
config.senderOriginal = senderOriginal->id;
|
||||||
config.authorOriginal = fwd->authorOriginal();
|
config.authorOriginal = original->authorOriginal();
|
||||||
if (senderOriginal->isChannel()) {
|
if (senderOriginal->isChannel()) {
|
||||||
config.originalId = fwd->idOriginal();
|
config.originalId = original->idOriginal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (history->peer->isSelf()) {
|
if (history->peer->isSelf()) {
|
||||||
|
@ -379,16 +394,16 @@ HistoryMessage::HistoryMessage(
|
||||||
// config.savedFromPeer = config.senderOriginal;
|
// config.savedFromPeer = config.senderOriginal;
|
||||||
// config.savedFromMsgId = config.originalId;
|
// config.savedFromMsgId = config.originalId;
|
||||||
//} else {
|
//} else {
|
||||||
config.savedFromPeer = fwd->history()->peer->id;
|
config.savedFromPeer = original->history()->peer->id;
|
||||||
config.savedFromMsgId = fwd->id;
|
config.savedFromMsgId = original->id;
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
if (flags & MTPDmessage::Flag::f_post_author) {
|
if (flags & MTPDmessage::Flag::f_post_author) {
|
||||||
config.author = postAuthor;
|
config.author = postAuthor;
|
||||||
}
|
}
|
||||||
auto fwdViaBot = fwd->viaBot();
|
auto fwdViaBot = original->viaBot();
|
||||||
if (fwdViaBot) config.viaBotId = peerToUser(fwdViaBot->id);
|
if (fwdViaBot) config.viaBotId = peerToUser(fwdViaBot->id);
|
||||||
int fwdViewsCount = fwd->viewsCount();
|
int fwdViewsCount = original->viewsCount();
|
||||||
if (fwdViewsCount > 0) {
|
if (fwdViewsCount > 0) {
|
||||||
config.viewsCount = fwdViewsCount;
|
config.viewsCount = fwdViewsCount;
|
||||||
} else if (isPost()) {
|
} else if (isPost()) {
|
||||||
|
@ -396,9 +411,9 @@ HistoryMessage::HistoryMessage(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy inline keyboard when forwarding messages with a game.
|
// Copy inline keyboard when forwarding messages with a game.
|
||||||
auto mediaOriginal = fwd->media();
|
auto mediaOriginal = original->media();
|
||||||
if (mediaOriginal && mediaOriginal->game()) {
|
if (mediaOriginal && mediaOriginal->game()) {
|
||||||
config.inlineMarkup = fwd->inlineReplyMarkup();
|
config.inlineMarkup = original->inlineReplyMarkup();
|
||||||
}
|
}
|
||||||
|
|
||||||
createComponents(config);
|
createComponents(config);
|
||||||
|
@ -416,7 +431,7 @@ HistoryMessage::HistoryMessage(
|
||||||
if (mediaOriginal && !ignoreMedia()) {
|
if (mediaOriginal && !ignoreMedia()) {
|
||||||
_media = mediaOriginal->clone(this);
|
_media = mediaOriginal->clone(this);
|
||||||
}
|
}
|
||||||
setText(fwd->originalText());
|
setText(original->originalText());
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryMessage::HistoryMessage(
|
HistoryMessage::HistoryMessage(
|
||||||
|
@ -425,7 +440,7 @@ HistoryMessage::HistoryMessage(
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
const TextWithEntities &textWithEntities)
|
const TextWithEntities &textWithEntities)
|
||||||
|
@ -437,17 +452,17 @@ HistoryMessage::HistoryMessage(
|
||||||
|
|
||||||
HistoryMessage::HistoryMessage(
|
HistoryMessage::HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
const TextWithEntities &caption,
|
const TextWithEntities &caption,
|
||||||
const MTPReplyMarkup &markup)
|
const MTPReplyMarkup &markup)
|
||||||
: HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) {
|
: HistoryItem(history, id, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) {
|
||||||
createComponentsHelper(flags, replyTo, viaBotId, postAuthor, markup);
|
createComponentsHelper(flags, replyTo, viaBotId, postAuthor, markup);
|
||||||
|
|
||||||
_media = std::make_unique<Data::MediaFile>(this, document);
|
_media = std::make_unique<Data::MediaFile>(this, document);
|
||||||
|
@ -456,17 +471,17 @@ HistoryMessage::HistoryMessage(
|
||||||
|
|
||||||
HistoryMessage::HistoryMessage(
|
HistoryMessage::HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
const TextWithEntities &caption,
|
const TextWithEntities &caption,
|
||||||
const MTPReplyMarkup &markup)
|
const MTPReplyMarkup &markup)
|
||||||
: HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) {
|
: HistoryItem(history, id, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) {
|
||||||
createComponentsHelper(flags, replyTo, viaBotId, postAuthor, markup);
|
createComponentsHelper(flags, replyTo, viaBotId, postAuthor, markup);
|
||||||
|
|
||||||
_media = std::make_unique<Data::MediaPhoto>(this, photo);
|
_media = std::make_unique<Data::MediaPhoto>(this, photo);
|
||||||
|
@ -475,16 +490,16 @@ HistoryMessage::HistoryMessage(
|
||||||
|
|
||||||
HistoryMessage::HistoryMessage(
|
HistoryMessage::HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
not_null<GameData*> game,
|
not_null<GameData*> game,
|
||||||
const MTPReplyMarkup &markup)
|
const MTPReplyMarkup &markup)
|
||||||
: HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) {
|
: HistoryItem(history, id, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) {
|
||||||
createComponentsHelper(flags, replyTo, viaBotId, postAuthor, markup);
|
createComponentsHelper(flags, replyTo, viaBotId, postAuthor, markup);
|
||||||
|
|
||||||
_media = std::make_unique<Data::MediaGame>(this, game);
|
_media = std::make_unique<Data::MediaGame>(this, game);
|
||||||
|
@ -564,7 +579,7 @@ bool HistoryMessage::allowsForward() const {
|
||||||
return !_media || _media->allowsForward();
|
return !_media || _media->allowsForward();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryMessage::allowsEdit(const QDateTime &now) const {
|
bool HistoryMessage::allowsEdit(TimeId now) const {
|
||||||
const auto peer = _history->peer;
|
const auto peer = _history->peer;
|
||||||
const auto messageToMyself = peer->isSelf();
|
const auto messageToMyself = peer->isSelf();
|
||||||
const auto canPinInMegagroup = [&] {
|
const auto canPinInMegagroup = [&] {
|
||||||
|
@ -575,7 +590,7 @@ bool HistoryMessage::allowsEdit(const QDateTime &now) const {
|
||||||
}();
|
}();
|
||||||
const auto messageTooOld = (messageToMyself || canPinInMegagroup)
|
const auto messageTooOld = (messageToMyself || canPinInMegagroup)
|
||||||
? false
|
? false
|
||||||
: (date.secsTo(now) >= Global::EditTimeLimit());
|
: (now >= date() + Global::EditTimeLimit());
|
||||||
if (id < 0 || messageTooOld) {
|
if (id < 0 || messageTooOld) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -626,7 +641,7 @@ void HistoryMessage::createComponents(const CreateConfig &config) {
|
||||||
}
|
}
|
||||||
return (config.inlineMarkup != nullptr);
|
return (config.inlineMarkup != nullptr);
|
||||||
};
|
};
|
||||||
if (!config.editDate.isNull()) {
|
if (config.editDate != TimeId(0)) {
|
||||||
mask |= HistoryMessageEdited::Bit();
|
mask |= HistoryMessageEdited::Bit();
|
||||||
}
|
}
|
||||||
if (config.senderOriginal) {
|
if (config.senderOriginal) {
|
||||||
|
@ -866,7 +881,7 @@ void HistoryMessage::applyEdition(const MTPDmessage &message) {
|
||||||
AddComponents(HistoryMessageEdited::Bit());
|
AddComponents(HistoryMessageEdited::Bit());
|
||||||
}
|
}
|
||||||
auto edited = Get<HistoryMessageEdited>();
|
auto edited = Get<HistoryMessageEdited>();
|
||||||
edited->date = ::date(message.vedit_date);
|
edited->date = message.vedit_date.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextWithEntities textWithEntities = { qs(message.vmessage), EntitiesInText() };
|
TextWithEntities textWithEntities = { qs(message.vmessage), EntitiesInText() };
|
||||||
|
|
|
@ -29,35 +29,35 @@ class HistoryMessage
|
||||||
public:
|
public:
|
||||||
HistoryMessage(
|
HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
const MTPDmessage &msg);
|
const MTPDmessage &data);
|
||||||
HistoryMessage(
|
HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
const MTPDmessageService &msg);
|
const MTPDmessageService &data);
|
||||||
HistoryMessage(
|
HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
not_null<HistoryMessage*> fwd); // local forwarded
|
not_null<HistoryMessage*> original); // local forwarded
|
||||||
HistoryMessage(
|
HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
const TextWithEntities &textWithEntities); // local message
|
const TextWithEntities &textWithEntities); // local message
|
||||||
HistoryMessage(
|
HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
|
@ -65,11 +65,11 @@ public:
|
||||||
const MTPReplyMarkup &markup); // local document
|
const MTPReplyMarkup &markup); // local document
|
||||||
HistoryMessage(
|
HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
|
@ -77,11 +77,11 @@ public:
|
||||||
const MTPReplyMarkup &markup); // local photo
|
const MTPReplyMarkup &markup); // local photo
|
||||||
HistoryMessage(
|
HistoryMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
MsgId id,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
MsgId replyTo,
|
MsgId replyTo,
|
||||||
UserId viaBotId,
|
UserId viaBotId,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
UserId from,
|
UserId from,
|
||||||
const QString &postAuthor,
|
const QString &postAuthor,
|
||||||
not_null<GameData*> game,
|
not_null<GameData*> game,
|
||||||
|
@ -95,7 +95,7 @@ public:
|
||||||
const MTPMessageMedia &media);
|
const MTPMessageMedia &media);
|
||||||
|
|
||||||
bool allowsForward() const override;
|
bool allowsForward() const override;
|
||||||
bool allowsEdit(const QDateTime &now) const override;
|
bool allowsEdit(TimeId now) const override;
|
||||||
bool uploading() const;
|
bool uploading() const;
|
||||||
|
|
||||||
void applyGroupAdminChanges(
|
void applyGroupAdminChanges(
|
||||||
|
|
|
@ -400,32 +400,39 @@ HistoryService::PreparedText HistoryService::preparePaymentSentText() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryService::HistoryService(not_null<History*> history, const MTPDmessage &message) :
|
|
||||||
HistoryItem(history, message.vid.v, message.vflags.v, ::date(message.vdate), message.has_from_id() ? message.vfrom_id.v : 0) {
|
|
||||||
createFromMtp(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
HistoryService::HistoryService(
|
HistoryService::HistoryService(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
const MTPDmessageService &message)
|
const MTPDmessage &data)
|
||||||
: HistoryItem(
|
: HistoryItem(
|
||||||
history,
|
history,
|
||||||
message.vid.v,
|
data.vid.v,
|
||||||
mtpCastFlags(message.vflags.v),
|
data.vflags.v,
|
||||||
::date(message.vdate),
|
data.vdate.v,
|
||||||
message.has_from_id() ? message.vfrom_id.v : 0) {
|
data.has_from_id() ? data.vfrom_id.v : UserId(0)) {
|
||||||
createFromMtp(message);
|
createFromMtp(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryService::HistoryService(
|
HistoryService::HistoryService(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
const MTPDmessageService &data)
|
||||||
QDateTime date,
|
: HistoryItem(
|
||||||
|
history,
|
||||||
|
data.vid.v,
|
||||||
|
mtpCastFlags(data.vflags.v),
|
||||||
|
data.vdate.v,
|
||||||
|
data.has_from_id() ? data.vfrom_id.v : UserId(0)) {
|
||||||
|
createFromMtp(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryService::HistoryService(
|
||||||
|
not_null<History*> history,
|
||||||
|
MsgId id,
|
||||||
|
TimeId date,
|
||||||
const PreparedText &message,
|
const PreparedText &message,
|
||||||
MTPDmessage::Flags flags,
|
MTPDmessage::Flags flags,
|
||||||
UserId from,
|
UserId from,
|
||||||
PhotoData *photo)
|
PhotoData *photo)
|
||||||
: HistoryItem(history, msgId, flags, date, from) {
|
: HistoryItem(history, id, flags, date, from) {
|
||||||
setServiceText(message);
|
setServiceText(message);
|
||||||
if (photo) {
|
if (photo) {
|
||||||
_media = std::make_unique<Data::MediaPhoto>(
|
_media = std::make_unique<Data::MediaPhoto>(
|
||||||
|
@ -665,7 +672,7 @@ HistoryService::PreparedText GenerateJoinedText(
|
||||||
|
|
||||||
HistoryService *GenerateJoinedMessage(
|
HistoryService *GenerateJoinedMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
const QDateTime &inviteDate,
|
TimeId inviteDate,
|
||||||
not_null<UserData*> inviter,
|
not_null<UserData*> inviter,
|
||||||
MTPDmessage::Flags flags) {
|
MTPDmessage::Flags flags) {
|
||||||
return new HistoryService(
|
return new HistoryService(
|
||||||
|
|
|
@ -58,14 +58,14 @@ public:
|
||||||
QList<ClickHandlerPtr> links;
|
QList<ClickHandlerPtr> links;
|
||||||
};
|
};
|
||||||
|
|
||||||
HistoryService(not_null<History*> history, const MTPDmessage &message);
|
HistoryService(not_null<History*> history, const MTPDmessage &data);
|
||||||
HistoryService(
|
HistoryService(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
const MTPDmessageService &message);
|
const MTPDmessageService &data);
|
||||||
HistoryService(
|
HistoryService(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MsgId msgId,
|
MsgId id,
|
||||||
QDateTime date,
|
TimeId date,
|
||||||
const PreparedText &message,
|
const PreparedText &message,
|
||||||
MTPDmessage::Flags flags = 0,
|
MTPDmessage::Flags flags = 0,
|
||||||
UserId from = 0,
|
UserId from = 0,
|
||||||
|
@ -153,6 +153,6 @@ private:
|
||||||
|
|
||||||
HistoryService *GenerateJoinedMessage(
|
HistoryService *GenerateJoinedMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
const QDateTime &inviteDate,
|
TimeId inviteDate,
|
||||||
not_null<UserData*> inviter,
|
not_null<UserData*> inviter,
|
||||||
MTPDmessage::Flags flags);
|
MTPDmessage::Flags flags);
|
||||||
|
|
|
@ -5137,7 +5137,9 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) {
|
||||||
}
|
}
|
||||||
} else if (e->key() == Qt::Key_Up) {
|
} else if (e->key() == Qt::Key_Up) {
|
||||||
if (!(e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier))) {
|
if (!(e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier))) {
|
||||||
if (_history && _history->lastSentMsg && _history->lastSentMsg->allowsEdit(::date(unixtime()))) {
|
if (_history
|
||||||
|
&& _history->lastSentMsg
|
||||||
|
&& _history->lastSentMsg->allowsEdit(unixtime())) {
|
||||||
if (_field->isEmpty() && !_editMsgId && !_replyToId && _history->lastSentMsg) {
|
if (_field->isEmpty() && !_editMsgId && !_replyToId && _history->lastSentMsg) {
|
||||||
editMessage(_history->lastSentMsg);
|
editMessage(_history->lastSentMsg);
|
||||||
return;
|
return;
|
||||||
|
@ -5490,7 +5492,7 @@ bool HistoryWidget::sendExistingDocument(
|
||||||
flags,
|
flags,
|
||||||
0,
|
0,
|
||||||
options.replyTo,
|
options.replyTo,
|
||||||
date(MTP_int(unixtime())),
|
unixtime(),
|
||||||
messageFromId,
|
messageFromId,
|
||||||
messagePostAuthor,
|
messagePostAuthor,
|
||||||
doc,
|
doc,
|
||||||
|
@ -5586,7 +5588,7 @@ void HistoryWidget::sendExistingPhoto(
|
||||||
flags,
|
flags,
|
||||||
0,
|
0,
|
||||||
options.replyTo,
|
options.replyTo,
|
||||||
date(MTP_int(unixtime())),
|
unixtime(),
|
||||||
messageFromId,
|
messageFromId,
|
||||||
messagePostAuthor,
|
messagePostAuthor,
|
||||||
photo,
|
photo,
|
||||||
|
@ -6539,8 +6541,7 @@ void HistoryWidget::paintEditHeader(Painter &p, const QRect &rect, int left, int
|
||||||
|
|
||||||
QString editTimeLeftText;
|
QString editTimeLeftText;
|
||||||
int updateIn = -1;
|
int updateIn = -1;
|
||||||
auto tmp = ::date(unixtime());
|
auto timeSinceMessage = ItemDateTime(_replyEditMsg).msecsTo(QDateTime::currentDateTime());
|
||||||
auto timeSinceMessage = _replyEditMsg->date.msecsTo(QDateTime::currentDateTime());
|
|
||||||
auto editTimeLeft = (Global::EditTimeLimit() * 1000LL) - timeSinceMessage;
|
auto editTimeLeft = (Global::EditTimeLimit() * 1000LL) - timeSinceMessage;
|
||||||
if (editTimeLeft < 2) {
|
if (editTimeLeft < 2) {
|
||||||
editTimeLeftText = qsl("0:00");
|
editTimeLeftText = qsl("0:00");
|
||||||
|
|
|
@ -137,6 +137,7 @@ Element::Element(
|
||||||
not_null<HistoryItem*> data)
|
not_null<HistoryItem*> data)
|
||||||
: _delegate(delegate)
|
: _delegate(delegate)
|
||||||
, _data(data)
|
, _data(data)
|
||||||
|
, _dateTime(ItemDateTime(data))
|
||||||
, _context(delegate->elementContext()) {
|
, _context(delegate->elementContext()) {
|
||||||
Auth().data().registerItemView(this);
|
Auth().data().registerItemView(this);
|
||||||
refreshMedia();
|
refreshMedia();
|
||||||
|
@ -153,6 +154,10 @@ not_null<HistoryItem*> Element::data() const {
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDateTime Element::dateTime() const {
|
||||||
|
return _dateTime;
|
||||||
|
}
|
||||||
|
|
||||||
HistoryMedia *Element::media() const {
|
HistoryMedia *Element::media() const {
|
||||||
return _media.get();
|
return _media.get();
|
||||||
}
|
}
|
||||||
|
@ -287,7 +292,7 @@ bool Element::computeIsAttachToPrevious(not_null<Element*> previous) {
|
||||||
const auto prev = previous->data();
|
const auto prev = previous->data();
|
||||||
const auto possible = !item->serviceMsg() && !prev->serviceMsg()
|
const auto possible = !item->serviceMsg() && !prev->serviceMsg()
|
||||||
&& !item->isEmpty() && !prev->isEmpty()
|
&& !item->isEmpty() && !prev->isEmpty()
|
||||||
&& (qAbs(prev->date.secsTo(item->date)) < kAttachMessageToPreviousSecondsDelta)
|
&& (std::abs(prev->date() - item->date()) < kAttachMessageToPreviousSecondsDelta)
|
||||||
&& (_context == Context::Feed
|
&& (_context == Context::Feed
|
||||||
|| (!item->isPost() && !prev->isPost()));
|
|| (!item->isPost() && !prev->isPost()));
|
||||||
if (possible) {
|
if (possible) {
|
||||||
|
@ -367,9 +372,10 @@ void Element::recountDisplayDateInBlocks() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto previous = previousInBlocks()) {
|
if (const auto previous = previousInBlocks()) {
|
||||||
const auto prev = previous->data();
|
const auto prev = previous->data();
|
||||||
return prev->isEmpty() || (prev->date.date() != item->date.date());
|
return prev->isEmpty()
|
||||||
|
|| (previous->dateTime().date() != dateTime().date());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
|
@ -391,7 +397,7 @@ void Element::setDisplayDate(bool displayDate) {
|
||||||
const auto item = data();
|
const auto item = data();
|
||||||
if (displayDate && !Has<DateBadge>()) {
|
if (displayDate && !Has<DateBadge>()) {
|
||||||
AddComponents(DateBadge::Bit());
|
AddComponents(DateBadge::Bit());
|
||||||
Get<DateBadge>()->init(item->date);
|
Get<DateBadge>()->init(dateTime());
|
||||||
setPendingResize();
|
setPendingResize();
|
||||||
} else if (!displayDate && Has<DateBadge>()) {
|
} else if (!displayDate && Has<DateBadge>()) {
|
||||||
RemoveComponents(DateBadge::Bit());
|
RemoveComponents(DateBadge::Bit());
|
||||||
|
@ -478,8 +484,8 @@ bool Element::displayEditedBadge() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime Element::displayedEditDate() const {
|
TimeId Element::displayedEditDate() const {
|
||||||
return QDateTime();
|
return TimeId(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Element::hasVisibleText() const {
|
bool Element::hasVisibleText() const {
|
||||||
|
|
|
@ -121,6 +121,8 @@ public:
|
||||||
Context context() const;
|
Context context() const;
|
||||||
void refreshDataId();
|
void refreshDataId();
|
||||||
|
|
||||||
|
QDateTime dateTime() const;
|
||||||
|
|
||||||
int y() const;
|
int y() const;
|
||||||
void setY(int y);
|
void setY(int y);
|
||||||
|
|
||||||
|
@ -221,7 +223,7 @@ public:
|
||||||
int outerWidth) const;
|
int outerWidth) const;
|
||||||
virtual ClickHandlerPtr rightActionLink() const;
|
virtual ClickHandlerPtr rightActionLink() const;
|
||||||
virtual bool displayEditedBadge() const;
|
virtual bool displayEditedBadge() const;
|
||||||
virtual QDateTime displayedEditDate() const;
|
virtual TimeId displayedEditDate() const;
|
||||||
virtual bool hasVisibleText() const;
|
virtual bool hasVisibleText() const;
|
||||||
|
|
||||||
// Legacy blocks structure.
|
// Legacy blocks structure.
|
||||||
|
@ -266,9 +268,10 @@ private:
|
||||||
const not_null<ElementDelegate*> _delegate;
|
const not_null<ElementDelegate*> _delegate;
|
||||||
const not_null<HistoryItem*> _data;
|
const not_null<HistoryItem*> _data;
|
||||||
std::unique_ptr<HistoryMedia> _media;
|
std::unique_ptr<HistoryMedia> _media;
|
||||||
|
const QDateTime _dateTime;
|
||||||
|
|
||||||
int _y = 0;
|
int _y = 0;
|
||||||
Context _context;
|
Context _context = Context();
|
||||||
|
|
||||||
Flags _flags = Flag::NeedsResize;
|
Flags _flags = Flag::NeedsResize;
|
||||||
|
|
||||||
|
|
|
@ -908,7 +908,7 @@ QString ListWidget::tooltipText() const {
|
||||||
? _overElement->data().get()
|
? _overElement->data().get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (_mouseCursorState == CursorState::Date && item) {
|
if (_mouseCursorState == CursorState::Date && item) {
|
||||||
return item->date.toString(
|
return _overElement->dateTime().toString(
|
||||||
QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
QLocale::system().dateTimeFormat(QLocale::LongFormat));
|
||||||
} else if (_mouseCursorState == CursorState::Forwarded && item) {
|
} else if (_mouseCursorState == CursorState::Forwarded && item) {
|
||||||
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
|
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
|
||||||
|
@ -1178,7 +1178,7 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
||||||
} else {
|
} else {
|
||||||
ServiceMessagePainter::paintDate(
|
ServiceMessagePainter::paintDate(
|
||||||
p,
|
p,
|
||||||
view->data()->date,
|
view->dateTime(),
|
||||||
dateY,
|
dateY,
|
||||||
width);
|
width);
|
||||||
}
|
}
|
||||||
|
@ -1238,7 +1238,7 @@ TextWithEntities ListWidget::getSelectedText() const {
|
||||||
const auto wrapItem = [&](
|
const auto wrapItem = [&](
|
||||||
not_null<HistoryItem*> item,
|
not_null<HistoryItem*> item,
|
||||||
TextWithEntities &&unwrapped) {
|
TextWithEntities &&unwrapped) {
|
||||||
auto time = item->date.toString(timeFormat);
|
auto time = ItemDateTime(item).toString(timeFormat);
|
||||||
auto part = TextWithEntities();
|
auto part = TextWithEntities();
|
||||||
auto size = item->author()->name.size()
|
auto size = item->author()->name.size()
|
||||||
+ time.size()
|
+ time.size()
|
||||||
|
@ -2158,8 +2158,8 @@ void ListWidget::refreshAttachmentsFromTill(int from, int till) {
|
||||||
if (next->isHidden()) {
|
if (next->isHidden()) {
|
||||||
next->setDisplayDate(false);
|
next->setDisplayDate(false);
|
||||||
} else {
|
} else {
|
||||||
const auto viewDate = view->data()->date;
|
const auto viewDate = view->dateTime();
|
||||||
const auto nextDate = next->data()->date;
|
const auto nextDate = next->dateTime();
|
||||||
next->setDisplayDate(nextDate.date() != viewDate.date());
|
next->setDisplayDate(nextDate.date() != viewDate.date());
|
||||||
auto attached = next->computeIsAttachToPrevious(view);
|
auto attached = next->computeIsAttachToPrevious(view);
|
||||||
next->setAttachToPrevious(attached);
|
next->setAttachToPrevious(attached);
|
||||||
|
|
|
@ -1682,12 +1682,12 @@ void Message::refreshEditedBadge() {
|
||||||
const auto item = message();
|
const auto item = message();
|
||||||
const auto edited = displayedEditBadge();
|
const auto edited = displayedEditBadge();
|
||||||
const auto editDate = displayedEditDate();
|
const auto editDate = displayedEditDate();
|
||||||
const auto dateText = item->date.toString(cTimeFormat());
|
const auto dateText = dateTime().toString(cTimeFormat());
|
||||||
if (edited) {
|
if (edited) {
|
||||||
edited->refresh(dateText, !editDate.isNull());
|
edited->refresh(dateText, editDate != 0);
|
||||||
}
|
}
|
||||||
if (const auto msgsigned = item->Get<HistoryMessageSigned>()) {
|
if (const auto msgsigned = item->Get<HistoryMessageSigned>()) {
|
||||||
const auto text = (!edited || editDate.isNull())
|
const auto text = (!edited || !editDate)
|
||||||
? dateText
|
? dateText
|
||||||
: edited->text.originalText();
|
: edited->text.originalText();
|
||||||
msgsigned->refresh(text);
|
msgsigned->refresh(text);
|
||||||
|
@ -1702,7 +1702,7 @@ void Message::initTime() {
|
||||||
} else if (const auto edited = displayedEditBadge()) {
|
} else if (const auto edited = displayedEditBadge()) {
|
||||||
item->_timeWidth = edited->maxWidth();
|
item->_timeWidth = edited->maxWidth();
|
||||||
} else {
|
} else {
|
||||||
item->_timeText = item->date.toString(cTimeFormat());
|
item->_timeText = dateTime().toString(cTimeFormat());
|
||||||
item->_timeWidth = st::msgDateFont->width(item->_timeText);
|
item->_timeWidth = st::msgDateFont->width(item->_timeText);
|
||||||
}
|
}
|
||||||
if (const auto views = item->Get<HistoryMessageViews>()) {
|
if (const auto views = item->Get<HistoryMessageViews>()) {
|
||||||
|
@ -1722,29 +1722,29 @@ void Message::initTime() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Message::displayEditedBadge() const {
|
bool Message::displayEditedBadge() const {
|
||||||
return !displayedEditDate().isNull();
|
return (displayedEditDate() != TimeId(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime Message::displayedEditDate() const {
|
TimeId Message::displayedEditDate() const {
|
||||||
const auto item = message();
|
const auto item = message();
|
||||||
auto hasViaBotId = item->Has<HistoryMessageVia>();
|
auto hasViaBotId = item->Has<HistoryMessageVia>();
|
||||||
auto hasInlineMarkup = (item->inlineReplyMarkup() != nullptr);
|
auto hasInlineMarkup = (item->inlineReplyMarkup() != nullptr);
|
||||||
return displayedEditDate(hasViaBotId || hasInlineMarkup);
|
return displayedEditDate(hasViaBotId || hasInlineMarkup);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime Message::displayedEditDate(
|
TimeId Message::displayedEditDate(
|
||||||
bool hasViaBotOrInlineMarkup) const {
|
bool hasViaBotOrInlineMarkup) const {
|
||||||
if (hasViaBotOrInlineMarkup) {
|
if (hasViaBotOrInlineMarkup) {
|
||||||
return QDateTime();
|
return TimeId(0);
|
||||||
} else if (const auto fromUser = message()->from()->asUser()) {
|
} else if (const auto fromUser = message()->from()->asUser()) {
|
||||||
if (fromUser->botInfo) {
|
if (fromUser->botInfo) {
|
||||||
return QDateTime();
|
return TimeId(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (const auto edited = displayedEditBadge()) {
|
if (const auto edited = displayedEditBadge()) {
|
||||||
return edited->date;
|
return edited->date;
|
||||||
}
|
}
|
||||||
return QDateTime();
|
return TimeId(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryMessageEdited *Message::displayedEditBadge() {
|
HistoryMessageEdited *Message::displayedEditBadge() {
|
||||||
|
|
|
@ -79,7 +79,7 @@ public:
|
||||||
int outerWidth) const override;
|
int outerWidth) const override;
|
||||||
ClickHandlerPtr rightActionLink() const override;
|
ClickHandlerPtr rightActionLink() const override;
|
||||||
bool displayEditedBadge() const override;
|
bool displayEditedBadge() const override;
|
||||||
QDateTime displayedEditDate() const override;
|
TimeId displayedEditDate() const override;
|
||||||
int infoWidth() const override;
|
int infoWidth() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -135,7 +135,7 @@ private:
|
||||||
bool displayFastShare() const;
|
bool displayFastShare() const;
|
||||||
bool displayGoToOriginal() const;
|
bool displayGoToOriginal() const;
|
||||||
ClickHandlerPtr fastReplyLink() const;
|
ClickHandlerPtr fastReplyLink() const;
|
||||||
QDateTime displayedEditDate(bool hasViaBotOrInlineMarkup) const;
|
TimeId displayedEditDate(bool hasViaBotOrInlineMarkup) const;
|
||||||
const HistoryMessageEdited *displayedEditBadge() const;
|
const HistoryMessageEdited *displayedEditBadge() const;
|
||||||
HistoryMessageEdited *displayedEditBadge();
|
HistoryMessageEdited *displayedEditBadge();
|
||||||
void initTime();
|
void initTime();
|
||||||
|
|
|
@ -194,7 +194,7 @@ bool ListWidget::Section::addItem(not_null<BaseLayout*> item) {
|
||||||
|
|
||||||
void ListWidget::Section::setHeader(not_null<BaseLayout*> item) {
|
void ListWidget::Section::setHeader(not_null<BaseLayout*> item) {
|
||||||
auto text = [&] {
|
auto text = [&] {
|
||||||
auto date = item->getItem()->date.date();
|
auto date = item->dateTime().date();
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case Type::Photo:
|
case Type::Photo:
|
||||||
case Type::Video:
|
case Type::Video:
|
||||||
|
@ -217,8 +217,8 @@ void ListWidget::Section::setHeader(not_null<BaseLayout*> item) {
|
||||||
bool ListWidget::Section::belongsHere(
|
bool ListWidget::Section::belongsHere(
|
||||||
not_null<BaseLayout*> item) const {
|
not_null<BaseLayout*> item) const {
|
||||||
Expects(!_items.empty());
|
Expects(!_items.empty());
|
||||||
auto date = item->getItem()->date.date();
|
auto date = item->dateTime().date();
|
||||||
auto myDate = _items.back().second->getItem()->date.date();
|
auto myDate = _items.back().second->dateTime().date();
|
||||||
|
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case Type::Photo:
|
case Type::Photo:
|
||||||
|
|
|
@ -131,7 +131,7 @@ void SendPhoto::addToHistory(
|
||||||
flags,
|
flags,
|
||||||
viaBotId,
|
viaBotId,
|
||||||
replyToId,
|
replyToId,
|
||||||
date(mtpDate),
|
mtpDate.v,
|
||||||
fromId,
|
fromId,
|
||||||
postAuthor,
|
postAuthor,
|
||||||
_photo,
|
_photo,
|
||||||
|
@ -166,7 +166,7 @@ void SendFile::addToHistory(
|
||||||
flags,
|
flags,
|
||||||
viaBotId,
|
viaBotId,
|
||||||
replyToId,
|
replyToId,
|
||||||
date(mtpDate),
|
mtpDate.v,
|
||||||
fromId,
|
fromId,
|
||||||
postAuthor,
|
postAuthor,
|
||||||
_document,
|
_document,
|
||||||
|
@ -208,7 +208,7 @@ void SendGame::addToHistory(
|
||||||
flags,
|
flags,
|
||||||
viaBotId,
|
viaBotId,
|
||||||
replyToId,
|
replyToId,
|
||||||
date(mtpDate),
|
mtpDate.v,
|
||||||
fromId,
|
fromId,
|
||||||
postAuthor,
|
postAuthor,
|
||||||
_game,
|
_game,
|
||||||
|
|
|
@ -4860,16 +4860,20 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateContactRegistered: {
|
case mtpc_updateContactRegistered: {
|
||||||
auto &d = update.c_updateContactRegistered();
|
const auto &d = update.c_updateContactRegistered();
|
||||||
if (auto user = App::userLoaded(d.vuser_id.v)) {
|
if (const auto user = App::userLoaded(d.vuser_id.v)) {
|
||||||
if (App::history(user->id)->loadedAtBottom()) {
|
if (App::history(user->id)->loadedAtBottom()) {
|
||||||
App::history(user->id)->addNewService(clientMsgId(), date(d.vdate), lng_action_user_registered(lt_from, user->name), 0);
|
App::history(user->id)->addNewService(
|
||||||
|
clientMsgId(),
|
||||||
|
d.vdate.v,
|
||||||
|
lng_action_user_registered(lt_from, user->name),
|
||||||
|
MTPDmessage::Flags(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateContactLink: {
|
case mtpc_updateContactLink: {
|
||||||
auto &d = update.c_updateContactLink();
|
const auto &d = update.c_updateContactLink();
|
||||||
App::feedUserLink(d.vuser_id, d.vmy_link, d.vforeign_link);
|
App::feedUserLink(d.vuser_id, d.vmy_link, d.vforeign_link);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
|
@ -468,22 +468,31 @@ void Widget::handleSongChange() {
|
||||||
|
|
||||||
TextWithEntities textWithEntities;
|
TextWithEntities textWithEntities;
|
||||||
if (document->isVoiceMessage() || document->isVideoMessage()) {
|
if (document->isVoiceMessage() || document->isVideoMessage()) {
|
||||||
if (auto item = App::histItemById(current.contextId())) {
|
if (const auto item = App::histItemById(current.contextId())) {
|
||||||
auto name = App::peerName(item->fromOriginal());
|
const auto name = App::peerName(item->fromOriginal());
|
||||||
auto date = [item] {
|
const auto date = [item] {
|
||||||
auto date = item->date.date();
|
const auto parsed = ItemDateTime(item);
|
||||||
auto time = item->date.time().toString(cTimeFormat());
|
const auto date = parsed.date();
|
||||||
auto today = QDateTime::currentDateTime().date();
|
const auto time = parsed.time().toString(cTimeFormat());
|
||||||
|
const auto today = QDateTime::currentDateTime().date();
|
||||||
if (date == today) {
|
if (date == today) {
|
||||||
return lng_player_message_today(lt_time, time);
|
return lng_player_message_today(lt_time, time);
|
||||||
} else if (date.addDays(1) == today) {
|
} else if (date.addDays(1) == today) {
|
||||||
return lng_player_message_yesterday(lt_time, time);
|
return lng_player_message_yesterday(lt_time, time);
|
||||||
}
|
}
|
||||||
return lng_player_message_date(lt_date, langDayOfMonthFull(date), lt_time, time);
|
return lng_player_message_date(
|
||||||
|
lt_date,
|
||||||
|
langDayOfMonthFull(date),
|
||||||
|
lt_time,
|
||||||
|
time);
|
||||||
};
|
};
|
||||||
|
|
||||||
textWithEntities.text = name + ' ' + date();
|
textWithEntities.text = name + ' ' + date();
|
||||||
textWithEntities.entities.append({ EntityInTextBold, 0, name.size(), QString() });
|
textWithEntities.entities.append(EntityInText(
|
||||||
|
EntityInTextBold,
|
||||||
|
0,
|
||||||
|
name.size(),
|
||||||
|
QString()));
|
||||||
} else {
|
} else {
|
||||||
textWithEntities.text = lang(lng_media_audio);
|
textWithEntities.text = lang(lng_media_audio);
|
||||||
}
|
}
|
||||||
|
|
|
@ -325,14 +325,17 @@ void MediaView::updateControls() {
|
||||||
_moreNav = myrtlrect(width() - st::mediaviewIconSize.width(), height() - st::mediaviewIconSize.height(), st::mediaviewIconSize.width(), st::mediaviewIconSize.height());
|
_moreNav = myrtlrect(width() - st::mediaviewIconSize.width(), height() - st::mediaviewIconSize.height(), st::mediaviewIconSize.width(), st::mediaviewIconSize.height());
|
||||||
_moreNavIcon = centerrect(_moreNav, st::mediaviewMore);
|
_moreNavIcon = centerrect(_moreNav, st::mediaviewMore);
|
||||||
|
|
||||||
QDateTime d, dNow(date(unixtime()));
|
const auto dNow = QDateTime::currentDateTime();
|
||||||
if (_photo) {
|
const auto d = [&] {
|
||||||
d = date(_photo->date);
|
if (_photo) {
|
||||||
} else if (_doc) {
|
return ParseDateTime(_photo->date);
|
||||||
d = date(_doc->date);
|
} else if (_doc) {
|
||||||
} else if (auto item = App::histItemById(_msgid)) {
|
return ParseDateTime(_doc->date);
|
||||||
d = item->date;
|
} else if (const auto item = App::histItemById(_msgid)) {
|
||||||
}
|
return ItemDateTime(item);
|
||||||
|
}
|
||||||
|
return dNow;
|
||||||
|
}();
|
||||||
if (d.date() == dNow.date()) {
|
if (d.date() == dNow.date()) {
|
||||||
_dateText = lng_mediaview_today(lt_time, d.time().toString(cTimeFormat()));
|
_dateText = lng_mediaview_today(lt_time, d.time().toString(cTimeFormat()));
|
||||||
} else if (d.date().addDays(1) == dNow.date()) {
|
} else if (d.date().addDays(1) == dNow.date()) {
|
||||||
|
@ -847,14 +850,23 @@ void MediaView::onSaveAs() {
|
||||||
|
|
||||||
psBringToBack(this);
|
psBringToBack(this);
|
||||||
auto filter = qsl("JPEG Image (*.jpg);;") + FileDialog::AllFilesFilter();
|
auto filter = qsl("JPEG Image (*.jpg);;") + FileDialog::AllFilesFilter();
|
||||||
FileDialog::GetWritePath(lang(lng_save_photo), filter, filedialogDefaultName(qsl("photo"), qsl(".jpg"), QString(), false, _photo->date), base::lambda_guarded(this, [this, photo = _photo](const QString &result) {
|
FileDialog::GetWritePath(
|
||||||
if (!result.isEmpty() && _photo == photo && photo->loaded()) {
|
lang(lng_save_photo),
|
||||||
photo->full->pix().toImage().save(result, "JPG");
|
filter,
|
||||||
}
|
filedialogDefaultName(
|
||||||
psShowOverAll(this);
|
qsl("photo"),
|
||||||
}), base::lambda_guarded(this, [this] {
|
qsl(".jpg"),
|
||||||
psShowOverAll(this);
|
QString(),
|
||||||
}));
|
false,
|
||||||
|
_photo->date),
|
||||||
|
base::lambda_guarded(this, [this, photo = _photo](const QString &result) {
|
||||||
|
if (!result.isEmpty() && _photo == photo && photo->loaded()) {
|
||||||
|
photo->full->pix().toImage().save(result, "JPG");
|
||||||
|
}
|
||||||
|
psShowOverAll(this);
|
||||||
|
}), base::lambda_guarded(this, [this] {
|
||||||
|
psShowOverAll(this);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
activateWindow();
|
activateWindow();
|
||||||
Sandbox::setActiveWindow(this);
|
Sandbox::setActiveWindow(this);
|
||||||
|
|
|
@ -124,7 +124,13 @@ MsgId AbstractItem::msgId() const {
|
||||||
return item ? item->id : 0;
|
return item ? item->id : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemBase::ItemBase(not_null<HistoryItem*> parent) : _parent(parent) {
|
ItemBase::ItemBase(not_null<HistoryItem*> parent)
|
||||||
|
: _parent(parent)
|
||||||
|
, _dateTime(ItemDateTime(parent)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime ItemBase::dateTime() const {
|
||||||
|
return _dateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemBase::clickHandlerActiveChanged(
|
void ItemBase::clickHandlerActiveChanged(
|
||||||
|
@ -564,9 +570,19 @@ Voice::Voice(
|
||||||
setDocumentLinks(_data);
|
setDocumentLinks(_data);
|
||||||
|
|
||||||
updateName();
|
updateName();
|
||||||
QString d = textcmdLink(1, TextUtilities::EscapeForRichParsing(langDateTime(date(_data->date))));
|
const auto dateText = textcmdLink(
|
||||||
|
1,
|
||||||
|
TextUtilities::EscapeForRichParsing(
|
||||||
|
langDateTime(ParseDateTime(_data->date))));
|
||||||
TextParseOptions opts = { TextParseRichText, 0, 0, Qt::LayoutDirectionAuto };
|
TextParseOptions opts = { TextParseRichText, 0, 0, Qt::LayoutDirectionAuto };
|
||||||
_details.setText(st::defaultTextStyle, lng_date_and_duration(lt_date, d, lt_duration, formatDurationText(_data->voice()->duration)), opts);
|
_details.setText(
|
||||||
|
st::defaultTextStyle,
|
||||||
|
lng_date_and_duration(
|
||||||
|
lt_date,
|
||||||
|
dateText,
|
||||||
|
lt_duration,
|
||||||
|
formatDurationText(_data->voice()->duration)),
|
||||||
|
opts);
|
||||||
_details.setLink(1, goToMessageClickHandler(parent));
|
_details.setLink(1, goToMessageClickHandler(parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,7 +820,7 @@ Document::Document(
|
||||||
, _msgl(goToMessageClickHandler(parent))
|
, _msgl(goToMessageClickHandler(parent))
|
||||||
, _namel(std::make_shared<DocumentOpenClickHandler>(_data, parent->fullId()))
|
, _namel(std::make_shared<DocumentOpenClickHandler>(_data, parent->fullId()))
|
||||||
, _st(st)
|
, _st(st)
|
||||||
, _date(langDateTime(date(_data->date)))
|
, _date(langDateTime(ParseDateTime(_data->date)))
|
||||||
, _datew(st::normalFont->width(_date))
|
, _datew(st::normalFont->width(_date))
|
||||||
, _colorIndex(documentColorIndex(_data, _ext)) {
|
, _colorIndex(documentColorIndex(_data, _ext)) {
|
||||||
_name.setMarkedText(st::defaultTextStyle, ComposeNameWithEntities(_data), _documentNameOptions);
|
_name.setMarkedText(st::defaultTextStyle, ComposeNameWithEntities(_data), _documentNameOptions);
|
||||||
|
|
|
@ -64,6 +64,8 @@ class ItemBase : public AbstractItem {
|
||||||
public:
|
public:
|
||||||
ItemBase(not_null<HistoryItem*> parent);
|
ItemBase(not_null<HistoryItem*> parent);
|
||||||
|
|
||||||
|
QDateTime dateTime() const;
|
||||||
|
|
||||||
void setPosition(int position) {
|
void setPosition(int position) {
|
||||||
_position = position;
|
_position = position;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +105,8 @@ private:
|
||||||
void ensureCheckboxCreated();
|
void ensureCheckboxCreated();
|
||||||
|
|
||||||
int _position = 0;
|
int _position = 0;
|
||||||
not_null<HistoryItem*> _parent;
|
const not_null<HistoryItem*> _parent;
|
||||||
|
const QDateTime _dateTime;
|
||||||
std::unique_ptr<Checkbox> _check;
|
std::unique_ptr<Checkbox> _check;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -331,7 +331,9 @@ void System::showNext() {
|
||||||
if (nextNotify) {
|
if (nextNotify) {
|
||||||
if (forwardedItem) {
|
if (forwardedItem) {
|
||||||
auto nextForwarded = nextNotify->Has<HistoryMessageForwarded>() ? nextNotify : nullptr;
|
auto nextForwarded = nextNotify->Has<HistoryMessageForwarded>() ? nextNotify : nullptr;
|
||||||
if (nextForwarded && forwardedItem->author() == nextForwarded->author() && qAbs(int64(nextForwarded->date.toTime_t()) - int64(forwardedItem->date.toTime_t())) < 2) {
|
if (nextForwarded
|
||||||
|
&& forwardedItem->author() == nextForwarded->author()
|
||||||
|
&& qAbs(int64(nextForwarded->date()) - int64(forwardedItem->date())) < 2) {
|
||||||
forwardedItem = nextForwarded;
|
forwardedItem = nextForwarded;
|
||||||
++forwardedCount;
|
++forwardedCount;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -309,13 +309,13 @@ void Controller::showJumpToDate(not_null<PeerData*> peer, QDate requestedDate) {
|
||||||
auto currentPeerDate = [peer] {
|
auto currentPeerDate = [peer] {
|
||||||
if (auto history = App::historyLoaded(peer)) {
|
if (auto history = App::historyLoaded(peer)) {
|
||||||
if (history->scrollTopItem) {
|
if (history->scrollTopItem) {
|
||||||
return history->scrollTopItem->data()->date.date();
|
return history->scrollTopItem->dateTime().date();
|
||||||
} else if (history->loadedAtTop() && !history->isEmpty() && history->peer->migrateFrom()) {
|
} else if (history->loadedAtTop() && !history->isEmpty() && history->peer->migrateFrom()) {
|
||||||
if (auto migrated = App::historyLoaded(history->peer->migrateFrom())) {
|
if (auto migrated = App::historyLoaded(history->peer->migrateFrom())) {
|
||||||
if (migrated->scrollTopItem) {
|
if (migrated->scrollTopItem) {
|
||||||
// We're up in the migrated history.
|
// We're up in the migrated history.
|
||||||
// So current date is the date of first message here.
|
// So current date is the date of first message here.
|
||||||
return history->blocks.front()->messages.front()->data()->date.date();
|
return history->blocks.front()->messages.front()->dateTime().date();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!history->chatsListDate().isNull()) {
|
} else if (!history->chatsListDate().isNull()) {
|
||||||
|
@ -344,7 +344,7 @@ void Controller::showJumpToDate(not_null<PeerData*> peer, QDate requestedDate) {
|
||||||
if (auto history = App::historyLoaded(chat)) {
|
if (auto history = App::historyLoaded(chat)) {
|
||||||
if (history->loadedAtTop()) {
|
if (history->loadedAtTop()) {
|
||||||
if (!history->isEmpty()) {
|
if (!history->isEmpty()) {
|
||||||
return history->blocks.front()->messages.front()->data()->date.date();
|
return history->blocks.front()->messages.front()->dateTime().date();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return startDate();
|
return startDate();
|
||||||
|
@ -354,7 +354,7 @@ void Controller::showJumpToDate(not_null<PeerData*> peer, QDate requestedDate) {
|
||||||
if (auto history = App::historyLoaded(peer)) {
|
if (auto history = App::historyLoaded(peer)) {
|
||||||
if (history->loadedAtTop()) {
|
if (history->loadedAtTop()) {
|
||||||
if (!history->isEmpty()) {
|
if (!history->isEmpty()) {
|
||||||
return history->blocks.front()->messages.front()->data()->date.date();
|
return history->blocks.front()->messages.front()->dateTime().date();
|
||||||
}
|
}
|
||||||
return QDate::currentDate();
|
return QDate::currentDate();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue