mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-20 10:17:43 +00:00
Suggest start export when time comes.
This commit is contained in:
parent
844d030332
commit
0143fd28af
Telegram
Resources/langs
SourceFiles
@ -1703,6 +1703,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
"lng_export_folder" = "Choose export folder";
|
"lng_export_folder" = "Choose export folder";
|
||||||
"lng_export_invalid" = "Sorry, you have started a new data export, so this data export is now cancelled.";
|
"lng_export_invalid" = "Sorry, you have started a new data export, so this data export is now cancelled.";
|
||||||
"lng_export_delay" = "Sorry, for security reasons, you will be able to begin downloading your data in 24 hours. We have notified all your devices about the export request to make sure it's authorized and give you time to react if it's not.\n\nPlease come back on {date} and repeat the request using the same device.";
|
"lng_export_delay" = "Sorry, for security reasons, you will be able to begin downloading your data in 24 hours. We have notified all your devices about the export request to make sure it's authorized and give you time to react if it's not.\n\nPlease come back on {date} and repeat the request using the same device.";
|
||||||
|
"lng_export_suggest_title" = "Data export ready";
|
||||||
|
"lng_export_suggest_text" = "You can now download the data you requested. Start exporting data?";
|
||||||
|
"lng_export_suggest_cancel" = "Not now";
|
||||||
|
|
||||||
// Wnd specific
|
// Wnd specific
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ using float32 = float;
|
|||||||
using float64 = double;
|
using float64 = double;
|
||||||
|
|
||||||
using TimeMs = int64;
|
using TimeMs = int64;
|
||||||
|
using TimeId = int32;
|
||||||
|
|
||||||
#define qsl(s) QStringLiteral(s)
|
#define qsl(s) QStringLiteral(s)
|
||||||
#define qstr(s) QLatin1String((s), sizeof(s) - 1)
|
#define qstr(s) QLatin1String((s), sizeof(s) - 1)
|
||||||
|
@ -188,7 +188,6 @@ inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; }
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; }
|
inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; }
|
||||||
|
|
||||||
using TimeId = int32;
|
|
||||||
void unixtimeInit();
|
void unixtimeInit();
|
||||||
void unixtimeSet(TimeId serverTime, bool force = false);
|
void unixtimeSet(TimeId serverTime, bool force = false);
|
||||||
TimeId unixtime();
|
TimeId unixtime();
|
||||||
|
@ -83,6 +83,29 @@ void Session::startExport() {
|
|||||||
}, _export->lifetime());
|
}, _export->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::suggestStartExport(TimeId availableAt) {
|
||||||
|
_exportAvailableAt = availableAt;
|
||||||
|
suggestStartExport();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::suggestStartExport() {
|
||||||
|
if (_exportAvailableAt <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto now = unixtime();
|
||||||
|
const auto left = (_exportAvailableAt <= now)
|
||||||
|
? 0
|
||||||
|
: (_exportAvailableAt - now);
|
||||||
|
if (!left) {
|
||||||
|
Export::View::SuggestStart();
|
||||||
|
} else {
|
||||||
|
App::CallDelayed(
|
||||||
|
std::min(left + 5, 3600) * TimeMs(1000),
|
||||||
|
_session,
|
||||||
|
[=] { suggestStartExport(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<Export::View::PanelController*> Session::currentExportView(
|
rpl::producer<Export::View::PanelController*> Session::currentExportView(
|
||||||
) const {
|
) const {
|
||||||
return _exportViewChanges.events_starting_with(_exportPanel.get());
|
return _exportViewChanges.events_starting_with(_exportPanel.get());
|
||||||
|
@ -52,6 +52,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void startExport();
|
void startExport();
|
||||||
|
void suggestStartExport(TimeId availableAt);
|
||||||
rpl::producer<Export::View::PanelController*> currentExportView() const;
|
rpl::producer<Export::View::PanelController*> currentExportView() const;
|
||||||
bool exportInProgress() const;
|
bool exportInProgress() const;
|
||||||
void stopExportWithConfirmation(FnMut<void()> callback);
|
void stopExportWithConfirmation(FnMut<void()> callback);
|
||||||
@ -408,6 +409,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void suggestStartExport();
|
||||||
|
|
||||||
void setupContactViewsViewer();
|
void setupContactViewsViewer();
|
||||||
void setupChannelLeavingViewer();
|
void setupChannelLeavingViewer();
|
||||||
void photoApplyFields(
|
void photoApplyFields(
|
||||||
@ -505,6 +508,7 @@ private:
|
|||||||
std::unique_ptr<Export::ControllerWrap> _export;
|
std::unique_ptr<Export::ControllerWrap> _export;
|
||||||
std::unique_ptr<Export::View::PanelController> _exportPanel;
|
std::unique_ptr<Export::View::PanelController> _exportPanel;
|
||||||
rpl::event_stream<Export::View::PanelController*> _exportViewChanges;
|
rpl::event_stream<Export::View::PanelController*> _exportViewChanges;
|
||||||
|
TimeId _exportAvailableAt = 0;
|
||||||
|
|
||||||
base::Variable<bool> _contactsLoaded = { false };
|
base::Variable<bool> _contactsLoaded = { false };
|
||||||
base::Variable<bool> _allChatsLoaded = { false };
|
base::Variable<bool> _allChatsLoaded = { false };
|
||||||
|
@ -20,7 +20,6 @@ namespace Export {
|
|||||||
struct Settings;
|
struct Settings;
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
using TimeId = int32;
|
|
||||||
using Utf8String = QByteArray;
|
using Utf8String = QByteArray;
|
||||||
using PeerId = uint64;
|
using PeerId = uint64;
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ struct ApiWrap::LeftChannelsProcess : ChatsProcess {
|
|||||||
|
|
||||||
struct ApiWrap::DialogsProcess : ChatsProcess {
|
struct ApiWrap::DialogsProcess : ChatsProcess {
|
||||||
int splitIndexPlusOne = 0;
|
int splitIndexPlusOne = 0;
|
||||||
Data::TimeId offsetDate = 0;
|
TimeId offsetDate = 0;
|
||||||
int32 offsetId = 0;
|
int32 offsetId = 0;
|
||||||
MTPInputPeer offsetPeer = MTP_inputPeerEmpty();
|
MTPInputPeer offsetPeer = MTP_inputPeerEmpty();
|
||||||
};
|
};
|
||||||
|
@ -76,6 +76,8 @@ struct Settings {
|
|||||||
Types fullChats = DefaultFullChats();
|
Types fullChats = DefaultFullChats();
|
||||||
MediaSettings media;
|
MediaSettings media;
|
||||||
|
|
||||||
|
TimeId availableAt = 0;
|
||||||
|
|
||||||
static inline Types DefaultTypes() {
|
static inline Types DefaultTypes() {
|
||||||
return Type::PersonalInfo
|
return Type::PersonalInfo
|
||||||
| Type::Userpics
|
| Type::Userpics
|
||||||
|
@ -17,6 +17,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
#include "platform/platform_specific.h"
|
#include "platform/platform_specific.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
#include "styles/style_export.h"
|
#include "styles/style_export.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
|
||||||
@ -24,11 +26,72 @@ namespace Export {
|
|||||||
namespace View {
|
namespace View {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kAddDelay = TimeId(60);
|
|
||||||
constexpr auto kSaveSettingsTimeout = TimeMs(1000);
|
constexpr auto kSaveSettingsTimeout = TimeMs(1000);
|
||||||
|
|
||||||
|
class SuggestBox : public BoxContent {
|
||||||
|
public:
|
||||||
|
SuggestBox(QWidget*);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void prepare() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _cleared = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SuggestBox::SuggestBox(QWidget*) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuggestBox::prepare() {
|
||||||
|
setTitle(langFactory(lng_export_suggest_title));
|
||||||
|
|
||||||
|
const auto clear = [=] {
|
||||||
|
if (_cleared) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_cleared = true;
|
||||||
|
|
||||||
|
auto settings = Local::ReadExportSettings();
|
||||||
|
settings.availableAt = 0;
|
||||||
|
Local::WriteExportSettings(settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
addButton(langFactory(lng_box_ok), [=] {
|
||||||
|
clear();
|
||||||
|
closeBox();
|
||||||
|
Auth().data().startExport();
|
||||||
|
});
|
||||||
|
addButton(langFactory(lng_export_suggest_cancel), [=] { closeBox(); });
|
||||||
|
setCloseByOutsideClick(false);
|
||||||
|
|
||||||
|
const auto content = Ui::CreateChild<Ui::FlatLabel>(
|
||||||
|
this,
|
||||||
|
lang(lng_export_suggest_text),
|
||||||
|
Ui::FlatLabel::InitType::Simple,
|
||||||
|
st::boxLabel);
|
||||||
|
widthValue(
|
||||||
|
) | rpl::start_with_next([=](int width) {
|
||||||
|
const auto contentWidth = width
|
||||||
|
- st::boxPadding.left()
|
||||||
|
- st::boxPadding.right();
|
||||||
|
content->resizeToWidth(contentWidth);
|
||||||
|
content->moveToLeft(st::boxPadding.left(), 0);
|
||||||
|
}, content->lifetime());
|
||||||
|
content->heightValue(
|
||||||
|
) | rpl::start_with_next([=](int height) {
|
||||||
|
setDimensions(st::boxWidth, height + st::boxPadding.bottom());
|
||||||
|
}, content->lifetime());
|
||||||
|
|
||||||
|
boxClosing() | rpl::start_with_next(clear, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void SuggestStart() {
|
||||||
|
Ui::show(Box<SuggestBox>(), LayerOption::KeepOther);
|
||||||
|
}
|
||||||
|
|
||||||
PanelController::PanelController(not_null<ControllerWrap*> process)
|
PanelController::PanelController(not_null<ControllerWrap*> process)
|
||||||
: _process(process)
|
: _process(process)
|
||||||
, _settings(std::make_unique<Settings>(Local::ReadExportSettings()))
|
, _settings(std::make_unique<Settings>(Local::ReadExportSettings()))
|
||||||
@ -91,10 +154,15 @@ void PanelController::showError(const ApiErrorState &error) {
|
|||||||
showError(lang(lng_export_invalid));
|
showError(lang(lng_export_invalid));
|
||||||
} else if (error.data.type().startsWith(qstr("TAKEOUT_INIT_DELAY_"))) {
|
} else if (error.data.type().startsWith(qstr("TAKEOUT_INIT_DELAY_"))) {
|
||||||
const auto seconds = std::max(error.data.type().mid(
|
const auto seconds = std::max(error.data.type().mid(
|
||||||
qstr("TAKEOUT_INIT_DELAY_").size()).toInt(), 0) + kAddDelay;
|
qstr("TAKEOUT_INIT_DELAY_").size()).toInt(), 1);
|
||||||
const auto now = QDateTime::currentDateTime();
|
const auto now = QDateTime::currentDateTime();
|
||||||
const auto when = now.addSecs(seconds);
|
const auto when = now.addSecs(seconds);
|
||||||
showError(lng_export_delay(lt_date, langDateTimeFull(when)));
|
showError(lng_export_delay(lt_date, langDateTimeFull(when)));
|
||||||
|
|
||||||
|
_settings->availableAt = unixtime() + seconds;
|
||||||
|
_saveSettingsTimer.callOnce(kSaveSettingsTimeout);
|
||||||
|
|
||||||
|
Auth().data().suggestStartExport(_settings->availableAt);
|
||||||
} else {
|
} else {
|
||||||
showCriticalError("API Error happened :(\n"
|
showCriticalError("API Error happened :(\n"
|
||||||
+ QString::number(error.data.code()) + ": " + error.data.type()
|
+ QString::number(error.data.code()) + ": " + error.data.type()
|
||||||
|
@ -21,6 +21,8 @@ class SeparatePanel;
|
|||||||
namespace Export {
|
namespace Export {
|
||||||
namespace View {
|
namespace View {
|
||||||
|
|
||||||
|
void SuggestStart();
|
||||||
|
|
||||||
class Panel;
|
class Panel;
|
||||||
|
|
||||||
class PanelController {
|
class PanelController {
|
||||||
|
@ -79,6 +79,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "core/update_checker.h"
|
#include "core/update_checker.h"
|
||||||
#include "calls/calls_instance.h"
|
#include "calls/calls_instance.h"
|
||||||
#include "calls/calls_top_bar.h"
|
#include "calls/calls_top_bar.h"
|
||||||
|
#include "export/export_settings.h"
|
||||||
#include "export/view/export_view_top_bar.h"
|
#include "export/view/export_view_top_bar.h"
|
||||||
#include "export/view/export_view_panel_controller.h"
|
#include "export/view/export_view_panel_controller.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
@ -3821,6 +3822,10 @@ void MainWidget::start(const MTPUser *self) {
|
|||||||
Local::readRecentStickers();
|
Local::readRecentStickers();
|
||||||
Local::readFavedStickers();
|
Local::readFavedStickers();
|
||||||
Local::readSavedGifs();
|
Local::readSavedGifs();
|
||||||
|
if (const auto availableAt = Local::ReadExportSettings().availableAt) {
|
||||||
|
Auth().data().suggestStartExport(availableAt);
|
||||||
|
}
|
||||||
|
|
||||||
_history->start();
|
_history->start();
|
||||||
|
|
||||||
Messenger::Instance().checkStartUrl();
|
Messenger::Instance().checkStartUrl();
|
||||||
|
@ -4623,7 +4623,8 @@ void WriteExportSettings(const Export::Settings &settings) {
|
|||||||
&& settings.media.types == check.media.types
|
&& settings.media.types == check.media.types
|
||||||
&& settings.media.sizeLimit == check.media.sizeLimit
|
&& settings.media.sizeLimit == check.media.sizeLimit
|
||||||
&& settings.path == check.path
|
&& settings.path == check.path
|
||||||
&& settings.format == check.format) {
|
&& settings.format == check.format
|
||||||
|
&& settings.availableAt == check.availableAt) {
|
||||||
if (_exportSettingsKey) {
|
if (_exportSettingsKey) {
|
||||||
clearKey(_exportSettingsKey);
|
clearKey(_exportSettingsKey);
|
||||||
_exportSettingsKey = 0;
|
_exportSettingsKey = 0;
|
||||||
@ -4636,7 +4637,7 @@ void WriteExportSettings(const Export::Settings &settings) {
|
|||||||
_mapChanged = true;
|
_mapChanged = true;
|
||||||
_writeMap(WriteMapWhen::Fast);
|
_writeMap(WriteMapWhen::Fast);
|
||||||
}
|
}
|
||||||
quint32 size = sizeof(quint32) * 5
|
quint32 size = sizeof(quint32) * 6
|
||||||
+ Serialize::stringSize(settings.path);
|
+ Serialize::stringSize(settings.path);
|
||||||
EncryptedDescriptor data(size);
|
EncryptedDescriptor data(size);
|
||||||
data.stream
|
data.stream
|
||||||
@ -4645,7 +4646,8 @@ void WriteExportSettings(const Export::Settings &settings) {
|
|||||||
<< quint32(settings.media.types)
|
<< quint32(settings.media.types)
|
||||||
<< quint32(settings.media.sizeLimit)
|
<< quint32(settings.media.sizeLimit)
|
||||||
<< quint32(settings.format)
|
<< quint32(settings.format)
|
||||||
<< settings.path;
|
<< settings.path
|
||||||
|
<< quint32(settings.availableAt);
|
||||||
|
|
||||||
FileWriteDescriptor file(_exportSettingsKey);
|
FileWriteDescriptor file(_exportSettingsKey);
|
||||||
file.writeEncrypted(data);
|
file.writeEncrypted(data);
|
||||||
@ -4663,7 +4665,7 @@ Export::Settings ReadExportSettings() {
|
|||||||
|
|
||||||
quint32 types = 0, fullChats = 0;
|
quint32 types = 0, fullChats = 0;
|
||||||
quint32 mediaTypes = 0, mediaSizeLimit = 0;
|
quint32 mediaTypes = 0, mediaSizeLimit = 0;
|
||||||
quint32 format = 0;
|
quint32 format = 0, availableAt = 0;
|
||||||
QString path;
|
QString path;
|
||||||
file.stream
|
file.stream
|
||||||
>> types
|
>> types
|
||||||
@ -4671,7 +4673,8 @@ Export::Settings ReadExportSettings() {
|
|||||||
>> mediaTypes
|
>> mediaTypes
|
||||||
>> mediaSizeLimit
|
>> mediaSizeLimit
|
||||||
>> format
|
>> format
|
||||||
>> path;
|
>> path
|
||||||
|
>> availableAt;
|
||||||
auto result = Export::Settings();
|
auto result = Export::Settings();
|
||||||
result.types = Export::Settings::Types::from_raw(types);
|
result.types = Export::Settings::Types::from_raw(types);
|
||||||
result.fullChats = Export::Settings::Types::from_raw(fullChats);
|
result.fullChats = Export::Settings::Types::from_raw(fullChats);
|
||||||
@ -4679,7 +4682,10 @@ Export::Settings ReadExportSettings() {
|
|||||||
result.media.sizeLimit = mediaSizeLimit;
|
result.media.sizeLimit = mediaSizeLimit;
|
||||||
result.format = Export::Output::Format(format);
|
result.format = Export::Output::Format(format);
|
||||||
result.path = path;
|
result.path = path;
|
||||||
return result.validate() ? result : Export::Settings();
|
result.availableAt = availableAt;
|
||||||
|
return (file.stream.status() == QDataStream::Ok && result.validate())
|
||||||
|
? result
|
||||||
|
: Export::Settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeSavedPeers() {
|
void writeSavedPeers() {
|
||||||
|
Loading…
Reference in New Issue
Block a user