feat: separate into "Download All" and "Update All" in font manager (#1955)

## Summary

* **What is the goal of this PR?**  
Separate the font manager's combined `Download / Update All` action into
separate `Download All` and `Update All` rows

* **What changes are included?**  
- Updated multiple i18n translation files to add `STR_UPDATE_ALL` and
adjust `STR_DOWNLOAD_ALL` text.
- Added separate handlers: `downloadAll()` for fonts that have been
installed and `updateAll()` for fonts with updates.
  - `Download All` and `Update All` are only shown when applicable.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**PARTIALLY**_
This commit is contained in:
WuTofu
2026-05-12 12:17:01 -05:00
committed by GitHub
parent 8d1b86a893
commit bc6e090aa8
6 changed files with 90 additions and 22 deletions
+2 -1
View File
@@ -323,7 +323,8 @@ STR_SD_CARD_FULL: "Insufficient SD card space"
STR_FILES_LABEL: "Files: "
STR_SIZE_LABEL: "Size: "
STR_REDOWNLOAD: "Re-download"
STR_DOWNLOAD_ALL: "Download / Update All"
STR_DOWNLOAD_ALL: "Download All"
STR_UPDATE_ALL: "Update All"
STR_ALL_FONTS_INSTALLED: "All fonts installed!"
STR_UPDATE_AVAILABLE: "Update"
STR_CRASH_TITLE: "System Crash"
+2 -1
View File
@@ -323,7 +323,8 @@ STR_SD_CARD_FULL: "Za mało pamięci na karcie SD"
STR_FILES_LABEL: "Pliki: "
STR_SIZE_LABEL: "Rozmiar: "
STR_REDOWNLOAD: "Re-download"
STR_DOWNLOAD_ALL: "Pobierz / Uaktualnij wszystkie"
STR_DOWNLOAD_ALL: "Pobierz wszystkie"
STR_UPDATE_ALL: "Uaktualnij wszystkie"
STR_ALL_FONTS_INSTALLED: "Wszystkie czcionki zainstalowane!"
STR_UPDATE_AVAILABLE: "Uaktualnij"
STR_CRASH_TITLE: "Awaria systemu"
+2 -1
View File
@@ -323,7 +323,8 @@ STR_SD_CARD_FULL: "Otillräckligt utrymme på SD-kortet"
STR_FILES_LABEL: "Filer: "
STR_SIZE_LABEL: "Storlek: "
STR_REDOWNLOAD: "Ladda ner igen"
STR_DOWNLOAD_ALL: "Ladda ner / Uppdatera alla"
STR_DOWNLOAD_ALL: "Ladda ner alla"
STR_UPDATE_ALL: "Uppdatera alla"
STR_ALL_FONTS_INSTALLED: "Alla teckensnitt installerade!"
STR_UPDATE_AVAILABLE: "Uppdatering"
STR_CRASH_TITLE: "Systemkrasch"
+3 -2
View File
@@ -323,8 +323,9 @@ STR_SD_CARD_FULL: "Недостатньо місця на SD-карті"
STR_FILES_LABEL: "Файли: "
STR_SIZE_LABEL: "Розмір: "
STR_REDOWNLOAD: "Завантажити повторно"
STR_DOWNLOAD_ALL: "Завантажити / Оновити все"
STR_ALL_FONTS_INSTALLED: "Шрифти встановлено!"
STR_DOWNLOAD_ALL: "Завантажити все"
STR_UPDATE_ALL: "Оновити все"
STR_ALL_FONTS_INSTALLED: "Всі шрифти встановлено!"
STR_UPDATE_AVAILABLE: "Оновити"
STR_CRASH_TITLE: "Збій Системи"
STR_CRASH_DESCRIPTION: "Дані про збій збережено в crash_report.txt. Додайте цей файл до вашого звіту про помилку."
@@ -173,7 +173,7 @@ bool FontDownloadActivity::fetchAndParseManifest() {
void FontDownloadActivity::downloadAll() {
for (size_t i = 0; i < families_.size(); i++) {
if (families_[i].installed && !families_[i].hasUpdate) continue;
if (families_[i].installed) continue;
downloadFamily(families_[i]);
if (state_ == ERROR) return;
}
@@ -184,10 +184,59 @@ void FontDownloadActivity::downloadAll() {
}
}
size_t FontDownloadActivity::totalUninstalledSize() const {
void FontDownloadActivity::updateAll() {
for (size_t i = 0; i < families_.size(); i++) {
if (!families_[i].hasUpdate) continue;
downloadFamily(families_[i]);
if (state_ == ERROR) return;
}
{
RenderLock lock(*this);
state_ = COMPLETE;
}
}
bool FontDownloadActivity::showDownloadAllRow() const {
for (const auto& f : families_) {
if (!f.installed) return true;
}
return false;
}
bool FontDownloadActivity::showUpdateAllRow() const {
for (const auto& f : families_) {
if (f.hasUpdate) return true;
}
return false;
}
int FontDownloadActivity::specialRowCount() const {
return (showDownloadAllRow() ? 1 : 0) + (showUpdateAllRow() ? 1 : 0);
}
bool FontDownloadActivity::isDownloadAllRow(int index) const { return showDownloadAllRow() && index == 0; }
bool FontDownloadActivity::isUpdateAllRow(int index) const {
return showUpdateAllRow() && index == (showDownloadAllRow() ? 1 : 0);
}
int FontDownloadActivity::listItemCount() const {
return families_.empty() ? 0 : static_cast<int>(families_.size()) + specialRowCount();
}
size_t FontDownloadActivity::totalDownloadSize() const {
size_t total = 0;
for (const auto& f : families_) {
if (!f.installed || f.hasUpdate) total += f.totalSize;
if (!f.installed) total += f.totalSize;
}
return total;
}
size_t FontDownloadActivity::totalUpdateSize() const {
size_t total = 0;
for (const auto& f : families_) {
if (f.hasUpdate) total += f.totalSize;
}
return total;
}
@@ -299,6 +348,7 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
fontInstaller_.refreshRegistry();
family.installed = true;
family.hasUpdate = false;
{
RenderLock lock(*this);
@@ -341,7 +391,8 @@ void FontDownloadActivity::onDeleteConfirmationResult(const ActivityResult& resu
}
bool FontDownloadActivity::isSelectedFamilyDeletable() const {
if (selectedIndex_ <= 0 || selectedIndex_ >= listItemCount()) return false;
if (isDownloadAllRow(selectedIndex_) || isUpdateAllRow(selectedIndex_)) return false;
if (selectedIndex_ < specialRowCount() || selectedIndex_ >= listItemCount()) return false;
const auto& family = families_[familyIndexFromList(selectedIndex_)];
return family.installed && !family.hasUpdate;
}
@@ -380,8 +431,10 @@ void FontDownloadActivity::loop() {
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
if (!families_.empty()) {
if (isDownloadAllSelected()) {
if (isDownloadAllRow(selectedIndex_)) {
downloadAll();
} else if (isUpdateAllRow(selectedIndex_)) {
updateAll();
} else {
auto& family = families_[familyIndexFromList(selectedIndex_)];
if (!family.installed || family.hasUpdate) {
@@ -467,18 +520,21 @@ void FontDownloadActivity::render(RenderLock&&) {
Rect{0, contentTop, pageWidth, pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing},
listItemCount(), selectedIndex_,
[this](int index) -> std::string {
if (index == 0) {
return std::string(tr(STR_DOWNLOAD_ALL)) + " (" + formatSize(totalUninstalledSize()) + ")";
if (isDownloadAllRow(index)) {
return std::string(tr(STR_DOWNLOAD_ALL)) + " (" + formatSize(totalDownloadSize()) + ")";
}
if (isUpdateAllRow(index)) {
return std::string(tr(STR_UPDATE_ALL)) + " (" + formatSize(totalUpdateSize()) + ")";
}
return families_[familyIndexFromList(index)].name;
},
[this](int index) -> std::string {
if (index == 0) return "";
if (isDownloadAllRow(index) || isUpdateAllRow(index)) return "";
return families_[familyIndexFromList(index)].description;
},
nullptr,
[this](int index) -> std::string {
if (index == 0) return "";
if (isDownloadAllRow(index) || isUpdateAllRow(index)) return "";
const auto& f = families_[familyIndexFromList(index)];
if (f.hasUpdate) return tr(STR_UPDATE_AVAILABLE);
if (f.installed) return tr(STR_INSTALLED);
@@ -486,14 +542,16 @@ void FontDownloadActivity::render(RenderLock&&) {
},
true,
[this](int index) -> bool {
if (index == 0) return false;
if (isDownloadAllRow(index) || isUpdateAllRow(index)) return false;
const auto& f = families_[familyIndexFromList(index)];
return f.installed && !f.hasUpdate;
});
const auto labels =
mappedInput.mapLabels(tr(STR_BACK), isSelectedFamilyDeletable() ? tr(STR_DELETE) : tr(STR_DOWNLOAD),
tr(STR_DIR_UP), tr(STR_DIR_DOWN));
const auto labels = mappedInput.mapLabels(tr(STR_BACK),
isSelectedFamilyDeletable() ? tr(STR_DELETE)
: isUpdateAllRow(selectedIndex_) ? tr(STR_UPDATE)
: tr(STR_DOWNLOAD),
tr(STR_DIR_UP), tr(STR_DIR_DOWN));
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
}
} else if (state_ == DOWNLOADING) {
+10 -4
View File
@@ -84,13 +84,19 @@ class FontDownloadActivity : public Activity {
bool fetchAndParseManifest();
void downloadFamily(ManifestFamily& family);
void downloadAll();
void updateAll();
static bool computeFileCrc32(const char* path, uint32_t& outCrc);
bool isDownloadAllSelected() const { return selectedIndex_ == 0 && !families_.empty(); }
bool showDownloadAllRow() const;
bool showUpdateAllRow() const;
int specialRowCount() const;
bool isDownloadAllRow(int index) const;
bool isUpdateAllRow(int index) const;
bool isSelectedFamilyDeletable() const;
void promptDeleteSelectedFamily();
void onDeleteConfirmationResult(const ActivityResult& result);
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;
int familyIndexFromList(int listIndex) const { return listIndex - specialRowCount(); }
int listItemCount() const;
size_t totalDownloadSize() const;
size_t totalUpdateSize() const;
static std::string formatSize(size_t bytes);
};