Compare commits
No commits in common. "ff8a83ca2ddf3d906282f6d4df65b6bbfa8c7c1d" and "ff11835333ed1a3d13a541d2f91db436c2114d86" have entirely different histories.
ff8a83ca2d
...
ff11835333
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>TuskerInfo</key>
|
|
||||||
<dict>
|
|
||||||
<key>PushProxyHost</key>
|
|
||||||
<string>$(TUSKER_PUSH_PROXY_HOST)</string>
|
|
||||||
<key>PushProxyScheme</key>
|
|
||||||
<string>$(TUSKER_PUSH_PROXY_SCHEME)</string>
|
|
||||||
<key>SentryDSN</key>
|
|
||||||
<string>$(SENTRY_DSN)</string>
|
|
||||||
</dict>
|
|
||||||
<key>NSExtension</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSExtensionPointIdentifier</key>
|
|
||||||
<string>com.apple.usernotifications.service</string>
|
|
||||||
<key>NSExtensionPrincipalClass</key>
|
|
||||||
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>com.apple.security.app-sandbox</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.application-groups</key>
|
|
||||||
<array>
|
|
||||||
<string>group.$(BUNDLE_ID_PREFIX).Tusker</string>
|
|
||||||
</array>
|
|
||||||
<key>com.apple.security.network.client</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -1,150 +0,0 @@
|
||||||
//
|
|
||||||
// NotificationService.swift
|
|
||||||
// NotificationExtension
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 4/9/24.
|
|
||||||
// Copyright © 2024 Shadowfacts. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UserNotifications
|
|
||||||
import UserAccounts
|
|
||||||
import PushNotifications
|
|
||||||
import CryptoKit
|
|
||||||
import OSLog
|
|
||||||
import Pachyderm
|
|
||||||
|
|
||||||
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "NotificationService")
|
|
||||||
|
|
||||||
class NotificationService: UNNotificationServiceExtension {
|
|
||||||
|
|
||||||
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
|
||||||
guard let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent else {
|
|
||||||
contentHandler(request.content)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard request.content.userInfo["v"] as? Int == 1,
|
|
||||||
let accountID = request.content.userInfo["ctx"] as? String,
|
|
||||||
let account = UserAccountsManager.shared.getAccount(id: accountID),
|
|
||||||
let subscription = getSubscription(account: account),
|
|
||||||
let encryptedBody = (request.content.userInfo["data"] as? String).flatMap({ Data(base64Encoded: $0) }),
|
|
||||||
let salt = (request.content.userInfo["salt"] as? String).flatMap(decodeBase64URL(_:)),
|
|
||||||
let serverPublicKeyData = (request.content.userInfo["pk"] as? String).flatMap(decodeBase64URL(_:)) else {
|
|
||||||
logger.error("Missing info from push notification")
|
|
||||||
contentHandler(request.content)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let body = decryptNotification(subscription: subscription, serverPublicKeyData: serverPublicKeyData, salt: salt, encryptedBody: encryptedBody) else {
|
|
||||||
contentHandler(request.content)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let withoutPadding = body.dropFirst(2)
|
|
||||||
|
|
||||||
let notification: PushNotification
|
|
||||||
do {
|
|
||||||
notification = try JSONDecoder().decode(PushNotification.self, from: withoutPadding)
|
|
||||||
} catch {
|
|
||||||
logger.error("Unable to decode push payload: \(String(describing: error))")
|
|
||||||
contentHandler(request.content)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mutableContent.title = notification.title
|
|
||||||
mutableContent.body = notification.body
|
|
||||||
|
|
||||||
contentHandler(mutableContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
override func serviceExtensionTimeWillExpire() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private func getSubscription(account: UserAccountInfo) -> PushNotifications.PushSubscription? {
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
// this is necessary because of a swift bug: https://github.com/apple/swift/pull/72507
|
|
||||||
MainActor.runUnsafely {
|
|
||||||
PushManager.shared.pushSubscription(account: account)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func decryptNotification(subscription: PushNotifications.PushSubscription, serverPublicKeyData: Data, salt: Data, encryptedBody: Data) -> Data? {
|
|
||||||
// See https://github.com/ClearlyClaire/webpush/blob/f14a4d52e201128b1b00245d11b6de80d6cfdcd9/lib/webpush/encryption.rb
|
|
||||||
|
|
||||||
var context = Data()
|
|
||||||
context.append(0)
|
|
||||||
let clientPublicKey = subscription.secretKey.publicKey.x963Representation
|
|
||||||
let clientPublicKeyLength = UInt16(clientPublicKey.count)
|
|
||||||
context.append(UInt8((clientPublicKeyLength >> 8) & 0xFF))
|
|
||||||
context.append(UInt8(clientPublicKeyLength & 0xFF))
|
|
||||||
context.append(clientPublicKey)
|
|
||||||
let serverPublicKeyLength = UInt16(serverPublicKeyData.count)
|
|
||||||
context.append(UInt8((serverPublicKeyLength >> 8) & 0xFF))
|
|
||||||
context.append(UInt8(serverPublicKeyLength & 0xFF))
|
|
||||||
context.append(serverPublicKeyData)
|
|
||||||
|
|
||||||
func info(encoding: String) -> Data {
|
|
||||||
var info = Data("Content-Encoding: \(encoding)\0P-256".utf8)
|
|
||||||
info.append(context)
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
let sharedSecret: SharedSecret
|
|
||||||
do {
|
|
||||||
let serverPublicKey = try P256.KeyAgreement.PublicKey(x963Representation: serverPublicKeyData)
|
|
||||||
sharedSecret = try subscription.secretKey.sharedSecretFromKeyAgreement(with: serverPublicKey)
|
|
||||||
} catch {
|
|
||||||
logger.error("Error getting shared secret: \(String(describing: error))")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let sharedInfo = Data("Content-Encoding: auth\0".utf8)
|
|
||||||
let pseudoRandomKey = sharedSecret.hkdfDerivedSymmetricKey(using: SHA256.self, salt: subscription.authSecret, sharedInfo: sharedInfo, outputByteCount: 32)
|
|
||||||
let contentEncryptionKeyInfo = info(encoding: "aesgcm")
|
|
||||||
let contentEncryptionKey = HKDF<SHA256>.deriveKey(inputKeyMaterial: pseudoRandomKey, salt: salt, info: contentEncryptionKeyInfo, outputByteCount: 16)
|
|
||||||
let nonceInfo = info(encoding: "nonce")
|
|
||||||
let nonce = HKDF<SHA256>.deriveKey(inputKeyMaterial: pseudoRandomKey, salt: salt, info: nonceInfo, outputByteCount: 12)
|
|
||||||
|
|
||||||
let nonceAndEncryptedBody = nonce.withUnsafeBytes { noncePtr in
|
|
||||||
var data = Data(buffer: noncePtr.bindMemory(to: UInt8.self))
|
|
||||||
data.append(encryptedBody)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
let sealedBox = try AES.GCM.SealedBox(combined: nonceAndEncryptedBody)
|
|
||||||
let decrypted = try AES.GCM.open(sealedBox, using: contentEncryptionKey)
|
|
||||||
return decrypted
|
|
||||||
} catch {
|
|
||||||
logger.error("Error decrypting push: \(String(describing: error))")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension MainActor {
|
|
||||||
@_unavailableFromAsync
|
|
||||||
@available(macOS, obsoleted: 14.0)
|
|
||||||
@available(iOS, obsoleted: 17.0)
|
|
||||||
@available(watchOS, obsoleted: 10.0)
|
|
||||||
@available(tvOS, obsoleted: 17.0)
|
|
||||||
static func runUnsafely<T>(_ body: @MainActor () throws -> T) rethrows -> T {
|
|
||||||
if #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) {
|
|
||||||
return try MainActor.assumeIsolated(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchPrecondition(condition: .onQueue(.main))
|
|
||||||
return try withoutActuallyEscaping(body) { fn in
|
|
||||||
try unsafeBitCast(fn, to: (() throws -> T).self)()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func decodeBase64URL(_ s: String) -> Data? {
|
|
||||||
var str = s.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
|
|
||||||
if str.count % 4 != 0 {
|
|
||||||
str.append(String(repeating: "=", count: 4 - str.count % 4))
|
|
||||||
}
|
|
||||||
return Data(base64Encoded: str)
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
//
|
|
||||||
// PushNotification.swift
|
|
||||||
// Pachyderm
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 4/9/24.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import WebURL
|
|
||||||
|
|
||||||
public struct PushNotification: Decodable {
|
|
||||||
public let accessToken: String
|
|
||||||
public let preferredLocale: String
|
|
||||||
public let notificationID: String
|
|
||||||
public let notificationType: Notification.Kind
|
|
||||||
public let icon: WebURL
|
|
||||||
public let title: String
|
|
||||||
public let body: String
|
|
||||||
|
|
||||||
public init(from decoder: any Decoder) throws {
|
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
||||||
self.accessToken = try container.decode(String.self, forKey: .accessToken)
|
|
||||||
self.preferredLocale = try container.decode(String.self, forKey: .preferredLocale)
|
|
||||||
// this should be a string, but mastodon encodes it as a json number
|
|
||||||
if let s = try? container.decode(String.self, forKey: .notificationID) {
|
|
||||||
self.notificationID = s
|
|
||||||
} else {
|
|
||||||
let i = try container.decode(Int.self, forKey: .notificationID)
|
|
||||||
self.notificationID = i.description
|
|
||||||
}
|
|
||||||
self.notificationType = try container.decode(Notification.Kind.self, forKey: .notificationType)
|
|
||||||
self.icon = try container.decode(WebURL.self, forKey: .icon)
|
|
||||||
self.title = try container.decode(String.self, forKey: .title)
|
|
||||||
self.body = try container.decode(String.self, forKey: .body)
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
|
||||||
case accessToken = "access_token"
|
|
||||||
case preferredLocale = "preferred_locale"
|
|
||||||
case notificationID = "notification_id"
|
|
||||||
case notificationType = "notification_type"
|
|
||||||
case icon
|
|
||||||
case title
|
|
||||||
case body
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,9 +24,6 @@ class DisabledPushManager: _PushManager {
|
||||||
func removeSubscription(account: UserAccountInfo) {
|
func removeSubscription(account: UserAccountInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSubscription(account: UserAccountInfo, alerts: PushSubscription.Alerts, policy: PushSubscription.Policy) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func pushSubscription(account: UserAccountInfo) -> PushSubscription? {
|
func pushSubscription(account: UserAccountInfo) -> PushSubscription? {
|
||||||
nil
|
nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ public protocol _PushManager {
|
||||||
|
|
||||||
func createSubscription(account: UserAccountInfo) throws -> PushSubscription
|
func createSubscription(account: UserAccountInfo) throws -> PushSubscription
|
||||||
func removeSubscription(account: UserAccountInfo)
|
func removeSubscription(account: UserAccountInfo)
|
||||||
func updateSubscription(account: UserAccountInfo, alerts: PushSubscription.Alerts, policy: PushSubscription.Policy)
|
|
||||||
func pushSubscription(account: UserAccountInfo) -> PushSubscription?
|
func pushSubscription(account: UserAccountInfo) -> PushSubscription?
|
||||||
|
|
||||||
func register(transactionID: UInt64) async throws -> PushProxyRegistration
|
func register(transactionID: UInt64) async throws -> PushProxyRegistration
|
||||||
|
|
|
@ -95,16 +95,6 @@ class PushManagerImpl: _PushManager {
|
||||||
subscriptions.removeAll { $0.accountID == account.id }
|
subscriptions.removeAll { $0.accountID == account.id }
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSubscription(account: UserAccountInfo, alerts: PushSubscription.Alerts, policy: PushSubscription.Policy) {
|
|
||||||
guard let index = subscriptions.firstIndex(where: { $0.accountID == account.id }) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var copy = subscriptions[index]
|
|
||||||
copy.alerts = alerts
|
|
||||||
copy.policy = policy
|
|
||||||
subscriptions[index] = copy
|
|
||||||
}
|
|
||||||
|
|
||||||
func pushSubscription(account: UserAccountInfo) -> PushSubscription? {
|
func pushSubscription(account: UserAccountInfo) -> PushSubscription? {
|
||||||
subscriptions.first { $0.accountID == account.id }
|
subscriptions.first { $0.accountID == account.id }
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>group.$(BUNDLE_ID_PREFIX).Tusker</string>
|
<string>group.space.vaccor.Tusker</string>
|
||||||
</array>
|
</array>
|
||||||
<key>com.apple.security.network.client</key>
|
<key>com.apple.security.network.client</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
|
|
@ -95,12 +95,6 @@
|
||||||
D630C3C82BC43AFD00208903 /* PushNotifications in Frameworks */ = {isa = PBXBuildFile; productRef = D630C3C72BC43AFD00208903 /* PushNotifications */; };
|
D630C3C82BC43AFD00208903 /* PushNotifications in Frameworks */ = {isa = PBXBuildFile; productRef = D630C3C72BC43AFD00208903 /* PushNotifications */; };
|
||||||
D630C3CA2BC59FF500208903 /* MastodonController+Push.swift in Sources */ = {isa = PBXBuildFile; fileRef = D630C3C92BC59FF500208903 /* MastodonController+Push.swift */; };
|
D630C3CA2BC59FF500208903 /* MastodonController+Push.swift in Sources */ = {isa = PBXBuildFile; fileRef = D630C3C92BC59FF500208903 /* MastodonController+Push.swift */; };
|
||||||
D630C3CC2BC5FD4600208903 /* GetAuthorizationTokenService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D630C3CB2BC5FD4600208903 /* GetAuthorizationTokenService.swift */; };
|
D630C3CC2BC5FD4600208903 /* GetAuthorizationTokenService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D630C3CB2BC5FD4600208903 /* GetAuthorizationTokenService.swift */; };
|
||||||
D630C3D42BC61B6100208903 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D630C3D32BC61B6100208903 /* NotificationService.swift */; };
|
|
||||||
D630C3D82BC61B6100208903 /* NotificationExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D630C3D12BC61B6000208903 /* NotificationExtension.appex */; platformFilters = (ios, maccatalyst, ); settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
|
||||||
D630C3DF2BC61C4900208903 /* PushNotifications in Frameworks */ = {isa = PBXBuildFile; productRef = D630C3DE2BC61C4900208903 /* PushNotifications */; };
|
|
||||||
D630C3E12BC61C6700208903 /* UserAccounts in Frameworks */ = {isa = PBXBuildFile; productRef = D630C3E02BC61C6700208903 /* UserAccounts */; };
|
|
||||||
D630C3E52BC6313400208903 /* Pachyderm in Frameworks */ = {isa = PBXBuildFile; productRef = D630C3E42BC6313400208903 /* Pachyderm */; };
|
|
||||||
D630C3E72BC6313F00208903 /* WebURLFoundationExtras in Frameworks */ = {isa = PBXBuildFile; productRef = D630C3E62BC6313F00208903 /* WebURLFoundationExtras */; };
|
|
||||||
D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6311C4F25B3765B00B27539 /* ImageDataCache.swift */; };
|
D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6311C4F25B3765B00B27539 /* ImageDataCache.swift */; };
|
||||||
D6333B372137838300CE884A /* AttributedString+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B362137838300CE884A /* AttributedString+Helpers.swift */; };
|
D6333B372137838300CE884A /* AttributedString+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B362137838300CE884A /* AttributedString+Helpers.swift */; };
|
||||||
D6333B792139AEFD00CE884A /* Date+TimeAgo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */; };
|
D6333B792139AEFD00CE884A /* Date+TimeAgo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */; };
|
||||||
|
@ -365,13 +359,6 @@
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
D630C3D62BC61B6100208903 /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = D6D4DDC4212518A000E1C4BB /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = D630C3D02BC61B6000208903;
|
|
||||||
remoteInfo = NotificationExtension;
|
|
||||||
};
|
|
||||||
D6A4531B29EF64BA00032932 /* PBXContainerItemProxy */ = {
|
D6A4531B29EF64BA00032932 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = D6D4DDC4212518A000E1C4BB /* Project object */;
|
containerPortal = D6D4DDC4212518A000E1C4BB /* Project object */;
|
||||||
|
@ -410,7 +397,6 @@
|
||||||
dstSubfolderSpec = 13;
|
dstSubfolderSpec = 13;
|
||||||
files = (
|
files = (
|
||||||
D6A4531D29EF64BA00032932 /* ShareExtension.appex in Embed Foundation Extensions */,
|
D6A4531D29EF64BA00032932 /* ShareExtension.appex in Embed Foundation Extensions */,
|
||||||
D630C3D82BC61B6100208903 /* NotificationExtension.appex in Embed Foundation Extensions */,
|
|
||||||
D6E343B4265AAD6B00C4AA01 /* OpenInTusker.appex in Embed Foundation Extensions */,
|
D6E343B4265AAD6B00C4AA01 /* OpenInTusker.appex in Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
name = "Embed Foundation Extensions";
|
name = "Embed Foundation Extensions";
|
||||||
|
@ -515,10 +501,6 @@
|
||||||
D62FF04723D7CDD700909D6E /* AttributedStringHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringHelperTests.swift; sourceTree = "<group>"; };
|
D62FF04723D7CDD700909D6E /* AttributedStringHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringHelperTests.swift; sourceTree = "<group>"; };
|
||||||
D630C3C92BC59FF500208903 /* MastodonController+Push.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonController+Push.swift"; sourceTree = "<group>"; };
|
D630C3C92BC59FF500208903 /* MastodonController+Push.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonController+Push.swift"; sourceTree = "<group>"; };
|
||||||
D630C3CB2BC5FD4600208903 /* GetAuthorizationTokenService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetAuthorizationTokenService.swift; sourceTree = "<group>"; };
|
D630C3CB2BC5FD4600208903 /* GetAuthorizationTokenService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetAuthorizationTokenService.swift; sourceTree = "<group>"; };
|
||||||
D630C3D12BC61B6000208903 /* NotificationExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
D630C3D32BC61B6100208903 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
|
|
||||||
D630C3D52BC61B6100208903 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
|
||||||
D630C3D92BC61B6100208903 /* NotificationExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationExtension.entitlements; sourceTree = "<group>"; };
|
|
||||||
D6311C4F25B3765B00B27539 /* ImageDataCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageDataCache.swift; sourceTree = "<group>"; };
|
D6311C4F25B3765B00B27539 /* ImageDataCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageDataCache.swift; sourceTree = "<group>"; };
|
||||||
D6333B362137838300CE884A /* AttributedString+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttributedString+Helpers.swift"; sourceTree = "<group>"; };
|
D6333B362137838300CE884A /* AttributedString+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttributedString+Helpers.swift"; sourceTree = "<group>"; };
|
||||||
D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+TimeAgo.swift"; sourceTree = "<group>"; };
|
D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+TimeAgo.swift"; sourceTree = "<group>"; };
|
||||||
|
@ -796,17 +778,6 @@
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
D630C3CE2BC61B6000208903 /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
D630C3E52BC6313400208903 /* Pachyderm in Frameworks */,
|
|
||||||
D630C3E72BC6313F00208903 /* WebURLFoundationExtras in Frameworks */,
|
|
||||||
D630C3DF2BC61C4900208903 /* PushNotifications in Frameworks */,
|
|
||||||
D630C3E12BC61C6700208903 /* UserAccounts in Frameworks */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D6A4531029EF64BA00032932 /* Frameworks */ = {
|
D6A4531029EF64BA00032932 /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -999,16 +970,6 @@
|
||||||
path = Shortcuts;
|
path = Shortcuts;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D630C3D22BC61B6100208903 /* NotificationExtension */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D630C3D92BC61B6100208903 /* NotificationExtension.entitlements */,
|
|
||||||
D630C3D32BC61B6100208903 /* NotificationService.swift */,
|
|
||||||
D630C3D52BC61B6100208903 /* Info.plist */,
|
|
||||||
);
|
|
||||||
path = NotificationExtension;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D6370B9924421FE00092A7FF /* CoreData */ = {
|
D6370B9924421FE00092A7FF /* CoreData */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1528,7 +1489,6 @@
|
||||||
D6D4DDEE212518A200E1C4BB /* TuskerUITests */,
|
D6D4DDEE212518A200E1C4BB /* TuskerUITests */,
|
||||||
D6E343A9265AAD6B00C4AA01 /* OpenInTusker */,
|
D6E343A9265AAD6B00C4AA01 /* OpenInTusker */,
|
||||||
D6A4531429EF64BA00032932 /* ShareExtension */,
|
D6A4531429EF64BA00032932 /* ShareExtension */,
|
||||||
D630C3D22BC61B6100208903 /* NotificationExtension */,
|
|
||||||
D6D4DDCD212518A000E1C4BB /* Products */,
|
D6D4DDCD212518A000E1C4BB /* Products */,
|
||||||
D65A37F221472F300087646E /* Frameworks */,
|
D65A37F221472F300087646E /* Frameworks */,
|
||||||
);
|
);
|
||||||
|
@ -1542,7 +1502,6 @@
|
||||||
D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */,
|
D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */,
|
||||||
D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */,
|
D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */,
|
||||||
D6A4531329EF64BA00032932 /* ShareExtension.appex */,
|
D6A4531329EF64BA00032932 /* ShareExtension.appex */,
|
||||||
D630C3D12BC61B6000208903 /* NotificationExtension.appex */,
|
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1719,29 +1678,6 @@
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
D630C3D02BC61B6000208903 /* NotificationExtension */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = D630C3DA2BC61B6100208903 /* Build configuration list for PBXNativeTarget "NotificationExtension" */;
|
|
||||||
buildPhases = (
|
|
||||||
D630C3CD2BC61B6000208903 /* Sources */,
|
|
||||||
D630C3CE2BC61B6000208903 /* Frameworks */,
|
|
||||||
D630C3CF2BC61B6000208903 /* Resources */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
name = NotificationExtension;
|
|
||||||
packageProductDependencies = (
|
|
||||||
D630C3DE2BC61C4900208903 /* PushNotifications */,
|
|
||||||
D630C3E02BC61C6700208903 /* UserAccounts */,
|
|
||||||
D630C3E42BC6313400208903 /* Pachyderm */,
|
|
||||||
D630C3E62BC6313F00208903 /* WebURLFoundationExtras */,
|
|
||||||
);
|
|
||||||
productName = NotificationExtension;
|
|
||||||
productReference = D630C3D12BC61B6000208903 /* NotificationExtension.appex */;
|
|
||||||
productType = "com.apple.product-type.app-extension";
|
|
||||||
};
|
|
||||||
D6A4531229EF64BA00032932 /* ShareExtension */ = {
|
D6A4531229EF64BA00032932 /* ShareExtension */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = D6A4532229EF64BA00032932 /* Build configuration list for PBXNativeTarget "ShareExtension" */;
|
buildConfigurationList = D6A4532229EF64BA00032932 /* Build configuration list for PBXNativeTarget "ShareExtension" */;
|
||||||
|
@ -1783,7 +1719,6 @@
|
||||||
dependencies = (
|
dependencies = (
|
||||||
D6E343B3265AAD6B00C4AA01 /* PBXTargetDependency */,
|
D6E343B3265AAD6B00C4AA01 /* PBXTargetDependency */,
|
||||||
D6A4531C29EF64BA00032932 /* PBXTargetDependency */,
|
D6A4531C29EF64BA00032932 /* PBXTargetDependency */,
|
||||||
D630C3D72BC61B6100208903 /* PBXTargetDependency */,
|
|
||||||
);
|
);
|
||||||
name = Tusker;
|
name = Tusker;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
@ -1869,13 +1804,10 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = YES;
|
BuildIndependentTargetsInParallel = YES;
|
||||||
LastSwiftUpdateCheck = 1530;
|
LastSwiftUpdateCheck = 1430;
|
||||||
LastUpgradeCheck = 1500;
|
LastUpgradeCheck = 1500;
|
||||||
ORGANIZATIONNAME = Shadowfacts;
|
ORGANIZATIONNAME = Shadowfacts;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
D630C3D02BC61B6000208903 = {
|
|
||||||
CreatedOnToolsVersion = 15.3;
|
|
||||||
};
|
|
||||||
D6A4531229EF64BA00032932 = {
|
D6A4531229EF64BA00032932 = {
|
||||||
CreatedOnToolsVersion = 14.3;
|
CreatedOnToolsVersion = 14.3;
|
||||||
};
|
};
|
||||||
|
@ -1928,19 +1860,11 @@
|
||||||
D6D4DDEA212518A200E1C4BB /* TuskerUITests */,
|
D6D4DDEA212518A200E1C4BB /* TuskerUITests */,
|
||||||
D6E343A7265AAD6B00C4AA01 /* OpenInTusker */,
|
D6E343A7265AAD6B00C4AA01 /* OpenInTusker */,
|
||||||
D6A4531229EF64BA00032932 /* ShareExtension */,
|
D6A4531229EF64BA00032932 /* ShareExtension */,
|
||||||
D630C3D02BC61B6000208903 /* NotificationExtension */,
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
D630C3CF2BC61B6000208903 /* Resources */ = {
|
|
||||||
isa = PBXResourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D6A4531129EF64BA00032932 /* Resources */ = {
|
D6A4531129EF64BA00032932 /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -2041,14 +1965,6 @@
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
D630C3CD2BC61B6000208903 /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
D630C3D42BC61B6100208903 /* NotificationService.swift in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D6A4530F29EF64BA00032932 /* Sources */ = {
|
D6A4530F29EF64BA00032932 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -2396,11 +2312,6 @@
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
D630C3D72BC61B6100208903 /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = D630C3D02BC61B6000208903 /* NotificationExtension */;
|
|
||||||
targetProxy = D630C3D62BC61B6100208903 /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
D6A4531C29EF64BA00032932 /* PBXTargetDependency */ = {
|
D6A4531C29EF64BA00032932 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = D6A4531229EF64BA00032932 /* ShareExtension */;
|
target = D6A4531229EF64BA00032932 /* ShareExtension */;
|
||||||
|
@ -2459,100 +2370,6 @@
|
||||||
/* End PBXVariantGroup section */
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
D630C3DB2BC61B6100208903 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
|
||||||
CODE_SIGN_ENTITLEMENTS = NotificationExtension/NotificationExtension.entitlements;
|
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
|
||||||
CODE_SIGN_STYLE = Automatic;
|
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
|
||||||
INFOPLIST_FILE = NotificationExtension/Info.plist;
|
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = NotificationExtension;
|
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Shadowfacts. All rights reserved.";
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
"@executable_path/../../Frameworks",
|
|
||||||
);
|
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.NotificationExtension;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SKIP_INSTALL = YES;
|
|
||||||
SUPPORTS_MACCATALYST = YES;
|
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
D630C3DC2BC61B6100208903 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
|
||||||
CODE_SIGN_ENTITLEMENTS = NotificationExtension/NotificationExtension.entitlements;
|
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
|
||||||
CODE_SIGN_STYLE = Automatic;
|
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
|
||||||
INFOPLIST_FILE = NotificationExtension/Info.plist;
|
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = NotificationExtension;
|
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Shadowfacts. All rights reserved.";
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
"@executable_path/../../Frameworks",
|
|
||||||
);
|
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.NotificationExtension;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SKIP_INSTALL = YES;
|
|
||||||
SUPPORTS_MACCATALYST = YES;
|
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
D630C3DD2BC61B6100208903 /* Dist */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
|
||||||
CODE_SIGN_ENTITLEMENTS = NotificationExtension/NotificationExtension.entitlements;
|
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
|
||||||
CODE_SIGN_STYLE = Automatic;
|
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
|
||||||
INFOPLIST_FILE = NotificationExtension/Info.plist;
|
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = NotificationExtension;
|
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Shadowfacts. All rights reserved.";
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
"@executable_path/../../Frameworks",
|
|
||||||
);
|
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.NotificationExtension;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SKIP_INSTALL = YES;
|
|
||||||
SUPPORTS_MACCATALYST = YES;
|
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
};
|
|
||||||
name = Dist;
|
|
||||||
};
|
|
||||||
D63CC705290ECE77000E19DE /* Dist */ = {
|
D63CC705290ECE77000E19DE /* Dist */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D63CC703290EC472000E19DE /* Dist.xcconfig */;
|
baseConfigurationReference = D63CC703290EC472000E19DE /* Dist.xcconfig */;
|
||||||
|
@ -3117,16 +2934,6 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
D630C3DA2BC61B6100208903 /* Build configuration list for PBXNativeTarget "NotificationExtension" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
D630C3DB2BC61B6100208903 /* Debug */,
|
|
||||||
D630C3DC2BC61B6100208903 /* Release */,
|
|
||||||
D630C3DD2BC61B6100208903 /* Dist */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
D6A4532229EF64BA00032932 /* Build configuration list for PBXNativeTarget "ShareExtension" */ = {
|
D6A4532229EF64BA00032932 /* Build configuration list for PBXNativeTarget "ShareExtension" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
@ -3238,23 +3045,6 @@
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = PushNotifications;
|
productName = PushNotifications;
|
||||||
};
|
};
|
||||||
D630C3DE2BC61C4900208903 /* PushNotifications */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
productName = PushNotifications;
|
|
||||||
};
|
|
||||||
D630C3E02BC61C6700208903 /* UserAccounts */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
productName = UserAccounts;
|
|
||||||
};
|
|
||||||
D630C3E42BC6313400208903 /* Pachyderm */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
productName = Pachyderm;
|
|
||||||
};
|
|
||||||
D630C3E62BC6313F00208903 /* WebURLFoundationExtras */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D6676CA127A8D0020052936B /* XCRemoteSwiftPackageReference "swift-url" */;
|
|
||||||
productName = WebURLFoundationExtras;
|
|
||||||
};
|
|
||||||
D635237029B78A7D009ED5E7 /* TuskerComponents */ = {
|
D635237029B78A7D009ED5E7 /* TuskerComponents */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = TuskerComponents;
|
productName = TuskerComponents;
|
||||||
|
|
|
@ -47,10 +47,6 @@ public extension MainActor {
|
||||||
///
|
///
|
||||||
/// It will crash if run on any non-main thread.
|
/// It will crash if run on any non-main thread.
|
||||||
@_unavailableFromAsync
|
@_unavailableFromAsync
|
||||||
@available(macOS, obsoleted: 14.0)
|
|
||||||
@available(iOS, obsoleted: 17.0)
|
|
||||||
@available(watchOS, obsoleted: 10.0)
|
|
||||||
@available(tvOS, obsoleted: 17.0)
|
|
||||||
static func runUnsafely<T>(_ body: @MainActor () throws -> T) rethrows -> T {
|
static func runUnsafely<T>(_ body: @MainActor () throws -> T) rethrows -> T {
|
||||||
if #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) {
|
if #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) {
|
||||||
return try MainActor.assumeIsolated(body)
|
return try MainActor.assumeIsolated(body)
|
||||||
|
|
|
@ -108,7 +108,6 @@ struct PushInstanceSettingsView: View {
|
||||||
do {
|
do {
|
||||||
let result = try await mastodonController.updatePushSubscription(alerts: alerts, policy: policy)
|
let result = try await mastodonController.updatePushSubscription(alerts: alerts, policy: policy)
|
||||||
PushManager.logger.debug("Push subscription \(result.id) updated on \(account.instanceURL)")
|
PushManager.logger.debug("Push subscription \(result.id) updated on \(account.instanceURL)")
|
||||||
await PushManager.shared.updateSubscription(account: account, alerts: alerts, policy: policy)
|
|
||||||
subscription?.alerts = alerts
|
subscription?.alerts = alerts
|
||||||
subscription?.policy = policy
|
subscription?.policy = policy
|
||||||
return true
|
return true
|
||||||
|
|
Loading…
Reference in New Issue