diff --git a/Meshtastic/Model/ConfigModels.swift b/Meshtastic/Model/ConfigModels.swift index b3c3a4921..0debb5ab6 100644 --- a/Meshtastic/Model/ConfigModels.swift +++ b/Meshtastic/Model/ConfigModels.swift @@ -47,6 +47,9 @@ final class BluetoothConfigEntity { @Model final class CannedMessageConfigEntity { + /// Deprecated (no successor, removed from active use — #2021). Retained as a stored + /// SwiftData property to preserve the schema and keep existing persisted values readable; + /// it is no longer surfaced in the UI, read, or actively written by app code. var enabled: Bool = false var inputbrokerEventCcw: Int32 = 0 var inputbrokerEventCw: Int32 = 0 diff --git a/Meshtastic/Persistence/CoreDataMigrationService.swift b/Meshtastic/Persistence/CoreDataMigrationService.swift index ed74abc7e..78550d658 100644 --- a/Meshtastic/Persistence/CoreDataMigrationService.swift +++ b/Meshtastic/Persistence/CoreDataMigrationService.swift @@ -477,7 +477,8 @@ private extension CoreDataMigrationService { nodeMap: nodeMap ) { obj -> CannedMessageConfigEntity in let sd = CannedMessageConfigEntity() - sd.enabled = (obj.value(forKey: "enabled") as? Bool) ?? false + // enabled is deprecated (no successor) and no longer written — not migrated; the + // stored property keeps its default. (#2021) sd.inputbrokerEventCcw = (obj.value(forKey: "inputbrokerEventCcw") as? Int32) ?? 0 sd.inputbrokerEventCw = (obj.value(forKey: "inputbrokerEventCw") as? Int32) ?? 0 sd.inputbrokerEventPress = (obj.value(forKey: "inputbrokerEventPress") as? Int32) ?? 0 diff --git a/Meshtastic/Persistence/UpdateSwiftData.swift b/Meshtastic/Persistence/UpdateSwiftData.swift index c566203e9..23c5f7b41 100644 --- a/Meshtastic/Persistence/UpdateSwiftData.swift +++ b/Meshtastic/Persistence/UpdateSwiftData.swift @@ -1251,7 +1251,8 @@ extension MeshPackets { if fetchedNode[0].cannedMessageConfig == nil { let newCannedMessageConfig = CannedMessageConfigEntity() modelContext.insert(newCannedMessageConfig) - newCannedMessageConfig.enabled = config.enabled + // config.enabled is deprecated (no successor, removed from active use); + // tolerated on read but no longer written to the stored entity. (#2021) newCannedMessageConfig.sendBell = config.sendBell newCannedMessageConfig.rotary1Enabled = config.rotary1Enabled newCannedMessageConfig.updown1Enabled = config.updown1Enabled @@ -1263,7 +1264,7 @@ extension MeshPackets { newCannedMessageConfig.inputbrokerEventPress = Int32(config.inputbrokerEventPress.rawValue) fetchedNode[0].cannedMessageConfig = newCannedMessageConfig } else { - fetchedNode[0].cannedMessageConfig?.enabled = config.enabled + // config.enabled is deprecated (see above); no longer written. (#2021) fetchedNode[0].cannedMessageConfig?.sendBell = config.sendBell fetchedNode[0].cannedMessageConfig?.rotary1Enabled = config.rotary1Enabled fetchedNode[0].cannedMessageConfig?.updown1Enabled = config.updown1Enabled diff --git a/Meshtastic/Resources/docs/developer/swiftdata.html b/Meshtastic/Resources/docs/developer/swiftdata.html index d91badf3d..d0bcc8e57 100644 --- a/Meshtastic/Resources/docs/developer/swiftdata.html +++ b/Meshtastic/Resources/docs/developer/swiftdata.html @@ -173,6 +173,29 @@

Adding a New Schema Version

  • Update MeshtasticSchema.current to point to the new version.
  • Warning — Never delete a VersionedSchema. Migration history must be preserved or the migration plan will fail on devices that skipped intermediate versions.
    +

    Deprecated Properties

    +

    When a proto field is deprecated upstream and the app stops using it, do not remove the corresponding @Model property — deleting a stored property is a schema change that would require a migration, and while V1 is unreleased there is nowhere to migrate from. Instead, retain the property as-is so:

    + +

    The field simply stops being surfaced in the UI, read, or actively written by app code. Mark it with a doc comment noting the deprecation and the tracking issue. Current examples:

    + + + + + + + + + + + + + + + +
    ModelPropertyNotes
    CannedMessageConfigEntityenabled#2021 — no successor; retained for schema/value compatibility, no longer read or written

    Query Helpers

    QuerySwiftData.swift contains helper functions for common fetches:

    let node = getNodeInfo(id: nodeNum, context: context)
    diff --git a/Meshtastic/Resources/docs/index.json b/Meshtastic/Resources/docs/index.json
    index 0cd9d182d..46879116b 100644
    --- a/Meshtastic/Resources/docs/index.json
    +++ b/Meshtastic/Resources/docs/index.json
    @@ -1025,20 +1025,20 @@
                 "node",
                 "stats",
                 "simctl",
    +            "model",
                 "local",
                 "nodes",
    +            "app",
                 "store",
    -            "model",
    +            "schema",
                 "context",
                 "packet",
                 "history",
                 "data",
                 "child",
    -            "app",
                 "swift",
    -            "schema",
    -            "launch",
                 "device",
    +            "launch",
                 "var",
                 "true",
                 "telemetry",
    @@ -1050,7 +1050,7 @@
                 "type",
                 "set"
             ],
    -        "charCount": 11360
    +        "charCount": 12115
         },
         {
             "id": "tak-protocol",
    diff --git a/Meshtastic/Resources/docs/markdown/developer/swiftdata.md b/Meshtastic/Resources/docs/markdown/developer/swiftdata.md
    index 16bab1304..3e8fc27dc 100644
    --- a/Meshtastic/Resources/docs/markdown/developer/swiftdata.md
    +++ b/Meshtastic/Resources/docs/markdown/developer/swiftdata.md
    @@ -157,6 +157,19 @@ static let migrateV1toV2 = MigrationStage.custom(
     
     > **Warning — Never delete a `VersionedSchema`.** Migration history must be preserved or the migration plan will fail on devices that skipped intermediate versions.
     
    +### Deprecated Properties
    +
    +When a proto field is deprecated upstream and the app stops using it, **do not remove the corresponding `@Model` property** — deleting a stored property is a schema change that would require a migration, and while V1 is unreleased there is nowhere to migrate from. Instead, retain the property as-is so:
    +
    +- the SwiftData schema is unchanged, and
    +- any values already persisted on-device remain readable.
    +
    +The field simply stops being surfaced in the UI, read, or actively written by app code. Mark it with a doc comment noting the deprecation and the tracking issue. Current examples:
    +
    +| Model | Property | Notes |
    +|-------|----------|-------|
    +| `CannedMessageConfigEntity` | `enabled` | #2021 — no successor; retained for schema/value compatibility, no longer read or written |
    +
     ## Query Helpers
     
     `QuerySwiftData.swift` contains helper functions for common fetches:
    diff --git a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift
    index 9e96a54bb..02d3a514c 100644
    --- a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift
    +++ b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift
    @@ -17,7 +17,6 @@ struct CannedMessagesConfig: View {
     	@State var hasChanges = false
     	@State var hasMessagesChanges = false
     	@State var configPreset = 0
    -	@State var enabled = false
     	/// CannedMessageModule will sends a bell character with the messages.
     	@State var sendBell: Bool = false
     	/// Enable the rotary encoder #1. This is a 'dumb' encoder sending pulses on both A and B pins while rotating.
    @@ -43,12 +42,6 @@ struct CannedMessagesConfig: View {
     			
     			Section(header: Text("Options")) {
     				
    -				Toggle(isOn: $enabled) {
    -					
    -					Label("Enabled", systemImage: "list.bullet.rectangle.fill")
    -				}
    -				.tint(.accentColor)
    -				
     				Toggle(isOn: $sendBell) {
     					
     					Label("Send Bell", systemImage: "bell")
    @@ -184,7 +177,8 @@ struct CannedMessagesConfig: View {
     						dismiss: goBack
     					) { fromUser, toUser in
     						var cmc = ModuleConfig.CannedMessageConfig()
    -						cmc.enabled = enabled
    +						// enabled is deprecated with no successor and removed from active
    +						// use — intentionally not written. (#2021)
     						cmc.sendBell = sendBell
     						cmc.rotary1Enabled = rotary1Enabled
     						cmc.updown1Enabled = updown1Enabled
    @@ -265,9 +259,6 @@ struct CannedMessagesConfig: View {
     			
     			hasChanges = true
     		}
    -		.onChange(of: enabled) { _, newEnabled in
    -			if newEnabled != node?.cannedMessageConfig?.enabled { hasChanges = true }
    -		}
     		.onChange(of: sendBell) { _, newSendBell in
     			if newSendBell != node?.cannedMessageConfig?.sendBell { hasChanges = true }
     		}
    @@ -297,7 +288,6 @@ struct CannedMessagesConfig: View {
     		}
     	}
     	func setCannedMessagesValues() {
    -		self.enabled = node?.cannedMessageConfig?.enabled ?? false
     		self.sendBell = node?.cannedMessageConfig?.sendBell ?? false
     		self.rotary1Enabled = node?.cannedMessageConfig?.rotary1Enabled ?? false
     		self.updown1Enabled = node?.cannedMessageConfig?.updown1Enabled ?? false
    diff --git a/docs/developer/swiftdata.md b/docs/developer/swiftdata.md
    index 16bab1304..3e8fc27dc 100644
    --- a/docs/developer/swiftdata.md
    +++ b/docs/developer/swiftdata.md
    @@ -157,6 +157,19 @@ static let migrateV1toV2 = MigrationStage.custom(
     
     > **Warning — Never delete a `VersionedSchema`.** Migration history must be preserved or the migration plan will fail on devices that skipped intermediate versions.
     
    +### Deprecated Properties
    +
    +When a proto field is deprecated upstream and the app stops using it, **do not remove the corresponding `@Model` property** — deleting a stored property is a schema change that would require a migration, and while V1 is unreleased there is nowhere to migrate from. Instead, retain the property as-is so:
    +
    +- the SwiftData schema is unchanged, and
    +- any values already persisted on-device remain readable.
    +
    +The field simply stops being surfaced in the UI, read, or actively written by app code. Mark it with a doc comment noting the deprecation and the tracking issue. Current examples:
    +
    +| Model | Property | Notes |
    +|-------|----------|-------|
    +| `CannedMessageConfigEntity` | `enabled` | #2021 — no successor; retained for schema/value compatibility, no longer read or written |
    +
     ## Query Helpers
     
     `QuerySwiftData.swift` contains helper functions for common fetches: