Add UI to specify export time range.

This commit is contained in:
John Preston 2018-10-06 14:06:07 +03:00
parent 0f535a98a7
commit f362702856
11 changed files with 181 additions and 4 deletions

View File

@ -1744,6 +1744,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_export_option_location" = "Download path: {path}";
"lng_export_option_html" = "Human-readable HTML";
"lng_export_option_json" = "Machine-readable JSON";
"lng_export_limits" = "From: {from}, Till: {till}";
"lng_export_beginning" = "Beginning";
"lng_export_end" = "End";
"lng_export_from_beginning" = "From Beginning";
"lng_export_till_end" = "Till End";
"lng_export_start" = "Export";
"lng_export_state_initializing" = "Initializing...";
"lng_export_state_userpics" = "Profile pictures";

View File

@ -440,13 +440,19 @@ void CalendarBox::Title::paintEvent(QPaintEvent *e) {
p.drawTextLeft((width() - _textWidth) / 2, (height() - st::calendarTitleFont->height) / 2, width(), _text, _textWidth);
}
CalendarBox::CalendarBox(QWidget*, QDate month, QDate highlighted, Fn<void(QDate date)> callback)
CalendarBox::CalendarBox(
QWidget*,
QDate month,
QDate highlighted,
Fn<void(QDate date)> callback,
FnMut<void(not_null<CalendarBox*>)> finalize)
: _context(std::make_unique<Context>(month, highlighted))
, _inner(this, _context.get())
, _title(this, _context.get())
, _previous(this, st::calendarPrevious)
, _next(this, st::calendarNext)
, _callback(std::move(callback)) {
, _callback(std::move(callback))
, _finalize(std::move(finalize)) {
}
void CalendarBox::setMinDate(QDate date) {
@ -477,6 +483,10 @@ void CalendarBox::prepare() {
subscribe(_context->month(), [this](QDate month) { monthChanged(month); });
_context->start();
if (_finalize) {
_finalize(this);
}
}
bool CalendarBox::isPreviousEnabled() const {

View File

@ -15,7 +15,12 @@ class IconButton;
class CalendarBox : public BoxContent {
public:
CalendarBox(QWidget*, QDate month, QDate highlighted, Fn<void(QDate date)> callback);
CalendarBox(
QWidget*,
QDate month,
QDate highlighted,
Fn<void(QDate date)> callback,
FnMut<void(not_null<CalendarBox*>)> finalize = nullptr);
void setMinDate(QDate date);
void setMaxDate(QDate date);
@ -45,5 +50,6 @@ private:
object_ptr<Ui::IconButton> _next;
Fn<void(QDate date)> _callback;
FnMut<void(not_null<CalendarBox*>)> _finalize;
};

View File

@ -41,6 +41,8 @@ bool Settings::validate() const {
return false;
} else if (!media.validate()) {
return false;
} else if (singlePeerTill > 0 && singlePeerTill <= singlePeerFrom) {
return false;
}
return true;
};

View File

@ -78,6 +78,8 @@ struct Settings {
MediaSettings media;
MTPInputPeer singlePeer = MTP_inputPeerEmpty();
TimeId singlePeerFrom = 0;
TimeId singlePeerTill = 0;
TimeId availableAt = 0;

View File

@ -34,6 +34,7 @@ exportLocationLabel: FlatLabel(boxLabel) {
maxHeight: 21px;
}
exportLocationPadding: margins(22px, 8px, 22px, 8px);
exportLimitsPadding: margins(22px, 0px, 22px, 0px);
exportAboutOptionLabel: FlatLabel(defaultFlatLabel) {
textFg: windowSubTextFg;

View File

@ -158,6 +158,12 @@ void PanelController::showSettings() {
auto settings = base::make_unique_q<SettingsWidget>(
_panel,
*_settings);
settings->setShowBoxCallback([=](object_ptr<BoxContent> box) {
_panel->showBox(
std::move(box),
LayerOption::KeepOther,
anim::type::normal);
});
settings->startClicks(
) | rpl::start_with_next([=]() {

View File

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/fade_wrap.h"
#include "platform/platform_specific.h"
#include "core/file_utilities.h"
#include "boxes/calendar_box.h"
#include "auth_session.h"
#include "styles/style_widgets.h"
#include "styles/style_export.h"
@ -210,6 +211,7 @@ void SettingsWidget::setupPathAndFormat(
not_null<Ui::VerticalLayout*> container) {
if (_singlePeerId != 0) {
addLocationLabel(container);
addLimitsLabel(container);
return;
}
const auto formatGroup = std::make_shared<Ui::RadioenumGroup<Format>>(
@ -271,6 +273,126 @@ void SettingsWidget::addLocationLabel(
#endif // OS_MAC_STORE
}
void SettingsWidget::addLimitsLabel(
not_null<Ui::VerticalLayout*> container) {
auto pathLabel = value() | rpl::map([](const Settings &data) {
return std::make_tuple(data.singlePeerFrom, data.singlePeerTill);
}) | rpl::distinct_until_changed(
) | rpl::map([](TimeId from, TimeId till) {
const auto begin = from
? langDayOfMonthFull(ParseDateTime(from).date())
: lang(lng_export_beginning);
const auto end = till
? langDayOfMonthFull(ParseDateTime(till).date())
: lang(lng_export_end);
auto fromLink = TextWithEntities{ begin };
fromLink.entities.push_back(EntityInText(
EntityInTextCustomUrl,
0,
begin.size(),
QString("internal:edit_from")));
auto tillLink = TextWithEntities{ end };
tillLink.entities.push_back(EntityInText(
EntityInTextCustomUrl,
0,
end.size(),
QString("internal:edit_till")));
return lng_export_limits__generic<TextWithEntities>(
lt_from,
fromLink,
lt_till,
tillLink);
}) | rpl::after_next([=] {
container->resizeToWidth(container->width());
});
const auto label = container->add(
object_ptr<Ui::FlatLabel>(
container,
std::move(pathLabel),
st::exportLocationLabel),
st::exportLimitsPadding);
label->setClickHandlerFilter([=](
const ClickHandlerPtr &handler,
Qt::MouseButton) {
const auto url = handler->dragText();
if (url == qstr("internal:edit_from")) {
const auto done = [=](TimeId limit) {
changeData([&](Settings &settings) {
settings.singlePeerFrom = limit;
});
};
editDateLimit(
readData().singlePeerFrom,
0,
readData().singlePeerTill,
lng_export_from_beginning,
done);
} else if (url == qstr("internal:edit_till")) {
const auto done = [=](TimeId limit) {
changeData([&](Settings &settings) {
settings.singlePeerTill = limit;
});
};
editDateLimit(
readData().singlePeerTill,
readData().singlePeerFrom,
0,
lng_export_till_end,
done);
} else {
Unexpected("Click handler URL in export limits edit.");
}
return false;
});
}
void SettingsWidget::editDateLimit(
TimeId current,
TimeId min,
TimeId max,
LangKey resetLabel,
Fn<void(TimeId)> done) {
Expects(_showBoxCallback != nullptr);
const auto highlighted = current
? ParseDateTime(current).date()
: max
? ParseDateTime(max).date()
: min
? ParseDateTime(min).date()
: QDate::currentDate();
const auto month = highlighted;
const auto shared = std::make_shared<QPointer<CalendarBox>>();
const auto finalize = [=](not_null<CalendarBox*> box) {
box->setMaxDate(max
? ParseDateTime(max).date()
: QDate::currentDate());
box->setMinDate(min
? ParseDateTime(min).date()
: QDate(2013, 8, 1)); // Telegram was launched in August 2013 :)
box->addLeftButton(langFactory(resetLabel), crl::guard(this, [=] {
done(0);
if (const auto weak = shared->data()) {
weak->closeBox();
}
}));
};
const auto callback = crl::guard(this, [=](const QDate &date) {
done(ServerTimeFromParsed(QDateTime(date)));
if (const auto weak = shared->data()) {
weak->closeBox();
}
});
auto box = Box<CalendarBox>(
month,
highlighted,
callback,
finalize);
*shared = make_weak(box.data());
_showBoxCallback(std::move(box));
}
not_null<Ui::RpWidget*> SettingsWidget::setupButtons(
not_null<Ui::ScrollArea*> scroll,
not_null<Ui::RpWidget*> wrap) {

View File

@ -30,6 +30,10 @@ public:
rpl::producer<> startClicks() const;
rpl::producer<> cancelClicks() const;
void setShowBoxCallback(Fn<void(object_ptr<BoxContent>)> callback) {
_showBoxCallback = std::move(callback);
}
private:
using Type = Settings::Type;
using Types = Settings::Types;
@ -70,16 +74,26 @@ private:
void addSizeSlider(not_null<Ui::VerticalLayout*> container);
void addLocationLabel(
not_null<Ui::VerticalLayout*> container);
void addLimitsLabel(
not_null<Ui::VerticalLayout*> container);
void chooseFolder();
void refreshButtons(
not_null<Ui::RpWidget*> container,
bool canStart);
void editDateLimit(
TimeId current,
TimeId min,
TimeId max,
LangKey resetLabel,
Fn<void(TimeId)> done);
const Settings &readData() const;
template <typename Callback>
void changeData(Callback &&callback);
PeerId _singlePeerId = 0;
Fn<void(object_ptr<BoxContent>)> _showBoxCallback;
// Use through readData / changeData wrappers.
Settings _internal_data;

View File

@ -30,7 +30,8 @@ public:
[method = std::move(method), consumer](auto &&value) {
auto copy = method;
consumer.put_next_copy(value);
std::move(copy)(
details::callable_invoke(
std::move(copy),
std::forward<decltype(value)>(value));
}, [consumer](auto &&error) {
consumer.put_error_forward(

View File

@ -4345,6 +4345,8 @@ void WriteExportSettings(const Export::Settings &settings) {
}, [&](const MTPDinputPeerEmpty &) {
data.stream << kSinglePeerTypeEmpty;
});
data.stream << qint32(settings.singlePeerFrom);
data.stream << qint32(settings.singlePeerTill);
FileWriteDescriptor file(_exportSettingsKey);
file.writeEncrypted(data);
@ -4366,6 +4368,7 @@ Export::Settings ReadExportSettings() {
QString path;
qint32 singlePeerType = 0, singlePeerBareId = 0;
quint64 singlePeerAccessHash = 0;
qint32 singlePeerFrom = 0, singlePeerTill = 0;
file.stream
>> types
>> fullChats
@ -4387,6 +4390,9 @@ Export::Settings ReadExportSettings() {
default: return Export::Settings();
}
}
if (!file.stream.atEnd()) {
file.stream >> singlePeerFrom >> singlePeerTill;
}
auto result = Export::Settings();
result.types = Export::Settings::Types::from_raw(types);
result.fullChats = Export::Settings::Types::from_raw(fullChats);
@ -4414,6 +4420,8 @@ Export::Settings ReadExportSettings() {
}
Unexpected("Type in export data single peer.");
}();
result.singlePeerFrom = singlePeerFrom;
result.singlePeerTill = singlePeerTill;
return (file.stream.status() == QDataStream::Ok && result.validate())
? result
: Export::Settings();