Add option to remove a downloaded font

This commit is contained in:
jpirnay
2026-05-12 14:33:14 +02:00
parent 8d2cfb17a7
commit 693a650094
4 changed files with 101 additions and 8 deletions
+1
View File
@@ -100,6 +100,7 @@ STR_CREATE_FALLBACK_FOR_INVALID_TOC: "Create fallback for invalid TOC"
STR_ORIENTATION: "Reading Orientation"
STR_LONG_PRESS_SKIP: "Long-press Chapter Skip"
STR_FONT_FAMILY: "Reader Font Family"
STR_FONT_MANAGER: "Font Manager"
STR_FONT_DOWNLOAD: "Font Download"
STR_FONT_INSTALLED: "Font installed!"
STR_FONT_INSTALL_FAILED: "Font installation failed"
@@ -7,11 +7,13 @@
#include <Logging.h>
#include <WiFi.h>
#include <algorithm>
#include <cstring>
#include "MappedInputManager.h"
#include "SdCardFontGlobals.h"
#include "activities/network/WifiSelectionActivity.h"
#include "activities/util/ConfirmationActivity.h"
#include "components/UITheme.h"
#include "fontIds.h"
#include "network/HttpDownloader.h"
@@ -202,6 +204,8 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
LOG_ERR("FONT", "Failed to clean staging dir: %s", stagingDir);
RenderLock lock(*this);
state_ = ERROR;
pendingErrorAction_ = PendingFontAction::Download;
downloadingFamilyIndex_ = static_cast<int>(&family - families_.data());
errorMessage_ = "Failed to prepare staging area";
return;
}
@@ -210,6 +214,8 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
LOG_ERR("FONT", "Failed to create staging dir: %s", stagingDir);
RenderLock lock(*this);
state_ = ERROR;
pendingErrorAction_ = PendingFontAction::Download;
downloadingFamilyIndex_ = static_cast<int>(&family - families_.data());
errorMessage_ = "Failed to create staging area";
return;
}
@@ -254,6 +260,8 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
Storage.removeDir(stagingDir);
RenderLock lock(*this);
state_ = ERROR;
pendingErrorAction_ = PendingFontAction::Download;
downloadingFamilyIndex_ = static_cast<int>(&family - families_.data());
errorMessage_ = "Download failed: " + file.name;
return;
}
@@ -263,6 +271,8 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
Storage.removeDir(stagingDir);
RenderLock lock(*this);
state_ = ERROR;
pendingErrorAction_ = PendingFontAction::Download;
downloadingFamilyIndex_ = static_cast<int>(&family - families_.data());
errorMessage_ = "Invalid font file: " + file.name;
return;
}
@@ -275,6 +285,8 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
Storage.removeDir(stagingDir);
RenderLock lock(*this);
state_ = ERROR;
pendingErrorAction_ = PendingFontAction::Download;
downloadingFamilyIndex_ = static_cast<int>(&family - families_.data());
errorMessage_ = "Failed to prepare backup area";
return;
}
@@ -284,6 +296,8 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
Storage.removeDir(stagingDir);
RenderLock lock(*this);
state_ = ERROR;
pendingErrorAction_ = PendingFontAction::Download;
downloadingFamilyIndex_ = static_cast<int>(&family - families_.data());
errorMessage_ = "Failed to replace installed font";
return;
}
@@ -296,6 +310,8 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
Storage.removeDir(stagingDir);
RenderLock lock(*this);
state_ = ERROR;
pendingErrorAction_ = PendingFontAction::Download;
downloadingFamilyIndex_ = static_cast<int>(&family - families_.data());
errorMessage_ = "Failed to finalize font install";
return;
}
@@ -312,6 +328,61 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
state_ = COMPLETE;
}
void FontDownloadActivity::promptDeleteFamily(int familyIndex) {
if (familyIndex < 0 || familyIndex >= static_cast<int>(families_.size())) return;
const auto& family = families_[familyIndex];
const std::string heading = tr(STR_DELETE) + std::string("?");
const std::string body = family.name;
startActivityForResult(std::make_unique<ConfirmationActivity>(renderer, mappedInput, heading, body),
[this, familyIndex](const ActivityResult& result) {
if (result.isCancelled) return;
deleteFamilyAtIndex(familyIndex);
});
}
void FontDownloadActivity::deleteFamilyAtIndex(int familyIndex) {
if (familyIndex < 0 || familyIndex >= static_cast<int>(families_.size())) return;
auto& family = families_[familyIndex];
const auto result = fontInstaller_.deleteFamily(family.name.c_str());
if (result == FontInstaller::Error::OK) {
fontInstaller_.refreshRegistry();
family.installed = false;
family.hasUpdate = false;
pendingErrorAction_ = PendingFontAction::None;
errorMessage_.clear();
if (selectedIndex_ >= listItemCount()) {
selectedIndex_ = std::max(0, listItemCount() - 1);
}
RenderLock lock(*this);
state_ = FAMILY_LIST;
requestUpdate();
return;
}
std::string message = "Failed to delete font";
if (result == FontInstaller::Error::INVALID_FAMILY_NAME) {
message = "Invalid font family";
}
RenderLock lock(*this);
state_ = ERROR;
downloadingFamilyIndex_ = familyIndex;
pendingErrorAction_ = PendingFontAction::Delete;
errorMessage_ = message;
}
std::string FontDownloadActivity::confirmButtonLabel() const {
if (families_.empty()) return tr(STR_DOWNLOAD);
if (isDownloadAllSelected()) return tr(STR_DOWNLOAD);
const auto& family = families_[familyIndexFromList(selectedIndex_)];
if (family.installed && !family.hasUpdate) return tr(STR_DELETE);
if (family.hasUpdate) return tr(STR_UPDATE);
return tr(STR_DOWNLOAD);
}
// --- Input handling ---
void FontDownloadActivity::loop() {
@@ -339,13 +410,17 @@ void FontDownloadActivity::loop() {
if (!families_.empty()) {
if (isDownloadAllSelected()) {
downloadAll();
requestUpdateAndWait();
} else {
const auto& family = families_[familyIndexFromList(selectedIndex_)];
if (!family.installed || family.hasUpdate) {
downloadFamily(families_[familyIndexFromList(selectedIndex_)]);
const int familyIndex = familyIndexFromList(selectedIndex_);
const auto& family = families_[familyIndex];
if (family.installed && !family.hasUpdate) {
promptDeleteFamily(familyIndex);
} else {
downloadFamily(families_[familyIndex]);
requestUpdateAndWait();
}
}
requestUpdateAndWait();
}
}
} else if (state_ == COMPLETE) {
@@ -366,7 +441,11 @@ void FontDownloadActivity::loop() {
requestUpdate();
} else if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
if (downloadingFamilyIndex_ >= 0 && downloadingFamilyIndex_ < static_cast<int>(families_.size())) {
downloadFamily(families_[downloadingFamilyIndex_]);
if (pendingErrorAction_ == PendingFontAction::Delete) {
deleteFamilyAtIndex(downloadingFamilyIndex_);
} else {
downloadFamily(families_[downloadingFamilyIndex_]);
}
requestUpdateAndWait();
} else {
{
@@ -400,7 +479,7 @@ void FontDownloadActivity::render(RenderLock&&) {
renderer.clearScreen();
GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, tr(STR_FONT_DOWNLOAD));
GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, tr(STR_FONT_MANAGER));
const auto lineHeight = renderer.getLineHeight(UI_10_FONT_ID);
const auto contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing;
@@ -434,7 +513,8 @@ void FontDownloadActivity::render(RenderLock&&) {
},
true);
const auto labels = mappedInput.mapLabels(tr(STR_BACK), tr(STR_DOWNLOAD), tr(STR_DIR_UP), tr(STR_DIR_DOWN));
const std::string confirmLabel = confirmButtonLabel();
const auto labels = mappedInput.mapLabels(tr(STR_BACK), confirmLabel.c_str(), tr(STR_DIR_UP), tr(STR_DIR_DOWN));
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
}
} else if (state_ == DOWNLOADING) {
@@ -56,11 +56,18 @@ class FontDownloadActivity : public Activity {
std::vector<ManifestFamily> families_;
int selectedIndex_ = 0;
enum class PendingFontAction {
None,
Download,
Delete,
};
size_t currentFileIndex_ = 0;
size_t currentFileTotal_ = 0;
size_t fileProgress_ = 0;
size_t fileTotal_ = 0;
int downloadingFamilyIndex_ = 0;
PendingFontAction pendingErrorAction_ = PendingFontAction::None;
std::string errorMessage_;
void onWifiSelectionComplete(bool success);
@@ -71,5 +78,10 @@ class FontDownloadActivity : public Activity {
int familyIndexFromList(int listIndex) const { return listIndex - 1; }
int listItemCount() const { return families_.empty() ? 0 : static_cast<int>(families_.size()) + 1; }
size_t totalUninstalledSize() const;
std::string confirmButtonLabel() const;
void promptDeleteFamily(int familyIndex);
void deleteFamilyAtIndex(int familyIndex);
static std::string formatSize(size_t bytes);
};
+1 -1
View File
@@ -68,7 +68,7 @@ void SettingsActivity::onEnter() {
SettingInfo includeBetaUpdatesSetting{};
auto insertFontDownloadBelowFontSection = [&]() {
auto fontDownload = SettingInfo::Action(StrId::STR_FONT_DOWNLOAD, SettingAction::DownloadFonts);
auto fontDownload = SettingInfo::Action(StrId::STR_FONT_MANAGER, SettingAction::DownloadFonts);
fontDownload.withSubcategory(StrId::STR_MENU_READER_FONT);
addToMoved(readerSettings, lastReaderSub, std::move(fontDownload));
insertedFontDownload = true;