mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-14 15:16:40 +00:00
Replace the single device-wide Scope text field with a small named list (wildcard "*" fixed first, plus a movable default): each channel picks one scope of its own (matching the app's per-channel region picker, surfaced in the channel-history title), and the repeater's Extra scopes multi-selects from the same list instead of comma-typed names. Both pickers are popups (PopupMenu gains addCheckItem()/a fillable-square checkbox glyph) over the existing screen rather than a full-screen takeover. Also fixes a stray-bits bug where a pre-existing prefs file's own sentinel tail could read into the new repeat_extra_scope_mask/ch_scope_idx fields and silently reappear as a real pick later once the scope list grew into that range. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
80 lines
3.6 KiB
C++
80 lines
3.6 KiB
C++
#pragma once
|
|
|
|
#include <helpers/IdentityStore.h>
|
|
#include <helpers/ContactInfo.h>
|
|
#include <helpers/ChannelDetails.h>
|
|
#include "NodePrefs.h"
|
|
#include "ScopeList.h"
|
|
|
|
class DataStoreHost {
|
|
public:
|
|
virtual bool onContactLoaded(const ContactInfo& contact) =0;
|
|
virtual bool getContactForSave(uint32_t idx, ContactInfo& contact) =0;
|
|
virtual bool onChannelLoaded(uint8_t channel_idx, const ChannelDetails& ch) =0;
|
|
virtual bool getChannelForSave(uint8_t channel_idx, ChannelDetails& ch) =0;
|
|
};
|
|
|
|
class DataStore {
|
|
FILESYSTEM* _fs;
|
|
FILESYSTEM* _fsExtra;
|
|
mesh::RTCClock* _clock;
|
|
IdentityStore identity_store;
|
|
|
|
void loadPrefsInt(const char *filename, NodePrefs& prefs, double& node_lat, double& node_lon);
|
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
|
void checkAdvBlobFile();
|
|
#endif
|
|
|
|
public:
|
|
DataStore(FILESYSTEM& fs, mesh::RTCClock& clock);
|
|
DataStore(FILESYSTEM& fs, FILESYSTEM& fsExtra, mesh::RTCClock& clock);
|
|
void begin();
|
|
bool formatFileSystem();
|
|
FILESYSTEM* getPrimaryFS() const { return _fs; }
|
|
FILESYSTEM* getSecondaryFS() const { return _fsExtra; }
|
|
bool loadMainIdentity(mesh::LocalIdentity &identity);
|
|
bool saveMainIdentity(const mesh::LocalIdentity &identity);
|
|
void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon);
|
|
void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon);
|
|
void loadContacts(DataStoreHost* host);
|
|
void saveContacts(DataStoreHost* host, bool (*filter)(const ContactInfo& c) = NULL);
|
|
// Returns true if a channels file (current or legacy) existed and was
|
|
// loaded -- false only on a genuinely fresh device with neither file, so
|
|
// the caller knows whether it's safe to seed default channels (see
|
|
// MyMesh::begin()'s addChannel("Public", ...) -- seeding unconditionally
|
|
// would resurrect a channel the user had deliberately deleted, since a
|
|
// deleted slot is simply absent from the file, not written as empty).
|
|
bool loadChannels(DataStoreHost* host);
|
|
void saveChannels(DataStoreHost* host);
|
|
// /scopes1: the shared named-scope list (see ScopeList.h). `prefs` is only
|
|
// read, for a one-time migration of a pre-existing single
|
|
// default_scope_name/key into list entry 1 -- the file is authoritative
|
|
// once it exists. Returns true if the file existed or the migration ran
|
|
// (i.e. `list` reflects real prior configuration); false only means a
|
|
// genuinely fresh, unconfigured device (list left at its default: empty,
|
|
// default_idx 0 == "*").
|
|
bool loadScopeList(ScopeList& list, const NodePrefs& prefs);
|
|
void saveScopeList(const ScopeList& list);
|
|
void migrateToSecondaryFS();
|
|
uint8_t getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]);
|
|
bool putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], uint8_t len);
|
|
bool deleteBlobByKey(const uint8_t key[], int key_len);
|
|
File openRead(const char* filename);
|
|
File openRead(FILESYSTEM* fs, const char* filename);
|
|
File openWrite(const char* filename);
|
|
// Atomically replace final_path with a fully-written temp file (see
|
|
// openWrite()). Use for small custom records that want the same crash-safety
|
|
// as contacts/channels: write everything to a .tmp, then commit. Returns
|
|
// false if the swap fails (the previous good file is left untouched).
|
|
bool commitFile(const char* tmp_path, const char* final_path);
|
|
bool removeFile(const char* filename);
|
|
bool removeFile(FILESYSTEM* fs, const char* filename);
|
|
uint32_t getStorageUsedKb() const;
|
|
uint32_t getStorageTotalKb() const;
|
|
void saveRTCTime();
|
|
void restoreRTCTime();
|
|
|
|
private:
|
|
FILESYSTEM* _getContactsChannelsFS() const { if (_fsExtra) return _fsExtra; return _fs;};
|
|
};
|