diff --git a/Package.swift b/Package.swift index bb8325e0..c7d00c54 100644 --- a/Package.swift +++ b/Package.swift @@ -25,7 +25,7 @@ let package = Package( .package(url: "https://github.com/1024jp/GzipSwift", from: "5.2.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.4-beta2"), + .package(url: "https://github.com/xmtp/libxmtp-swift", exact: "0.4.4-beta3"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Sources/XMTPiOS/DecodedMessage.swift b/Sources/XMTPiOS/DecodedMessage.swift index 70f7bf3c..f39b82b2 100644 --- a/Sources/XMTPiOS/DecodedMessage.swift +++ b/Sources/XMTPiOS/DecodedMessage.swift @@ -22,6 +22,8 @@ public struct DecodedMessage: Sendable { public var sent: Date public var client: Client + + public var deliveryStatus: MessageDeliveryStatus = .published init( id: String, @@ -29,7 +31,8 @@ public struct DecodedMessage: Sendable { topic: String, encodedContent: EncodedContent, senderAddress: String, - sent: Date + sent: Date, + deliveryStatus: MessageDeliveryStatus = .published ) { self.id = id self.client = client @@ -37,6 +40,7 @@ public struct DecodedMessage: Sendable { self.encodedContent = encodedContent self.senderAddress = senderAddress self.sent = sent + self.deliveryStatus = deliveryStatus } public init( @@ -44,13 +48,15 @@ public struct DecodedMessage: Sendable { topic: String, encodedContent: EncodedContent, senderAddress: String, - sent: Date + sent: Date, + deliveryStatus: MessageDeliveryStatus = .published ) { self.client = client self.topic = topic self.encodedContent = encodedContent self.senderAddress = senderAddress self.sent = sent + self.deliveryStatus = deliveryStatus } public func content() throws -> T { diff --git a/Sources/XMTPiOS/Group.swift b/Sources/XMTPiOS/Group.swift index 4b70478b..17f4a781 100644 --- a/Sources/XMTPiOS/Group.swift +++ b/Sources/XMTPiOS/Group.swift @@ -133,8 +133,8 @@ public struct Group: Identifiable, Equatable, Hashable { try await client.contacts.allowGroup(groupIds: [id]) } - try await ffiGroup.send(contentBytes: encodedContent.serializedData()) - return id.toHex + let messageId = try await ffiGroup.send(contentBytes: encodedContent.serializedData()) + return messageId.toHex } public func prepareMessage(content: T, options: SendOptions?) async throws -> EncodedContent { @@ -213,8 +213,19 @@ public struct Group: Identifiable, Equatable, Hashable { } } - public func messages(before: Date? = nil, after: Date? = nil, limit: Int? = nil, direction: PagingInfoSortDirection? = .descending) async throws -> [DecodedMessage] { - var options = FfiListMessagesOptions(sentBeforeNs: nil, sentAfterNs: nil, limit: nil) + public func messages( + before: Date? = nil, + after: Date? = nil, + limit: Int? = nil, + direction: PagingInfoSortDirection? = .descending, + deliveryStatus: MessageDeliveryStatus = .all + ) async throws -> [DecodedMessage] { + var options = FfiListMessagesOptions( + sentBeforeNs: nil, + sentAfterNs: nil, + limit: nil, + deliveryStatus: nil + ) if let before { options.sentBeforeNs = Int64(before.millisecondsSinceEpoch * 1_000_000) @@ -228,6 +239,13 @@ public struct Group: Identifiable, Equatable, Hashable { options.limit = Int64(limit) } + options.deliveryStatus = switch deliveryStatus { + case .published: FfiDeliveryStatus.published + case .unpublished: FfiDeliveryStatus.unpublished + case .failed: FfiDeliveryStatus.failed + default: nil + } + let messages = try ffiGroup.findMessages(opts: options).compactMap { ffiMessage in return MessageV3(client: self.client, ffiMessage: ffiMessage).decodeOrNull() } @@ -240,8 +258,19 @@ public struct Group: Identifiable, Equatable, Hashable { } } - public func decryptedMessages(before: Date? = nil, after: Date? = nil, limit: Int? = nil, direction: PagingInfoSortDirection? = .descending) async throws -> [DecryptedMessage] { - var options = FfiListMessagesOptions(sentBeforeNs: nil, sentAfterNs: nil, limit: nil) + public func decryptedMessages( + before: Date? = nil, + after: Date? = nil, + limit: Int? = nil, + direction: PagingInfoSortDirection? = .descending, + deliveryStatus: MessageDeliveryStatus? = .all + ) async throws -> [DecryptedMessage] { + var options = FfiListMessagesOptions( + sentBeforeNs: nil, + sentAfterNs: nil, + limit: nil, + deliveryStatus: nil + ) if let before { options.sentBeforeNs = Int64(before.millisecondsSinceEpoch * 1_000_000) @@ -254,6 +283,13 @@ public struct Group: Identifiable, Equatable, Hashable { if let limit { options.limit = Int64(limit) } + + options.deliveryStatus = switch deliveryStatus { + case .published: FfiDeliveryStatus.published + case .unpublished: FfiDeliveryStatus.unpublished + case .failed: FfiDeliveryStatus.failed + default: nil + } let messages = try ffiGroup.findMessages(opts: options).compactMap { ffiMessage in return MessageV3(client: self.client, ffiMessage: ffiMessage).decryptOrNull() diff --git a/Sources/XMTPiOS/Messages/DecryptedMessage.swift b/Sources/XMTPiOS/Messages/DecryptedMessage.swift index 2109b5b0..69a1a57a 100644 --- a/Sources/XMTPiOS/Messages/DecryptedMessage.swift +++ b/Sources/XMTPiOS/Messages/DecryptedMessage.swift @@ -13,4 +13,5 @@ public struct DecryptedMessage { public var senderAddress: String public var sentAt: Date public var topic: String = "" + public var deliveryStatus: MessageDeliveryStatus = .published } diff --git a/Sources/XMTPiOS/Messages/Message.swift b/Sources/XMTPiOS/Messages/Message.swift index ff2613b4..2d5efa26 100644 --- a/Sources/XMTPiOS/Messages/Message.swift +++ b/Sources/XMTPiOS/Messages/Message.swift @@ -13,6 +13,13 @@ public enum MessageVersion: String, RawRepresentable { v2 } +public enum MessageDeliveryStatus: Sendable { + case all, + published, + unpublished, + failed +} + extension Message { init(v1: MessageV1) { self.init() diff --git a/Sources/XMTPiOS/Mls/MessageV3.swift b/Sources/XMTPiOS/Mls/MessageV3.swift index 989370ab..ec0792e0 100644 --- a/Sources/XMTPiOS/Mls/MessageV3.swift +++ b/Sources/XMTPiOS/Mls/MessageV3.swift @@ -37,6 +37,17 @@ public struct MessageV3: Identifiable { return Date(timeIntervalSince1970: TimeInterval(ffiMessage.sentAtNs) / 1_000_000_000) } + var deliveryStatus: MessageDeliveryStatus { + switch ffiMessage.deliveryStatus { + case .unpublished: + return .unpublished + case .published: + return .published + case .failed: + return .failed + } + } + public func decode() throws -> DecodedMessage { do { let encodedContent = try EncodedContent(serializedData: ffiMessage.content) @@ -47,7 +58,8 @@ public struct MessageV3: Identifiable { topic: Topic.groupMessage(convoId.toHex).description, encodedContent: encodedContent, senderAddress: senderAddress, - sent: sentAt + sent: sentAt, + deliveryStatus: deliveryStatus ) if decodedMessage.encodedContent.type == ContentTypeGroupMembershipChanged && ffiMessage.kind != .membershipChange { @@ -86,7 +98,8 @@ public struct MessageV3: Identifiable { encodedContent: encodedContent, senderAddress: senderAddress, sentAt: Date(), - topic: Topic.groupMessage(convoId.toHex).description + topic: Topic.groupMessage(convoId.toHex).description, + deliveryStatus: deliveryStatus ) if decrytedMessage.encodedContent.type == ContentTypeGroupMembershipChanged && ffiMessage.kind != .membershipChange { diff --git a/Tests/XMTPTests/GroupTests.swift b/Tests/XMTPTests/GroupTests.swift index cbead0e1..fe0d5cf1 100644 --- a/Tests/XMTPTests/GroupTests.swift +++ b/Tests/XMTPTests/GroupTests.swift @@ -378,7 +378,7 @@ class GroupTests: XCTestCase { let bobGroup = try await fixtures.bobClient.conversations.groups()[0] _ = try await aliceGroup.send(content: "sup gang original") - _ = try await aliceGroup.send(content: "sup gang") + let messageId = try await aliceGroup.send(content: "sup gang") _ = try await aliceGroup.send(content: membershipChange, options: SendOptions(contentType: ContentTypeGroupMembershipChanged)) try await aliceGroup.sync() @@ -392,9 +392,45 @@ class GroupTests: XCTestCase { let bobMessage = try await bobGroup.messages().first! XCTAssertEqual("sup gang", try aliceMessage.content()) + XCTAssertEqual(messageId, aliceMessage.id) + XCTAssertEqual(.published, aliceMessage.deliveryStatus) XCTAssertEqual("sup gang", try bobMessage.content()) } + func testCanListGroupMessages() async throws { + let fixtures = try await localFixtures() + let aliceGroup = try await fixtures.aliceClient.conversations.newGroup(with: [fixtures.bob.address]) + _ = try await aliceGroup.send(content: "howdy") + _ = try await aliceGroup.send(content: "gm") + + var aliceMessagesCount = try await aliceGroup.messages().count + var aliceMessagesUnpublishedCount = try await aliceGroup.messages(deliveryStatus: .unpublished).count + var aliceMessagesPublishedCount = try await aliceGroup.messages(deliveryStatus: .published).count + XCTAssertEqual(3, aliceMessagesCount) + XCTAssertEqual(2, aliceMessagesUnpublishedCount) + XCTAssertEqual(1, aliceMessagesPublishedCount) + + try await aliceGroup.sync() + + aliceMessagesCount = try await aliceGroup.messages().count + aliceMessagesUnpublishedCount = try await aliceGroup.messages(deliveryStatus: .unpublished).count + aliceMessagesPublishedCount = try await aliceGroup.messages(deliveryStatus: .published).count + XCTAssertEqual(3, aliceMessagesCount) + XCTAssertEqual(0, aliceMessagesUnpublishedCount) + XCTAssertEqual(3, aliceMessagesPublishedCount) + + try await fixtures.bobClient.conversations.sync() + let bobGroup = try await fixtures.bobClient.conversations.groups()[0] + try await bobGroup.sync() + + var bobMessagesCount = try await bobGroup.messages().count + var bobMessagesUnpublishedCount = try await bobGroup.messages(deliveryStatus: .unpublished).count + var bobMessagesPublishedCount = try await bobGroup.messages(deliveryStatus: .published).count + XCTAssertEqual(2, bobMessagesCount) + XCTAssertEqual(0, bobMessagesUnpublishedCount) + XCTAssertEqual(2, bobMessagesPublishedCount) + + } func testCanSendMessagesToGroupDecrypted() async throws { let fixtures = try await localFixtures() diff --git a/XMTP.podspec b/XMTP.podspec index bcb18b50..39f06310 100644 --- a/XMTP.podspec +++ b/XMTP.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |spec| # spec.name = "XMTP" - spec.version = "0.10.3" + spec.version = "0.10.4" spec.summary = "XMTP SDK Cocoapod" # This description is used to generate tags and improve search results. @@ -44,5 +44,5 @@ Pod::Spec.new do |spec| spec.dependency "web3.swift" spec.dependency "GzipSwift" spec.dependency "Connect-Swift", "= 0.12.0" - spec.dependency 'LibXMTP', '= 0.4.4-beta2' + spec.dependency 'LibXMTP', '= 0.4.4-beta3' end diff --git a/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d2204aed..5af3add1 100644 --- a/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/XMTPiOSExample/XMTPiOSExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -59,8 +59,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/xmtp/libxmtp-swift", "state" : { - "revision" : "79abd63c8850958337f2991d9763ef908223de43", - "version" : "0.4.4-beta2" + "revision" : "5326f84ed781f766054f0b4dcceaf8c0cca91d1b", + "version" : "0.4.4-beta3" } }, {