From 844d030332fff00e403d5e3917164fb8a11f04af Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 22 Jun 2018 22:32:00 +0100 Subject: [PATCH] Save export settings to local storage. --- .../SourceFiles/core/click_handler_types.h | 2 +- .../SourceFiles/export/export_settings.cpp | 48 +++++ Telegram/SourceFiles/export/export_settings.h | 9 + .../view/export_view_panel_controller.cpp | 46 ++++- .../view/export_view_panel_controller.h | 5 + .../export/view/export_view_settings.cpp | 165 +++++++++++------- .../export/view/export_view_settings.h | 24 ++- Telegram/SourceFiles/storage/localstorage.cpp | 84 ++++++++- Telegram/SourceFiles/storage/localstorage.h | 7 + Telegram/gyp/lib_export.gyp | 1 + 10 files changed, 312 insertions(+), 79 deletions(-) create mode 100644 Telegram/SourceFiles/export/export_settings.cpp diff --git a/Telegram/SourceFiles/core/click_handler_types.h b/Telegram/SourceFiles/core/click_handler_types.h index f9c472d5ac370d..860e3db15c1858 100644 --- a/Telegram/SourceFiles/core/click_handler_types.h +++ b/Telegram/SourceFiles/core/click_handler_types.h @@ -87,7 +87,7 @@ class HiddenUrlClickHandler : public UrlClickHandler { HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) { } QString copyToClipboardContextItemText() const override { - return url().isEmpty() + return (url().isEmpty() || url().startsWith(qstr("internal:"))) ? QString() : UrlClickHandler::copyToClipboardContextItemText(); } diff --git a/Telegram/SourceFiles/export/export_settings.cpp b/Telegram/SourceFiles/export/export_settings.cpp new file mode 100644 index 00000000000000..082f90bcdfb420 --- /dev/null +++ b/Telegram/SourceFiles/export/export_settings.cpp @@ -0,0 +1,48 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "export/export_settings.h" + +#include "export/output/export_output_abstract.h" + +namespace Export { +namespace { + +constexpr auto kMaxFileSize = 1500 * 1024 * 1024; + +} // namespace + +bool MediaSettings::validate() const { + if ((types | Type::AllMask) != Type::AllMask) { + return false; + } else if (sizeLimit < 0 || sizeLimit > kMaxFileSize) { + return false; + } + return true; +} + +bool Settings::validate() const { + using Format = Output::Format; + const auto MustBeFull = Type::PersonalChats | Type::BotChats; + const auto MustNotBeFull = Type::PublicGroups | Type::PublicChannels; + if ((types | Type::AllMask) != Type::AllMask) { + return false; + } else if ((fullChats | Type::AllMask) != Type::AllMask) { + return false; + } else if ((fullChats & MustBeFull) != MustBeFull) { + return false; + } else if ((fullChats & MustNotBeFull) != 0) { + return false; + } else if (format != Format::Text && format != Format::Json) { + return false; + } else if (!media.validate()) { + return false; + } + return true; +}; + +} // namespace Export diff --git a/Telegram/SourceFiles/export/export_settings.h b/Telegram/SourceFiles/export/export_settings.h index eb6ea4bee3324a..355d46a3c537d2 100644 --- a/Telegram/SourceFiles/export/export_settings.h +++ b/Telegram/SourceFiles/export/export_settings.h @@ -16,6 +16,8 @@ enum class Format; } // namespace Output struct MediaSettings { + bool validate() const; + enum class Type { Photo = 0x01, Video = 0x02, @@ -24,6 +26,9 @@ struct MediaSettings { Sticker = 0x10, GIF = 0x20, File = 0x40, + + MediaMask = Photo | Video | VoiceMessage | VideoMessage, + AllMask = MediaMask | Sticker | GIF | File, }; using Types = base::flags; friend inline constexpr auto is_flag_type(Type) { return true; }; @@ -38,6 +43,8 @@ struct MediaSettings { }; struct Settings { + bool validate() const; + enum class Type { PersonalInfo = 0x001, Userpics = 0x002, @@ -55,6 +62,8 @@ struct Settings { GroupsChannelsMask = GroupsMask | ChannelsMask, NonChannelChatsMask = PersonalChats | BotChats | PrivateGroups, AnyChatsMask = PersonalChats | BotChats | GroupsChannelsMask, + NonChatsMask = PersonalInfo | Userpics | Contacts | Sessions, + AllMask = NonChatsMask | AnyChatsMask, }; using Types = base::flags; friend inline constexpr auto is_flag_type(Type) { return true; }; diff --git a/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp b/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp index 551f60d0f16a68..020e95a60e543f 100644 --- a/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp +++ b/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp @@ -14,7 +14,9 @@ For license and copyright information please follow this link: #include "ui/wrap/padding_wrap.h" #include "boxes/confirm_box.h" #include "lang/lang_keys.h" +#include "storage/localstorage.h" #include "core/file_utilities.h" +#include "platform/platform_specific.h" #include "styles/style_export.h" #include "styles/style_boxes.h" @@ -23,11 +25,19 @@ namespace View { namespace { constexpr auto kAddDelay = TimeId(60); +constexpr auto kSaveSettingsTimeout = TimeMs(1000); } // namespace PanelController::PanelController(not_null process) -: _process(process) { +: _process(process) +, _settings(std::make_unique(Local::ReadExportSettings())) +, _saveSettingsTimer([=] { saveSettings(); }) { + if (_settings->path.isEmpty()) { + _settings->path = psDownloadPath(); + } + _settings->internalLinksDomain = Global::InternalLinksDomain(); + _process->state( ) | rpl::start_with_next([=](State &&state) { updateState(std::move(state)); @@ -52,12 +62,14 @@ void PanelController::createPanel() { } void PanelController::showSettings() { - auto settings = base::make_unique_q(_panel); + auto settings = base::make_unique_q( + _panel, + *_settings); settings->startClicks( - ) | rpl::start_with_next([=](const Settings &settings) { + ) | rpl::start_with_next([=]() { showProgress(); - _process->startExport(settings); + _process->startExport(*_settings); }, settings->lifetime()); settings->cancelClicks( @@ -65,6 +77,12 @@ void PanelController::showSettings() { _panel->hideGetDuration(); }, settings->lifetime()); + settings->changes( + ) | rpl::start_with_next([=](Settings &&settings) { + *_settings = std::move(settings); + _saveSettingsTimer.callOnce(kSaveSettingsTimeout); + }, settings->lifetime()); + _panel->showInner(std::move(settings)); } @@ -218,7 +236,25 @@ void PanelController::updateState(State &&state) { } } -PanelController::~PanelController() = default; +void PanelController::saveSettings() const { + const auto check = [](const QString &value) { + const auto result = value.endsWith('/') + ? value.mid(0, value.size() - 1) + : value; + return (cPlatform() == dbipWindows) ? result.toLower() : result; + }; + auto settings = *_settings; + if (check(settings.path) == check(psDownloadPath())) { + settings.path = QString(); + } + Local::WriteExportSettings(settings); +} + +PanelController::~PanelController() { + if (_saveSettingsTimer.isActive()) { + saveSettings(); + } +} } // namespace View } // namespace Export diff --git a/Telegram/SourceFiles/export/view/export_view_panel_controller.h b/Telegram/SourceFiles/export/view/export_view_panel_controller.h index cd31890598dc70..0656f243edbd6a 100644 --- a/Telegram/SourceFiles/export/view/export_view_panel_controller.h +++ b/Telegram/SourceFiles/export/view/export_view_panel_controller.h @@ -10,6 +10,7 @@ For license and copyright information please follow this link: #include "export/export_controller.h" #include "export/view/export_view_content.h" #include "base/unique_qptr.h" +#include "base/timer.h" class BoxContent; @@ -52,7 +53,11 @@ class PanelController { void showError(const QString &text); void showCriticalError(const QString &text); + void saveSettings() const; + not_null _process; + std::unique_ptr _settings; + base::Timer _saveSettingsTimer; base::unique_qptr _panel; diff --git a/Telegram/SourceFiles/export/view/export_view_settings.cpp b/Telegram/SourceFiles/export/view/export_view_settings.cpp index 9dd430929daf6d..8ca45c9a287494 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.cpp +++ b/Telegram/SourceFiles/export/view/export_view_settings.cpp @@ -57,14 +57,22 @@ int SizeLimitByIndex(int index) { } // namespace -SettingsWidget::SettingsWidget(QWidget *parent) -: RpWidget(parent) { - _data.path = psDownloadPath(); - _data.internalLinksDomain = Global::InternalLinksDomain(); - +SettingsWidget::SettingsWidget(QWidget *parent, Settings data) +: RpWidget(parent) +, _internal_data(std::move(data)) { setupContent(); } +const Settings &SettingsWidget::readData() const { + return _internal_data; +} + +template +void SettingsWidget::changeData(Callback &&callback) { + callback(_internal_data); + _changes.fire_copy(_internal_data); +} + void SettingsWidget::setupContent() { const auto scroll = Ui::CreateChild( this, @@ -78,8 +86,6 @@ void SettingsWidget::setupContent() { setupOptions(content); setupPathAndFormat(content); - _refreshButtons.fire({}); - sizeValue( ) | rpl::start_with_next([=](QSize size) { scroll->resize(size.width(), size.height() - buttons->height()); @@ -138,8 +144,9 @@ void SettingsWidget::setupMediaOptions( addMediaOption(media, lng_export_option_files, MediaType::File); addSizeSlider(media); - _dataTypesChanges.events_starting_with_copy( - _data.types + value() | rpl::map([](const Settings &data) { + return data.types; + }) | rpl::distinct_until_changed( ) | rpl::start_with_next([=](Settings::Types types) { mediaWrap->toggle((types & (Type::PersonalChats | Type::BotChats @@ -158,9 +165,11 @@ void SettingsWidget::setupMediaOptions( void SettingsWidget::setupPathAndFormat( not_null container) { const auto formatGroup = std::make_shared>( - _data.format); + readData().format); formatGroup->setChangedCallback([=](Format format) { - _data.format = format; + changeData([&](Settings &data) { + data.format = format; + }); }); const auto addFormatOption = [&](LangKey key, Format format) { const auto radio = container->add( @@ -180,10 +189,17 @@ void SettingsWidget::setupPathAndFormat( void SettingsWidget::addLocationLabel( not_null container) { - auto pathLabel = _locationChanges.events_starting_with_copy( - _data.path + auto pathLabel = value() | rpl::map([](const Settings &data) { + return data.path; + }) | rpl::distinct_until_changed( ) | rpl::map([](const QString &path) { - const auto text = (path == psDownloadPath()) + const auto check = [](const QString &value) { + const auto result = value.endsWith('/') + ? value.mid(0, value.size() - 1) + : value; + return (cPlatform() == dbipWindows) ? result.toLower() : result; + }; + const auto text = (check(path) == check(psDownloadPath())) ? QString("Downloads/Telegram Desktop") : path; auto pathLink = TextWithEntities{ @@ -194,7 +210,7 @@ void SettingsWidget::addLocationLabel( EntityInTextCustomUrl, 0, text.size(), - "internal:edit_export_path")); + QString("internal:edit_export_path"))); return lng_export_option_location__generic( lt_path, pathLink); @@ -236,9 +252,11 @@ not_null SettingsWidget::setupButtons( return top < scroll->scrollTopMax(); })); - _refreshButtons.events( - ) | rpl::start_with_next([=] { - refreshButtons(buttons); + value() | rpl::map([](const Settings &data) { + return data.types != Types(0); + }) | rpl::distinct_until_changed( + ) | rpl::start_with_next([=](bool canStart) { + refreshButtons(buttons, canStart); topShadow->raise(); bottomShadow->raise(); }, buttons->lifetime()); @@ -276,19 +294,19 @@ not_null SettingsWidget::addOption( object_ptr( container, lang(key), - ((_data.types & types) == types), + ((readData().types & types) == types), st::defaultBoxCheckbox), st::exportSettingPadding); base::ObservableViewer( checkbox->checkedChanged ) | rpl::start_with_next([=](bool checked) { - if (checked) { - _data.types |= types; - } else { - _data.types &= ~types; - } - _dataTypesChanges.fire_copy(_data.types); - _refreshButtons.fire({}); + changeData([&](Settings &data) { + if (checked) { + data.types |= types; + } else { + data.types &= ~types; + } + }); }, lifetime()); return checkbox; } @@ -304,18 +322,20 @@ void SettingsWidget::addChatOption( object_ptr( container, lang(lng_export_option_only_my), - ((_data.fullChats & types) != types), + ((readData().fullChats & types) != types), st::defaultBoxCheckbox), st::exportSubSettingPadding)); base::ObservableViewer( onlyMy->entity()->checkedChanged ) | rpl::start_with_next([=](bool checked) { - if (checked) { - _data.fullChats &= ~types; - } else { - _data.fullChats |= types; - } + changeData([&](Settings &data) { + if (checked) { + data.fullChats &= ~types; + } else { + data.fullChats |= types; + } + }); }, checkbox->lifetime()); onlyMy->toggleOn(base::ObservableViewer( @@ -338,18 +358,19 @@ void SettingsWidget::addMediaOption( object_ptr( container, lang(key), - ((_data.media.types & type) == type), + ((readData().media.types & type) == type), st::defaultBoxCheckbox), st::exportSettingPadding); base::ObservableViewer( checkbox->checkedChanged ) | rpl::start_with_next([=](bool checked) { - if (checked) { - _data.media.types |= type; - } else { - _data.media.types &= ~type; - } - _refreshButtons.fire({}); + changeData([&](Settings &data) { + if (checked) { + data.media.types |= type; + } else { + data.media.types &= ~type; + } + }); }, lifetime()); } @@ -364,7 +385,7 @@ void SettingsWidget::addSizeSlider( slider->setAlwaysDisplayMarker(true); slider->setDirection(Ui::ContinuousSlider::Direction::Horizontal); for (auto i = 0; i != kSizeValueCount + 1; ++i) { - if (_data.media.sizeLimit <= SizeLimitByIndex(i)) { + if (readData().media.sizeLimit <= SizeLimitByIndex(i)) { slider->setValue(i / float64(kSizeValueCount)); break; } @@ -373,24 +394,26 @@ void SettingsWidget::addSizeSlider( const auto label = Ui::CreateChild( container.get(), st::exportFileSizeLabel); - const auto refreshSizeLimit = [=] { - const auto limit = _data.media.sizeLimit / kMegabyte; - const auto size = ((limit > 0) - ? QString::number(limit) - : QString::number(float64(_data.media.sizeLimit) / kMegabyte)) - + " MB"; - const auto text = lng_export_option_size_limit(lt_size, size); - label->setText(text); - }; slider->setAdjustCallback([=](float64 value) { return std::round(value * kSizeValueCount) / kSizeValueCount; }); slider->setChangeProgressCallback([=](float64 value) { const auto index = int(std::round(value * kSizeValueCount)); - _data.media.sizeLimit = SizeLimitByIndex(index); - refreshSizeLimit(); + changeData([&](Settings &data) { + data.media.sizeLimit = SizeLimitByIndex(index); + }); }); - refreshSizeLimit(); + value() | rpl::map([](const Settings &data) { + return data.media.sizeLimit; + }) | rpl::start_with_next([=](int sizeLimit) { + const auto limit = sizeLimit / kMegabyte; + const auto size = ((limit > 0) + ? QString::number(limit) + : QString::number(float64(sizeLimit) / kMegabyte)) + + " MB"; + const auto text = lng_export_option_size_limit(lt_size, size); + label->setText(text); + }, slider->lifetime()); rpl::combine( label->widthValue(), @@ -404,7 +427,9 @@ void SettingsWidget::addSizeSlider( } -void SettingsWidget::refreshButtons(not_null container) { +void SettingsWidget::refreshButtons( + not_null container, + bool canStart) { container->hideChildren(); const auto children = container->children(); for (const auto child : children) { @@ -412,7 +437,7 @@ void SettingsWidget::refreshButtons(not_null container) { child->deleteLater(); } } - const auto start = _data.types + const auto start = canStart ? Ui::CreateChild( container.get(), langFactory(lng_export_start), @@ -420,9 +445,7 @@ void SettingsWidget::refreshButtons(not_null container) { : nullptr; if (start) { start->show(); - start->addClickHandler([=] { - _startClicks.fire(base::duplicate(_data)); - }); + _startClicks = start->clicks(); container->sizeValue( ) | rpl::start_with_next([=](QSize size) { @@ -451,15 +474,31 @@ void SettingsWidget::refreshButtons(not_null container) { } void SettingsWidget::chooseFolder() { - const auto ready = [=](QString &&result) { - _data.path = result; - _locationChanges.fire(std::move(result)); + const auto callback = [=](QString &&result) { + changeData([&](Settings &data) { + data.path = std::move(result); + }); }; - FileDialog::GetFolder(this, lang(lng_export_folder), _data.path, ready); + FileDialog::GetFolder( + this, + lang(lng_export_folder), + readData().path, + callback); } -rpl::producer SettingsWidget::startClicks() const { - return _startClicks.events(); +rpl::producer SettingsWidget::changes() const { + return _changes.events(); +} + +rpl::producer SettingsWidget::value() const { + return rpl::single(readData()) | rpl::then(changes()); +} + +rpl::producer<> SettingsWidget::startClicks() const { + return _startClicks.value( + ) | rpl::map([](Wrap &&wrap) { + return std::move(wrap.value); + }) | rpl::flatten_latest(); } rpl::producer<> SettingsWidget::cancelClicks() const { diff --git a/Telegram/SourceFiles/export/view/export_view_settings.h b/Telegram/SourceFiles/export/view/export_view_settings.h index b5794c365ddd8a..227712c8faddd1 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.h +++ b/Telegram/SourceFiles/export/view/export_view_settings.h @@ -23,9 +23,11 @@ namespace View { class SettingsWidget : public Ui::RpWidget { public: - SettingsWidget(QWidget *parent); + SettingsWidget(QWidget *parent, Settings data); - rpl::producer startClicks() const; + rpl::producer value() const; + rpl::producer changes() const; + rpl::producer<> startClicks() const; rpl::producer<> cancelClicks() const; private: @@ -61,9 +63,17 @@ class SettingsWidget : public Ui::RpWidget { void addLocationLabel( not_null container); void chooseFolder(); - void refreshButtons(not_null container); + void refreshButtons( + not_null container, + bool canStart); + + const Settings &readData() const; + template + void changeData(Callback &&callback); + + // Use through readData / changeData wrappers. + Settings _internal_data; - Settings _data; struct Wrap { Wrap(rpl::producer<> value = rpl::never<>()) : value(std::move(value)) { @@ -71,11 +81,9 @@ class SettingsWidget : public Ui::RpWidget { rpl::producer<> value; }; - rpl::event_stream _startClicks; + rpl::event_stream _changes; + rpl::variable _startClicks; rpl::variable _cancelClicks; - rpl::event_stream _dataTypesChanges; - rpl::event_stream<> _refreshButtons; - rpl::event_stream _locationChanges; }; diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 01858b2ef8d863..57d7c03db3263c 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -13,6 +13,7 @@ For license and copyright information please follow this link: #include "data/data_drafts.h" #include "boxes/send_files_box.h" #include "window/themes/window_theme.h" +#include "export/export_settings.h" #include "core/crash_reports.h" #include "core/update_checker.h" #include "observer_peer.h" @@ -501,6 +502,7 @@ enum { // Local Storage Keys lskStickersKeys = 0x10, // no data lskTrustedBots = 0x11, // no data lskFavedStickers = 0x12, // no data + lskExportSettings = 0x13, // no data }; enum { @@ -634,6 +636,8 @@ FileKey _userSettingsKey = 0; FileKey _recentHashtagsAndBotsKey = 0; bool _recentHashtagsAndBotsWereRead = false; +FileKey _exportSettingsKey = 0; + FileKey _savedPeersKey = 0; FileKey _langPackKey = 0; @@ -2065,7 +2069,7 @@ ReadMapState _readMap(const QByteArray &pass) { quint64 recentStickersKeyOld = 0; quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, favedStickersKey = 0, archivedStickersKey = 0; quint64 savedGifsKey = 0; - quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0; + quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0, exportSettingsKey = 0; while (!map.stream.atEnd()) { quint32 keyType; map.stream >> keyType; @@ -2167,6 +2171,9 @@ ReadMapState _readMap(const QByteArray &pass) { case lskSavedPeers: { map.stream >> savedPeersKey; } break; + case lskExportSettings: { + map.stream >> exportSettingsKey; + } break; default: LOG(("App Error: unknown key type in encrypted map: %1").arg(keyType)); return ReadMapFailed; @@ -2201,6 +2208,7 @@ ReadMapState _readMap(const QByteArray &pass) { _backgroundKey = backgroundKey; _userSettingsKey = userSettingsKey; _recentHashtagsAndBotsKey = recentHashtagsAndBotsKey; + _exportSettingsKey = exportSettingsKey; _oldMapVersion = mapData.version; if (_oldMapVersion < AppVersion) { _mapChanged = true; @@ -2279,6 +2287,7 @@ void _writeMap(WriteMapWhen when) { if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_recentHashtagsAndBotsKey) mapSize += sizeof(quint32) + sizeof(quint64); + if (_exportSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (mapSize > 30 * 1024 * 1024) { CrashReports::SetAnnotation("MapSize", QString("%1,%2,%3,%4,%5" @@ -2356,6 +2365,9 @@ void _writeMap(WriteMapWhen when) { if (_recentHashtagsAndBotsKey) { mapData.stream << quint32(lskRecentHashtagsAndBots) << quint64(_recentHashtagsAndBotsKey); } + if (_exportSettingsKey) { + mapData.stream << quint32(lskExportSettings) << quint64(_exportSettingsKey); + } map.writeEncrypted(mapData); _mapChanged = false; @@ -2613,7 +2625,7 @@ void reset() { _recentStickersKeyOld = 0; _installedStickersKey = _featuredStickersKey = _recentStickersKey = _favedStickersKey = _archivedStickersKey = 0; _savedGifsKey = 0; - _backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0; + _backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = _exportSettingsKey = 0; _oldMapVersion = _oldSettingsVersion = 0; StoredAuthSessionCache.reset(); _mapChanged = true; @@ -4602,6 +4614,74 @@ void readRecentHashtagsAndBots() { } } +void WriteExportSettings(const Export::Settings &settings) { + if (!_working()) return; + + const auto check = Export::Settings(); + if (settings.types == check.types + && settings.fullChats == check.fullChats + && settings.media.types == check.media.types + && settings.media.sizeLimit == check.media.sizeLimit + && settings.path == check.path + && settings.format == check.format) { + if (_exportSettingsKey) { + clearKey(_exportSettingsKey); + _exportSettingsKey = 0; + _mapChanged = true; + } + _writeMap(); + } else { + if (!_exportSettingsKey) { + _exportSettingsKey = genKey(); + _mapChanged = true; + _writeMap(WriteMapWhen::Fast); + } + quint32 size = sizeof(quint32) * 5 + + Serialize::stringSize(settings.path); + EncryptedDescriptor data(size); + data.stream + << quint32(settings.types) + << quint32(settings.fullChats) + << quint32(settings.media.types) + << quint32(settings.media.sizeLimit) + << quint32(settings.format) + << settings.path; + + FileWriteDescriptor file(_exportSettingsKey); + file.writeEncrypted(data); + } +} + +Export::Settings ReadExportSettings() { + FileReadDescriptor file; + if (!readEncryptedFile(file, _exportSettingsKey)) { + clearKey(_exportSettingsKey); + _exportSettingsKey = 0; + _writeMap(); + return Export::Settings(); + } + + quint32 types = 0, fullChats = 0; + quint32 mediaTypes = 0, mediaSizeLimit = 0; + quint32 format = 0; + QString path; + file.stream + >> types + >> fullChats + >> mediaTypes + >> mediaSizeLimit + >> format + >> path; + auto result = Export::Settings(); + result.types = Export::Settings::Types::from_raw(types); + result.fullChats = Export::Settings::Types::from_raw(fullChats); + result.media.types = Export::MediaSettings::Types::from_raw(mediaTypes); + result.media.sizeLimit = mediaSizeLimit; + result.format = Export::Output::Format(format); + result.path = path; + return result.validate() ? result : Export::Settings(); +} + void writeSavedPeers() { if (!_working()) return; diff --git a/Telegram/SourceFiles/storage/localstorage.h b/Telegram/SourceFiles/storage/localstorage.h index 8dd307a60da2d8..d8c317a731761d 100644 --- a/Telegram/SourceFiles/storage/localstorage.h +++ b/Telegram/SourceFiles/storage/localstorage.h @@ -17,6 +17,10 @@ struct Cached; } // namespace Theme } // namespace Window +namespace Export { +struct Settings; +} // namespace Export + namespace Local { void start(); @@ -162,6 +166,9 @@ void writeLangPack(); void writeRecentHashtagsAndBots(); void readRecentHashtagsAndBots(); +void WriteExportSettings(const Export::Settings &settings); +Export::Settings ReadExportSettings(); + void addSavedPeer(PeerData *peer, const QDateTime &position); void removeSavedPeer(PeerData *peer); void readSavedPeers(); diff --git a/Telegram/gyp/lib_export.gyp b/Telegram/gyp/lib_export.gyp index d9912ac6fec8be..5840dd1ee27ee8 100644 --- a/Telegram/gyp/lib_export.gyp +++ b/Telegram/gyp/lib_export.gyp @@ -54,6 +54,7 @@ '<(src_loc)/export/export_api_wrap.h', '<(src_loc)/export/export_controller.cpp', '<(src_loc)/export/export_controller.h', + '<(src_loc)/export/export_settings.cpp', '<(src_loc)/export/export_settings.h', '<(src_loc)/export/data/export_data_types.cpp', '<(src_loc)/export/data/export_data_types.h',