Add Swift UniFFI session bridge adapter
This commit is contained in:
@@ -156,12 +156,21 @@ public struct Profile: Equatable, Sendable {
|
||||
public enum SessionEvent: Equatable, Sendable {
|
||||
case authChanged(AuthState)
|
||||
case chatListChanged([ChatSummary])
|
||||
case folderListChanged([Folder])
|
||||
case messageAdded(Int64, Message)
|
||||
case messageUpdated(Int64, Message)
|
||||
case messageDeleted(Int64, [Int64])
|
||||
case reactionChanged(Int64, Int64, [Reaction])
|
||||
case incomingNotificationCandidate(ChatSummary, Message, String)
|
||||
case networkChanged(NetworkState)
|
||||
case draftChanged(Draft)
|
||||
case profileLoaded(Profile)
|
||||
case mediaDownloadProgress(fileId: Int32, downloadedSize: Int64, totalSize: Int64)
|
||||
}
|
||||
|
||||
public enum NetworkState: Equatable, Sendable {
|
||||
case waitingForNetwork
|
||||
case connectingToProxy
|
||||
case connecting
|
||||
case updating
|
||||
case ready
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
import Foundation
|
||||
|
||||
#if canImport(tele_ios_ffiFFI)
|
||||
import tele_ios_ffiFFI
|
||||
|
||||
public actor UniFfiSessionBridge: SessionBridge {
|
||||
private let handle: SessionHandle
|
||||
private let defaultLimit: Int32
|
||||
|
||||
public init(account: Account, useFakeTdlib: Bool = true, defaultLimit: Int32 = 100) throws {
|
||||
self.handle = try createSession(config: IosSessionConfig(
|
||||
accountId: account.id,
|
||||
displayName: account.displayName,
|
||||
databasePath: account.databasePath.path,
|
||||
useFakeTdlib: useFakeTdlib
|
||||
))
|
||||
self.defaultLimit = defaultLimit
|
||||
}
|
||||
|
||||
public init(handle: SessionHandle, defaultLimit: Int32 = 100) {
|
||||
self.handle = handle
|
||||
self.defaultLimit = defaultLimit
|
||||
}
|
||||
|
||||
public func authState() async throws -> AuthState {
|
||||
Self.mapAuthState(handle.authState())
|
||||
}
|
||||
|
||||
public func pollEvents() async throws -> [SessionEvent] {
|
||||
handle.pollEvents().map(Self.mapEvent)
|
||||
}
|
||||
|
||||
public func sendPhoneNumber(_ phone: String) async throws {
|
||||
try handle.sendPhoneNumber(phone: phone)
|
||||
}
|
||||
|
||||
public func sendCode(_ code: String) async throws {
|
||||
try handle.sendCode(code: code)
|
||||
}
|
||||
|
||||
public func sendPassword(_ password: String) async throws {
|
||||
try handle.sendPassword(password: password)
|
||||
}
|
||||
|
||||
public func loadFolders() async throws -> [Folder] {
|
||||
handle.loadFolders().map(Self.mapFolder)
|
||||
}
|
||||
|
||||
public func loadChats(folderId: Int32?) async throws -> [ChatSummary] {
|
||||
let chats = if let folderId {
|
||||
try handle.loadFolderChats(folderId: folderId, limit: defaultLimit)
|
||||
} else {
|
||||
try handle.loadChats(limit: defaultLimit)
|
||||
}
|
||||
return chats.map(Self.mapChatSummary)
|
||||
}
|
||||
|
||||
public func loadHistory(chatId: Int64) async throws -> [Message] {
|
||||
try handle.loadHistory(chatId: chatId, limit: defaultLimit)
|
||||
.map { Self.mapMessage($0, chatId: chatId) }
|
||||
}
|
||||
|
||||
public func searchMessages(chatId: Int64, query: String) async throws -> [Message] {
|
||||
try handle.searchMessages(chatId: chatId, query: query)
|
||||
.map { Self.mapMessage($0.message, chatId: $0.chatId) }
|
||||
}
|
||||
|
||||
public func openProfile(chatId: Int64) async throws -> Profile {
|
||||
try Self.mapProfile(handle.openProfile(chatId: chatId))
|
||||
}
|
||||
|
||||
public func sendMessage(chatId: Int64, text: String, replyToMessageId: Int64?) async throws -> Message {
|
||||
try Self.mapMessage(
|
||||
handle.sendMessage(chatId: chatId, text: text, replyToMessageId: replyToMessageId),
|
||||
chatId: chatId
|
||||
)
|
||||
}
|
||||
|
||||
public func editMessage(chatId: Int64, messageId: Int64, text: String) async throws -> Message {
|
||||
try Self.mapMessage(
|
||||
handle.editMessage(chatId: chatId, messageId: messageId, text: text),
|
||||
chatId: chatId
|
||||
)
|
||||
}
|
||||
|
||||
public func deleteMessages(chatId: Int64, messageIds: [Int64]) async throws {
|
||||
try handle.deleteMessages(chatId: chatId, messageIds: messageIds, revoke: true)
|
||||
}
|
||||
|
||||
public func forwardMessages(toChatId: Int64, fromChatId: Int64, messageIds: [Int64]) async throws {
|
||||
try handle.forwardMessages(toChatId: toChatId, fromChatId: fromChatId, messageIds: messageIds)
|
||||
}
|
||||
|
||||
public func react(chatId: Int64, messageId: Int64, reaction: String) async throws -> [Reaction] {
|
||||
try handle.react(chatId: chatId, messageId: messageId, reaction: reaction)
|
||||
.map(Self.mapReaction)
|
||||
}
|
||||
|
||||
public func pinnedMessages(chatId: Int64) async throws -> [Message] {
|
||||
[]
|
||||
}
|
||||
|
||||
public func copyPayload(chatId: Int64, messageId: Int64) async throws -> String {
|
||||
try handle.copyPayload(chatId: chatId, messageId: messageId)
|
||||
}
|
||||
|
||||
private static func mapAuthState(_ state: IosAuthState) -> AuthState {
|
||||
switch state {
|
||||
case .waitTdlibParameters:
|
||||
.waitTdlibParameters
|
||||
case .waitPhoneNumber:
|
||||
.waitPhoneNumber
|
||||
case .waitCode:
|
||||
.waitCode
|
||||
case .waitPassword:
|
||||
.waitPassword
|
||||
case .ready:
|
||||
.ready
|
||||
case .closed:
|
||||
.closed
|
||||
case let .error(message):
|
||||
.error(message)
|
||||
}
|
||||
}
|
||||
|
||||
private static func mapNetworkState(_ state: IosNetworkState) -> NetworkState {
|
||||
switch state {
|
||||
case .waitingForNetwork:
|
||||
.waitingForNetwork
|
||||
case .connectingToProxy:
|
||||
.connectingToProxy
|
||||
case .connecting:
|
||||
.connecting
|
||||
case .updating:
|
||||
.updating
|
||||
case .ready:
|
||||
.ready
|
||||
}
|
||||
}
|
||||
|
||||
private static func mapFolder(_ folder: IosFolder) -> Folder {
|
||||
Folder(id: folder.id, name: folder.name)
|
||||
}
|
||||
|
||||
private static func mapDraft(_ draft: IosDraft) -> Draft {
|
||||
Draft(chatId: draft.chatId, text: draft.text)
|
||||
}
|
||||
|
||||
private static func mapChatSummary(_ chat: IosChatSummary) -> ChatSummary {
|
||||
ChatSummary(
|
||||
id: chat.id,
|
||||
title: chat.title,
|
||||
username: chat.username,
|
||||
lastMessage: chat.lastMessage,
|
||||
unreadCount: chat.unreadCount,
|
||||
unreadMentionCount: chat.unreadMentionCount,
|
||||
isPinned: chat.isPinned,
|
||||
folderIds: chat.folderIds,
|
||||
isMuted: chat.isMuted,
|
||||
draft: chat.draft.map(mapDraft)
|
||||
)
|
||||
}
|
||||
|
||||
private static func mapReaction(_ reaction: IosReaction) -> Reaction {
|
||||
Reaction(emoji: reaction.emoji, count: reaction.count, isChosen: reaction.isChosen)
|
||||
}
|
||||
|
||||
private static func mapMessage(_ message: IosMessage, chatId: Int64) -> Message {
|
||||
Message(
|
||||
id: message.id,
|
||||
chatId: chatId,
|
||||
senderName: message.senderName,
|
||||
text: message.text,
|
||||
isOutgoing: message.isOutgoing,
|
||||
isRead: message.isRead,
|
||||
editDate: message.editDate,
|
||||
replyText: message.reply?.text,
|
||||
forwardSenderName: message.forward?.senderName,
|
||||
reactions: message.reactions.map(mapReaction)
|
||||
)
|
||||
}
|
||||
|
||||
private static func mapProfile(_ profile: IosProfile) -> Profile {
|
||||
Profile(
|
||||
chatId: profile.chatId,
|
||||
title: profile.title,
|
||||
username: profile.username,
|
||||
bio: profile.bio ?? profile.description,
|
||||
isGroup: profile.isGroup,
|
||||
memberCount: profile.memberCount
|
||||
)
|
||||
}
|
||||
|
||||
private static func mapEvent(_ event: IosEvent) -> SessionEvent {
|
||||
switch event {
|
||||
case let .authChanged(state):
|
||||
.authChanged(mapAuthState(state))
|
||||
case let .chatListChanged(chats):
|
||||
.chatListChanged(chats.map(mapChatSummary))
|
||||
case let .folderListChanged(folders):
|
||||
.folderListChanged(folders.map(mapFolder))
|
||||
case let .messageAdded(chatId, message):
|
||||
.messageAdded(chatId, mapMessage(message, chatId: chatId))
|
||||
case let .messageUpdated(chatId, message):
|
||||
.messageUpdated(chatId, mapMessage(message, chatId: chatId))
|
||||
case let .messageDeleted(chatId, messageIds):
|
||||
.messageDeleted(chatId, messageIds)
|
||||
case let .reactionChanged(chatId, messageId, reactions):
|
||||
.reactionChanged(chatId, messageId, reactions.map(mapReaction))
|
||||
case let .incomingNotificationCandidate(chat, message, senderName):
|
||||
.incomingNotificationCandidate(
|
||||
mapChatSummary(chat),
|
||||
mapMessage(message, chatId: chat.id),
|
||||
senderName
|
||||
)
|
||||
case let .networkChanged(state):
|
||||
.networkChanged(mapNetworkState(state))
|
||||
case let .draftChanged(draft):
|
||||
.draftChanged(mapDraft(draft))
|
||||
case let .profileLoaded(profile):
|
||||
.profileLoaded(mapProfile(profile))
|
||||
case let .mediaDownloadProgress(fileId, downloadedSize, totalSize):
|
||||
.mediaDownloadProgress(fileId: fileId, downloadedSize: downloadedSize, totalSize: totalSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user