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.

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:

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];
}

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
    }
}];

Resetting a user's identity

You can reset the identity of a user which will force a new unique identifier to be generated. This will cause them to be unassociated with the any ongoing chats and the local cache to be discarded. Important This will also cause agents to no longer see past chats as they will be identified as a new visitor.

Swift

Chat.instance?.resetIdentity()

Objective-C

[ZDKChat.instance resetIdentity];

ObserveBehaviours

Usually you'll have multiple subscriptions to chat observers. Storing reference and cancelling ObservationTokens 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()
    }
}