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