Add AppDelegate and shared AppState object to control navigation programatically

This commit is contained in:
Ben Meadors 2023-08-21 10:24:17 -05:00
parent f2e3288631
commit 66298d52c7
6 changed files with 76 additions and 25 deletions

View file

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
6DA39D8E2A92DC52007E311C /* MeshtasticAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DA39D8D2A92DC52007E311C /* MeshtasticAppDelegate.swift */; };
C9697F9D279336B700250207 /* LocalMBTileOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9697F9C279336B700250207 /* LocalMBTileOverlay.swift */; };
C9697FA527933B8C00250207 /* SQLite in Frameworks */ = {isa = PBXBuildFile; productRef = C9697FA427933B8C00250207 /* SQLite */; };
DD0D3D222A55CEB10066DB71 /* CocoaMQTT in Frameworks */ = {isa = PBXBuildFile; productRef = DD0D3D212A55CEB10066DB71 /* CocoaMQTT */; };
@ -195,6 +196,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
6DA39D8D2A92DC52007E311C /* MeshtasticAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticAppDelegate.swift; sourceTree = "<group>"; };
A65FA974296876BF00A97686 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
C9697F9C279336B700250207 /* LocalMBTileOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalMBTileOverlay.swift; sourceTree = "<group>"; };
DD0E9C222A30CE3A00580CBB /* MeshtasticDataModelV14.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV14.xcdatamodel; sourceTree = "<group>"; };
@ -625,6 +627,7 @@
DDC2E15726CE248E0042C5E4 /* MeshtasticApp.swift */,
DDC2E16526CE248F0042C5E4 /* Info.plist */,
DDC2E15D26CE248F0042C5E4 /* Preview Content */,
6DA39D8D2A92DC52007E311C /* MeshtasticAppDelegate.swift */,
);
path = Meshtastic;
sourceTree = "<group>";
@ -1058,6 +1061,7 @@
DD5E520D298EE33B00D21B61 /* storeforward.pb.swift in Sources */,
DD882F5D2772E4640005BF05 /* Contacts.swift in Sources */,
DD964FC2297272AE007C176F /* WaypointEntityExtension.swift in Sources */,
6DA39D8E2A92DC52007E311C /* MeshtasticAppDelegate.swift in Sources */,
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */,
DD5E520A298EE33B00D21B61 /* channel.pb.swift in Sources */,
DDDEE5E129DA3E1100A8E078 /* NodeInfoView.swift in Sources */,

View file

@ -10,16 +10,16 @@ class LocalNotificationManager {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if granted == true && error == nil {
self.scheduleNotifications()
self.scheduleNotifications()
}
}
}
func schedule() {
func schedule() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
switch settings.authorizationStatus {
case .notDetermined:
self.requestAuthorization()
self.requestAuthorization()
case .authorized, .provisional:
self.scheduleNotifications()
default:
@ -37,6 +37,9 @@ class LocalNotificationManager {
content.body = notification.content
content.sound = .default
content.interruptionLevel = .timeSensitive
if notification.target != nil {
content.userInfo["target"] = notification.target
}
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
let request = UNNotificationRequest(identifier: notification.id, content: content, trigger: trigger)
@ -65,4 +68,5 @@ struct Notification {
var title: String
var subtitle: String
var content: String
var target: String?
}

View file

@ -877,7 +877,9 @@ func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) {
id: ("notification.id.\(waypoint.id)"),
title: "New Waypoint Received",
subtitle: "\(icon) \(waypoint.name ?? "Dropped Pin")",
content: "\(waypoint.longDescription ?? "\(latitude), \(longitude)")")
content: "\(waypoint.longDescription ?? "\(latitude), \(longitude)")",
target: "waypoint"
)
]
manager.schedule()
} catch {

View file

@ -4,8 +4,8 @@ import SwiftUI
import CoreData
@main
struct MeshtasticAppleApp: App {
struct MeshtasticAppleApp : App {
@UIApplicationDelegateAdaptor(MeshtasticAppDelegate.self) var appDelegate
let persistenceController = PersistenceController.shared
@ObservedObject private var bleManager: BLEManager = BLEManager()
@Environment(\.scenePhase) var scenePhase
@ -13,10 +13,11 @@ struct MeshtasticAppleApp: App {
@State var saveChannels = false
@State var incomingUrl: URL?
@State var channelSettings: String?
@StateObject var appState = AppState.shared
var body: some Scene {
WindowGroup {
ContentView()
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.environmentObject(bleManager)
.sheet(isPresented: $saveChannels) {
@ -45,7 +46,6 @@ struct MeshtasticAppleApp: App {
print("Some sort of URL was received \(url)")
self.incomingUrl = url
if url.absoluteString.lowercased().contains("meshtastic.org/e/#") {
if let components = self.incomingUrl?.absoluteString.components(separatedBy: "#") {
self.channelSettings = components.last!
@ -115,5 +115,11 @@ struct MeshtasticAppleApp: App {
print("💥 Apple must have changed something")
}
}
}
}
}
class AppState: ObservableObject {
static let shared = AppState()
@Published var tabSelection: Tab = .ble
}

View file

@ -0,0 +1,37 @@
//
// MeshtasticAppDelegate.swift
// Meshtastic
//
// Created by Ben on 8/20/23.
//
import SwiftUI
class MeshtasticAppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("App launched!")
UNUserNotificationCenter.current().delegate = self
return true
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
}
// This method is called when user clicked on the notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
{
let userInfo = response.notification.request.content.userInfo
if let targetValue = userInfo["target"] as? String, targetValue == "waypoint"
{
openWaypoint()
}
completionHandler()
}
private func openWaypoint()
{
AppState.shared.tabSelection = Tab.map
}
}

View file

@ -5,22 +5,11 @@
import SwiftUI
struct ContentView: View {
@State private var selection: Tab = .ble
enum Tab {
case contacts
case messages
case map
case ble
case nodes
case settings
}
@StateObject var appState = AppState.shared
var body: some View {
TabView(selection: $selection) {
TabView(selection: $appState.tabSelection) {
Contacts()
.tabItem {
Label("messages", systemImage: "message")
@ -55,3 +44,12 @@ struct ContentView_Previews: PreviewProvider {
ContentView()
}
}
enum Tab {
case contacts
case messages
case map
case ble
case nodes
case settings
}