gitbay/Push/PushTarget.swift
31 lines · 1600 bytes
1import Foundation
2
3/// A tapped notification resolved against the accounts signed in on
4/// this device: which account it belongs to, and the screen it opens.
5nonisolated struct PushTarget: Equatable, Sendable {
6 let accountID: String
7 let destination: NotificationDestination
8
9 /// Nil when no signed-in account matches — you signed out of it —
10 /// or when the path names nothing the app can route to.
11 init?(payload: PushPayload, accounts: [Account]) {
12 guard let destination = notificationDestination(forPath: payload.path) else { return nil }
13 // Run the payload's instance through the same normalisation an
14 // account's did (trailing slash, default port) rather than
15 // comparing raw URLs, which a server's unnormalised config can
16 // make unequal even when they name the same instance.
17 guard let instance = try? GitbayInstance(url: payload.instance.absoluteString) else { return nil }
18 // Both sides, not just the payload's: an account stored before
19 // the constructor folded the default port still holds an
20 // explicit ":443". Normalising is for the comparison only —
21 // rewriting what is stored would change `Account.id` and orphan
22 // the Keychain token it keys.
23 let match = accounts.first {
24 $0.username == payload.user
25 && (try? GitbayInstance(url: $0.instance.baseURL.absoluteString))?.baseURL == instance.baseURL
26 }
27 guard let match else { return nil }
28 self.accountID = match.id
29 self.destination = destination
30 }
31}