diff --git a/Packages/PushNotifications/.gitignore b/Packages/PushNotifications/.gitignore
new file mode 100644
index 00000000..0023a534
--- /dev/null
+++ b/Packages/PushNotifications/.gitignore
@@ -0,0 +1,8 @@
+.DS_Store
+/.build
+/Packages
+xcuserdata/
+DerivedData/
+.swiftpm/configuration/registries.json
+.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
+.netrc
diff --git a/Packages/PushNotifications/.swiftpm/xcode/xcshareddata/xcschemes/PushNotifications.xcscheme b/Packages/PushNotifications/.swiftpm/xcode/xcshareddata/xcschemes/PushNotifications.xcscheme
new file mode 100644
index 00000000..dc00e721
--- /dev/null
+++ b/Packages/PushNotifications/.swiftpm/xcode/xcshareddata/xcschemes/PushNotifications.xcscheme
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Packages/PushNotifications/Package.swift b/Packages/PushNotifications/Package.swift
new file mode 100644
index 00000000..aa1efd40
--- /dev/null
+++ b/Packages/PushNotifications/Package.swift
@@ -0,0 +1,26 @@
+// swift-tools-version: 5.10
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "PushNotifications",
+ platforms: [
+ .iOS(.v15),
+ ],
+ products: [
+ // Products define the executables and libraries a package produces, making them visible to other packages.
+ .library(
+ name: "PushNotifications",
+ targets: ["PushNotifications"]),
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package, defining a module or a test suite.
+ // Targets can depend on other targets in this package and products from dependencies.
+ .target(
+ name: "PushNotifications"),
+ .testTarget(
+ name: "PushNotificationsTests",
+ dependencies: ["PushNotifications"]),
+ ]
+)
diff --git a/Packages/PushNotifications/Sources/PushNotifications/DisabledPushManager.swift b/Packages/PushNotifications/Sources/PushNotifications/DisabledPushManager.swift
new file mode 100644
index 00000000..6a715a43
--- /dev/null
+++ b/Packages/PushNotifications/Sources/PushNotifications/DisabledPushManager.swift
@@ -0,0 +1,45 @@
+//
+// DisabledPushManager.swift
+// PushNotifications
+//
+// Created by Shadowfacts on 4/7/24.
+//
+
+import Foundation
+import UserAccounts
+
+class DisabledPushManager: _PushManager {
+ var enabled: Bool {
+ false
+ }
+
+ var pushProxyRegistration: PushProxyRegistration? {
+ nil
+ }
+
+ func pushSubscription(account: UserAccountInfo) -> PushSubscription? {
+ nil
+ }
+
+ func register(transactionID: UInt64) async throws -> PushProxyRegistration {
+ throw Disabled()
+ }
+
+ func unregister() async throws {
+ throw Disabled()
+ }
+
+ func updateIfNecessary() async {
+ }
+
+ func didRegisterForRemoteNotifications(deviceToken: Data) {
+ }
+ func didFailToRegisterForRemoteNotifications(error: any Error) {
+ }
+
+ struct Disabled: LocalizedError {
+ var errorDescription: String? {
+ "Push notifications disabled"
+ }
+ }
+}
diff --git a/Packages/PushNotifications/Sources/PushNotifications/PushManager.swift b/Packages/PushNotifications/Sources/PushNotifications/PushManager.swift
new file mode 100644
index 00000000..cd449e6d
--- /dev/null
+++ b/Packages/PushNotifications/Sources/PushNotifications/PushManager.swift
@@ -0,0 +1,56 @@
+//
+// PushManager.swift
+// PushNotifications
+//
+// Created by Shadowfacts on 4/7/24.
+//
+
+import Foundation
+import OSLog
+#if canImport(Sentry)
+import Sentry
+#endif
+import Pachyderm
+import UserAccounts
+
+public struct PushManager {
+ @MainActor
+ public static let shared = createPushManager()
+
+ static let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "PushManager")
+
+ private init() {}
+
+ @MainActor
+ private static func createPushManager() -> any _PushManager {
+ guard let info = Bundle.main.object(forInfoDictionaryKey: "TuskerInfo") as? [String: Any],
+ let scheme = info["PushProxyScheme"] as? String,
+ let host = info["PushProxyHost"] as? String,
+ !scheme.isEmpty,
+ !host.isEmpty else {
+ logger.debug("Missing proxy info, push disabled")
+ return DisabledPushManager()
+ }
+ var endpoint = URLComponents()
+ endpoint.scheme = scheme
+ endpoint.host = host
+ let url = endpoint.url!
+ logger.debug("Push notifications enabled with proxy \(url.absoluteString, privacy: .public)")
+ return PushManagerImpl(endpoint: url)
+ }
+}
+
+@MainActor
+public protocol _PushManager {
+ var enabled: Bool { get }
+ var pushProxyRegistration: PushProxyRegistration? { get }
+
+ func pushSubscription(account: UserAccountInfo) -> PushSubscription?
+
+ func register(transactionID: UInt64) async throws -> PushProxyRegistration
+ func unregister() async throws
+ func updateIfNecessary() async
+
+ func didRegisterForRemoteNotifications(deviceToken: Data)
+ func didFailToRegisterForRemoteNotifications(error: any Error)
+}
diff --git a/Tusker/Push/PushManager.swift b/Packages/PushNotifications/Sources/PushNotifications/PushManagerImpl.swift
similarity index 61%
rename from Tusker/Push/PushManager.swift
rename to Packages/PushNotifications/Sources/PushNotifications/PushManagerImpl.swift
index ac6267fa..ed7bb81f 100644
--- a/Tusker/Push/PushManager.swift
+++ b/Packages/PushNotifications/Sources/PushNotifications/PushManagerImpl.swift
@@ -1,97 +1,17 @@
//
-// PushManager.swift
-// Tusker
+// PushManagerImpl.swift
+// PushNotifications
//
-// Created by Shadowfacts on 4/6/24.
-// Copyright © 2024 Shadowfacts. All rights reserved.
+// Created by Shadowfacts on 4/7/24.
//
-import Foundation
-import OSLog
+import UIKit
+import UserAccounts
#if canImport(Sentry)
import Sentry
#endif
-import Pachyderm
-import UserAccounts
-private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "PushManager")
-
-@MainActor
-struct PushManager {
- static let shared = createPushManager()
-
- private init() {}
-
- private static func createPushManager() -> any _PushManager {
- guard let info = Bundle.main.object(forInfoDictionaryKey: "TuskerInfo") as? [String: Any],
- let scheme = info["PushProxyScheme"] as? String,
- let host = info["PushProxyHost"] as? String,
- !scheme.isEmpty,
- !host.isEmpty else {
- logger.debug("Missing proxy info, push disabled")
- return DisabledPushManager()
- }
- var endpoint = URLComponents()
- endpoint.scheme = scheme
- endpoint.host = host
- let url = endpoint.url!
- logger.debug("Push notifications enabled with proxy \(url.absoluteString, privacy: .public)")
- return PushManagerImpl(endpoint: url)
- }
-}
-
-@MainActor
-protocol _PushManager {
- var enabled: Bool { get }
- var pushProxyRegistration: PushProxyRegistration? { get }
-
- func pushSubscription(account: UserAccountInfo) -> PushSubscription?
-
- func register(transactionID: UInt64) async throws -> PushProxyRegistration
- func unregister() async throws
- func updateIfNecessary() async
-
- func didRegisterForRemoteNotifications(deviceToken: Data)
- func didFailToRegisterForRemoteNotifications(error: any Error)
-}
-
-private class DisabledPushManager: _PushManager {
- var enabled: Bool {
- false
- }
-
- var pushProxyRegistration: PushProxyRegistration? {
- nil
- }
-
- func pushSubscription(account: UserAccountInfo) -> PushSubscription? {
- nil
- }
-
- func register(transactionID: UInt64) async throws -> PushProxyRegistration {
- throw Disabled()
- }
-
- func unregister() async throws {
- throw Disabled()
- }
-
- func updateIfNecessary() async {
- }
-
- func didRegisterForRemoteNotifications(deviceToken: Data) {
- }
- func didFailToRegisterForRemoteNotifications(error: any Error) {
- }
-
- struct Disabled: LocalizedError {
- var errorDescription: String? {
- "Push notifications disabled"
- }
- }
-}
-
-private class PushManagerImpl: _PushManager {
+class PushManagerImpl: _PushManager {
private let endpoint: URL
var enabled: Bool {
@@ -148,13 +68,13 @@ private class PushManagerImpl: _PushManager {
throw PushRegistrationError.alreadyRegistering
}
let deviceToken = try await getDeviceToken().hexEncodedString()
- logger.debug("Got device token: \(deviceToken)")
+ PushManager.logger.debug("Got device token: \(deviceToken)")
let registration: PushProxyRegistration
do {
registration = try await register(deviceToken: deviceToken)
- logger.debug("Got endpoint: \(registration.endpoint)")
+ PushManager.logger.debug("Got endpoint: \(registration.endpoint)")
} catch {
- logger.error("Proxy registration failed: \(String(describing: error))")
+ PushManager.logger.error("Proxy registration failed: \(String(describing: error))")
throw PushRegistrationError.registeringWithProxy(error)
}
pushProxyRegistration = registration
@@ -173,9 +93,9 @@ private class PushManagerImpl: _PushManager {
let status = (resp as! HTTPURLResponse).statusCode
if (200...299).contains(status) {
self.pushProxyRegistration = nil
- logger.debug("Unregistered from proxy")
+ PushManager.logger.debug("Unregistered from proxy")
} else {
- logger.error("Unregistering: unexpected status \(status)")
+ PushManager.logger.error("Unregistering: unexpected status \(status)")
let error = (try? JSONDecoder().decode(ProxyRegistrationError.self, from: data)) ?? ProxyRegistrationError(error: "Unknown error", fields: nil)
throw PushRegistrationError.unregistering(error)
}
@@ -185,7 +105,7 @@ private class PushManagerImpl: _PushManager {
guard let pushProxyRegistration else {
return
}
- logger.debug("Push proxy registration: \(pushProxyRegistration.id, privacy: .public)")
+ PushManager.logger.debug("Push proxy registration: \(pushProxyRegistration.id, privacy: .public)")
do {
let token = try await getDeviceToken().hexEncodedString()
guard token != pushProxyRegistration.deviceToken else {
@@ -197,7 +117,7 @@ private class PushManagerImpl: _PushManager {
// TODO: update subscriptions if the endpoint's changed
}
} catch {
- logger.error("Failed to update push registration: \(String(describing: error), privacy: .public)")
+ PushManager.logger.error("Failed to update push registration: \(String(describing: error), privacy: .public)")
#if canImport(Sentry)
SentrySDK.capture(error: error)
#endif
@@ -232,7 +152,7 @@ private class PushManagerImpl: _PushManager {
let (data, resp) = try await URLSession.shared.data(for: request)
let status = (resp as! HTTPURLResponse).statusCode
guard (200...299).contains(status) else {
- logger.error("Registering: unexpected status \(status)")
+ PushManager.logger.error("Registering: unexpected status \(status)")
let error = (try? JSONDecoder().decode(ProxyRegistrationError.self, from: data)) ?? ProxyRegistrationError(error: "Unknown error", fields: [])
throw error
}
@@ -249,7 +169,7 @@ private class PushManagerImpl: _PushManager {
let (data, resp) = try await URLSession.shared.data(for: request)
let status = (resp as! HTTPURLResponse).statusCode
guard (200...299).contains(status) else {
- logger.error("Updating: unexpected status \(status)")
+ PushManager.logger.error("Updating: unexpected status \(status)")
let error = (try? JSONDecoder().decode(ProxyRegistrationError.self, from: data)) ?? ProxyRegistrationError(error: "Unknown error", fields: [])
throw error
}
@@ -322,37 +242,6 @@ private struct PushUpdateParams: Encodable {
}
}
-struct PushProxyRegistration: Decodable {
- let id: String
- let endpoint: URL
- let deviceToken: String
-
- fileprivate var defaultsDict: [String: String] {
- [
- "id": id,
- "endpoint": endpoint.absoluteString,
- "deviceToken": deviceToken,
- ]
- }
-
- fileprivate init?(defaultsDict: [String: String]) {
- guard let id = defaultsDict["id"],
- let endpoint = defaultsDict["endpoint"].flatMap(URL.init(string:)),
- let deviceToken = defaultsDict["deviceToken"] else {
- return nil
- }
- self.id = id
- self.endpoint = endpoint
- self.deviceToken = deviceToken
- }
-
- private enum CodingKeys: String, CodingKey {
- case id
- case endpoint
- case deviceToken = "device_token"
- }
-}
-
private extension Data {
func hexEncodedString() -> String {
String(unsafeUninitializedCapacity: count * 2) { buffer in
@@ -366,49 +255,3 @@ private extension Data {
}
}
}
-
-struct PushSubscription {
- let accountID: String
- let endpoint: URL
- let alerts: Alerts
- let policy: Policy
-
- fileprivate var defaultsDict: [String: Any] {
- [
- "accountID": accountID,
- "endpoint": endpoint.absoluteString,
- "alerts": alerts.rawValue,
- "policy": policy.rawValue
- ]
- }
-
- init?(defaultsDict: [String: Any]) {
- guard let accountID = defaultsDict["accountID"] as? String,
- let endpoint = (defaultsDict["endpoint"] as? String).flatMap(URL.init(string:)),
- let alerts = defaultsDict["alerts"] as? Int,
- let policy = (defaultsDict["policy"] as? String).flatMap(Policy.init(rawValue:)) else {
- return nil
- }
- self.accountID = accountID
- self.endpoint = endpoint
- self.alerts = Alerts(rawValue: alerts)
- self.policy = policy
- }
-
- enum Policy: String {
- case all, followed, followers
- }
-
- struct Alerts: OptionSet {
- static let mention = Alerts(rawValue: 1 << 0)
- static let status = Alerts(rawValue: 1 << 1)
- static let reblog = Alerts(rawValue: 1 << 2)
- static let follow = Alerts(rawValue: 1 << 3)
- static let followRequest = Alerts(rawValue: 1 << 4)
- static let favorite = Alerts(rawValue: 1 << 5)
- static let poll = Alerts(rawValue: 1 << 6)
- static let update = Alerts(rawValue: 1 << 7)
-
- let rawValue: Int
- }
-}
diff --git a/Packages/PushNotifications/Sources/PushNotifications/PushProxyRegistration.swift b/Packages/PushNotifications/Sources/PushNotifications/PushProxyRegistration.swift
new file mode 100644
index 00000000..395cda90
--- /dev/null
+++ b/Packages/PushNotifications/Sources/PushNotifications/PushProxyRegistration.swift
@@ -0,0 +1,39 @@
+//
+// PushProxyRegistration.swift
+// PushNotifications
+//
+// Created by Shadowfacts on 4/7/24.
+//
+
+import Foundation
+
+public struct PushProxyRegistration: Decodable {
+ let id: String
+ let endpoint: URL
+ let deviceToken: String
+
+ var defaultsDict: [String: String] {
+ [
+ "id": id,
+ "endpoint": endpoint.absoluteString,
+ "deviceToken": deviceToken,
+ ]
+ }
+
+ init?(defaultsDict: [String: String]) {
+ guard let id = defaultsDict["id"],
+ let endpoint = defaultsDict["endpoint"].flatMap(URL.init(string:)),
+ let deviceToken = defaultsDict["deviceToken"] else {
+ return nil
+ }
+ self.id = id
+ self.endpoint = endpoint
+ self.deviceToken = deviceToken
+ }
+
+ private enum CodingKeys: String, CodingKey {
+ case id
+ case endpoint
+ case deviceToken = "device_token"
+ }
+}
diff --git a/Packages/PushNotifications/Sources/PushNotifications/PushSubscription.swift b/Packages/PushNotifications/Sources/PushNotifications/PushSubscription.swift
new file mode 100644
index 00000000..4003a4eb
--- /dev/null
+++ b/Packages/PushNotifications/Sources/PushNotifications/PushSubscription.swift
@@ -0,0 +1,54 @@
+//
+// PushSubscription.swift
+// PushNotifications
+//
+// Created by Shadowfacts on 4/7/24.
+//
+
+import Foundation
+
+public struct PushSubscription {
+ let accountID: String
+ let endpoint: URL
+ let alerts: Alerts
+ let policy: Policy
+
+ var defaultsDict: [String: Any] {
+ [
+ "accountID": accountID,
+ "endpoint": endpoint.absoluteString,
+ "alerts": alerts.rawValue,
+ "policy": policy.rawValue
+ ]
+ }
+
+ init?(defaultsDict: [String: Any]) {
+ guard let accountID = defaultsDict["accountID"] as? String,
+ let endpoint = (defaultsDict["endpoint"] as? String).flatMap(URL.init(string:)),
+ let alerts = defaultsDict["alerts"] as? Int,
+ let policy = (defaultsDict["policy"] as? String).flatMap(Policy.init(rawValue:)) else {
+ return nil
+ }
+ self.accountID = accountID
+ self.endpoint = endpoint
+ self.alerts = Alerts(rawValue: alerts)
+ self.policy = policy
+ }
+
+ enum Policy: String {
+ case all, followed, followers
+ }
+
+ struct Alerts: OptionSet {
+ static let mention = Alerts(rawValue: 1 << 0)
+ static let status = Alerts(rawValue: 1 << 1)
+ static let reblog = Alerts(rawValue: 1 << 2)
+ static let follow = Alerts(rawValue: 1 << 3)
+ static let followRequest = Alerts(rawValue: 1 << 4)
+ static let favorite = Alerts(rawValue: 1 << 5)
+ static let poll = Alerts(rawValue: 1 << 6)
+ static let update = Alerts(rawValue: 1 << 7)
+
+ let rawValue: Int
+ }
+}
diff --git a/Packages/PushNotifications/Tests/PushNotificationsTests/PushNotificationsTests.swift b/Packages/PushNotifications/Tests/PushNotificationsTests/PushNotificationsTests.swift
new file mode 100644
index 00000000..d36eb331
--- /dev/null
+++ b/Packages/PushNotifications/Tests/PushNotificationsTests/PushNotificationsTests.swift
@@ -0,0 +1,12 @@
+import XCTest
+@testable import PushNotifications
+
+final class PushNotificationsTests: XCTestCase {
+ func testExample() throws {
+ // XCTest Documentation
+ // https://developer.apple.com/documentation/xctest
+
+ // Defining Test Cases and Test Methods
+ // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
+ }
+}
diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj
index ad9973fb..f2e6a02a 100644
--- a/Tusker.xcodeproj/project.pbxproj
+++ b/Tusker.xcodeproj/project.pbxproj
@@ -92,6 +92,7 @@
D62E9985279CA23900C26176 /* URLSession+Development.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9984279CA23900C26176 /* URLSession+Development.swift */; };
D62E9987279D094F00C26176 /* StatusMetaIndicatorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9986279D094F00C26176 /* StatusMetaIndicatorsView.swift */; };
D62FF04823D7CDD700909D6E /* AttributedStringHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62FF04723D7CDD700909D6E /* AttributedStringHelperTests.swift */; };
+ D630C3C82BC43AFD00208903 /* PushNotifications in Frameworks */ = {isa = PBXBuildFile; productRef = D630C3C72BC43AFD00208903 /* PushNotifications */; };
D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6311C4F25B3765B00B27539 /* ImageDataCache.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 */; };
@@ -122,7 +123,6 @@
D64AAE9526C88C5000FC57FB /* ToastableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64AAE9426C88C5000FC57FB /* ToastableViewController.swift */; };
D64AAE9726C88DC400FC57FB /* ToastConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64AAE9626C88DC400FC57FB /* ToastConfiguration.swift */; };
D64B967C2BC19C28002C8990 /* NotificationsPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64B967B2BC19C28002C8990 /* NotificationsPrefsView.swift */; };
- D64B967F2BC1D447002C8990 /* PushManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64B967E2BC1D447002C8990 /* PushManager.swift */; };
D64B96812BC3279D002C8990 /* PrefsAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64B96802BC3279D002C8990 /* PrefsAccountView.swift */; };
D64B96842BC3893C002C8990 /* PushSubscriptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64B96832BC3893C002C8990 /* PushSubscriptionView.swift */; };
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; };
@@ -528,7 +528,6 @@
D64AAE9426C88C5000FC57FB /* ToastableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastableViewController.swift; sourceTree = ""; };
D64AAE9626C88DC400FC57FB /* ToastConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastConfiguration.swift; sourceTree = ""; };
D64B967B2BC19C28002C8990 /* NotificationsPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsPrefsView.swift; sourceTree = ""; };
- D64B967E2BC1D447002C8990 /* PushManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushManager.swift; sourceTree = ""; };
D64B96802BC3279D002C8990 /* PrefsAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsAccountView.swift; sourceTree = ""; };
D64B96832BC3893C002C8990 /* PushSubscriptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushSubscriptionView.swift; sourceTree = ""; };
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = ""; };
@@ -539,6 +538,7 @@
D659F36129541065002D944A /* TTTView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTTView.swift; sourceTree = ""; };
D65A261A2BC3928A005EB5D8 /* TriStateToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TriStateToggle.swift; sourceTree = ""; };
D65A261C2BC39399005EB5D8 /* PushInstanceSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushInstanceSettingsView.swift; sourceTree = ""; };
+ D65A26242BC39A02005EB5D8 /* PushNotifications */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = PushNotifications; sourceTree = ""; };
D65B4B532971F71D00DABDFB /* EditedReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditedReport.swift; sourceTree = ""; };
D65B4B552971F98300DABDFB /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = ""; };
D65B4B57297203A700DABDFB /* ReportSelectRulesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportSelectRulesView.swift; sourceTree = ""; };
@@ -793,6 +793,7 @@
buildActionMask = 2147483647;
files = (
D6BD395929B64426005FFD2B /* ComposeUI in Frameworks */,
+ D630C3C82BC43AFD00208903 /* PushNotifications in Frameworks */,
D6FA94E129B52898006AAC51 /* InstanceFeatures in Frameworks */,
D635237129B78A7D009ED5E7 /* TuskerComponents in Frameworks */,
D674A50927F9128D00BA03AC /* Pachyderm in Frameworks */,
@@ -1181,6 +1182,7 @@
D6CA6ED029EF6060003EC5DF /* TuskerPreferences */,
D6A9E04F29F8917500BEDC7E /* MatchedGeometryPresentation */,
D642E83D2BA7AD0F004BFD6A /* GalleryVC */,
+ D65A26242BC39A02005EB5D8 /* PushNotifications */,
);
path = Packages;
sourceTree = "";
@@ -1195,14 +1197,6 @@
path = Toast;
sourceTree = "";
};
- D64B967D2BC1D43A002C8990 /* Push */ = {
- isa = PBXGroup;
- children = (
- D64B967E2BC1D447002C8990 /* PushManager.swift */,
- );
- path = Push;
- sourceTree = "";
- };
D64B96822BC3892B002C8990 /* Notifications */ = {
isa = PBXGroup;
children = (
@@ -1551,7 +1545,6 @@
D6E57FA525C26FAB00341037 /* Localizable.stringsdict */,
D61959D2241E846D00A37B8E /* Models */,
D663626021360A9600C9CBA2 /* Preferences */,
- D64B967D2BC1D43A002C8990 /* Push */,
D63CC70A2910AAC6000E19DE /* Scenes */,
D641C780213DD7C4004B4513 /* Screens */,
D62D241E217AA46B005076CC /* Shortcuts */,
@@ -1739,6 +1732,7 @@
D6CA6ED129EF6091003EC5DF /* TuskerPreferences */,
D60BB3932B30076F00DAEA65 /* HTMLStreamer */,
D6934F2B2BA7AD32002B1C8D /* GalleryVC */,
+ D630C3C72BC43AFD00208903 /* PushNotifications */,
);
productName = Tusker;
productReference = D6D4DDCC212518A000E1C4BB /* Tusker.app */;
@@ -2161,7 +2155,6 @@
D686BBE324FBF8110068E6AA /* WrappedProgressView.swift in Sources */,
D65A261B2BC3928A005EB5D8 /* TriStateToggle.swift in Sources */,
D620483423D3801D008A63EF /* LinkTextView.swift in Sources */,
- D64B967F2BC1D447002C8990 /* PushManager.swift in Sources */,
D61F75882932DB6000C0B37F /* StatusSwipeActions.swift in Sources */,
D68A76EA295285D0001DA1B3 /* AddHashtagPinnedTimelineView.swift in Sources */,
D6F253CF2AC9F86300806D83 /* SearchTokenSuggestionCollectionViewCell.swift in Sources */,
@@ -3044,6 +3037,10 @@
isa = XCSwiftPackageProductDependency;
productName = Pachyderm;
};
+ D630C3C72BC43AFD00208903 /* PushNotifications */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = PushNotifications;
+ };
D635237029B78A7D009ED5E7 /* TuskerComponents */ = {
isa = XCSwiftPackageProductDependency;
productName = TuskerComponents;
diff --git a/Tusker/AppDelegate.swift b/Tusker/AppDelegate.swift
index d53d231f..6a7cc075 100644
--- a/Tusker/AppDelegate.swift
+++ b/Tusker/AppDelegate.swift
@@ -15,6 +15,7 @@ import Sentry
import UserAccounts
import ComposeUI
import TuskerPreferences
+import PushNotifications
typealias Preferences = TuskerPreferences.Preferences
diff --git a/Tusker/Screens/Preferences/Notifications/NotificationsPrefsView.swift b/Tusker/Screens/Preferences/Notifications/NotificationsPrefsView.swift
index 94676603..1717ce5d 100644
--- a/Tusker/Screens/Preferences/Notifications/NotificationsPrefsView.swift
+++ b/Tusker/Screens/Preferences/Notifications/NotificationsPrefsView.swift
@@ -9,6 +9,7 @@
import SwiftUI
import UserNotifications
import UserAccounts
+import PushNotifications
struct NotificationsPrefsView: View {
@State private var error: NotificationsSetupError?
@@ -19,8 +20,9 @@ struct NotificationsPrefsView: View {
var body: some View {
List {
enableSection
- if isSetup == .on {
- accountsSection
+ if isSetup == .on,
+ let pushProxyRegistration {
+ accountsSection(pushProxyRegistration: pushProxyRegistration)
}
}
.listStyle(.insetGrouped)
@@ -53,10 +55,10 @@ struct NotificationsPrefsView: View {
}
}
- private var accountsSection: some View {
+ private func accountsSection(pushProxyRegistration: PushProxyRegistration) -> some View {
Section {
ForEach(userAccounts.accounts) { account in
- PushInstanceSettingsView(account: account)
+ PushInstanceSettingsView(account: account, pushProxyRegistration: pushProxyRegistration)
}
}
.appGroupedListRowBackground()
diff --git a/Tusker/Screens/Preferences/Notifications/PushInstanceSettingsView.swift b/Tusker/Screens/Preferences/Notifications/PushInstanceSettingsView.swift
index 9206f102..fac58441 100644
--- a/Tusker/Screens/Preferences/Notifications/PushInstanceSettingsView.swift
+++ b/Tusker/Screens/Preferences/Notifications/PushInstanceSettingsView.swift
@@ -9,11 +9,12 @@
import SwiftUI
import UserAccounts
import Pachyderm
+import PushNotifications
struct PushInstanceSettingsView: View {
let account: UserAccountInfo
let pushProxyRegistration: PushProxyRegistration
- @State private var mode: TriStateToggle.Mode
+ @State private var mode: TriStateToggle.Mode = .off
@State private var error: Error?
var body: some View {
@@ -49,13 +50,13 @@ struct PushInstanceSettingsView: View {
}
private func enableNotifications() async throws {
- let req = Pachyderm.PushSubscription.create(
- endpoint: pushProxyRegistration.endpoint,
- publicKey: <#T##Data#>,
- authSecret: <#T##Data#>,
- alerts: <#T##PushSubscription.Alerts#>,
- policy: <#T##PushSubscription.Policy#>
- )
+// let req = Pachyderm.PushSubscription.create(
+// endpoint: pushProxyRegistration.endpoint,
+// publicKey: <#T##Data#>,
+// authSecret: <#T##Data#>,
+// alerts: <#T##PushSubscription.Alerts#>,
+// policy: <#T##PushSubscription.Policy#>
+// )
}
private func disableNotifications() async throws {
diff --git a/Tusker/Screens/Preferences/Notifications/PushSubscriptionView.swift b/Tusker/Screens/Preferences/Notifications/PushSubscriptionView.swift
index eac3dbbf..02c6604b 100644
--- a/Tusker/Screens/Preferences/Notifications/PushSubscriptionView.swift
+++ b/Tusker/Screens/Preferences/Notifications/PushSubscriptionView.swift
@@ -8,6 +8,7 @@
import SwiftUI
import UserAccounts
+import PushNotifications
struct PushSubscriptionView: View {
let account: UserAccountInfo