mirror of https://github.com/procxx/kepka.git
Improve export HTML layout.
This commit is contained in:
parent
78558e513c
commit
0b7bb806b7
|
@ -400,9 +400,6 @@ a.block_link:hover {
|
||||||
.section.web {
|
.section.web {
|
||||||
background-image: url(../images/section_web.png);
|
background-image: url(../images/section_web.png);
|
||||||
}
|
}
|
||||||
.section.leftchats {
|
|
||||||
background-image: url(../images/section_leftchats.png);
|
|
||||||
}
|
|
||||||
.section.other {
|
.section.other {
|
||||||
background-image: url(../images/section_other.png)
|
background-image: url(../images/section_other.png)
|
||||||
}
|
}
|
||||||
|
@ -464,9 +461,6 @@ a.block_link:hover {
|
||||||
.section.web {
|
.section.web {
|
||||||
background-image: url(../images/section_web@2x.png);
|
background-image: url(../images/section_web@2x.png);
|
||||||
}
|
}
|
||||||
.section.leftchats {
|
|
||||||
background-image: url(../images/section_leftchats@2x.png);
|
|
||||||
}
|
|
||||||
.section.other {
|
.section.other {
|
||||||
background-image: url(../images/section_other@2x.png);
|
background-image: url(../images/section_other@2x.png);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1731,11 +1731,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_export_suggest_cancel" = "Not now";
|
"lng_export_suggest_cancel" = "Not now";
|
||||||
"lng_export_about_telegram" = "Here is all the data you requested. Remember: we don’t use your data for ad targeting, we don’t sell it to others, and we’re 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_telegram" = "Here is all the data you requested. Remember: we don’t use your data for ad targeting, we don’t sell it to others, and we’re 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_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_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_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_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
|
// Wnd specific
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
<file alias="images/section_contacts@2x.png">../export_html/images/section_contacts@2x.png</file>
|
<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.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_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.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_other@2x.png">../export_html/images/section_other@2x.png</file>
|
||||||
<file alias="images/section_photos.png">../export_html/images/section_photos.png</file>
|
<file alias="images/section_photos.png">../export_html/images/section_photos.png</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) {
|
DialogInfo::Type DialogTypeFromChat(const Chat &chat) {
|
||||||
using Type = DialogInfo::Type;
|
using Type = DialogInfo::Type;
|
||||||
return chat.username.isEmpty()
|
return chat.username.isEmpty()
|
||||||
|
@ -1325,7 +1347,7 @@ DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data) {
|
||||||
}, [&](const auto &data) { // MTPDmessages_dialogs &data) {
|
}, [&](const auto &data) { // MTPDmessages_dialogs &data) {
|
||||||
const auto peers = ParsePeersLists(data.vusers, data.vchats);
|
const auto peers = ParsePeersLists(data.vusers, data.vchats);
|
||||||
const auto messages = ParseMessagesList(data.vmessages, folder);
|
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) {
|
for (const auto &dialog : data.vdialogs.v) {
|
||||||
if (dialog.type() != mtpc_dialog) {
|
if (dialog.type() != mtpc_dialog) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1358,7 +1380,7 @@ DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data) {
|
||||||
const auto &message = messageIt->second;
|
const auto &message = messageIt->second;
|
||||||
info.topMessageDate = message.date;
|
info.topMessageDate = message.date;
|
||||||
}
|
}
|
||||||
result.list.push_back(std::move(info));
|
result.chats.push_back(std::move(info));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
@ -1367,7 +1389,7 @@ DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data) {
|
||||||
DialogsInfo ParseLeftChannelsInfo(const MTPmessages_Chats &data) {
|
DialogsInfo ParseLeftChannelsInfo(const MTPmessages_Chats &data) {
|
||||||
auto result = DialogsInfo();
|
auto result = DialogsInfo();
|
||||||
data.match([&](const auto &data) { //MTPDmessages_chats &data) {
|
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) {
|
for (const auto &single : data.vchats.v) {
|
||||||
const auto chat = ParseChat(single);
|
const auto chat = ParseChat(single);
|
||||||
auto info = DialogInfo();
|
auto info = DialogInfo();
|
||||||
|
@ -1377,17 +1399,20 @@ DialogsInfo ParseLeftChannelsInfo(const MTPmessages_Chats &data) {
|
||||||
info.topMessageDate = 0;
|
info.topMessageDate = 0;
|
||||||
info.topMessageId = 0;
|
info.topMessageId = 0;
|
||||||
info.type = DialogTypeFromChat(chat);
|
info.type = DialogTypeFromChat(chat);
|
||||||
result.list.push_back(std::move(info));
|
info.isLeftChannel = true;
|
||||||
|
result.left.push_back(std::move(info));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings) {
|
void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings) {
|
||||||
auto &list = info.list;
|
auto &chats = info.chats;
|
||||||
const auto digits = Data::NumberToString(list.size() - 1).size();
|
auto &left = info.left;
|
||||||
|
const auto fullCount = chats.size() + left.size();
|
||||||
|
const auto digits = Data::NumberToString(fullCount - 1).size();
|
||||||
auto index = 0;
|
auto index = 0;
|
||||||
for (auto &dialog : list) {
|
for (auto &dialog : chats) {
|
||||||
const auto number = Data::NumberToString(++index, digits, '0');
|
const auto number = Data::NumberToString(++index, digits, '0');
|
||||||
dialog.relativePath = "chats/chat_" + number + '/';
|
dialog.relativePath = "chats/chat_" + number + '/';
|
||||||
|
|
||||||
|
@ -1410,15 +1435,9 @@ void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings) {
|
||||||
|
|
||||||
ranges::reverse(dialog.splits);
|
ranges::reverse(dialog.splits);
|
||||||
}
|
}
|
||||||
}
|
for (auto &dialog : left) {
|
||||||
|
|
||||||
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) {
|
|
||||||
const auto number = Data::NumberToString(++index, digits, '0');
|
const auto number = Data::NumberToString(++index, digits, '0');
|
||||||
dialog.relativePath = "chats/left_" + number + '/';
|
dialog.relativePath = "chats/chat_" + number + '/';
|
||||||
dialog.onlyMyMessages = true;
|
dialog.onlyMyMessages = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -521,13 +521,14 @@ struct DialogInfo {
|
||||||
MTPInputPeer input = MTP_inputPeerEmpty();
|
MTPInputPeer input = MTP_inputPeerEmpty();
|
||||||
int32 topMessageId = 0;
|
int32 topMessageId = 0;
|
||||||
TimeId topMessageDate = 0;
|
TimeId topMessageDate = 0;
|
||||||
PeerId peerId;
|
PeerId peerId = 0;
|
||||||
|
|
||||||
// User messages splits which contained that dialog.
|
// User messages splits which contained that dialog.
|
||||||
std::vector<int> splits;
|
std::vector<int> splits;
|
||||||
|
|
||||||
// Filled after the whole dialogs list is accumulated.
|
// Filled after the whole dialogs list is accumulated.
|
||||||
bool onlyMyMessages = false;
|
bool onlyMyMessages = false;
|
||||||
|
bool isLeftChannel = false;
|
||||||
QString relativePath;
|
QString relativePath;
|
||||||
|
|
||||||
// Filled when requesting dialog messages.
|
// Filled when requesting dialog messages.
|
||||||
|
@ -535,7 +536,11 @@ struct DialogInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DialogsInfo {
|
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);
|
DialogInfo::Type DialogTypeFromChat(const Chat &chat);
|
||||||
|
@ -543,7 +548,6 @@ DialogInfo::Type DialogTypeFromChat(const Chat &chat);
|
||||||
DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data);
|
DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data);
|
||||||
DialogsInfo ParseLeftChannelsInfo(const MTPmessages_Chats &data);
|
DialogsInfo ParseLeftChannelsInfo(const MTPmessages_Chats &data);
|
||||||
void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings);
|
void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings);
|
||||||
void FinalizeLeftChannelsInfo(DialogsInfo &info, const Settings &settings);
|
|
||||||
|
|
||||||
struct MessagesSlice {
|
struct MessagesSlice {
|
||||||
std::vector<Message> list;
|
std::vector<Message> list;
|
||||||
|
|
|
@ -536,8 +536,8 @@ void ApiWrap::requestLeftChannelsCount() {
|
||||||
Expects(_startProcess != nullptr);
|
Expects(_startProcess != nullptr);
|
||||||
Expects(_leftChannelsProcess != nullptr);
|
Expects(_leftChannelsProcess != nullptr);
|
||||||
|
|
||||||
_startProcess->info.leftChannelsCount
|
_startProcess->info.dialogsCount
|
||||||
= _leftChannelsProcess->fullCount;
|
+= _leftChannelsProcess->fullCount;
|
||||||
sendNextStartRequest();
|
sendNextStartRequest();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -569,7 +569,6 @@ void ApiWrap::requestLeftChannelsSlice() {
|
||||||
|
|
||||||
if (_leftChannelsProcess->finished) {
|
if (_leftChannelsProcess->finished) {
|
||||||
const auto process = base::take(_leftChannelsProcess);
|
const auto process = base::take(_leftChannelsProcess);
|
||||||
Data::FinalizeLeftChannelsInfo(process->info, *_settings);
|
|
||||||
process->done(std::move(process->info));
|
process->done(std::move(process->info));
|
||||||
} else {
|
} else {
|
||||||
requestLeftChannelsSlice();
|
requestLeftChannelsSlice();
|
||||||
|
@ -987,10 +986,10 @@ void ApiWrap::requestDialogsSlice() {
|
||||||
});
|
});
|
||||||
|
|
||||||
auto info = Data::ParseDialogsInfo(result);
|
auto info = Data::ParseDialogsInfo(result);
|
||||||
_dialogsProcess->processedCount += info.list.size();
|
_dialogsProcess->processedCount += info.chats.size();
|
||||||
const auto last = info.list.empty()
|
const auto last = info.chats.empty()
|
||||||
? Data::DialogInfo()
|
? Data::DialogInfo()
|
||||||
: info.list.back();
|
: info.chats.back();
|
||||||
appendDialogsSlice(std::move(info));
|
appendDialogsSlice(std::move(info));
|
||||||
|
|
||||||
if (!_dialogsProcess->progress(_dialogsProcess->processedCount)) {
|
if (!_dialogsProcess->progress(_dialogsProcess->processedCount)) {
|
||||||
|
@ -1007,7 +1006,7 @@ void ApiWrap::requestDialogsSlice() {
|
||||||
_dialogsProcess->offsetDate = 0;
|
_dialogsProcess->offsetDate = 0;
|
||||||
_dialogsProcess->offsetPeer = MTP_inputPeerEmpty();
|
_dialogsProcess->offsetPeer = MTP_inputPeerEmpty();
|
||||||
} else {
|
} else {
|
||||||
finishDialogsList();
|
requestLeftChannelsIfNeeded();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
requestDialogsSlice();
|
requestDialogsSlice();
|
||||||
|
@ -1020,16 +1019,35 @@ void ApiWrap::appendDialogsSlice(Data::DialogsInfo &&info) {
|
||||||
|
|
||||||
appendChatsSlice(
|
appendChatsSlice(
|
||||||
*_dialogsProcess,
|
*_dialogsProcess,
|
||||||
std::move(info),
|
_dialogsProcess->info.chats,
|
||||||
|
std::move(info.chats),
|
||||||
_dialogsProcess->splitIndexPlusOne - 1);
|
_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() {
|
void ApiWrap::finishDialogsList() {
|
||||||
Expects(_dialogsProcess != nullptr);
|
Expects(_dialogsProcess != nullptr);
|
||||||
|
|
||||||
const auto process = base::take(_dialogsProcess);
|
const auto process = base::take(_dialogsProcess);
|
||||||
|
|
||||||
ranges::reverse(process->info.list);
|
ranges::reverse(process->info.chats);
|
||||||
Data::FinalizeDialogsInfo(process->info, *_settings);
|
Data::FinalizeDialogsInfo(process->info, *_settings);
|
||||||
|
|
||||||
process->done(std::move(process->info));
|
process->done(std::move(process->info));
|
||||||
|
@ -1067,7 +1085,7 @@ void ApiWrap::requestLeftChannelsSliceGeneric(FnMut<void()> done) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process->progress) {
|
if (process->progress) {
|
||||||
if (!process->progress(process->info.list.size())) {
|
if (!process->progress(process->info.left.size())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1082,32 +1100,33 @@ void ApiWrap::appendLeftChannelsSlice(Data::DialogsInfo &&info) {
|
||||||
|
|
||||||
appendChatsSlice(
|
appendChatsSlice(
|
||||||
*_leftChannelsProcess,
|
*_leftChannelsProcess,
|
||||||
std::move(info),
|
_leftChannelsProcess->info.left,
|
||||||
|
std::move(info.left),
|
||||||
_splits.size() - 1);
|
_splits.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::appendChatsSlice(
|
void ApiWrap::appendChatsSlice(
|
||||||
ChatsProcess &to,
|
ChatsProcess &process,
|
||||||
Data::DialogsInfo &&info,
|
std::vector<Data::DialogInfo> &to,
|
||||||
|
std::vector<Data::DialogInfo> &&from,
|
||||||
int splitIndex) {
|
int splitIndex) {
|
||||||
Expects(_settings != nullptr);
|
Expects(_settings != nullptr);
|
||||||
|
|
||||||
const auto types = _settings->types;
|
const auto types = _settings->types;
|
||||||
auto filtered = ranges::view::all(
|
auto filtered = ranges::view::all(
|
||||||
info.list
|
from
|
||||||
) | ranges::view::filter([&](const Data::DialogInfo &info) {
|
) | ranges::view::filter([&](const Data::DialogInfo &info) {
|
||||||
return (types & SettingsFromDialogsType(info.type)) != 0;
|
return (types & SettingsFromDialogsType(info.type)) != 0;
|
||||||
});
|
});
|
||||||
auto &list = to.info.list;
|
to.reserve(to.size() + from.size());
|
||||||
list.reserve(list.size() + info.list.size());
|
|
||||||
for (auto &info : filtered) {
|
for (auto &info : filtered) {
|
||||||
const auto nextIndex = list.size();
|
const auto nextIndex = to.size();
|
||||||
const auto [i, ok] = to.indexByPeer.emplace(info.peerId, nextIndex);
|
const auto [i, ok] = process.indexByPeer.emplace(info.peerId, nextIndex);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
list.push_back(std::move(info));
|
to.push_back(std::move(info));
|
||||||
}
|
}
|
||||||
list[i->second].splits.push_back(splitIndex);
|
to[i->second].splits.push_back(splitIndex);
|
||||||
list[i->second].messagesCountPerSplit.push_back(0);
|
to[i->second].messagesCountPerSplit.push_back(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,16 +42,12 @@ public:
|
||||||
struct StartInfo {
|
struct StartInfo {
|
||||||
int userpicsCount = 0;
|
int userpicsCount = 0;
|
||||||
int dialogsCount = 0;
|
int dialogsCount = 0;
|
||||||
int leftChannelsCount = 0;
|
|
||||||
};
|
};
|
||||||
void startExport(
|
void startExport(
|
||||||
const Settings &settings,
|
const Settings &settings,
|
||||||
Output::Stats *stats,
|
Output::Stats *stats,
|
||||||
FnMut<void(StartInfo)> done);
|
FnMut<void(StartInfo)> done);
|
||||||
|
|
||||||
void requestLeftChannelsList(
|
|
||||||
Fn<bool(int count)> progress,
|
|
||||||
FnMut<void(Data::DialogsInfo&&)> done);
|
|
||||||
void requestDialogsList(
|
void requestDialogsList(
|
||||||
Fn<bool(int count)> progress,
|
Fn<bool(int count)> progress,
|
||||||
FnMut<void(Data::DialogsInfo&&)> done);
|
FnMut<void(Data::DialogsInfo&&)> done);
|
||||||
|
@ -129,13 +125,18 @@ private:
|
||||||
void appendDialogsSlice(Data::DialogsInfo &&info);
|
void appendDialogsSlice(Data::DialogsInfo &&info);
|
||||||
void finishDialogsList();
|
void finishDialogsList();
|
||||||
|
|
||||||
|
void requestLeftChannelsIfNeeded();
|
||||||
|
void requestLeftChannelsList(
|
||||||
|
Fn<bool(int count)> progress,
|
||||||
|
FnMut<void(Data::DialogsInfo&&)> done);
|
||||||
void requestLeftChannelsSliceGeneric(FnMut<void()> done);
|
void requestLeftChannelsSliceGeneric(FnMut<void()> done);
|
||||||
void requestLeftChannelsSlice();
|
void requestLeftChannelsSlice();
|
||||||
void appendLeftChannelsSlice(Data::DialogsInfo &&info);
|
void appendLeftChannelsSlice(Data::DialogsInfo &&info);
|
||||||
|
|
||||||
void appendChatsSlice(
|
void appendChatsSlice(
|
||||||
ChatsProcess &to,
|
ChatsProcess &process,
|
||||||
Data::DialogsInfo &&info,
|
std::vector<Data::DialogInfo> &to,
|
||||||
|
std::vector<Data::DialogInfo> &&from,
|
||||||
int splitIndex);
|
int splitIndex);
|
||||||
|
|
||||||
void requestMessagesCount(int localSplitIndex);
|
void requestMessagesCount(int localSplitIndex);
|
||||||
|
|
|
@ -54,7 +54,6 @@ private:
|
||||||
void exportNext();
|
void exportNext();
|
||||||
void initialize();
|
void initialize();
|
||||||
void initialized(const ApiWrap::StartInfo &info);
|
void initialized(const ApiWrap::StartInfo &info);
|
||||||
void collectLeftChannels();
|
|
||||||
void collectDialogsList();
|
void collectDialogsList();
|
||||||
void exportPersonalInfo();
|
void exportPersonalInfo();
|
||||||
void exportUserpics();
|
void exportUserpics();
|
||||||
|
@ -63,31 +62,24 @@ private:
|
||||||
void exportOtherData();
|
void exportOtherData();
|
||||||
void exportDialogs();
|
void exportDialogs();
|
||||||
void exportNextDialog();
|
void exportNextDialog();
|
||||||
void exportLeftChannels();
|
|
||||||
void exportNextLeftChannel();
|
|
||||||
|
|
||||||
template <typename Callback = const decltype(kNullStateCallback) &>
|
template <typename Callback = const decltype(kNullStateCallback) &>
|
||||||
ProcessingState prepareState(
|
ProcessingState prepareState(
|
||||||
Step step,
|
Step step,
|
||||||
Callback &&callback = kNullStateCallback) const;
|
Callback &&callback = kNullStateCallback) const;
|
||||||
ProcessingState stateInitializing() const;
|
ProcessingState stateInitializing() const;
|
||||||
ProcessingState stateLeftChannelsList(int processed) const;
|
|
||||||
ProcessingState stateDialogsList(int processed) const;
|
ProcessingState stateDialogsList(int processed) const;
|
||||||
ProcessingState statePersonalInfo() const;
|
ProcessingState statePersonalInfo() const;
|
||||||
ProcessingState stateUserpics(const DownloadProgress &progress) const;
|
ProcessingState stateUserpics(const DownloadProgress &progress) const;
|
||||||
ProcessingState stateContacts() const;
|
ProcessingState stateContacts() const;
|
||||||
ProcessingState stateSessions() const;
|
ProcessingState stateSessions() const;
|
||||||
ProcessingState stateOtherData() const;
|
ProcessingState stateOtherData() const;
|
||||||
ProcessingState stateLeftChannels(
|
|
||||||
const DownloadProgress &progress) const;
|
|
||||||
ProcessingState stateDialogs(const DownloadProgress &progress) const;
|
ProcessingState stateDialogs(const DownloadProgress &progress) const;
|
||||||
void fillMessagesState(
|
void fillMessagesState(
|
||||||
ProcessingState &result,
|
ProcessingState &result,
|
||||||
const Data::DialogsInfo &info,
|
const Data::DialogsInfo &info,
|
||||||
int index,
|
int index,
|
||||||
const DownloadProgress &progress,
|
const DownloadProgress &progress) const;
|
||||||
int addIndex,
|
|
||||||
int addCount) const;
|
|
||||||
|
|
||||||
int substepsInStep(Step step) const;
|
int substepsInStep(Step step) const;
|
||||||
|
|
||||||
|
@ -97,9 +89,6 @@ private:
|
||||||
Settings _settings;
|
Settings _settings;
|
||||||
Environment _environment;
|
Environment _environment;
|
||||||
|
|
||||||
Data::DialogsInfo _leftChannelsInfo;
|
|
||||||
int _leftChannelIndex = -1;
|
|
||||||
|
|
||||||
Data::DialogsInfo _dialogsInfo;
|
Data::DialogsInfo _dialogsInfo;
|
||||||
int _dialogIndex = -1;
|
int _dialogIndex = -1;
|
||||||
|
|
||||||
|
@ -241,9 +230,6 @@ void Controller::startExport(
|
||||||
void Controller::fillExportSteps() {
|
void Controller::fillExportSteps() {
|
||||||
using Type = Settings::Type;
|
using Type = Settings::Type;
|
||||||
_steps.push_back(Step::Initializing);
|
_steps.push_back(Step::Initializing);
|
||||||
if (_settings.types & Type::GroupsChannelsMask) {
|
|
||||||
_steps.push_back(Step::LeftChannelsList);
|
|
||||||
}
|
|
||||||
if (_settings.types & Type::AnyChatsMask) {
|
if (_settings.types & Type::AnyChatsMask) {
|
||||||
_steps.push_back(Step::DialogsList);
|
_steps.push_back(Step::DialogsList);
|
||||||
}
|
}
|
||||||
|
@ -265,9 +251,6 @@ void Controller::fillExportSteps() {
|
||||||
if (_settings.types & Type::AnyChatsMask) {
|
if (_settings.types & Type::AnyChatsMask) {
|
||||||
_steps.push_back(Step::Dialogs);
|
_steps.push_back(Step::Dialogs);
|
||||||
}
|
}
|
||||||
if (_settings.types & Type::GroupsChannelsMask) {
|
|
||||||
_steps.push_back(Step::LeftChannels);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
|
void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
|
||||||
|
@ -280,9 +263,6 @@ void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
|
||||||
result[index] = count;
|
result[index] = count;
|
||||||
};
|
};
|
||||||
push(Step::Initializing, 1);
|
push(Step::Initializing, 1);
|
||||||
if (_settings.types & Settings::Type::GroupsChannelsMask) {
|
|
||||||
push(Step::LeftChannelsList, 1);
|
|
||||||
}
|
|
||||||
if (_settings.types & Settings::Type::AnyChatsMask) {
|
if (_settings.types & Settings::Type::AnyChatsMask) {
|
||||||
push(Step::DialogsList, 1);
|
push(Step::DialogsList, 1);
|
||||||
}
|
}
|
||||||
|
@ -301,9 +281,6 @@ void Controller::fillSubstepsInSteps(const ApiWrap::StartInfo &info) {
|
||||||
if (_settings.types & Settings::Type::OtherData) {
|
if (_settings.types & Settings::Type::OtherData) {
|
||||||
push(Step::OtherData, 1);
|
push(Step::OtherData, 1);
|
||||||
}
|
}
|
||||||
if (_settings.types & Settings::Type::GroupsChannelsMask) {
|
|
||||||
push(Step::LeftChannels, info.leftChannelsCount);
|
|
||||||
}
|
|
||||||
if (_settings.types & Settings::Type::AnyChatsMask) {
|
if (_settings.types & Settings::Type::AnyChatsMask) {
|
||||||
push(Step::Dialogs, info.dialogsCount);
|
push(Step::Dialogs, info.dialogsCount);
|
||||||
}
|
}
|
||||||
|
@ -330,14 +307,12 @@ void Controller::exportNext() {
|
||||||
const auto step = _steps[_stepIndex];
|
const auto step = _steps[_stepIndex];
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case Step::Initializing: return initialize();
|
case Step::Initializing: return initialize();
|
||||||
case Step::LeftChannelsList: return collectLeftChannels();
|
|
||||||
case Step::DialogsList: return collectDialogsList();
|
case Step::DialogsList: return collectDialogsList();
|
||||||
case Step::PersonalInfo: return exportPersonalInfo();
|
case Step::PersonalInfo: return exportPersonalInfo();
|
||||||
case Step::Userpics: return exportUserpics();
|
case Step::Userpics: return exportUserpics();
|
||||||
case Step::Contacts: return exportContacts();
|
case Step::Contacts: return exportContacts();
|
||||||
case Step::Sessions: return exportSessions();
|
case Step::Sessions: return exportSessions();
|
||||||
case Step::OtherData: return exportOtherData();
|
case Step::OtherData: return exportOtherData();
|
||||||
case Step::LeftChannels: return exportLeftChannels();
|
|
||||||
case Step::Dialogs: return exportDialogs();
|
case Step::Dialogs: return exportDialogs();
|
||||||
}
|
}
|
||||||
Unexpected("Step in Controller::exportNext.");
|
Unexpected("Step in Controller::exportNext.");
|
||||||
|
@ -358,17 +333,6 @@ void Controller::initialized(const ApiWrap::StartInfo &info) {
|
||||||
exportNext();
|
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() {
|
void Controller::collectDialogsList() {
|
||||||
setState(stateDialogsList(0));
|
setState(stateDialogsList(0));
|
||||||
_api.requestDialogsList([=](int count) {
|
_api.requestDialogsList([=](int count) {
|
||||||
|
@ -457,9 +421,9 @@ void Controller::exportDialogs() {
|
||||||
|
|
||||||
void Controller::exportNextDialog() {
|
void Controller::exportNextDialog() {
|
||||||
const auto index = ++_dialogIndex;
|
const auto index = ++_dialogIndex;
|
||||||
if (index < _dialogsInfo.list.size()) {
|
const auto info = _dialogsInfo.item(index);
|
||||||
const auto &info = _dialogsInfo.list[index];
|
if (info) {
|
||||||
_api.requestMessages(info, [=](const Data::DialogInfo &info) {
|
_api.requestMessages(*info, [=](const Data::DialogInfo &info) {
|
||||||
if (ioCatchError(_writer->writeDialogStart(info))) {
|
if (ioCatchError(_writer->writeDialogStart(info))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -493,52 +457,6 @@ void Controller::exportNextDialog() {
|
||||||
exportNext();
|
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>
|
template <typename Callback>
|
||||||
ProcessingState Controller::prepareState(
|
ProcessingState Controller::prepareState(
|
||||||
Step step,
|
Step step,
|
||||||
|
@ -561,22 +479,11 @@ ProcessingState Controller::stateInitializing() const {
|
||||||
return ProcessingState();
|
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 {
|
ProcessingState Controller::stateDialogsList(int processed) const {
|
||||||
const auto step = Step::DialogsList;
|
const auto step = Step::DialogsList;
|
||||||
return prepareState(step, [&](ProcessingState &result) {
|
return prepareState(step, [&](ProcessingState &result) {
|
||||||
result.entityIndex = substepsInStep(Step::LeftChannels) + processed;
|
result.entityIndex = processed;
|
||||||
result.entityCount = substepsInStep(Step::LeftChannels) + std::max(
|
result.entityCount = std::max(
|
||||||
processed,
|
processed,
|
||||||
substepsInStep(Step::Dialogs));
|
substepsInStep(Step::Dialogs));
|
||||||
});
|
});
|
||||||
|
@ -612,35 +519,15 @@ ProcessingState Controller::stateOtherData() const {
|
||||||
return prepareState(Step::OtherData);
|
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(
|
ProcessingState Controller::stateDialogs(
|
||||||
const DownloadProgress &progress) const {
|
const DownloadProgress &progress) const {
|
||||||
const auto step = Step::Dialogs;
|
const auto step = Step::Dialogs;
|
||||||
return prepareState(step, [&](ProcessingState &result) {
|
return prepareState(step, [&](ProcessingState &result) {
|
||||||
const auto addIndex = 0;
|
|
||||||
const auto addCount = _leftChannelsInfo.list.size();
|
|
||||||
fillMessagesState(
|
fillMessagesState(
|
||||||
result,
|
result,
|
||||||
_dialogsInfo,
|
_dialogsInfo,
|
||||||
_dialogIndex,
|
_dialogIndex,
|
||||||
progress,
|
progress);
|
||||||
addIndex,
|
|
||||||
addCount);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,14 +535,14 @@ void Controller::fillMessagesState(
|
||||||
ProcessingState &result,
|
ProcessingState &result,
|
||||||
const Data::DialogsInfo &info,
|
const Data::DialogsInfo &info,
|
||||||
int index,
|
int index,
|
||||||
const DownloadProgress &progress,
|
const DownloadProgress &progress) const {
|
||||||
int addIndex,
|
const auto dialog = info.item(index);
|
||||||
int addCount) const {
|
Assert(dialog != nullptr);
|
||||||
const auto &dialog = info.list[index];
|
|
||||||
result.entityIndex = index + addIndex;
|
result.entityIndex = index;
|
||||||
result.entityCount = info.list.size() + addCount;
|
result.entityCount = info.chats.size() + info.left.size();
|
||||||
result.entityName = dialog.name;
|
result.entityName = dialog->name;
|
||||||
result.entityType = (dialog.type == Data::DialogInfo::Type::Self)
|
result.entityType = (dialog->type == Data::DialogInfo::Type::Self)
|
||||||
? ProcessingState::EntityType::SavedMessages
|
? ProcessingState::EntityType::SavedMessages
|
||||||
: ProcessingState::EntityType::Chat;
|
: ProcessingState::EntityType::Chat;
|
||||||
result.itemIndex = _messagesWritten + progress.itemIndex;
|
result.itemIndex = _messagesWritten + progress.itemIndex;
|
||||||
|
|
|
@ -28,14 +28,12 @@ struct PasswordCheckState {
|
||||||
struct ProcessingState {
|
struct ProcessingState {
|
||||||
enum class Step {
|
enum class Step {
|
||||||
Initializing,
|
Initializing,
|
||||||
LeftChannelsList,
|
|
||||||
DialogsList,
|
DialogsList,
|
||||||
PersonalInfo,
|
PersonalInfo,
|
||||||
Userpics,
|
Userpics,
|
||||||
Contacts,
|
Contacts,
|
||||||
Sessions,
|
Sessions,
|
||||||
OtherData,
|
OtherData,
|
||||||
LeftChannels,
|
|
||||||
Dialogs,
|
Dialogs,
|
||||||
};
|
};
|
||||||
enum class FileType {
|
enum class FileType {
|
||||||
|
|
|
@ -467,8 +467,8 @@ Stats AbstractWriter::produceTestExample(
|
||||||
dialogChat.splits.push_back(1);
|
dialogChat.splits.push_back(1);
|
||||||
dialogChat.topMessageDate = sliceChat2.list.back().date;
|
dialogChat.topMessageDate = sliceChat2.list.back().date;
|
||||||
dialogChat.topMessageId = sliceChat2.list.back().id;
|
dialogChat.topMessageId = sliceChat2.list.back().id;
|
||||||
dialogs.list.push_back(dialogBot);
|
dialogs.chats.push_back(dialogBot);
|
||||||
dialogs.list.push_back(dialogChat);
|
dialogs.chats.push_back(dialogChat);
|
||||||
|
|
||||||
check(writeDialogsStart(dialogs));
|
check(writeDialogsStart(dialogs));
|
||||||
check(writeDialogStart(dialogBot));
|
check(writeDialogStart(dialogBot));
|
||||||
|
@ -481,9 +481,6 @@ Stats AbstractWriter::produceTestExample(
|
||||||
check(writeDialogEnd());
|
check(writeDialogEnd());
|
||||||
check(writeDialogsEnd());
|
check(writeDialogsEnd());
|
||||||
|
|
||||||
check(writeLeftChannelsStart(Data::DialogsInfo()));
|
|
||||||
check(writeLeftChannelsEnd());
|
|
||||||
|
|
||||||
check(finish());
|
check(finish());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -75,15 +75,6 @@ public:
|
||||||
[[nodiscard]] virtual Result writeDialogEnd() = 0;
|
[[nodiscard]] virtual Result writeDialogEnd() = 0;
|
||||||
[[nodiscard]] virtual Result writeDialogsEnd() = 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 Result finish() = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual QString mainFilePath() = 0;
|
[[nodiscard]] virtual QString mainFilePath() = 0;
|
||||||
|
|
|
@ -1755,7 +1755,6 @@ Result HtmlWriter::start(
|
||||||
"images/section_chats.png",
|
"images/section_chats.png",
|
||||||
"images/section_contacts.png",
|
"images/section_contacts.png",
|
||||||
"images/section_frequent.png",
|
"images/section_frequent.png",
|
||||||
"images/section_leftchats.png",
|
|
||||||
"images/section_other.png",
|
"images/section_other.png",
|
||||||
"images/section_photos.png",
|
"images/section_photos.png",
|
||||||
"images/section_sessions.png",
|
"images/section_sessions.png",
|
||||||
|
@ -1874,7 +1873,7 @@ Result HtmlWriter::writeUserpicsStart(const Data::UserpicsInfo &data) {
|
||||||
_userpics = fileWithRelativePath(userpicsFilePath());
|
_userpics = fileWithRelativePath(userpicsFilePath());
|
||||||
|
|
||||||
auto block = _userpics->pushHeader(
|
auto block = _userpics->pushHeader(
|
||||||
"Personal photos",
|
"Profile pictures",
|
||||||
mainFileRelativePath());
|
mainFileRelativePath());
|
||||||
block.append(_userpics->pushDiv("page_body list_page"));
|
block.append(_userpics->pushDiv("page_body list_page"));
|
||||||
block.append(_userpics->pushDiv("entry_list"));
|
block.append(_userpics->pushDiv("entry_list"));
|
||||||
|
@ -2198,98 +2197,36 @@ Result HtmlWriter::writeOtherData(const Data::File &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HtmlWriter::writeDialogsStart(const Data::DialogsInfo &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(_summary != nullptr);
|
||||||
Expects(_chats == nullptr);
|
Expects(_chats == nullptr);
|
||||||
|
|
||||||
if (data.list.empty()) {
|
if (data.chats.empty() && data.left.empty()) {
|
||||||
return Result::Success();
|
return Result::Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
_dialogsRelativePath = fileName;
|
_dialogsRelativePath = "lists/chats.html";
|
||||||
_chats = fileWithRelativePath(fileName);
|
_chats = fileWithRelativePath(_dialogsRelativePath);
|
||||||
_dialogIndex = 0;
|
|
||||||
_dialogsCount = data.list.size();
|
|
||||||
|
|
||||||
auto block = _chats->pushHeader(
|
auto block = _chats->pushHeader(
|
||||||
listName,
|
"Chats",
|
||||||
mainFileRelativePath());
|
mainFileRelativePath());
|
||||||
block.append(_chats->pushDiv("page_body list_page"));
|
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) {
|
if (const auto result = _chats->writeBlock(block); !result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pushSection(
|
pushSection(
|
||||||
0,
|
0,
|
||||||
listName,
|
"Chats",
|
||||||
buttonClass,
|
"chats",
|
||||||
data.list.size(),
|
data.chats.size() + data.left.size(),
|
||||||
fileName);
|
"lists/chats.html");
|
||||||
return writeSections();
|
return writeSections();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HtmlWriter::writeChatStart(const Data::DialogInfo &data) {
|
Result HtmlWriter::writeDialogStart(const Data::DialogInfo &data) {
|
||||||
Expects(_chat == nullptr);
|
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));
|
_chat = fileWithRelativePath(data.relativePath + messagesFile(0));
|
||||||
_chatFileEmpty = true;
|
_chatFileEmpty = true;
|
||||||
_messagesCount = 0;
|
_messagesCount = 0;
|
||||||
|
@ -2299,29 +2236,7 @@ Result HtmlWriter::writeChatStart(const Data::DialogInfo &data) {
|
||||||
return Result::Success();
|
return Result::Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HtmlWriter::writeChatOpening(int index) {
|
Result HtmlWriter::writeDialogSlice(const Data::MessagesSlice &data) {
|
||||||
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) {
|
|
||||||
Expects(_chat != nullptr);
|
Expects(_chat != nullptr);
|
||||||
Expects(!data.list.empty());
|
Expects(!data.list.empty());
|
||||||
|
|
||||||
|
@ -2331,7 +2246,7 @@ Result HtmlWriter::writeChatSlice(const Data::MessagesSlice &data) {
|
||||||
auto block = QByteArray();
|
auto block = QByteArray();
|
||||||
for (const auto &message : data.list) {
|
for (const auto &message : data.list) {
|
||||||
if (_chatFileEmpty) {
|
if (_chatFileEmpty) {
|
||||||
if (const auto result = writeChatOpening(oldIndex); !result) {
|
if (const auto result = writeDialogOpening(oldIndex); !result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
_chatFileEmpty = false;
|
_chatFileEmpty = false;
|
||||||
|
@ -2378,7 +2293,7 @@ Result HtmlWriter::writeChatSlice(const Data::MessagesSlice &data) {
|
||||||
return _chat->writeBlock(block);
|
return _chat->writeBlock(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HtmlWriter::writeChatEnd() {
|
Result HtmlWriter::writeDialogEnd() {
|
||||||
Expects(_chats != nullptr);
|
Expects(_chats != nullptr);
|
||||||
Expects(_chat != nullptr);
|
Expects(_chat != nullptr);
|
||||||
|
|
||||||
|
@ -2446,6 +2361,12 @@ Result HtmlWriter::writeChatEnd() {
|
||||||
};
|
};
|
||||||
userpic.firstName = NameString(_dialog);
|
userpic.firstName = NameString(_dialog);
|
||||||
userpic.lastName = LastNameString(_dialog);
|
userpic.lastName = LastNameString(_dialog);
|
||||||
|
|
||||||
|
const auto result = validateDialogsMode(_dialog.isLeftChannel);
|
||||||
|
if (!result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return _chats->writeBlock(_chats->pushListEntry(
|
return _chats->writeBlock(_chats->pushListEntry(
|
||||||
userpic,
|
userpic,
|
||||||
ComposeName(userpic, DeletedString(_dialog.type)),
|
ComposeName(userpic, DeletedString(_dialog.type)),
|
||||||
|
@ -2456,13 +2377,55 @@ Result HtmlWriter::writeChatEnd() {
|
||||||
: QString())));
|
: 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) {
|
if (_chats) {
|
||||||
return base::take(_chats)->close();
|
return base::take(_chats)->close();
|
||||||
}
|
}
|
||||||
return Result::Success();
|
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(
|
void HtmlWriter::pushSection(
|
||||||
int priority,
|
int priority,
|
||||||
const QByteArray &label,
|
const QByteArray &label,
|
||||||
|
@ -2513,7 +2476,7 @@ Result HtmlWriter::switchToNextChatFile(int index) {
|
||||||
{ "class", "pagination block_link" },
|
{ "class", "pagination block_link" },
|
||||||
{ "href", nextPath.toUtf8() }
|
{ "href", nextPath.toUtf8() }
|
||||||
});
|
});
|
||||||
next.append("Next messages part");
|
next.append("Next messages");
|
||||||
next.append(_chat->popTag());
|
next.append(_chat->popTag());
|
||||||
if (const auto result = _chat->writeBlock(next); !result) {
|
if (const auto result = _chat->writeBlock(next); !result) {
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -71,12 +71,6 @@ public:
|
||||||
Result writeDialogEnd() override;
|
Result writeDialogEnd() override;
|
||||||
Result writeDialogsEnd() 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;
|
Result finish() override;
|
||||||
|
|
||||||
QString mainFilePath() override;
|
QString mainFilePath() override;
|
||||||
|
@ -89,15 +83,21 @@ private:
|
||||||
using MediaData = details::MediaData;
|
using MediaData = details::MediaData;
|
||||||
class Wrap;
|
class Wrap;
|
||||||
struct MessageInfo;
|
struct MessageInfo;
|
||||||
|
enum class DialogsMode {
|
||||||
|
None,
|
||||||
|
Chats,
|
||||||
|
Left,
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] Result copyFile(
|
[[nodiscard]] Result copyFile(
|
||||||
const QString &source,
|
const QString &source,
|
||||||
const QString &relativePath) const;
|
const QString &relativePath) const;
|
||||||
|
|
||||||
QString mainFileRelativePath() const;
|
[[nodiscard]] QString mainFileRelativePath() const;
|
||||||
QString pathWithRelativePath(const QString &path) const;
|
[[nodiscard]] QString pathWithRelativePath(const QString &path) const;
|
||||||
std::unique_ptr<Wrap> fileWithRelativePath(const QString &path) const;
|
[[nodiscard]] std::unique_ptr<Wrap> fileWithRelativePath(
|
||||||
QString messagesFile(int index) const;
|
const QString &path) const;
|
||||||
|
[[nodiscard]] QString messagesFile(int index) const;
|
||||||
|
|
||||||
[[nodiscard]] Result writeSavedContacts(const Data::ContactsList &data);
|
[[nodiscard]] Result writeSavedContacts(const Data::ContactsList &data);
|
||||||
[[nodiscard]] Result writeFrequentContacts(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 writeSessions(const Data::SessionsList &data);
|
||||||
[[nodiscard]] Result writeWebSessions(const Data::SessionsList &data);
|
[[nodiscard]] Result writeWebSessions(const Data::SessionsList &data);
|
||||||
|
|
||||||
[[nodiscard]] Result writeChatsStart(
|
[[nodiscard]] Result validateDialogsMode(bool isLeftChannel);
|
||||||
const Data::DialogsInfo &data,
|
[[nodiscard]] Result writeDialogOpening(int index);
|
||||||
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 switchToNextChatFile(int index);
|
[[nodiscard]] Result switchToNextChatFile(int index);
|
||||||
|
|
||||||
void pushSection(
|
void pushSection(
|
||||||
|
@ -153,10 +144,9 @@ private:
|
||||||
int _userpicsCount = 0;
|
int _userpicsCount = 0;
|
||||||
std::unique_ptr<Wrap> _userpics;
|
std::unique_ptr<Wrap> _userpics;
|
||||||
|
|
||||||
int _dialogsCount = 0;
|
|
||||||
int _dialogIndex = 0;
|
|
||||||
QString _dialogsRelativePath;
|
QString _dialogsRelativePath;
|
||||||
Data::DialogInfo _dialog;
|
Data::DialogInfo _dialog;
|
||||||
|
DialogsMode _dialogsMode = DialogsMode::None;
|
||||||
|
|
||||||
int _messagesCount = 0;
|
int _messagesCount = 0;
|
||||||
std::unique_ptr<MessageInfo> _lastMessageInfo;
|
std::unique_ptr<MessageInfo> _lastMessageInfo;
|
||||||
|
|
|
@ -593,7 +593,10 @@ Result JsonWriter::start(
|
||||||
_stats = stats;
|
_stats = stats;
|
||||||
_output = fileWithRelativePath(mainFileRelativePath());
|
_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) {
|
QByteArray JsonWriter::pushNesting(Context::Type type) {
|
||||||
|
@ -943,56 +946,16 @@ Result JsonWriter::writeWebSessions(const Data::SessionsList &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result JsonWriter::writeDialogsStart(const Data::DialogsInfo &data) {
|
Result JsonWriter::writeDialogsStart(const Data::DialogsInfo &data) {
|
||||||
return writeChatsStart(data, "chats");
|
return Result::Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result JsonWriter::writeDialogStart(const Data::DialogInfo &data) {
|
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);
|
Expects(_output != nullptr);
|
||||||
|
|
||||||
auto block = prepareObjectItemStart(listName);
|
const auto result = validateDialogsMode(data.isLeftChannel);
|
||||||
return _output->writeBlock(block + pushNesting(Context::kArray));
|
if (!result) {
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
Result JsonWriter::writeChatStart(const Data::DialogInfo &data) {
|
|
||||||
Expects(_output != nullptr);
|
|
||||||
|
|
||||||
using Type = Data::DialogInfo::Type;
|
using Type = Data::DialogInfo::Type;
|
||||||
const auto TypeString = [](Type type) {
|
const auto TypeString = [](Type type) {
|
||||||
|
@ -1023,7 +986,26 @@ Result JsonWriter::writeChatStart(const Data::DialogInfo &data) {
|
||||||
return _output->writeBlock(block);
|
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);
|
Expects(_output != nullptr);
|
||||||
|
|
||||||
auto block = QByteArray();
|
auto block = QByteArray();
|
||||||
|
@ -1037,17 +1019,35 @@ Result JsonWriter::writeChatSlice(const Data::MessagesSlice &data) {
|
||||||
return _output->writeBlock(block);
|
return _output->writeBlock(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result JsonWriter::writeChatEnd() {
|
Result JsonWriter::writeDialogEnd() {
|
||||||
Expects(_output != nullptr);
|
Expects(_output != nullptr);
|
||||||
|
|
||||||
auto block = popNesting();
|
auto block = popNesting();
|
||||||
return _output->writeBlock(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() {
|
Result JsonWriter::writeChatsEnd() {
|
||||||
Expects(_output != nullptr);
|
Expects(_output != nullptr);
|
||||||
|
|
||||||
return _output->writeBlock(popNesting());
|
auto block = popNesting();
|
||||||
|
return _output->writeBlock(block + popNesting());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result JsonWriter::finish() {
|
Result JsonWriter::finish() {
|
||||||
|
|
|
@ -56,41 +56,39 @@ public:
|
||||||
Result writeDialogEnd() override;
|
Result writeDialogEnd() override;
|
||||||
Result writeDialogsEnd() 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;
|
Result finish() override;
|
||||||
|
|
||||||
QString mainFilePath() override;
|
QString mainFilePath() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Context = details::JsonContext;
|
using Context = details::JsonContext;
|
||||||
|
enum class DialogsMode {
|
||||||
|
None,
|
||||||
|
Chats,
|
||||||
|
Left,
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] QByteArray pushNesting(Context::Type type);
|
[[nodiscard]] QByteArray pushNesting(Context::Type type);
|
||||||
[[nodiscard]] QByteArray prepareObjectItemStart(const QByteArray &key);
|
[[nodiscard]] QByteArray prepareObjectItemStart(const QByteArray &key);
|
||||||
[[nodiscard]] QByteArray prepareArrayItemStart();
|
[[nodiscard]] QByteArray prepareArrayItemStart();
|
||||||
[[nodiscard]] QByteArray popNesting();
|
[[nodiscard]] QByteArray popNesting();
|
||||||
|
|
||||||
QString mainFileRelativePath() const;
|
[[nodiscard]] QString mainFileRelativePath() const;
|
||||||
QString pathWithRelativePath(const QString &path) const;
|
[[nodiscard]] QString pathWithRelativePath(const QString &path) const;
|
||||||
std::unique_ptr<File> fileWithRelativePath(const QString &path) const;
|
[[nodiscard]] std::unique_ptr<File> fileWithRelativePath(
|
||||||
|
const QString &path) const;
|
||||||
|
|
||||||
Result writeSavedContacts(const Data::ContactsList &data);
|
[[nodiscard]] Result writeSavedContacts(const Data::ContactsList &data);
|
||||||
Result writeFrequentContacts(const Data::ContactsList &data);
|
[[nodiscard]] Result writeFrequentContacts(const Data::ContactsList &data);
|
||||||
|
|
||||||
Result writeSessions(const Data::SessionsList &data);
|
[[nodiscard]] Result writeSessions(const Data::SessionsList &data);
|
||||||
Result writeWebSessions(const Data::SessionsList &data);
|
[[nodiscard]] Result writeWebSessions(const Data::SessionsList &data);
|
||||||
|
|
||||||
Result writeChatsStart(
|
[[nodiscard]] Result validateDialogsMode(bool isLeftChannel);
|
||||||
const Data::DialogsInfo &data,
|
[[nodiscard]] Result writeChatsStart(
|
||||||
const QByteArray &listName);
|
const QByteArray &listName,
|
||||||
Result writeChatStart(const Data::DialogInfo &data);
|
const QByteArray &about);
|
||||||
Result writeChatSlice(const Data::MessagesSlice &data);
|
[[nodiscard]] Result writeChatsEnd();
|
||||||
Result writeChatEnd();
|
|
||||||
Result writeChatsEnd();
|
|
||||||
|
|
||||||
Settings _settings;
|
Settings _settings;
|
||||||
Environment _environment;
|
Environment _environment;
|
||||||
|
@ -98,6 +96,7 @@ private:
|
||||||
|
|
||||||
Context _context;
|
Context _context;
|
||||||
bool _currentNestingHadItem = false;
|
bool _currentNestingHadItem = false;
|
||||||
|
DialogsMode _dialogsMode = DialogsMode::None;
|
||||||
|
|
||||||
std::unique_ptr<File> _output;
|
std::unique_ptr<File> _output;
|
||||||
|
|
||||||
|
|
|
@ -786,95 +786,47 @@ Result TextWriter::writeOtherData(const Data::File &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TextWriter::writeDialogsStart(const Data::DialogsInfo &data) {
|
Result TextWriter::writeDialogsStart(const Data::DialogsInfo &data) {
|
||||||
return writeChatsStart(
|
_dialogsCount = data.chats.size();
|
||||||
data,
|
_leftChannelsCount = data.left.size();
|
||||||
"Chats",
|
return Result::Success();
|
||||||
_environment.aboutChats,
|
|
||||||
"lists/chats.txt");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TextWriter::writeDialogStart(const Data::DialogInfo &data) {
|
Result TextWriter::writeDialogStart(const Data::DialogInfo &data) {
|
||||||
return writeChatStart(data);
|
Expects(_chat == nullptr);
|
||||||
}
|
|
||||||
|
|
||||||
Result TextWriter::writeDialogSlice(const Data::MessagesSlice &data) {
|
const auto result = validateDialogsMode(data.isLeftChannel);
|
||||||
return writeChatSlice(data);
|
if (!result) {
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
return 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");
|
_chat = fileWithRelativePath(data.relativePath + "messages.txt");
|
||||||
_messagesCount = 0;
|
_messagesCount = 0;
|
||||||
_dialog = data;
|
_dialog = data;
|
||||||
return Result::Success();
|
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(_chat != nullptr);
|
||||||
Expects(!data.list.empty());
|
Expects(!data.list.empty());
|
||||||
|
|
||||||
|
@ -893,7 +845,7 @@ Result TextWriter::writeChatSlice(const Data::MessagesSlice &data) {
|
||||||
return _chat->writeBlock(full);
|
return _chat->writeBlock(full);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TextWriter::writeChatEnd() {
|
Result TextWriter::writeDialogEnd() {
|
||||||
Expects(_chats != nullptr);
|
Expects(_chats != nullptr);
|
||||||
Expects(_chat != 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() {
|
Result TextWriter::writeChatsEnd() {
|
||||||
_chats = nullptr;
|
_chats = nullptr;
|
||||||
return Result::Success();
|
return Result::Success();
|
||||||
|
|
|
@ -44,36 +44,35 @@ public:
|
||||||
Result writeDialogEnd() override;
|
Result writeDialogEnd() override;
|
||||||
Result writeDialogsEnd() 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;
|
Result finish() override;
|
||||||
|
|
||||||
QString mainFilePath() override;
|
QString mainFilePath() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString mainFileRelativePath() const;
|
enum class DialogsMode {
|
||||||
QString pathWithRelativePath(const QString &path) const;
|
None,
|
||||||
std::unique_ptr<File> fileWithRelativePath(const QString &path) const;
|
Chats,
|
||||||
|
Left,
|
||||||
|
};
|
||||||
|
|
||||||
Result writeSavedContacts(const Data::ContactsList &data);
|
[[nodiscard]] QString mainFileRelativePath() const;
|
||||||
Result writeFrequentContacts(const Data::ContactsList &data);
|
[[nodiscard]] QString pathWithRelativePath(const QString &path) const;
|
||||||
|
[[nodiscard]] std::unique_ptr<File> fileWithRelativePath(
|
||||||
|
const QString &path) const;
|
||||||
|
|
||||||
Result writeSessions(const Data::SessionsList &data);
|
[[nodiscard]] Result writeSavedContacts(const Data::ContactsList &data);
|
||||||
Result writeWebSessions(const Data::SessionsList &data);
|
[[nodiscard]] Result writeFrequentContacts(const Data::ContactsList &data);
|
||||||
|
|
||||||
Result writeChatsStart(
|
[[nodiscard]] Result writeSessions(const Data::SessionsList &data);
|
||||||
const Data::DialogsInfo &data,
|
[[nodiscard]] Result writeWebSessions(const Data::SessionsList &data);
|
||||||
|
|
||||||
|
[[nodiscard]] Result validateDialogsMode(bool isLeftChannel);
|
||||||
|
[[nodiscard]] Result writeChatsStart(
|
||||||
|
int count,
|
||||||
const QByteArray &listName,
|
const QByteArray &listName,
|
||||||
const QByteArray &about,
|
const QByteArray &about,
|
||||||
const QString &fileName);
|
const QString &fileName);
|
||||||
Result writeChatStart(const Data::DialogInfo &data);
|
[[nodiscard]] Result writeChatsEnd();
|
||||||
Result writeChatSlice(const Data::MessagesSlice &data);
|
|
||||||
Result writeChatEnd();
|
|
||||||
Result writeChatsEnd();
|
|
||||||
|
|
||||||
Settings _settings;
|
Settings _settings;
|
||||||
Environment _environment;
|
Environment _environment;
|
||||||
|
@ -85,8 +84,9 @@ private:
|
||||||
std::unique_ptr<File> _userpics;
|
std::unique_ptr<File> _userpics;
|
||||||
|
|
||||||
int _dialogsCount = 0;
|
int _dialogsCount = 0;
|
||||||
int _dialogIndex = 0;
|
int _leftChannelsCount = 0;
|
||||||
Data::DialogInfo _dialog;
|
Data::DialogInfo _dialog;
|
||||||
|
DialogsMode _dialogsMode = DialogsMode::None;
|
||||||
|
|
||||||
int _messagesCount = 0;
|
int _messagesCount = 0;
|
||||||
std::unique_ptr<File> _chats;
|
std::unique_ptr<File> _chats;
|
||||||
|
|
|
@ -61,7 +61,6 @@ Content ContentFromState(const ProcessingState &state) {
|
||||||
case Step::Initializing:
|
case Step::Initializing:
|
||||||
pushMain(lang(lng_export_state_initializing));
|
pushMain(lang(lng_export_state_initializing));
|
||||||
break;
|
break;
|
||||||
case Step::LeftChannelsList:
|
|
||||||
case Step::DialogsList:
|
case Step::DialogsList:
|
||||||
pushMain(lang(lng_export_state_chats_list));
|
pushMain(lang(lng_export_state_chats_list));
|
||||||
break;
|
break;
|
||||||
|
@ -83,7 +82,6 @@ Content ContentFromState(const ProcessingState &state) {
|
||||||
case Step::OtherData:
|
case Step::OtherData:
|
||||||
pushMain(lang(lng_export_option_other));
|
pushMain(lang(lng_export_option_other));
|
||||||
break;
|
break;
|
||||||
case Step::LeftChannels:
|
|
||||||
case Step::Dialogs:
|
case Step::Dialogs:
|
||||||
pushMain(lang(lng_export_state_chats));
|
pushMain(lang(lng_export_state_chats));
|
||||||
push(
|
push(
|
||||||
|
|
Loading…
Reference in New Issue