From 89b62b4c669130f7df3e9ad63c35ee976dabb77d Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 14 Mar 2024 11:23:21 -0700 Subject: [PATCH] HMAC Push notification updates (#283) * generate new iOS proto code for pushes * add new subscribe with metadata method to the push server * create a type alias * add the implementation side * Update if/def to include typealias declarations Also update connect-swift package version. --------- Co-authored-by: Ethan Mateja --- Package.resolved | 42 +- Package.swift | 2 +- Sources/XMTPiOS/Push/XMTPPush.swift | 217 ++--- Sources/XMTPiOS/Push/service.connect.swift | 80 +- Sources/XMTPiOS/Push/service.pb.swift | 794 +++++++++++------- .../Views/ConversationListView.swift | 17 +- 6 files changed, 717 insertions(+), 435 deletions(-) diff --git a/Package.resolved b/Package.resolved index d2e8c1d2..61972371 100644 --- a/Package.resolved +++ b/Package.resolved @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/bufbuild/connect-swift", "state" : { - "revision" : "6f5afc57f44a3ed15b9a01381ce73f84d15e43db", - "version" : "0.3.0" + "revision" : "1701d3d1b2c4c63fcccfd7094f86a88672fa5acb", + "version" : "0.12.0" } }, { @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/xmtp/libxmtp-swift", "state" : { - "revision" : "28ee27a4ded8b996a74850e366247e9fe51d782a", - "version" : "0.4.2-beta4" + "revision" : "f8c4be0d591671067c8e7772b7c402931f33ed54", + "version" : "0.4.3-beta1" } }, { @@ -59,8 +59,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-atomics.git", "state" : { - "revision" : "919eb1d83e02121cdb434c7bfc1f0c66ef17febe", - "version" : "1.0.2" + "revision" : "cd142fd2f64be2100422d658e7411e39489da985", + "version" : "1.2.0" } }, { @@ -104,8 +104,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio.git", "state" : { - "revision" : "edfceecba13d68c1c993382806e72f7e96feaa86", - "version" : "2.44.0" + "revision" : "fc63f0cf4e55a4597407a9fc95b16a2bc44b4982", + "version" : "2.64.0" + } + }, + { + "identity" : "swift-nio-http2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-http2.git", + "state" : { + "revision" : "0904bf0feb5122b7e5c3f15db7df0eabe623dd87", + "version" : "1.30.0" } }, { @@ -113,8 +122,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-ssl.git", "state" : { - "revision" : "4fb7ead803e38949eb1d6fabb849206a72c580f3", - "version" : "2.23.0" + "revision" : "7c381eb6083542b124a6c18fae742f55001dc2b5", + "version" : "2.26.0" } }, { @@ -131,8 +140,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-protobuf.git", "state" : { - "revision" : "ab3a58b7209a17d781c0d1dbb3e1ff3da306bae8", - "version" : "1.20.3" + "revision" : "65e8f29b2d63c4e38e736b25c27b83e012159be8", + "version" : "1.25.2" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "025bcb1165deab2e20d4eaba79967ce73013f496", + "version" : "1.2.1" } }, { diff --git a/Package.swift b/Package.swift index 547935f9..18d4630e 100644 --- a/Package.swift +++ b/Package.swift @@ -23,7 +23,7 @@ let package = Package( .package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", exact: "0.10.0"), .package(url: "https://github.com/argentlabs/web3.swift", from: "1.1.0"), .package(url: "https://github.com/1024jp/GzipSwift", from: "5.2.0"), - .package(url: "https://github.com/bufbuild/connect-swift", exact: "0.3.0"), + .package(url: "https://github.com/bufbuild/connect-swift", exact: "0.12.0"), .package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.0.0"), .package(url: "https://github.com/xmtp/libxmtp-swift", exact: "0.4.3-beta2"), ], diff --git a/Sources/XMTPiOS/Push/XMTPPush.swift b/Sources/XMTPiOS/Push/XMTPPush.swift index c6a0b7b9..e65ec2b7 100644 --- a/Sources/XMTPiOS/Push/XMTPPush.swift +++ b/Sources/XMTPiOS/Push/XMTPPush.swift @@ -4,134 +4,157 @@ // // Created by Pat Nakajima on 1/20/23. // -#if canImport(UIKit) - import Connect - import UIKit - import UserNotifications - enum XMTPPushError: Error { - case noPushServer - } +import Connect - public struct XMTPPush { - public static var shared = XMTPPush() +import UserNotifications - var installationID: String - var installationIDKey: String = "installationID" +public typealias NotificationSubscription = Notifications_V1_Subscription +public typealias NotificationSubscriptionHmacKey = Notifications_V1_Subscription.HmacKey - var pushServer: String = "" +enum XMTPPushError: Error { + case noPushServer +} - private init() { - if let id = UserDefaults.standard.string(forKey: installationIDKey) { - installationID = id - } else { - installationID = UUID().uuidString - UserDefaults.standard.set(installationID, forKey: installationIDKey) - } - } +#if canImport(UIKit) +import UIKit - public mutating func setPushServer(_ server: String) { - pushServer = server - } +public struct XMTPPush { + public static var shared = XMTPPush() - public func request() async throws -> Bool { - if pushServer == "" { - throw XMTPPushError.noPushServer - } + var installationID: String + var installationIDKey: String = "installationID" - if try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge]) { -// await UIApplication.shared.registerForRemoteNotifications() + var pushServer: String = "" - return true - } + private init() { + if let id = UserDefaults.standard.string(forKey: installationIDKey) { + installationID = id + } else { + installationID = UUID().uuidString + UserDefaults.standard.set(installationID, forKey: installationIDKey) + } + } - return false + public mutating func setPushServer(_ server: String) { + pushServer = server + } + + public func request() async throws -> Bool { + if pushServer == "" { + throw XMTPPushError.noPushServer } - public func register(token: String) async throws { - if pushServer == "" { - throw XMTPPushError.noPushServer - } + if try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge]) { +// await UIApplication.shared.registerForRemoteNotifications() - let request = Notifications_V1_RegisterInstallationRequest.with { request in - request.installationID = installationID - request.deliveryMechanism = Notifications_V1_DeliveryMechanism.with { delivery in - delivery.apnsDeviceToken = token - delivery.deliveryMechanismType = .apnsDeviceToken(token) - } - } + return true + } - _ = await client.registerInstallation(request: request) + return false + } + + public func register(token: String) async throws { + if pushServer == "" { + throw XMTPPushError.noPushServer } - public func subscribe(topics: [String]) async throws { - if pushServer == "" { - throw XMTPPushError.noPushServer + let request = Notifications_V1_RegisterInstallationRequest.with { request in + request.installationID = installationID + request.deliveryMechanism = Notifications_V1_DeliveryMechanism.with { delivery in + delivery.apnsDeviceToken = token + delivery.deliveryMechanismType = .apnsDeviceToken(token) } + } - let request = Notifications_V1_SubscribeRequest.with { request in - request.installationID = installationID - request.topics = topics - } + _ = await client.registerInstallation(request: request) + } - _ = await client.subscribe(request: request) + public func subscribe(topics: [String]) async throws { + if pushServer == "" { + throw XMTPPushError.noPushServer } - - public func unsubscribe(topics: [String]) async throws { - if pushServer == "" { - throw XMTPPushError.noPushServer - } - - let request = Notifications_V1_UnsubscribeRequest.with { request in - request.installationID = installationID - request.topics = topics - } - - _ = await client.unsubscribe(request: request) - } - - var client: Notifications_V1_NotificationsClient { - let protocolClient = ProtocolClient( - httpClient: URLSessionHTTPClient(), - config: ProtocolClientConfig( - host: pushServer, - networkProtocol: .connect, - codec: ProtoCodec() - ) - ) - return Notifications_V1_NotificationsClient(client: protocolClient) + let request = Notifications_V1_SubscribeRequest.with { request in + request.installationID = installationID + request.topics = topics } + + _ = await client.subscribe(request: request) } -#else - public struct XMTPPush { - public static var shared = XMTPPush() - private init() { - fatalError("XMTPPush not available") + + public func subscribeWithMetadata(subscriptions: [NotificationSubscription]) async throws { + if pushServer == "" { + throw XMTPPushError.noPushServer } - public mutating func setPushServer(_: String) { - fatalError("XMTPPush not available") + let request = Notifications_V1_SubscribeWithMetadataRequest.with { request in + request.installationID = installationID + request.subscriptions = subscriptions } - public func request() async throws -> Bool { - fatalError("XMTPPush not available") + _ = await client.subscribeWithMetadata(request: request) + } + + public func unsubscribe(topics: [String]) async throws { + if pushServer == "" { + throw XMTPPushError.noPushServer } - public func register(token _: String) async throws { - fatalError("XMTPPush not available") + let request = Notifications_V1_UnsubscribeRequest.with { request in + request.installationID = installationID + request.topics = topics } - public func subscribe(topics _: [String]) async throws { - fatalError("XMTPPush not available") - } - - public func unsubscribe(topics _: [String]) async throws { - fatalError("XMTPPush not available") - } + _ = await client.unsubscribe(request: request) + } - var client: Notifications_V1_NotificationsClient { - fatalError("XMTPPush not available") - } + var client: Notifications_V1_NotificationsClient { + let protocolClient = ProtocolClient( + httpClient: URLSessionHTTPClient(), + config: ProtocolClientConfig( + host: pushServer, + networkProtocol: .connect, + codec: ProtoCodec() + ) + ) + + return Notifications_V1_NotificationsClient(client: protocolClient) + } +} +#else +public struct XMTPPush { + public static var shared = XMTPPush() + private init() { + fatalError("XMTPPush not available") + } + + public mutating func setPushServer(_: String) { + fatalError("XMTPPush not available") + } + + public func request() async throws -> Bool { + fatalError("XMTPPush not available") + } + + public func register(token _: String) async throws { + fatalError("XMTPPush not available") + } + + public func subscribe(topics _: [String]) async throws { + fatalError("XMTPPush not available") + } + + public func subscribeWithMetadata(subscriptions _: [NotificationSubscription]) async throws { + fatalError("XMTPPush not available") + } + + public func unsubscribe(topics _: [String]) async throws { + fatalError("XMTPPush not available") + } + + var client: Notifications_V1_NotificationsClient { + fatalError("XMTPPush not available") } +} #endif diff --git a/Sources/XMTPiOS/Push/service.connect.swift b/Sources/XMTPiOS/Push/service.connect.swift index 75bc9e6a..b2adeabb 100644 --- a/Sources/XMTPiOS/Push/service.connect.swift +++ b/Sources/XMTPiOS/Push/service.connect.swift @@ -1,36 +1,47 @@ // Code generated by protoc-gen-connect-swift. DO NOT EDIT. // -// Source: service.proto +// Source: notifications/v1/service.proto // import Connect import Foundation import SwiftProtobuf -public protocol Notifications_V1_NotificationsClientInterface { +public protocol Notifications_V1_NotificationsClientInterface: Sendable { + @discardableResult - func registerInstallation(request: Notifications_V1_RegisterInstallationRequest, headers: Connect.Headers, completion: @escaping (ResponseMessage) -> Void) -> Connect.Cancelable + func `registerInstallation`(request: Notifications_V1_RegisterInstallationRequest, headers: Connect.Headers, completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable - func registerInstallation(request: Notifications_V1_RegisterInstallationRequest, headers: Connect.Headers) async -> ResponseMessage + @available(iOS 13, *) + func `registerInstallation`(request: Notifications_V1_RegisterInstallationRequest, headers: Connect.Headers) async -> ResponseMessage @discardableResult - func deleteInstallation(request: Notifications_V1_DeleteInstallationRequest, headers: Connect.Headers, completion: @escaping (ResponseMessage) -> Void) -> Connect.Cancelable + func `deleteInstallation`(request: Notifications_V1_DeleteInstallationRequest, headers: Connect.Headers, completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable - func deleteInstallation(request: Notifications_V1_DeleteInstallationRequest, headers: Connect.Headers) async -> ResponseMessage + @available(iOS 13, *) + func `deleteInstallation`(request: Notifications_V1_DeleteInstallationRequest, headers: Connect.Headers) async -> ResponseMessage @discardableResult - func subscribe(request: Notifications_V1_SubscribeRequest, headers: Connect.Headers, completion: @escaping (ResponseMessage) -> Void) -> Connect.Cancelable + func `subscribe`(request: Notifications_V1_SubscribeRequest, headers: Connect.Headers, completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable - func subscribe(request: Notifications_V1_SubscribeRequest, headers: Connect.Headers) async -> ResponseMessage + @available(iOS 13, *) + func `subscribe`(request: Notifications_V1_SubscribeRequest, headers: Connect.Headers) async -> ResponseMessage @discardableResult - func unsubscribe(request: Notifications_V1_UnsubscribeRequest, headers: Connect.Headers, completion: @escaping (ResponseMessage) -> Void) -> Connect.Cancelable + func `subscribeWithMetadata`(request: Notifications_V1_SubscribeWithMetadataRequest, headers: Connect.Headers, completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable + + @available(iOS 13, *) + func `subscribeWithMetadata`(request: Notifications_V1_SubscribeWithMetadataRequest, headers: Connect.Headers) async -> ResponseMessage - func unsubscribe(request: Notifications_V1_UnsubscribeRequest, headers: Connect.Headers) async -> ResponseMessage + @discardableResult + func `unsubscribe`(request: Notifications_V1_UnsubscribeRequest, headers: Connect.Headers, completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable + + @available(iOS 13, *) + func `unsubscribe`(request: Notifications_V1_UnsubscribeRequest, headers: Connect.Headers) async -> ResponseMessage } /// Concrete implementation of `Notifications_V1_NotificationsClientInterface`. -public final class Notifications_V1_NotificationsClient: Notifications_V1_NotificationsClientInterface { +public final class Notifications_V1_NotificationsClient: Notifications_V1_NotificationsClientInterface, Sendable { private let client: Connect.ProtocolClientInterface public init(client: Connect.ProtocolClientInterface) { @@ -38,39 +49,53 @@ public final class Notifications_V1_NotificationsClient: Notifications_V1_Notifi } @discardableResult - public func registerInstallation(request: Notifications_V1_RegisterInstallationRequest, headers: Connect.Headers = [:], completion: @escaping (ResponseMessage) -> Void) -> Connect.Cancelable { - return client.unary(path: "notifications.v1.Notifications/RegisterInstallation", request: request, headers: headers, completion: completion) + public func `registerInstallation`(request: Notifications_V1_RegisterInstallationRequest, headers: Connect.Headers = [:], completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable { + return self.client.unary(path: "/notifications.v1.Notifications/RegisterInstallation", idempotencyLevel: .unknown, request: request, headers: headers, completion: completion) + } + + @available(iOS 13, *) + public func `registerInstallation`(request: Notifications_V1_RegisterInstallationRequest, headers: Connect.Headers = [:]) async -> ResponseMessage { + return await self.client.unary(path: "/notifications.v1.Notifications/RegisterInstallation", idempotencyLevel: .unknown, request: request, headers: headers) + } + + @discardableResult + public func `deleteInstallation`(request: Notifications_V1_DeleteInstallationRequest, headers: Connect.Headers = [:], completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable { + return self.client.unary(path: "/notifications.v1.Notifications/DeleteInstallation", idempotencyLevel: .unknown, request: request, headers: headers, completion: completion) } - public func registerInstallation(request: Notifications_V1_RegisterInstallationRequest, headers: Connect.Headers = [:]) async -> ResponseMessage { - return await client.unary(path: "notifications.v1.Notifications/RegisterInstallation", request: request, headers: headers) + @available(iOS 13, *) + public func `deleteInstallation`(request: Notifications_V1_DeleteInstallationRequest, headers: Connect.Headers = [:]) async -> ResponseMessage { + return await self.client.unary(path: "/notifications.v1.Notifications/DeleteInstallation", idempotencyLevel: .unknown, request: request, headers: headers) } @discardableResult - public func deleteInstallation(request: Notifications_V1_DeleteInstallationRequest, headers: Connect.Headers = [:], completion: @escaping (ResponseMessage) -> Void) -> Connect.Cancelable { - return client.unary(path: "notifications.v1.Notifications/DeleteInstallation", request: request, headers: headers, completion: completion) + public func `subscribe`(request: Notifications_V1_SubscribeRequest, headers: Connect.Headers = [:], completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable { + return self.client.unary(path: "/notifications.v1.Notifications/Subscribe", idempotencyLevel: .unknown, request: request, headers: headers, completion: completion) } - public func deleteInstallation(request: Notifications_V1_DeleteInstallationRequest, headers: Connect.Headers = [:]) async -> ResponseMessage { - return await client.unary(path: "notifications.v1.Notifications/DeleteInstallation", request: request, headers: headers) + @available(iOS 13, *) + public func `subscribe`(request: Notifications_V1_SubscribeRequest, headers: Connect.Headers = [:]) async -> ResponseMessage { + return await self.client.unary(path: "/notifications.v1.Notifications/Subscribe", idempotencyLevel: .unknown, request: request, headers: headers) } @discardableResult - public func subscribe(request: Notifications_V1_SubscribeRequest, headers: Connect.Headers = [:], completion: @escaping (ResponseMessage) -> Void) -> Connect.Cancelable { - return client.unary(path: "notifications.v1.Notifications/Subscribe", request: request, headers: headers, completion: completion) + public func `subscribeWithMetadata`(request: Notifications_V1_SubscribeWithMetadataRequest, headers: Connect.Headers = [:], completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable { + return self.client.unary(path: "/notifications.v1.Notifications/SubscribeWithMetadata", idempotencyLevel: .unknown, request: request, headers: headers, completion: completion) } - public func subscribe(request: Notifications_V1_SubscribeRequest, headers: Connect.Headers = [:]) async -> ResponseMessage { - return await client.unary(path: "notifications.v1.Notifications/Subscribe", request: request, headers: headers) + @available(iOS 13, *) + public func `subscribeWithMetadata`(request: Notifications_V1_SubscribeWithMetadataRequest, headers: Connect.Headers = [:]) async -> ResponseMessage { + return await self.client.unary(path: "/notifications.v1.Notifications/SubscribeWithMetadata", idempotencyLevel: .unknown, request: request, headers: headers) } @discardableResult - public func unsubscribe(request: Notifications_V1_UnsubscribeRequest, headers: Connect.Headers = [:], completion: @escaping (ResponseMessage) -> Void) -> Connect.Cancelable { - return client.unary(path: "notifications.v1.Notifications/Unsubscribe", request: request, headers: headers, completion: completion) + public func `unsubscribe`(request: Notifications_V1_UnsubscribeRequest, headers: Connect.Headers = [:], completion: @escaping @Sendable (ResponseMessage) -> Void) -> Connect.Cancelable { + return self.client.unary(path: "/notifications.v1.Notifications/Unsubscribe", idempotencyLevel: .unknown, request: request, headers: headers, completion: completion) } - public func unsubscribe(request: Notifications_V1_UnsubscribeRequest, headers: Connect.Headers = [:]) async -> ResponseMessage { - return await client.unary(path: "notifications.v1.Notifications/Unsubscribe", request: request, headers: headers) + @available(iOS 13, *) + public func `unsubscribe`(request: Notifications_V1_UnsubscribeRequest, headers: Connect.Headers = [:]) async -> ResponseMessage { + return await self.client.unary(path: "/notifications.v1.Notifications/Unsubscribe", idempotencyLevel: .unknown, request: request, headers: headers) } public enum Metadata { @@ -78,6 +103,7 @@ public final class Notifications_V1_NotificationsClient: Notifications_V1_Notifi public static let registerInstallation = Connect.MethodSpec(name: "RegisterInstallation", service: "notifications.v1.Notifications", type: .unary) public static let deleteInstallation = Connect.MethodSpec(name: "DeleteInstallation", service: "notifications.v1.Notifications", type: .unary) public static let subscribe = Connect.MethodSpec(name: "Subscribe", service: "notifications.v1.Notifications", type: .unary) + public static let subscribeWithMetadata = Connect.MethodSpec(name: "SubscribeWithMetadata", service: "notifications.v1.Notifications", type: .unary) public static let unsubscribe = Connect.MethodSpec(name: "Unsubscribe", service: "notifications.v1.Notifications", type: .unary) } } diff --git a/Sources/XMTPiOS/Push/service.pb.swift b/Sources/XMTPiOS/Push/service.pb.swift index d23ab3f0..e99fb5a1 100644 --- a/Sources/XMTPiOS/Push/service.pb.swift +++ b/Sources/XMTPiOS/Push/service.pb.swift @@ -2,7 +2,7 @@ // swift-format-ignore-file // // Generated by the Swift generator plugin for the protocol buffer compiler. -// Source: service.proto +// Source: notifications/v1/service.proto // // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ @@ -15,399 +15,599 @@ import SwiftProtobuf // incompatible with the version of SwiftProtobuf to which you are linking. // Please ensure that you are building against the same version of the API // that was used to generate this file. -private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { - struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} - typealias Version = _2 +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 } +/// An union of possible delibery mechanisms public struct Notifications_V1_DeliveryMechanism { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. - public var deliveryMechanismType: Notifications_V1_DeliveryMechanism.OneOf_DeliveryMechanismType? + public var deliveryMechanismType: Notifications_V1_DeliveryMechanism.OneOf_DeliveryMechanismType? = nil - public var apnsDeviceToken: String { - get { - if case let .apnsDeviceToken(v)? = deliveryMechanismType { return v } - return String() - } - set { deliveryMechanismType = .apnsDeviceToken(newValue) } + public var apnsDeviceToken: String { + get { + if case .apnsDeviceToken(let v)? = deliveryMechanismType {return v} + return String() } + set {deliveryMechanismType = .apnsDeviceToken(newValue)} + } - public var firebaseDeviceToken: String { - get { - if case let .firebaseDeviceToken(v)? = deliveryMechanismType { return v } - return String() - } - set { deliveryMechanismType = .firebaseDeviceToken(newValue) } + public var firebaseDeviceToken: String { + get { + if case .firebaseDeviceToken(let v)? = deliveryMechanismType {return v} + return String() } + set {deliveryMechanismType = .firebaseDeviceToken(newValue)} + } - public var unknownFields = SwiftProtobuf.UnknownStorage() - - public enum OneOf_DeliveryMechanismType: Equatable { - case apnsDeviceToken(String) - case firebaseDeviceToken(String) - - #if !swift(>=4.1) - public static func == (lhs: Notifications_V1_DeliveryMechanism.OneOf_DeliveryMechanismType, rhs: Notifications_V1_DeliveryMechanism.OneOf_DeliveryMechanismType) -> Bool { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch (lhs, rhs) { - case (.apnsDeviceToken, .apnsDeviceToken): return { - guard case let .apnsDeviceToken(l) = lhs, case let .apnsDeviceToken(r) = rhs else { preconditionFailure() } - return l == r - }() - case (.firebaseDeviceToken, .firebaseDeviceToken): return { - guard case let .firebaseDeviceToken(l) = lhs, case let .firebaseDeviceToken(r) = rhs else { preconditionFailure() } - return l == r - }() - default: return false - } - } - #endif + public var customToken: String { + get { + if case .customToken(let v)? = deliveryMechanismType {return v} + return String() + } + set {deliveryMechanismType = .customToken(newValue)} + } + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public enum OneOf_DeliveryMechanismType: Equatable { + case apnsDeviceToken(String) + case firebaseDeviceToken(String) + case customToken(String) + + #if !swift(>=4.1) + public static func ==(lhs: Notifications_V1_DeliveryMechanism.OneOf_DeliveryMechanismType, rhs: Notifications_V1_DeliveryMechanism.OneOf_DeliveryMechanismType) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.apnsDeviceToken, .apnsDeviceToken): return { + guard case .apnsDeviceToken(let l) = lhs, case .apnsDeviceToken(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.firebaseDeviceToken, .firebaseDeviceToken): return { + guard case .firebaseDeviceToken(let l) = lhs, case .firebaseDeviceToken(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.customToken, .customToken): return { + guard case .customToken(let l) = lhs, case .customToken(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } } + #endif + } - public init() {} + public init() {} } +/// A request to register an installation with the service public struct Notifications_V1_RegisterInstallationRequest { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. - - public var installationID: String = .init() + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. - public var deliveryMechanism: Notifications_V1_DeliveryMechanism { - get { return _deliveryMechanism ?? Notifications_V1_DeliveryMechanism() } - set { _deliveryMechanism = newValue } - } + public var installationID: String = String() - /// Returns true if `deliveryMechanism` has been explicitly set. - public var hasDeliveryMechanism: Bool { return _deliveryMechanism != nil } - /// Clears the value of `deliveryMechanism`. Subsequent reads from it will return its default value. - public mutating func clearDeliveryMechanism() { _deliveryMechanism = nil } + public var deliveryMechanism: Notifications_V1_DeliveryMechanism { + get {return _deliveryMechanism ?? Notifications_V1_DeliveryMechanism()} + set {_deliveryMechanism = newValue} + } + /// Returns true if `deliveryMechanism` has been explicitly set. + public var hasDeliveryMechanism: Bool {return self._deliveryMechanism != nil} + /// Clears the value of `deliveryMechanism`. Subsequent reads from it will return its default value. + public mutating func clearDeliveryMechanism() {self._deliveryMechanism = nil} - public var unknownFields = SwiftProtobuf.UnknownStorage() + public var unknownFields = SwiftProtobuf.UnknownStorage() - public init() {} + public init() {} - fileprivate var _deliveryMechanism: Notifications_V1_DeliveryMechanism? + fileprivate var _deliveryMechanism: Notifications_V1_DeliveryMechanism? = nil } +/// Response to RegisterInstallationRequest public struct Notifications_V1_RegisterInstallationResponse { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. - public var installationID: String = .init() + public var installationID: String = String() - public var validUntil: UInt64 = 0 + public var validUntil: UInt64 = 0 - public var unknownFields = SwiftProtobuf.UnknownStorage() + public var unknownFields = SwiftProtobuf.UnknownStorage() - public init() {} + public init() {} } +/// Delete an installation from the service public struct Notifications_V1_DeleteInstallationRequest { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + public var installationID: String = String() + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public init() {} +} + +/// A subscription with associated metadata +public struct Notifications_V1_Subscription { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + public var topic: String = String() + + public var hmacKeys: [Notifications_V1_Subscription.HmacKey] = [] + + public var isSilent: Bool = false + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public struct HmacKey { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. - public var installationID: String = .init() + public var thirtyDayPeriodsSinceEpoch: UInt32 = 0 + + public var key: Data = Data() public var unknownFields = SwiftProtobuf.UnknownStorage() public init() {} + } + + public init() {} } +/// A request to subscribe to a list of topics and update the associated metadata +public struct Notifications_V1_SubscribeWithMetadataRequest { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + public var installationID: String = String() + + public var subscriptions: [Notifications_V1_Subscription] = [] + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public init() {} +} + +/// Subscribe to a list of topics public struct Notifications_V1_SubscribeRequest { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. - public var installationID: String = .init() + public var installationID: String = String() - public var topics: [String] = [] + public var topics: [String] = [] - public var unknownFields = SwiftProtobuf.UnknownStorage() + public var unknownFields = SwiftProtobuf.UnknownStorage() - public init() {} + public init() {} } +/// Unsubscribe from a list of topics public struct Notifications_V1_UnsubscribeRequest { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. - public var installationID: String = .init() + public var installationID: String = String() - public var topics: [String] = [] + public var topics: [String] = [] - public var unknownFields = SwiftProtobuf.UnknownStorage() + public var unknownFields = SwiftProtobuf.UnknownStorage() - public init() {} + public init() {} } #if swift(>=5.5) && canImport(_Concurrency) - extension Notifications_V1_DeliveryMechanism: @unchecked Sendable {} - extension Notifications_V1_DeliveryMechanism.OneOf_DeliveryMechanismType: @unchecked Sendable {} - extension Notifications_V1_RegisterInstallationRequest: @unchecked Sendable {} - extension Notifications_V1_RegisterInstallationResponse: @unchecked Sendable {} - extension Notifications_V1_DeleteInstallationRequest: @unchecked Sendable {} - extension Notifications_V1_SubscribeRequest: @unchecked Sendable {} - extension Notifications_V1_UnsubscribeRequest: @unchecked Sendable {} -#endif // swift(>=5.5) && canImport(_Concurrency) +extension Notifications_V1_DeliveryMechanism: @unchecked Sendable {} +extension Notifications_V1_DeliveryMechanism.OneOf_DeliveryMechanismType: @unchecked Sendable {} +extension Notifications_V1_RegisterInstallationRequest: @unchecked Sendable {} +extension Notifications_V1_RegisterInstallationResponse: @unchecked Sendable {} +extension Notifications_V1_DeleteInstallationRequest: @unchecked Sendable {} +extension Notifications_V1_Subscription: @unchecked Sendable {} +extension Notifications_V1_Subscription.HmacKey: @unchecked Sendable {} +extension Notifications_V1_SubscribeWithMetadataRequest: @unchecked Sendable {} +extension Notifications_V1_SubscribeRequest: @unchecked Sendable {} +extension Notifications_V1_UnsubscribeRequest: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) // MARK: - Code below here is support for the SwiftProtobuf runtime. -private let _protobuf_package = "notifications.v1" +fileprivate let _protobuf_package = "notifications.v1" extension Notifications_V1_DeliveryMechanism: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - public static let protoMessageName: String = _protobuf_package + ".DeliveryMechanism" - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 1: .standard(proto: "apns_device_token"), - 2: .standard(proto: "firebase_device_token"), - ] - - public mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try { - var v: String? - try decoder.decodeSingularStringField(value: &v) - if let v = v { - if self.deliveryMechanismType != nil { try decoder.handleConflictingOneOf() } - self.deliveryMechanismType = .apnsDeviceToken(v) - } - }() - case 2: try { - var v: String? - try decoder.decodeSingularStringField(value: &v) - if let v = v { - if self.deliveryMechanismType != nil { try decoder.handleConflictingOneOf() } - self.deliveryMechanismType = .firebaseDeviceToken(v) - } - }() - default: break - } + public static let protoMessageName: String = _protobuf_package + ".DeliveryMechanism" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "apns_device_token"), + 2: .standard(proto: "firebase_device_token"), + 3: .standard(proto: "custom_token"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { + var v: String? + try decoder.decodeSingularStringField(value: &v) + if let v = v { + if self.deliveryMechanismType != nil {try decoder.handleConflictingOneOf()} + self.deliveryMechanismType = .apnsDeviceToken(v) } - } - - public func traverse(visitor: inout V) throws { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every if/case branch local when no optimizations - // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and - // https://github.com/apple/swift-protobuf/issues/1182 - switch deliveryMechanismType { - case .apnsDeviceToken?: try { - guard case let .apnsDeviceToken(v)? = self.deliveryMechanismType else { preconditionFailure() } - try visitor.visitSingularStringField(value: v, fieldNumber: 1) - }() - case .firebaseDeviceToken?: try { - guard case let .firebaseDeviceToken(v)? = self.deliveryMechanismType else { preconditionFailure() } - try visitor.visitSingularStringField(value: v, fieldNumber: 2) - }() - case nil: break + }() + case 2: try { + var v: String? + try decoder.decodeSingularStringField(value: &v) + if let v = v { + if self.deliveryMechanismType != nil {try decoder.handleConflictingOneOf()} + self.deliveryMechanismType = .firebaseDeviceToken(v) + } + }() + case 3: try { + var v: String? + try decoder.decodeSingularStringField(value: &v) + if let v = v { + if self.deliveryMechanismType != nil {try decoder.handleConflictingOneOf()} + self.deliveryMechanismType = .customToken(v) } - try unknownFields.traverse(visitor: &visitor) + }() + default: break + } } - - public static func == (lhs: Notifications_V1_DeliveryMechanism, rhs: Notifications_V1_DeliveryMechanism) -> Bool { - if lhs.deliveryMechanismType != rhs.deliveryMechanismType { return false } - if lhs.unknownFields != rhs.unknownFields { return false } - return true + } + + public func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + switch self.deliveryMechanismType { + case .apnsDeviceToken?: try { + guard case .apnsDeviceToken(let v)? = self.deliveryMechanismType else { preconditionFailure() } + try visitor.visitSingularStringField(value: v, fieldNumber: 1) + }() + case .firebaseDeviceToken?: try { + guard case .firebaseDeviceToken(let v)? = self.deliveryMechanismType else { preconditionFailure() } + try visitor.visitSingularStringField(value: v, fieldNumber: 2) + }() + case .customToken?: try { + guard case .customToken(let v)? = self.deliveryMechanismType else { preconditionFailure() } + try visitor.visitSingularStringField(value: v, fieldNumber: 3) + }() + case nil: break } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Notifications_V1_DeliveryMechanism, rhs: Notifications_V1_DeliveryMechanism) -> Bool { + if lhs.deliveryMechanismType != rhs.deliveryMechanismType {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } } extension Notifications_V1_RegisterInstallationRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - public static let protoMessageName: String = _protobuf_package + ".RegisterInstallationRequest" - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 1: .standard(proto: "installation_id"), - 2: .standard(proto: "delivery_mechanism"), - ] - - public mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try try decoder.decodeSingularStringField(value: &installationID) - case 2: try try decoder.decodeSingularMessageField(value: &_deliveryMechanism) - default: break - } - } + public static let protoMessageName: String = _protobuf_package + ".RegisterInstallationRequest" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "installation_id"), + 2: .standard(proto: "delivery_mechanism"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.installationID) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._deliveryMechanism) }() + default: break + } } + } + + public func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if !self.installationID.isEmpty { + try visitor.visitSingularStringField(value: self.installationID, fieldNumber: 1) + } + try { if let v = self._deliveryMechanism { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } }() + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Notifications_V1_RegisterInstallationRequest, rhs: Notifications_V1_RegisterInstallationRequest) -> Bool { + if lhs.installationID != rhs.installationID {return false} + if lhs._deliveryMechanism != rhs._deliveryMechanism {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} - public func traverse(visitor: inout V) throws { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every if/case branch local when no optimizations - // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and - // https://github.com/apple/swift-protobuf/issues/1182 - if !installationID.isEmpty { - try visitor.visitSingularStringField(value: installationID, fieldNumber: 1) - } - try { if let v = self._deliveryMechanism { - try visitor.visitSingularMessageField(value: v, fieldNumber: 2) - } }() - try unknownFields.traverse(visitor: &visitor) +extension Notifications_V1_RegisterInstallationResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".RegisterInstallationResponse" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "installation_id"), + 2: .standard(proto: "valid_until"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.installationID) }() + case 2: try { try decoder.decodeSingularUInt64Field(value: &self.validUntil) }() + default: break + } } + } - public static func == (lhs: Notifications_V1_RegisterInstallationRequest, rhs: Notifications_V1_RegisterInstallationRequest) -> Bool { - if lhs.installationID != rhs.installationID { return false } - if lhs._deliveryMechanism != rhs._deliveryMechanism { return false } - if lhs.unknownFields != rhs.unknownFields { return false } - return true + public func traverse(visitor: inout V) throws { + if !self.installationID.isEmpty { + try visitor.visitSingularStringField(value: self.installationID, fieldNumber: 1) + } + if self.validUntil != 0 { + try visitor.visitSingularUInt64Field(value: self.validUntil, fieldNumber: 2) } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Notifications_V1_RegisterInstallationResponse, rhs: Notifications_V1_RegisterInstallationResponse) -> Bool { + if lhs.installationID != rhs.installationID {return false} + if lhs.validUntil != rhs.validUntil {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } } -extension Notifications_V1_RegisterInstallationResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - public static let protoMessageName: String = _protobuf_package + ".RegisterInstallationResponse" - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 1: .standard(proto: "installation_id"), - 2: .standard(proto: "valid_until"), - ] - - public mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try try decoder.decodeSingularStringField(value: &installationID) - case 2: try try decoder.decodeSingularUInt64Field(value: &validUntil) - default: break - } - } +extension Notifications_V1_DeleteInstallationRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".DeleteInstallationRequest" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "installation_id"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.installationID) }() + default: break + } } + } - public func traverse(visitor: inout V) throws { - if !installationID.isEmpty { - try visitor.visitSingularStringField(value: installationID, fieldNumber: 1) - } - if validUntil != 0 { - try visitor.visitSingularUInt64Field(value: validUntil, fieldNumber: 2) - } - try unknownFields.traverse(visitor: &visitor) + public func traverse(visitor: inout V) throws { + if !self.installationID.isEmpty { + try visitor.visitSingularStringField(value: self.installationID, fieldNumber: 1) } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Notifications_V1_DeleteInstallationRequest, rhs: Notifications_V1_DeleteInstallationRequest) -> Bool { + if lhs.installationID != rhs.installationID {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Notifications_V1_Subscription: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".Subscription" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "topic"), + 2: .standard(proto: "hmac_keys"), + 3: .standard(proto: "is_silent"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.topic) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.hmacKeys) }() + case 3: try { try decoder.decodeSingularBoolField(value: &self.isSilent) }() + default: break + } + } + } - public static func == (lhs: Notifications_V1_RegisterInstallationResponse, rhs: Notifications_V1_RegisterInstallationResponse) -> Bool { - if lhs.installationID != rhs.installationID { return false } - if lhs.validUntil != rhs.validUntil { return false } - if lhs.unknownFields != rhs.unknownFields { return false } - return true + public func traverse(visitor: inout V) throws { + if !self.topic.isEmpty { + try visitor.visitSingularStringField(value: self.topic, fieldNumber: 1) } + if !self.hmacKeys.isEmpty { + try visitor.visitRepeatedMessageField(value: self.hmacKeys, fieldNumber: 2) + } + if self.isSilent != false { + try visitor.visitSingularBoolField(value: self.isSilent, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Notifications_V1_Subscription, rhs: Notifications_V1_Subscription) -> Bool { + if lhs.topic != rhs.topic {return false} + if lhs.hmacKeys != rhs.hmacKeys {return false} + if lhs.isSilent != rhs.isSilent {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } } -extension Notifications_V1_DeleteInstallationRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - public static let protoMessageName: String = _protobuf_package + ".DeleteInstallationRequest" - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 1: .standard(proto: "installation_id"), - ] - - public mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try try decoder.decodeSingularStringField(value: &installationID) - default: break - } - } +extension Notifications_V1_Subscription.HmacKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = Notifications_V1_Subscription.protoMessageName + ".HmacKey" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "thirty_day_periods_since_epoch"), + 2: .same(proto: "key"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt32Field(value: &self.thirtyDayPeriodsSinceEpoch) }() + case 2: try { try decoder.decodeSingularBytesField(value: &self.key) }() + default: break + } } + } - public func traverse(visitor: inout V) throws { - if !installationID.isEmpty { - try visitor.visitSingularStringField(value: installationID, fieldNumber: 1) - } - try unknownFields.traverse(visitor: &visitor) + public func traverse(visitor: inout V) throws { + if self.thirtyDayPeriodsSinceEpoch != 0 { + try visitor.visitSingularUInt32Field(value: self.thirtyDayPeriodsSinceEpoch, fieldNumber: 1) + } + if !self.key.isEmpty { + try visitor.visitSingularBytesField(value: self.key, fieldNumber: 2) } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Notifications_V1_Subscription.HmacKey, rhs: Notifications_V1_Subscription.HmacKey) -> Bool { + if lhs.thirtyDayPeriodsSinceEpoch != rhs.thirtyDayPeriodsSinceEpoch {return false} + if lhs.key != rhs.key {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} - public static func == (lhs: Notifications_V1_DeleteInstallationRequest, rhs: Notifications_V1_DeleteInstallationRequest) -> Bool { - if lhs.installationID != rhs.installationID { return false } - if lhs.unknownFields != rhs.unknownFields { return false } - return true +extension Notifications_V1_SubscribeWithMetadataRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".SubscribeWithMetadataRequest" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "installation_id"), + 2: .same(proto: "subscriptions"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.installationID) }() + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.subscriptions) }() + default: break + } } + } + + public func traverse(visitor: inout V) throws { + if !self.installationID.isEmpty { + try visitor.visitSingularStringField(value: self.installationID, fieldNumber: 1) + } + if !self.subscriptions.isEmpty { + try visitor.visitRepeatedMessageField(value: self.subscriptions, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Notifications_V1_SubscribeWithMetadataRequest, rhs: Notifications_V1_SubscribeWithMetadataRequest) -> Bool { + if lhs.installationID != rhs.installationID {return false} + if lhs.subscriptions != rhs.subscriptions {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } } extension Notifications_V1_SubscribeRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - public static let protoMessageName: String = _protobuf_package + ".SubscribeRequest" - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 1: .standard(proto: "installation_id"), - 2: .same(proto: "topics"), - ] - - public mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try try decoder.decodeSingularStringField(value: &installationID) - case 2: try try decoder.decodeRepeatedStringField(value: &topics) - default: break - } - } + public static let protoMessageName: String = _protobuf_package + ".SubscribeRequest" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "installation_id"), + 2: .same(proto: "topics"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.installationID) }() + case 2: try { try decoder.decodeRepeatedStringField(value: &self.topics) }() + default: break + } } + } - public func traverse(visitor: inout V) throws { - if !installationID.isEmpty { - try visitor.visitSingularStringField(value: installationID, fieldNumber: 1) - } - if !topics.isEmpty { - try visitor.visitRepeatedStringField(value: topics, fieldNumber: 2) - } - try unknownFields.traverse(visitor: &visitor) + public func traverse(visitor: inout V) throws { + if !self.installationID.isEmpty { + try visitor.visitSingularStringField(value: self.installationID, fieldNumber: 1) } - - public static func == (lhs: Notifications_V1_SubscribeRequest, rhs: Notifications_V1_SubscribeRequest) -> Bool { - if lhs.installationID != rhs.installationID { return false } - if lhs.topics != rhs.topics { return false } - if lhs.unknownFields != rhs.unknownFields { return false } - return true + if !self.topics.isEmpty { + try visitor.visitRepeatedStringField(value: self.topics, fieldNumber: 2) } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Notifications_V1_SubscribeRequest, rhs: Notifications_V1_SubscribeRequest) -> Bool { + if lhs.installationID != rhs.installationID {return false} + if lhs.topics != rhs.topics {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } } extension Notifications_V1_UnsubscribeRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - public static let protoMessageName: String = _protobuf_package + ".UnsubscribeRequest" - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 1: .standard(proto: "installation_id"), - 2: .same(proto: "topics"), - ] - - public mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try try decoder.decodeSingularStringField(value: &installationID) - case 2: try try decoder.decodeRepeatedStringField(value: &topics) - default: break - } - } + public static let protoMessageName: String = _protobuf_package + ".UnsubscribeRequest" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "installation_id"), + 2: .same(proto: "topics"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.installationID) }() + case 2: try { try decoder.decodeRepeatedStringField(value: &self.topics) }() + default: break + } } + } - public func traverse(visitor: inout V) throws { - if !installationID.isEmpty { - try visitor.visitSingularStringField(value: installationID, fieldNumber: 1) - } - if !topics.isEmpty { - try visitor.visitRepeatedStringField(value: topics, fieldNumber: 2) - } - try unknownFields.traverse(visitor: &visitor) + public func traverse(visitor: inout V) throws { + if !self.installationID.isEmpty { + try visitor.visitSingularStringField(value: self.installationID, fieldNumber: 1) } - - public static func == (lhs: Notifications_V1_UnsubscribeRequest, rhs: Notifications_V1_UnsubscribeRequest) -> Bool { - if lhs.installationID != rhs.installationID { return false } - if lhs.topics != rhs.topics { return false } - if lhs.unknownFields != rhs.unknownFields { return false } - return true + if !self.topics.isEmpty { + try visitor.visitRepeatedStringField(value: self.topics, fieldNumber: 2) } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Notifications_V1_UnsubscribeRequest, rhs: Notifications_V1_UnsubscribeRequest) -> Bool { + if lhs.installationID != rhs.installationID {return false} + if lhs.topics != rhs.topics {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } } diff --git a/XMTPiOSExample/XMTPiOSExample/Views/ConversationListView.swift b/XMTPiOSExample/XMTPiOSExample/Views/ConversationListView.swift index abd9ee2c..bd863618 100644 --- a/XMTPiOSExample/XMTPiOSExample/Views/ConversationListView.swift +++ b/XMTPiOSExample/XMTPiOSExample/Views/ConversationListView.swift @@ -141,7 +141,22 @@ struct ConversationListView: View { case .conversation(let conversation): // Ensure we're subscribed to push notifications on these conversations do { - try await XMTPPush.shared.subscribe(topics: [conversation.topic]) + let hmacKeysResult = await client.conversations.getHmacKeys() + let hmacKeys = hmacKeysResult.hmacKeys + + let result = hmacKeys[conversation.topic]?.values.map { hmacKey -> NotificationSubscriptionHmacKey in + NotificationSubscriptionHmacKey.with { sub_key in + sub_key.key = hmacKey.hmacKey + sub_key.thirtyDayPeriodsSinceEpoch = UInt32(hmacKey.thirtyDayPeriodsSinceEpoch) + } + } + + let subscription = NotificationSubscription.with { sub in + sub.hmacKeys = result ?? [] + sub.topic = conversation.topic + sub.isSilent = conversation.version == .v1 + } + try await XMTPPush.shared.subscribeWithMetadata(subscriptions: [subscription]) } catch { print("Error subscribing: \(error)") }