Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion Meshtastic/Enums/LoraConfigEnums.swift
Original file line number Diff line number Diff line change
Expand Up @@ -525,12 +525,24 @@ enum ModemPresets: Int, CaseIterable, Identifiable {
}
}

/// Presets deprecated upstream that must no longer be offered for new selection,
/// mirroring how Android filters them out. They remain as cases so a radio already
/// configured on one round-trips through protobuf and renders the correct label.
var isDeprecated: Bool {
switch self {
case .longSlow:
return true
default:
return false
}
}

/// Presets selectable for a connected device, given whether its firmware
/// implements the 2.8 rework. On older firmware the 2.8-only presets are
/// dropped. Callers should additionally constrain this to the selected
/// region's legal set via `RegionPresetInfo` when the firmware provides one.
static func selectable(supports2_8: Bool) -> [ModemPresets] {
allCases.filter { supports2_8 || !$0.requiresFirmware2_8 }
allCases.filter { !$0.isDeprecated && (supports2_8 || !$0.requiresFirmware2_8) }
}

/// The conservative (pre-2.8) selectable set. Retained for callers that have
Expand Down
10 changes: 8 additions & 2 deletions Meshtastic/Views/Settings/Config/LoRaConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,17 @@ struct LoRaConfig: View {
/// one. Never empty (spec §6 — never show an empty picker).
private var availablePresets: [ModemPresets] {
let base = ModemPresets.selectable(supports2_8: supports2_8)
var presets = base
if let info = regionPresetInfo, !info.presets.isEmpty {
let constrained = base.filter { info.presets.contains($0.protoEnumValue()) }
if !constrained.isEmpty { return constrained }
if !constrained.isEmpty { presets = constrained }
}
return base
// Keep a currently-configured but deprecated preset (e.g. Long Slow on an existing
// radio) visible so the picker doesn't render a blank selection.
if let current = ModemPresets(rawValue: modemPreset), current.isDeprecated, !presets.contains(current) {
presets.append(current)
}
return presets
}

var body: some View {
Expand Down
14 changes: 14 additions & 0 deletions MeshtasticTests/LoraDeviceEnumTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,20 @@ struct LoRaFirmwareGatingTests {
#expect(selectable.contains(.tinyFast))
#expect(selectable.contains(.liteSlow))
}

@Test func deprecatedPreset_excludedFromSelectable() {
#expect(ModemPresets.longSlow.isDeprecated)
#expect(!ModemPresets.selectable(supports2_8: false).contains(.longSlow))
#expect(!ModemPresets.selectable(supports2_8: true).contains(.longSlow))
#expect(!ModemPresets.userSelectable.contains(.longSlow))
}

@Test func deprecatedPreset_stillExistsForDisplay() {
// longSlow remains a case so an existing radio's value round-trips and renders its label.
let preset = ModemPresets(rawValue: 1)
#expect(preset == .longSlow)
#expect(preset?.name == "LongSlow")
}
}

// MARK: - LoRaRegionPresetMap decoding (2.8 region→preset compatibility)
Expand Down
Loading