import ExpoModulesCore // 导入Twilio Conversations SDK import TwilioConversationsClient public class MyNativeModule: Module, TwilioConversationsClientDelegate { // 存储Twilio客户端实例 private var conversationsClient: TwilioConversationsClient? // 初始化时创建的Promise解析器,用于异步操作 private var initCompletion: PromiseCompletionBlock? private var createConversationCompletion: PromiseCompletionBlock? // Each module class must implement the definition function. public func definition() -> ModuleDefinition { // 设置模块名称 Name("MyNativeModule") // 定义常量 Constant("PI") { Double.pi } // 定义模块可以发送到JavaScript的事件 Events( "onChange", "onClientSynchronized", "onClientError", "onConnectionStateChanged", "onConversationAdded", "onConversationUpdated", "onConversationDeleted", "onMessageAdded", "onMessageUpdated", "onMessageDeleted", "onParticipantAdded", "onParticipantUpdated", "onParticipantDeleted" ) // 同步函数 Function("hello") { return "Hello world! 👋" } // 原有异步函数 AsyncFunction("setValueAsync") { (value: String) in // Send an event to JavaScript. self.sendEvent("onChange", [ "value": value ]) } // Twilio Conversations 客户端初始化 AsyncFunction("initialize") { (token: String, completion: @escaping PromiseCompletionBlock) -> Void in if token.isEmpty { completion(["error": "Token cannot be empty"]) return } // 保存完成回调 self.initCompletion = completion // 创建Twilio客户端实例 TwilioConversationsClient.conversationsClient(withToken: token, properties: nil, delegate: self) { result, error in if let error = error { self.sendEvent("onClientError", ["error": error.localizedDescription]) self.initCompletion?(nil, error) return } if let client = result { self.conversationsClient = client // 发送成功消息 self.initCompletion?("Twilio Conversations 客户端已成功初始化", nil) } else { self.initCompletion?(["error": "Failed to initialize client"]) } } } // 获取所有对话列表 AsyncFunction("getConversations") { (completion: @escaping PromiseCompletionBlock) -> Void in guard let client = self.conversationsClient else { completion(["error": "客户端未初始化"]) return } // 获取对话列表 client.conversations() { result, error in if let error = error { completion(nil, error) return } if let conversations = result { // 转换为JS友好的格式 let jsConversations = conversations.map { conversation -> [String: Any] in var conversationDict: [String: Any] = [ "sid": conversation.sid, "friendlyName": conversation.friendlyName ?? "未命名对话" ] // 添加时间戳信息(如果可用) if let dateCreated = conversation.dateCreated { conversationDict["dateCreated"] = Int(dateCreated.timeIntervalSince1970 * 1000) } if let dateUpdated = conversation.dateUpdated { conversationDict["dateUpdated"] = Int(dateUpdated.timeIntervalSince1970 * 1000) } return conversationDict } completion(jsConversations, nil) } else { completion([], nil) } } } // 创建新对话 AsyncFunction("createConversation") { (friendlyName: String, completion: @escaping PromiseCompletionBlock) -> Void in guard let client = self.conversationsClient else { completion(["error": "客户端未初始化"]) return } if friendlyName.isEmpty { completion(["error": "对话名称不能为空"]) return } // 保存完成回调 self.createConversationCompletion = completion // 创建对话 client.createConversation(options: ["friendlyName": friendlyName]) { result, error in if let error = error { completion(nil, error) return } if let conversation = result { // 返回创建状态和名称 completion(["status": "creating", "friendlyName": conversation.friendlyName ?? friendlyName], nil) // 发送事件通知 self.sendEvent("onConversationAdded", [ "sid": conversation.sid, "friendlyName": conversation.friendlyName ?? friendlyName ]) } else { completion(["error": "创建对话失败"]) } } } // 获取客户端状态 AsyncFunction("getClientStatus") { (completion: @escaping PromiseCompletionBlock) -> Void in guard let client = self.conversationsClient else { completion("not_initialized") return } // 根据连接状态返回相应的状态字符串 switch client.connectionState { case .connecting: completion("connecting") case .connected: completion("connected") case .disconnected: completion("disconnected") case .denied: completion("denied") case .error: completion("error") @unknown default: completion("unknown") } } // 断开客户端连接 AsyncFunction("disconnect") { (completion: @escaping PromiseCompletionBlock) -> Void in guard let client = self.conversationsClient else { completion("already_disconnected") return } // 断开连接 client.shutdown() self.conversationsClient = nil completion("disconnected") } // 原生视图定义 View(MyNativeModuleView.self) { // 定义url属性的setter Prop("url") { (view: MyNativeModuleView, url: URL) in if view.webView.url != url { view.webView.load(URLRequest(url: url)) } } Events("onLoad") } } // MARK: - TwilioConversationsClientDelegate方法 // 客户端同步完成 public func conversationsClientDidSynchronize(_ client: TwilioConversationsClient) { sendEvent("onClientSynchronized", ["status": "synchronized"]) } // 客户端连接状态变化 public func conversationsClient(_ client: TwilioConversationsClient, connectionStateChanged state: TwilioConversationsClient.ConnectionState) { var stateString: String switch state { case .connecting: stateString = "connecting" case .connected: stateString = "connected" case .disconnected: stateString = "disconnected" case .denied: stateString = "denied" case .error: stateString = "error" @unknown default: stateString = "unknown" } sendEvent("onConnectionStateChanged", ["state": stateString]) } // 对话添加 public func conversationsClient(_ client: TwilioConversationsClient, conversationAdded conversation: TCHConversation) { sendEvent("onConversationAdded", [ "sid": conversation.sid, "friendlyName": conversation.friendlyName ?? "未命名对话" ]) } // 对话更新 public func conversationsClient(_ client: TwilioConversationsClient, conversationUpdated conversation: TCHConversation) { sendEvent("onConversationUpdated", [ "sid": conversation.sid, "friendlyName": conversation.friendlyName ?? "未命名对话" ]) } // 对话删除 public func conversationsClient(_ client: TwilioConversationsClient, conversationDeleted conversation: TCHConversation) { sendEvent("onConversationDeleted", ["sid": conversation.sid]) } // 消息添加 public func conversationsClient(_ client: TwilioConversationsClient, conversation: TCHConversation, messageAdded message: TCHMessage) { sendEvent("onMessageAdded", [ "conversationSid": conversation.sid, "messageSid": message.sid ]) } // 消息更新 public func conversationsClient(_ client: TwilioConversationsClient, conversation: TCHConversation, messageUpdated message: TCHMessage) { sendEvent("onMessageUpdated", [ "conversationSid": conversation.sid, "messageSid": message.sid ]) } // 消息删除 public func conversationsClient(_ client: TwilioConversationsClient, conversation: TCHConversation, messageDeleted message: TCHMessage) { sendEvent("onMessageDeleted", [ "conversationSid": conversation.sid, "messageSid": message.sid ]) } // 参与者添加 public func conversationsClient(_ client: TwilioConversationsClient, conversation: TCHConversation, participantAdded participant: TCHParticipant) { sendEvent("onParticipantAdded", [ "conversationSid": conversation.sid, "participantIdentity": participant.identity ?? "" ]) } // 参与者更新 public func conversationsClient(_ client: TwilioConversationsClient, conversation: TCHConversation, participantUpdated participant: TCHParticipant) { sendEvent("onParticipantUpdated", [ "conversationSid": conversation.sid, "participantIdentity": participant.identity ?? "" ]) } // 参与者删除 public func conversationsClient(_ client: TwilioConversationsClient, conversation: TCHConversation, participantDeleted participant: TCHParticipant) { sendEvent("onParticipantDeleted", [ "conversationSid": conversation.sid, "participantIdentity": participant.identity ?? "" ]) } // 客户端错误 public func conversationsClient(_ client: TwilioConversationsClient, synchronizationStatusChanged status: TCHClientSynchronizationStatus) { // 同步状态变化事件处理 var statusString: String switch status { case .started: statusString = "started" case .completed: statusString = "completed" case .failed: statusString = "failed" @unknown default: statusString = "unknown" } sendEvent("onClientSynchronized", ["status": statusString]) } }