Meshtastic-Apple/Meshtastic/Views/ContentView.swift
copilot-swe-agent[bot] a8f4cf9631
feat: improve routing performance with split state, fetch batching, node cache, and debounce
- Split Router's single @Published navigationState into per-tab properties
  to reduce spurious re-renders across unrelated views
- Add fetchBatchSize=50 and relationshipKeyPathsForPrefetching to node list
- Optimize in-body array re-sort from 2 filter passes to single pass
- Add in-memory node object ID cache on Router for O(1) lookups
- Add fetchLimit=1 to getNodeInfo for early termination
- Debounce rapid node selection changes with 100ms Task delay

Agent-Logs-Url: https://github.com/meshtastic/Meshtastic-Apple/sessions/9bfe91f2-8ed7-4d2c-bb2e-4ed3dfd3a16c

Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com>
2026-04-01 23:52:56 +00:00

80 lines
1.8 KiB
Swift

/*
Copyright (c) Garth Vander Houwen 2021
*/
import SwiftUI
struct ContentView: View {
@ObservedObject var appState: AppState
@EnvironmentObject var accessoryManager: AccessoryManager
@State var router: Router
@State var isShowingDeviceOnboardingFlow: Bool = false
init(appState: AppState, router: Router) {
self.appState = appState
self.router = router
UITabBar.appearance().scrollEdgeAppearance = UITabBarAppearance(idiom: .unspecified)
}
var body: some View {
TabView(selection: $appState.router.selectedTab) {
Messages(
router: appState.router,
unreadChannelMessages: $appState.unreadChannelMessages,
unreadDirectMessages: $appState.unreadDirectMessages
)
.tabItem {
Label("Messages", systemImage: "message")
}
.tag(NavigationState.Tab.messages)
.badge(appState.totalUnreadMessages)
Connect(
router: appState.router
)
.tabItem {
Label("Connect", systemImage: "link")
}
.tag(NavigationState.Tab.connect)
NodeList(
router: appState.router
)
.tabItem {
Label("Nodes", systemImage: "flipphone")
}
.tag(NavigationState.Tab.nodes)
MeshMap(router: appState.router)
.tabItem {
Label("Mesh Map", systemImage: "map")
}
.tag(NavigationState.Tab.map)
Settings(
router: appState.router
)
.tabItem {
Label("Settings", systemImage: "gear")
.font(.title)
}
.tag(NavigationState.Tab.settings)
}.sheet(
isPresented: $isShowingDeviceOnboardingFlow,
onDismiss: {
UserDefaults.firstLaunch = false
accessoryManager.startDiscovery()
}, content: {
DeviceOnboarding()
}
)
.onAppear {
if UserDefaults.firstLaunch {
isShowingDeviceOnboardingFlow = true
}
}
.onChange(of: UserDefaults.showDeviceOnboarding) {_, newValue in
isShowingDeviceOnboardingFlow = newValue
}
}
}