fix: resolve mod build errors after upstream sync

- Update open-x4-sdk submodule to 9f76376 (BatteryMonitor ESP-IDF 5.x compat)
- Add RTC_NOINIT bounds check for logHead in Logging.cpp
- Add drawTextRotated90CCW to GfxRenderer for dictionary UI
- Add getWordXpos() accessor to TextBlock for dictionary word selection
- Fix bare include paths (ActivityResult.h, RenderLock.h) across 10 files
- Fix rvalue ref binding in setResult() lambdas (std::move pattern)
- Fix std::max type mismatch (uint8_t vs int) in EpubReaderActivity
- Fix FsFile forward declaration conflict in Dictionary.h
- Restore StringUtils::checkFileExtension() and sortFileList()
- Restore RecentBooksStore::removeBook()

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-07 20:56:40 -05:00
parent 9464df1727
commit 4627ec95f9
22 changed files with 180 additions and 34 deletions

View File

@@ -53,6 +53,15 @@ void RecentBooksStore::updateBook(const std::string& path, const std::string& ti
}
}
void RecentBooksStore::removeBook(const std::string& path) {
auto it =
std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == path; });
if (it != recentBooks.end()) {
recentBooks.erase(it);
saveToFile();
}
}
bool RecentBooksStore::saveToFile() const {
Storage.mkdir("/.crosspoint");
return JsonSettingsIO::saveRecentBooks(*this, RECENT_BOOKS_FILE_JSON);

View File

@@ -37,6 +37,8 @@ class RecentBooksStore {
void updateBook(const std::string& path, const std::string& title, const std::string& author,
const std::string& coverBmpPath);
void removeBook(const std::string& path);
// Get the list of recent books (most recent first)
const std::vector<RecentBook>& getBooks() const { return recentBooks; }

View File

@@ -4,7 +4,7 @@
#include <algorithm>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include <cctype>
#include <cstdlib>

View File

@@ -5,7 +5,7 @@
#include "DictionaryDefinitionActivity.h"
#include "HalDisplay.h"
#include "MappedInputManager.h"
#include "RenderLock.h"
#include "activities/RenderLock.h"
#include "components/UITheme.h"
#include "fontIds.h"
#include "util/Dictionary.h"
@@ -56,9 +56,9 @@ void DictionarySuggestionsActivity::loop() {
startActivityForResult(
std::make_unique<DictionaryDefinitionActivity>(renderer, mappedInput, selected, definition, readerFontId,
orientation, true),
[this](const ActivityResult& result) {
[this](ActivityResult result) {
if (!result.isCancelled) {
setResult(result);
setResult(std::move(result));
finish();
} else {
requestUpdate();

View File

@@ -5,7 +5,7 @@
#include <algorithm>
#include <climits>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include "CrossPointSettings.h"
#include "DictionaryDefinitionActivity.h"
#include "DictionarySuggestionsActivity.h"
@@ -353,9 +353,9 @@ void DictionaryWordSelectActivity::loop() {
startActivityForResult(
std::make_unique<DictionaryDefinitionActivity>(renderer, mappedInput, cleaned, definition, fontId, orientation,
true),
[this](const ActivityResult& result) {
[this](ActivityResult result) {
if (!result.isCancelled) {
setResult(result);
setResult(std::move(result));
finish();
} else {
requestUpdate();
@@ -372,9 +372,9 @@ void DictionaryWordSelectActivity::loop() {
startActivityForResult(
std::make_unique<DictionaryDefinitionActivity>(renderer, mappedInput, stem, stemDef, fontId, orientation,
true),
[this](const ActivityResult& result) {
[this](ActivityResult result) {
if (!result.isCancelled) {
setResult(result);
setResult(std::move(result));
finish();
} else {
requestUpdate();
@@ -390,9 +390,9 @@ void DictionaryWordSelectActivity::loop() {
startActivityForResult(
std::make_unique<DictionarySuggestionsActivity>(renderer, mappedInput, cleaned, similar, fontId, orientation,
cachePath),
[this](const ActivityResult& result) {
[this](ActivityResult result) {
if (!result.isCancelled) {
setResult(result);
setResult(std::move(result));
finish();
} else {
requestUpdate();

View File

@@ -3,7 +3,7 @@
#include <GfxRenderer.h>
#include <I18n.h>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include "MappedInputManager.h"
#include "components/UITheme.h"
#include "fontIds.h"

View File

@@ -717,7 +717,7 @@ bool EpubReaderActivity::silentIndexNextChapterIfNeeded() {
marginTop += SETTINGS.screenMargin;
marginLeft += SETTINGS.screenMargin;
marginRight += SETTINGS.screenMargin;
marginBottom += std::max(SETTINGS.screenMargin, UITheme::getInstance().getStatusBarHeight());
marginBottom += std::max(static_cast<int>(SETTINGS.screenMargin), UITheme::getInstance().getStatusBarHeight());
const uint16_t vpWidth = renderer.getScreenWidth() - marginLeft - marginRight;
const uint16_t vpHeight = renderer.getScreenHeight() - marginTop - marginBottom;

View File

@@ -2,7 +2,7 @@
#include <GfxRenderer.h>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include "MappedInputManager.h"
#include "components/UITheme.h"
#include "fontIds.h"

View File

@@ -5,7 +5,7 @@
#include <algorithm>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include "DictionaryDefinitionActivity.h"
#include "DictionarySuggestionsActivity.h"
#include "MappedInputManager.h"
@@ -143,9 +143,9 @@ void LookedUpWordsActivity::loop() {
startActivityForResult(
std::make_unique<DictionaryDefinitionActivity>(renderer, mappedInput, headword, definition, readerFontId,
orientation, true),
[this](const ActivityResult& result) {
[this](ActivityResult result) {
if (!result.isCancelled) {
setResult(result);
setResult(std::move(result));
finish();
} else {
requestUpdate();
@@ -162,9 +162,9 @@ void LookedUpWordsActivity::loop() {
startActivityForResult(
std::make_unique<DictionaryDefinitionActivity>(renderer, mappedInput, stem, stemDef, readerFontId,
orientation, true),
[this](const ActivityResult& result) {
[this](ActivityResult result) {
if (!result.isCancelled) {
setResult(result);
setResult(std::move(result));
finish();
} else {
requestUpdate();
@@ -180,9 +180,9 @@ void LookedUpWordsActivity::loop() {
startActivityForResult(
std::make_unique<DictionarySuggestionsActivity>(renderer, mappedInput, headword, similar, readerFontId,
orientation, cachePath),
[this](const ActivityResult& result) {
[this](ActivityResult result) {
if (!result.isCancelled) {
setResult(result);
setResult(std::move(result));
finish();
} else {
requestUpdate();

View File

@@ -5,7 +5,7 @@
#include <Logging.h>
#include <WiFi.h>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include "CrossPointSettings.h"
#include "MappedInputManager.h"
#include "activities/network/WifiSelectionActivity.h"

View File

@@ -3,7 +3,7 @@
#include <GfxRenderer.h>
#include <I18n.h>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include "MappedInputManager.h"
#include "OpdsServerStore.h"
#include "OpdsSettingsActivity.h"

View File

@@ -6,7 +6,7 @@
#include <cstring>
#include <string>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include "MappedInputManager.h"
#include "OpdsServerStore.h"
#include "activities/util/DirectoryPickerActivity.h"

View File

@@ -5,7 +5,7 @@
#include <cstring>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include "MappedInputManager.h"
#include "components/UITheme.h"
#include "fontIds.h"

View File

@@ -6,7 +6,7 @@
#include <algorithm>
#include <cstdio>
#include "ActivityResult.h"
#include "activities/ActivityResult.h"
#include "MappedInputManager.h"
#include "components/UITheme.h"
#include "fontIds.h"

View File

@@ -1,11 +1,11 @@
#pragma once
#include <HalStorage.h>
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
class FsFile;
class Dictionary {
public:
static bool exists();

View File

@@ -2,6 +2,10 @@
#include <Utf8.h>
#include <algorithm>
#include <cctype>
#include <cstring>
namespace StringUtils {
std::string sanitizeFilename(const std::string& name, size_t maxBytes) {
@@ -43,4 +47,48 @@ std::string sanitizeFilename(const std::string& name, size_t maxBytes) {
return result.empty() ? "book" : result;
}
bool checkFileExtension(const std::string& fileName, const char* extension) {
const size_t extLen = strlen(extension);
if (fileName.length() < extLen) return false;
const std::string tail = fileName.substr(fileName.length() - extLen);
for (size_t i = 0; i < extLen; i++) {
if (tolower(static_cast<unsigned char>(tail[i])) != tolower(static_cast<unsigned char>(extension[i]))) return false;
}
return true;
}
void sortFileList(std::vector<std::string>& entries) {
std::sort(entries.begin(), entries.end(), [](const std::string& a, const std::string& b) {
bool isDir1 = !a.empty() && a.back() == '/';
bool isDir2 = !b.empty() && b.back() == '/';
if (isDir1 != isDir2) return isDir1;
const char* s1 = a.c_str();
const char* s2 = b.c_str();
while (*s1 && *s2) {
if (isdigit(*s1) && isdigit(*s2)) {
while (*s1 == '0') s1++;
while (*s2 == '0') s2++;
int len1 = 0, len2 = 0;
while (isdigit(s1[len1])) len1++;
while (isdigit(s2[len2])) len2++;
if (len1 != len2) return len1 < len2;
for (int i = 0; i < len1; i++) {
if (s1[i] != s2[i]) return s1[i] < s2[i];
}
s1 += len1;
s2 += len2;
} else {
char c1 = tolower(*s1);
char c2 = tolower(*s2);
if (c1 != c2) return c1 < c2;
s1++;
s2++;
}
}
return *s1 == 0 && *s2 != 0;
});
}
} // namespace StringUtils

View File

@@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <vector>
namespace StringUtils {
@@ -11,4 +12,15 @@ namespace StringUtils {
*/
std::string sanitizeFilename(const std::string& name, size_t maxBytes = 100);
/**
* Case-insensitive file extension check.
*/
bool checkFileExtension(const std::string& fileName, const char* extension);
/**
* Sort a file/directory list with directories first, using case-insensitive natural sort.
* Directory entries are identified by a trailing '/'.
*/
void sortFileList(std::vector<std::string>& entries);
} // namespace StringUtils