From fc8b958fb6d51555d72571bf3ba2c76d05086f03 Mon Sep 17 00:00:00 2001 From: Pixelplanet Date: Thu, 15 Oct 2026 14:50:52 +0200 Subject: [PATCH] Skip status node again (tiny-square artifact); remove head-locked download line; download shows size/%/ETA (folder pre-walk); bigger badge --- src/app/app.cpp | 7 ++-- src/gfx/vulkan_renderer.cpp | 16 +++++--- src/ui/browser.cpp | 73 ++++++++++++++++++++++++++++++------- 3 files changed, 73 insertions(+), 23 deletions(-) diff --git a/src/app/app.cpp b/src/app/app.cpp index f3f495c..011955d 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -533,10 +533,9 @@ int App::run() { downloadToast_ = nowT + std::chrono::seconds(10); } const bool dlRecent = browser_.downloadActive() || nowT < downloadToast_; - // Head-locked line only while a download is actually running; the - // completion is shown by the Downloads window / green button badge. - renderer_.setDownloadStatus(!browser_.isOpen() && browser_.downloadActive(), - browser_.downloadText()); + // No head-locked download text (it followed the view); progress lives + // in the Downloads window and the control-bar badge. + renderer_.setDownloadStatus(false, ""); renderer_.setDownloadsBadge(browser_.downloadActive(), !browser_.downloadActive() && browser_.hasDownloads() && dlRecent); diff --git a/src/gfx/vulkan_renderer.cpp b/src/gfx/vulkan_renderer.cpp index 48b6550..316a84f 100644 --- a/src/gfx/vulkan_renderer.cpp +++ b/src/gfx/vulkan_renderer.cpp @@ -1579,16 +1579,16 @@ void VulkanRenderer::renderView(uint32_t viewIndex, uint32_t imageIndex, const float badgeY = kBarY + kBtnHalfH * 0.55f; if (downloadsAllDone_) { const float tickBg[4] = {0.10f, 0.65f, 0.25f, 1.0f}; - drawUiElement(vpPanel, badgeX, badgeY, kBtnHalfH * 0.36f, - kBtnHalfH * 0.36f, UiShape::RoundedBox, tickBg, + drawUiElement(vpPanel, badgeX, badgeY, kBtnHalfH * 0.62f, + kBtnHalfH * 0.62f, UiShape::RoundedBox, tickBg, 0.50f, 0.0f, nullptr); - drawUiElement(vpPanel, badgeX, badgeY, kBtnHalfH * 0.24f, - kBtnHalfH * 0.24f, UiShape::Checkmark, + drawUiElement(vpPanel, badgeX, badgeY, kBtnHalfH * 0.44f, + kBtnHalfH * 0.44f, UiShape::Checkmark, iconCol); } else { const float dotCol[4] = {0.30f, 0.75f, 1.0f, 1.0f}; - drawUiElement(vpPanel, badgeX, badgeY, kBtnHalfH * 0.22f, - kBtnHalfH * 0.22f, UiShape::Cursor, dotCol); + drawUiElement(vpPanel, badgeX, badgeY, kBtnHalfH * 0.34f, + kBtnHalfH * 0.34f, UiShape::Cursor, dotCol); } } } @@ -1956,6 +1956,10 @@ void VulkanRenderer::renderView(uint32_t viewIndex, uint32_t imageIndex, !modelNodeStates_.empty() && !modelNodeStates_[0].name.empty(); for (std::size_t si = 0; si < modelSubmeshes_.size(); ++si) { const ModelSubmesh& sm = modelSubmeshes_[si]; + // The 'status' display node maps the whole atlas to a tiny + // quad (the runtime normally textures it); skip it so it does + // not render as a tiny sheet of labels on the body. + if (sm.nodeName == "status") continue; const float* np = identityPos; const float* nq = identityQuat; if (haveNames) { diff --git a/src/ui/browser.cpp b/src/ui/browser.cpp index 4231cec..c618238 100644 --- a/src/ui/browser.cpp +++ b/src/ui/browser.cpp @@ -499,6 +499,48 @@ void Browser::startDownloadFolder(const std::string& uri, long long got = 0; long long count = 0; bool ok = true; + // Pre-walk the tree to total the size, so % progress and ETA can be shown. + long long total = 0; + std::function sumSizes = + [&](const std::string& src) { + int d = -1; + { + std::lock_guard smb(smbGlobalLock()); + d = smbc_opendir(src.c_str()); + } + if (d < 0) return; + for (;;) { + std::string nm; + int typ = 0; + { + std::lock_guard smb(smbGlobalLock()); + struct smbc_dirent* de = smbc_readdir(d); + if (de == nullptr) break; + nm = de->name; + typ = de->smbc_type; + } + if (nm.empty() || nm == "." || nm == "..") continue; + std::string s = src; + if (!s.empty() && s.back() != '/') s += '/'; + s += nm; + if (typ == SMBC_DIR) { + sumSizes(s); + } else { + struct stat st{}; + { + std::lock_guard smb(smbGlobalLock()); + smbc_stat(s.c_str(), &st); + } + total += static_cast(st.st_size); + } + } + { + std::lock_guard smb(smbGlobalLock()); + smbc_closedir(d); + } + }; + sumSizes(uri); + dlTotal_.store(total); // Depth-first copy of an SMB folder. Recomputes a running byte total so // the overlay can show progress as files complete. std::function copyDir; @@ -551,20 +593,21 @@ void Browser::startDownloadFolder(const std::string& uri, return; } for (;;) { - struct smbc_dirent* de = nullptr; + std::string nm; + int typ = 0; { std::lock_guard smb(smbGlobalLock()); - de = smbc_readdir(d); + struct smbc_dirent* de = smbc_readdir(d); + if (de == nullptr) break; + nm = de->name; + typ = de->smbc_type; } - if (de == nullptr) break; - const std::string nm = de->name; if (nm.empty() || nm == "." || nm == "..") continue; std::string s = src; if (!s.empty() && s.back() != '/') s += '/'; s += nm; const std::string t = dst + "/" + nm; - const bool isDirEnt = (de->smbc_type == SMBC_DIR); - if (isDirEnt) { + if (typ == SMBC_DIR) { copyDir(s, t); } else { copyFile(s, t); @@ -640,11 +683,16 @@ std::string Browser::downloadText() const { const long long b = dlBytes_.load(); const long long t = dlTotal_.load(); std::string n = dlName_; - if (n.size() > 26) n = n.substr(0, 25) + "~"; - std::string s = "Downloading " + n + " "; - char buf[128]; + if (n.size() > 24) n = n.substr(0, 23) + "~"; + std::string s = n + " "; + char buf[160]; + const double mb = static_cast(b) / (1024.0 * 1024.0); if (t > 0) { - std::snprintf(buf, sizeof(buf), "%lld%%", b * 100 / t); + std::snprintf(buf, sizeof(buf), "%lld%% %.0f/%.0f MB", b * 100 / t, mb, + static_cast(t) / (1024.0 * 1024.0)); + s += buf; + } else { + std::snprintf(buf, sizeof(buf), "%.0f MB", mb); s += buf; } if (dlSpeed_ > 1.0) { @@ -652,11 +700,10 @@ std::string Browser::downloadText() const { dlSpeed_ / (1024.0 * 1024.0)); s += buf; if (t > 0) { - double eta = (t - b) / dlSpeed_; + double eta = static_cast(t - b) / dlSpeed_; if (eta < 0.0) eta = 0.0; const int secs = static_cast(eta); - std::snprintf(buf, sizeof(buf), " ETA %d:%02d", secs / 60, - secs % 60); + std::snprintf(buf, sizeof(buf), " ETA %d:%02d", secs / 60, secs % 60); s += buf; } }