From 5fb002ab4cdd06157e6231ef4f79177be4b8cc90 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 15 Feb 2025 19:08:35 +0300 Subject: [PATCH] Added ability to specify time when export data. --- .../export/view/export_view_settings.cpp | 137 +++++++++++++++++- Telegram/SourceFiles/ui/boxes/choose_time.cpp | 12 +- Telegram/SourceFiles/ui/boxes/choose_time.h | 3 +- 3 files changed, 145 insertions(+), 7 deletions(-) diff --git a/Telegram/SourceFiles/export/view/export_view_settings.cpp b/Telegram/SourceFiles/export/view/export_view_settings.cpp index fdb61a799..bc25b6039 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.cpp +++ b/Telegram/SourceFiles/export/view/export_view_settings.cpp @@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/layers/generic_box.h" #include "ui/text/text_utilities.h" #include "ui/boxes/calendar_box.h" +#include "ui/boxes/choose_time.h" #include "platform/platform_specific.h" #include "core/application.h" #include "core/file_utilities.h" @@ -388,7 +389,7 @@ void SettingsWidget::addFormatAndLocationLabel( void SettingsWidget::addLimitsLabel( not_null container) { - auto fromLink = value() | rpl::map([](const Settings &data) { + auto fromDateLink = value() | rpl::map([](const Settings &data) { return data.singlePeerFrom; }) | rpl::distinct_until_changed( ) | rpl::map([](TimeId from) { @@ -399,7 +400,34 @@ void SettingsWidget::addLimitsLabel( ) | Ui::Text::ToLink(u"internal:edit_from"_q); }) | rpl::flatten_latest(); - auto tillLink = value() | rpl::map([](const Settings &data) { + const auto mapToTime = [](TimeId id, const QString &link) { + return rpl::single(id + ? QLocale().toString( + base::unixtime::parse(id).time(), + QLocale::ShortFormat) + : QString() + ) | Ui::Text::ToLink(link); + }; + + const auto concat = [](TextWithEntities date, TextWithEntities link) { + return link.text.isEmpty() + ? date + : date.append(u", "_q).append(std::move(link)); + }; + + auto fromTimeLink = value() | rpl::map([](const Settings &data) { + return data.singlePeerFrom; + }) | rpl::distinct_until_changed( + ) | rpl::map([=](TimeId from) { + return mapToTime(from, u"internal:edit_from_time"_q); + }) | rpl::flatten_latest(); + + auto fromLink = rpl::combine( + std::move(fromDateLink), + std::move(fromTimeLink) + ) | rpl::map(concat); + + auto tillDateLink = value() | rpl::map([](const Settings &data) { return data.singlePeerTill; }) | rpl::distinct_until_changed( ) | rpl::map([](TimeId till) { @@ -410,6 +438,18 @@ void SettingsWidget::addLimitsLabel( ) | Ui::Text::ToLink(u"internal:edit_till"_q); }) | rpl::flatten_latest(); + auto tillTimeLink = value() | rpl::map([](const Settings &data) { + return data.singlePeerTill; + }) | rpl::distinct_until_changed( + ) | rpl::map([=](TimeId till) { + return mapToTime(till, u"internal:edit_till_time"_q); + }) | rpl::flatten_latest(); + + auto tillLink = rpl::combine( + std::move(tillDateLink), + std::move(tillTimeLink) + ) | rpl::map(concat); + auto datesText = tr::lng_export_limits( lt_from, std::move(fromLink), @@ -424,8 +464,47 @@ void SettingsWidget::addLimitsLabel( object_ptr( container, std::move(datesText), - st::exportLocationLabel), + st::boxLabel), st::exportLimitsPadding); + + const auto removeTime = [](TimeId dateTime) { + return base::unixtime::serialize( + QDateTime( + base::unixtime::parse(dateTime).date(), + QTime())); + }; + + const auto editTimeLimit = [=](Fn now, Fn done) { + _showBoxCallback(Box([=](not_null box) { + auto result = Ui::ChooseTimeWidget( + box->verticalLayout(), + [&] { + const auto time = base::unixtime::parse(now()).time(); + return time.hour() * 3600 + + time.minute() * 60 + + time.second(); + }(), + true); + const auto widget = box->addRow(std::move(result.widget)); + const auto toSave = widget->lifetime().make_state(0); + std::move( + result.secondsValue + ) | rpl::start_with_next([=](TimeId t) { + *toSave = t; + }, box->lifetime()); + box->addButton(tr::lng_settings_save(), [=] { + done(*toSave); + box->closeBox(); + }); + box->addButton(tr::lng_cancel(), [=] { + box->closeBox(); + }); + box->setTitle(tr::lng_settings_ttl_after_custom()); + })); + }; + + constexpr auto kOffset = 600; + label->overrideLinkClickHandler([=](const QString &url) { if (url == u"internal:edit_from"_q) { const auto done = [=](TimeId limit) { @@ -439,10 +518,38 @@ void SettingsWidget::addLimitsLabel( readData().singlePeerTill, tr::lng_export_from_beginning(), done); + } else if (url == u"internal:edit_from_time"_q) { + const auto now = [=] { + auto result = TimeId(0); + changeData([&](Settings &settings) { + result = settings.singlePeerFrom; + }); + return result; + }; + const auto done = [=](TimeId time) { + changeData([&](Settings &settings) { + const auto result = time + + removeTime(settings.singlePeerFrom); + if (result >= settings.singlePeerTill + && settings.singlePeerTill) { + settings.singlePeerFrom = settings.singlePeerTill + - kOffset; + } else { + settings.singlePeerFrom = result; + } + }); + }; + editTimeLimit(now, done); } else if (url == u"internal:edit_till"_q) { const auto done = [=](TimeId limit) { changeData([&](Settings &settings) { - settings.singlePeerTill = limit; + if (limit <= settings.singlePeerFrom + && settings.singlePeerFrom) { + settings.singlePeerTill = settings.singlePeerFrom + + kOffset; + } else { + settings.singlePeerTill = limit; + } }); }; editDateLimit( @@ -451,6 +558,28 @@ void SettingsWidget::addLimitsLabel( 0, tr::lng_export_till_end(), done); + } else if (url == u"internal:edit_till_time"_q) { + const auto now = [=] { + auto result = TimeId(0); + changeData([&](Settings &settings) { + result = settings.singlePeerTill; + }); + return result; + }; + const auto done = [=](TimeId time) { + changeData([&](Settings &settings) { + const auto result = time + + removeTime(settings.singlePeerTill); + if (result <= settings.singlePeerFrom + && settings.singlePeerFrom) { + settings.singlePeerTill = settings.singlePeerFrom + + kOffset; + } else { + settings.singlePeerTill = result; + } + }); + }; + editTimeLimit(now, done); } else { Unexpected("Click handler URL in export limits edit."); } diff --git a/Telegram/SourceFiles/ui/boxes/choose_time.cpp b/Telegram/SourceFiles/ui/boxes/choose_time.cpp index 488c1c0d3..aa7f2836e 100644 --- a/Telegram/SourceFiles/ui/boxes/choose_time.cpp +++ b/Telegram/SourceFiles/ui/boxes/choose_time.cpp @@ -18,7 +18,8 @@ namespace Ui { ChooseTimeResult ChooseTimeWidget( not_null parent, - TimeId startSeconds) { + TimeId startSeconds, + bool hiddenDaysInput) { using TimeField = Ui::TimePartWithPlaceholder; const auto putNext = [](not_null field, QChar ch) { field->setCursorPosition(0); @@ -79,6 +80,10 @@ ChooseTimeResult ChooseTimeWidget( const auto hour = Ui::MakeWeak(state->hour); const auto minute = Ui::MakeWeak(state->minute); + if (hiddenDaysInput) { + day->setVisible(false); + } + day->setPhrase(tr::lng_days); day->setMaxValue(31); day->setWheelStep(1); @@ -105,13 +110,16 @@ ChooseTimeResult ChooseTimeWidget( content->sizeValue( ) | rpl::start_with_next([=](const QSize &s) { - const auto inputWidth = s.width() / 3; + const auto inputWidth = s.width() / (hiddenDaysInput ? 2 : 3); auto rect = QRect( 0, (s.height() - day->height()) / 2, inputWidth, day->height()); for (const auto &input : { day, hour, minute }) { + if (input->isHidden()) { + continue; + } input->setGeometry(rect - st::muteBoxTimeFieldPadding); rect.translate(inputWidth, 0); } diff --git a/Telegram/SourceFiles/ui/boxes/choose_time.h b/Telegram/SourceFiles/ui/boxes/choose_time.h index ca25710cf..d2f7f1ee7 100644 --- a/Telegram/SourceFiles/ui/boxes/choose_time.h +++ b/Telegram/SourceFiles/ui/boxes/choose_time.h @@ -20,6 +20,7 @@ struct ChooseTimeResult { ChooseTimeResult ChooseTimeWidget( not_null parent, - TimeId startSeconds); + TimeId startSeconds, + bool hiddenDaysInput = false); } // namespace Ui