mirror of
https://github.com/home-assistant/iOS.git
synced 2026-06-17 09:25:54 -05:00
Starting in iOS 15, there's a number of crashes happening in the background with Realm. They don't appear to be due to the file lock in the shared app container, but this may help resolve them either way -- easy to see if the next beta doesn't crash a bunch.
99 lines
2.9 KiB
Swift
99 lines
2.9 KiB
Swift
import Foundation
|
|
import ObjectMapper
|
|
import PromiseKit
|
|
import UserNotifications
|
|
|
|
extension WebhookResponseIdentifier {
|
|
static var location: Self { .init(rawValue: "updateLocation") }
|
|
}
|
|
|
|
struct WebhookResponseLocationLocalMetadata: ImmutableMappable {
|
|
let trigger: LocationUpdateTrigger
|
|
let zoneName: String
|
|
|
|
init(trigger: LocationUpdateTrigger, zone: RLMZone?) {
|
|
self.trigger = trigger
|
|
self.zoneName = zone?.Name ?? "(unknown)"
|
|
}
|
|
|
|
init(map: Map) throws {
|
|
self.trigger = try map.value("trigger")
|
|
self.zoneName = try map.value("zone_name")
|
|
}
|
|
|
|
func mapping(map: Map) {
|
|
trigger >>> map["trigger"]
|
|
zoneName >>> map["zone_name"]
|
|
}
|
|
}
|
|
|
|
struct WebhookResponseLocation: WebhookResponseHandler {
|
|
let api: HomeAssistantAPI
|
|
init(api: HomeAssistantAPI) {
|
|
self.api = api
|
|
}
|
|
|
|
static func localMetdata(
|
|
trigger: LocationUpdateTrigger,
|
|
zone: RLMZone?
|
|
) -> [String: Any] {
|
|
WebhookResponseLocationLocalMetadata(
|
|
trigger: trigger,
|
|
zone: zone
|
|
).toJSON()
|
|
}
|
|
|
|
static func shouldReplace(request current: WebhookRequest, with proposed: WebhookRequest) -> Bool {
|
|
// recency should always win
|
|
true
|
|
}
|
|
|
|
enum HandleError: Error {
|
|
case missingLocalMetadata
|
|
}
|
|
|
|
func handle(
|
|
request: Promise<WebhookRequest>,
|
|
result: Promise<Any>
|
|
) -> Guarantee<WebhookResponseHandlerResult> {
|
|
firstly {
|
|
when(fulfilled: request, result)
|
|
}.map { request, _ in
|
|
guard let localMetadata = request.localMetadata.flatMap({
|
|
Mapper<WebhookResponseLocationLocalMetadata>().map(JSON: $0)
|
|
}) else {
|
|
throw HandleError.missingLocalMetadata
|
|
}
|
|
|
|
let notificationOptions = localMetadata.trigger.notificationOptionsFor(zoneName: localMetadata.zoneName)
|
|
|
|
Current.clientEventStore.addEvent(ClientEvent(
|
|
text: notificationOptions.body,
|
|
type: .locationUpdate,
|
|
payload: try? request.asDictionary()
|
|
)).cauterize()
|
|
|
|
guard notificationOptions.shouldNotify else {
|
|
return nil
|
|
}
|
|
|
|
return UNNotificationRequest(
|
|
identifier: notificationOptions.identifier ?? UUID().uuidString,
|
|
content: with(UNMutableNotificationContent()) {
|
|
$0.title = notificationOptions.title
|
|
$0.body = notificationOptions.body
|
|
$0.sound = UNNotificationSound.default
|
|
},
|
|
trigger: nil
|
|
)
|
|
}.recover { _ -> Guarantee<UNNotificationRequest?> in
|
|
// don't send a notification for failed
|
|
.value(nil)
|
|
}.map { notification in
|
|
var result = WebhookResponseHandlerResult.default
|
|
result.notification = notification
|
|
return result
|
|
}
|
|
}
|
|
}
|