-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
4,879 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// | ||
// File.swift | ||
// | ||
// | ||
// Created by Pat Nakajima on 2/1/24. | ||
// | ||
|
||
import Foundation | ||
import LibXMTP | ||
|
||
public typealias GroupMembershipChanges = Xmtp_Mls_MessageContents_GroupMembershipChanges | ||
|
||
public let ContentTypeGroupMembershipChanged = ContentTypeID(authorityID: "xmtp.org", typeID: "group_membership_change", versionMajor: 1, versionMinor: 0) | ||
|
||
public struct GroupMembershipChangedCodec: ContentCodec { | ||
|
||
public typealias T = GroupMembershipChanges | ||
|
||
public init() { } | ||
|
||
public var contentType = ContentTypeGroupMembershipChanged | ||
|
||
public func encode(content: GroupMembershipChanges, client _: Client) throws -> EncodedContent { | ||
var encodedContent = EncodedContent() | ||
|
||
encodedContent.type = ContentTypeGroupMembershipChanged | ||
encodedContent.content = try content.serializedData() | ||
|
||
return encodedContent | ||
} | ||
|
||
public func decode(content: EncodedContent, client _: Client) throws -> GroupMembershipChanges { | ||
return try GroupMembershipChanges(serializedData: content.content) | ||
} | ||
|
||
public func fallback(content: GroupMembershipChanges) throws -> String? { | ||
return nil | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// | ||
// File.swift | ||
// | ||
// | ||
// Created by Pat Nakajima on 2/1/24. | ||
// | ||
|
||
import Foundation | ||
|
||
extension URL { | ||
static var documentsDirectory: URL { | ||
guard let documentsDirectory = try? FileManager.default.url( | ||
for: .documentDirectory, | ||
in: .userDomainMask, | ||
appropriateFor: nil, | ||
create: false | ||
) else { | ||
fatalError("No documents directory") | ||
} | ||
|
||
return documentsDirectory | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// | ||
// Group.swift | ||
// | ||
// | ||
// Created by Pat Nakajima on 2/1/24. | ||
// | ||
|
||
import Foundation | ||
import LibXMTP | ||
|
||
public struct Group: Identifiable, Equatable, Hashable { | ||
var ffiGroup: FfiGroup | ||
var client: Client | ||
|
||
public struct Member { | ||
var ffiGroupMember: FfiGroupMember | ||
|
||
public var accountAddress: String { | ||
ffiGroupMember.accountAddress | ||
} | ||
} | ||
|
||
public var id: Data { | ||
ffiGroup.id() | ||
} | ||
|
||
public static func == (lhs: Group, rhs: Group) -> Bool { | ||
lhs.id == rhs.id | ||
} | ||
|
||
public func hash(into hasher: inout Hasher) { | ||
id.hash(into: &hasher) | ||
} | ||
|
||
public func members() async throws -> [Member] { | ||
_ = try await ffiGroup.sync() | ||
return try ffiGroup.listMembers().map(\.fromFFI) | ||
} | ||
|
||
public var cachedMembers: [Member] { | ||
do { | ||
return try ffiGroup.listMembers().map(\.fromFFI) | ||
} catch { | ||
return [] | ||
} | ||
} | ||
|
||
public func addMembers(addresses: [String]) async throws { | ||
try await ffiGroup.addMembers(accountAddresses: addresses) | ||
try await ffiGroup.sync() | ||
} | ||
|
||
public func removeMembers(addresses: [String]) async throws { | ||
try await ffiGroup.removeMembers(accountAddresses: addresses) | ||
try await ffiGroup.sync() | ||
} | ||
|
||
public func send<T>(content: T, options: SendOptions? = nil) async throws { | ||
func encode<Codec: ContentCodec>(codec: Codec, content: Any) throws -> EncodedContent { | ||
if let content = content as? Codec.T { | ||
return try codec.encode(content: content, client: client) | ||
} else { | ||
throw CodecError.invalidContent | ||
} | ||
} | ||
|
||
let codec = client.codecRegistry.find(for: options?.contentType) | ||
var encoded = try encode(codec: codec, content: content) | ||
|
||
func fallback<Codec: ContentCodec>(codec: Codec, content: Any) throws -> String? { | ||
if let content = content as? Codec.T { | ||
return try codec.fallback(content: content) | ||
} else { | ||
throw CodecError.invalidContent | ||
} | ||
} | ||
|
||
if let fallback = try fallback(codec: codec, content: content) { | ||
encoded.fallback = fallback | ||
} | ||
|
||
if let compression = options?.compression { | ||
encoded = try encoded.compress(compression) | ||
} | ||
|
||
try await ffiGroup.send(contentBytes: encoded.serializedData()) | ||
} | ||
|
||
public func messages() async throws -> [DecodedMessage] { | ||
// TODO: paginate | ||
try await ffiGroup.sync() | ||
let messages = try ffiGroup.findMessages(opts: .init(sentBeforeNs: nil, sentAfterNs: nil, limit: nil)) | ||
|
||
return try messages.map { ffiMessage in | ||
let encodedContent = try EncodedContent(serializedData: ffiMessage.content) | ||
|
||
return DecodedMessage( | ||
client: client, | ||
topic: "", | ||
encodedContent: encodedContent, | ||
senderAddress: ffiMessage.addrFrom, | ||
sent: Date(timeIntervalSince1970: TimeInterval(ffiMessage.sentAtNs / 1_000_000_000)) | ||
) | ||
} | ||
} | ||
} |
Oops, something went wrong.