Using the Chat SDK API providers
Using the Chat SDK API providers
The Chat SDK API providers encapsulate all of the functionality of the Chat SDK from setting visitor information to more advanced functionality like observing certain events that can occur during a chat.
If you wish to build your own UI, you can use these providers to implement functionality such as sending messages on behalf of the visitor.
Using the API providers alongside the Chat SDK
Please be aware, the Chat SDK has its own connection management, based on the lifecycle of the UIViewController provided by the Unified SDK. This is important if you are using the Chat API providers alongside the Chat SDK. The ownership of the connection life-cycle outside of the Chat screen, is in your own hands.
Important: Before using the API providers, make sure you call connect
, and set up a connection status observer to handle the connection state appropriately. This is required for Chat to work properly.
chat.connectionProvider.connect()
connect
can be called before or after the rest of your api calls.
This is because all api requests go into an operation queue. Once a connection is established, the requests are sent in sequence.
If you need to be certain an api call is made, you can wrap it in a once-off connection observation, like so:
func fireChatAPICalls() {
var token: ChatProvidersSDK.ObservationToken?
token = Chat.connectionProvider?.observeConnectionStatus { status in
guard status.isConnected else { return }
Chat.profileProvider?.addTags(["tag"])
Chat.profileProvider?.setNote("Visitor Notes")
token?.cancel() // Ensure call only happens once
}
Chat.connectionProvider?.connect()
}
Remember to call disconnect before any flow that brings the user back to the chat screen.
chat.connectionProvider.disconnect()
This article on implementing the Chat v1 message counter feature is a good sample on how to leverage the Chat APIs outside of the Chat screen.
Accessing the providers
Providers can be accessed from the Chat
singleton:
Swift
Chat.accountProvider
Chat.connectionProvider
Chat.chatProvider
Chat.profileProvider
Chat.pushNotificationsProvider
Chat.settingsProvider
Objective-C
ZDKChat.accountProvider
ZDKChat.connectionProvider
ZDKChat.chatProvider
ZDKChat.profileProvider
ZDKChat.pushNotificationsProvider
ZDKChat.settingsProvider
Observing events
The providers allow you to observe certain events that can occur. It's important that if you start observing these events that you also remember to stop observing them.
It's likely you will have multiple ObservationToken objects in your setup. Leverage ObserveBehaviours collection to group them nicely.
Swift
var token: ObservationToken?
init() {
let token = Chat.accountProvider?.observeAccount { (account) in
// The account model has changed
}
}
deinit() {
token?.cancel()
}
Objective-C
@property(nonatomic, retain) ZDKObservationToken *token;
- (instancetype)init {
ZDKObservationToken *token = [ZDKChat.accountProvider observeAccount:^(ZDKChatAccount *account) {
// The account model has changed
}];
}
- (void)dealloc {
[_token cancel];
}
Checking for info about an ongoing chat
You can check if there's already an ongoing conversation before starting the chat.
Note: This API proactively connects to web sockets for authenticated users.
This connection is kept alive. You should call disconnect()
on the ConnectionProvider if you don't need to keep it open.
Swift
Chat.chatProvider?.getChatInfo { (result) in
switch result {
case .success(let chatInfo):
if chatInfo.isChatting {
// There's an ongoing conversation
}
case .failure(let error):
// Something went wrong
}
}
Objective-C
[ZDKChat.getChatInfo:^(ZDKChatInfo *chatInfo, NSError *error) {
if (chatInfo.isChatting) {
/// There's an ongoing conversation
}
}];
Getting the availability of agents
You can check the availability of agents and departments:
Swift
Chat.accountProvider?.getAccount { (result) in
switch result {
case .success(let account):
switch account.accountStatus {
case .online:
// There are agents available
// You can then get the departments that have agents available
let onlineDepartments = account.departments?.map { $0.status == .online }
default:
// No agents are available
}
case .failure(let error):
// Something went wrong
}
}
Objective-C
[ZDKChat.accountProvider getAccount:^(ZDKChatAccount *account, NSError *error) {
if (account) {
switch (account.accountStatus) {
case ZDKChatAccountStatusOnline:
// There are agents available
// You can then get the departments that have agents available
NSArray *departments = account.departments;
NSArray *onlineDepartments = [departments objectsAtIndexes:[departments indexesOfObjectsPassingTest:^BOOL(ZDKDepartment *department, NSUInteger idx, BOOL *stop) {
return department.departmentStatus == ZDKDepartmentStatusOnline;
}]];
break;
default:
break;
}
}
}];
For details about the Account
class, see the reference docs.
You can also observe changes to the availability of agents:
Swift
let token = Chat.accountProvider?.observeAccount { (account) in
switch account.status {
case .online:
// Agents are available
break
default:
// No agents are available
break
}
}
Objective-C
ZDKObservationToken *token = [Chat.accountProvider observeAccount:^(ZDKChatAccount *account) {
switch (account.status) {
case ZDKChatAccountStatusOnline:
// Agents are available
break;
default:
// No agents are available
break;
}
}];
Observing changes to Chat settings
You can be notified of any changes that are made to the settings in the Chat dashboard:
Swift
let token = Chat.settingsProvider?.observeChatSettings { (settings) in
switch settings.isFileSendingEnabled {
case true:
// Attachments are enabled
case false:
// Attachments are disabled
}
}
Objective-C
ZDKObservationToken *token = [ZDKChat.settingsProvider observeChatSettings:^(ZDKChatSettings* settings) {
if (settings.isFileSendingEnabled) {
// Attachments are enabled
} else {
// Attachments are disabled
}
}];
For details about the ChatSettings
class, see the reference docs.
Observing the connection state
You can listen for connection status changes:
Swift
let token = Chat.connectionProvider?.observeConnectionStatus { (status) in
switch status {
case .connecting, .connected:
break
case .disconnected, .reconnecting, .failed, .unreachable:
break
}
}
Objective-C
ZDKObservationToken *token = [ZDKChat.connectionProvider observeConnectionStatus:^(enum ZDKConnectionStatus status) {
switch (status) {
case ZDKConnectionStatusConnected:
break;
case ZDKConnectionStatusDisconnected:
break;
default:
break;
}
}];
Observing the chat state
You can observe the state of the chat, and gather information about the session:
Swift
let token = Chat.chatProvider?.observeChatState { (chatState) in
// Handle chatState updates
}
Objective-C
ZDKObservationToken *token = [ZDKChat.chatProvider observeChatState:^(ZDKChatState *chatState) {
// Handle chatState updates
}];
The ChatState
object has the following properties:
Property | Description |
---|---|
agents | List of agents in the chat. |
logs | Array of ChatLog items that represent the messages in the conversation. |
queuePosition | The visitor's current queue position. |
isChatting | Whether the visitor has started chatting with an agent. |
department | Department requested by the visitor. |
chatSessionStatus | The phase of the current chat session. See the reference docs. |
rating | The rating of the current session given by the visitor. |
comment | The rating comment of the current session given by the visitor. |
For details about the ChatState
class, see the reference docs.
Sending a message
Swift
Chat.chatProvider?.sendMessage("Help me.")
Chat.chatProvider?.sendMessage("Help me.") { (result) in
switch result {
case .success(let messageId):
// The message was successfully sent
case .failure(let error):
// Something went wrong
// You can easily retrieve the messageId to use when retrying
let messageId = error.messageId
}
}
Objective-C
[ZDKChat.chatProvider sendMessage:@"Hi!" completion:^(NSString *messageId, NSError *error) {
if (messageId) {
// The message was successfully sent
}
}];
You can try resending or deleting a failed message with the following methods, which take the chatLogId
as an argument:
Swift
Chat.chatProvider?.resendFailedMessage(withId: "messageId")
Objective-C
[ZDKChat.chatProvider resendFailedMessageWithId:@"messageId" completion:nil];
Swift
Chat.chatProvider?.deleteFailedMessage(withId: "messageId")
Objective-C
[ZDKChat.chatProvider deleteFailedMessageWithId:@"messageId" completion:nil];
Sending an attachment
An attachment can be sent by providing a URL
. There are two closures, the first will fire with the progress of the upload and the second when the upload is complete. The Result
passed in will identify the success or failure.
Swift
Chat.chatProvider?.sendFile(url: fileURL, onProgress: { (progress) in
// Do something with the progress
}, completion: { result in
switch result {
case .success:
// The attachment was sent
case .failure(let error):
// Something went wrong
}
})
Objective-C
[ZDKChat.chatProvider sendFileWithUrl:url
onProgress:^(double progress) {
// Do something with the progress
} completion:^(NSString *identifier, ZDKChatAttachmentMessage *attachment, NSError *error) {
if (attachment) {
// The attachment was sent
}
}];
You can resend a file with the following method, which takes the chatLogId
as an argument:
Swift
Chat.chatProvider?.resendFailedFile(withId: "Id", onProgress: { (progress) in
// Do something with the progress
}, completion: { (result) in
// Do something with the result
})
Objective-C
[ZDKChat.chatProvider sendFileWithUrl:url
onProgress:^(double progress) {
// Do something with the progress
} completion:^(NSString *identifier, ZDKChatAttachmentMessage *attachment, NSError *error) {
if (attachment) {
// The attachment was successfully resent
}
}];
Ending a chat
You can end a chat at any point and use the closure to verify whether it was successful.
Swift
Chat.chatProvider?.endChat()
Chat.chatProvider?.endChat { (result) in
switch result {
case .success:
// The chat was successfully ended
case .failure(let error):
// Something went wrong
}
}
Objective-C
[ZDKChat.chatProvider endChat:^(BOOL didEndChat, NSError *error) {
if (didEndChat) {
// The chat was successfully ended
}
}];
Adding and removing tags
To append a specific tag:
Swift
Chat.profileProvider?.addTags(["Tag"])
Objective-C
[ZDKChat.profileProvider addTags:@[@"Tag"] completion:nil];
To remove a tag that has already been added:
Swift
Chat.profileProvider?.removeTags(["Tag"])
Objective-C
[ZDKChat.profileProvider removeTags:@[@"Tag"] completion:nil];
If you need to clear all tags that have been added to a chat, you will need to keep track of each possible tag:
Below is an example that uses CaseIterable
:
Swift
enum Tags: String, CaseIterable {
case products
case help
case mobile
}
func clearTags() {
let tags = Tags.allCases.map { $0.rawValue }
Chat.profileProvider?.removeTags(tags)
}
Sending a chat rating
Swift
Chat.chatProvider?.sendChatRating(.good)
Objective-C
[ZDKChat.chatProvider sendChatRating:ZDKRatingGood completion:nil];
Sending a chat comment
Swift
Chat.chatProvider?.sendChatComment("Very helpful, thanks!")
Objective-C
[ZDKChat.chatProvider sendChatComment:@"Very helpful, thanks!" completion:nil];
Sending an offline message
This method should only be used to send an offline message to an offline account or department. A new chat is created every time this method is called. If your Chat account is linked to a Support account, a ticket will automatically be created for each message.
Swift
let visitorInfo = VisitorInfo(name: "Name",
email: "Email",
phoneNumber: "Phone Number")
let offlineForm = OfflineForm(visitorInfo: visitorInfo,
departmentId: "Department ID",
message: "Message")
Chat.chatProvider?.sendOfflineForm(offlineForm) { (result) in
switch result {
case .success:
// The form was sent
case .failure(let error):
// Something went wrong
}
}
Objective-C
ZDKVisitorInfo *visitorInfo = [[ZDKVisitorInfo alloc] initWithName:@"Name"
email:@"Email"
phoneNumber:@"Phone Number"];
ZDKOfflineForm *form = [[ZDKOfflineForm alloc] initWithVisitorInfo:visitorInfo
departmentId:@"Department ID"
message:@"Message"];
[ZDKChat.chatProvider sendOfflineForm:form
completion:^(ZDKOfflineForm *offlineForm, NSError *error) {
if (offlineForm) {
// The form was sent
}
}];
ObserveBehaviours
Usually you'll have multiple subscriptions to chat observers. Storing reference and cancelling ObservationToken
s can bloat your codebase. We've provided the ObserveBehaviours
collection for handling these tokens in a concise manner.
Swift
final class ChatWrapper {
var observeBehaviours: ObserveBehaviours?
let chat: Chat
func observeChat() {
observeBehaviours = ObserveBehaviours(
observeChatSettings(),
observeChatState()
)
}
func observeChatSettings() -> ObservationBehaviour {
chat.settingsProvider.observeChatSettings { settings in
// Handle settings update
}.asBehaviour()
}
func observeChatState() -> ObservationBehaviour {
chat.chatProvider.observeChatState { state in
// Handle chatState update
}.asBehaviour()
}
func unobserveChat() {
observeBehaviours?.unobserve()
}
deinit {
unobserveChat()
}
}