mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Channel display fix
This commit is contained in:
parent
ed9605a4c1
commit
a6e7a2a803
3 changed files with 64 additions and 9 deletions
|
|
@ -218,7 +218,18 @@ extension AccessoryManager {
|
|||
do {
|
||||
let fetchedMyInfo = try context.fetch(fetchMyInfoRequest)
|
||||
if fetchedMyInfo.count == 1 {
|
||||
let channelsToDelete = fetchedMyInfo[0].channels
|
||||
for channel in channelsToDelete {
|
||||
context.delete(channel)
|
||||
}
|
||||
fetchedMyInfo[0].channels.removeAll()
|
||||
|
||||
// Clean orphaned channels from older app versions where channels were
|
||||
// detached but not deleted, which can create duplicate rows in queries.
|
||||
let allChannels = try context.fetch(FetchDescriptor<ChannelEntity>())
|
||||
for channel in allChannels where channel.myInfoChannel == nil {
|
||||
context.delete(channel)
|
||||
}
|
||||
do {
|
||||
try context.save()
|
||||
} catch {
|
||||
|
|
|
|||
|
|
@ -22,8 +22,19 @@ struct ChannelList: View {
|
|||
|
||||
var restrictedChannels = ["gpio", "mqtt", "serial", "admin"]
|
||||
|
||||
@Query(sort: \ChannelEntity.index)
|
||||
private var channels: [ChannelEntity]
|
||||
private var visibleChannels: [ChannelEntity] {
|
||||
guard let myInfo = node?.myInfo else { return [] }
|
||||
|
||||
var channelsByIndex: [Int32: ChannelEntity] = [:]
|
||||
for channel in myInfo.channels {
|
||||
channelsByIndex[channel.index] = channel
|
||||
}
|
||||
|
||||
return channelsByIndex
|
||||
.values
|
||||
.filter { !restrictedChannels.contains($0.name?.lowercased() ?? "") }
|
||||
.sorted { $0.index < $1.index }
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func makeChannelRow(
|
||||
|
|
@ -170,10 +181,8 @@ struct ChannelList: View {
|
|||
// Display Contacts for the rest of the non admin channels
|
||||
if let node, let myInfo = node.myInfo {
|
||||
List(selection: $channelSelection) {
|
||||
ForEach(channels) { (channel: ChannelEntity) in
|
||||
if !restrictedChannels.contains(channel.name?.lowercased() ?? "") {
|
||||
makeChannelListItem(node: node, myInfo: myInfo, channel: channel)
|
||||
}
|
||||
ForEach(visibleChannels) { (channel: ChannelEntity) in
|
||||
makeChannelListItem(node: node, myInfo: myInfo, channel: channel)
|
||||
}
|
||||
}
|
||||
.olderThanOS26 { $0.padding([.top, .bottom]) }
|
||||
|
|
|
|||
|
|
@ -53,6 +53,33 @@ struct Channels: View {
|
|||
@Query(sort: \NodeInfoEntity.lastHeard, order: .reverse)
|
||||
var nodes: [NodeInfoEntity]
|
||||
|
||||
private var displayChannels: [ChannelEntity] {
|
||||
guard let channels = node.myInfo?.channels else { return [] }
|
||||
var byIndex: [Int32: ChannelEntity] = [:]
|
||||
for channel in channels {
|
||||
byIndex[channel.index] = channel
|
||||
}
|
||||
return byIndex.values.sorted { $0.index < $1.index }
|
||||
}
|
||||
|
||||
private func normalizeDuplicateChannelsIfNeeded() {
|
||||
guard let channels = node.myInfo?.channels else { return }
|
||||
var uniqueChannels: [Int32: ChannelEntity] = [:]
|
||||
for channel in channels {
|
||||
uniqueChannels[channel.index] = channel
|
||||
}
|
||||
let deduped = uniqueChannels.values.sorted { $0.index < $1.index }
|
||||
guard deduped.count != channels.count else { return }
|
||||
node.myInfo?.channels = deduped
|
||||
do {
|
||||
try context.save()
|
||||
Logger.data.info("💾 Normalized duplicate channels for node \(self.node.num, privacy: .public)")
|
||||
} catch {
|
||||
context.rollback()
|
||||
Logger.data.error("Failed normalizing duplicate channels: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
|
@ -61,7 +88,7 @@ struct Channels: View {
|
|||
.tipBackground(colorScheme == .dark ? Color(.systemBackground) : Color(.secondarySystemBackground))
|
||||
.listRowSeparator(.hidden)
|
||||
if node.myInfo != nil {
|
||||
ForEach(node.myInfo?.channels ?? [], id: \.self) { (channel: ChannelEntity) in
|
||||
ForEach(displayChannels, id: \.self) { (channel: ChannelEntity) in
|
||||
Button(action: {
|
||||
channelIndex = channel.index
|
||||
channelRole = Int(channel.role)
|
||||
|
|
@ -175,12 +202,17 @@ struct Channels: View {
|
|||
guard var channels = node.myInfo?.channels else {
|
||||
return
|
||||
}
|
||||
if let idx = channels.firstIndex(where: { $0.psk == selectedChannel?.psk && $0.name == selectedChannel?.name }) {
|
||||
if let idx = channels.firstIndex(where: { $0.index == selectedChannel?.index }) {
|
||||
channels[idx] = selectedChannel!
|
||||
} else {
|
||||
channels.append(selectedChannel!)
|
||||
}
|
||||
node.myInfo?.channels = channels
|
||||
|
||||
var uniqueChannels: [Int32: ChannelEntity] = [:]
|
||||
for channel in channels {
|
||||
uniqueChannels[channel.index] = channel
|
||||
}
|
||||
node.myInfo?.channels = uniqueChannels.values.sorted { $0.index < $1.index }
|
||||
if channel.role != Channel.Role.disabled {
|
||||
do {
|
||||
try context.save()
|
||||
|
|
@ -340,6 +372,9 @@ struct Channels: View {
|
|||
}
|
||||
.padding(.bottom, 5)
|
||||
.navigationTitle("Channels")
|
||||
.onAppear {
|
||||
normalizeDuplicateChannelsIfNeeded()
|
||||
}
|
||||
.navigationBarItems(trailing:
|
||||
ZStack {
|
||||
ConnectedDevice(deviceConnected: accessoryManager.isConnected, name: accessoryManager.activeConnection?.device.shortName ?? "?")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue