mirror of
https://github.com/ratspeak/ratdeck.git
synced 2026-03-30 14:15:39 +00:00
Stamp incoming messages with receiver time, radio-style freq editor
Timestamps: Incoming messages with invalid sender timestamps (< Nov 2023 epoch) are now stamped with the receiver's local time if available. Previously, messages from devices without NTP/GPS showed no timestamp at all. Frequency editor: Replace raw 9-digit Hz accumulator with a radio-style digit cursor. Display shows NNN.NNN.NNN format with bracket cursor on active digit (e.g., "920.[6]50.500"). Trackball left/right moves cursor, digit keys replace at cursor and advance. Esc restores original value. Matches amateur radio transceiver UX.
This commit is contained in:
@@ -309,6 +309,11 @@ void LXMFManager::processIncoming(const uint8_t* data, size_t len, const RNS::By
|
||||
if (destHash.size() > 0) {
|
||||
msg.destHash = destHash;
|
||||
}
|
||||
// Stamp with receiver's local time if sender's timestamp is missing/invalid
|
||||
if (msg.timestamp < 1700000000) {
|
||||
time_t now = time(nullptr);
|
||||
if (now > 1700000000) msg.timestamp = (double)now;
|
||||
}
|
||||
Serial.printf("[LXMF] Message from %s (%d bytes) content_len=%d\n",
|
||||
msg.sourceHash.toHex().substr(0, 8).c_str(), (int)len, (int)msg.content.size());
|
||||
if (_store) { _store->saveMessage(msg); }
|
||||
|
||||
@@ -810,7 +810,10 @@ void LvSettingsScreen::rebuildItemList() {
|
||||
String valStr;
|
||||
uint32_t valColor = Theme::PRIMARY;
|
||||
|
||||
if (_editing && selected) {
|
||||
if (_freqEditing && selected) {
|
||||
valStr = String("< ") + freqFormatWithCursor() + " >";
|
||||
valColor = Theme::WARNING_CLR;
|
||||
} else if (_editing && selected) {
|
||||
if (item.type == SettingType::ENUM_CHOICE && !item.enumLabels.empty()) {
|
||||
int vi = constrain(_editValue, 0, (int)item.enumLabels.size() - 1);
|
||||
valStr = String("< ") + item.enumLabels[vi] + " >";
|
||||
@@ -1055,6 +1058,41 @@ bool LvSettingsScreen::handleKey(const KeyEvent& event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Frequency digit-cursor edit mode
|
||||
if (_freqEditing) {
|
||||
if (event.left) {
|
||||
if (_freqCursor > 0) _freqCursor--;
|
||||
rebuildItemList(); return true;
|
||||
}
|
||||
if (event.right) {
|
||||
if (_freqCursor < 8) _freqCursor++;
|
||||
rebuildItemList(); return true;
|
||||
}
|
||||
if (event.character >= '0' && event.character <= '9') {
|
||||
_freqDigits[_freqCursor] = event.character - '0';
|
||||
_editValue = freqRecompose();
|
||||
if (_freqCursor < 8) _freqCursor++;
|
||||
rebuildItemList(); return true;
|
||||
}
|
||||
if (event.enter || event.character == '\n' || event.character == '\r') {
|
||||
auto& item = _items[_selectedIdx];
|
||||
_editValue = freqRecompose();
|
||||
if (item.setter) item.setter(_editValue);
|
||||
_freqEditing = false; _editing = false;
|
||||
applyAndSave(); rebuildItemList(); return true;
|
||||
}
|
||||
if (event.del || event.character == 8) {
|
||||
if (_freqCursor > 0) _freqCursor--;
|
||||
rebuildItemList(); return true;
|
||||
}
|
||||
if (event.character == 0x1B) {
|
||||
_editValue = _freqOriginal;
|
||||
_freqEditing = false; _editing = false;
|
||||
rebuildItemList(); return true;
|
||||
}
|
||||
return true; // Consume all keys in freq mode
|
||||
}
|
||||
|
||||
// Value edit mode
|
||||
if (_editing) {
|
||||
auto& item = _items[_selectedIdx];
|
||||
@@ -1148,6 +1186,15 @@ bool LvSettingsScreen::handleKey(const KeyEvent& event) {
|
||||
if (item.setter) item.setter(val ? 0 : 1);
|
||||
applyAndSave();
|
||||
rebuildItemList();
|
||||
} else if (strcmp(item.label, "Frequency") == 0 && item.type == SettingType::INTEGER) {
|
||||
// Radio-style digit cursor editor for frequency
|
||||
_editing = true;
|
||||
_editValue = item.getter ? item.getter() : 0;
|
||||
_freqOriginal = _editValue;
|
||||
freqDecompose(_editValue);
|
||||
_freqCursor = 0;
|
||||
_freqEditing = true;
|
||||
rebuildItemList();
|
||||
} else {
|
||||
_editing = true;
|
||||
_numericTyping = false;
|
||||
@@ -1230,6 +1277,44 @@ bool LvSettingsScreen::tcpSettingsChanged() const {
|
||||
return curHost != _tcpSnapHost || curPort != _tcpSnapPort;
|
||||
}
|
||||
|
||||
// --- Frequency digit-cursor editor helpers ---
|
||||
|
||||
void LvSettingsScreen::freqDecompose(int value) {
|
||||
// Decompose Hz value into 9 individual digits (left-padded with zeros)
|
||||
for (int i = 8; i >= 0; i--) {
|
||||
_freqDigits[i] = value % 10;
|
||||
value /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
int LvSettingsScreen::freqRecompose() const {
|
||||
int val = 0;
|
||||
for (int i = 0; i < 9; i++) val = val * 10 + _freqDigits[i];
|
||||
return val;
|
||||
}
|
||||
|
||||
String LvSettingsScreen::freqFormatWithCursor() const {
|
||||
// Format as "NNN.NNN.NNN" with brackets around cursor digit
|
||||
char buf[24];
|
||||
char digits[9];
|
||||
for (int i = 0; i < 9; i++) digits[i] = '0' + _freqDigits[i];
|
||||
|
||||
// Build string with cursor brackets: e.g., "920.[6]50.500"
|
||||
int pos = 0;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
if (i == 3 || i == 6) buf[pos++] = '.';
|
||||
if (i == _freqCursor) {
|
||||
buf[pos++] = '[';
|
||||
buf[pos++] = digits[i];
|
||||
buf[pos++] = ']';
|
||||
} else {
|
||||
buf[pos++] = digits[i];
|
||||
}
|
||||
}
|
||||
buf[pos] = '\0';
|
||||
return String(buf);
|
||||
}
|
||||
|
||||
void LvSettingsScreen::applyAndSave() {
|
||||
if (!_cfg) return;
|
||||
auto& s = _cfg->settings();
|
||||
|
||||
@@ -135,6 +135,15 @@ private:
|
||||
bool _confirmingReset = false;
|
||||
bool _confirmingDevMode = false;
|
||||
|
||||
// Frequency digit-cursor editor (radio-style)
|
||||
bool _freqEditing = false;
|
||||
int _freqCursor = 0; // 0-8, active digit position
|
||||
int _freqDigits[9] = {}; // Individual digits of Hz frequency
|
||||
int _freqOriginal = 0; // Original value for Esc cancel
|
||||
void freqDecompose(int value);
|
||||
int freqRecompose() const;
|
||||
String freqFormatWithCursor() const;
|
||||
|
||||
// WiFi picker
|
||||
std::vector<WiFiInterface::ScanResult> _wifiResults;
|
||||
int _wifiPickerIdx = 0;
|
||||
|
||||
Reference in New Issue
Block a user