mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Initial formatted date support.
This commit is contained in:
@@ -5542,6 +5542,38 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
|
|
||||||
"lng_text_copied" = "Text copied to clipboard.";
|
"lng_text_copied" = "Text copied to clipboard.";
|
||||||
"lng_code_copied" = "Code copied to clipboard.";
|
"lng_code_copied" = "Code copied to clipboard.";
|
||||||
|
"lng_date_copied" = "Date copied to clipboard.";
|
||||||
|
|
||||||
|
"lng_date_relative_now" = "now";
|
||||||
|
|
||||||
|
"lng_date_relative_seconds_ago#one" = "{count} second ago";
|
||||||
|
"lng_date_relative_seconds_ago#other" = "{count} seconds ago";
|
||||||
|
"lng_date_relative_minutes_ago#one" = "{count} minute ago";
|
||||||
|
"lng_date_relative_minutes_ago#other" = "{count} minutes ago";
|
||||||
|
"lng_date_relative_hours_ago#one" = "{count} hour ago";
|
||||||
|
"lng_date_relative_hours_ago#other" = "{count} hours ago";
|
||||||
|
"lng_date_relative_days_ago#one" = "{count} day ago";
|
||||||
|
"lng_date_relative_days_ago#other" = "{count} days ago";
|
||||||
|
"lng_date_relative_months_ago#one" = "{count} month ago";
|
||||||
|
"lng_date_relative_months_ago#other" = "{count} months ago";
|
||||||
|
"lng_date_relative_years_ago#one" = "{count} year ago";
|
||||||
|
"lng_date_relative_years_ago#other" = "{count} years ago";
|
||||||
|
|
||||||
|
"lng_date_relative_in_seconds#one" = "in {count} second";
|
||||||
|
"lng_date_relative_in_seconds#other" = "in {count} seconds";
|
||||||
|
"lng_date_relative_in_minutes#one" = "in {count} minute";
|
||||||
|
"lng_date_relative_in_minutes#other" = "in {count} minutes";
|
||||||
|
"lng_date_relative_in_hours#one" = "in {count} hour";
|
||||||
|
"lng_date_relative_in_hours#other" = "in {count} hours";
|
||||||
|
"lng_date_relative_in_days#one" = "in {count} day";
|
||||||
|
"lng_date_relative_in_days#other" = "in {count} days";
|
||||||
|
"lng_date_relative_in_months#one" = "in {count} month";
|
||||||
|
"lng_date_relative_in_months#other" = "in {count} months";
|
||||||
|
"lng_date_relative_in_years#one" = "in {count} year";
|
||||||
|
"lng_date_relative_in_years#other" = "in {count} years";
|
||||||
|
|
||||||
|
"lng_context_copy_date" = "Copy Date";
|
||||||
|
"lng_context_set_reminder" = "Set a Reminder";
|
||||||
|
|
||||||
"lng_spellchecker_submenu" = "Spelling";
|
"lng_spellchecker_submenu" = "Spelling";
|
||||||
"lng_spellchecker_add" = "Add to Dictionary";
|
"lng_spellchecker_add" = "Add to Dictionary";
|
||||||
|
|||||||
@@ -239,6 +239,31 @@ EntitiesInText EntitiesFromMTP(
|
|||||||
d.is_collapsed() ? u"1"_q : QString(),
|
d.is_collapsed() ? u"1"_q : QString(),
|
||||||
});
|
});
|
||||||
}, [&](const MTPDmessageEntityFormattedDate &d) {
|
}, [&](const MTPDmessageEntityFormattedDate &d) {
|
||||||
|
auto flags = FormattedDateFlags();
|
||||||
|
if (d.is_relative()) {
|
||||||
|
flags |= FormattedDateFlag::Relative;
|
||||||
|
}
|
||||||
|
if (d.is_short_time()) {
|
||||||
|
flags |= FormattedDateFlag::ShortTime;
|
||||||
|
}
|
||||||
|
if (d.is_long_time()) {
|
||||||
|
flags |= FormattedDateFlag::LongTime;
|
||||||
|
}
|
||||||
|
if (d.is_short_date()) {
|
||||||
|
flags |= FormattedDateFlag::ShortDate;
|
||||||
|
}
|
||||||
|
if (d.is_long_date()) {
|
||||||
|
flags |= FormattedDateFlag::LongDate;
|
||||||
|
}
|
||||||
|
if (d.is_day_of_week()) {
|
||||||
|
flags |= FormattedDateFlag::DayOfWeek;
|
||||||
|
}
|
||||||
|
result.push_back({
|
||||||
|
EntityType::FormattedDate,
|
||||||
|
d.voffset().v,
|
||||||
|
d.vlength().v,
|
||||||
|
SerializeFormattedDateData(d.vdate().v, flags),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -359,6 +384,37 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(
|
|||||||
v.push_back(*valid);
|
v.push_back(*valid);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case EntityType::FormattedDate: {
|
||||||
|
const auto [date, dateFlags] = DeserializeFormattedDateData(
|
||||||
|
entity.data());
|
||||||
|
if (date) {
|
||||||
|
using Flag = MTPDmessageEntityFormattedDate::Flag;
|
||||||
|
auto mtpFlags = MTPDmessageEntityFormattedDate::Flags();
|
||||||
|
if (dateFlags & FormattedDateFlag::Relative) {
|
||||||
|
mtpFlags |= Flag::f_relative;
|
||||||
|
}
|
||||||
|
if (dateFlags & FormattedDateFlag::ShortTime) {
|
||||||
|
mtpFlags |= Flag::f_short_time;
|
||||||
|
}
|
||||||
|
if (dateFlags & FormattedDateFlag::LongTime) {
|
||||||
|
mtpFlags |= Flag::f_long_time;
|
||||||
|
}
|
||||||
|
if (dateFlags & FormattedDateFlag::ShortDate) {
|
||||||
|
mtpFlags |= Flag::f_short_date;
|
||||||
|
}
|
||||||
|
if (dateFlags & FormattedDateFlag::LongDate) {
|
||||||
|
mtpFlags |= Flag::f_long_date;
|
||||||
|
}
|
||||||
|
if (dateFlags & FormattedDateFlag::DayOfWeek) {
|
||||||
|
mtpFlags |= Flag::f_day_of_week;
|
||||||
|
}
|
||||||
|
v.push_back(MTP_messageEntityFormattedDate(
|
||||||
|
MTP_flags(mtpFlags),
|
||||||
|
offset,
|
||||||
|
length,
|
||||||
|
MTP_int(date)));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return MTP_vector<MTPMessageEntity>(std::move(v));
|
return MTP_vector<MTPMessageEntity>(std::move(v));
|
||||||
|
|||||||
@@ -29,8 +29,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "window/window_session_controller_link_info.h"
|
#include "window/window_session_controller_link_info.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "history/view/history_view_schedule_box.h"
|
||||||
|
#include "menu/menu_send.h"
|
||||||
|
#include "data/data_types.h"
|
||||||
#include "styles/style_calls.h" // groupCallBoxLabel
|
#include "styles/style_calls.h" // groupCallBoxLabel
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
|
#include "styles/style_menu_icons.h"
|
||||||
|
|
||||||
|
#include <QtCore/QDateTime>
|
||||||
|
#include <QtCore/QLocale>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -438,3 +446,81 @@ auto MonospaceClickHandler::getTextEntity() const -> TextEntity {
|
|||||||
QString MonospaceClickHandler::url() const {
|
QString MonospaceClickHandler::url() const {
|
||||||
return _text;
|
return _text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FormattedDateClickHandler::FormattedDateClickHandler(
|
||||||
|
int32 date,
|
||||||
|
FormattedDateFlags flags)
|
||||||
|
: _date(date)
|
||||||
|
, _entityData(SerializeFormattedDateData(date, flags)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void FormattedDateClickHandler::onClick(ClickContext context) const {
|
||||||
|
if (context.button != Qt::LeftButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto my = context.other.value<ClickHandlerContext>();
|
||||||
|
const auto controller = my.sessionWindow.get();
|
||||||
|
if (!controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto menu = Ui::CreateChild<Ui::PopupMenu>(
|
||||||
|
controller->content(),
|
||||||
|
st::popupMenuWithIcons);
|
||||||
|
|
||||||
|
const auto date = _date;
|
||||||
|
const auto show = controller->uiShow();
|
||||||
|
|
||||||
|
menu->addAction(
|
||||||
|
tr::lng_context_copy_date(tr::now),
|
||||||
|
[date, show] {
|
||||||
|
const auto dateTime = QDateTime::fromSecsSinceEpoch(date);
|
||||||
|
const auto text = QLocale().toString(
|
||||||
|
dateTime,
|
||||||
|
QLocale::LongFormat);
|
||||||
|
TextUtilities::SetClipboardText(
|
||||||
|
TextForMimeData::Simple(text));
|
||||||
|
show->showToast(tr::lng_date_copied(tr::now));
|
||||||
|
},
|
||||||
|
&st::menuIconCopy);
|
||||||
|
|
||||||
|
const auto itemId = my.itemId;
|
||||||
|
const auto &owner = controller->session().data();
|
||||||
|
const auto item = owner.message(itemId);
|
||||||
|
const auto canForward = item
|
||||||
|
&& !item->forbidsForward()
|
||||||
|
&& item->history()->peer->allowsForwarding();
|
||||||
|
if (canForward) {
|
||||||
|
menu->addAction(
|
||||||
|
tr::lng_context_set_reminder(tr::now),
|
||||||
|
[itemId, show] {
|
||||||
|
const auto session = &show->session();
|
||||||
|
const auto item = session->data().message(itemId);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto self = session->user();
|
||||||
|
const auto history = self->owner().history(self);
|
||||||
|
show->showBox(HistoryView::PrepareScheduleBox(
|
||||||
|
session,
|
||||||
|
show,
|
||||||
|
SendMenu::Details{ .type = SendMenu::Type::Reminder },
|
||||||
|
[=](Api::SendOptions options) {
|
||||||
|
auto action = Api::SendAction(history, options);
|
||||||
|
action.clearDraft = false;
|
||||||
|
action.generateLocal = false;
|
||||||
|
session->api().forwardMessages(
|
||||||
|
Data::ResolvedForwardDraft{
|
||||||
|
.items = { item },
|
||||||
|
},
|
||||||
|
action);
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
&st::menuIconSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu->popup(QCursor::pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto FormattedDateClickHandler::getTextEntity() const -> TextEntity {
|
||||||
|
return { EntityType::FormattedDate, _entityData };
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/basic_click_handlers.h"
|
#include "ui/basic_click_handlers.h"
|
||||||
|
#include "ui/text/text_entity.h"
|
||||||
#include "data/data_msg_id.h"
|
#include "data/data_msg_id.h"
|
||||||
|
|
||||||
constexpr auto kPeerLinkPeerIdProperty = 0x01;
|
constexpr auto kPeerLinkPeerIdProperty = 0x01;
|
||||||
@@ -237,3 +238,16 @@ private:
|
|||||||
const TextEntity _entity;
|
const TextEntity _entity;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FormattedDateClickHandler : public ClickHandler {
|
||||||
|
public:
|
||||||
|
FormattedDateClickHandler(int32 date, FormattedDateFlags flags);
|
||||||
|
|
||||||
|
void onClick(ClickContext context) const override;
|
||||||
|
TextEntity getTextEntity() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32 _date = 0;
|
||||||
|
QString _entityData;
|
||||||
|
|
||||||
|
};
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "base/unixtime.h"
|
||||||
|
|
||||||
|
#include <QtCore/QDateTime>
|
||||||
|
#include <QtCore/QLocale>
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
namespace {
|
namespace {
|
||||||
@@ -114,6 +118,129 @@ const auto kBadPrefix = u"http://"_q;
|
|||||||
return cWorkingDir() + "tdata/angle_backend";
|
return cWorkingDir() + "tdata/angle_backend";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Ui::Text::FormattedDateResult FormatDateRelative(TimeId date) {
|
||||||
|
const auto now = base::unixtime::now();
|
||||||
|
const auto delta = int64(date) - int64(now);
|
||||||
|
const auto absDelta = std::abs(delta);
|
||||||
|
const auto future = (delta > 0);
|
||||||
|
auto text = QString();
|
||||||
|
auto nextUpdate = int32(0);
|
||||||
|
|
||||||
|
if (absDelta < 1) {
|
||||||
|
text = tr::lng_date_relative_now(tr::now);
|
||||||
|
nextUpdate = now + 1;
|
||||||
|
} else if (absDelta < 60) {
|
||||||
|
const auto count = int(absDelta);
|
||||||
|
text = (future
|
||||||
|
? tr::lng_date_relative_in_seconds
|
||||||
|
: tr::lng_date_relative_seconds_ago)(tr::now, lt_count, count);
|
||||||
|
nextUpdate = now + 1;
|
||||||
|
} else if (absDelta < 3600) {
|
||||||
|
const auto count = int(absDelta / 60);
|
||||||
|
text = (future
|
||||||
|
? tr::lng_date_relative_in_minutes
|
||||||
|
: tr::lng_date_relative_minutes_ago)(tr::now, lt_count, count);
|
||||||
|
nextUpdate = future
|
||||||
|
? ((count > 1)
|
||||||
|
? (date - (count - 1) * 60)
|
||||||
|
: (date - 59))
|
||||||
|
: (date + (count + 1) * 60);
|
||||||
|
} else if (absDelta < 86400) {
|
||||||
|
const auto count = int(absDelta / 3600);
|
||||||
|
text = (future
|
||||||
|
? tr::lng_date_relative_in_hours
|
||||||
|
: tr::lng_date_relative_hours_ago)(tr::now, lt_count, count);
|
||||||
|
nextUpdate = future
|
||||||
|
? ((count > 1)
|
||||||
|
? (date - (count - 1) * 3600)
|
||||||
|
: (date - 3599))
|
||||||
|
: (date + (count + 1) * 3600);
|
||||||
|
} else if (absDelta < 30 * 86400) {
|
||||||
|
const auto count = int(absDelta / 86400);
|
||||||
|
text = (future
|
||||||
|
? tr::lng_date_relative_in_days
|
||||||
|
: tr::lng_date_relative_days_ago)(tr::now, lt_count, count);
|
||||||
|
nextUpdate = future
|
||||||
|
? ((count > 1)
|
||||||
|
? (date - (count - 1) * 86400)
|
||||||
|
: (date - 86399))
|
||||||
|
: (date + (count + 1) * 86400);
|
||||||
|
} else if (absDelta < 365 * 86400) {
|
||||||
|
const auto count = int(absDelta / (30 * 86400));
|
||||||
|
text = (future
|
||||||
|
? tr::lng_date_relative_in_months
|
||||||
|
: tr::lng_date_relative_months_ago)(tr::now, lt_count, count);
|
||||||
|
nextUpdate = future
|
||||||
|
? ((count > 1)
|
||||||
|
? (date - (count - 1) * 30 * 86400)
|
||||||
|
: (date - 30 * 86400 + 1))
|
||||||
|
: (date + (count + 1) * 30 * 86400);
|
||||||
|
} else {
|
||||||
|
const auto count = int(absDelta / (365 * 86400));
|
||||||
|
text = (future
|
||||||
|
? tr::lng_date_relative_in_years
|
||||||
|
: tr::lng_date_relative_years_ago)(tr::now, lt_count, count);
|
||||||
|
nextUpdate = future
|
||||||
|
? ((count > 1)
|
||||||
|
? (date - (count - 1) * 365 * 86400)
|
||||||
|
: (date - 365 * 86400 + 1))
|
||||||
|
: (date + (count + 1) * 365 * 86400);
|
||||||
|
}
|
||||||
|
return { text, nextUpdate };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Ui::Text::FormattedDateResult FormatDateWithFlags(
|
||||||
|
TimeId date,
|
||||||
|
FormattedDateFlags flags) {
|
||||||
|
if (flags & FormattedDateFlag::Relative) {
|
||||||
|
return FormatDateRelative(date);
|
||||||
|
}
|
||||||
|
const auto dateTime = QDateTime::fromSecsSinceEpoch(date);
|
||||||
|
const auto locale = QLocale();
|
||||||
|
auto parts = QStringList();
|
||||||
|
const auto hasDayOfWeek = (flags
|
||||||
|
& FormattedDateFlag::DayOfWeek);
|
||||||
|
const auto hasShortDate = (flags
|
||||||
|
& FormattedDateFlag::ShortDate);
|
||||||
|
const auto hasLongDate = (flags
|
||||||
|
& FormattedDateFlag::LongDate);
|
||||||
|
const auto hasShortTime = (flags
|
||||||
|
& FormattedDateFlag::ShortTime);
|
||||||
|
const auto hasLongTime = (flags
|
||||||
|
& FormattedDateFlag::LongTime);
|
||||||
|
if (hasDayOfWeek && !hasShortDate) {
|
||||||
|
parts.push_back(locale.dayName(
|
||||||
|
dateTime.date().dayOfWeek()));
|
||||||
|
} else if (hasDayOfWeek) {
|
||||||
|
parts.push_back(locale.dayName(
|
||||||
|
dateTime.date().dayOfWeek(),
|
||||||
|
QLocale::ShortFormat));
|
||||||
|
}
|
||||||
|
if (hasLongDate) {
|
||||||
|
parts.push_back(locale.toString(
|
||||||
|
dateTime.date(),
|
||||||
|
QLocale::LongFormat));
|
||||||
|
} else if (hasShortDate) {
|
||||||
|
parts.push_back(locale.toString(
|
||||||
|
dateTime.date(),
|
||||||
|
QLocale::ShortFormat));
|
||||||
|
}
|
||||||
|
if (hasLongTime) {
|
||||||
|
parts.push_back(locale.toString(
|
||||||
|
dateTime.time(),
|
||||||
|
QLocale::LongFormat));
|
||||||
|
} else if (hasShortTime) {
|
||||||
|
parts.push_back(locale.toString(
|
||||||
|
dateTime.time(),
|
||||||
|
QLocale::ShortFormat));
|
||||||
|
}
|
||||||
|
auto text = parts.join(u" "_q);
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
text = locale.toString(dateTime, QLocale::ShortFormat);
|
||||||
|
}
|
||||||
|
return { text, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Ui::Text::MarkedContext TextContext(TextContextArgs &&args) {
|
Ui::Text::MarkedContext TextContext(TextContextArgs &&args) {
|
||||||
@@ -146,6 +273,7 @@ Ui::Text::MarkedContext TextContext(TextContextArgs &&args) {
|
|||||||
return {
|
return {
|
||||||
.repaint = std::move(args.repaint),
|
.repaint = std::move(args.repaint),
|
||||||
.customEmojiFactory = std::move(factory),
|
.customEmojiFactory = std::move(factory),
|
||||||
|
.formattedDateFactory = FormatDateWithFlags,
|
||||||
.other = std::move(args.details),
|
.other = std::move(args.details),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -267,6 +395,12 @@ std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
|
|||||||
return (my && my->session)
|
return (my && my->session)
|
||||||
? std::make_shared<BankCardClickHandler>(my->session, data.text)
|
? std::make_shared<BankCardClickHandler>(my->session, data.text)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
case EntityType::FormattedDate: {
|
||||||
|
const auto [date, flags] = DeserializeFormattedDateData(data.data);
|
||||||
|
if (date) {
|
||||||
|
return std::make_shared<FormattedDateClickHandler>(date, flags);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
return Integration::createLinkHandler(data, context);
|
return Integration::createLinkHandler(data, context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,6 +235,7 @@ Session::Session(not_null<Main::Session*> session)
|
|||||||
, _contactsList(Dialogs::SortMode::Name)
|
, _contactsList(Dialogs::SortMode::Name)
|
||||||
, _contactsNoChatsList(Dialogs::SortMode::Name)
|
, _contactsNoChatsList(Dialogs::SortMode::Name)
|
||||||
, _ttlCheckTimer([=] { checkTTLs(); })
|
, _ttlCheckTimer([=] { checkTTLs(); })
|
||||||
|
, _formattedDateTimer([=] { checkFormattedDateUpdates(); })
|
||||||
, _selfDestructTimer([=] { checkSelfDestructItems(); })
|
, _selfDestructTimer([=] { checkSelfDestructItems(); })
|
||||||
, _pollsClosingTimer([=] { checkPollsClosings(); })
|
, _pollsClosingTimer([=] { checkPollsClosings(); })
|
||||||
, _watchForOfflineTimer([=] { checkLocalUsersWentOffline(); })
|
, _watchForOfflineTimer([=] { checkLocalUsersWentOffline(); })
|
||||||
@@ -2805,6 +2806,49 @@ void Session::checkTTLs() {
|
|||||||
scheduleNextTTLs();
|
scheduleNextTTLs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::registerFormattedDateUpdate(
|
||||||
|
TimeId when,
|
||||||
|
not_null<HistoryView::Element*> view) {
|
||||||
|
_formattedDateUpdates[when].push_back(
|
||||||
|
base::make_weak(view.get()));
|
||||||
|
const auto nearest = _formattedDateUpdates.begin()->first;
|
||||||
|
if (nearest < when && _formattedDateTimer.isActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scheduleNextFormattedDateUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::scheduleNextFormattedDateUpdate() {
|
||||||
|
if (_formattedDateUpdates.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto nearest = _formattedDateUpdates.begin()->first;
|
||||||
|
const auto now = base::unixtime::now();
|
||||||
|
const auto maxTimeout = TimeId(86400);
|
||||||
|
const auto timeout = std::min(
|
||||||
|
std::max(now, nearest) - now,
|
||||||
|
maxTimeout);
|
||||||
|
_formattedDateTimer.callOnce(timeout * crl::time(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::checkFormattedDateUpdates() {
|
||||||
|
_formattedDateTimer.cancel();
|
||||||
|
const auto now = base::unixtime::now();
|
||||||
|
auto expired = std::vector<base::weak_ptr<HistoryView::Element>>();
|
||||||
|
while (!_formattedDateUpdates.empty()
|
||||||
|
&& _formattedDateUpdates.begin()->first <= now) {
|
||||||
|
auto &list = _formattedDateUpdates.begin()->second;
|
||||||
|
expired.insert(expired.end(), list.begin(), list.end());
|
||||||
|
_formattedDateUpdates.erase(_formattedDateUpdates.begin());
|
||||||
|
}
|
||||||
|
for (const auto &weak : expired) {
|
||||||
|
if (const auto strong = weak.get()) {
|
||||||
|
requestItemTextRefresh(strong->data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scheduleNextFormattedDateUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
void Session::processMessagesDeleted(
|
void Session::processMessagesDeleted(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
const QVector<MTPint> &data) {
|
const QVector<MTPint> &data) {
|
||||||
|
|||||||
@@ -528,6 +528,10 @@ public:
|
|||||||
void registerMessageTTL(TimeId when, not_null<HistoryItem*> item);
|
void registerMessageTTL(TimeId when, not_null<HistoryItem*> item);
|
||||||
void unregisterMessageTTL(TimeId when, not_null<HistoryItem*> item);
|
void unregisterMessageTTL(TimeId when, not_null<HistoryItem*> item);
|
||||||
|
|
||||||
|
void registerFormattedDateUpdate(
|
||||||
|
TimeId when,
|
||||||
|
not_null<HistoryView::Element*> view);
|
||||||
|
|
||||||
// Returns true if item found and it is not detached.
|
// Returns true if item found and it is not detached.
|
||||||
bool updateExistingMessage(const MTPDmessage &data);
|
bool updateExistingMessage(const MTPDmessage &data);
|
||||||
void updateEditedMessage(const MTPMessage &data);
|
void updateEditedMessage(const MTPMessage &data);
|
||||||
@@ -958,6 +962,9 @@ private:
|
|||||||
void scheduleNextTTLs();
|
void scheduleNextTTLs();
|
||||||
void checkTTLs();
|
void checkTTLs();
|
||||||
|
|
||||||
|
void scheduleNextFormattedDateUpdate();
|
||||||
|
void checkFormattedDateUpdates();
|
||||||
|
|
||||||
int computeUnreadBadge(const Dialogs::UnreadState &state) const;
|
int computeUnreadBadge(const Dialogs::UnreadState &state) const;
|
||||||
bool computeUnreadBadgeMuted(const Dialogs::UnreadState &state) const;
|
bool computeUnreadBadgeMuted(const Dialogs::UnreadState &state) const;
|
||||||
|
|
||||||
@@ -1147,6 +1154,9 @@ private:
|
|||||||
std::map<TimeId, base::flat_set<not_null<HistoryItem*>>> _ttlMessages;
|
std::map<TimeId, base::flat_set<not_null<HistoryItem*>>> _ttlMessages;
|
||||||
base::Timer _ttlCheckTimer;
|
base::Timer _ttlCheckTimer;
|
||||||
|
|
||||||
|
std::map<TimeId, std::vector<base::weak_ptr<HistoryView::Element>>> _formattedDateUpdates;
|
||||||
|
base::Timer _formattedDateTimer;
|
||||||
|
|
||||||
std::unordered_map<MsgId, not_null<HistoryItem*>> _nonChannelMessages;
|
std::unordered_map<MsgId, not_null<HistoryItem*>> _nonChannelMessages;
|
||||||
|
|
||||||
base::flat_map<uint64, FullMsgId> _messageByRandomId;
|
base::flat_map<uint64, FullMsgId> _messageByRandomId;
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ int KeyboardStyle::minButtonWidth(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (modification.added) {
|
if (modification.added) {
|
||||||
++result.to;
|
result.to += modification.added;
|
||||||
}
|
}
|
||||||
const auto shiftTo = std::min(
|
const auto shiftTo = std::min(
|
||||||
int(modification.skipped),
|
int(modification.skipped),
|
||||||
@@ -452,7 +452,7 @@ int KeyboardStyle::minButtonWidth(
|
|||||||
result.to -= shiftTo;
|
result.to -= shiftTo;
|
||||||
if (modification.position <= result.from) {
|
if (modification.position <= result.from) {
|
||||||
if (modification.added) {
|
if (modification.added) {
|
||||||
++result.from;
|
result.from += modification.added;
|
||||||
}
|
}
|
||||||
const auto shiftFrom = std::min(
|
const auto shiftFrom = std::min(
|
||||||
int(modification.skipped),
|
int(modification.skipped),
|
||||||
@@ -1866,6 +1866,9 @@ void Element::setTextWithLinks(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InitElementTextPart(this, _text);
|
InitElementTextPart(this, _text);
|
||||||
|
if (const auto next = _text.nextFormattedDateUpdate()) {
|
||||||
|
history()->session().data().registerFormattedDateUpdate(next, this);
|
||||||
|
}
|
||||||
_textWidth = -1;
|
_textWidth = -1;
|
||||||
_textHeight = 0;
|
_textHeight = 0;
|
||||||
}
|
}
|
||||||
@@ -2668,12 +2671,16 @@ SelectedQuote Element::FindSelectedQuote(
|
|||||||
modified.from += modification.skipped;
|
modified.from += modification.skipped;
|
||||||
if (modification.added
|
if (modification.added
|
||||||
&& modification.position < selection.from) {
|
&& modification.position < selection.from) {
|
||||||
--modified.from;
|
modified.from = uint16(std::max(
|
||||||
|
0,
|
||||||
|
int(modified.from) - int(modification.added)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
modified.to += modification.skipped;
|
modified.to += modification.skipped;
|
||||||
if (modification.added && modified.to > modified.from) {
|
if (modification.added && modified.to > modified.from) {
|
||||||
--modified.to;
|
modified.to = uint16(std::max(
|
||||||
|
int(modified.from),
|
||||||
|
int(modified.to) - int(modification.added)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto result = item->originalText();
|
auto result = item->originalText();
|
||||||
|
|||||||
+1
-1
Submodule Telegram/lib_ui updated: ed74b00b7e...1bb25b4a5a
Reference in New Issue
Block a user