Move push notifications stuff to separate package
This commit is contained in:
parent
f98589b419
commit
b03991ae1d
|
@ -0,0 +1,8 @@
|
||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
xcuserdata/
|
||||||
|
DerivedData/
|
||||||
|
.swiftpm/configuration/registries.json
|
||||||
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
|
.netrc
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1530"
|
||||||
|
version = "1.7">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES"
|
||||||
|
buildArchitectures = "Automatic">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "PushNotifications"
|
||||||
|
BuildableName = "PushNotifications"
|
||||||
|
BlueprintName = "PushNotifications"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
shouldAutocreateTestPlan = "YES">
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "PushNotifications"
|
||||||
|
BuildableName = "PushNotifications"
|
||||||
|
BlueprintName = "PushNotifications"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -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"]),
|
||||||
|
]
|
||||||
|
)
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -1,97 +1,17 @@
|
||||||
//
|
//
|
||||||
// PushManager.swift
|
// PushManagerImpl.swift
|
||||||
// Tusker
|
// PushNotifications
|
||||||
//
|
//
|
||||||
// Created by Shadowfacts on 4/6/24.
|
// Created by Shadowfacts on 4/7/24.
|
||||||
// Copyright © 2024 Shadowfacts. All rights reserved.
|
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import UIKit
|
||||||
import OSLog
|
import UserAccounts
|
||||||
#if canImport(Sentry)
|
#if canImport(Sentry)
|
||||||
import Sentry
|
import Sentry
|
||||||
#endif
|
#endif
|
||||||
import Pachyderm
|
|
||||||
import UserAccounts
|
|
||||||
|
|
||||||
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "PushManager")
|
class PushManagerImpl: _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 {
|
|
||||||
private let endpoint: URL
|
private let endpoint: URL
|
||||||
|
|
||||||
var enabled: Bool {
|
var enabled: Bool {
|
||||||
|
@ -148,13 +68,13 @@ private class PushManagerImpl: _PushManager {
|
||||||
throw PushRegistrationError.alreadyRegistering
|
throw PushRegistrationError.alreadyRegistering
|
||||||
}
|
}
|
||||||
let deviceToken = try await getDeviceToken().hexEncodedString()
|
let deviceToken = try await getDeviceToken().hexEncodedString()
|
||||||
logger.debug("Got device token: \(deviceToken)")
|
PushManager.logger.debug("Got device token: \(deviceToken)")
|
||||||
let registration: PushProxyRegistration
|
let registration: PushProxyRegistration
|
||||||
do {
|
do {
|
||||||
registration = try await register(deviceToken: deviceToken)
|
registration = try await register(deviceToken: deviceToken)
|
||||||
logger.debug("Got endpoint: \(registration.endpoint)")
|
PushManager.logger.debug("Got endpoint: \(registration.endpoint)")
|
||||||
} catch {
|
} catch {
|
||||||
logger.error("Proxy registration failed: \(String(describing: error))")
|
PushManager.logger.error("Proxy registration failed: \(String(describing: error))")
|
||||||
throw PushRegistrationError.registeringWithProxy(error)
|
throw PushRegistrationError.registeringWithProxy(error)
|
||||||
}
|
}
|
||||||
pushProxyRegistration = registration
|
pushProxyRegistration = registration
|
||||||
|
@ -173,9 +93,9 @@ private class PushManagerImpl: _PushManager {
|
||||||
let status = (resp as! HTTPURLResponse).statusCode
|
let status = (resp as! HTTPURLResponse).statusCode
|
||||||
if (200...299).contains(status) {
|
if (200...299).contains(status) {
|
||||||
self.pushProxyRegistration = nil
|
self.pushProxyRegistration = nil
|
||||||
logger.debug("Unregistered from proxy")
|
PushManager.logger.debug("Unregistered from proxy")
|
||||||
} else {
|
} 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)
|
let error = (try? JSONDecoder().decode(ProxyRegistrationError.self, from: data)) ?? ProxyRegistrationError(error: "Unknown error", fields: nil)
|
||||||
throw PushRegistrationError.unregistering(error)
|
throw PushRegistrationError.unregistering(error)
|
||||||
}
|
}
|
||||||
|
@ -185,7 +105,7 @@ private class PushManagerImpl: _PushManager {
|
||||||
guard let pushProxyRegistration else {
|
guard let pushProxyRegistration else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.debug("Push proxy registration: \(pushProxyRegistration.id, privacy: .public)")
|
PushManager.logger.debug("Push proxy registration: \(pushProxyRegistration.id, privacy: .public)")
|
||||||
do {
|
do {
|
||||||
let token = try await getDeviceToken().hexEncodedString()
|
let token = try await getDeviceToken().hexEncodedString()
|
||||||
guard token != pushProxyRegistration.deviceToken else {
|
guard token != pushProxyRegistration.deviceToken else {
|
||||||
|
@ -197,7 +117,7 @@ private class PushManagerImpl: _PushManager {
|
||||||
// TODO: update subscriptions if the endpoint's changed
|
// TODO: update subscriptions if the endpoint's changed
|
||||||
}
|
}
|
||||||
} catch {
|
} 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)
|
#if canImport(Sentry)
|
||||||
SentrySDK.capture(error: error)
|
SentrySDK.capture(error: error)
|
||||||
#endif
|
#endif
|
||||||
|
@ -232,7 +152,7 @@ private class PushManagerImpl: _PushManager {
|
||||||
let (data, resp) = try await URLSession.shared.data(for: request)
|
let (data, resp) = try await URLSession.shared.data(for: request)
|
||||||
let status = (resp as! HTTPURLResponse).statusCode
|
let status = (resp as! HTTPURLResponse).statusCode
|
||||||
guard (200...299).contains(status) else {
|
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: [])
|
let error = (try? JSONDecoder().decode(ProxyRegistrationError.self, from: data)) ?? ProxyRegistrationError(error: "Unknown error", fields: [])
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
@ -249,7 +169,7 @@ private class PushManagerImpl: _PushManager {
|
||||||
let (data, resp) = try await URLSession.shared.data(for: request)
|
let (data, resp) = try await URLSession.shared.data(for: request)
|
||||||
let status = (resp as! HTTPURLResponse).statusCode
|
let status = (resp as! HTTPURLResponse).statusCode
|
||||||
guard (200...299).contains(status) else {
|
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: [])
|
let error = (try? JSONDecoder().decode(ProxyRegistrationError.self, from: data)) ?? ProxyRegistrationError(error: "Unknown error", fields: [])
|
||||||
throw error
|
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 {
|
private extension Data {
|
||||||
func hexEncodedString() -> String {
|
func hexEncodedString() -> String {
|
||||||
String(unsafeUninitializedCapacity: count * 2) { buffer in
|
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,6 +92,7 @@
|
||||||
D62E9985279CA23900C26176 /* URLSession+Development.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9984279CA23900C26176 /* URLSession+Development.swift */; };
|
D62E9985279CA23900C26176 /* URLSession+Development.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9984279CA23900C26176 /* URLSession+Development.swift */; };
|
||||||
D62E9987279D094F00C26176 /* StatusMetaIndicatorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9986279D094F00C26176 /* StatusMetaIndicatorsView.swift */; };
|
D62E9987279D094F00C26176 /* StatusMetaIndicatorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9986279D094F00C26176 /* StatusMetaIndicatorsView.swift */; };
|
||||||
D62FF04823D7CDD700909D6E /* AttributedStringHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62FF04723D7CDD700909D6E /* AttributedStringHelperTests.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 */; };
|
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 */; };
|
||||||
|
@ -122,7 +123,6 @@
|
||||||
D64AAE9526C88C5000FC57FB /* ToastableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64AAE9426C88C5000FC57FB /* ToastableViewController.swift */; };
|
D64AAE9526C88C5000FC57FB /* ToastableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64AAE9426C88C5000FC57FB /* ToastableViewController.swift */; };
|
||||||
D64AAE9726C88DC400FC57FB /* ToastConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64AAE9626C88DC400FC57FB /* ToastConfiguration.swift */; };
|
D64AAE9726C88DC400FC57FB /* ToastConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64AAE9626C88DC400FC57FB /* ToastConfiguration.swift */; };
|
||||||
D64B967C2BC19C28002C8990 /* NotificationsPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64B967B2BC19C28002C8990 /* NotificationsPrefsView.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 */; };
|
D64B96812BC3279D002C8990 /* PrefsAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64B96802BC3279D002C8990 /* PrefsAccountView.swift */; };
|
||||||
D64B96842BC3893C002C8990 /* PushSubscriptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64B96832BC3893C002C8990 /* PushSubscriptionView.swift */; };
|
D64B96842BC3893C002C8990 /* PushSubscriptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64B96832BC3893C002C8990 /* PushSubscriptionView.swift */; };
|
||||||
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.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 = "<group>"; };
|
D64AAE9426C88C5000FC57FB /* ToastableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastableViewController.swift; sourceTree = "<group>"; };
|
||||||
D64AAE9626C88DC400FC57FB /* ToastConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastConfiguration.swift; sourceTree = "<group>"; };
|
D64AAE9626C88DC400FC57FB /* ToastConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastConfiguration.swift; sourceTree = "<group>"; };
|
||||||
D64B967B2BC19C28002C8990 /* NotificationsPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsPrefsView.swift; sourceTree = "<group>"; };
|
D64B967B2BC19C28002C8990 /* NotificationsPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsPrefsView.swift; sourceTree = "<group>"; };
|
||||||
D64B967E2BC1D447002C8990 /* PushManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushManager.swift; sourceTree = "<group>"; };
|
|
||||||
D64B96802BC3279D002C8990 /* PrefsAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsAccountView.swift; sourceTree = "<group>"; };
|
D64B96802BC3279D002C8990 /* PrefsAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsAccountView.swift; sourceTree = "<group>"; };
|
||||||
D64B96832BC3893C002C8990 /* PushSubscriptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushSubscriptionView.swift; sourceTree = "<group>"; };
|
D64B96832BC3893C002C8990 /* PushSubscriptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushSubscriptionView.swift; sourceTree = "<group>"; };
|
||||||
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; };
|
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -539,6 +538,7 @@
|
||||||
D659F36129541065002D944A /* TTTView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTTView.swift; sourceTree = "<group>"; };
|
D659F36129541065002D944A /* TTTView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTTView.swift; sourceTree = "<group>"; };
|
||||||
D65A261A2BC3928A005EB5D8 /* TriStateToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TriStateToggle.swift; sourceTree = "<group>"; };
|
D65A261A2BC3928A005EB5D8 /* TriStateToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TriStateToggle.swift; sourceTree = "<group>"; };
|
||||||
D65A261C2BC39399005EB5D8 /* PushInstanceSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushInstanceSettingsView.swift; sourceTree = "<group>"; };
|
D65A261C2BC39399005EB5D8 /* PushInstanceSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushInstanceSettingsView.swift; sourceTree = "<group>"; };
|
||||||
|
D65A26242BC39A02005EB5D8 /* PushNotifications */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = PushNotifications; sourceTree = "<group>"; };
|
||||||
D65B4B532971F71D00DABDFB /* EditedReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditedReport.swift; sourceTree = "<group>"; };
|
D65B4B532971F71D00DABDFB /* EditedReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditedReport.swift; sourceTree = "<group>"; };
|
||||||
D65B4B552971F98300DABDFB /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = "<group>"; };
|
D65B4B552971F98300DABDFB /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = "<group>"; };
|
||||||
D65B4B57297203A700DABDFB /* ReportSelectRulesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportSelectRulesView.swift; sourceTree = "<group>"; };
|
D65B4B57297203A700DABDFB /* ReportSelectRulesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportSelectRulesView.swift; sourceTree = "<group>"; };
|
||||||
|
@ -793,6 +793,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D6BD395929B64426005FFD2B /* ComposeUI in Frameworks */,
|
D6BD395929B64426005FFD2B /* ComposeUI in Frameworks */,
|
||||||
|
D630C3C82BC43AFD00208903 /* PushNotifications in Frameworks */,
|
||||||
D6FA94E129B52898006AAC51 /* InstanceFeatures in Frameworks */,
|
D6FA94E129B52898006AAC51 /* InstanceFeatures in Frameworks */,
|
||||||
D635237129B78A7D009ED5E7 /* TuskerComponents in Frameworks */,
|
D635237129B78A7D009ED5E7 /* TuskerComponents in Frameworks */,
|
||||||
D674A50927F9128D00BA03AC /* Pachyderm in Frameworks */,
|
D674A50927F9128D00BA03AC /* Pachyderm in Frameworks */,
|
||||||
|
@ -1181,6 +1182,7 @@
|
||||||
D6CA6ED029EF6060003EC5DF /* TuskerPreferences */,
|
D6CA6ED029EF6060003EC5DF /* TuskerPreferences */,
|
||||||
D6A9E04F29F8917500BEDC7E /* MatchedGeometryPresentation */,
|
D6A9E04F29F8917500BEDC7E /* MatchedGeometryPresentation */,
|
||||||
D642E83D2BA7AD0F004BFD6A /* GalleryVC */,
|
D642E83D2BA7AD0F004BFD6A /* GalleryVC */,
|
||||||
|
D65A26242BC39A02005EB5D8 /* PushNotifications */,
|
||||||
);
|
);
|
||||||
path = Packages;
|
path = Packages;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1195,14 +1197,6 @@
|
||||||
path = Toast;
|
path = Toast;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D64B967D2BC1D43A002C8990 /* Push */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D64B967E2BC1D447002C8990 /* PushManager.swift */,
|
|
||||||
);
|
|
||||||
path = Push;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D64B96822BC3892B002C8990 /* Notifications */ = {
|
D64B96822BC3892B002C8990 /* Notifications */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1551,7 +1545,6 @@
|
||||||
D6E57FA525C26FAB00341037 /* Localizable.stringsdict */,
|
D6E57FA525C26FAB00341037 /* Localizable.stringsdict */,
|
||||||
D61959D2241E846D00A37B8E /* Models */,
|
D61959D2241E846D00A37B8E /* Models */,
|
||||||
D663626021360A9600C9CBA2 /* Preferences */,
|
D663626021360A9600C9CBA2 /* Preferences */,
|
||||||
D64B967D2BC1D43A002C8990 /* Push */,
|
|
||||||
D63CC70A2910AAC6000E19DE /* Scenes */,
|
D63CC70A2910AAC6000E19DE /* Scenes */,
|
||||||
D641C780213DD7C4004B4513 /* Screens */,
|
D641C780213DD7C4004B4513 /* Screens */,
|
||||||
D62D241E217AA46B005076CC /* Shortcuts */,
|
D62D241E217AA46B005076CC /* Shortcuts */,
|
||||||
|
@ -1739,6 +1732,7 @@
|
||||||
D6CA6ED129EF6091003EC5DF /* TuskerPreferences */,
|
D6CA6ED129EF6091003EC5DF /* TuskerPreferences */,
|
||||||
D60BB3932B30076F00DAEA65 /* HTMLStreamer */,
|
D60BB3932B30076F00DAEA65 /* HTMLStreamer */,
|
||||||
D6934F2B2BA7AD32002B1C8D /* GalleryVC */,
|
D6934F2B2BA7AD32002B1C8D /* GalleryVC */,
|
||||||
|
D630C3C72BC43AFD00208903 /* PushNotifications */,
|
||||||
);
|
);
|
||||||
productName = Tusker;
|
productName = Tusker;
|
||||||
productReference = D6D4DDCC212518A000E1C4BB /* Tusker.app */;
|
productReference = D6D4DDCC212518A000E1C4BB /* Tusker.app */;
|
||||||
|
@ -2161,7 +2155,6 @@
|
||||||
D686BBE324FBF8110068E6AA /* WrappedProgressView.swift in Sources */,
|
D686BBE324FBF8110068E6AA /* WrappedProgressView.swift in Sources */,
|
||||||
D65A261B2BC3928A005EB5D8 /* TriStateToggle.swift in Sources */,
|
D65A261B2BC3928A005EB5D8 /* TriStateToggle.swift in Sources */,
|
||||||
D620483423D3801D008A63EF /* LinkTextView.swift in Sources */,
|
D620483423D3801D008A63EF /* LinkTextView.swift in Sources */,
|
||||||
D64B967F2BC1D447002C8990 /* PushManager.swift in Sources */,
|
|
||||||
D61F75882932DB6000C0B37F /* StatusSwipeActions.swift in Sources */,
|
D61F75882932DB6000C0B37F /* StatusSwipeActions.swift in Sources */,
|
||||||
D68A76EA295285D0001DA1B3 /* AddHashtagPinnedTimelineView.swift in Sources */,
|
D68A76EA295285D0001DA1B3 /* AddHashtagPinnedTimelineView.swift in Sources */,
|
||||||
D6F253CF2AC9F86300806D83 /* SearchTokenSuggestionCollectionViewCell.swift in Sources */,
|
D6F253CF2AC9F86300806D83 /* SearchTokenSuggestionCollectionViewCell.swift in Sources */,
|
||||||
|
@ -3044,6 +3037,10 @@
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = Pachyderm;
|
productName = Pachyderm;
|
||||||
};
|
};
|
||||||
|
D630C3C72BC43AFD00208903 /* PushNotifications */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = PushNotifications;
|
||||||
|
};
|
||||||
D635237029B78A7D009ED5E7 /* TuskerComponents */ = {
|
D635237029B78A7D009ED5E7 /* TuskerComponents */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = TuskerComponents;
|
productName = TuskerComponents;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import Sentry
|
||||||
import UserAccounts
|
import UserAccounts
|
||||||
import ComposeUI
|
import ComposeUI
|
||||||
import TuskerPreferences
|
import TuskerPreferences
|
||||||
|
import PushNotifications
|
||||||
|
|
||||||
typealias Preferences = TuskerPreferences.Preferences
|
typealias Preferences = TuskerPreferences.Preferences
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import UserNotifications
|
import UserNotifications
|
||||||
import UserAccounts
|
import UserAccounts
|
||||||
|
import PushNotifications
|
||||||
|
|
||||||
struct NotificationsPrefsView: View {
|
struct NotificationsPrefsView: View {
|
||||||
@State private var error: NotificationsSetupError?
|
@State private var error: NotificationsSetupError?
|
||||||
|
@ -19,8 +20,9 @@ struct NotificationsPrefsView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
List {
|
||||||
enableSection
|
enableSection
|
||||||
if isSetup == .on {
|
if isSetup == .on,
|
||||||
accountsSection
|
let pushProxyRegistration {
|
||||||
|
accountsSection(pushProxyRegistration: pushProxyRegistration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.listStyle(.insetGrouped)
|
.listStyle(.insetGrouped)
|
||||||
|
@ -53,10 +55,10 @@ struct NotificationsPrefsView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var accountsSection: some View {
|
private func accountsSection(pushProxyRegistration: PushProxyRegistration) -> some View {
|
||||||
Section {
|
Section {
|
||||||
ForEach(userAccounts.accounts) { account in
|
ForEach(userAccounts.accounts) { account in
|
||||||
PushInstanceSettingsView(account: account)
|
PushInstanceSettingsView(account: account, pushProxyRegistration: pushProxyRegistration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.appGroupedListRowBackground()
|
.appGroupedListRowBackground()
|
||||||
|
|
|
@ -9,11 +9,12 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import UserAccounts
|
import UserAccounts
|
||||||
import Pachyderm
|
import Pachyderm
|
||||||
|
import PushNotifications
|
||||||
|
|
||||||
struct PushInstanceSettingsView: View {
|
struct PushInstanceSettingsView: View {
|
||||||
let account: UserAccountInfo
|
let account: UserAccountInfo
|
||||||
let pushProxyRegistration: PushProxyRegistration
|
let pushProxyRegistration: PushProxyRegistration
|
||||||
@State private var mode: TriStateToggle.Mode
|
@State private var mode: TriStateToggle.Mode = .off
|
||||||
@State private var error: Error?
|
@State private var error: Error?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
@ -49,13 +50,13 @@ struct PushInstanceSettingsView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func enableNotifications() async throws {
|
private func enableNotifications() async throws {
|
||||||
let req = Pachyderm.PushSubscription.create(
|
// let req = Pachyderm.PushSubscription.create(
|
||||||
endpoint: pushProxyRegistration.endpoint,
|
// endpoint: pushProxyRegistration.endpoint,
|
||||||
publicKey: <#T##Data#>,
|
// publicKey: <#T##Data#>,
|
||||||
authSecret: <#T##Data#>,
|
// authSecret: <#T##Data#>,
|
||||||
alerts: <#T##PushSubscription.Alerts#>,
|
// alerts: <#T##PushSubscription.Alerts#>,
|
||||||
policy: <#T##PushSubscription.Policy#>
|
// policy: <#T##PushSubscription.Policy#>
|
||||||
)
|
// )
|
||||||
}
|
}
|
||||||
|
|
||||||
private func disableNotifications() async throws {
|
private func disableNotifications() async throws {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import UserAccounts
|
import UserAccounts
|
||||||
|
import PushNotifications
|
||||||
|
|
||||||
struct PushSubscriptionView: View {
|
struct PushSubscriptionView: View {
|
||||||
let account: UserAccountInfo
|
let account: UserAccountInfo
|
||||||
|
|
Loading…
Reference in New Issue