Add option to remove a downloaded font
This commit is contained in:
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user