twilio-rn/modules/my-native-module/ios/MyNativeModule.swift

330 lines
10 KiB
Swift
Raw Normal View History

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) {
// urlsetter
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])
}
}