mirror of
https://github.com/hub-team/OnlineChatSdk-SwiftPM.git
synced 2026-04-14 16:53:52 +00:00
update
This commit is contained in:
@@ -15,8 +15,10 @@ class ViewController: UIViewController {
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
}
|
||||
@IBAction func openChat(_ sender: Any) {
|
||||
let chatController = storyboard?.instantiateViewController(withIdentifier: "DemoChatController") as! DemoController
|
||||
navigationController?.pushViewController(chatController, animated: true)
|
||||
// let chatController = storyboard?.instantiateViewController(withIdentifier: "DemoChatController") as! DemoController
|
||||
let chatController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DemoChatController") as! DemoController
|
||||
// navigationController?.pushViewController(chatController, animated: true)
|
||||
navigationController?.present(chatController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use_frameworks!
|
||||
|
||||
target 'OnlineChatSdk_Example' do
|
||||
pod 'OnlineChatSdk', :path => '../'
|
||||
pod 'OnlineChatSdk'
|
||||
# pod 'OnlineChatSdk', :path => '../'
|
||||
|
||||
target 'OnlineChatSdk_Tests' do
|
||||
inherit! :search_paths
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
PODS:
|
||||
- OnlineChatSdk (0.0.1)
|
||||
- OnlineChatSdk (0.0.2)
|
||||
|
||||
DEPENDENCIES:
|
||||
- OnlineChatSdk
|
||||
@@ -9,7 +9,7 @@ SPEC REPOS:
|
||||
- OnlineChatSdk
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
OnlineChatSdk: fdc87678fced5df5f4ad3f4304d3eec4de6dad4c
|
||||
OnlineChatSdk: 421b17a804f22c193f81f02a891e7d91128c525b
|
||||
|
||||
PODFILE CHECKSUM: adee2f574d16e8ed8f504f977cf28d2797543903
|
||||
|
||||
|
||||
4
Example/Pods/Manifest.lock
generated
4
Example/Pods/Manifest.lock
generated
@@ -1,5 +1,5 @@
|
||||
PODS:
|
||||
- OnlineChatSdk (0.0.1)
|
||||
- OnlineChatSdk (0.0.2)
|
||||
|
||||
DEPENDENCIES:
|
||||
- OnlineChatSdk
|
||||
@@ -9,7 +9,7 @@ SPEC REPOS:
|
||||
- OnlineChatSdk
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
OnlineChatSdk: fdc87678fced5df5f4ad3f4304d3eec4de6dad4c
|
||||
OnlineChatSdk: 421b17a804f22c193f81f02a891e7d91128c525b
|
||||
|
||||
PODFILE CHECKSUM: adee2f574d16e8ed8f504f977cf28d2797543903
|
||||
|
||||
|
||||
55
Example/Pods/OnlineChatSdk/OnlineChatSdk/Classes/ChatApi.swift
generated
Normal file
55
Example/Pods/OnlineChatSdk/OnlineChatSdk/Classes/ChatApi.swift
generated
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// ChatApi.swift
|
||||
// OnlineChatSdk
|
||||
//
|
||||
// Created by Andrew Blinov on 29/03/2019.
|
||||
// Copyright © 2019 Andrew Blinov. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class ChatApi {
|
||||
|
||||
private func post(_ url: String, _ params: Dictionary<String, Any>, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) {
|
||||
guard let url = URL(string: url) else { return }
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: []) else { return }
|
||||
request.httpBody = httpBody
|
||||
|
||||
let session = URLSession.shared
|
||||
session.dataTask(with: request, completionHandler: completionHandler).resume()
|
||||
}
|
||||
|
||||
public func send(_ token: String, _ method: String, _ params: Dictionary<String, Any>, callback: @escaping (NSDictionary?) -> Void) {
|
||||
let url = "https://admin.verbox.ru/api/chat/\(token)/\(method)"
|
||||
post(url, params) { (data, response, error) in
|
||||
guard let data = data else { return }
|
||||
do {
|
||||
let json = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary
|
||||
callback(json)
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
public func messages(_ token: String, params: Dictionary<String, Any>, callback: @escaping (NSDictionary?) -> Void) {
|
||||
send(token, "message", params, callback: callback)
|
||||
}
|
||||
|
||||
public static func getNewMessages(_ token: String, _ clientId: String, callback: @escaping (NSDictionary?) -> Void) {
|
||||
let dtFormatter = DateFormatter()
|
||||
dtFormatter.calendar = Calendar(identifier: Calendar.Identifier.iso8601)
|
||||
dtFormatter.locale = Locale(identifier: "en")
|
||||
dtFormatter.dateFormat = "yyyy'-'MM'-'dd'"
|
||||
dtFormatter.timeZone = TimeZone(secondsFromGMT: 10800)
|
||||
|
||||
let params = [
|
||||
"client": ["clientId": clientId],
|
||||
"sender": "operator",
|
||||
"status": "unreaded",
|
||||
"dateRange": ["start": dtFormatter.string(from: Date(timeIntervalSince1970: Date().timeIntervalSince1970 - 86400 * 14)), "stop": dtFormatter.string(from: Date())]
|
||||
] as [String : Any]
|
||||
(ChatApi()).messages(token, params: params, callback: callback)
|
||||
}
|
||||
}
|
||||
253
Example/Pods/OnlineChatSdk/OnlineChatSdk/Classes/ChatController.swift
generated
Normal file
253
Example/Pods/OnlineChatSdk/OnlineChatSdk/Classes/ChatController.swift
generated
Normal file
@@ -0,0 +1,253 @@
|
||||
//
|
||||
// ChatController.swift
|
||||
// OnlineChatSdk
|
||||
//
|
||||
// Created by Andrew Blinov on 22/03/2019.
|
||||
// Copyright © 2019 Andrew Blinov. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import WebKit
|
||||
import AVFoundation
|
||||
|
||||
open class ChatController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler {
|
||||
|
||||
public static let event_operatorSendMessage = "operatorSendMessage";
|
||||
public static let event_clientSendMessage = "clientSendMessage";
|
||||
public static let event_clientMakeSubscribe = "clientMakeSubscribe";
|
||||
public static let event_contactsUpdated = "contactsUpdated";
|
||||
public static let event_sendRate = "sendRate";
|
||||
public static let event_clientId = "clientId";
|
||||
|
||||
public static let method_setClientInfo = "setClientInfo";
|
||||
public static let method_setTarget = "setTarget";
|
||||
public static let method_openReviewsTab = "openReviewsTab";
|
||||
public static let method_openTab = "openTab";
|
||||
public static let method_sendMessage = "sendMessage";
|
||||
public static let method_receiveMessage = "receiveMessage";
|
||||
public static let method_setOperator = "setOperator";
|
||||
public static let method_getContacts = "getContacts";
|
||||
|
||||
public var chatView: WKWebView!
|
||||
private var callJs: Array<String>!
|
||||
private var didFinish: Bool = false
|
||||
|
||||
override public func loadView() {
|
||||
let contentController = WKUserContentController()
|
||||
contentController.add(self, name: "chatInterface")
|
||||
|
||||
let preferences = WKPreferences()
|
||||
preferences.javaScriptEnabled = true
|
||||
preferences.javaScriptCanOpenWindowsAutomatically = true
|
||||
|
||||
let config = WKWebViewConfiguration()
|
||||
config.userContentController = contentController
|
||||
config.preferences = preferences
|
||||
|
||||
var frame = UIScreen.main.bounds
|
||||
if self.parent != nil && self.parent?.view != nil && self.parent?.view.bounds != nil {
|
||||
frame = (self.parent?.view.bounds)!
|
||||
}
|
||||
self.chatView = WKWebView(frame: frame, configuration: config)
|
||||
self.chatView.navigationDelegate = self
|
||||
self.view = self.chatView
|
||||
}
|
||||
|
||||
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||
self.didFinish = true
|
||||
if self.callJs != nil && !self.callJs.isEmpty {
|
||||
for script in self.callJs {
|
||||
callJs(script)
|
||||
}
|
||||
self.callJs = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func getCallJsMethod(_ name: String, params: Array<Any>) -> String {
|
||||
var res: String = "window.MeTalk('"
|
||||
res.append(name)
|
||||
res.append("'")
|
||||
if params.count > 0 {
|
||||
for p in params {
|
||||
res.append(",")
|
||||
if p is Int {
|
||||
res.append(String(describing: p))
|
||||
} else if p is Command {
|
||||
res.append((p as! Command).command)
|
||||
} else {
|
||||
res.append("'")
|
||||
res.append(String(describing: p))
|
||||
res.append("'")
|
||||
}
|
||||
}
|
||||
}
|
||||
res.append(")")
|
||||
return res
|
||||
}
|
||||
|
||||
private func callJs(_ script: String) {
|
||||
self.chatView.evaluateJavaScript(script)
|
||||
}
|
||||
|
||||
private func toJson(_ jsonObj: AnyObject) -> String {
|
||||
var data:Data? = nil
|
||||
do {
|
||||
data = try JSONSerialization.data(withJSONObject: jsonObj, options: JSONSerialization.WritingOptions());
|
||||
} catch {}
|
||||
if data != nil {
|
||||
return NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! as String
|
||||
}
|
||||
return "{}"
|
||||
}
|
||||
|
||||
public func load(_ id: String, _ domain: String, _ language: String = "", _ clientId: String = "") {
|
||||
var setup: Dictionary<String, Any> = [:]
|
||||
if !language.isEmpty {
|
||||
setup["language"] = language
|
||||
}
|
||||
if !clientId.isEmpty {
|
||||
setup["clientId"] = clientId
|
||||
}
|
||||
let surl = "https://admin.verbox.ru/support/chat/\(id)/\(domain)"
|
||||
var url = URL(string: surl)
|
||||
if !setup.isEmpty {
|
||||
var urlComponents = URLComponents(url: url!, resolvingAgainstBaseURL: false)
|
||||
urlComponents?.queryItems = [URLQueryItem(name: "setup", value: toJson(setup as AnyObject))]
|
||||
url = urlComponents!.url!
|
||||
}
|
||||
if url == nil {
|
||||
url = URL(string: surl)
|
||||
}
|
||||
|
||||
self.chatView.load(URLRequest(url: url!))
|
||||
self.chatView.allowsBackForwardNavigationGestures = true
|
||||
}
|
||||
|
||||
public func callJsMethod(_ name: String, params: Array<Any>) {
|
||||
if self.didFinish {
|
||||
callJs(getCallJsMethod(name, params: params))
|
||||
} else {
|
||||
if self.callJs == nil {
|
||||
self.callJs = []
|
||||
}
|
||||
self.callJs.append(getCallJsMethod(name, params: params))
|
||||
}
|
||||
}
|
||||
|
||||
public func callJsSetClientInfo(_ jsonInfo: String) {
|
||||
callJsMethod(ChatController.method_setClientInfo, params: [jsonInfo])
|
||||
}
|
||||
|
||||
public func callJsSetTarget(_ reason: String) {
|
||||
callJsMethod(ChatController.method_setTarget, params: [reason])
|
||||
}
|
||||
|
||||
public func callJsOpenReviewsTab() {
|
||||
callJsMethod(ChatController.method_openReviewsTab, params: [])
|
||||
}
|
||||
|
||||
public func callJsOpenTab(_ index: Int) {
|
||||
callJsMethod(ChatController.method_openTab, params: [index])
|
||||
}
|
||||
|
||||
public func callJsSendMessage(_ text: String) {
|
||||
callJsMethod(ChatController.method_sendMessage, params: [text])
|
||||
}
|
||||
|
||||
public func callJsReceiveMessage(_ text: String, _ oper: String, _ simulateTyping: Int) {
|
||||
callJsMethod(ChatController.method_receiveMessage, params: [text, oper, simulateTyping])
|
||||
}
|
||||
|
||||
public func callJsSetOperator(_ login: String) {
|
||||
callJsMethod(ChatController.method_setOperator, params: [login])
|
||||
}
|
||||
|
||||
public func callJsGetContacts() {
|
||||
callJsMethod(ChatController.method_getContacts, params: [Command("window.getContactsCallback")])
|
||||
}
|
||||
|
||||
public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
|
||||
if message.name != "chatInterface" {
|
||||
return
|
||||
}
|
||||
|
||||
let jsonBody = (message.body as! String).data(using: .utf8)!
|
||||
let body = try? (JSONSerialization.jsonObject(with: jsonBody, options: .mutableLeaves) as! NSDictionary)
|
||||
if body == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if body!["name"] == nil {
|
||||
return
|
||||
}
|
||||
var data: NSDictionary?
|
||||
if body!["data"] != nil {
|
||||
data = (body!["data"] as! NSDictionary)
|
||||
} else {
|
||||
data = [:]
|
||||
}
|
||||
let name = body!["name"] as! String
|
||||
switch name {
|
||||
case ChatController.event_clientId:
|
||||
onClientId(data!["clientId"] != nil ? data!["clientId"] as! String : "")
|
||||
break
|
||||
case ChatController.event_sendRate:
|
||||
onSendRate(data!)
|
||||
break
|
||||
case ChatController.event_contactsUpdated:
|
||||
onContactsUpdated(data!)
|
||||
break
|
||||
case ChatController.event_clientSendMessage:
|
||||
onClientSendMessage(data!)
|
||||
break
|
||||
case ChatController.event_clientMakeSubscribe:
|
||||
onClientMakeSubscribe(data!)
|
||||
break
|
||||
case ChatController.event_operatorSendMessage:
|
||||
onOperatorSendMessage(data!)
|
||||
break
|
||||
case ChatController.method_getContacts:
|
||||
getContactsCallback(data!)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
onEvent(name, data!)
|
||||
}
|
||||
|
||||
open func playSound(_ systemSoundId: SystemSoundID) {
|
||||
AudioServicesPlaySystemSound(systemSoundId)
|
||||
}
|
||||
|
||||
open func onClientId(_ clientId: String) {
|
||||
|
||||
}
|
||||
|
||||
open func onSendRate(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
open func onContactsUpdated(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
open func onClientSendMessage(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
open func onClientMakeSubscribe(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
open func onOperatorSendMessage(_ data: NSDictionary) {
|
||||
self.playSound(1315)
|
||||
}
|
||||
|
||||
open func onEvent(_ name: String, _ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
open func getContactsCallback(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
}
|
||||
17
Example/Pods/OnlineChatSdk/OnlineChatSdk/Classes/Command.swift
generated
Normal file
17
Example/Pods/OnlineChatSdk/OnlineChatSdk/Classes/Command.swift
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// Command.swift
|
||||
// OnlineChatSdk
|
||||
//
|
||||
// Created by Andrew Blinov on 26/03/2019.
|
||||
// Copyright © 2019 Andrew Blinov. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Command {
|
||||
let command: String
|
||||
|
||||
init(_ command: String) {
|
||||
self.command = command
|
||||
}
|
||||
}
|
||||
141
Example/Pods/OnlineChatSdk/README.md
generated
Normal file
141
Example/Pods/OnlineChatSdk/README.md
generated
Normal file
@@ -0,0 +1,141 @@
|
||||
# OnlineChatSdk-Swift
|
||||
[](https://cocoapods.org/pods/OnlineChatSdk)
|
||||
[](https://cocoapods.org/pods/OnlineChatSdk)
|
||||

|
||||
|
||||
## Добавление в проект
|
||||
|
||||
pod 'OnlineChatSdk'
|
||||
|
||||
## Получение id
|
||||
Перейдите в раздел «Настройки - Установка» и скопируйте значение переменной id.
|
||||

|
||||
|
||||
## Пример использования
|
||||
Добавьте свой **ViewController** с суперклассом `ChatController`.
|
||||
```swift
|
||||
class MyController: ChatController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
load("<Ваш id>", "<Домен вашего сайта>")
|
||||
}
|
||||
}
|
||||
```
|
||||
Так же при загрузке можно указать **language** и **clientId**.
|
||||
```swift
|
||||
load("<Ваш id>", "<Домен вашего сайта>", "en", "newClientId")
|
||||
```
|
||||
|
||||
## События
|
||||
* **operatorSendMessage** - оператор отправил сообщение посетителю.
|
||||
* **clientSendMessage** - посетитель отправил сообщение оператору.
|
||||
* **clientMakeSubscribe** - посетитель заполнил форму.
|
||||
* **contactsUpdated** - посетитель обновил информацию о себе.
|
||||
* **sendRate** - посетитель отправил новый отзыв.
|
||||
* **clientId** - уникальный идентификатор посетителя.
|
||||
|
||||
Для каждого события есть персональный обработчик.
|
||||
```swift
|
||||
override func onOperatorSendMessage(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
override func onClientSendMessage(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
override func onClientMakeSubscribe(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
override func onContactsUpdated(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
override func onSendRate(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
|
||||
override func onClientId(_ clientId: String) {
|
||||
|
||||
}
|
||||
```
|
||||
Или можно задать один обработчик на все события.
|
||||
```swift
|
||||
override func onEvent(_ name: String, _ data: NSDictionary) {
|
||||
switch name {
|
||||
case ChatController.event_operatorSendMessage:
|
||||
break
|
||||
case ChatController.event_clientSendMessage:
|
||||
break
|
||||
case ChatController.event_clientMakeSubscribe:
|
||||
break
|
||||
case ChatController.event_contactsUpdated:
|
||||
break
|
||||
case ChatController.event_sendRate:
|
||||
break
|
||||
case ChatController.event_clientId:
|
||||
break
|
||||
case ChatController.method_getContacts:
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Методы
|
||||
* **setClientInfo** - изменение информации о посетителе.
|
||||
* **setTarget** - пометить посетителя целевым.
|
||||
* **openReviewsTab** - отобразить форму для отзыва.
|
||||
* **openTab** - отобразить необходимую вкладку.
|
||||
* **sendMessage** - отправка сообщения от имени клиента.
|
||||
* **receiveMessage** - отправка сообщения от имени оператора.
|
||||
* **setOperator** - выбор любого оператора.
|
||||
* **getContacts** - получение контактных данных.
|
||||
|
||||
```swift
|
||||
callJsSetClientInfo("{name: \"Имя\", email: \"test@mail.ru\"")
|
||||
|
||||
callJsSetTarget("reason")
|
||||
|
||||
callJsOpenReviewsTab()
|
||||
|
||||
callJsOpenTab(1)
|
||||
|
||||
callJsSendMessage("Здравствуйте! У меня серьёзная проблема!")
|
||||
|
||||
callJsReceiveMessage("Мы уже спешим на помощь ;)", "", 2000)
|
||||
|
||||
callJsSetOperator("Логин оператора")
|
||||
|
||||
callJsGetContacts() // результат прилетает в getContactsCallback
|
||||
override func getContactsCallback(_ data: NSDictionary) {
|
||||
|
||||
}
|
||||
```
|
||||
Подробное описание методов можно прочесть в разделе «Интеграция и API - Javascript API».
|
||||
|
||||
## Получение token
|
||||
Перейдите в раздел «Интеграция и API - REST API», скопируйте существующий token или добавьте новый.
|
||||

|
||||
|
||||
## ChatApi
|
||||
**getNewMessages** - получение новых сообщений от оператора.
|
||||
|
||||
```swift
|
||||
ChatApi.getNewMessages("<TOKEN>", "<clientId>")
|
||||
{(result) in
|
||||
if result?["error"] != nil {
|
||||
print("error : \(String(describing: result?["error"]))")
|
||||
} else {
|
||||
print("result : \(result.debugDescription)")
|
||||
}
|
||||
}
|
||||
```
|
||||
Подробное описание можно прочесть в разделе «Интеграция и API - REST API - Инструкции по подключению».
|
||||
|
||||
## License
|
||||
|
||||
OnlineChatSdk is available under the MIT license. See the LICENSE file for more info.
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.0.1</string>
|
||||
<string>0.0.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'OnlineChatSdk'
|
||||
s.version = '0.0.2'
|
||||
s.version = '0.0.3'
|
||||
s.summary = 'A small library containing a wrapper for the WKWebView.'
|
||||
s.swift_versions = '5.0'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user