mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Save export settings to local storage.
This commit is contained in:
parent
ae18ece549
commit
844d030332
10 changed files with 312 additions and 79 deletions
|
@ -87,7 +87,7 @@ public:
|
|||
HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) {
|
||||
}
|
||||
QString copyToClipboardContextItemText() const override {
|
||||
return url().isEmpty()
|
||||
return (url().isEmpty() || url().startsWith(qstr("internal:")))
|
||||
? QString()
|
||||
: UrlClickHandler::copyToClipboardContextItemText();
|
||||
}
|
||||
|
|
48
Telegram/SourceFiles/export/export_settings.cpp
Normal file
48
Telegram/SourceFiles/export/export_settings.cpp
Normal file
|
@ -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
|
|
@ -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<Type>;
|
||||
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<Type>;
|
||||
friend inline constexpr auto is_flag_type(Type) { return true; };
|
||||
|
|
|
@ -14,7 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#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<ControllerWrap*> process)
|
||||
: _process(process) {
|
||||
: _process(process)
|
||||
, _settings(std::make_unique<Settings>(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<SettingsWidget>(_panel);
|
||||
auto settings = base::make_unique_q<SettingsWidget>(
|
||||
_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
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#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 @@ private:
|
|||
void showError(const QString &text);
|
||||
void showCriticalError(const QString &text);
|
||||
|
||||
void saveSettings() const;
|
||||
|
||||
not_null<ControllerWrap*> _process;
|
||||
std::unique_ptr<Settings> _settings;
|
||||
base::Timer _saveSettingsTimer;
|
||||
|
||||
base::unique_qptr<Ui::SeparatePanel> _panel;
|
||||
|
||||
|
|
|
@ -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 <typename Callback>
|
||||
void SettingsWidget::changeData(Callback &&callback) {
|
||||
callback(_internal_data);
|
||||
_changes.fire_copy(_internal_data);
|
||||
}
|
||||
|
||||
void SettingsWidget::setupContent() {
|
||||
const auto scroll = Ui::CreateChild<Ui::ScrollArea>(
|
||||
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<Ui::VerticalLayout*> container) {
|
||||
const auto formatGroup = std::make_shared<Ui::RadioenumGroup<Format>>(
|
||||
_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<Ui::VerticalLayout*> 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<TextWithEntities>(
|
||||
lt_path,
|
||||
pathLink);
|
||||
|
@ -236,9 +252,11 @@ not_null<Ui::RpWidget*> 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<Ui::Checkbox*> SettingsWidget::addOption(
|
|||
object_ptr<Ui::Checkbox>(
|
||||
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<Ui::Checkbox>(
|
||||
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<Ui::Checkbox>(
|
||||
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<Ui::LabelSimple>(
|
||||
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<Ui::RpWidget*> container) {
|
||||
void SettingsWidget::refreshButtons(
|
||||
not_null<Ui::RpWidget*> container,
|
||||
bool canStart) {
|
||||
container->hideChildren();
|
||||
const auto children = container->children();
|
||||
for (const auto child : children) {
|
||||
|
@ -412,7 +437,7 @@ void SettingsWidget::refreshButtons(not_null<Ui::RpWidget*> container) {
|
|||
child->deleteLater();
|
||||
}
|
||||
}
|
||||
const auto start = _data.types
|
||||
const auto start = canStart
|
||||
? Ui::CreateChild<Ui::RoundButton>(
|
||||
container.get(),
|
||||
langFactory(lng_export_start),
|
||||
|
@ -420,9 +445,7 @@ void SettingsWidget::refreshButtons(not_null<Ui::RpWidget*> 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<Ui::RpWidget*> 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<Settings> SettingsWidget::startClicks() const {
|
||||
return _startClicks.events();
|
||||
rpl::producer<Settings> SettingsWidget::changes() const {
|
||||
return _changes.events();
|
||||
}
|
||||
|
||||
rpl::producer<Settings> 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 {
|
||||
|
|
|
@ -23,9 +23,11 @@ namespace View {
|
|||
|
||||
class SettingsWidget : public Ui::RpWidget {
|
||||
public:
|
||||
SettingsWidget(QWidget *parent);
|
||||
SettingsWidget(QWidget *parent, Settings data);
|
||||
|
||||
rpl::producer<Settings> startClicks() const;
|
||||
rpl::producer<Settings> value() const;
|
||||
rpl::producer<Settings> changes() const;
|
||||
rpl::producer<> startClicks() const;
|
||||
rpl::producer<> cancelClicks() const;
|
||||
|
||||
private:
|
||||
|
@ -61,9 +63,17 @@ private:
|
|||
void addLocationLabel(
|
||||
not_null<Ui::VerticalLayout*> container);
|
||||
void chooseFolder();
|
||||
void refreshButtons(not_null<Ui::RpWidget*> container);
|
||||
void refreshButtons(
|
||||
not_null<Ui::RpWidget*> container,
|
||||
bool canStart);
|
||||
|
||||
const Settings &readData() const;
|
||||
template <typename Callback>
|
||||
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 @@ private:
|
|||
|
||||
rpl::producer<> value;
|
||||
};
|
||||
rpl::event_stream<Settings> _startClicks;
|
||||
rpl::event_stream<Settings> _changes;
|
||||
rpl::variable<Wrap> _startClicks;
|
||||
rpl::variable<Wrap> _cancelClicks;
|
||||
rpl::event_stream<Settings::Types> _dataTypesChanges;
|
||||
rpl::event_stream<> _refreshButtons;
|
||||
rpl::event_stream<QString> _locationChanges;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Add table
Reference in a new issue