mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
feat(companion): delete saved presets, align app-driven repeat with on-device toggle
- Radio Preset popup: "+ Save current..." moved to the top of the list; add "- Delete preset..." (shown only when a saved preset exists) which opens a sub-list of just the saved presets and clears the picked slot. - CMD_SET_RADIO_PARAMS no longer requires repeat=1 to land on one of the three dedicated repeat_freq_ranges bands — none of the 16 built-in presets matched those exactly, so app-driven repeat would either get rejected or silently retune away from the user's chosen frequency. Commented out (not deleted) so the old behaviour can be restored if needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1818,9 +1818,15 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
repeat = cmd_frame[i++]; // FIRMWARE_VER_CODE 9+
|
||||
}
|
||||
|
||||
if (repeat && !isValidClientRepeatFreq(freq)) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
} else if (freq >= 150000 && freq <= 2500000 && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7000 &&
|
||||
// Dedicated-band requirement for app-driven repeat disabled, to match the
|
||||
// on-device Repeater toggle (Settings > Radio), which repeats on whatever
|
||||
// frequency is already set with no band restriction. Uncomment to restore
|
||||
// the old behaviour (repeat=1 only accepted on repeat_freq_ranges, i.e.
|
||||
// 433.000/869.495/918.000 MHz exactly, by default).
|
||||
// if (repeat && !isValidClientRepeatFreq(freq)) {
|
||||
// writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
// } else
|
||||
if (freq >= 150000 && freq <= 2500000 && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7000 &&
|
||||
bw <= 500000) {
|
||||
_prefs.sf = sf;
|
||||
_prefs.cr = cr;
|
||||
|
||||
@@ -140,16 +140,16 @@ class SettingsScreen : public UIScreen {
|
||||
}
|
||||
|
||||
// Position of the current settings within the popup list built by
|
||||
// openPresetMenu() below (built-ins first, then non-empty user slots in
|
||||
// slot order) — or -1 ("Custom") if nothing matches.
|
||||
// openPresetMenu() below ("Save current..." at 0, then built-ins, then
|
||||
// non-empty user slots in slot order) — or -1 ("Custom") if nothing matches.
|
||||
int currentPresetListIndex() {
|
||||
NodePrefs* p = _task->getNodePrefs();
|
||||
if (!p) return -1;
|
||||
for (int i = 0; i < RADIO_PRESET_COUNT; i++) {
|
||||
const RadioPreset& r = RADIO_PRESETS[i];
|
||||
if (matchesPreset(p, r.freq, r.bw, r.sf, r.cr)) return i;
|
||||
if (matchesPreset(p, r.freq, r.bw, r.sf, r.cr)) return i + 1;
|
||||
}
|
||||
int pos = RADIO_PRESET_COUNT;
|
||||
int pos = RADIO_PRESET_COUNT + 1;
|
||||
for (int i = 0; i < NodePrefs::USER_RADIO_PRESET_MAX; i++) {
|
||||
const auto& u = p->user_radio_presets[i];
|
||||
if (!u.name[0]) continue;
|
||||
@@ -716,11 +716,16 @@ class SettingsScreen : public UIScreen {
|
||||
// NodePrefs::user_radio_presets (empty slots are skipped when building the list).
|
||||
uint8_t _preset_user_slot[NodePrefs::USER_RADIO_PRESET_MAX];
|
||||
int _preset_user_count = 0;
|
||||
bool _preset_saving = false; // _kb is open to name a new preset, not a msg slot
|
||||
bool _preset_saving = false; // _kb is open to name a new preset, not a msg slot
|
||||
bool _preset_deleting = false; // _preset_menu is showing the delete sub-list
|
||||
|
||||
// Layout: [0]="+ Save current...", [1..RADIO_PRESET_COUNT]=built-ins,
|
||||
// [..+_preset_user_count]=saved user presets, ["- Delete preset..." if any].
|
||||
void openPresetMenu() {
|
||||
NodePrefs* p = _task->getNodePrefs();
|
||||
_preset_deleting = false;
|
||||
_preset_menu.begin("Radio Preset", 6);
|
||||
_preset_menu.addItem("+ Save current...");
|
||||
for (int i = 0; i < RADIO_PRESET_COUNT; i++) _preset_menu.addItem(RADIO_PRESETS[i].name);
|
||||
_preset_user_count = 0;
|
||||
if (p) {
|
||||
@@ -730,11 +735,22 @@ class SettingsScreen : public UIScreen {
|
||||
_preset_user_slot[_preset_user_count++] = (uint8_t)i;
|
||||
}
|
||||
}
|
||||
_preset_menu.addItem("+ Save current...");
|
||||
if (_preset_user_count > 0) _preset_menu.addItem("- Delete preset...");
|
||||
int idx = currentPresetListIndex();
|
||||
_preset_menu.setSelected(idx >= 0 ? idx : 0);
|
||||
}
|
||||
|
||||
// Reuses _preset_menu for a second-level list of just the saved user presets
|
||||
// (their slot mapping in _preset_user_slot is still the one openPresetMenu()
|
||||
// just built, since this is only reached from within that same popup).
|
||||
void openDeletePresetMenu() {
|
||||
NodePrefs* p = _task->getNodePrefs();
|
||||
_preset_menu.begin("Delete Preset", 6);
|
||||
for (int i = 0; i < _preset_user_count; i++)
|
||||
_preset_menu.addItem(p->user_radio_presets[_preset_user_slot[i]].name);
|
||||
_preset_deleting = true;
|
||||
}
|
||||
|
||||
public:
|
||||
SettingsScreen(UITask* task, KeyboardWidget* kb)
|
||||
: _task(task), _kb(kb), _selected(SECTION_DISPLAY), _scroll(0), _visible(4), _dirty(false), _edit_slot(-1) {
|
||||
@@ -806,27 +822,42 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Radio preset popup
|
||||
// Radio preset popup (and its "delete a saved preset" sub-list)
|
||||
if (_preset_menu.active) {
|
||||
auto res = _preset_menu.handleInput(c);
|
||||
if (res == PopupMenu::SELECTED && p) {
|
||||
int idx = _preset_menu.selectedIndex();
|
||||
int user_base = RADIO_PRESET_COUNT;
|
||||
int save_idx = RADIO_PRESET_COUNT + _preset_user_count;
|
||||
if (idx >= 0 && idx < user_base) {
|
||||
const RadioPreset& r = RADIO_PRESETS[idx];
|
||||
p->freq = r.freq; p->bw = r.bw; p->sf = r.sf; p->cr = r.cr;
|
||||
_task->applyRadioParams();
|
||||
_dirty = true;
|
||||
} else if (idx >= user_base && idx < save_idx) {
|
||||
const NodePrefs::UserRadioPreset& u = p->user_radio_presets[_preset_user_slot[idx - user_base]];
|
||||
p->freq = u.freq; p->bw = u.bw; p->sf = u.sf; p->cr = u.cr;
|
||||
_task->applyRadioParams();
|
||||
_dirty = true;
|
||||
} else if (idx == save_idx) {
|
||||
_preset_saving = true;
|
||||
_kb->begin("", (int)sizeof(p->user_radio_presets[0].name) - 1);
|
||||
if (_preset_deleting) {
|
||||
if (idx >= 0 && idx < _preset_user_count) {
|
||||
p->user_radio_presets[_preset_user_slot[idx]].name[0] = '\0';
|
||||
_dirty = true;
|
||||
_task->showAlert("Preset deleted", 800);
|
||||
}
|
||||
_preset_deleting = false;
|
||||
} else {
|
||||
int save_idx = 0;
|
||||
int builtin_base = 1;
|
||||
int user_base = builtin_base + RADIO_PRESET_COUNT;
|
||||
int delete_idx = user_base + _preset_user_count;
|
||||
if (idx == save_idx) {
|
||||
_preset_saving = true;
|
||||
_kb->begin("", (int)sizeof(p->user_radio_presets[0].name) - 1);
|
||||
} else if (idx >= builtin_base && idx < user_base) {
|
||||
const RadioPreset& r = RADIO_PRESETS[idx - builtin_base];
|
||||
p->freq = r.freq; p->bw = r.bw; p->sf = r.sf; p->cr = r.cr;
|
||||
_task->applyRadioParams();
|
||||
_dirty = true;
|
||||
} else if (idx >= user_base && idx < delete_idx) {
|
||||
const NodePrefs::UserRadioPreset& u = p->user_radio_presets[_preset_user_slot[idx - user_base]];
|
||||
p->freq = u.freq; p->bw = u.bw; p->sf = u.sf; p->cr = u.cr;
|
||||
_task->applyRadioParams();
|
||||
_dirty = true;
|
||||
} else if (_preset_user_count > 0 && idx == delete_idx) {
|
||||
openDeletePresetMenu();
|
||||
}
|
||||
}
|
||||
} else if (res == PopupMenu::CANCELLED) {
|
||||
_preset_deleting = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user