Skip to content

Commit

Permalink
Refactor router state to more closely match tab bar behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
72A12F4E committed Aug 28, 2024
1 parent 6b84450 commit 620e329
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 129 deletions.
47 changes: 6 additions & 41 deletions Meshtastic/Router/NavigationState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,7 @@ enum SettingsNavigationState: String {
case firmwareUpdates
}

enum NavigationState: Hashable {
case messages(MessagesNavigationState? = nil)
case bluetooth
case nodes(selectedNodeNum: Int64? = nil)
case map(MapNavigationState? = nil)
case settings(SettingsNavigationState? = nil)
}

// MARK: Tab Bar

extension NavigationState {
struct NavigationState: Hashable {
enum Tab: String, Hashable {
case messages
case bluetooth
Expand All @@ -74,34 +64,9 @@ extension NavigationState {
case settings
}

var tab: Tab {
get {
switch self {
case .messages:
.messages
case .bluetooth:
.bluetooth
case .nodes:
.nodes
case .map:
.map
case .settings:
.settings
}
}
set {
self = switch newValue {
case .messages:
.messages()
case .bluetooth:
.bluetooth
case .nodes:
.nodes()
case .map:
.map()
case .settings:
.settings()
}
}
}
var selectedTab: Tab = .bluetooth
var messages: MessagesNavigationState?
var nodeListSelectedNodeNum: Int64?
var map: MapNavigationState?
var settings: SettingsNavigationState?
}
30 changes: 17 additions & 13 deletions Meshtastic/Router/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ class Router: ObservableObject {
private var cancellables: Set<AnyCancellable> = []

init(
navigationState: NavigationState = .bluetooth
navigationState: NavigationState = NavigationState(
selectedTab: .bluetooth
)
) {
self.navigationState = navigationState

Expand All @@ -21,10 +23,6 @@ class Router: ObservableObject {
}.store(in: &cancellables)
}

func route(to destination: NavigationState) {
navigationState = destination
}

func route(url: URL) {
guard url.scheme == "meshtastic" else {
Logger.services.error("🛣 Received routing URL \(url, privacy: .public) with invalid scheme. Ignoring route.")
Expand All @@ -38,7 +36,7 @@ class Router: ObservableObject {
if components.path == "/messages" {
routeMessages(components)
} else if components.path == "/bluetooth" {
route(to: .bluetooth)
navigationState.selectedTab = .bluetooth
} else if components.path == "/nodes" {
routeNodes(components)
} else if components.path == "/map" {
Expand Down Expand Up @@ -75,15 +73,18 @@ class Router: ObservableObject {
} else {
nil
}
route(to: .messages(state))
navigationState.selectedTab = .messages
navigationState.messages = state
}

private func routeNodes(_ components: URLComponents) {
let nodeId = components.queryItems?
.first(where: { $0.name == "nodenum" })?
.value
.flatMap(Int64.init)
route(to: .nodes(selectedNodeNum: nodeId))

navigationState.selectedTab = .nodes
navigationState.nodeListSelectedNodeNum = nodeId
}

private func routeMap(_ components: URLComponents) {
Expand All @@ -95,12 +96,14 @@ class Router: ObservableObject {
.first(where: { $0.name == "waypointId" })?
.value
.flatMap(Int64.init)
if let nodeId {
route(to: .map(.selectedNode(nodeId)))

navigationState.selectedTab = .map
navigationState.map = if let nodeId {
.selectedNode(nodeId)
} else if let waypointId {
route(to: .map(.waypoint(waypointId)))
.waypoint(waypointId)
} else {
route(to: .map())
nil
}
}

Expand All @@ -112,6 +115,7 @@ class Router: ObservableObject {
.flatMap(String.init)
.flatMap(SettingsNavigationState.init(rawValue:))

route(to: .settings(settingFromPath))
navigationState.selectedTab = .settings
navigationState.settings = settingFromPath
}
}
9 changes: 1 addition & 8 deletions Meshtastic/Views/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,7 @@ struct ContentView: View {
var router: Router

var body: some View {
TabView(selection: Binding(
get: {
appState.router.navigationState.tab
},
set: { newValue in
appState.router.navigationState.tab = newValue
}
)) {
TabView(selection: $appState.router.navigationState.selectedTab) {
Messages(
router: appState.router,
unreadChannelMessages: $appState.unreadChannelMessages,
Expand Down
34 changes: 8 additions & 26 deletions Meshtastic/Views/Messages/Messages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,6 @@ struct Messages: View {
@Binding
var unreadDirectMessages: Int

// Aliases the navigation state for the NavigationSplitView sidebar selection
private var messagesSelection: Binding<MessagesNavigationState?> {
Binding(
get: {
guard case .messages(let state) = router.navigationState else {
return nil
}
return state
},
set: { newValue in
router.navigationState = .messages(newValue)
}
)
}

@State var node: NodeInfoEntity?
@State private var userSelection: UserEntity? // Nothing selected by default.
@State private var channelSelection: ChannelEntity? // Nothing selected by default.
Expand All @@ -49,7 +34,7 @@ struct Messages: View {

var body: some View {
NavigationSplitView(columnVisibility: $columnVisibility) {
List(selection: messagesSelection) {
List(selection: $router.navigationState.messages) {
NavigationLink(value: MessagesNavigationState.channels()) {
Label {
Text("channels")
Expand Down Expand Up @@ -88,21 +73,22 @@ struct Messages: View {
.navigationBarTitleDisplayMode(.large)
.navigationBarItems(leading: MeshtasticLogo())
} content: {
if case .messages(.channels) = router.navigationState {
switch router.navigationState.messages {
case .channels(let channelId, let messageId):
ChannelList(node: $node, channelSelection: $channelSelection)
} else if case .messages(.directMessages) = router.navigationState {
case .directMessages(let userNum, let messageId):
UserList(node: $node, userSelection: $userSelection)
} else if case .messages(nil) = router.navigationState {
case nil:
Text("Select a conversation type")
}
} detail: {
if let myInfo = node?.myInfo, let channelSelection {
ChannelMessageList(myInfo: myInfo, channel: channelSelection)
} else if let userSelection {
UserMessageList(user: userSelection)
} else if case .messages(.channels) = router.navigationState {
} else if case .channels = router.navigationState.messages {
Text("Select a channel")
} else if case .messages(.directMessages) = router.navigationState {
} else if case .directMessages = router.navigationState.messages {
Text("Select a conversation")
}
}.onChange(of: router.navigationState) { _ in
Expand All @@ -116,11 +102,7 @@ struct Messages: View {
node = getNodeInfo(id: nodeId, context: context)
}

guard case .messages(let state) = router.navigationState else {
return
}

guard let state else {
guard let state = router.navigationState.messages else {
channelSelection = nil
userSelection = nil
return
Expand Down
2 changes: 1 addition & 1 deletion Meshtastic/Views/Nodes/MeshMap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ struct MeshMap: View {
MapSettingsForm(traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMap: $isMeshMap)
}
.onChange(of: router.navigationState) {
guard case .map(let selectedNodeNum) = router.navigationState else { return }
guard case .map = router.navigationState.selectedTab else { return }
// TODO: handle deep link for waypoints
}
.onChange(of: selectedMapLayer) { newMapLayer in
Expand Down
7 changes: 2 additions & 5 deletions Meshtastic/Views/Nodes/NodeList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,8 @@ struct NodeList: View {
}
}
.onChange(of: router.navigationState) { _ in
// Handle deep link routing
if case .nodes(let selected) = router.navigationState {
self.selectedNode = selected.flatMap {
getNodeInfo(id: $0, context: context)
}
if let selected = router.navigationState.nodeListSelectedNodeNum {
self.selectedNode = getNodeInfo(id: selected, context: context)
} else {
self.selectedNode = nil
}
Expand Down
7 changes: 2 additions & 5 deletions Meshtastic/Views/Settings/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -299,13 +299,10 @@ struct Settings: View {
NavigationStack(
path: Binding<[SettingsNavigationState]>(
get: {
guard case .settings(let route) = router.navigationState, let setting = route else {
return []
}
return [setting]
[router.navigationState.settings].compactMap { $0 }
},
set: { newPath in
router.navigationState = .settings(newPath.first)
router.navigationState.settings = newPath.first
}
)
) {
Expand Down
Loading

0 comments on commit 620e329

Please sign in to comment.