Improve export HTML layout.

This commit is contained in:
John Preston 2018-07-12 00:06:35 +03:00
parent 78558e513c
commit 0b7bb806b7
18 changed files with 331 additions and 490 deletions

View File

@ -400,9 +400,6 @@ a.block_link:hover {
.section.web {
background-image: url(../images/section_web.png);
}
.section.leftchats {
background-image: url(../images/section_leftchats.png);
}
.section.other {
background-image: url(../images/section_other.png)
}
@ -464,9 +461,6 @@ a.block_link:hover {
.section.web {
background-image: url(../images/section_web@2x.png);
}
.section.leftchats {
background-image: url(../images/section_leftchats@2x.png);
}
.section.other {
background-image: url(../images/section_other@2x.png);
}

View File

@ -1731,11 +1731,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_export_suggest_cancel" = "Not now";
"lng_export_about_telegram" = "Here is all the data you requested. Remember: we dont use your data for ad targeting, we dont sell it to others, and were not part of any “family of companies.”\n\nTelegram only keeps the information it needs to function as a feature-rich cloud service for example, your cloud chats so that you can access them from any devices without using third-party backups, or your contacts so that you can rely on your existing social graph when messaging people on Telegram.\n\nCheck out Settings > Privacy & Security on Telegram's mobile apps for relevant settings.";
"lng_export_about_contacts" = "If you allow access, your contacts are continuously synced with Telegram. Thanks to this, you can easily switch to Telegram without losing your existing social graph and connect with friends across all your devices. We use data about your contacts to let you know when they join Telegram. We also use it to make sure that you see the names you have in your phone book instead of the screen names people choose for themselves.\n\nYou can disable contact syncing or delete your stored contacts in Settings > Privacy & Security on Telegram's mobile apps.";
"lng_export_about_frequent" = "This rating shows which people you are likelier to message frequently. Telegram uses this data to populate the 'People' box at the top of the Search section. This rating is also calculated for inline bots so that the app can suggest the bots you are most likely to use in the attachment menu (or when you start a new message with \"@\").\n\nTo delete this data, go to Settings > Privacy & Security and disable 'Suggest Frequent Contacts' (requires Telegram for iOS v.4.8.3 or Telegram for Android v.4.8.10 or higher). See this page for more information: https://telegram.org/faq_export";
"lng_export_about_frequent" = "This rating shows which people you are likelier to message frequently. Telegram uses this data to populate the 'People' box at the top of the Search section. This rating is also calculated for inline bots so that the app can suggest the bots you are most likely to use in the attachment menu (or when you start a new message with \"@\").\n\nTo delete this data, go to Settings > Privacy & Security and disable 'Suggest Frequent Contacts' (requires Telegram for iOS v.4.8.3 or Telegram for Android v.4.8.10 or higher).";
"lng_export_about_sessions" = "We store session info to display your connected devices in Settings > Privacy & Security > Active Sessions.";
"lng_export_about_web_sessions" = "We store this to display the websites where you logged in using authentication via Telegram. This information is shown in Settings > Privacy & Security > Active Sessions.";
"lng_export_about_chats" = "This page lists all chats from this export and where to look for their data.";
"lng_export_about_left_chats" = "This page lists all supergroups and channels from this export that you've left and where to look for their data.\n\nNote that when you leave a channel or supergroup you've created, you have the option to either delete it, or simply leave (in case you want to rejoin later, or keep the community alive despite not being a member).";
"lng_export_about_left_chats" = "Below are the supergroups and channels from this export that you've left or where you were banned.\n\nNote that when you leave a channel or supergroup you've created, you have the option to either delete it, or simply leave (in case you want to rejoin later, or keep the community alive despite not being a member).";
// Wnd specific

View File

@ -31,8 +31,6 @@
<file alias="images/section_contacts@2x.png">../export_html/images/section_contacts@2x.png</file>
<file alias="images/section_frequent.png">../export_html/images/section_frequent.png</file>
<file alias="images/section_frequent@2x.png">../export_html/images/section_frequent@2x.png</file>
<file alias="images/section_leftchats.png">../export_html/images/section_leftchats.png</file>
<file alias="images/section_leftchats@2x.png">../export_html/images/section_leftchats@2x.png</file>
<file alias="images/section_other.png">../export_html/images/section_other.png</file>
<file alias="images/section_other@2x.png">../export_html/images/section_other@2x.png</file>
<file alias="images/section_photos.png">../export_html/images/section_photos.png</file>

View File

@ -1296,6 +1296,28 @@ SessionsList ParseWebSessionsList(
});
}
DialogInfo *DialogsInfo::item(int index) {
const auto chatsCount = chats.size();
return (index < 0)
? nullptr
: (index < chatsCount)
? &chats[index]
: (index - chatsCount < left.size())
? &left[index - chatsCount]
: nullptr;
}
const DialogInfo *DialogsInfo::item(int index) const {
const auto chatsCount = chats.size();
return (index < 0)
? nullptr
: (index < chatsCount)
? &chats[index]
: (index - chatsCount < left.size())
? &left[index - chatsCount]
: nullptr;
}
DialogInfo::Type DialogTypeFromChat(const Chat &chat) {
using Type = DialogInfo::Type;
return chat.username.isEmpty()
@ -1325,7 +1347,7 @@ DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data) {
}, [&](const auto &data) { // MTPDmessages_dialogs &data) {
const auto peers = ParsePeersLists(data.vusers, data.vchats);
const auto messages = ParseMessagesList(data.vmessages, folder);
result.list.reserve(result.list.size() + data.vdialogs.v.size());
result.chats.reserve(result.chats.size() + data.vdialogs.v.size());
for (const auto &dialog : data.vdialogs.v) {
if (dialog.type() != mtpc_dialog) {
continue;
@ -1358,7 +1380,7 @@ DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data) {
const auto &message = messageIt->second;
info.topMessageDate = message.date;
}
result.list.push_back(std::move(info));
result.chats.push_back(std::move(info));
}
});
return result;
@ -1367,7 +1389,7 @@ DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data) {
DialogsInfo ParseLeftChannelsInfo(const MTPmessages_Chats &data) {
auto result = DialogsInfo();
data.match([&](const auto &data) { //MTPDmessages_chats &data) {
result.list.reserve(data.vchats.v.size());
result.left.reserve(data.vchats.v.size());
for (const auto &single : data.vchats.v) {
const auto chat = ParseChat(single);
auto info = DialogInfo();
@ -1377,17 +1399,20 @@ DialogsInfo ParseLeftChannelsInfo(const MTPmessages_Chats &data) {
info.topMessageDate = 0;
info.topMessageId = 0;
info.type = DialogTypeFromChat(chat);
result.list.push_back(std::move(info));
info.isLeftChannel = true;
result.left.push_back(std::move(info));
}
});
return result;
}
void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings) {
auto &list = info.list;
const auto digits = Data::NumberToString(list.size() - 1).size();
auto &chats = info.chats;
auto &left = info.left;
const auto fullCount = chats.size() + left.size();
const auto digits = Data::NumberToString(fullCount - 1).size();
auto index = 0;
for (auto &dialog : list) {
for (auto &dialog : chats) {
const auto number = Data::NumberToString(++index, digits, '0');
dialog.relativePath = "chats/chat_" + number + '/';
@ -1410,15 +1435,9 @@ void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings) {
ranges::reverse(dialog.splits);
}
}
void FinalizeLeftChannelsInfo(DialogsInfo &info, const Settings &settings) {
auto &list = info.list;
const auto digits = Data::NumberToString(list.size() - 1).size();
auto index = 0;
for (auto &dialog : list) {
for (auto &dialog : left) {
const auto number = Data::NumberToString(++index, digits, '0');
dialog.relativePath = "chats/left_" + number + '/';
dialog.relativePath = "chats/chat_" + number + '/';
dialog.onlyMyMessages = true;
}
}

View File

@ -521,13 +521,14 @@ struct DialogInfo {
MTPInputPeer input = MTP_inputPeerEmpty();
int32 topMessageId = 0;
TimeId topMessageDate = 0;
PeerId peerId;
PeerId peerId = 0;
// User messages splits which contained that dialog.
std::vector<int> splits;
// Filled after the whole dialogs list is accumulated.
bool onlyMyMessages = false;
bool isLeftChannel = false;
QString relativePath;
// Filled when requesting dialog messages.
@ -535,7 +536,11 @@ struct DialogInfo {
};
struct DialogsInfo {
std::vector<DialogInfo> list;
DialogInfo *item(int index);
const DialogInfo *item(int index) const;
std::vector<DialogInfo> chats;
std::vector<DialogInfo> left;
};
DialogInfo::Type DialogTypeFromChat(const Chat &chat);
@ -543,7 +548,6 @@ DialogInfo::Type DialogTypeFromChat(const Chat &chat);
DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data);
DialogsInfo ParseLeftChannelsInfo(const MTPmessages_Chats &data);
void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings);
void FinalizeLeftChannelsInfo(DialogsInfo &info, const Settings &settings);
struct MessagesSlice {
std::vector<Message> list;

View File

@ -536,8 +536,8 @@ void ApiWrap::requestLeftChannelsCount() {
Expects(_startProcess != nullptr);
Expects(_leftChannelsProcess != nullptr);
_startProcess->info.leftChannelsCount
= _leftChannelsProcess->fullCount;
_startProcess->info.dialogsCount
+= _leftChannelsProcess->fullCount;
sendNextStartRequest();
});
}
@ -569,7 +569,6 @@ void ApiWrap::requestLeftChannelsSlice() {
if (_leftChannelsProcess->finished) {
const auto process = base::take(_leftChannelsProcess);
Data::FinalizeLeftChannelsInfo(process->info, *_settings);
process->done(std::move(process->info));
} else {
requestLeftChannelsSlice();
@ -987,10 +986,10 @@ void ApiWrap::requestDialogsSlice() {
});
auto info = Data::ParseDialogsInfo(result);
_dialogsProcess->processedCount += info.list.size();
const auto last = info.list.empty()
_dialogsProcess->processedCount += info.chats.size();
const auto last = info.chats.empty()
? Data::DialogInfo()
: info.list.back();
: info.chats.back();
appendDialogsSlice(std::move(info));
if (!_dialogsProcess->progress(_dialogsProcess->processedCount)) {
@ -1007,7 +1006,7 @@ void ApiWrap::requestDialogsSlice() {
_dialogsProcess->offsetDate = 0;
_dialogsProcess->offsetPeer = MTP_inputPeerEmpty();
} else {
finishDialogsList();
requestLeftChannelsIfNeeded();
return;
}
requestDialogsSlice();
@ -1020,16 +1019,35 @@ void ApiWrap::appendDialogsSlice(Data::DialogsInfo &&info) {
appendChatsSlice(
*_dialogsProcess,
std::move(info),
_dialogsProcess->info.chats,
std::move(info.chats),
_dialogsProcess->splitIndexPlusOne - 1);
}
void ApiWrap::requestLeftChannelsIfNeeded() {
if (_settings->types & Settings::Type::GroupsChannelsMask) {
requestLeftChannelsList([=](int count) {
Expects(_dialogsProcess != nullptr);
return _dialogsProcess->progress(
_dialogsProcess->processedCount + count);
}, [=](Data::DialogsInfo &&result) {
Expects(_dialogsProcess != nullptr);
_dialogsProcess->info.left = std::move(result.left);
finishDialogsList();
});
} else {
finishDialogsList();
}
}
void ApiWrap::finishDialogsList() {
Expects(_dialogsProcess != nullptr);
const auto process = base::take(_dialogsProcess);
ranges::reverse(process->info.list);
ranges::reverse(process->info.chats);
Data::FinalizeDialogsInfo(process->info, *_settings);
process->done(std::move(process->info));
@ -1067,7 +1085,7 @@ void ApiWrap::requestLeftChannelsSliceGeneric(FnMut<void()> done) {
});
if (process->progress) {
if (!process->progress(process->info.list.size())) {
if (!process->progress(process->info.left.size())) {
return;
}
}
@ -1082,32 +1100,33 @@ void ApiWrap::appendLeftChannelsSlice(Data::DialogsInfo &&info) {
appendChatsSlice(
*_leftChannelsProcess,
std::move(info),
_leftChannelsProcess->info.left,
std::move(info.left),
_splits.size() - 1);
}
void ApiWrap::appendChatsSlice(
ChatsProcess &to,
Data::DialogsInfo &&info,
ChatsProcess &process,
std::vector<Data::DialogInfo> &to,
std::vector<Data::DialogInfo> &&from,
int splitIndex) {
Expects(_settings != nullptr);
const auto types = _settings->types;
auto filtered = ranges::view::all(
info.list
from
) | ranges::view::filter([&](const Data::DialogInfo &info) {
return (types & SettingsFromDialogsType(info.type)) != 0;
});
auto &list = to.info.list;
list.reserve(list.size() + info.list.size());
to.reserve(to.size() + from.size());
for (auto &info : filtered) {
const auto nextIndex = list.size();
const auto [i, ok] = to.indexByPeer.emplace(info.peerId, nextIndex);
const auto nextIndex = to.size();
const auto [i, ok] = process.indexByPeer.emplace(info.peerId, nextIndex);
if (ok) {
list.push_back(std::move(info));
to.push_back(std::move(info));
}
list[i->second].splits.push_back(splitIndex);
list[i->second].messagesCountPerSplit.push_back(0);
to[i->second].splits.push_back(splitIndex);
to[i->second].messagesCountPerSplit.push_back(0);
}
}

View File

@ -42,16 +42,12 @@ public:
struct StartInfo {
int userpicsCount = 0;
int dialogsCount = 0;
int leftChannelsCount = 0;
};
void startExport(
const Settings &settings,
Output::Stats *stats,
FnMut<void(StartInfo)> done);
void requestLeftChannelsList(
Fn<bool(int count)> progress,
FnMut<void(Data::DialogsInfo&&)> done);
void requestDialogsList(
Fn<bool(int count)> progress,
FnMut<void(Data::DialogsInfo&&)> done);
@ -129,13 +125,18 @@ private:
void appendDialogsSlice(Data::DialogsInfo &&info);
void finishDialogsList();
void requestLeftChannelsIfNeeded();
void requestLeftChannelsList(
Fn<bool(int count)> progress,
FnMut<void(Data::DialogsInfo&&)> done);
void requestLeftChannelsSliceGeneric(FnMut<void()> done);
void requestLeftChannelsSlice();
void appendLeftChannelsSlice(Data::DialogsInfo &&info);
void appendChatsSlice(
ChatsProcess &to,
Data::DialogsInfo &&info,
ChatsProcess &process,
std::vector<Data::DialogInfo> &to,
std::vector<Data::DialogInfo> &&from,
int splitIndex);
void requestMessagesCount(int localSplitIndex);

View File

@ -54,7 +54,6 @@ private:
void exportNext();
void initialize();
void initialized(const ApiWrap::StartInfo &info);
void collectLeftChannels();
void collectDialogsList();
void exportPersonalInfo();
void exportUserpics();
@ -63,31 +62,24 @@ private:
void exportOtherData();
void exportDialogs();
void exportNextDialog();
void exportLeftChannels();
void exportNextLeftChannel();
template <typename Callback = const decltype(kNullStateCallback) &>
ProcessingState prepareState(
Step step,
Callback &&callback = kNullStateCallback) const;
ProcessingState stateInitializing() const;
ProcessingState stateLeftChannelsList(int processed) const;
ProcessingState stateDialogsList(int processed) const;
ProcessingState statePersonalInfo() const;
ProcessingState stateUserpics(const DownloadProgress &progress) const;
ProcessingState stateContacts() const;
ProcessingState stateSessions() const;
ProcessingState stateOtherData() const;
ProcessingState stateLeftChannels(
const DownloadProgress &progress) const;
ProcessingState stateDialogs(const DownloadProgress &progress) const;
void fillMessagesState(
ProcessingState &result,
const Data::DialogsInfo &info,
int index,
const DownloadProgress &progress,
int addIndex,
int addCount) const;
const DownloadProgress &progress) const;
int substepsInStep(Step step) const;
@ -97,9 +89,6 @@ private:
Settings _settings;
Environment _environment;
Data::DialogsInfo _leftChannelsInfo;
int _leftChannelIndex = -1;
Data::DialogsInfo _dialogsInfo;
int _dialogIndex = -1;
@ -241,9 +230,6 @@ void Controller::startExport(
void Controller::fillExportSteps() {
using Type = Settings::Type;
_steps.push_back(Step::Initializing);
if (_settings.types & Type::GroupsChannelsMask) {
_steps.push_back(Step::LeftChannelsList);
}
if (_settings.types & Type::AnyChatsMask) {
_steps.push_back(Step::DialogsList);
}
@ -265,9 +251,6 @@ void Controller::fillExportSteps() {
if (_settings.types & Type::AnyChatsMask) {
_steps.push_back(Step::Dialogs);
}
if (_settings.types & Type::GroupsChannelsMask) {
_steps.push_back(Step::LeftChannels);
}
}
void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
@ -280,9 +263,6 @@ void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
result[index] = count;
};
push(Step::Initializing, 1);
if (_settings.types & Settings::Type::GroupsChannelsMask) {
push(Step::LeftChannelsList, 1);
}
if (_settings.types & Settings::Type::AnyChatsMask) {
push(Step::DialogsList, 1);
}
@ -301,9 +281,6 @@ void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
if (_settings.types & Settings::Type::OtherData) {
push(Step::OtherData, 1);
}
if (_settings.types & Settings::Type::GroupsChannelsMask) {
push(Step::LeftChannels, info.leftChannelsCount);
}
if (_settings.types & Settings::Type::AnyChatsMask) {
push(Step::Dialogs, info.dialogsCount);
}
@ -330,14 +307,12 @@ void Controller::exportNext() {
const auto step = _steps[_stepIndex];
switch (step) {
case Step::Initializing: return initialize();
case Step::LeftChannelsList: return collectLeftChannels();
case Step::DialogsList: return collectDialogsList();
case Step::PersonalInfo: return exportPersonalInfo();
case Step::Userpics: return exportUserpics();
case Step::Contacts: return exportContacts();
case Step::Sessions: return exportSessions();
case Step::OtherData: return exportOtherData();
case Step::LeftChannels: return exportLeftChannels();
case Step::Dialogs: return exportDialogs();
}
Unexpected("Step in Controller::exportNext.");
@ -358,17 +333,6 @@ void Controller::initialized(const ApiWrap::StartInfo &info) {
exportNext();
}
void Controller::collectLeftChannels() {
setState(stateLeftChannelsList(0));
_api.requestLeftChannelsList([=](int count) {
setState(stateLeftChannelsList(count));
return true;
}, [=](Data::DialogsInfo &&result) {
_leftChannelsInfo = std::move(result);
exportNext();
});
}
void Controller::collectDialogsList() {
setState(stateDialogsList(0));
_api.requestDialogsList([=](int count) {
@ -457,9 +421,9 @@ void Controller::exportDialogs() {
void Controller::exportNextDialog() {
const auto index = ++_dialogIndex;
if (index < _dialogsInfo.list.size()) {
const auto &info = _dialogsInfo.list[index];
_api.requestMessages(info, [=](const Data::DialogInfo &info) {
const auto info = _dialogsInfo.item(index);
if (info) {
_api.requestMessages(*info, [=](const Data::DialogInfo &info) {
if (ioCatchError(_writer->writeDialogStart(info))) {
return false;
}
@ -493,52 +457,6 @@ void Controller::exportNextDialog() {
exportNext();
}
void Controller::exportLeftChannels() {
if (ioCatchError(_writer->writeLeftChannelsStart(_leftChannelsInfo))) {
return;
}
exportNextLeftChannel();
}
void Controller::exportNextLeftChannel() {
const auto index = ++_leftChannelIndex;
if (index < _leftChannelsInfo.list.size()) {
const auto &info = _leftChannelsInfo.list[index];
_api.requestMessages(info, [=](const Data::DialogInfo &info) {
if (ioCatchError(_writer->writeLeftChannelStart(info))) {
return false;
}
_messagesWritten = 0;
_messagesCount = ranges::accumulate(
info.messagesCountPerSplit,
0);
setState(stateLeftChannels(DownloadProgress()));
return true;
}, [=](DownloadProgress progress) {
setState(stateLeftChannels(progress));
return true;
}, [=](Data::MessagesSlice &&result) {
if (ioCatchError(_writer->writeLeftChannelSlice(result))) {
return false;
}
_messagesWritten += result.list.size();
setState(stateLeftChannels(DownloadProgress()));
return true;
}, [=] {
if (ioCatchError(_writer->writeLeftChannelEnd())) {
return;
}
exportNextLeftChannel();
});
return;
}
if (ioCatchError(_writer->writeLeftChannelsEnd())) {
return;
}
exportNext();
}
template <typename Callback>
ProcessingState Controller::prepareState(
Step step,
@ -561,22 +479,11 @@ ProcessingState Controller::stateInitializing() const {
return ProcessingState();
}
ProcessingState Controller::stateLeftChannelsList(int processed) const {
return prepareState(Step::LeftChannelsList, [&](
ProcessingState &result) {
result.entityIndex = processed;
result.entityCount = std::max(
processed,
substepsInStep(Step::LeftChannels))
+ substepsInStep(Step::Dialogs);
});
}
ProcessingState Controller::stateDialogsList(int processed) const {
const auto step = Step::DialogsList;
return prepareState(step, [&](ProcessingState &result) {
result.entityIndex = substepsInStep(Step::LeftChannels) + processed;
result.entityCount = substepsInStep(Step::LeftChannels) + std::max(
result.entityIndex = processed;
result.entityCount = std::max(
processed,
substepsInStep(Step::Dialogs));
});
@ -612,35 +519,15 @@ ProcessingState Controller::stateOtherData() const {
return prepareState(Step::OtherData);
}
ProcessingState Controller::stateLeftChannels(
const DownloadProgress & progress) const {
const auto step = Step::LeftChannels;
return prepareState(step, [&](ProcessingState &result) {
const auto addIndex = _dialogsInfo.list.size();
const auto addCount = addIndex;
fillMessagesState(
result,
_leftChannelsInfo,
_leftChannelIndex,
progress,
addIndex,
addCount);
});
}
ProcessingState Controller::stateDialogs(
const DownloadProgress &progress) const {
const auto step = Step::Dialogs;
return prepareState(step, [&](ProcessingState &result) {
const auto addIndex = 0;
const auto addCount = _leftChannelsInfo.list.size();
fillMessagesState(
result,
_dialogsInfo,
_dialogIndex,
progress,
addIndex,
addCount);
progress);
});
}
@ -648,14 +535,14 @@ void Controller::fillMessagesState(
ProcessingState &result,
const Data::DialogsInfo &info,
int index,
const DownloadProgress &progress,
int addIndex,
int addCount) const {
const auto &dialog = info.list[index];
result.entityIndex = index + addIndex;
result.entityCount = info.list.size() + addCount;
result.entityName = dialog.name;
result.entityType = (dialog.type == Data::DialogInfo::Type::Self)
const DownloadProgress &progress) const {
const auto dialog = info.item(index);
Assert(dialog != nullptr);
result.entityIndex = index;
result.entityCount = info.chats.size() + info.left.size();
result.entityName = dialog->name;
result.entityType = (dialog->type == Data::DialogInfo::Type::Self)
? ProcessingState::EntityType::SavedMessages
: ProcessingState::EntityType::Chat;
result.itemIndex = _messagesWritten + progress.itemIndex;

View File

@ -28,14 +28,12 @@ struct PasswordCheckState {
struct ProcessingState {
enum class Step {
Initializing,
LeftChannelsList,
DialogsList,
PersonalInfo,
Userpics,
Contacts,
Sessions,
OtherData,
LeftChannels,
Dialogs,
};
enum class FileType {

View File

@ -467,8 +467,8 @@ Stats AbstractWriter::produceTestExample(
dialogChat.splits.push_back(1);
dialogChat.topMessageDate = sliceChat2.list.back().date;
dialogChat.topMessageId = sliceChat2.list.back().id;
dialogs.list.push_back(dialogBot);
dialogs.list.push_back(dialogChat);
dialogs.chats.push_back(dialogBot);
dialogs.chats.push_back(dialogChat);
check(writeDialogsStart(dialogs));
check(writeDialogStart(dialogBot));
@ -481,9 +481,6 @@ Stats AbstractWriter::produceTestExample(
check(writeDialogEnd());
check(writeDialogsEnd());
check(writeLeftChannelsStart(Data::DialogsInfo()));
check(writeLeftChannelsEnd());
check(finish());
return result;

View File

@ -75,15 +75,6 @@ public:
[[nodiscard]] virtual Result writeDialogEnd() = 0;
[[nodiscard]] virtual Result writeDialogsEnd() = 0;
[[nodiscard]] virtual Result writeLeftChannelsStart(
const Data::DialogsInfo &data) = 0;
[[nodiscard]] virtual Result writeLeftChannelStart(
const Data::DialogInfo &data) = 0;
[[nodiscard]] virtual Result writeLeftChannelSlice(
const Data::MessagesSlice &data) = 0;
[[nodiscard]] virtual Result writeLeftChannelEnd() = 0;
[[nodiscard]] virtual Result writeLeftChannelsEnd() = 0;
[[nodiscard]] virtual Result finish() = 0;
[[nodiscard]] virtual QString mainFilePath() = 0;

View File

@ -1755,7 +1755,6 @@ Result HtmlWriter::start(
"images/section_chats.png",
"images/section_contacts.png",
"images/section_frequent.png",
"images/section_leftchats.png",
"images/section_other.png",
"images/section_photos.png",
"images/section_sessions.png",
@ -1874,7 +1873,7 @@ Result HtmlWriter::writeUserpicsStart(const Data::UserpicsInfo &data) {
_userpics = fileWithRelativePath(userpicsFilePath());
auto block = _userpics->pushHeader(
"Personal photos",
"Profile pictures",
mainFileRelativePath());
block.append(_userpics->pushDiv("page_body list_page"));
block.append(_userpics->pushDiv("entry_list"));
@ -2198,98 +2197,36 @@ Result HtmlWriter::writeOtherData(const Data::File &data) {
}
Result HtmlWriter::writeDialogsStart(const Data::DialogsInfo &data) {
return writeChatsStart(
data,
"Chats",
"chats",
_environment.aboutChats,
"lists/chats.html");
}
Result HtmlWriter::writeDialogStart(const Data::DialogInfo &data) {
return writeChatStart(data);
}
Result HtmlWriter::writeDialogSlice(const Data::MessagesSlice &data) {
return writeChatSlice(data);
}
Result HtmlWriter::writeDialogEnd() {
return writeChatEnd();
}
Result HtmlWriter::writeDialogsEnd() {
return writeChatsEnd();
}
Result HtmlWriter::writeLeftChannelsStart(const Data::DialogsInfo &data) {
return writeChatsStart(
data,
"Left chats",
"leftchats",
_environment.aboutLeftChats,
"lists/left_chats.html");
}
Result HtmlWriter::writeLeftChannelStart(const Data::DialogInfo &data) {
return writeChatStart(data);
}
Result HtmlWriter::writeLeftChannelSlice(const Data::MessagesSlice &data) {
return writeChatSlice(data);
}
Result HtmlWriter::writeLeftChannelEnd() {
return writeChatEnd();
}
Result HtmlWriter::writeLeftChannelsEnd() {
return writeChatsEnd();
}
Result HtmlWriter::writeChatsStart(
const Data::DialogsInfo &data,
const QByteArray &listName,
const QByteArray &buttonClass,
const QByteArray &about,
const QString &fileName) {
Expects(_summary != nullptr);
Expects(_chats == nullptr);
if (data.list.empty()) {
if (data.chats.empty() && data.left.empty()) {
return Result::Success();
}
_dialogsRelativePath = fileName;
_chats = fileWithRelativePath(fileName);
_dialogIndex = 0;
_dialogsCount = data.list.size();
_dialogsRelativePath = "lists/chats.html";
_chats = fileWithRelativePath(_dialogsRelativePath);
auto block = _chats->pushHeader(
listName,
"Chats",
mainFileRelativePath());
block.append(_chats->pushDiv("page_body list_page"));
block.append(_chats->pushAbout(about));
block.append(_chats->pushDiv("entry_list"));
if (const auto result = _chats->writeBlock(block); !result) {
return result;
}
pushSection(
0,
listName,
buttonClass,
data.list.size(),
fileName);
"Chats",
"chats",
data.chats.size() + data.left.size(),
"lists/chats.html");
return writeSections();
}
Result HtmlWriter::writeChatStart(const Data::DialogInfo &data) {
Result HtmlWriter::writeDialogStart(const Data::DialogInfo &data) {
Expects(_chat == nullptr);
Expects(_dialogIndex < _dialogsCount);
const auto digits = Data::NumberToString(_dialogsCount - 1).size();
const auto number = Data::NumberToString(++_dialogIndex, digits, '0');
_chat = fileWithRelativePath(data.relativePath + messagesFile(0));
_chatFileEmpty = true;
_messagesCount = 0;
@ -2299,29 +2236,7 @@ Result HtmlWriter::writeChatStart(const Data::DialogInfo &data) {
return Result::Success();
}
Result HtmlWriter::writeChatOpening(int index) {
const auto name = (_dialog.name.isEmpty()
&& _dialog.lastName.isEmpty())
? QByteArray("Deleted Account")
: (_dialog.name + ' ' + _dialog.lastName);
auto block = _chat->pushHeader(
name,
_dialogsRelativePath);
block.append(_chat->pushDiv("page_body chat_page"));
block.append(_chat->pushDiv("history"));
if (index > 0) {
const auto previousPath = messagesFile(index - 1);
block.append(_chat->pushTag("a", {
{ "class", "pagination block_link" },
{ "href", previousPath.toUtf8() }
}));
block.append("Previous messages part");
block.append(_chat->popTag());
}
return _chat->writeBlock(block);
}
Result HtmlWriter::writeChatSlice(const Data::MessagesSlice &data) {
Result HtmlWriter::writeDialogSlice(const Data::MessagesSlice &data) {
Expects(_chat != nullptr);
Expects(!data.list.empty());
@ -2331,7 +2246,7 @@ Result HtmlWriter::writeChatSlice(const Data::MessagesSlice &data) {
auto block = QByteArray();
for (const auto &message : data.list) {
if (_chatFileEmpty) {
if (const auto result = writeChatOpening(oldIndex); !result) {
if (const auto result = writeDialogOpening(oldIndex); !result) {
return result;
}
_chatFileEmpty = false;
@ -2378,7 +2293,7 @@ Result HtmlWriter::writeChatSlice(const Data::MessagesSlice &data) {
return _chat->writeBlock(block);
}
Result HtmlWriter::writeChatEnd() {
Result HtmlWriter::writeDialogEnd() {
Expects(_chats != nullptr);
Expects(_chat != nullptr);
@ -2446,6 +2361,12 @@ Result HtmlWriter::writeChatEnd() {
};
userpic.firstName = NameString(_dialog);
userpic.lastName = LastNameString(_dialog);
const auto result = validateDialogsMode(_dialog.isLeftChannel);
if (!result) {
return result;
}
return _chats->writeBlock(_chats->pushListEntry(
userpic,
ComposeName(userpic, DeletedString(_dialog.type)),
@ -2456,13 +2377,55 @@ Result HtmlWriter::writeChatEnd() {
: QString())));
}
Result HtmlWriter::writeChatsEnd() {
Result HtmlWriter::validateDialogsMode(bool isLeftChannel) {
const auto mode = isLeftChannel
? DialogsMode::Left
: DialogsMode::Chats;
if (_dialogsMode == mode) {
return Result::Success();
} else if (_dialogsMode != DialogsMode::None) {
const auto result = _chats->writeBlock(_chats->popTag());
if (!result) {
return result;
}
}
_dialogsMode = mode;
auto block = _chats->pushAbout(isLeftChannel
? _environment.aboutLeftChats
: _environment.aboutChats);
block.append(_chats->pushDiv("entry_list"));
return _chats->writeBlock(block);
}
Result HtmlWriter::writeDialogsEnd() {
if (_chats) {
return base::take(_chats)->close();
}
return Result::Success();
}
Result HtmlWriter::writeDialogOpening(int index) {
const auto name = (_dialog.name.isEmpty()
&& _dialog.lastName.isEmpty())
? QByteArray("Deleted Account")
: (_dialog.name + ' ' + _dialog.lastName);
auto block = _chat->pushHeader(
name,
_dialogsRelativePath);
block.append(_chat->pushDiv("page_body chat_page"));
block.append(_chat->pushDiv("history"));
if (index > 0) {
const auto previousPath = messagesFile(index - 1);
block.append(_chat->pushTag("a", {
{ "class", "pagination block_link" },
{ "href", previousPath.toUtf8() }
}));
block.append("Previous messages");
block.append(_chat->popTag());
}
return _chat->writeBlock(block);
}
void HtmlWriter::pushSection(
int priority,
const QByteArray &label,
@ -2513,7 +2476,7 @@ Result HtmlWriter::switchToNextChatFile(int index) {
{ "class", "pagination block_link" },
{ "href", nextPath.toUtf8() }
});
next.append("Next messages part");
next.append("Next messages");
next.append(_chat->popTag());
if (const auto result = _chat->writeBlock(next); !result) {
return result;

View File

@ -71,12 +71,6 @@ public:
Result writeDialogEnd() override;
Result writeDialogsEnd() override;
Result writeLeftChannelsStart(const Data::DialogsInfo &data) override;
Result writeLeftChannelStart(const Data::DialogInfo &data) override;
Result writeLeftChannelSlice(const Data::MessagesSlice &data) override;
Result writeLeftChannelEnd() override;
Result writeLeftChannelsEnd() override;
Result finish() override;
QString mainFilePath() override;
@ -89,15 +83,21 @@ private:
using MediaData = details::MediaData;
class Wrap;
struct MessageInfo;
enum class DialogsMode {
None,
Chats,
Left,
};
[[nodiscard]] Result copyFile(
const QString &source,
const QString &relativePath) const;
QString mainFileRelativePath() const;
QString pathWithRelativePath(const QString &path) const;
std::unique_ptr<Wrap> fileWithRelativePath(const QString &path) const;
QString messagesFile(int index) const;
[[nodiscard]] QString mainFileRelativePath() const;
[[nodiscard]] QString pathWithRelativePath(const QString &path) const;
[[nodiscard]] std::unique_ptr<Wrap> fileWithRelativePath(
const QString &path) const;
[[nodiscard]] QString messagesFile(int index) const;
[[nodiscard]] Result writeSavedContacts(const Data::ContactsList &data);
[[nodiscard]] Result writeFrequentContacts(const Data::ContactsList &data);
@ -105,17 +105,8 @@ private:
[[nodiscard]] Result writeSessions(const Data::SessionsList &data);
[[nodiscard]] Result writeWebSessions(const Data::SessionsList &data);
[[nodiscard]] Result writeChatsStart(
const Data::DialogsInfo &data,
const QByteArray &listName,
const QByteArray &buttonClass,
const QByteArray &about,
const QString &fileName);
[[nodiscard]] Result writeChatStart(const Data::DialogInfo &data);
[[nodiscard]] Result writeChatOpening(int index);
[[nodiscard]] Result writeChatSlice(const Data::MessagesSlice &data);
[[nodiscard]] Result writeChatEnd();
[[nodiscard]] Result writeChatsEnd();
[[nodiscard]] Result validateDialogsMode(bool isLeftChannel);
[[nodiscard]] Result writeDialogOpening(int index);
[[nodiscard]] Result switchToNextChatFile(int index);
void pushSection(
@ -153,10 +144,9 @@ private:
int _userpicsCount = 0;
std::unique_ptr<Wrap> _userpics;
int _dialogsCount = 0;
int _dialogIndex = 0;
QString _dialogsRelativePath;
Data::DialogInfo _dialog;
DialogsMode _dialogsMode = DialogsMode::None;
int _messagesCount = 0;
std::unique_ptr<MessageInfo> _lastMessageInfo;

View File

@ -593,7 +593,10 @@ Result JsonWriter::start(
_stats = stats;
_output = fileWithRelativePath(mainFileRelativePath());
return _output->writeBlock(pushNesting(Context::kObject));
auto block = pushNesting(Context::kObject);
block.append(prepareObjectItemStart("about"));
block.append(SerializeString(_environment.aboutTelegram));
return _output->writeBlock(block);
}
QByteArray JsonWriter::pushNesting(Context::Type type) {
@ -943,56 +946,16 @@ Result JsonWriter::writeWebSessions(const Data::SessionsList &data) {
}
Result JsonWriter::writeDialogsStart(const Data::DialogsInfo &data) {
return writeChatsStart(data, "chats");
return Result::Success();
}
Result JsonWriter::writeDialogStart(const Data::DialogInfo &data) {
return writeChatStart(data);
}
Result JsonWriter::writeDialogSlice(const Data::MessagesSlice &data) {
return writeChatSlice(data);
}
Result JsonWriter::writeDialogEnd() {
return writeChatEnd();
}
Result JsonWriter::writeDialogsEnd() {
return writeChatsEnd();
}
Result JsonWriter::writeLeftChannelsStart(const Data::DialogsInfo &data) {
return writeChatsStart(data, "left_chats");
}
Result JsonWriter::writeLeftChannelStart(const Data::DialogInfo &data) {
return writeChatStart(data);
}
Result JsonWriter::writeLeftChannelSlice(const Data::MessagesSlice &data) {
return writeChatSlice(data);
}
Result JsonWriter::writeLeftChannelEnd() {
return writeChatEnd();
}
Result JsonWriter::writeLeftChannelsEnd() {
return writeChatsEnd();
}
Result JsonWriter::writeChatsStart(
const Data::DialogsInfo &data,
const QByteArray &listName) {
Expects(_output != nullptr);
auto block = prepareObjectItemStart(listName);
return _output->writeBlock(block + pushNesting(Context::kArray));
}
Result JsonWriter::writeChatStart(const Data::DialogInfo &data) {
Expects(_output != nullptr);
const auto result = validateDialogsMode(data.isLeftChannel);
if (!result) {
return result;
}
using Type = Data::DialogInfo::Type;
const auto TypeString = [](Type type) {
@ -1023,7 +986,26 @@ Result JsonWriter::writeChatStart(const Data::DialogInfo &data) {
return _output->writeBlock(block);
}
Result JsonWriter::writeChatSlice(const Data::MessagesSlice &data) {
Result JsonWriter::validateDialogsMode(bool isLeftChannel) {
const auto mode = isLeftChannel
? DialogsMode::Left
: DialogsMode::Chats;
if (_dialogsMode == mode) {
return Result::Success();
} else if (_dialogsMode != DialogsMode::None) {
if (const auto result = writeChatsEnd(); !result) {
return result;
}
}
_dialogsMode = mode;
return writeChatsStart(
isLeftChannel ? "left_chats" : "chats",
(isLeftChannel
? _environment.aboutLeftChats
: _environment.aboutChats));
}
Result JsonWriter::writeDialogSlice(const Data::MessagesSlice &data) {
Expects(_output != nullptr);
auto block = QByteArray();
@ -1037,17 +1019,35 @@ Result JsonWriter::writeChatSlice(const Data::MessagesSlice &data) {
return _output->writeBlock(block);
}
Result JsonWriter::writeChatEnd() {
Result JsonWriter::writeDialogEnd() {
Expects(_output != nullptr);
auto block = popNesting();
return _output->writeBlock(block + popNesting());
}
Result JsonWriter::writeDialogsEnd() {
return writeChatsEnd();
}
Result JsonWriter::writeChatsStart(
const QByteArray &listName,
const QByteArray &about) {
Expects(_output != nullptr);
auto block = prepareObjectItemStart(listName);
block.append(pushNesting(Context::kObject));
block.append(prepareObjectItemStart("about"));
block.append(SerializeString(about));
block.append(prepareObjectItemStart("list"));
return _output->writeBlock(block + pushNesting(Context::kArray));
}
Result JsonWriter::writeChatsEnd() {
Expects(_output != nullptr);
return _output->writeBlock(popNesting());
auto block = popNesting();
return _output->writeBlock(block + popNesting());
}
Result JsonWriter::finish() {

View File

@ -56,41 +56,39 @@ public:
Result writeDialogEnd() override;
Result writeDialogsEnd() override;
Result writeLeftChannelsStart(const Data::DialogsInfo &data) override;
Result writeLeftChannelStart(const Data::DialogInfo &data) override;
Result writeLeftChannelSlice(const Data::MessagesSlice &data) override;
Result writeLeftChannelEnd() override;
Result writeLeftChannelsEnd() override;
Result finish() override;
QString mainFilePath() override;
private:
using Context = details::JsonContext;
enum class DialogsMode {
None,
Chats,
Left,
};
[[nodiscard]] QByteArray pushNesting(Context::Type type);
[[nodiscard]] QByteArray prepareObjectItemStart(const QByteArray &key);
[[nodiscard]] QByteArray prepareArrayItemStart();
[[nodiscard]] QByteArray popNesting();
QString mainFileRelativePath() const;
QString pathWithRelativePath(const QString &path) const;
std::unique_ptr<File> fileWithRelativePath(const QString &path) const;
[[nodiscard]] QString mainFileRelativePath() const;
[[nodiscard]] QString pathWithRelativePath(const QString &path) const;
[[nodiscard]] std::unique_ptr<File> fileWithRelativePath(
const QString &path) const;
Result writeSavedContacts(const Data::ContactsList &data);
Result writeFrequentContacts(const Data::ContactsList &data);
[[nodiscard]] Result writeSavedContacts(const Data::ContactsList &data);
[[nodiscard]] Result writeFrequentContacts(const Data::ContactsList &data);
Result writeSessions(const Data::SessionsList &data);
Result writeWebSessions(const Data::SessionsList &data);
[[nodiscard]] Result writeSessions(const Data::SessionsList &data);
[[nodiscard]] Result writeWebSessions(const Data::SessionsList &data);
Result writeChatsStart(
const Data::DialogsInfo &data,
const QByteArray &listName);
Result writeChatStart(const Data::DialogInfo &data);
Result writeChatSlice(const Data::MessagesSlice &data);
Result writeChatEnd();
Result writeChatsEnd();
[[nodiscard]] Result validateDialogsMode(bool isLeftChannel);
[[nodiscard]] Result writeChatsStart(
const QByteArray &listName,
const QByteArray &about);
[[nodiscard]] Result writeChatsEnd();
Settings _settings;
Environment _environment;
@ -98,6 +96,7 @@ private:
Context _context;
bool _currentNestingHadItem = false;
DialogsMode _dialogsMode = DialogsMode::None;
std::unique_ptr<File> _output;

View File

@ -786,95 +786,47 @@ Result TextWriter::writeOtherData(const Data::File &data) {
}
Result TextWriter::writeDialogsStart(const Data::DialogsInfo &data) {
return writeChatsStart(
data,
"Chats",
_environment.aboutChats,
"lists/chats.txt");
_dialogsCount = data.chats.size();
_leftChannelsCount = data.left.size();
return Result::Success();
}
Result TextWriter::writeDialogStart(const Data::DialogInfo &data) {
return writeChatStart(data);
}
Expects(_chat == nullptr);
Result TextWriter::writeDialogSlice(const Data::MessagesSlice &data) {
return writeChatSlice(data);
}
Result TextWriter::writeDialogEnd() {
return writeChatEnd();
}
Result TextWriter::writeDialogsEnd() {
return writeChatsEnd();
}
Result TextWriter::writeLeftChannelsStart(const Data::DialogsInfo &data) {
return writeChatsStart(
data,
"Left chats",
_environment.aboutLeftChats,
"lists/left_chats.txt");
}
Result TextWriter::writeLeftChannelStart(const Data::DialogInfo &data) {
return writeChatStart(data);
}
Result TextWriter::writeLeftChannelSlice(const Data::MessagesSlice &data) {
return writeChatSlice(data);
}
Result TextWriter::writeLeftChannelEnd() {
return writeChatEnd();
}
Result TextWriter::writeLeftChannelsEnd() {
return writeChatsEnd();
}
Result TextWriter::writeChatsStart(
const Data::DialogsInfo &data,
const QByteArray &listName,
const QByteArray &about,
const QString &fileName) {
Expects(_summary != nullptr);
Expects(_chats == nullptr);
if (data.list.empty()) {
return Result::Success();
}
_chats = fileWithRelativePath(fileName);
_dialogIndex = 0;
_dialogsCount = data.list.size();
const auto block = about + kLineBreak;
if (const auto result = _chats->writeBlock(block); !result) {
const auto result = validateDialogsMode(data.isLeftChannel);
if (!result) {
return result;
}
const auto header = listName + " "
"(" + Data::NumberToString(data.list.size()) + ") - "
+ fileName.toUtf8()
+ kLineBreak
+ kLineBreak;
return _summary->writeBlock(header);
}
Result TextWriter::writeChatStart(const Data::DialogInfo &data) {
Expects(_chat == nullptr);
Expects(_dialogIndex < _dialogsCount);
const auto digits = Data::NumberToString(_dialogsCount - 1).size();
const auto number = Data::NumberToString(++_dialogIndex, digits, '0');
_chat = fileWithRelativePath(data.relativePath + "messages.txt");
_messagesCount = 0;
_dialog = data;
return Result::Success();
}
Result TextWriter::writeChatSlice(const Data::MessagesSlice &data) {
Result TextWriter::validateDialogsMode(bool isLeftChannel) {
const auto mode = isLeftChannel
? DialogsMode::Left
: DialogsMode::Chats;
if (_dialogsMode == mode) {
return Result::Success();
} else if (_dialogsMode != DialogsMode::None) {
if (const auto result = writeChatsEnd(); !result) {
return result;
}
}
_dialogsMode = mode;
return writeChatsStart(
isLeftChannel ? _leftChannelsCount : _dialogsCount,
isLeftChannel ? "Left chats" : "Chats",
(isLeftChannel
? _environment.aboutLeftChats
: _environment.aboutChats),
isLeftChannel ? "lists/left_chats.txt" : "lists/chats.txt");
}
Result TextWriter::writeDialogSlice(const Data::MessagesSlice &data) {
Expects(_chat != nullptr);
Expects(!data.list.empty());
@ -893,7 +845,7 @@ Result TextWriter::writeChatSlice(const Data::MessagesSlice &data) {
return _chat->writeBlock(full);
}
Result TextWriter::writeChatEnd() {
Result TextWriter::writeDialogEnd() {
Expects(_chats != nullptr);
Expects(_chat != nullptr);
@ -954,6 +906,37 @@ Result TextWriter::writeChatEnd() {
}));
}
Result TextWriter::writeDialogsEnd() {
return writeChatsEnd();
}
Result TextWriter::writeChatsStart(
int count,
const QByteArray &listName,
const QByteArray &about,
const QString &fileName) {
Expects(_summary != nullptr);
Expects(_chats == nullptr);
if (!count) {
return Result::Success();
}
_chats = fileWithRelativePath(fileName);
const auto block = about + kLineBreak;
if (const auto result = _chats->writeBlock(block); !result) {
return result;
}
const auto header = listName + " "
"(" + Data::NumberToString(count) + ") - "
+ fileName.toUtf8()
+ kLineBreak
+ kLineBreak;
return _summary->writeBlock(header);
}
Result TextWriter::writeChatsEnd() {
_chats = nullptr;
return Result::Success();

View File

@ -44,36 +44,35 @@ public:
Result writeDialogEnd() override;
Result writeDialogsEnd() override;
Result writeLeftChannelsStart(const Data::DialogsInfo &data) override;
Result writeLeftChannelStart(const Data::DialogInfo &data) override;
Result writeLeftChannelSlice(const Data::MessagesSlice &data) override;
Result writeLeftChannelEnd() override;
Result writeLeftChannelsEnd() override;
Result finish() override;
QString mainFilePath() override;
private:
QString mainFileRelativePath() const;
QString pathWithRelativePath(const QString &path) const;
std::unique_ptr<File> fileWithRelativePath(const QString &path) const;
enum class DialogsMode {
None,
Chats,
Left,
};
Result writeSavedContacts(const Data::ContactsList &data);
Result writeFrequentContacts(const Data::ContactsList &data);
[[nodiscard]] QString mainFileRelativePath() const;
[[nodiscard]] QString pathWithRelativePath(const QString &path) const;
[[nodiscard]] std::unique_ptr<File> fileWithRelativePath(
const QString &path) const;
Result writeSessions(const Data::SessionsList &data);
Result writeWebSessions(const Data::SessionsList &data);
[[nodiscard]] Result writeSavedContacts(const Data::ContactsList &data);
[[nodiscard]] Result writeFrequentContacts(const Data::ContactsList &data);
Result writeChatsStart(
const Data::DialogsInfo &data,
[[nodiscard]] Result writeSessions(const Data::SessionsList &data);
[[nodiscard]] Result writeWebSessions(const Data::SessionsList &data);
[[nodiscard]] Result validateDialogsMode(bool isLeftChannel);
[[nodiscard]] Result writeChatsStart(
int count,
const QByteArray &listName,
const QByteArray &about,
const QString &fileName);
Result writeChatStart(const Data::DialogInfo &data);
Result writeChatSlice(const Data::MessagesSlice &data);
Result writeChatEnd();
Result writeChatsEnd();
[[nodiscard]] Result writeChatsEnd();
Settings _settings;
Environment _environment;
@ -85,8 +84,9 @@ private:
std::unique_ptr<File> _userpics;
int _dialogsCount = 0;
int _dialogIndex = 0;
int _leftChannelsCount = 0;
Data::DialogInfo _dialog;
DialogsMode _dialogsMode = DialogsMode::None;
int _messagesCount = 0;
std::unique_ptr<File> _chats;

View File

@ -61,7 +61,6 @@ Content ContentFromState(const ProcessingState &state) {
case Step::Initializing:
pushMain(lang(lng_export_state_initializing));
break;
case Step::LeftChannelsList:
case Step::DialogsList:
pushMain(lang(lng_export_state_chats_list));
break;
@ -83,7 +82,6 @@ Content ContentFromState(const ProcessingState &state) {
case Step::OtherData:
pushMain(lang(lng_export_option_other));
break;
case Step::LeftChannels:
case Step::Dialogs:
pushMain(lang(lng_export_state_chats));
push(