diff --git a/src/CrossPointSettings.cpp b/src/CrossPointSettings.cpp index 05cdeffe..1404709d 100644 --- a/src/CrossPointSettings.cpp +++ b/src/CrossPointSettings.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "fontIds.h" @@ -21,8 +22,7 @@ void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) { namespace { constexpr uint8_t SETTINGS_FILE_VERSION = 1; -// Increment this when adding new persisted settings fields -constexpr uint8_t SETTINGS_COUNT = 30; +// SETTINGS_COUNT is now calculated automatically in saveToFile constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin"; // Validate front button mapping to ensure each hardware button is unique. @@ -77,6 +77,68 @@ void applyLegacyFrontButtonLayout(CrossPointSettings& settings) { } } // namespace +class SettingsWriter { + public: + bool is_counting = false; + uint8_t item_count = 0; + template + + 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); + // New fields need to be added at end for backward compatibility + + return writer.item_count; +} + bool CrossPointSettings::saveToFile() const { // Make sure the directory exists Storage.mkdir("/.crosspoint"); @@ -86,39 +148,15 @@ bool CrossPointSettings::saveToFile() const { 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_COUNT); - serialization::writePod(outputFile, sleepScreen); - serialization::writePod(outputFile, extraParagraphSpacing); - 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); - // New fields added at end for backward compatibility + serialization::writePod(outputFile, static_cast(item_count)); + // Second pass: actually write the settings + writeSettings(outputFile); // This will write the actual data + outputFile.close(); LOG_DBG("CPS", "Settings saved to file"); diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index 1348519f..a2814eb8 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -2,6 +2,9 @@ #include #include +// Forward declarations +class FsFile; + class CrossPointSettings { private: // Private constructor for singleton @@ -182,6 +185,9 @@ class CrossPointSettings { } 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 loadFromFile();