Consolidate companion components

This commit is contained in:
mikecarper committed 2026-09-17 13:41:39 -07:00
1 parent aab8f5038a
commit ebee99af81
32 files changed
+286 -287

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
#pragma once
#include <helpers/CompanionJohnConfig.h>
#include <helpers/CompanionReaderConfig.h>
#include <helpers/ota/OtaMemoryPolicy.h>
// The role terminal is also used by WebConfig on WiFi-only Companions. Its
+9 -9
View File
@@ -11,8 +11,8 @@
#include <errno.h>
#include <sys/stat.h>
#endif
#if COMPANION_FEATURE_JOHN
#include <helpers/bible/JohnBookmarkFiles.h>
#if COMPANION_FEATURE_READER
#include <helpers/bible/ReaderBookmarkFiles.h>
#endif
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
@@ -446,12 +446,12 @@ File DataStore::openRead(const char* filename) {
return openRead(_fs, filename);
}
#if COMPANION_FEATURE_JOHN
#if COMPANION_FEATURE_READER
namespace {
class JohnBookmarkFiles {
class ReaderBookmarkFiles {
FILESYSTEM* _fs;
public:
explicit JohnBookmarkFiles(FILESYSTEM* fs) : _fs(fs) {}
explicit ReaderBookmarkFiles(FILESYSTEM* fs) : _fs(fs) {}
bool exists(const char* path) {
#if defined(NRF52_PLATFORM)
bool present = false;
@@ -496,20 +496,20 @@ public:
};
} // namespace
bool DataStore::loadJohnBookmark(mesh::bible::Position& pos) {
bool DataStore::loadReaderBookmark(mesh::bible::Position& pos) {
pos = mesh::bible::Position{};
#if defined(NRF52_PLATFORM)
if (_primary_storage_unavailable) return false;
#endif
JohnBookmarkFiles files(_fs);
ReaderBookmarkFiles files(_fs);
return mesh::bible::loadReaderBookmark(files, pos);
}
bool DataStore::saveJohnBookmark(mesh::bible::Position pos) {
bool DataStore::saveReaderBookmark(mesh::bible::Position pos) {
#if defined(NRF52_PLATFORM)
if (_primary_storage_unavailable) return false;
#endif
JohnBookmarkFiles files(_fs);
ReaderBookmarkFiles files(_fs);
return mesh::bible::saveReaderBookmark(files, pos);
}
#endif
+6 -6
View File
@@ -8,9 +8,9 @@
#if MESH_CONTACT_CACHE
#include <helpers/ContactSecretCache.h>
#endif
#include <helpers/CompanionJohnConfig.h>
#if COMPANION_FEATURE_JOHN
#include <helpers/bible/JohnReader.h>
#include <helpers/CompanionReaderConfig.h>
#if COMPANION_FEATURE_READER
#include <helpers/bible/Reader.h>
#endif
class DataStoreHost {
@@ -116,9 +116,9 @@ public:
bool loadPrefs(CompanionNodePrefs& prefs, double& node_lat,
double& node_lon);
bool savePrefs(const CompanionNodePrefs& prefs, double node_lat, double node_lon);
#if COMPANION_FEATURE_JOHN
bool loadJohnBookmark(mesh::bible::Position& pos);
bool saveJohnBookmark(mesh::bible::Position pos);
#if COMPANION_FEATURE_READER
bool loadReaderBookmark(mesh::bible::Position& pos);
bool saveReaderBookmark(mesh::bible::Position pos);
#endif
void loadContacts(DataStoreHost* host);
bool saveContacts(DataStoreHost* host, bool (*filter)(const ContactInfo& c) = NULL);
+5 -5
View File
@@ -14,7 +14,7 @@
#include <Mesh.h>
#include <helpers/CompanionHardwareCommandCompat.h>
#include <helpers/CompanionStatusResponse.h>
#include <helpers/CompanionJohn.h>
#include <helpers/CompanionReader.h>
#include <helpers/IdentityGeneration.h>
#include <helpers/LazyPersistence.h>
#include <helpers/StorageLayout.h>
@@ -7881,8 +7881,8 @@ void MyMesh::handleTerminalCommand(char* command) {
if (*command == 0) return;
mesh::cli::normalizeCommandVerb(command);
#if COMPANION_FEATURE_JOHN
if (mesh::handleJohnCommand(command, terminalOutput())) return;
#if COMPANION_FEATURE_READER
if (mesh::handleReaderCommand(command, terminalOutput())) return;
#endif
char local_reply[160];
@@ -8362,8 +8362,8 @@ void MyMesh::handleTerminalCommand(char* command) {
terminalOutput().print(" board\r\n");
terminalOutput().print(" version\r\n");
terminalOutput().print(" get storage.layout\r\n");
#if COMPANION_FEATURE_JOHN
terminalOutput().print(" get John <chapter>:<verse> (World English Bible, offline)\r\n");
#if COMPANION_FEATURE_READER
terminalOutput().print(" get reader <chapter>:<verse> (World English Bible, offline)\r\n");
#endif
terminalOutput().print(" get pwrmgt.bootreason\r\n");
#if COMPANION_FEATURE_MEMORY_DIAGNOSTICS
+3 -3
View File
@@ -360,9 +360,9 @@ public:
if (saved) _prefs.clearDirty();
return saved;
}
#if COMPANION_FEATURE_JOHN
bool loadJohnBookmark(mesh::bible::Position& pos) { return _store->loadJohnBookmark(pos); }
bool saveJohnBookmark(mesh::bible::Position pos) { return _store->saveJohnBookmark(pos); }
#if COMPANION_FEATURE_READER
bool loadReaderBookmark(mesh::bible::Position& pos) { return _store->loadReaderBookmark(pos); }
bool saveReaderBookmark(mesh::bible::Position pos) { return _store->saveReaderBookmark(pos); }
#endif
#if ENV_INCLUDE_GPS == 1
@@ -1,6 +1,6 @@
#pragma once
#include <helpers/CompanionJohn.h>
#include <helpers/bible/JohnReader.h>
#include <helpers/CompanionReader.h>
#include <helpers/bible/Reader.h>
#include <helpers/ui/ReaderNavigationHint.h>
#if UI_SMALL_MESSAGE_FONT || UI_BUTTON_READER_HINT
#include <helpers/ui/SmallMessageText.h>
@@ -8,7 +8,7 @@
// Included by UITask.cpp after the task and MyMesh declarations. Only a small
// cursor/checkpoint object persists; the 2 KiB decode buffer is on demand.
class JohnReaderScreen : public UIScreen {
class ReaderScreen : public UIScreen {
UITask* _task;
DisplayDriver* _display;
mesh::bible::ReaderBookmark _bookmark;
@@ -79,12 +79,12 @@ class JohnReaderScreen : public UIScreen {
// At most two lookups: the current verse, then its adjacent verse when
// navigation crosses a boundary. No recursive decode or second buffer.
for (int pass = 0; pass < 2; ++pass) {
const LookupResult result = mesh::readJohnVerse(
const LookupResult result = mesh::readReaderVerse(
referenceAt(pos.verse), scratch, sizeof(scratch), text);
if (result != LookupResult::Found) {
if (draw) {
body.setColor(UIColor::warning_txt);
body.drawTextEllipsized(0, top, width, "John unavailable");
body.drawTextEllipsized(0, top, width, "Reader unavailable");
#if UI_BUTTON_READER_HINT
#if UI_READER_TOUCH_BAR
mesh::ui::drawReaderTouchBar(hint_text, _touch_bar);
@@ -92,7 +92,7 @@ class JohnReaderScreen : public UIScreen {
mesh::ui::drawButtonReaderHint(hint_text, hint);
#endif
#endif
} else _task->showAlert("John data error", 1500);
} else _task->showAlert("Reader data error", 1500);
return;
}
memmove(scratch, text, strlen(text) + 1);
@@ -114,7 +114,7 @@ class JohnReaderScreen : public UIScreen {
if (!draw) return;
char label[32], progress[16];
const Reference ref = referenceAt(pos.verse);
snprintf(label, sizeof(label), "John %u:%u", ref.chapter, ref.verse);
snprintf(label, sizeof(label), "Reader %u:%u", ref.chapter, ref.verse);
snprintf(progress, sizeof(progress), "%u/%u", page.part, page.parts);
const int progress_width = _display->getTextWidth(progress);
if (stacked_header || _display->getTextWidth(label) > width - progress_width - 4)
@@ -147,18 +147,18 @@ public:
#if UI_READER_TOUCH_BAR
const mesh::ui::TouchNavigationBar* readerTouchBar() const { return &_touch_bar; }
#endif
JohnReaderScreen(UITask* task, DisplayDriver* display) : _task(task), _display(display) {}
ReaderScreen(UITask* task, DisplayDriver* display) : _task(task), _display(display) {}
void open() {
if (!_loaded) {
mesh::bible::Position pos;
the_mesh.loadJohnBookmark(pos);
the_mesh.loadReaderBookmark(pos);
_bookmark.restore(pos);
_loaded = true;
}
}
bool flush() {
if (!_bookmark.dirty()) return true;
if (!the_mesh.saveJohnBookmark(_bookmark.position())) {
if (!the_mesh.saveReaderBookmark(_bookmark.position())) {
_retry_at = millis() + 30000;
return false;
}
@@ -186,7 +186,7 @@ public:
}
return true;
}
if (key == KEY_ENTER || key == KEY_CANCEL) { _task->closeJohnReader(); return true; }
if (key == KEY_ENTER || key == KEY_CANCEL) { _task->closeReader(); return true; }
return false;
}
};
+34 -34
View File
@@ -90,8 +90,8 @@ static uint64_t companionMessageElapsedMillis(uint64_t heard_millis) {
#endif
#endif
#if COMPANION_FEATURE_JOHN
#include "JohnReaderScreen.h"
#if COMPANION_FEATURE_READER
#include "ReaderScreen.h"
#include <new>
#endif
@@ -575,7 +575,7 @@ public:
}
void showFirstPage() { _page = HomePage::FIRST; }
#if COMPANION_FEATURE_JOHN
#if COMPANION_FEATURE_READER
bool isRadioPage() const { return _page == HomePage::RADIO; }
#endif
@@ -1169,9 +1169,9 @@ public:
_page = (_page + HomePage::Count - 1) % HomePage::Count;
return true;
}
#if COMPANION_FEATURE_JOHN
#if COMPANION_FEATURE_READER
if (key == KEY_ENTER && _page == HomePage::RADIO) {
_task->showJohnReader();
_task->showReader();
return true;
}
#endif
@@ -1823,17 +1823,17 @@ void UITask::showMessages() {
setCurrScreen(msg_preview);
}
#if COMPANION_FEATURE_JOHN
void UITask::showJohnReader() {
#if COMPANION_FEATURE_READER
void UITask::showReader() {
if (!_display || isPairingScreenActive()) return;
if (!_display->isOn()) _display->wake(mesh::ui::DisplayWake::Button);
if (!john_reader) john_reader = new (std::nothrow) JohnReaderScreen(this, _display);
if (!john_reader) { showAlert("Reader: no memory", 1500); return; }
static_cast<JohnReaderScreen*>(john_reader)->open();
setCurrScreen(john_reader);
if (!reader) reader = new (std::nothrow) ReaderScreen(this, _display);
if (!reader) { showAlert("Reader: no memory", 1500); return; }
static_cast<ReaderScreen*>(reader)->open();
setCurrScreen(reader);
}
void UITask::closeJohnReader() {
void UITask::closeReader() {
// Home retains the selected radio page while the reader is open.
setCurrScreen(home);
}
@@ -1911,8 +1911,8 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text,
// pairing completes or the pairing display window expires.
_deferred_msg_preview = true;
}
#if COMPANION_FEATURE_JOHN
else if (isJohnReaderActive()) {
#if COMPANION_FEATURE_READER
else if (isReaderActive()) {
// Queue incoming messages without stealing the reader's page.
_deferred_msg_preview = true;
}
@@ -1951,9 +1951,9 @@ void UITask::userLedHandler() {
}
void UITask::setCurrScreen(UIScreen* c) {
#if COMPANION_FEATURE_JOHN
if (isJohnReaderActive() && c != john_reader
&& !static_cast<JohnReaderScreen*>(john_reader)->flush()) {
#if COMPANION_FEATURE_READER
if (isReaderActive() && c != reader
&& !static_cast<ReaderScreen*>(reader)->flush()) {
showAlert("Bookmark save failed", 1500);
}
#endif
@@ -2033,9 +2033,9 @@ void UITask::servicePairingState() {
_board->isExternalPowered() || _board->isUsbHostConnected(),
hasConnection(), isPairingScreenActive())) {
_next_refresh = 0;
#if COMPANION_FEATURE_JOHN
if (!_display->isOn() && isJohnReaderActive())
static_cast<JohnReaderScreen*>(john_reader)->flush();
#if COMPANION_FEATURE_READER
if (!_display->isOn() && isReaderActive())
static_cast<ReaderScreen*>(reader)->flush();
#endif
}
}
@@ -2045,8 +2045,8 @@ void UITask::servicePairingState() {
*/
void UITask::shutdown(bool restart){
if (!prepareForShutdown()) return;
#if COMPANION_FEATURE_JOHN
if (john_reader) static_cast<JohnReaderScreen*>(john_reader)->flush();
#if COMPANION_FEATURE_READER
if (reader) static_cast<ReaderScreen*>(reader)->flush();
#endif
#ifdef PIN_BUZZER
@@ -2126,8 +2126,8 @@ void UITask::loop() {
if (ev == BUTTON_EVENT_CLICK) {
c = checkDisplayOn(KEY_ENTER);
} else if (ev == BUTTON_EVENT_LONG_PRESS) {
#if COMPANION_FEATURE_JOHN
if (isJohnReaderActive() || (curr == home && static_cast<HomeScreen*>(home)->isRadioPage()))
#if COMPANION_FEATURE_READER
if (isReaderActive() || (curr == home && static_cast<HomeScreen*>(home)->isRadioPage()))
c = handleLongPress(KEY_ENTER);
else
#endif
@@ -2277,8 +2277,8 @@ void UITask::loop() {
#endif
if (curr) curr->poll();
#if COMPANION_FEATURE_JOHN
if (john_reader && curr != john_reader) john_reader->poll();
#if COMPANION_FEATURE_READER
if (reader && curr != reader) reader->poll();
#endif
if (_display != NULL && _display->isOn()) {
@@ -2372,9 +2372,9 @@ void UITask::getTouchControls(mesh::ui::TouchSplitSelector& transport_touch_sele
#if UI_READER_TOUCH_BAR
if (curr == msg_preview)
reader_touch_bar = static_cast<MsgPreviewScreen*>(msg_preview)->readerTouchBar();
#if COMPANION_FEATURE_JOHN
else if (isJohnReaderActive())
reader_touch_bar = static_cast<JohnReaderScreen*>(john_reader)->readerTouchBar();
#if COMPANION_FEATURE_READER
else if (isReaderActive())
reader_touch_bar = static_cast<ReaderScreen*>(reader)->readerTouchBar();
#endif
#endif
}
@@ -2396,12 +2396,12 @@ char UITask::handleLongPress(char c) {
// Exit an incoming message preview even during the startup rescue window.
// The on-screen reader hint must not unexpectedly enter CLI rescue.
if (curr == msg_preview) return c;
#if COMPANION_FEATURE_JOHN
#if COMPANION_FEATURE_READER
// The radio page's reader gesture, including exit, takes precedence over
// the global early-boot rescue gesture just like the WiFi setup page.
if (isJohnReaderActive()) { closeJohnReader(); return 0; }
if (isReaderActive()) { closeReader(); return 0; }
if (curr == home && static_cast<HomeScreen*>(home)->isRadioPage()) {
showJohnReader();
showReader();
return 0;
}
#endif
@@ -2428,8 +2428,8 @@ char UITask::handleDoubleClick(char c) {
char UITask::handleMultiClick(char c, bool backwards) {
MESH_DEBUG_PRINTLN("UITask: %s-click triggered", backwards ? "quadruple" : "triple");
if (curr == msg_preview
#if COMPANION_FEATURE_JOHN
|| isJohnReaderActive()
#if COMPANION_FEATURE_READER
|| isReaderActive()
#endif
) {
return checkDisplayOn(backwards ? KEY_UP : KEY_DOWN);
+7 -7
View File
@@ -24,7 +24,7 @@
#include "../AbstractUITask.h"
#include "../NodePrefs.h"
#include <helpers/CompanionJohnConfig.h>
#include <helpers/CompanionReaderConfig.h>
class UITask : public AbstractUITask {
DisplayDriver* _display;
@@ -94,8 +94,8 @@ class UITask : public AbstractUITask {
UIScreen* home;
UIScreen* msg_preview = nullptr;
UIScreen* curr;
#if COMPANION_FEATURE_JOHN
UIScreen* john_reader = nullptr;
#if COMPANION_FEATURE_READER
UIScreen* reader = nullptr;
#endif
void userLedHandler();
@@ -132,10 +132,10 @@ public:
void gotoHomeScreen() { setCurrScreen(home); }
void showMessages();
#if COMPANION_FEATURE_JOHN
bool isJohnReaderActive() const { return john_reader && curr == john_reader; }
void showJohnReader();
void closeJohnReader();
#if COMPANION_FEATURE_READER
bool isReaderActive() const { return reader && curr == reader; }
void showReader();
void closeReader();
#endif
void showAlert(const char* text, int duration_millis);
int getMsgCount() const { return _msgcount; }