fix: Auto calculate the settings size on serialization (#832)

* The constant SETTINGS_CONST was hardcoded and needed to be updated
whenever an additional setting was added
* This is no longer necessary as the settings size will be determined
automatically on settings persistence

* New settings need to be added (as previously) in saveToFile - that's
it

---

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? YES

---------

Co-authored-by: Xuan Son Nguyen <son@huggingface.co>
This commit is contained in:
jpirnay
2026-02-16 12:11:26 +01:00
committed by cottongin
parent d11ad45e59
commit 6097ee03df
2 changed files with 79 additions and 35 deletions

View File

@@ -5,6 +5,7 @@
#include <Serialization.h> #include <Serialization.h>
#include <cstring> #include <cstring>
#include <string>
#include "fontIds.h" #include "fontIds.h"
@@ -21,8 +22,7 @@ void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) {
namespace { namespace {
constexpr uint8_t SETTINGS_FILE_VERSION = 1; constexpr uint8_t SETTINGS_FILE_VERSION = 1;
// Increment this when adding new persisted settings fields // SETTINGS_COUNT is now calculated automatically in saveToFile
constexpr uint8_t SETTINGS_COUNT = 31;
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin"; constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
// Validate front button mapping to ensure each hardware button is unique. // Validate front button mapping to ensure each hardware button is unique.
@@ -77,6 +77,69 @@ void applyLegacyFrontButtonLayout(CrossPointSettings& settings) {
} }
} // namespace } // namespace
class SettingsWriter {
public:
bool is_counting = false;
uint8_t item_count = 0;
template <typename T>
void writeItem(FsFile& file, const T& value) {
if (is_counting) {
item_count++;
} else {
serialization::writePod(file, value);
}
}
void writeItemString(FsFile& file, const char* value) {
if (is_counting) {
item_count++;
} else {
serialization::writeString(file, std::string(value));
}
}
};
uint8_t CrossPointSettings::writeSettings(FsFile& file, bool count_only) const {
SettingsWriter writer;
writer.is_counting = count_only;
writer.writeItem(file, sleepScreen);
writer.writeItem(file, extraParagraphSpacing);
writer.writeItem(file, shortPwrBtn);
writer.writeItem(file, statusBar);
writer.writeItem(file, orientation);
writer.writeItem(file, frontButtonLayout); // legacy
writer.writeItem(file, sideButtonLayout);
writer.writeItem(file, fontFamily);
writer.writeItem(file, fontSize);
writer.writeItem(file, lineSpacing);
writer.writeItem(file, paragraphAlignment);
writer.writeItem(file, sleepTimeout);
writer.writeItem(file, refreshFrequency);
writer.writeItem(file, screenMargin);
writer.writeItem(file, sleepScreenCoverMode);
writer.writeItemString(file, opdsServerUrl);
writer.writeItem(file, textAntiAliasing);
writer.writeItem(file, hideBatteryPercentage);
writer.writeItem(file, longPressChapterSkip);
writer.writeItem(file, hyphenationEnabled);
writer.writeItemString(file, opdsUsername);
writer.writeItemString(file, opdsPassword);
writer.writeItem(file, sleepScreenCoverFilter);
writer.writeItem(file, uiTheme);
writer.writeItem(file, frontButtonBack);
writer.writeItem(file, frontButtonConfirm);
writer.writeItem(file, frontButtonLeft);
writer.writeItem(file, frontButtonRight);
writer.writeItem(file, fadingFix);
writer.writeItem(file, embeddedStyle);
writer.writeItem(file, sleepScreenLetterboxFill);
// New fields need to be added at end for backward compatibility
return writer.item_count;
}
bool CrossPointSettings::saveToFile() const { bool CrossPointSettings::saveToFile() const {
// Make sure the directory exists // Make sure the directory exists
Storage.mkdir("/.crosspoint"); Storage.mkdir("/.crosspoint");
@@ -86,40 +149,15 @@ bool CrossPointSettings::saveToFile() const {
return false; return false;
} }
// First pass: count the items
uint8_t item_count = writeSettings(outputFile, true); // This will just count, not write
// Write header
serialization::writePod(outputFile, SETTINGS_FILE_VERSION); serialization::writePod(outputFile, SETTINGS_FILE_VERSION);
serialization::writePod(outputFile, SETTINGS_COUNT); serialization::writePod(outputFile, static_cast<uint8_t>(item_count));
serialization::writePod(outputFile, sleepScreen); // Second pass: actually write the settings
serialization::writePod(outputFile, extraParagraphSpacing); writeSettings(outputFile); // This will write the actual data
serialization::writePod(outputFile, shortPwrBtn);
serialization::writePod(outputFile, statusBar);
serialization::writePod(outputFile, orientation);
serialization::writePod(outputFile, frontButtonLayout); // legacy
serialization::writePod(outputFile, sideButtonLayout);
serialization::writePod(outputFile, fontFamily);
serialization::writePod(outputFile, fontSize);
serialization::writePod(outputFile, lineSpacing);
serialization::writePod(outputFile, paragraphAlignment);
serialization::writePod(outputFile, sleepTimeout);
serialization::writePod(outputFile, refreshFrequency);
serialization::writePod(outputFile, screenMargin);
serialization::writePod(outputFile, sleepScreenCoverMode);
serialization::writeString(outputFile, std::string(opdsServerUrl));
serialization::writePod(outputFile, textAntiAliasing);
serialization::writePod(outputFile, hideBatteryPercentage);
serialization::writePod(outputFile, longPressChapterSkip);
serialization::writePod(outputFile, hyphenationEnabled);
serialization::writeString(outputFile, std::string(opdsUsername));
serialization::writeString(outputFile, std::string(opdsPassword));
serialization::writePod(outputFile, sleepScreenCoverFilter);
serialization::writePod(outputFile, uiTheme);
serialization::writePod(outputFile, frontButtonBack);
serialization::writePod(outputFile, frontButtonConfirm);
serialization::writePod(outputFile, frontButtonLeft);
serialization::writePod(outputFile, frontButtonRight);
serialization::writePod(outputFile, fadingFix);
serialization::writePod(outputFile, embeddedStyle);
serialization::writePod(outputFile, sleepScreenLetterboxFill);
// New fields added at end for backward compatibility
outputFile.close(); outputFile.close();
LOG_DBG("CPS", "Settings saved to file"); LOG_DBG("CPS", "Settings saved to file");

View File

@@ -2,6 +2,9 @@
#include <cstdint> #include <cstdint>
#include <iosfwd> #include <iosfwd>
// Forward declarations
class FsFile;
class CrossPointSettings { class CrossPointSettings {
private: private:
// Private constructor for singleton // Private constructor for singleton
@@ -190,6 +193,9 @@ class CrossPointSettings {
} }
int getReaderFontId() const; int getReaderFontId() const;
// If count_only is true, returns the number of settings items that would be written.
uint8_t writeSettings(FsFile& file, bool count_only = false) const;
bool saveToFile() const; bool saveToFile() const;
bool loadFromFile(); bool loadFromFile();