implement progress visual to index unzip

This commit is contained in:
altalk23 2024-02-24 22:08:07 +03:00
parent b082dd1a9c
commit baf3a6b306
4 changed files with 69 additions and 4 deletions

View file

@ -154,6 +154,16 @@ namespace geode::utils::file {
*/ */
static Result<Unzip> create(ByteVector const& data); static Result<Unzip> create(ByteVector const& data);
/**
* Set a callback to be called with the progress of the unzip operation, first
* argument is the current entry, second argument is the total entries
* @note This is not thread-safe
* @param callback Callback to call with the progress of the unzip operation
*/
void setProgressCallback(
utils::MiniFunction<void(uint32_t, uint32_t)> callback
);
/** /**
* Path to the opened zip * Path to the opened zip
* @returns The path to the zip that is being read, or an empty path * @returns The path to the zip that is being read, or an empty path
@ -200,6 +210,13 @@ namespace geode::utils::file {
Path const& to, Path const& to,
bool deleteZipAfter = false bool deleteZipAfter = false
); );
static Result<> intoDir(
utils::MiniFunction<void(uint32_t, uint32_t)> progressCallback,
Path const& from,
Path const& to,
bool deleteZipAfter = false
);
}; };
/** /**

View file

@ -337,9 +337,20 @@ void Index::Impl::downloadIndex(std::string commitHash) {
// unzip new index // unzip new index
log::debug("Unzipping index"); log::debug("Unzipping index");
IndexUpdateEvent(UpdateProgress(100, "Unzipping index")).post(); uint32_t nextPercent = 1;
auto unzip = file::Unzip::intoDir(targetFile, targetDir, true) auto unzip = file::Unzip::intoDir(
.expect("Unable to unzip new index"); [&](uint32_t current, uint32_t total) {
if (total == 0) return;
if (static_cast<float>(current) / total * 100 >= nextPercent) {
Loader::get()->queueInMainThread([nextPercent]() {
IndexUpdateEvent(UpdateProgress(nextPercent, "Extracting")).post();
});
nextPercent++;
}
},
targetFile, targetDir, true
).expect("Unable to unzip new index");
if (!unzip) { if (!unzip) {
auto const err = unzip.unwrapErr(); auto const err = unzip.unwrapErr();
log::error("Failed to unzip latest index: {}", err); log::error("Failed to unzip latest index: {}", err);

View file

@ -628,7 +628,7 @@ void ModListLayer::onIndexUpdate(IndexUpdateEvent* event) {
[&](UpdateProgress const& prog) { [&](UpdateProgress const& prog) {
auto msg = prog.second; auto msg = prog.second;
// amazing // amazing
if (prog.second == "Downloading") { if (prog.second == "Downloading" || prog.second == "Extracting") {
msg += fmt::format(" {}%", prog.first); msg += fmt::format(" {}%", prog.first);
} }
m_listLabel->setString((msg + "...").c_str()); m_listLabel->setString((msg + "...").c_str());

View file

@ -170,6 +170,7 @@ private:
int32_t m_mode; int32_t m_mode;
std::variant<Path, ByteVector> m_srcDest; std::variant<Path, ByteVector> m_srcDest;
std::unordered_map<Path, ZipEntry> m_entries; std::unordered_map<Path, ZipEntry> m_entries;
utils::MiniFunction<void(uint32_t, uint32_t)> m_progressCallback;
Result<> init() { Result<> init() {
// open stream from file // open stream from file
@ -281,6 +282,10 @@ public:
return Ok(std::move(ret)); return Ok(std::move(ret));
} }
void setProgressCallback(utils::MiniFunction<void(uint32_t, uint32_t)> callback) {
m_progressCallback = callback;
}
Result<> extractAt(Path const& dir, Path const& name) { Result<> extractAt(Path const& dir, Path const& name) {
auto entry = m_entries.at(name); auto entry = m_entries.at(name);
@ -318,12 +323,21 @@ public:
.expect("Unable to navigate to first entry (code {error})") .expect("Unable to navigate to first entry (code {error})")
); );
uint64_t numEntries;
GEODE_UNWRAP(
mzTry(mz_zip_get_number_entry(m_handle, &numEntries))
.expect("Unable to get number of entries (code {error})")
);
uint32_t currentEntry = 0;
// while not at MZ_END_OF_LIST // while not at MZ_END_OF_LIST
do { do {
mz_zip_file* info = nullptr; mz_zip_file* info = nullptr;
if (mz_zip_entry_get_info(m_handle, &info) != MZ_OK) { if (mz_zip_entry_get_info(m_handle, &info) != MZ_OK) {
return Err("Unable to get entry info"); return Err("Unable to get entry info");
} }
currentEntry++;
Path filePath; Path filePath;
filePath.assign(info->filename, info->filename + info->filename_size); filePath.assign(info->filename, info->filename + info->filename_size);
@ -341,6 +355,7 @@ public:
else { else {
GEODE_UNWRAP(this->extractAt(dir, filePath)); GEODE_UNWRAP(this->extractAt(dir, filePath));
} }
m_progressCallback(currentEntry, numEntries);
} }
else { else {
log::error( log::error(
@ -505,6 +520,12 @@ Unzip::Path Unzip::getPath() const {
return m_impl->getPath(); return m_impl->getPath();
} }
void Unzip::setProgressCallback(
utils::MiniFunction<void(uint32_t, uint32_t)> callback
) {
return m_impl->setProgressCallback(callback);
}
std::vector<Unzip::Path> Unzip::getEntries() const { std::vector<Unzip::Path> Unzip::getEntries() const {
return map::keys(m_impl->getEntries()); return map::keys(m_impl->getEntries());
} }
@ -550,6 +571,22 @@ Result<> Unzip::intoDir(
return Ok(); return Ok();
} }
Result<> Unzip::intoDir(
utils::MiniFunction<void(uint32_t, uint32_t)> progressCallback,
Path const& from,
Path const& to,
bool deleteZipAfter
) {
GEODE_UNWRAP_INTO(auto unzip, Unzip::create(from));
unzip.setProgressCallback(progressCallback);
GEODE_UNWRAP(unzip.extractAllTo(to));
if (deleteZipAfter) {
std::error_code ec;
ghc::filesystem::remove(from, ec);
}
return Ok();
}
// Zip // Zip
Zip::Zip() : m_impl(nullptr) {} Zip::Zip() : m_impl(nullptr) {}