diff --git a/.gitignore b/.gitignore index dcd2777..4bddbf0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ .DS_Store .idea .vscode +/js build *.iml +local.properties diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..0a10fe1 --- /dev/null +++ b/.npmignore @@ -0,0 +1,6 @@ +.DS_Store +.idea +.vscode +build +*.iml +local.properties \ No newline at end of file diff --git a/README.md b/README.md index f9d4215..8a7151f 100644 --- a/README.md +++ b/README.md @@ -1,56 +1,106 @@ -# react-native-webim +# webim-react-native Implementation of [webim sdk](https://webim.ru/) for [react-native](https://github.com/facebook/react-native) -**Important:** last tested react-native version is 59.9 +**Important:** Updated version for RN 0.60+ ## Installation ``` -yarn add react-native-webim -react-native link react-native-webim +yarn add webim-react-native ``` -iOS: +iOS +- add to PodFile + ``` + use_frameworks! + pod 'WebimClientLibrary', :git => 'https://github.com/webim/webim-client-sdk-ios.git', :tag => '3.29.0' +``` +- pod install - - add `Libraries/RNWebim/Libraries/WebimClientLibrary/Product/WebimClientLibrary.framework` into **Link Binary With Libraries** - - to be done - - move `WebimClientLibrary.framework` and `SQLite.framework` to **Embedded binaries** - - create empty swift file in ios project root and agree with creating bridging header. +**Note:** Flipper doesn't work with use_frameworks flag ## Usage **Important:** All methods are promise based and can throw exceptions -- Init chat: - ```js - webim.resumeSession("accountName", "location") +### Init chat + + ```ts +import webim from 'webim-react-native'; + +webim.resumeSession(builderParams) +``` + +```ts +type SessionBuilderParams = { + accountName: string; + location: string; + accountJSON?: string; + providedAuthorizationToken?: string; + appVersion?: string; + clearVisitorData?: boolean; + storeHistoryLocally?: boolean; + title?: string; + pushToken?: string; +}; ``` +- accountName (required) - name of your account in webim system +- location (required) - name of location. For example "mobile" +- accountJSON - encrypted json with user data. See **Start chat with user data** +- clearVisitorData - clear visitor data before start chat +- storeHistoryLocally - cache messages in local store +- title - title for chat in webim web panel +- providedAuthorizationToken - user token. Session will not start with wrong token. Read webim documentation +- pushToken +- appVersion + + +### Init events listeners -- Init events listeners: ```js -webim.addListener(webimEvents.NEW_MESSAGE, ({ msg }) => { +import webim, { WebimEvents} from 'webim-react-native'; + +const listener = webim.addNewMessageListener(({ msg }) => { + // do something +}); +// usubscribe +listener.remove(); + +// or +const listener2 = webim.addListener(WebimEvents.NEW_MESSAGE, ({ msg }) => { // do something }); ``` -Supported events: `NEW_MESSAGE, REMOVE_MESSAGE, EDIT_MESSAGE, CLEAR_DIALOG` +Supported events (`WebimEvents`): +- WebimEvents.NEW_MESSAGE; +- WebimEvents.REMOVE_MESSAGE; +- WebimEvents.EDIT_MESSAGE; +- WebimEvents.CLEAR_DIALOG; +- WebimEvents.TOKEN_UPDATED; +- WebimEvents.ERROR; + +### Get messages -- Get messages: ```js -const { messages } = await webim.getLastMessages(100); +const { messages } = await webim.getLastMessages(limit); // or -const { messages } = await webim.getNextMessages(100); +const { messages } = await webim.getNextMessages(limit); // or const { messages } = await webim.getAllMessages(); ``` Note: method `getAllMessages` works strange on iOS, and sometimes returns empty array. We recommend to use `getLastMessages` instead -- Send text message: +### Send text message + ``` webim.send(message); ``` -- Use build in method for file attaching: +### Attach files + +#### Use build in method for file attaching: + ```js try { await webim.tryAttachFile(); @@ -64,7 +114,8 @@ try { } ``` -- or attach files by yourself: +#### or attach files by yourself + ```js try { webim.sendFile(uri, name, mime, extension) @@ -73,19 +124,20 @@ try { } ``` -- rate current operator: +### Rate current operator ```js webim.rateOperator() ``` -- destroy session: +### Destroy session ```js -webim.destroySession(); +webim.destroySession(clearData); ``` -See `index.d.ts` for getting types information +- clearData (optional) boolean - If true wil ## Start chat with user data + See [webim documentation](https://webim.ru/kb/dev/identification/8265-id-2-0/) for client identification. Example: @@ -93,9 +145,10 @@ Example: - install [react-native-crypto](https://github.com/tradle/react-native-crypto) with all dependencies and run `rn-nodeify --hack --install` - run `rn-nodeify --hack --install` after each `npm install` (add in postinstall script) -```js +```ts import './shim'; // set your path to shim.js import crypto from 'crypto'; + const getHmac_sha256 = (str: string, privateKey: string) => { const hmac = crypto.createHmac('sha256', privateKey); const promise = new Promise((resolve: (hash: string) => void) => hmac.on('readable', () => { @@ -127,8 +180,3 @@ acc.hash = await getHash(acc.fields); await webim.resumeSession('accountName', 'location', JSON.stringify(acc)); ``` - -## TODO: - -- screenshots for installation guide -- example diff --git a/RNWebim.podspec b/RNWebim.podspec new file mode 100644 index 0000000..d5828a9 --- /dev/null +++ b/RNWebim.podspec @@ -0,0 +1,24 @@ +require 'json' + +package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) + +Pod::Spec.new do |s| + s.name = 'RNWebim' + s.version = package['version'] + s.summary = package['description'] + s.license = package['license'] + s.author = package['author'] + s.source = { :git => "https://github.com/volga-volga/react-native-webim.git", :tag => "v#{s.version}" } + + s.homepage = package['repository']['url'] + + s.requires_arc = true + s.platform = :ios, '9.0' + + s.preserve_paths = 'LICENSE', 'README.md', 'package.json', 'index.js' + s.source_files = "ios/*.{h,m,swift}" + + s.dependency 'React' + s.dependency 'WebimClientLibrary' + +end diff --git a/android/.gradle/4.6/fileChanges/last-build.bin b/android/.gradle/4.6/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/android/.gradle/4.6/fileChanges/last-build.bin differ diff --git a/android/.gradle/4.6/fileHashes/fileHashes.bin b/android/.gradle/4.6/fileHashes/fileHashes.bin new file mode 100644 index 0000000..57ecbca Binary files /dev/null and b/android/.gradle/4.6/fileHashes/fileHashes.bin differ diff --git a/android/.gradle/4.6/fileHashes/fileHashes.lock b/android/.gradle/4.6/fileHashes/fileHashes.lock new file mode 100644 index 0000000..26993ab Binary files /dev/null and b/android/.gradle/4.6/fileHashes/fileHashes.lock differ diff --git a/android/.gradle/5.5/fileChanges/last-build.bin b/android/.gradle/5.5/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/android/.gradle/5.5/fileChanges/last-build.bin differ diff --git a/android/.gradle/5.5/fileHashes/fileHashes.lock b/android/.gradle/5.5/fileHashes/fileHashes.lock new file mode 100644 index 0000000..a0ce78a Binary files /dev/null and b/android/.gradle/5.5/fileHashes/fileHashes.lock differ diff --git a/android/.gradle/5.5/gc.properties b/android/.gradle/5.5/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/android/.gradle/vcs-1/gc.properties b/android/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/android/.gradle/vcsWorkingDirs/gc.properties b/android/.gradle/vcsWorkingDirs/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/android/build.gradle b/android/build.gradle index ed07952..974979f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,33 +1,30 @@ apply plugin: 'com.android.library' +def safeExtGet(prop, fallback) { + rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback +} + android { - compileSdkVersion rootProject.ext.compileSdkVersion - buildToolsVersion rootProject.ext.buildToolsVersion + compileSdkVersion safeExtGet('compileSdkVersion', 28) + buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3') defaultConfig { - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion + minSdkVersion safeExtGet('minSdkVersion', 16) + targetSdkVersion safeExtGet('targetSdkVersion', 28) versionCode 1 - versionName "1.0" - ndk { - abiFilters "armeabi-v7a", "x86" - } + versionName "0.0.7" } lintOptions { - warning 'InvalidPackage' + warning 'InvalidPackage' } } -allprojects { - repositories { - jcenter() - } +repositories { + mavenCentral() } dependencies { - implementation 'com.webimapp.sdk:webimclientsdkandroid:3.26.2' + implementation 'com.webimapp.sdk:webimclientsdkandroid:3.32.5' implementation 'com.facebook.react:react-native:+' implementation 'com.google.android.gms:play-services-wallet:16.0.0' - // todo: - implementation "com.android.support:appcompat-v7:25.0.1" } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 9a4163a..e0c4de3 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/src/main/java/ru/vvdev/webim/WebimModule.java b/android/src/main/java/ru/vvdev/webim/WebimModule.java index 659481d..8276c2a 100644 --- a/android/src/main/java/ru/vvdev/webim/WebimModule.java +++ b/android/src/main/java/ru/vvdev/webim/WebimModule.java @@ -3,8 +3,8 @@ import android.app.Activity; import android.content.Intent; import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.webkit.MimeTypeMap; import com.facebook.react.bridge.ActivityEventListener; import com.facebook.react.bridge.Arguments; @@ -13,6 +13,7 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.modules.core.DeviceEventManagerModule; @@ -24,18 +25,22 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.webimapp.android.sdk.FatalErrorHandler; import com.webimapp.android.sdk.Message; import com.webimapp.android.sdk.MessageListener; import com.webimapp.android.sdk.MessageStream; import com.webimapp.android.sdk.MessageTracker; +import com.webimapp.android.sdk.NotFatalErrorHandler; import com.webimapp.android.sdk.Operator; import com.webimapp.android.sdk.Webim; import com.webimapp.android.sdk.WebimError; import com.webimapp.android.sdk.WebimSession; +import com.webimapp.android.sdk.ProvidedAuthorizationTokenStateListener; -public class WebimModule extends ReactContextBaseJavaModule implements MessageListener { +@SuppressWarnings("unused") +public class WebimModule extends ReactContextBaseJavaModule implements MessageListener, ProvidedAuthorizationTokenStateListener, FatalErrorHandler, NotFatalErrorHandler { private static final int FILE_SELECT_CODE = 0; - private static final String REACT_CLASS = "webim"; + private static final String REACT_CLASS = "RNWebim"; private static ReactApplicationContext reactContext = null; private Callback fileCbSuccess; @@ -63,7 +68,12 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode, ? null : uri.getLastPathSegment() + "." + extension; if (fileCbSuccess != null) { - fileCbSuccess.invoke(uri.toString(), name, mime, extension); + WritableMap _data = Arguments.createMap(); + _data.putString("uri", uri.toString()); + _data.putString("name", name); + _data.putString("mime", mime); + _data.putString("extension", extension); + fileCbSuccess.invoke(_data); } } else { fileCbFailure.invoke(getSimpleMap("message", "unknown")); @@ -97,23 +107,58 @@ public Map getConstants() { return new HashMap<>(); } - private void init(String accountName, String location, String account) { + private void init(String accountName, String location, @Nullable String accountJSON, @Nullable String providedAuthorizationToken, @Nullable String appVersion, @Nullable Boolean clearVisitorData, @Nullable Boolean storeHistoryLocally, @Nullable String title, @Nullable String pushToken) { Webim.SessionBuilder builder = Webim.newSessionBuilder() .setContext(reactContext) .setAccountName(accountName) .setLocation(location) - .setPushSystem(Webim.PushSystem.FCM) - .setPushToken("none"); - if (account != null) { - builder.setVisitorFieldsJson(account); + .setErrorHandler(this) + .setNotFatalErrorHandler(this) + .setPushSystem(Webim.PushSystem.FCM); + if (pushToken != null) { + builder.setPushToken(pushToken); + } + if (accountJSON != null) { + builder.setVisitorFieldsJson(accountJSON); + } + if (appVersion != null) { + builder.setAppVersion(appVersion); + } + if (clearVisitorData != null) { + builder.setClearVisitorData(clearVisitorData); + } + if (storeHistoryLocally != null) { + builder.setStoreHistoryLocally(storeHistoryLocally); + } + if (title != null) { + builder.setTitle(title); + } + if (providedAuthorizationToken != null) { + builder.setProvidedAuthorizationTokenStateListener(this, providedAuthorizationToken); } session = builder.build(); } @ReactMethod - public void resumeSession(String accountName, String location, String account, final Callback errorCallback, final Callback successCallback) { + public void resumeSession(ReadableMap builderData, final Callback errorCallback, final Callback successCallback) { + String accountName = builderData.getString("accountName"); + String location = builderData.getString("location"); + + // optional + String accountJSON = builderData.hasKey("accountJSON") ? builderData.getString("accountJSON") : null; + String providedAuthorizationToken = builderData.hasKey("providedAuthorizationToken") ? builderData.getString("providedAuthorizationToken") : null; + String appVersion = builderData.hasKey("appVersion") ? builderData.getString("appVersion") : null; + Boolean clearVisitorData = builderData.hasKey("clearVisitorData") ? builderData.getBoolean("clearVisitorData") : null; + Boolean storeHistoryLocally = builderData.hasKey("storeHistoryLocally") ? builderData.getBoolean("storeHistoryLocally") : null; + String title = builderData.hasKey("title") ? builderData.getString("title") : null; + String pushToken = builderData.hasKey("pushToken") ? builderData.getString("pushToken") : null; + + if (session == null) { + init(accountName, location, accountJSON, providedAuthorizationToken, appVersion, clearVisitorData, storeHistoryLocally, title, pushToken); + } + if (session == null) { - init(accountName, location, account); + errorCallback.invoke(getSimpleMap("message", "resume null session")); } session.resume(); session.getStream().startChat(); @@ -123,11 +168,15 @@ public void resumeSession(String accountName, String location, String account, f } @ReactMethod - public void destroySession(final Callback errorCallback, final Callback successCallback) { + public void destroySession(Boolean clearData, final Callback errorCallback, final Callback successCallback) { if (session != null) { session.getStream().closeChat(); tracker.destroy(); - session.destroy(); + if (clearData) { + session.destroyWithClearVisitorData(); + } else { + session.destroy(); + } session = null; } successCallback.invoke(Arguments.createMap()); @@ -303,7 +352,7 @@ private static void emitDeviceEvent(String eventName, @Nullable WritableMap even private WritableMap messageToJson(Message msg) { final WritableMap map = Arguments.createMap(); map.putString("id", msg.getId().toString()); - map.putInt("time", (int) msg.getTime()); + map.putDouble("time", msg.getTime()); map.putString("type", msg.getType().toString()); map.putString("text", msg.getText()); map.putString("name", msg.getSenderName()); @@ -350,4 +399,19 @@ private WritableMap getSimpleMap(String key, String value) { map.putString(key, value); return map; } + + @Override + public void updateProvidedAuthorizationToken(@NonNull String providedAuthorizationToken) { + emitDeviceEvent("tokenUpdated", getSimpleMap("token", providedAuthorizationToken)); + } + + @Override + public void onError(@NonNull WebimError error) { + emitDeviceEvent("error", getSimpleMap("message", error.getErrorString())); + } + + @Override + public void onNotFatalError(@NonNull WebimError error) { + emitDeviceEvent("error", getSimpleMap("message", error.getErrorString())); + } } diff --git a/index.d.ts b/index.d.ts deleted file mode 100644 index d5533ff..0000000 --- a/index.d.ts +++ /dev/null @@ -1,58 +0,0 @@ -declare module 'webim-react-native' { - export type WebimEvents = 'NEW_MESSAGE' | 'REMOVE_MESSAGE' | 'EDIT_MESSAGE' | 'CLEAR_DIALOG'; - - export const webimEvents: { [K in WebimEvents]: string }; - - export interface Attachment { - contentType: string; - info: string; - name: string; - size: number; - url: string; - } - - export interface Message { - id: string; - avatar?: string; - time: number; - type: 'OPERATOR' | 'VISITOR' | 'INFO'; - text: string; - name: string; - status: 'SENT'; - read: boolean; - canEdit: boolean; - attachment?: Attachment; - } - - export type WebimListener = (msg: T) => void; - - class webim { - resumeSession(accountName: string, location: string, acc?: string): Promise; - - destroySession(): Promise; - - getLastMessages(limit: number): Promise<{ messages: Message[] }>; - - getNextMessages(limit: number): Promise<{ messages: Message[] }>; - - getAllMessages(): Promise<{ messages: Message[] }>; - - send(message: string): Promise<{ id: string }>; - - rateOperator(rate: number): Promise; - - tryAttachFile(): Promise; - - sendFile(uri: string, name: string, mime: string, extension: string): Promise; - - addListener(event: string, listener: WebimListener): void; - - removeListener(event: string, listener: WebimListener): void; - - removeAllListeners(event: string): void; - } - - const Webim: webim; - - export default Webim; -} diff --git a/index.js b/index.js deleted file mode 100644 index 69b0015..0000000 --- a/index.js +++ /dev/null @@ -1,101 +0,0 @@ -import { NativeModules, NativeEventEmitter, Platform } from 'react-native'; - -const { webim: WebimNative } = NativeModules; -const emitter = new NativeEventEmitter(NativeModules.webim); - -export const webimEvents = { - NEW_MESSAGE: 'newMessage', - REMOVE_MESSAGE: 'removeMessage', - EDIT_MESSAGE: 'changedMessage', - CLEAR_DIALOG: 'allMessagesRemoved', -}; - -function parseNativeResponse(response) { - return response || null; -} - -function processError(e) { - return new Error(e.message); -} - -class webim { - static resumeSession(accountName, location, account) { - return new Promise((resolve, reject) => { - WebimNative.resumeSession(accountName, location, account, e => reject(processError(e)), res => resolve(parseNativeResponse(res))); - }); - } - - static destroySession() { - return new Promise((resolve, reject) => { - WebimNative.destroySession(e => reject(processError(e)), res => resolve(parseNativeResponse(res))); - }); - } - - static getLastMessages(limit) { - return new Promise((resolve, reject) => { - WebimNative.getLastMessages(limit, e => reject(processError(e)), messages => resolve(parseNativeResponse(messages))); - }); - } - - static getNextMessages(limit) { - return new Promise((resolve, reject) => { - WebimNative.getNextMessages(limit, e => reject(processError(e)), messages => resolve(parseNativeResponse(messages))); - }); - } - - static getAllMessages() { - return new Promise((resolve, reject) => { - WebimNative.getAllMessages(e => reject(processError(e)), messages => resolve(parseNativeResponse(messages))); - }); - } - - static send(message) { - return new Promise((resolve, reject) => WebimNative.send(message, e => reject(processError(e)), id => resolve(id))); - } - - static rateOperator(rate) { - return new Promise((resolve, reject) => { - WebimNative.rateOperator(rate, e => reject(processError(e)), () => resolve()); - }); - } - - static tryAttachFile() { - return new Promise((resolve, reject) => { - WebimNative.tryAttachFile(e => reject(processError(e)), async (...args) => { - let uri; - let name; - let mime; - let extension; - if (Platform.OS === 'ios') { - [{ uri, name, mime, extension }] = args; - } else { - [uri, name, mime, extension] = args; - } - try { - await webim.sendFile(uri, name, mime, extension); - resolve(); - } catch (e) { - reject(processError(e)); - } - }); - }); - } - - static sendFile(uri, name, mime, extension) { - return new Promise((resolve, reject) => WebimNative.sendFile(uri, name, mime, extension, reject, resolve)); - } - - static addListener(event, listener) { - emitter.addListener(event, listener); - } - - static removeListener(event, listener) { - emitter.removeListener(event, listener); - } - - static removeAllListeners(event) { - emitter.removeAllListeners(event); - } -} - -export default webim; diff --git a/ios/swift_bridging/Department.swift b/ios/Department.swift similarity index 98% rename from ios/swift_bridging/Department.swift rename to ios/Department.swift index 125b91f..5c4edfb 100755 --- a/ios/swift_bridging/Department.swift +++ b/ios/Department.swift @@ -29,7 +29,7 @@ import WebimClientLibrary // MARK: - Department @objc(Department) -final class _ObjCDepartment: NSObject { +public final class _ObjCDepartment: NSObject { // MARK: - Properties private let department: Department diff --git a/ios/swift_bridging/FatalErrorHandler.swift b/ios/FatalErrorHandler.swift similarity index 97% rename from ios/swift_bridging/FatalErrorHandler.swift rename to ios/FatalErrorHandler.swift index 524fa84..4cae51f 100755 --- a/ios/swift_bridging/FatalErrorHandler.swift +++ b/ios/FatalErrorHandler.swift @@ -29,7 +29,7 @@ import WebimClientLibrary // MARK: - FatalErrorHandler @objc(FatalErrorHandler) -protocol _ObjCFatalErrorHandler { +public protocol _ObjCFatalErrorHandler { @objc(onError:) func on(error: _ObjCWebimError) diff --git a/ios/swift_bridging/Message.swift b/ios/Message.swift similarity index 77% rename from ios/swift_bridging/Message.swift rename to ios/Message.swift index 71b3d5a..8b1884e 100755 --- a/ios/swift_bridging/Message.swift +++ b/ios/Message.swift @@ -31,21 +31,21 @@ import WebimClientLibrary // MARK: - Message @objc(Message) -final class _ObjCMessage: NSObject { +public final class _ObjCMessage: NSObject { // MARK: - Properties private (set) var message: Message // MARK: - Initialization - init(message: Message) { + public init(message: Message) { self.message = message } // MARK: - Methods @objc(getAttachment) - func getAttachment() -> _ObjCMessageAttachment? { + public func getAttachment() -> _ObjCMessageAttachment? { if let attachment = message.getAttachment() { return _ObjCMessageAttachment(messageAttachment: attachment) } @@ -54,7 +54,7 @@ final class _ObjCMessage: NSObject { } @objc(getData) - func getData() -> [String: Any]? { + public func getData() -> [String: Any]? { if let data = message.getData() { var objCData = [String: Any]() for key in data.keys { @@ -70,27 +70,27 @@ final class _ObjCMessage: NSObject { } @objc(getID) - func getID() -> String { + public func getID() -> String { return message.getID() } @objc(getOperatorID) - func getOperatorID() -> String? { + public func getOperatorID() -> String? { return message.getOperatorID() } @objc(getSenderAvatarFullURL) - func getSenderAvatarFullURL() -> URL? { + public func getSenderAvatarFullURL() -> URL? { return message.getSenderAvatarFullURL() } @objc(getSenderName) - func getSenderName() -> String { + public func getSenderName() -> String { return message.getSenderName() } @objc(getSendStatus) - func getSendStatus() -> _ObjCMessageSendStatus { + public func getSendStatus() -> _ObjCMessageSendStatus { switch message.getSendStatus() { case .SENDING: return .SENDING @@ -100,17 +100,17 @@ final class _ObjCMessage: NSObject { } @objc(getText) - func getText() -> String { + public func getText() -> String { return message.getText() } @objc(getTime) - func getTime() -> Date { + public func getTime() -> Date { return message.getTime() } @objc(getType) - func getType() -> _ObjCMessageType { + public func getType() -> _ObjCMessageType { switch message.getType() { case .ACTION_REQUEST: return .ACTION_REQUEST @@ -128,21 +128,25 @@ final class _ObjCMessage: NSObject { return .OPERATOR_BUSY case .VISITOR: return .VISITOR + case .KEYBOARD: + return .KEYBOARD + case .KEYBOARD_RESPONSE: + return .KEYBOARD_RESPONSE } } @objc(isEqualTo:) - func isEqual(to message: _ObjCMessage) -> Bool { + public func isEqual(to message: _ObjCMessage) -> Bool { return self.message.isEqual(to: message.message) } @objc(isReadByOperator) - func isReadByOperator() -> Bool { + public func isReadByOperator() -> Bool { return message.isReadByOperator() } @objc(canBeEdited) - func canBeEdited() -> Bool { + public func canBeEdited() -> Bool { return message.canBeEdited() } @@ -150,14 +154,14 @@ final class _ObjCMessage: NSObject { // MARK: - MessageAttachment @objc(MessageAttachment) -final class _ObjCMessageAttachment: NSObject { +public final class _ObjCMessageAttachment: NSObject { // MARK: - Properties private let messageAttachment: MessageAttachment // MARK: - Initialization - init(messageAttachment: MessageAttachment) { + public init(messageAttachment: MessageAttachment) { self.messageAttachment = messageAttachment } @@ -165,17 +169,17 @@ final class _ObjCMessageAttachment: NSObject { // MARK: - Methods @objc(getContentType) - func getContentType() -> String { + public func getContentType() -> String { return messageAttachment.getContentType() } @objc(getFileName) - func getFileName() -> String { + public func getFileName() -> String { return messageAttachment.getFileName() } @objc(getImageInfo) - func getImageInfo() -> _ObjCImageInfo? { + public func getImageInfo() -> _ObjCImageInfo? { if let imageInfo = messageAttachment.getImageInfo() { return _ObjCImageInfo(imageInfo: imageInfo) } @@ -184,12 +188,12 @@ final class _ObjCMessageAttachment: NSObject { } @objc(getSize) - func getSize() -> NSNumber? { + public func getSize() -> NSNumber? { return messageAttachment.getSize() as NSNumber? } @objc(getURL) - func getURL() -> URL { + public func getURL() -> URL { return messageAttachment.getURL() } @@ -197,14 +201,14 @@ final class _ObjCMessageAttachment: NSObject { // MARK: - ImageInfo @objc(ImageInfo) -final class _ObjCImageInfo: NSObject { +public final class _ObjCImageInfo: NSObject { // MARK: - Properties private let imageInfo: ImageInfo // MARK: - Initialization - init(imageInfo: ImageInfo) { + public init(imageInfo: ImageInfo) { self.imageInfo = imageInfo } @@ -212,17 +216,17 @@ final class _ObjCImageInfo: NSObject { // MARK: - Methods @objc(getThumbURLString) - func getThumbURLString() -> URL { + public func getThumbURLString() -> URL { return imageInfo.getThumbURL() } @objc(getHeight) - func getHeight() -> NSNumber? { + public func getHeight() -> NSNumber? { return imageInfo.getHeight() as NSNumber? } @objc(getWidth) - func getWidth() -> NSNumber? { + public func getWidth() -> NSNumber? { return imageInfo.getWidth() as NSNumber? } @@ -231,7 +235,7 @@ final class _ObjCImageInfo: NSObject { // MARK: - MessageType @objc(MessageType) -enum _ObjCMessageType: Int { +public enum _ObjCMessageType: Int { case ACTION_REQUEST case CONTACTS_REQUEST case FILE_FROM_OPERATOR @@ -240,11 +244,13 @@ enum _ObjCMessageType: Int { case OPERATOR case OPERATOR_BUSY case VISITOR + case KEYBOARD + case KEYBOARD_RESPONSE } // MARK: - MessageSendStatus @objc(MessageSendStatus) -enum _ObjCMessageSendStatus: Int { +public enum _ObjCMessageSendStatus: Int { case SENDING case SENT } diff --git a/ios/swift_bridging/MessageListener.swift b/ios/MessageListener.swift similarity index 90% rename from ios/swift_bridging/MessageListener.swift rename to ios/MessageListener.swift index 30a087b..ed4b486 100755 --- a/ios/swift_bridging/MessageListener.swift +++ b/ios/MessageListener.swift @@ -31,7 +31,7 @@ import WebimClientLibrary // MARK: - MessageListener @objc(MessageListener) -protocol _ObjCMessageListener { +public protocol _ObjCMessageListener { @objc(addedMessage:after:) func added(message newMessage: _ObjCMessage, @@ -52,7 +52,7 @@ protocol _ObjCMessageListener { // MARK: - Protocols' wrappers // MARK: - MessageListener -final class MessageListenerWrapper: MessageListener { +public final class MessageListenerWrapper: MessageListener { // MARK: - Properties private weak var messageListener: _ObjCMessageListener? @@ -67,21 +67,21 @@ final class MessageListenerWrapper: MessageListener { // MARK: - Methods // MARK: MessageListener methods - func added(message newMessage: Message, + public func added(message newMessage: Message, after previousMessage: Message?) { messageListener?.added(message: _ObjCMessage(message: newMessage), after: ((previousMessage == nil) ? nil : _ObjCMessage(message: previousMessage!))) } - func removed(message: Message) { + public func removed(message: Message) { messageListener?.removed(message: _ObjCMessage(message: message)) } - func removedAllMessages() { + public func removedAllMessages() { messageListener?.removedAllMessages() } - func changed(message oldVersion: Message, + public func changed(message oldVersion: Message, to newVersion: Message) { messageListener?.changed(message: _ObjCMessage(message: oldVersion), to: _ObjCMessage(message: newVersion)) diff --git a/ios/swift_bridging/MessageStream.swift b/ios/MessageStream.swift similarity index 90% rename from ios/swift_bridging/MessageStream.swift rename to ios/MessageStream.swift index 061f1e0..4380790 100755 --- a/ios/swift_bridging/MessageStream.swift +++ b/ios/MessageStream.swift @@ -31,7 +31,7 @@ import WebimClientLibrary // MARK: - MessageStream @objc(MessageStream) -final class _ObjCMessageStream: NSObject { +public final class _ObjCMessageStream: NSObject { // MARK: - Properties private let messageStream: MessageStream @@ -61,7 +61,7 @@ final class _ObjCMessageStream: NSObject { // MARK: - Methods @objc(getVisitSessionState) - func getVisitSessionState() -> _ObjCVisitSessionState { + public func getVisitSessionState() -> _ObjCVisitSessionState { switch messageStream.getVisitSessionState() { case .CHAT: return .CHAT @@ -79,7 +79,7 @@ final class _ObjCMessageStream: NSObject { } @objc(getChatState) - func getChatState() -> _ObjCChatState { + public func getChatState() -> _ObjCChatState { switch messageStream.getChatState() { case .CHATTING: return .CHATTING @@ -101,17 +101,17 @@ final class _ObjCMessageStream: NSObject { } @objc(getUnreadByOperatorTimestamp) - func getUnreadByOperatorTimestamp() -> Date? { + public func getUnreadByOperatorTimestamp() -> Date? { return messageStream.getUnreadByOperatorTimestamp() } @objc(getUnreadByVisitorTimestamp) - func getUnreadByVisitorTimestamp() -> Date? { + public func getUnreadByVisitorTimestamp() -> Date? { return messageStream.getUnreadByVisitorTimestamp() } @objc(getDepartmentList) - func getDepartmentList() -> [_ObjCDepartment]? { + public func getDepartmentList() -> [_ObjCDepartment]? { if let departmentList = messageStream.getDepartmentList() { var objCDepartmentList = [_ObjCDepartment]() for department in departmentList { @@ -126,12 +126,12 @@ final class _ObjCMessageStream: NSObject { } @objc(getLocationSettings) - func getLocationSettings() -> _ObjCLocationSettings { + public func getLocationSettings() -> _ObjCLocationSettings { return _ObjCLocationSettings(locationSettings: messageStream.getLocationSettings()) } @objc(getCurrentOperator) - func getCurrentOperator() -> _ObjCOperator? { + public func getCurrentOperator() -> _ObjCOperator? { if let `operator` = messageStream.getCurrentOperator() { return _ObjCOperator(operator: `operator`) } @@ -140,12 +140,12 @@ final class _ObjCMessageStream: NSObject { } @objc(getLastRatingOfOperatorWithID:) - func getLastRatingOfOperatorWith(id: String) -> Int { + public func getLastRatingOfOperatorWith(id: String) -> Int { return messageStream.getLastRatingOfOperatorWith(id: id) } @objc(rateOperatorWithID:byRating:completionHandler:error:) - func rateOperatorWith(id: String?, + public func rateOperatorWith(id: String?, byRating rating: Int, completionHandler: _ObjCRateOperatorCompletionHandler) throws { try messageStream.rateOperatorWith(id: id, @@ -154,55 +154,55 @@ final class _ObjCMessageStream: NSObject { } @objc(respondSentryCall:error:) - func respondSentryCall(id: String) throws { + public func respondSentryCall(id: String) throws { try respondSentryCall(id: id) } @objc(startChat:) - func startChat() throws { + public func startChat() throws { try messageStream.startChat() } @objc(startChatWithDepartmentKey:error:) - func startChat(departmentKey: String?) throws { + public func startChat(departmentKey: String?) throws { try messageStream.startChat(departmentKey: departmentKey) } @objc(startChatWithCustomFields:error:) - func startChat(customFields: String?) throws { + public func startChat(customFields: String?) throws { try messageStream.startChat(customFields: customFields) } @objc(startChatWithFirstQuestion:error:) - func startChat(firstQuestion: String?) throws { + public func startChat(firstQuestion: String?) throws { try messageStream.startChat(firstQuestion: firstQuestion) } @objc(startChatWithDepartmentKey:firstQuestion:error:) - func startChat(departmentKey: String?, + public func startChat(departmentKey: String?, firstQuestion: String?) throws { try messageStream.startChat(departmentKey: departmentKey, firstQuestion: firstQuestion) } @objc(startChatWithFirstQuestion:customFields:error:) - func startChat(firstQuestion: String?, + public func startChat(firstQuestion: String?, customFields: String?) throws { try messageStream.startChat(firstQuestion: firstQuestion, customFields: customFields) } @objc(startChatWithDepartmentKey:customFields:error:) - func startChat(departmentKey: String?, + public func startChat(departmentKey: String?, customFields: String?) throws { try messageStream.startChat(departmentKey: departmentKey, customFields: customFields) } @objc(startChatWithDepartmentKey:firstQuestion:customFields:error:) - func startChat(departmentKey: String?, + public func startChat(departmentKey: String?, firstQuestion: String?, customFields: String?) throws { try messageStream.startChat(departmentKey: departmentKey, @@ -211,27 +211,27 @@ final class _ObjCMessageStream: NSObject { } @objc(closeChat:) - func closeChat() throws { + public func closeChat() throws { try messageStream.closeChat() } @objc(setVisitorTypingDraftMessage:error:) - func setVisitorTyping(draftMessage: String?) throws { + public func setVisitorTyping(draftMessage: String?) throws { try messageStream.setVisitorTyping(draftMessage: draftMessage) } @objc(setPrechatFields:error:) - func set(prechatFields: String) throws { + public func set(prechatFields: String) throws { try messageStream.set(prechatFields: prechatFields) } @objc(sendMessage:error:) - func send(message: String) throws -> String { + public func send(message: String) throws -> String { return try messageStream.send(message: message) } @objc(sendMessage:data:completionHandler:error:) - func send(message: String, + public func send(message: String, data: [String: Any]?, completionHandler: _ObjCDataMessageCompletionHandler?) throws -> String { return try messageStream.send(message: message, @@ -240,14 +240,14 @@ final class _ObjCMessageStream: NSObject { } @objc(sendMessage:isHintQuestion:error:) - func send(message: String, + public func send(message: String, isHintQuestion: Bool) throws -> String { return try messageStream.send(message: message, isHintQuestion: isHintQuestion) } @objc(sendFile:filename:mimeType:completionHandler:error:) - func send(file: Data, + public func send(file: Data, filename: String, mimeType: String, completionHandler: _ObjCSendFileCompletionHandler?) throws -> String { @@ -258,7 +258,7 @@ final class _ObjCMessageStream: NSObject { } @objc(editMessage:text:completionHandler:error:) - func edit(message: _ObjCMessage, + public func edit(message: _ObjCMessage, text: String, completionHandler: _ObjCEditMessageCompletionHandler?) throws -> NSNumber { let canBeEdited = try messageStream.edit(message: message.message, @@ -272,7 +272,7 @@ final class _ObjCMessageStream: NSObject { } @objc(deleteMessage:completionHandler:error:) - func delete(message: _ObjCMessage, + public func delete(message: _ObjCMessage, completionHandler: _ObjCDeleteMessageCompletionHandler?) throws -> NSNumber { let canBeEdited = try messageStream.delete(message: message.message, completionHandler: ((completionHandler == nil) ? nil : DeleteMessageCompletionHandlerWrapper(deleteMessageCompletionHandler: completionHandler!))) @@ -284,82 +284,82 @@ final class _ObjCMessageStream: NSObject { } @objc(setChatRead:) - func setChatRead() throws { + public func setChatRead() throws { try messageStream.setChatRead() } @objc(newMessageTrackerWithMessageListener:error:) - func newMessageTracker(messageListener: _ObjCMessageListener) throws -> _ObjCMessageTracker { + public func newMessageTracker(messageListener: _ObjCMessageListener) throws -> _ObjCMessageTracker { let wrapper = MessageListenerWrapper(messageListener: messageListener) messageListenerWrapper = wrapper return try _ObjCMessageTracker(messageTracker: messageStream.newMessageTracker(messageListener: wrapper)) } @objc(setVisitSessionStateListener:) - func set(visitSessionStateListener: _ObjCVisitSessionStateListener) { + public func set(visitSessionStateListener: _ObjCVisitSessionStateListener) { let wrapper = VisitSessionStateListenerWrapper(visitSessionStateListener: visitSessionStateListener) visitSessionStateListenerWrapper = wrapper messageStream.set(visitSessionStateListener: wrapper) } @objc(setChatStateListener:) - func set(chatStateListener: _ObjCChatStateListener) { + public func set(chatStateListener: _ObjCChatStateListener) { let wrapper = ChatStateListenerWrapper(chatStateListener: chatStateListener) chatStateListenerWrapper = wrapper messageStream.set(chatStateListener: wrapper) } @objc(setCurrentOperatorChangeListener:) - func set(currentOperatorChangeListener: _ObjCCurrentOperatorChangeListener) { + public func set(currentOperatorChangeListener: _ObjCCurrentOperatorChangeListener) { let wrapper = CurrentOperatorChangeListenerWrapper(currentOperatorChangeListener: currentOperatorChangeListener) currentOperatorChangeListenerWrapper = wrapper messageStream.set(currentOperatorChangeListener: wrapper) } @objc(setDepartmentListChangeListener:) - func set(departmentListChangeListener: _ObjCDepartmentListChangeListener) { + public func set(departmentListChangeListener: _ObjCDepartmentListChangeListener) { let wrapper = DepartmentListChangeListenerWrapper(departmentListChangeListener: departmentListChangeListener) departmentListChangeListenerWrapper = wrapper messageStream.set(departmentListChangeListener: wrapper) } @objc(LocationSettingsChangeListener:) - func set(locationSettingsChangeListener: _ObjCLocationSettingsChangeListener) { + public func set(locationSettingsChangeListener: _ObjCLocationSettingsChangeListener) { let wrapper = LocationSettingsChangeListenerWrapper(locationSettingsChangeListener: locationSettingsChangeListener) locationSettingsChangeListenerWrapper = wrapper messageStream.set(locationSettingsChangeListener: wrapper) } @objc(setOperatorTypingListener:) - func set(operatorTypingListener: _ObjCOperatorTypingListener) { + public func set(operatorTypingListener: _ObjCOperatorTypingListener) { let wrapper = OperatorTypingListenerWrapper(operatorTypingListener: operatorTypingListener) operatorTypingListenerWrapper = wrapper messageStream.set(operatorTypingListener: wrapper) } @objc(setOnlineStatusChangeListener:) - func set(onlineStatusChangeListener: _ObjCOnlineStatusChangeListener) { + public func set(onlineStatusChangeListener: _ObjCOnlineStatusChangeListener) { let wrapper = OnlineStatusChangeListenerWrapper(onlineStatusChangeListener: onlineStatusChangeListener) onlineStatusChangeListenerWrapper = wrapper messageStream.set(onlineStatusChangeListener: wrapper) } @objc(setUnreadByOperatorTimestampChangeListener:) - func set(unreadByOperatorTimestampChangeListener: _ObjCUnreadByOperatorTimestampChangeListener) { + public func set(unreadByOperatorTimestampChangeListener: _ObjCUnreadByOperatorTimestampChangeListener) { let wrapper = UnreadByOperatorTimestampChangeListenerWrapper(unreadByOperatorTimestampChangeListener: unreadByOperatorTimestampChangeListener) unreadByOperatorTimestampChangeListenerWrapper = wrapper messageStream.set(unreadByOperatorTimestampChangeListener: wrapper) } @objc(setUnreadByVisitorTimestampChangeListener:) - func set(unreadByVisitorTimestampChangeListener: _ObjCUnreadByVisitorTimestampChangeListener) { + public func set(unreadByVisitorTimestampChangeListener: _ObjCUnreadByVisitorTimestampChangeListener) { let wrapper = UnreadByVisitorTimestampChangeListenerWrapper(unreadByVisitorTimestampChangeListener: unreadByVisitorTimestampChangeListener) unreadByVisitorTimestampChangeListenerWrapper = wrapper messageStream.set(unreadByVisitorTimestampChangeListener: wrapper) } @objc(setUnreadByVisitorMessageCountChangeListener:) - func set(unreadByVisitorMessageCountChangeListener: _ObjCUnreadByVisitorMessageCountChangeListener) { + public func set(unreadByVisitorMessageCountChangeListener: _ObjCUnreadByVisitorMessageCountChangeListener) { let wrapper = UnreadByVisitorMessageCountChangeListenerWrapper(unreadByVisitorMessageCountChangeListener: unreadByVisitorMessageCountChangeListener) unreadByVisitorMessageCountChangeListenerWrapper = wrapper messageStream.set(unreadByVisitorMessageCountChangeListener: wrapper) @@ -369,7 +369,7 @@ final class _ObjCMessageStream: NSObject { // MARK: - LocationSettings @objc(LocationSettings) -final class _ObjCLocationSettings: NSObject { +public final class _ObjCLocationSettings: NSObject { // MARK: - Properties private let locationSettings: LocationSettings @@ -390,7 +390,7 @@ final class _ObjCLocationSettings: NSObject { // MARK: - DataMessageCompletionHandler @objc(DataMessageCompletionHandler) -protocol _ObjCDataMessageCompletionHandler { +public protocol _ObjCDataMessageCompletionHandler { @objc(onSuccessWithMessageID:) func onSuccess(messageID: String) @@ -403,7 +403,7 @@ protocol _ObjCDataMessageCompletionHandler { // MARK: - EditMessageCompletionHandler @objc(EditMessageCompletionHandler) -protocol _ObjCEditMessageCompletionHandler { +public protocol _ObjCEditMessageCompletionHandler { @objc(onSuccessWithMessageID:) func onSuccess(messageID: String) @@ -416,7 +416,7 @@ protocol _ObjCEditMessageCompletionHandler { // MARK: - DeleteMessageCompletionHandler @objc(DeleteMessageCompletionHandler) -protocol _ObjCDeleteMessageCompletionHandler { +public protocol _ObjCDeleteMessageCompletionHandler { @objc(onSuccessWithMessageID:) func onSuccess(messageID: String) @@ -429,7 +429,7 @@ protocol _ObjCDeleteMessageCompletionHandler { // MARK: - SendFileCompletionHandler @objc(SendFileCompletionHandler) -protocol _ObjCSendFileCompletionHandler { +public protocol _ObjCSendFileCompletionHandler { @objc(onSuccessWithMessageID:) func onSuccess(messageID: String) @@ -442,7 +442,7 @@ protocol _ObjCSendFileCompletionHandler { // MARK: - RateOperatorCompletionHandler @objc(RateOperatorCompletionHandler) -protocol _ObjCRateOperatorCompletionHandler { +public protocol _ObjCRateOperatorCompletionHandler { @objc(onSuccess) func onSuccess() @@ -454,7 +454,7 @@ protocol _ObjCRateOperatorCompletionHandler { // MARK: - VisitSessionStateListener @objc(VisitSessionStateListener) -protocol _ObjCVisitSessionStateListener { +public protocol _ObjCVisitSessionStateListener { @objc(changedState:to:) func changed(state previousState: _ObjCVisitSessionState, @@ -464,7 +464,7 @@ protocol _ObjCVisitSessionStateListener { // MARK: - ChatStateListener @objc(ChatStateListener) -protocol _ObjCChatStateListener { +public protocol _ObjCChatStateListener { @objc(changedState:to:) func changed(state previousState: _ObjCChatState, @@ -474,7 +474,7 @@ protocol _ObjCChatStateListener { // MARK: - CurrentOperatorChangeListener @objc(CurrentOperatorChangeListener) -protocol _ObjCCurrentOperatorChangeListener { +public protocol _ObjCCurrentOperatorChangeListener { @objc(changedOperator:to:) func changed(operator previousOperator: _ObjCOperator?, @@ -484,7 +484,7 @@ protocol _ObjCCurrentOperatorChangeListener { // MARK: - DepartmentListChangeListener @objc(DepartmentListChangeListener) -protocol _ObjCDepartmentListChangeListener { +public protocol _ObjCDepartmentListChangeListener { @objc(receivedDepartmentList:) func received(departmentList: [_ObjCDepartment]) @@ -493,7 +493,7 @@ protocol _ObjCDepartmentListChangeListener { // MARK: - LocationSettingsChangeListener @objc(LocationSettingsChangeListener) -protocol _ObjCLocationSettingsChangeListener { +public protocol _ObjCLocationSettingsChangeListener { @objc(changedLocationSettings:to:) func changed(locationSettings previousLocationSettings: _ObjCLocationSettings, @@ -503,7 +503,7 @@ protocol _ObjCLocationSettingsChangeListener { // MARK: - OperatorTypingListener @objc(OperatorTypingListener) -protocol _ObjCOperatorTypingListener { +public protocol _ObjCOperatorTypingListener { @objc(onOperatorTypingStateChangedTo:) func onOperatorTypingStateChanged(isTyping: Bool) @@ -512,7 +512,7 @@ protocol _ObjCOperatorTypingListener { // MARK: - OnlineStatusChangeListener @objc(SessionOnlineStatusChangeListener) -protocol _ObjCOnlineStatusChangeListener { +public protocol _ObjCOnlineStatusChangeListener { @objc(changedOnlineStatus:to:) func changed(onlineStatus previousOnlineStatus: _ObjCOnlineStatus, @@ -522,7 +522,7 @@ protocol _ObjCOnlineStatusChangeListener { // MARK: - UnreadByOperatorTimestampChangeListener @objc(UnreadByOperatorTimestampChangeListener) -protocol _ObjCUnreadByOperatorTimestampChangeListener { +public protocol _ObjCUnreadByOperatorTimestampChangeListener { @objc(changedUnreadByOperatorTimestampTo:) func changedUnreadByOperatorTimestampTo(newValue: Date?) @@ -531,7 +531,7 @@ protocol _ObjCUnreadByOperatorTimestampChangeListener { // MARK: - UnreadByVisitorTimestampChangeListener @objc(UnreadByVisitorTimestampChangeListener) -protocol _ObjCUnreadByVisitorTimestampChangeListener { +public protocol _ObjCUnreadByVisitorTimestampChangeListener { @objc(changedUnreadByVisitorTimestampTo:) func changedUnreadByVisitorTimestampTo(newValue: Date?) @@ -540,7 +540,7 @@ protocol _ObjCUnreadByVisitorTimestampChangeListener { // MARK: - UnreadByVisitorMessageCountChangeListener @objc(UnreadByVisitorMessageCountChangeListener) -protocol _ObjCUnreadByVisitorMessageCountChangeListener { +public protocol _ObjCUnreadByVisitorMessageCountChangeListener { @objc(changedUnreadByVisitorMessageCountTo:) func changedUnreadByVisitorMessageCountTo(newValue: Int) @@ -549,7 +549,7 @@ protocol _ObjCUnreadByVisitorMessageCountChangeListener { // MARK: - ChatState @objc(ChatState) -enum _ObjCChatState: Int { +public enum _ObjCChatState: Int { case CHATTING case CHATTING_WITH_ROBOT case CLOSED_BY_OPERATOR @@ -562,7 +562,7 @@ enum _ObjCChatState: Int { // MARK: - OnlineStatus @objc(OnlineStatus) -enum _ObjCOnlineStatus: Int { +public enum _ObjCOnlineStatus: Int { case BUSY_OFFLINE case BUSY_ONLINE case OFFLINE @@ -572,7 +572,7 @@ enum _ObjCOnlineStatus: Int { // MARK: - VisitSessionState @objc(VisitSessionState) -enum _ObjCVisitSessionState: Int { +public enum _ObjCVisitSessionState: Int { case CHAT case DEPARTMENT_SELECTION case IDLE @@ -583,7 +583,7 @@ enum _ObjCVisitSessionState: Int { // MARK: - DataMessageError @objc(DataMessageError) -enum _ObjCDataMessageError: Int, Error { +public enum _ObjCDataMessageError: Int, Error { case QUOTED_MESSAGE_CANNOT_BE_REPLIED case QUOTED_MESSAGE_FROM_ANOTHER_VISITOR case QUOTED_MESSAGE_MULTIPLE_IDS @@ -594,7 +594,7 @@ enum _ObjCDataMessageError: Int, Error { // MARK: - EditMessageError @objc(EditMessageError) -enum _ObjCEditMessageError: Int, Error { +public enum _ObjCEditMessageError: Int, Error { case UNKNOWN case NOT_ALLOWED case MESSAGE_EMPTY @@ -605,7 +605,7 @@ enum _ObjCEditMessageError: Int, Error { // MARK: - DeleteMessageError @objc(DeleteMessageError) -enum _ObjCDeleteMessageError: Int, Error { +public enum _ObjCDeleteMessageError: Int, Error { case UNKNOWN case NOT_ALLOWED case MESSAGE_NOT_OWNED @@ -614,7 +614,7 @@ enum _ObjCDeleteMessageError: Int, Error { // MARK: - SendFileError @objc(SendFileError) -enum _ObjCSendFileError: Int, Error { +public enum _ObjCSendFileError: Int, Error { case FILE_SIZE_EXCEEDED case FILE_TYPE_NOT_ALLOWED case UPLOADED_FILE_NOT_FOUND @@ -623,7 +623,7 @@ enum _ObjCSendFileError: Int, Error { // MARK: - RateOperatorError @objc(RateOperatorError) -enum _ObjCRateOperatorError: Int, Error { +public enum _ObjCRateOperatorError: Int, Error { case NO_CHAT case WRONG_OPERATOR_ID } diff --git a/ios/swift_bridging/MessageTracker.swift b/ios/MessageTracker.swift similarity index 87% rename from ios/swift_bridging/MessageTracker.swift rename to ios/MessageTracker.swift index c563538..98a945b 100755 --- a/ios/swift_bridging/MessageTracker.swift +++ b/ios/MessageTracker.swift @@ -31,14 +31,14 @@ import WebimClientLibrary // MARK: - MessageTracker @objc(MessageTracker) -final class _ObjCMessageTracker: NSObject { +public final class _ObjCMessageTracker: NSObject { // MARK: - Properties private let messageTracker: MessageTracker // MARK: - Initialization - init(messageTracker: MessageTracker) { + public init(messageTracker: MessageTracker) { self.messageTracker = messageTracker } @@ -46,7 +46,7 @@ final class _ObjCMessageTracker: NSObject { // MARK: - Methods @objc(getLastMessagesByLimit:completion:error:) - func getLastMessages(byLimit limitOfMessages: Int, + public func getLastMessages(byLimit limitOfMessages: Int, completion: @escaping (_ result: [_ObjCMessage]) -> ()) throws { try messageTracker.getLastMessages(byLimit: limitOfMessages) { messages in var objCMessages = [_ObjCMessage]() @@ -58,7 +58,7 @@ final class _ObjCMessageTracker: NSObject { } @objc(getNextMessagesByLimit:completion:error:) - func getNextMessages(byLimit limitOfMessages: Int, + public func getNextMessages(byLimit limitOfMessages: Int, completion: @escaping ([_ObjCMessage]) -> ()) throws { try messageTracker.getNextMessages(byLimit: limitOfMessages) { messages in var objCMessages = [_ObjCMessage]() @@ -70,7 +70,7 @@ final class _ObjCMessageTracker: NSObject { } @objc(getAllMessagesWithCompletion:error:) - func getAllMessages(completion: @escaping (_ result: [_ObjCMessage]) -> ()) throws { + public func getAllMessages(completion: @escaping (_ result: [_ObjCMessage]) -> ()) throws { try messageTracker.getAllMessages() { messages in var objCMessages = [_ObjCMessage]() for message in messages { @@ -81,12 +81,12 @@ final class _ObjCMessageTracker: NSObject { } @objc(resetToMessage:error:) - func resetTo(message: _ObjCMessage) throws { + public func resetTo(message: _ObjCMessage) throws { try messageTracker.resetTo(message: message.message) } @objc(destroy:) - func destroy() throws { + public func destroy() throws { try messageTracker.destroy() } diff --git a/ios/swift_bridging/Operator.swift b/ios/Operator.swift similarity index 89% rename from ios/swift_bridging/Operator.swift rename to ios/Operator.swift index 2332428..7790a08 100755 --- a/ios/swift_bridging/Operator.swift +++ b/ios/Operator.swift @@ -31,14 +31,14 @@ import WebimClientLibrary // MARK: - Operator @objc(Operator) -final class _ObjCOperator: NSObject { +public final class _ObjCOperator: NSObject { // MARK: - Private private let `operator`: Operator // MARK: - Initialization - init(operator: Operator) { + public init(operator: Operator) { self.`operator` = `operator` } @@ -46,17 +46,17 @@ final class _ObjCOperator: NSObject { // MARK: - Methods @objc(getID) - func getID() -> String { + public func getID() -> String { return `operator`.getID() } @objc(getName) - func getName() -> String { + public func getName() -> String { return `operator`.getName() } @objc(getAvatarURL) - func getAvatarURL() -> URL? { + public func getAvatarURL() -> URL? { return `operator`.getAvatarURL() } diff --git a/ios/swift_bridging/ProvidedAuthorizationTokenStateListener.swift b/ios/ProvidedAuthorizationTokenStateListener.swift similarity index 85% rename from ios/swift_bridging/ProvidedAuthorizationTokenStateListener.swift rename to ios/ProvidedAuthorizationTokenStateListener.swift index 06f360c..bb7369a 100755 --- a/ios/swift_bridging/ProvidedAuthorizationTokenStateListener.swift +++ b/ios/ProvidedAuthorizationTokenStateListener.swift @@ -28,7 +28,7 @@ import Foundation import WebimClientLibrary @objc(ProvidedAuthorizationTokenStateListener) -protocol _ObjCProvidedAuthorizationTokenStateListener { +public protocol _ObjCProvidedAuthorizationTokenStateListener { @objc(updateProvidedAuthorizationToken:) func update(providedAuthorizationToken: String) @@ -37,19 +37,19 @@ protocol _ObjCProvidedAuthorizationTokenStateListener { // MARK: - Protocols' wrappers // MARK: - ProvidedAuthorizationTokenStateListener -final class ProvidedAuthorizationTokenStateListenerWrapper: ProvidedAuthorizationTokenStateListener { +public final class ProvidedAuthorizationTokenStateListenerWrapper: ProvidedAuthorizationTokenStateListener { // MARK: - Properties private let providedAuthorizationTokenStateListener: _ObjCProvidedAuthorizationTokenStateListener // MARK: - Initialization - init(providedAuthorizationTokenStateListener: _ObjCProvidedAuthorizationTokenStateListener) { + public init(providedAuthorizationTokenStateListener: _ObjCProvidedAuthorizationTokenStateListener) { self.providedAuthorizationTokenStateListener = providedAuthorizationTokenStateListener } // MARK: - Methods // MARK: ProvidedAuthorizationTokenStateListener protocol methods - func update(providedAuthorizationToken: String) { + public func update(providedAuthorizationToken: String) { providedAuthorizationTokenStateListener.update(providedAuthorizationToken: providedAuthorizationToken) } diff --git a/ios/RNWebim.h b/ios/RNWebim.h index 5d421cd..86a8431 100644 --- a/ios/RNWebim.h +++ b/ios/RNWebim.h @@ -1,13 +1,11 @@ +#ifndef RNWebim_h +#define RNWebim_h -#if __has_include("React/RCTBridgeModule.h") -#import "React/RCTBridgeModule.h" -#else #import -#endif #import -#import "RNWebim-Swift.h" - -@interface webim : RCTEventEmitter +@interface RNWebim : RCTEventEmitter @end + +#endif /* RNWebim_h */ diff --git a/ios/RNWebim.m b/ios/RNWebim.m index 4704d9c..3aa5c11 100644 --- a/ios/RNWebim.m +++ b/ios/RNWebim.m @@ -1,8 +1,9 @@ #import "RNWebim.h" #import +#import // If use see compile error at this line, to fix repeat compile second time -@implementation webim +@implementation RNWebim WebimSession *webimSession; MessageStream *stream; @@ -24,18 +25,51 @@ - (dispatch_queue_t)methodQueue { RCT_EXPORT_MODULE() - (NSArray *)supportedEvents { - return @[@"newMessage", @"removeMessage", @"changedMessage", @"allMessagesRemoved"]; + return @[@"newMessage", @"removeMessage", @"changedMessage", @"allMessagesRemoved", @"tokenUpdated", @"error"]; } -RCT_EXPORT_METHOD(resumeSession:(NSString*) accountName location:(NSString*) location account:(NSString*) account reject:(RCTResponseSenderBlock) reject resolve:(RCTResponseSenderBlock) resolve) { +RCT_EXPORT_METHOD(resumeSession:(NSDictionary*) builderData reject:(RCTResponseSenderBlock) reject resolve:(RCTResponseSenderBlock) resolve) { NSError *error = nil; if (webimSession == nil) { SessionBuilder *sessionBuilder = [Webim newSessionBuilder]; + NSString* accountName = [builderData valueForKey:@"accountName"]; + NSString* location = [builderData valueForKey:@"location"]; + + // optional + NSString* accountJSON = [builderData valueForKey:@"accountJSON"]; + NSString* providedAuthorizationToken = [builderData valueForKey: @"providedAuthorizationToken"]; + NSString* appVersion = [builderData valueForKey:@"appVersion"]; + NSNumber* clearVisitorData = [builderData valueForKey:@"clearVisitorData"]; + NSNumber* storeHistoryLocally = [builderData valueForKey:@"storeHistoryLocally"]; + NSString* title = [builderData valueForKey:@"title"]; + NSString* pushToken = [builderData valueForKey:@"pushToken"]; sessionBuilder = [sessionBuilder setAccountName:accountName]; sessionBuilder = [sessionBuilder setLocation:location]; - if (account != nil) { - sessionBuilder = [sessionBuilder setVisitorFieldsJSONString:account]; + sessionBuilder = [sessionBuilder setFatalErrorHandler:(id)self]; + + if (accountJSON != nil) { + sessionBuilder = [sessionBuilder setVisitorFieldsJSONString:accountJSON]; + } + if (providedAuthorizationToken != nil) { + sessionBuilder = [sessionBuilder setProvidedAuthorizationTokenStateListener:(id)self providedAuthorizationToken:providedAuthorizationToken]; + } + if (appVersion != nil) { + sessionBuilder = [sessionBuilder setAppVersion:appVersion]; + } + if (clearVisitorData != nil) { + sessionBuilder = [sessionBuilder setIsVisitorDataClearingEnabled:[clearVisitorData boolValue]]; + } + if (storeHistoryLocally != nil) { + sessionBuilder = [sessionBuilder setIsLocalHistoryStoragingEnabled:[storeHistoryLocally boolValue]]; } + if (title != nil) { + sessionBuilder = [sessionBuilder setPageTitle:title]; + } + if (pushToken != nil) { + sessionBuilder = [sessionBuilder setDeviceToken:pushToken]; + } + sessionBuilder = [sessionBuilder setIsVisitorDataClearingEnabled:true]; + sessionBuilder = [sessionBuilder setIsLocalHistoryStoragingEnabled:false]; webimSession = [sessionBuilder build:&error]; if (error) { reject(@[@{ @"message": [error localizedDescription]}]); @@ -53,7 +87,7 @@ - (dispatch_queue_t)methodQueue { reject(@[@{ @"message": [error localizedDescription]}]); return; } - tracker = [stream newMessageTrackerWithMessageListener:self error:&error]; + tracker = [stream newMessageTrackerWithMessageListener:(id)self error:&error]; if (error) { reject(@[@{ @"message": [error localizedDescription]}]); return; @@ -66,7 +100,7 @@ - (dispatch_queue_t)methodQueue { resolve(@[@{}]); } -RCT_EXPORT_METHOD(destroySession:(RCTResponseSenderBlock) reject resolve:(RCTResponseSenderBlock) resolve) { +RCT_EXPORT_METHOD(destroySession:(NSNumber*) clearUserData reject:(RCTResponseSenderBlock) reject resolve:(RCTResponseSenderBlock) resolve) { NSError *err = nil; if (stream) { [stream closeChat:&err]; @@ -77,7 +111,19 @@ - (dispatch_queue_t)methodQueue { } stream = nil; if (webimSession) { - [webimSession pause:&err]; + if ([clearUserData boolValue]) { + [webimSession destroyWithClearVisitorData:&err]; + } else { + [webimSession destroy:&err]; + } + } + if (err) { + reject(@[@{ @"message": [err localizedDescription]}]); + return; + } + webimSession = nil; + if (tracker) { + [webimSession destroy:&err]; } if (err) { reject(@[@{ @"message": [err localizedDescription]}]); @@ -90,7 +136,7 @@ - (dispatch_queue_t)methodQueue { NSError *err = nil; [tracker getLastMessagesByLimit:[limit intValue] completion:^(NSArray * _Nonnull arr) { - resolve(@[@{@"messages": [self messagesToJsonArray:arr] }]); + resolve(@[@{@"messages": [self messagesToJsonArray:arr] }]); } error:&err]; if (err) { reject(@[@{@"message": [err localizedDescription]}]); @@ -125,7 +171,7 @@ - (dispatch_queue_t)methodQueue { NSError *err = nil; Operator* operator = [stream getCurrentOperator]; [stream rateOperatorWithID: [operator getID] byRating:[rating intValue] - completionHandler:self error:&err]; + completionHandler:(id)self error:&err]; if (err) { reject(@[@{ @"message": [err localizedDescription] }]); } else { @@ -168,7 +214,7 @@ - (dispatch_queue_t)methodQueue { NSString *_id = [stream sendFile:imageData filename:name mimeType:mime - completionHandler:self + completionHandler:(id) self error:&err]; if (err) { reject(@[@{ @"message": err.localizedDescription }]); @@ -364,4 +410,12 @@ -(void)clearRateResolvers { rateOperatorResolve = nil; } +- (void)updateProvidedAuthorizationToken:(NSString * _Nonnull)providedAuthorizationToken { + [self sendEventWithName:@"tokenUpdated" body:@{@"token": providedAuthorizationToken}]; +} + +- (void)onError:(WebimError * _Nonnull)error { + [self sendEventWithName:@"error" body:@{@"message": @"err"}]; +} + @end diff --git a/ios/RNWebim.xcodeproj/project.pbxproj b/ios/RNWebim.xcodeproj/project.pbxproj index 0dcd142..2386aee 100644 --- a/ios/RNWebim.xcodeproj/project.pbxproj +++ b/ios/RNWebim.xcodeproj/project.pbxproj @@ -8,82 +8,23 @@ /* Begin PBXBuildFile section */ B3E7B58A1CC2AC0600A0062D /* RNWebim.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNWebim.m */; }; - D65659C522A156A200B76477 /* Department.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659B822A156A000B76477 /* Department.swift */; }; - D65659C622A156A200B76477 /* WebimLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659B922A156A000B76477 /* WebimLogger.swift */; }; - D65659C722A156A200B76477 /* WebimError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659BA22A156A000B76477 /* WebimError.swift */; }; - D65659C822A156A200B76477 /* Operator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659BB22A156A100B76477 /* Operator.swift */; }; - D65659C922A156A200B76477 /* Webim.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659BC22A156A100B76477 /* Webim.swift */; }; - D65659CA22A156A200B76477 /* WebimSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659BD22A156A100B76477 /* WebimSession.swift */; }; - D65659CB22A156A200B76477 /* MessageTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659BE22A156A100B76477 /* MessageTracker.swift */; }; - D65659CC22A156A200B76477 /* WebimRemoteNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659BF22A156A100B76477 /* WebimRemoteNotification.swift */; }; - D65659CD22A156A200B76477 /* FatalErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659C022A156A100B76477 /* FatalErrorHandler.swift */; }; - D65659CE22A156A200B76477 /* MessageListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659C122A156A100B76477 /* MessageListener.swift */; }; - D65659CF22A156A200B76477 /* ProvidedAuthorizationTokenStateListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659C222A156A100B76477 /* ProvidedAuthorizationTokenStateListener.swift */; }; - D65659D022A156A200B76477 /* MessageStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659C322A156A200B76477 /* MessageStream.swift */; }; - D65659D122A156A200B76477 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65659C422A156A200B76477 /* Message.swift */; }; - D6565A0C22A16A2800B76477 /* WebimClientLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6565A0B22A16A1100B76477 /* WebimClientLibrary.framework */; }; - D6A45F8922A1393300B5BB27 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6A45F3622A137AF00B5BB27 /* SQLite.framework */; }; + D69EFDD624C836CC00728191 /* ProvidedAuthorizationTokenStateListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDC924C836CC00728191 /* ProvidedAuthorizationTokenStateListener.swift */; }; + D69EFDD724C836CC00728191 /* Operator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDCA24C836CC00728191 /* Operator.swift */; }; + D69EFDD824C836CC00728191 /* Department.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDCB24C836CC00728191 /* Department.swift */; }; + D69EFDD924C836CC00728191 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDCC24C836CC00728191 /* Message.swift */; }; + D69EFDDA24C836CC00728191 /* WebimSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDCD24C836CC00728191 /* WebimSession.swift */; }; + D69EFDDB24C836CC00728191 /* WebimError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDCE24C836CC00728191 /* WebimError.swift */; }; + D69EFDDC24C836CC00728191 /* MessageTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDCF24C836CC00728191 /* MessageTracker.swift */; }; + D69EFDDD24C836CC00728191 /* WebimLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDD024C836CC00728191 /* WebimLogger.swift */; }; + D69EFDDE24C836CC00728191 /* WebimRemoteNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDD124C836CC00728191 /* WebimRemoteNotification.swift */; }; + D69EFDDF24C836CC00728191 /* FatalErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDD224C836CC00728191 /* FatalErrorHandler.swift */; }; + D69EFDE024C836CC00728191 /* MessageListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDD324C836CC00728191 /* MessageListener.swift */; }; + D69EFDE124C836CC00728191 /* Webim.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDD424C836CC00728191 /* Webim.swift */; }; + D69EFDE224C836CC00728191 /* MessageStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69EFDD524C836CC00728191 /* MessageStream.swift */; }; + D69EFDE424C841AB00728191 /* RNWebim.h in Headers */ = {isa = PBXBuildFile; fileRef = B3E7B5881CC2AC0600A0062D /* RNWebim.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D69EFDE524C841B000728191 /* RNWebim-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = D69EFDC824C836CB00728191 /* RNWebim-Bridging-Header.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - D6565A0A22A16A1100B76477 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D6565A0622A16A1100B76477 /* WebimClientLibrary.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 8FD2427A200CDB18007EB9CB; - remoteInfo = WebimClientLibrary; - }; - D6A45F3522A137AF00B5BB27 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EE247AD31C3F04ED00AE3E12; - remoteInfo = "SQLite iOS"; - }; - D6A45F3722A137AF00B5BB27 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EE247ADD1C3F04ED00AE3E12; - remoteInfo = "SQLiteTests iOS"; - }; - D6A45F3922A137AF00B5BB27 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EE247B3C1C3F3ED000AE3E12; - remoteInfo = "SQLite Mac"; - }; - D6A45F3B22A137AF00B5BB27 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EE247B451C3F3ED000AE3E12; - remoteInfo = "SQLiteTests Mac"; - }; - D6A45F3D22A137AF00B5BB27 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 03A65E5A1C6BB0F50062603F; - remoteInfo = "SQLite tvOS"; - }; - D6A45F3F22A137AF00B5BB27 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 03A65E631C6BB0F60062603F; - remoteInfo = "SQLiteTests tvOS"; - }; - D6A45F4122A137AF00B5BB27 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = A121AC451CA35C79005A31D1; - remoteInfo = "SQLite watchOS"; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 58B511D91A9E6C8500147676 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -100,23 +41,21 @@ 134814201AA4EA6300B7C361 /* libRNWebim.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNWebim.a; sourceTree = BUILT_PRODUCTS_DIR; }; B3E7B5881CC2AC0600A0062D /* RNWebim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNWebim.h; sourceTree = ""; }; B3E7B5891CC2AC0600A0062D /* RNWebim.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNWebim.m; sourceTree = ""; }; - D65659AF22A1569F00B76477 /* RNWebim-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNWebim-Bridging-Header.h"; sourceTree = ""; }; - D65659B822A156A000B76477 /* Department.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Department.swift; path = swift_bridging/Department.swift; sourceTree = ""; }; - D65659B922A156A000B76477 /* WebimLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebimLogger.swift; path = swift_bridging/WebimLogger.swift; sourceTree = ""; }; - D65659BA22A156A000B76477 /* WebimError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebimError.swift; path = swift_bridging/WebimError.swift; sourceTree = ""; }; - D65659BB22A156A100B76477 /* Operator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Operator.swift; path = swift_bridging/Operator.swift; sourceTree = ""; }; - D65659BC22A156A100B76477 /* Webim.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Webim.swift; path = swift_bridging/Webim.swift; sourceTree = ""; }; - D65659BD22A156A100B76477 /* WebimSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebimSession.swift; path = swift_bridging/WebimSession.swift; sourceTree = ""; }; - D65659BE22A156A100B76477 /* MessageTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MessageTracker.swift; path = swift_bridging/MessageTracker.swift; sourceTree = ""; }; - D65659BF22A156A100B76477 /* WebimRemoteNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebimRemoteNotification.swift; path = swift_bridging/WebimRemoteNotification.swift; sourceTree = ""; }; - D65659C022A156A100B76477 /* FatalErrorHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FatalErrorHandler.swift; path = swift_bridging/FatalErrorHandler.swift; sourceTree = ""; }; - D65659C122A156A100B76477 /* MessageListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MessageListener.swift; path = swift_bridging/MessageListener.swift; sourceTree = ""; }; - D65659C222A156A100B76477 /* ProvidedAuthorizationTokenStateListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProvidedAuthorizationTokenStateListener.swift; path = swift_bridging/ProvidedAuthorizationTokenStateListener.swift; sourceTree = ""; }; - D65659C322A156A200B76477 /* MessageStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MessageStream.swift; path = swift_bridging/MessageStream.swift; sourceTree = ""; }; - D65659C422A156A200B76477 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Message.swift; path = swift_bridging/Message.swift; sourceTree = ""; }; D65659D222A158C400B76477 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - D6565A0622A16A1100B76477 /* WebimClientLibrary.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = WebimClientLibrary.xcodeproj; path = libs/Webim/WebimClientLibrary.xcodeproj; sourceTree = ""; }; - D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SQLite.xcodeproj; path = libs/Sqlite/SQLite.xcodeproj; sourceTree = ""; }; + D69EFDC824C836CB00728191 /* RNWebim-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNWebim-Bridging-Header.h"; sourceTree = ""; }; + D69EFDC924C836CC00728191 /* ProvidedAuthorizationTokenStateListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProvidedAuthorizationTokenStateListener.swift; sourceTree = ""; }; + D69EFDCA24C836CC00728191 /* Operator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operator.swift; sourceTree = ""; }; + D69EFDCB24C836CC00728191 /* Department.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Department.swift; sourceTree = ""; }; + D69EFDCC24C836CC00728191 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; }; + D69EFDCD24C836CC00728191 /* WebimSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimSession.swift; sourceTree = ""; }; + D69EFDCE24C836CC00728191 /* WebimError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimError.swift; sourceTree = ""; }; + D69EFDCF24C836CC00728191 /* MessageTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageTracker.swift; sourceTree = ""; }; + D69EFDD024C836CC00728191 /* WebimLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimLogger.swift; sourceTree = ""; }; + D69EFDD124C836CC00728191 /* WebimRemoteNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimRemoteNotification.swift; sourceTree = ""; }; + D69EFDD224C836CC00728191 /* FatalErrorHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FatalErrorHandler.swift; sourceTree = ""; }; + D69EFDD324C836CC00728191 /* MessageListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageListener.swift; sourceTree = ""; }; + D69EFDD424C836CC00728191 /* Webim.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Webim.swift; sourceTree = ""; }; + D69EFDD524C836CC00728191 /* MessageStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageStream.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -124,8 +63,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D6A45F8922A1393300B5BB27 /* SQLite.framework in Frameworks */, - D6565A0C22A16A2800B76477 /* WebimClientLibrary.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -143,57 +80,25 @@ 58B511D21A9E6C8500147676 = { isa = PBXGroup; children = ( - D6A45F2422A1379100B5BB27 /* Libraries */, B3E7B5881CC2AC0600A0062D /* RNWebim.h */, B3E7B5891CC2AC0600A0062D /* RNWebim.m */, - D65659B822A156A000B76477 /* Department.swift */, - D65659C022A156A100B76477 /* FatalErrorHandler.swift */, - D65659C422A156A200B76477 /* Message.swift */, - D65659C122A156A100B76477 /* MessageListener.swift */, - D65659C322A156A200B76477 /* MessageStream.swift */, - D65659BE22A156A100B76477 /* MessageTracker.swift */, - D65659BB22A156A100B76477 /* Operator.swift */, - D65659C222A156A100B76477 /* ProvidedAuthorizationTokenStateListener.swift */, - D65659BC22A156A100B76477 /* Webim.swift */, - D65659BA22A156A000B76477 /* WebimError.swift */, - D65659B922A156A000B76477 /* WebimLogger.swift */, - D65659BF22A156A100B76477 /* WebimRemoteNotification.swift */, - D65659BD22A156A100B76477 /* WebimSession.swift */, + D69EFDCB24C836CC00728191 /* Department.swift */, + D69EFDD224C836CC00728191 /* FatalErrorHandler.swift */, + D69EFDCC24C836CC00728191 /* Message.swift */, + D69EFDD324C836CC00728191 /* MessageListener.swift */, + D69EFDD524C836CC00728191 /* MessageStream.swift */, + D69EFDCF24C836CC00728191 /* MessageTracker.swift */, + D69EFDCA24C836CC00728191 /* Operator.swift */, + D69EFDC924C836CC00728191 /* ProvidedAuthorizationTokenStateListener.swift */, + D69EFDD424C836CC00728191 /* Webim.swift */, + D69EFDCE24C836CC00728191 /* WebimError.swift */, + D69EFDD024C836CC00728191 /* WebimLogger.swift */, + D69EFDD124C836CC00728191 /* WebimRemoteNotification.swift */, + D69EFDCD24C836CC00728191 /* WebimSession.swift */, 134814211AA4EA7D00B7C361 /* Products */, D6A45F7F22A1392900B5BB27 /* Frameworks */, - D65659AF22A1569F00B76477 /* RNWebim-Bridging-Header.h */, - ); - sourceTree = ""; - }; - D6565A0722A16A1100B76477 /* Products */ = { - isa = PBXGroup; - children = ( - D6565A0B22A16A1100B76477 /* WebimClientLibrary.framework */, - ); - name = Products; - sourceTree = ""; - }; - D6A45F2422A1379100B5BB27 /* Libraries */ = { - isa = PBXGroup; - children = ( - D6565A0622A16A1100B76477 /* WebimClientLibrary.xcodeproj */, - D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */, - ); - name = Libraries; - sourceTree = ""; - }; - D6A45F2C22A137AE00B5BB27 /* Products */ = { - isa = PBXGroup; - children = ( - D6A45F3622A137AF00B5BB27 /* SQLite.framework */, - D6A45F3822A137AF00B5BB27 /* SQLiteTests iOS.xctest */, - D6A45F3A22A137AF00B5BB27 /* SQLite.framework */, - D6A45F3C22A137AF00B5BB27 /* SQLiteTests Mac.xctest */, - D6A45F3E22A137AF00B5BB27 /* SQLite.framework */, - D6A45F4022A137AF00B5BB27 /* SQLiteTests tvOS.xctest */, - D6A45F4222A137AF00B5BB27 /* SQLite.framework */, + D69EFDC824C836CB00728191 /* RNWebim-Bridging-Header.h */, ); - name = Products; sourceTree = ""; }; D6A45F7F22A1392900B5BB27 /* Frameworks */ = { @@ -206,11 +111,24 @@ }; /* End PBXGroup section */ +/* Begin PBXHeadersBuildPhase section */ + D69EFDE324C841A300728191 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D69EFDE424C841AB00728191 /* RNWebim.h in Headers */, + D69EFDE524C841B000728191 /* RNWebim-Bridging-Header.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + /* Begin PBXNativeTarget section */ 58B511DA1A9E6C8500147676 /* RNWebim */ = { isa = PBXNativeTarget; buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNWebim" */; buildPhases = ( + D69EFDE324C841A300728191 /* Headers */, 58B511D71A9E6C8500147676 /* Sources */, 58B511D81A9E6C8500147676 /* Frameworks */, 58B511D91A9E6C8500147676 /* CopyFiles */, @@ -235,7 +153,7 @@ TargetAttributes = { 58B511DA1A9E6C8500147676 = { CreatedOnToolsVersion = 6.1.1; - LastSwiftMigration = 1020; + LastSwiftMigration = 1150; }; }; }; @@ -250,16 +168,6 @@ mainGroup = 58B511D21A9E6C8500147676; productRefGroup = 58B511D21A9E6C8500147676; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = D6A45F2C22A137AE00B5BB27 /* Products */; - ProjectRef = D6A45F2B22A137AE00B5BB27 /* SQLite.xcodeproj */; - }, - { - ProductGroup = D6565A0722A16A1100B76477 /* Products */; - ProjectRef = D6565A0622A16A1100B76477 /* WebimClientLibrary.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 58B511DA1A9E6C8500147676 /* RNWebim */, @@ -267,84 +175,25 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - D6565A0B22A16A1100B76477 /* WebimClientLibrary.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = WebimClientLibrary.framework; - remoteRef = D6565A0A22A16A1100B76477 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - D6A45F3622A137AF00B5BB27 /* SQLite.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = SQLite.framework; - remoteRef = D6A45F3522A137AF00B5BB27 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - D6A45F3822A137AF00B5BB27 /* SQLiteTests iOS.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = "SQLiteTests iOS.xctest"; - remoteRef = D6A45F3722A137AF00B5BB27 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - D6A45F3A22A137AF00B5BB27 /* SQLite.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = SQLite.framework; - remoteRef = D6A45F3922A137AF00B5BB27 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - D6A45F3C22A137AF00B5BB27 /* SQLiteTests Mac.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = "SQLiteTests Mac.xctest"; - remoteRef = D6A45F3B22A137AF00B5BB27 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - D6A45F3E22A137AF00B5BB27 /* SQLite.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = SQLite.framework; - remoteRef = D6A45F3D22A137AF00B5BB27 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - D6A45F4022A137AF00B5BB27 /* SQLiteTests tvOS.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = "SQLiteTests tvOS.xctest"; - remoteRef = D6A45F3F22A137AF00B5BB27 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - D6A45F4222A137AF00B5BB27 /* SQLite.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = SQLite.framework; - remoteRef = D6A45F4122A137AF00B5BB27 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXSourcesBuildPhase section */ 58B511D71A9E6C8500147676 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D65659CE22A156A200B76477 /* MessageListener.swift in Sources */, - D65659CD22A156A200B76477 /* FatalErrorHandler.swift in Sources */, - D65659CF22A156A200B76477 /* ProvidedAuthorizationTokenStateListener.swift in Sources */, - D65659CB22A156A200B76477 /* MessageTracker.swift in Sources */, + D69EFDDC24C836CC00728191 /* MessageTracker.swift in Sources */, + D69EFDD624C836CC00728191 /* ProvidedAuthorizationTokenStateListener.swift in Sources */, + D69EFDD724C836CC00728191 /* Operator.swift in Sources */, + D69EFDDB24C836CC00728191 /* WebimError.swift in Sources */, + D69EFDD924C836CC00728191 /* Message.swift in Sources */, + D69EFDE224C836CC00728191 /* MessageStream.swift in Sources */, + D69EFDDD24C836CC00728191 /* WebimLogger.swift in Sources */, + D69EFDDF24C836CC00728191 /* FatalErrorHandler.swift in Sources */, + D69EFDE124C836CC00728191 /* Webim.swift in Sources */, + D69EFDE024C836CC00728191 /* MessageListener.swift in Sources */, + D69EFDDE24C836CC00728191 /* WebimRemoteNotification.swift in Sources */, + D69EFDD824C836CC00728191 /* Department.swift in Sources */, + D69EFDDA24C836CC00728191 /* WebimSession.swift in Sources */, B3E7B58A1CC2AC0600A0062D /* RNWebim.m in Sources */, - D65659C722A156A200B76477 /* WebimError.swift in Sources */, - D65659CA22A156A200B76477 /* WebimSession.swift in Sources */, - D65659CC22A156A200B76477 /* WebimRemoteNotification.swift in Sources */, - D65659C922A156A200B76477 /* Webim.swift in Sources */, - D65659C822A156A200B76477 /* Operator.swift in Sources */, - D65659C522A156A200B76477 /* Department.swift in Sources */, - D65659D022A156A200B76477 /* MessageStream.swift in Sources */, - D65659C622A156A200B76477 /* WebimLogger.swift in Sources */, - D65659D122A156A200B76477 /* Message.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -354,6 +203,7 @@ 58B511ED1A9E6C8500147676 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -371,6 +221,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -398,6 +249,7 @@ 58B511EE1A9E6C8500147676 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -415,6 +267,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; + DEFINES_MODULE = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; diff --git a/ios/RNWebim.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/RNWebim.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/RNWebim.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/libs/Webim/Example/WebimClientLibrary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/RNWebim.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist old mode 100755 new mode 100644 similarity index 100% rename from ios/libs/Webim/Example/WebimClientLibrary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to ios/RNWebim.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/ios/RNWebim.xcodeproj/project.xcworkspace/xcuserdata/alfclausen.xcuserdatad/UserInterfaceState.xcuserstate b/ios/RNWebim.xcodeproj/project.xcworkspace/xcuserdata/alfclausen.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..c48b7a9 Binary files /dev/null and b/ios/RNWebim.xcodeproj/project.xcworkspace/xcuserdata/alfclausen.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ios/RNWebim.xcodeproj/project.xcworkspace/xcuserdata/nikitasirotkin.xcuserdatad/UserInterfaceState.xcuserstate b/ios/RNWebim.xcodeproj/project.xcworkspace/xcuserdata/nikitasirotkin.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..d887a41 Binary files /dev/null and b/ios/RNWebim.xcodeproj/project.xcworkspace/xcuserdata/nikitasirotkin.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ios/libs/Webim/WebimClientLibrary.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/RNWebim.xcodeproj/xcuserdata/alfclausen.xcuserdatad/xcschemes/xcschememanagement.plist similarity index 78% rename from ios/libs/Webim/WebimClientLibrary.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist rename to ios/RNWebim.xcodeproj/xcuserdata/alfclausen.xcuserdatad/xcschemes/xcschememanagement.plist index 18e0bff..7493a26 100644 --- a/ios/libs/Webim/WebimClientLibrary.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/ios/RNWebim.xcodeproj/xcuserdata/alfclausen.xcuserdatad/xcschemes/xcschememanagement.plist @@ -4,10 +4,10 @@ SchemeUserState - WebimClientLibrary.xcscheme_^#shared#^_ + RNWebim.xcscheme_^#shared#^_ orderHint - 7 + 0 diff --git a/ios/RNWebim.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/RNWebim.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist index 317a1a0..7493a26 100644 --- a/ios/RNWebim.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/ios/RNWebim.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,7 +7,7 @@ RNWebim.xcscheme_^#shared#^_ orderHint - 68 + 0 diff --git a/ios/swift_bridging/Webim.swift b/ios/Webim.swift similarity index 84% rename from ios/swift_bridging/Webim.swift rename to ios/Webim.swift index d215c2b..c195e4a 100755 --- a/ios/swift_bridging/Webim.swift +++ b/ios/Webim.swift @@ -28,20 +28,19 @@ import Foundation import WebimClientLibrary - // MARK: - Webim @objc(Webim) -final class _ObjCWebim: NSObject { +public final class _ObjCWebim: NSObject { // MARK: - Methods @objc - static func newSessionBuilder() -> _ObjCSessionBuilder { + public static func newSessionBuilder() -> _ObjCSessionBuilder { return _ObjCSessionBuilder(sessionBuilder: Webim.newSessionBuilder()) } @objc(parseRemoteNotification:) - static func parse(remoteNotification: [AnyHashable: Any]) -> _ObjCWebimRemoteNotification? { + public static func parse(remoteNotification: [AnyHashable: Any]) -> _ObjCWebimRemoteNotification? { if let webimRemoteNotification = Webim.parse(remoteNotification: remoteNotification) { return _ObjCWebimRemoteNotification(webimRemoteNotification: webimRemoteNotification) } else { @@ -66,7 +65,7 @@ final class _ObjCWebim: NSObject { // MARK: - RemoteNotificationSystem @objc(RemoteNotificationSystem) - enum _ObjCRemoteNotificationSystem: Int { + public enum _ObjCRemoteNotificationSystem: Int { case APNS case NONE } @@ -75,7 +74,7 @@ final class _ObjCWebim: NSObject { // MARK: - SessionBuilder @objc(SessionBuilder) -final class _ObjCSessionBuilder: NSObject { +public final class _ObjCSessionBuilder: NSObject { // MARK: - Properties private (set) var sessionBuilder: SessionBuilder @@ -91,49 +90,49 @@ final class _ObjCSessionBuilder: NSObject { // MARK: - Methods @objc(setAccountName:) - func set(accountName: String) -> _ObjCSessionBuilder { + public func set(accountName: String) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(accountName: accountName) return self } @objc(setLocation:) - func set(location: String) -> _ObjCSessionBuilder { + public func set(location: String) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(location: location) return self } @objc(setPrechat:) - func set(prechat: String) -> _ObjCSessionBuilder { + public func set(prechat: String) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(prechat: prechat) return self } @objc(setAppVersion:) - func set(appVersion: String) -> _ObjCSessionBuilder { + public func set(appVersion: String) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(appVersion: appVersion) return self } @objc(setVisitorFieldsJSONString:) - func set(visitorFieldsJSONString: String) -> _ObjCSessionBuilder { + public func set(visitorFieldsJSONString: String) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(visitorFieldsJSONString: visitorFieldsJSONString) return self } @objc(setVisitorFieldsJSONData:) - func set(visitorFieldsJSONData: Data) -> _ObjCSessionBuilder { + public func set(visitorFieldsJSONData: Data) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(visitorFieldsJSONData: visitorFieldsJSONData) return self } @objc(setProvidedAuthorizationTokenStateListener:providedAuthorizationToken:) - func set(providedAuthorizationTokenStateListener: _ObjCProvidedAuthorizationTokenStateListener, + public func set(providedAuthorizationTokenStateListener: _ObjCProvidedAuthorizationTokenStateListener, providedAuthorizationToken: String? = nil) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(providedAuthorizationTokenStateListener: ProvidedAuthorizationTokenStateListenerWrapper(providedAuthorizationTokenStateListener: providedAuthorizationTokenStateListener), providedAuthorizationToken: providedAuthorizationToken) @@ -142,21 +141,21 @@ final class _ObjCSessionBuilder: NSObject { } @objc(setPageTitle:) - func set(pageTitle: String) -> _ObjCSessionBuilder { + public func set(pageTitle: String) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(pageTitle: pageTitle) return self } @objc(setFatalErrorHandler:) - func set(fatalErrorHandler: _ObjCFatalErrorHandler) -> _ObjCSessionBuilder { + public func set(fatalErrorHandler: _ObjCFatalErrorHandler) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(fatalErrorHandler: FatalErrorHandlerWrapper(fatalErrorHandler: fatalErrorHandler)) return self } @objc(setRemoteNotificationSystem:) - func set(remoteNotificationSystem: _ObjCWebim._ObjCRemoteNotificationSystem) -> _ObjCSessionBuilder { + public func set(remoteNotificationSystem: _ObjCWebim._ObjCRemoteNotificationSystem) -> _ObjCSessionBuilder { var webimRemoteNotificationSystem: Webim.RemoteNotificationSystem? switch remoteNotificationSystem { case .APNS: @@ -170,7 +169,7 @@ final class _ObjCSessionBuilder: NSObject { } @objc(setDeviceToken:) - func set(deviceToken: String?) -> _ObjCSessionBuilder { + public func set(deviceToken: String?) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(deviceToken: deviceToken) return self @@ -184,14 +183,14 @@ final class _ObjCSessionBuilder: NSObject { } @objc(setIsVisitorDataClearingEnabled:) - func set(isVisitorDataClearingEnabled: Bool) -> _ObjCSessionBuilder { + public func set(isVisitorDataClearingEnabled: Bool) -> _ObjCSessionBuilder { sessionBuilder = sessionBuilder.set(isVisitorDataClearingEnabled: isVisitorDataClearingEnabled) return self } @objc(setWebimLogger:verbosityLevel:) - func set(webimLogger: _ObjCWebimLogger, + public func set(webimLogger: _ObjCWebimLogger, verbosityLevel: _ObjCWebimLoggerVerbosityLevel) -> _ObjCSessionBuilder { var internalVerbosityLevel: SessionBuilder.WebimLoggerVerbosityLevel? switch verbosityLevel { @@ -215,13 +214,13 @@ final class _ObjCSessionBuilder: NSObject { } @objc(build:) - func build() throws -> _ObjCWebimSession { + public func build() throws -> _ObjCWebimSession { return try _ObjCWebimSession(webimSession: sessionBuilder.build()) } // MARK: - @objc(WebimLoggerVerbosityLevel) - enum _ObjCWebimLoggerVerbosityLevel: Int { + public enum _ObjCWebimLoggerVerbosityLevel: Int { case VERBOSE case DEBUG case INFO diff --git a/ios/swift_bridging/WebimError.swift b/ios/WebimError.swift similarity index 96% rename from ios/swift_bridging/WebimError.swift rename to ios/WebimError.swift index 4155b8f..ddf22ff 100755 --- a/ios/swift_bridging/WebimError.swift +++ b/ios/WebimError.swift @@ -31,7 +31,7 @@ import WebimClientLibrary // MARK: - WebimError @objc(WebimError) -final class _ObjCWebimError: NSObject { +public final class _ObjCWebimError: NSObject { // MARK: - Properties private let webimError: WebimError @@ -71,7 +71,7 @@ final class _ObjCWebimError: NSObject { // MARK: - FatalErrorType @objc(FatalErrorType) -enum _ObjCFatalErrorType: Int { +public enum _ObjCFatalErrorType: Int { case ACCOUNT_BLOCKED case PROVIDED_VISITOR_FIELDS_EXPIRED case UNKNOWN diff --git a/ios/swift_bridging/WebimLogger.swift b/ios/WebimLogger.swift similarity index 90% rename from ios/swift_bridging/WebimLogger.swift rename to ios/WebimLogger.swift index 307ee59..8f57030 100755 --- a/ios/swift_bridging/WebimLogger.swift +++ b/ios/WebimLogger.swift @@ -29,7 +29,7 @@ import WebimClientLibrary // MARK: - WebimLogger @objc(WebimLogger) -protocol _ObjCWebimLogger { +public protocol _ObjCWebimLogger { @objc(logEntry:) func log(entry: String) @@ -38,17 +38,17 @@ protocol _ObjCWebimLogger { // MARK: - Protocols' wrappers // MARK: - WebimLogger -final class WebimLoggerWrapper: WebimLogger { +public final class WebimLoggerWrapper: WebimLogger { // MARK: - Properties private let webimLogger: _ObjCWebimLogger // MARK: - Initialization - init(webimLogger: _ObjCWebimLogger) { + public init(webimLogger: _ObjCWebimLogger) { self.webimLogger = webimLogger } - func log(entry: String) { + public func log(entry: String) { webimLogger.log(entry: entry) } diff --git a/ios/swift_bridging/WebimRemoteNotification.swift b/ios/WebimRemoteNotification.swift similarity index 86% rename from ios/swift_bridging/WebimRemoteNotification.swift rename to ios/WebimRemoteNotification.swift index c84f7c9..b276425 100755 --- a/ios/swift_bridging/WebimRemoteNotification.swift +++ b/ios/WebimRemoteNotification.swift @@ -29,14 +29,14 @@ import WebimClientLibrary // MARK: - WebimRemoteNotification @objc(WebimRemoteNotification) -final class _ObjCWebimRemoteNotification: NSObject { +public final class _ObjCWebimRemoteNotification: NSObject { // MARK: - Properties private let webimRemoteNotification: WebimRemoteNotification // MARK: - Initialization - init(webimRemoteNotification: WebimRemoteNotification) { + public init(webimRemoteNotification: WebimRemoteNotification) { self.webimRemoteNotification = webimRemoteNotification } @@ -44,7 +44,7 @@ final class _ObjCWebimRemoteNotification: NSObject { // MARK: - Methods @objc(getType) - func getType() -> _ObjCNotificationType { + public func getType() -> _ObjCNotificationType { switch webimRemoteNotification.getType() { case .CONTACT_INFORMATION_REQUEST: return .CONTACT_INFORMATION_REQUEST @@ -56,11 +56,13 @@ final class _ObjCWebimRemoteNotification: NSObject { return .OPERATOR_MESSAGE case .WIDGET: return .WIDGET + case .none: + return .NONE } } @objc(getEvent) - func getEvent() -> _ObjCNotificationEvent { + public func getEvent() -> _ObjCNotificationEvent { if let event = webimRemoteNotification.getEvent() { switch event { case .ADD: @@ -74,7 +76,7 @@ final class _ObjCWebimRemoteNotification: NSObject { } @objc(getParameters) - func getParameters() -> [String] { + public func getParameters() -> [String] { return webimRemoteNotification.getParameters() } @@ -83,17 +85,18 @@ final class _ObjCWebimRemoteNotification: NSObject { // MARK: - NotificationType @objc(NotificationType) -enum _ObjCNotificationType: Int { +public enum _ObjCNotificationType: Int { case CONTACT_INFORMATION_REQUEST case OPERATOR_ACCEPTED case OPERATOR_FILE case OPERATOR_MESSAGE case WIDGET + case NONE } // MARK: - NotificationEvent @objc(NotificationEvent) -enum _ObjCNotificationEvent: Int { +public enum _ObjCNotificationEvent: Int { case NONE case ADD case DELETE diff --git a/ios/swift_bridging/WebimSession.swift b/ios/WebimSession.swift similarity index 83% rename from ios/swift_bridging/WebimSession.swift rename to ios/WebimSession.swift index a9dd78d..5fcaf26 100755 --- a/ios/swift_bridging/WebimSession.swift +++ b/ios/WebimSession.swift @@ -31,53 +31,53 @@ import WebimClientLibrary // MARK: - WebimSession @objc(WebimSession) -final class _ObjCWebimSession: NSObject { - +public final class _ObjCWebimSession: NSObject { + // MARK: - Properties private let webimSession: WebimSession - - + + // MARK: - Initializers - init(webimSession: WebimSession) { + public init(webimSession: WebimSession) { self.webimSession = webimSession } - - + + // MARK: - Methods - + @objc(resume:) - func resume() throws { + public func resume() throws { try webimSession.resume() } - + @objc(pause:) - func pause() throws { + public func pause() throws { try webimSession.pause() } - + @objc(destroy:) - func destry() throws { + public func destroy() throws { try webimSession.destroy() } - + @objc(destroyWithClearVisitorData:) - func destroyWithClearVisitorData() throws { + public func destroyWithClearVisitorData() throws { try webimSession.destroyWithClearVisitorData() } - + @objc(getStream) - func getStream() -> _ObjCMessageStream { + public func getStream() -> _ObjCMessageStream { return _ObjCMessageStream(messageStream: webimSession.getStream()) } - + @objc(changeLocation:error:) - func change(location: String) throws { + public func change(location: String) throws { try webimSession.change(location: location) } - + @objc(setDeviceToken:error:) - func set(deviceToken: String) throws { + public func set(deviceToken: String) throws { try webimSession.set(deviceToken: deviceToken) } - + } diff --git a/ios/libs/Sqlite/CHANGELOG.md b/ios/libs/Sqlite/CHANGELOG.md deleted file mode 100755 index 027611e..0000000 --- a/ios/libs/Sqlite/CHANGELOG.md +++ /dev/null @@ -1,97 +0,0 @@ -0.11.6 (xxx), [diff][diff-0.11.6] -======================================== - -* Swift 4.2, SQLCipher 4.x ([#866][]) - -0.11.5 (04-14-2018), [diff][diff-0.11.5] -======================================== - -* Swift 4.1 ([#797][]) - -0.11.4 (30-09-2017), [diff][diff-0.11.4] -======================================== - -* Collate `.nocase` strictly enforces `NOT NULL` even when using Optional ([#697][]) -* Fix transactions not being rolled back when committing fails ([#426][]) -* Add possibility to have expression on right hand side of like ([#591][]) -* Added Date and Time functions ([#142][]) -* Add Swift4 Coding support ([#733][]) -* Preliminary Linux support ([#315][], [#681][]) -* Add `RowIterator` for more safety ([#647][], [#726][]) -* Make `Row.get` throw instead of crash ([#649][]) -* Fix create/drop index functions ([#666][]) -* Revert deployment target to 8.0 ([#625][], [#671][], [#717][]) -* Added support for the union query clause ([#723][]) -* Add support for `ORDER` and `LIMIT` on `UPDATE` and `DELETE` ([#657][], [#722][]) -* Swift 4 support ([#668][]) - -0.11.3 (30-03-2017), [diff][diff-0.11.3] -======================================== - -* Fix compilation problems when using Carthage ([#615][]) -* Add `WITHOUT ROWID` table option ([#541][]) -* Argument count fixed for binary custom functions ([#481][]) -* Documentation updates -* Tested with Xcode 8.3 / iOS 10.3 - -0.11.2 (25-12-2016), [diff][diff-0.11.2] -======================================== - -* Fixed SQLCipher integration with read-only databases ([#559][]) -* Preliminary Swift Package Manager support ([#548][], [#560][]) -* Fixed null pointer when fetching an empty BLOB ([#561][]) -* Allow `where` as alias for `filter` ([#571][]) - -0.11.1 (06-12-2016), [diff][diff-0.11.1] -======================================== - -* Integrate SQLCipher via CocoaPods ([#546][], [#553][]) -* Made lastInsertRowid consistent with other SQLite wrappers ([#532][]) -* Fix for `~=` operator used with Double ranges -* Various documentation updates - -0.11.0 (19-10-2016) -=================== - -* Swift3 migration ([diff][diff-0.11.0]) - - -[diff-0.11.0]: https://github.com/stephencelis/SQLite.swift/compare/0.10.1...0.11.0 -[diff-0.11.1]: https://github.com/stephencelis/SQLite.swift/compare/0.11.0...0.11.1 -[diff-0.11.2]: https://github.com/stephencelis/SQLite.swift/compare/0.11.1...0.11.2 -[diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3 -[diff-0.11.4]: https://github.com/stephencelis/SQLite.swift/compare/0.11.3...0.11.4 -[diff-0.11.5]: https://github.com/stephencelis/SQLite.swift/compare/0.11.4...0.11.5 -[diff-0.11.6]: https://github.com/stephencelis/SQLite.swift/compare/0.11.5...0.11.6 - -[#142]: https://github.com/stephencelis/SQLite.swift/issues/142 -[#315]: https://github.com/stephencelis/SQLite.swift/issues/315 -[#426]: https://github.com/stephencelis/SQLite.swift/pull/426 -[#481]: https://github.com/stephencelis/SQLite.swift/pull/481 -[#532]: https://github.com/stephencelis/SQLite.swift/issues/532 -[#541]: https://github.com/stephencelis/SQLite.swift/issues/541 -[#546]: https://github.com/stephencelis/SQLite.swift/issues/546 -[#548]: https://github.com/stephencelis/SQLite.swift/pull/548 -[#553]: https://github.com/stephencelis/SQLite.swift/pull/553 -[#559]: https://github.com/stephencelis/SQLite.swift/pull/559 -[#560]: https://github.com/stephencelis/SQLite.swift/pull/560 -[#561]: https://github.com/stephencelis/SQLite.swift/issues/561 -[#571]: https://github.com/stephencelis/SQLite.swift/issues/571 -[#591]: https://github.com/stephencelis/SQLite.swift/pull/591 -[#615]: https://github.com/stephencelis/SQLite.swift/pull/615 -[#625]: https://github.com/stephencelis/SQLite.swift/issues/625 -[#647]: https://github.com/stephencelis/SQLite.swift/pull/647 -[#649]: https://github.com/stephencelis/SQLite.swift/pull/649 -[#657]: https://github.com/stephencelis/SQLite.swift/issues/657 -[#666]: https://github.com/stephencelis/SQLite.swift/pull/666 -[#668]: https://github.com/stephencelis/SQLite.swift/pull/668 -[#671]: https://github.com/stephencelis/SQLite.swift/issues/671 -[#681]: https://github.com/stephencelis/SQLite.swift/issues/681 -[#697]: https://github.com/stephencelis/SQLite.swift/issues/697 -[#717]: https://github.com/stephencelis/SQLite.swift/issues/717 -[#722]: https://github.com/stephencelis/SQLite.swift/pull/722 -[#723]: https://github.com/stephencelis/SQLite.swift/pull/723 -[#733]: https://github.com/stephencelis/SQLite.swift/pull/733 -[#726]: https://github.com/stephencelis/SQLite.swift/pull/726 -[#797]: https://github.com/stephencelis/SQLite.swift/pull/797 -[#866]: https://github.com/stephencelis/SQLite.swift/pull/866 diff --git a/ios/libs/Sqlite/CONTRIBUTING.md b/ios/libs/Sqlite/CONTRIBUTING.md deleted file mode 100755 index 6c367b9..0000000 --- a/ios/libs/Sqlite/CONTRIBUTING.md +++ /dev/null @@ -1,108 +0,0 @@ -# Contributing - -The where and when to open an [issue](#issues) or [pull -request](#pull-requests). - - -## Issues - -Issues are used to track **bugs** and **feature requests**. Need **help** or -have a **general question**? [Ask on Stack Overflow][] (tag `sqlite.swift`). - -Before reporting a bug or requesting a feature, [run a few searches][Search] to -see if a similar issue has already been opened and ensure you’re not submitting -a duplicate. - -If you find a similar issue, read the existing conversation and see if it -addresses everything. If it doesn’t, continue the conversation there. - -If your searches return empty, see the [bug](#bugs) or [feature -request](#feature-requests) guidelines below. - -[Ask on Stack Overflow]: http://stackoverflow.com/questions/tagged/sqlite.swift -[Search]: https://github.com/stephencelis/SQLite.swift/search?type=Issues - - -### Bugs - -Think you’ve discovered a new **bug**? Let’s try troubleshooting a few things -first. - - - **Is it an installation issue?** - - If this is your first time building SQLite.swift in your project, you may - encounter a build error, _e.g._: - - No such module 'SQLite' - - Please carefully re-read the [installation instructions][] to make sure - everything is in order. - - - **Have you read the documentation?** - - If you can’t seem to get something working, check - [the documentation][See Documentation] to see if the solution is there. - - - **Are you up-to-date?** - - If you’re perusing [the documentation][See Documentation] online and find - that an example is just not working, please upgrade to the latest version - of SQLite.swift and try again before continuing. - - - **Is it an unhelpful build error?** - - While Swift error messaging is improving with each release, complex - expressions still lend themselves to misleading errors. If you encounter an - error on a complex line, breaking it down into smaller pieces generally - yields a more understandable error. - - - **Is it an _even more_ unhelpful build error?** - - Have you updated Xcode recently? Did your project stop building out of the - blue? - - Hold down the **option** key and select **Clean Build Folder…** from the - **Product** menu (⌥⇧⌘K). - -Made it through everything above and still having trouble? Sorry! -[Open an issue][]! And _please_: - - - Be as descriptive as possible. - - Provide as much information needed to _reliably reproduce_ the issue. - - Attach screenshots if possible. - - Better yet: attach GIFs or link to video. - - Even better: link to a sample project exhibiting the issue. - - Include the SQLite.swift commit or branch experiencing the issue. - - Include devices and operating systems affected. - - Include build information: the Xcode and macOS versions affected. - -[installation instructions]: Documentation/Index.md#installation -[See Documentation]: Documentation/Index.md#sqliteswift-documentation -[Open an issue]: https://github.com/stephencelis/SQLite.swift/issues/new - - -### Feature Requests - -Have an innovative **feature request**? [Open an issue][]! Be thorough! Provide -context and examples. Be open to discussion. - - -## Pull Requests - -Interested in contributing but don’t know where to start? Try the [`help -wanted`][help wanted] label. - -Ready to submit a fix or a feature? [Submit a pull request][]! And _please_: - - - If code changes, run the tests and make sure everything still works. - - Write new tests for new functionality. - - Update documentation comments where applicable. - - Maintain the existing style. - - Don’t forget to have fun. - -While we cannot guarantee a merge to every pull request, we do read each one -and love your input. - - -[help wanted]: https://github.com/stephencelis/SQLite.swift/labels/help%20wanted -[Submit a pull request]: https://github.com/stephencelis/SQLite.swift/fork diff --git a/ios/libs/Sqlite/Documentation/Index.md b/ios/libs/Sqlite/Documentation/Index.md deleted file mode 100755 index 70d67c2..0000000 --- a/ios/libs/Sqlite/Documentation/Index.md +++ /dev/null @@ -1,1901 +0,0 @@ -# SQLite.swift Documentation - - - [Installation](#installation) - - [Carthage](#carthage) - - [CocoaPods](#cocoapods) - - [Swift Package Manager](#swift-package-manager) - - [Manual](#manual) - - [Getting Started](#getting-started) - - [Connecting to a Database](#connecting-to-a-database) - - [Read-Write Databases](#read-write-databases) - - [Read-Only Databases](#read-only-databases) - - [In-Memory Databases](#in-memory-databases) - - [Thread-Safety](#thread-safety) - - [Building Type-Safe SQL](#building-type-safe-sql) - - [Expressions](#expressions) - - [Compound Expressions](#compound-expressions) - - [Queries](#queries) - - [Creating a Table](#creating-a-table) - - [Create Table Options](#create-table-options) - - [Column Constraints](#column-constraints) - - [Table Constraints](#table-constraints) - - [Inserting Rows](#inserting-rows) - - [Handling SQLite errors](#handling-sqlite-errors) - - [Setters](#setters) - - [Selecting Rows](#selecting-rows) - - [Iterating and Accessing Values](#iterating-and-accessing-values) - - [Plucking Rows](#plucking-rows) - - [Building Complex Queries](#building-complex-queries) - - [Selecting Columns](#selecting-columns) - - [Joining Other Tables](#joining-other-tables) - - [Column Namespacing](#column-namespacing) - - [Table Aliasing](#table-aliasing) - - [Filtering Rows](#filtering-rows) - - [Filter Operators and Functions](#filter-operators-and-functions) - - [Sorting Rows](#sorting-rows) - - [Limiting and Paging Results](#limiting-and-paging-results) - - [Aggregation](#aggregation) - - [Updating Rows](#updating-rows) - - [Deleting Rows](#deleting-rows) - - [Transactions and Savepoints](#transactions-and-savepoints) - - [Altering the Schema](#altering-the-schema) - - [Renaming Tables](#renaming-tables) - - [Adding Columns](#adding-columns) - - [Added Column Constraints](#added-column-constraints) - - [Indexes](#indexes) - - [Creating Indexes](#creating-indexes) - - [Dropping Indexes](#dropping-indexes) - - [Dropping Tables](#dropping-tables) - - [Migrations and Schema Versioning](#migrations-and-schema-versioning) - - [Custom Types](#custom-types) - - [Date-Time Values](#date-time-values) - - [Binary Data](#binary-data) - - [Codable Types](#codable-types) - - [Other Operators](#other-operators) - - [Core SQLite Functions](#core-sqlite-functions) - - [Aggregate SQLite Functions](#aggregate-sqlite-functions) - - [Date and Time Functions](#date-and-time-functions) - - [Custom SQL Functions](#custom-sql-functions) - - [Custom Collations](#custom-collations) - - [Full-text Search](#full-text-search) - - [Executing Arbitrary SQL](#executing-arbitrary-sql) - - [Logging](#logging) - - -[↩]: #sqliteswift-documentation - - -## Installation - -> _Note:_ SQLite.swift requires Swift 5 (and -> [Xcode 10.2](https://developer.apple.com/xcode/downloads/)) or greater. - - -### Carthage - -[Carthage][] is a simple, decentralized dependency manager for Cocoa. To -install SQLite.swift with Carthage: - 1. Make sure Carthage is [installed][Carthage Installation]. - - 2. Update your Cartfile to include the following: - - ```ruby - github "stephencelis/SQLite.swift" ~> 0.12.0 - ``` - - 3. Run `carthage update` and [add the appropriate framework][Carthage Usage]. - - -[Carthage]: https://github.com/Carthage/Carthage -[Carthage Installation]: https://github.com/Carthage/Carthage#installing-carthage -[Carthage Usage]: https://github.com/Carthage/Carthage#adding-frameworks-to-an-application - - -### CocoaPods - -[CocoaPods][] is a dependency manager for Cocoa projects. To install SQLite.swift with CocoaPods: - - 1. Make sure CocoaPods is [installed][CocoaPods Installation] (SQLite.swift - requires version 1.6.1 or greater). - - ```sh - # Using the default Ruby install will require you to use sudo when - # installing and updating gems. - [sudo] gem install cocoapods - ``` - - 2. Update your Podfile to include the following: - - ```ruby - use_frameworks! - - target 'YourAppTargetName' do - pod 'SQLite.swift', '~> 0.12.0' - end - ``` - - 3. Run `pod install --repo-update`. - - -#### Requiring a specific version of SQLite - -If you want to use a more recent version of SQLite than what is provided -with the OS you can require the `standalone` subspec: - -```ruby -target 'YourAppTargetName' do - pod 'SQLite.swift/standalone', '~> 0.12.0' -end -``` - -By default this will use the most recent version of SQLite without any -extras. If you want you can further customize this by adding another -dependency to sqlite3 or one of its subspecs: - -```ruby -target 'YourAppTargetName' do - pod 'SQLite.swift/standalone', '~> 0.12.0' - pod 'sqlite3/fts5', '= 3.15.0' # SQLite 3.15.0 with FTS5 enabled -end -``` - -See the [sqlite3 podspec][sqlite3pod] for more details. - -#### Using SQLite.swift with SQLCipher - -If you want to use [SQLCipher][] with SQLite.swift you can require the -`SQLCipher` subspec in your Podfile: - -```ruby -target 'YourAppTargetName' do - pod 'SQLite.swift/SQLCipher', '~> 0.12.0' -end -``` - -This will automatically add a dependency to the SQLCipher pod as well as -extend `Connection` with methods to change the database key: - -```swift -import SQLite - -let db = try Connection("path/to/db.sqlite3") -try db.key("secret") -try db.rekey("another secret") -``` - -[CocoaPods]: https://cocoapods.org -[CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started -[sqlite3pod]: https://github.com/clemensg/sqlite3pod -[SQLCipher]: https://www.zetetic.net/sqlcipher/ - -### Swift Package Manager - -The [Swift Package Manager][] is a tool for managing the distribution of -Swift code. It’s integrated with the Swift build system to automate the -process of downloading, compiling, and linking dependencies. - -It is the recommended approach for using SQLite.swift in OSX CLI -applications. - - 1. Add the following to your `Package.swift` file: - - ```swift - dependencies: [ - .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0") - ] - ``` - - 2. Build your project: - - ```sh - $ swift build - ``` - -[Swift Package Manager]: https://swift.org/package-manager - -### Manual - -To install SQLite.swift as an Xcode sub-project: - - 1. Drag the **SQLite.xcodeproj** file into your own project. - ([Submodule](http://git-scm.com/book/en/Git-Tools-Submodules), clone, or - [download](https://github.com/stephencelis/SQLite.swift/archive/master.zip) - the project first.) - - ![Installation Screen Shot](Resources/installation@2x.png) - - 2. In your target’s **General** tab, click the **+** button under **Linked - Frameworks and Libraries**. - - 3. Select the appropriate **SQLite.framework** for your platform. - - 4. **Add**. - -You should now be able to `import SQLite` from any of your target’s source -files and begin using SQLite.swift. - -Some additional steps are required to install the application on an actual -device: - - 5. In the **General** tab, click the **+** button under **Embedded - Binaries**. - - 6. Select the appropriate **SQLite.framework** for your platform. - - 7. **Add**. - -## Getting Started - -To use SQLite.swift classes or structures in your target’s source file, first -import the `SQLite` module. - -```swift -import SQLite -``` - - -### Connecting to a Database - -Database connections are established using the `Connection` class. A -connection is initialized with a path to a database. SQLite will attempt to -create the database file if it does not already exist. - -```swift -let db = try Connection("path/to/db.sqlite3") -``` - - -#### Read-Write Databases - -On iOS, you can create a writable database in your app’s **Documents** -directory. - -```swift -let path = NSSearchPathForDirectoriesInDomains( - .documentDirectory, .userDomainMask, true -).first! - -let db = try Connection("\(path)/db.sqlite3") -``` - -On macOS, you can use your app’s **Application Support** directory: - -```swift -var path = NSSearchPathForDirectoriesInDomains( - .applicationSupportDirectory, .userDomainMask, true -).first! + "/" + Bundle.main.bundleIdentifier! - -// create parent directory iff it doesn’t exist -try FileManager.default.createDirectoryAtPath( - path, withIntermediateDirectories: true, attributes: nil -) - -let db = try Connection("\(path)/db.sqlite3") -``` - - -#### Read-Only Databases - -If you bundle a database with your app (_i.e._, you’ve copied a database file -into your Xcode project and added it to your application target), you can -establish a _read-only_ connection to it. - -```swift -let path = Bundle.main.pathForResource("db", ofType: "sqlite3")! - -let db = try Connection(path, readonly: true) -``` - -> _Note:_ Signed applications cannot modify their bundle resources. If you -> bundle a database file with your app for the purpose of bootstrapping, copy -> it to a writable location _before_ establishing a connection (see -> [Read-Write Databases](#read-write-databases), above, for typical, writable -> locations). -> -> See these two Stack Overflow questions for more information about iOS apps -> with SQLite databases: [1](https://stackoverflow.com/questions/34609746/what-different-between-store-database-in-different-locations-in-ios), -> [2](https://stackoverflow.com/questions/34614968/ios-how-to-copy-pre-seeded-database-at-the-first-running-app-with-sqlite-swift). -> We welcome sample code to show how to successfully copy and use a bundled "seed" -> database for writing in an app. - -#### In-Memory Databases - -If you omit the path, SQLite.swift will provision an [in-memory -database](https://www.sqlite.org/inmemorydb.html). - -```swift -let db = try Connection() // equivalent to `Connection(.inMemory)` -``` - -To create a temporary, disk-backed database, pass an empty file name. - -```swift -let db = try Connection(.temporary) -``` - -In-memory databases are automatically deleted when the database connection is -closed. - - -#### Thread-Safety - -Every Connection comes equipped with its own serial queue for statement -execution and can be safely accessed across threads. Threads that open -transactions and savepoints will block other threads from executing -statements while the transaction is open. - -If you maintain multiple connections for a single database, consider setting a timeout (in seconds) and/or a busy handler: - -```swift -db.busyTimeout = 5 - -db.busyHandler({ tries in - if tries >= 3 { - return false - } - return true -}) -``` - -> _Note:_ The default timeout is 0, so if you see `database is locked` -> errors, you may be trying to access the same database simultaneously from -> multiple connections. - - -## Building Type-Safe SQL - -SQLite.swift comes with a typed expression layer that directly maps -[Swift types](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/) -to their [SQLite counterparts](https://www.sqlite.org/datatype3.html). - -| Swift Type | SQLite Type | -| --------------- | ----------- | -| `Int64`* | `INTEGER` | -| `Double` | `REAL` | -| `String` | `TEXT` | -| `nil` | `NULL` | -| `SQLite.Blob`† | `BLOB` | - -> *While `Int64` is the basic, raw type (to preserve 64-bit integers on -> 32-bit platforms), `Int` and `Bool` work transparently. -> -> †SQLite.swift defines its own `Blob` structure, which safely wraps the -> underlying bytes. -> -> See [Custom Types](#custom-types) for more information about extending -> other classes and structures to work with SQLite.swift. -> -> See [Executing Arbitrary SQL](#executing-arbitrary-sql) to forego the typed -> layer and execute raw SQL, instead. - -These expressions (in the form of the structure, -[`Expression`](#expressions)) build on one another and, with a query -([`QueryType`](#queries)), can create and execute SQL statements. - - -### Expressions - -Expressions are generic structures associated with a type ([built-in -](#building-type-safe-sql) or [custom](#custom-types)), raw SQL, and -(optionally) values to bind to that SQL. Typically, you will only explicitly -create expressions to describe your columns, and typically only once per -column. - -```swift -let id = Expression("id") -let email = Expression("email") -let balance = Expression("balance") -let verified = Expression("verified") -``` - -Use optional generics for expressions that can evaluate to `NULL`. - -```swift -let name = Expression("name") -``` - -> _Note:_ The default `Expression` initializer is for [quoted -> identifiers](https://www.sqlite.org/lang_keywords.html) (_i.e._, column -> names). To build a literal SQL expression, use `init(literal:)`. -> - - -### Compound Expressions - -Expressions can be combined with other expressions and types using -[filter operators and functions](#filter-operators-and-functions) -(as well as other [non-filter operators](#other-operators) and -[functions](#core-sqlite-functions)). These building blocks can create complex SQLite statements. - - -### Queries - -Queries are structures that reference a database and table name, and can be -used to build a variety of statements using expressions. We can create a -query by initializing a `Table`, `View`, or `VirtualTable`. - -```swift -let users = Table("users") -``` - -Assuming [the table exists](#creating-a-table), we can immediately [insert -](#inserting-rows), [select](#selecting-rows), [update](#updating-rows), and -[delete](#deleting-rows) rows. - - -## Creating a Table - -We can build [`CREATE TABLE` -statements](https://www.sqlite.org/lang_createtable.html) by calling the -`create` function on a `Table`. The following is a basic example of -SQLite.swift code (using the [expressions](#expressions) and -[query](#queries) above) and the corresponding SQL it generates. - -```swift -try db.run(users.create { t in // CREATE TABLE "users" ( - t.column(id, primaryKey: true) // "id" INTEGER PRIMARY KEY NOT NULL, - t.column(email, unique: true) // "email" TEXT UNIQUE NOT NULL, - t.column(name) // "name" TEXT -}) // ) -``` - -> _Note:_ `Expression` structures (in this case, the `id` and `email` -> columns), generate `NOT NULL` constraints automatically, while -> `Expression` structures (`name`) do not. - - -### Create Table Options - -The `Table.create` function has several default parameters we can override. - - - `temporary` adds a `TEMPORARY` clause to the `CREATE TABLE` statement (to - create a temporary table that will automatically drop when the database - connection closes). Default: `false`. - - ```swift - try db.run(users.create(temporary: true) { t in /* ... */ }) - // CREATE TEMPORARY TABLE "users" -- ... - ``` - - - `ifNotExists` adds an `IF NOT EXISTS` clause to the `CREATE TABLE` - statement (which will bail out gracefully if the table already exists). - Default: `false`. - - ```swift - try db.run(users.create(ifNotExists: true) { t in /* ... */ }) - // CREATE TABLE "users" IF NOT EXISTS -- ... - ``` - -### Column Constraints - -The `column` function is used for a single column definition. It takes an -[expression](#expressions) describing the column name and type, and accepts -several parameters that map to various column constraints and clauses. - - - `primaryKey` adds a `PRIMARY KEY` constraint to a single column. - - ```swift - t.column(id, primaryKey: true) - // "id" INTEGER PRIMARY KEY NOT NULL - - t.column(id, primaryKey: .autoincrement) - // "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL - ``` - - > _Note:_ The `primaryKey` parameter cannot be used alongside - > `references`. If you need to create a column that has a default value - > and is also a primary and/or foreign key, use the `primaryKey` and - > `foreignKey` functions mentioned under - > [Table Constraints](#table-constraints). - > - > Primary keys cannot be optional (_e.g._, `Expression`). - > - > Only an `INTEGER PRIMARY KEY` can take `.autoincrement`. - - - `unique` adds a `UNIQUE` constraint to the column. (See the `unique` - function under [Table Constraints](#table-constraints) for uniqueness - over multiple columns). - - ```swift - t.column(email, unique: true) - // "email" TEXT UNIQUE NOT NULL - ``` - - - `check` attaches a `CHECK` constraint to a column definition in the form - of a boolean expression (`Expression`). Boolean expressions can be - easily built using - [filter operators and functions](#filter-operators-and-functions). - (See also the `check` function under - [Table Constraints](#table-constraints).) - - ```swift - t.column(email, check: email.like("%@%")) - // "email" TEXT NOT NULL CHECK ("email" LIKE '%@%') - ``` - - - `defaultValue` adds a `DEFAULT` clause to a column definition and _only_ - accepts a value (or expression) matching the column’s type. This value is - used if none is explicitly provided during - [an `INSERT`](#inserting-rows). - - ```swift - t.column(name, defaultValue: "Anonymous") - // "name" TEXT DEFAULT 'Anonymous' - ``` - - > _Note:_ The `defaultValue` parameter cannot be used alongside - > `primaryKey` and `references`. If you need to create a column that has - > a default value and is also a primary and/or foreign key, use the - > `primaryKey` and `foreignKey` functions mentioned under - > [Table Constraints](#table-constraints). - - - `collate` adds a `COLLATE` clause to `Expression` (and - `Expression`) column definitions with - [a collating sequence](https://www.sqlite.org/datatype3.html#collation) - defined in the `Collation` enumeration. - - ```swift - t.column(email, collate: .nocase) - // "email" TEXT NOT NULL COLLATE "NOCASE" - - t.column(name, collate: .rtrim) - // "name" TEXT COLLATE "RTRIM" - ``` - - - `references` adds a `REFERENCES` clause to `Expression` (and - `Expression`) column definitions and accepts a table - (`SchemaType`) or namespaced column expression. (See the `foreignKey` - function under [Table Constraints](#table-constraints) for non-integer - foreign key support.) - - ```swift - t.column(user_id, references: users, id) - // "user_id" INTEGER REFERENCES "users" ("id") - ``` - - > _Note:_ The `references` parameter cannot be used alongside - > `primaryKey` and `defaultValue`. If you need to create a column that - > has a default value and is also a primary and/or foreign key, use the - > `primaryKey` and `foreignKey` functions mentioned under - > [Table Constraints](#table-constraints). - - -### Table Constraints - -Additional constraints may be provided outside the scope of a single column -using the following functions. - - - `primaryKey` adds a `PRIMARY KEY` constraint to the table. Unlike [the - column constraint, above](#column-constraints), it supports all SQLite - types, [ascending and descending orders](#sorting-rows), and composite - (multiple column) keys. - - ```swift - t.primaryKey(email.asc, name) - // PRIMARY KEY("email" ASC, "name") - ``` - - - `unique` adds a `UNIQUE` constraint to the table. Unlike - [the column constraint, above](#column-constraints), it - supports composite (multiplecolumn) constraints. - - ```swift - t.unique(local, domain) - // UNIQUE("local", "domain") - ``` - - - `check` adds a `CHECK` constraint to the table in the form of a boolean - expression (`Expression`). Boolean expressions can be easily built - using [filter operators and functions](#filter-operators-and-functions). - (See also the `check` parameter under - [Column Constraints](#column-constraints).) - - ```swift - t.check(balance >= 0) - // CHECK ("balance" >= 0.0) - ``` - - - `foreignKey` adds a `FOREIGN KEY` constraint to the table. Unlike [the - `references` constraint, above](#column-constraints), it supports all - SQLite types, both [`ON UPDATE` and `ON DELETE` - actions](https://www.sqlite.org/foreignkeys.html#fk_actions), and - composite (multiple column) keys. - - ```swift - t.foreignKey(user_id, references: users, id, delete: .setNull) - // FOREIGN KEY("user_id") REFERENCES "users"("id") ON DELETE SET NULL - ``` - - - - -## Inserting Rows - -We can insert rows into a table by calling a [query’s](#queries) `insert` -function with a list of [setters](#setters)—typically [typed column -expressions](#expressions) and values (which can also be expressions)—each -joined by the `<-` operator. - -```swift -try db.run(users.insert(email <- "alice@mac.com", name <- "Alice")) -// INSERT INTO "users" ("email", "name") VALUES ('alice@mac.com', 'Alice') - -try db.run(users.insert(or: .replace, email <- "alice@mac.com", name <- "Alice B.")) -// INSERT OR REPLACE INTO "users" ("email", "name") VALUES ('alice@mac.com', 'Alice B.') -``` - -The `insert` function, when run successfully, returns an `Int64` representing -the inserted row’s [`ROWID`][ROWID]. - -```swift -do { - let rowid = try db.run(users.insert(email <- "alice@mac.com")) - print("inserted id: \(rowid)") -} catch { - print("insertion failed: \(error)") -} -``` - -The [`update`](#updating-rows) and [`delete`](#deleting-rows) functions -follow similar patterns. - -> _Note:_ If `insert` is called without any arguments, the statement will run -> with a `DEFAULT VALUES` clause. The table must not have any constraints -> that aren’t fulfilled by default values. -> -> ```swift -> try db.run(timestamps.insert()) -> // INSERT INTO "timestamps" DEFAULT VALUES -> ``` - -### Handling SQLite errors - -You can pattern match on the error to selectively catch SQLite errors. For example, to -specifically handle constraint errors ([SQLITE_CONSTRAINT](https://sqlite.org/rescode.html#constraint)): - -```swift -do { - try db.run(users.insert(email <- "alice@mac.com")) - try db.run(users.insert(email <- "alice@mac.com")) -} catch let Result.error(message, code, statement) where code == SQLITE_CONSTRAINT { - print("constraint failed: \(message), in \(statement)") -} catch let error { - print("insertion failed: \(error)") -} -``` - -The `Result.error` type contains the English-language text that describes the error (`message`), -the error `code` (see [SQLite result code list](https://sqlite.org/rescode.html#primary_result_code_list) -for details) and a optional reference to the `statement` which produced the error. - -### Setters - -SQLite.swift typically uses the `<-` operator to set values during [inserts -](#inserting-rows) and [updates](#updating-rows). - -```swift -try db.run(counter.update(count <- 0)) -// UPDATE "counters" SET "count" = 0 WHERE ("id" = 1) -``` - -There are also a number of convenience setters that take the existing value -into account using native Swift operators. - -For example, to atomically increment a column, we can use `++`: - -```swift -try db.run(counter.update(count++)) // equivalent to `counter.update(count -> count + 1)` -// UPDATE "counters" SET "count" = "count" + 1 WHERE ("id" = 1) -``` - -To take an amount and “move” it via transaction, we can use `-=` and `+=`: - -```swift -let amount = 100.0 -try db.transaction { - try db.run(alice.update(balance -= amount)) - try db.run(betty.update(balance += amount)) -} -// BEGIN DEFERRED TRANSACTION -// UPDATE "users" SET "balance" = "balance" - 100.0 WHERE ("id" = 1) -// UPDATE "users" SET "balance" = "balance" + 100.0 WHERE ("id" = 2) -// COMMIT TRANSACTION -``` - - -###### Infix Setters - -| Operator | Types | -| -------- | ------------------ | -| `<-` | `Value -> Value` | -| `+=` | `Number -> Number` | -| `-=` | `Number -> Number` | -| `*=` | `Number -> Number` | -| `/=` | `Number -> Number` | -| `%=` | `Int -> Int` | -| `<<=` | `Int -> Int` | -| `>>=` | `Int -> Int` | -| `&=` | `Int -> Int` | -| `\|\|=` | `Int -> Int` | -| `^=` | `Int -> Int` | -| `+=` | `String -> String` | - - -###### Postfix Setters - -| Operator | Types | -| -------- | ------------ | -| `++` | `Int -> Int` | -| `--` | `Int -> Int` | - - -## Selecting Rows - -[Query structures](#queries) are `SELECT` statements waiting to happen. They -execute via [iteration](#iterating-and-accessing-values) and [other means -](#plucking-values) of sequence access. - - -### Iterating and Accessing Values - -Prepared [queries](#queries) execute lazily upon iteration. Each row is -returned as a `Row` object, which can be subscripted with a [column -expression](#expressions) matching one of the columns returned. - -```swift -for user in try db.prepare(users) { - print("id: \(user[id]), email: \(user[email]), name: \(user[name])") - // id: 1, email: alice@mac.com, name: Optional("Alice") -} -// SELECT * FROM "users" -``` - -`Expression` column values are _automatically unwrapped_ (we’ve made a -promise to the compiler that they’ll never be `NULL`), while `Expression` -values remain wrapped. - -⚠ Column subscripts on `Row` will force try and abort execution in error cases. -If you want to handle this yourself, use `Row.get(_ column: Expression)`: - -```swift -for user in try db.prepare(users) { - do { - print("name: \(try user.get(name))") - } catch { - // handle - } -} -``` - -### Plucking Rows - -We can pluck the first row by passing a query to the `pluck` function on a -database connection. - -```swift -if let user = try db.pluck(users) { /* ... */ } // Row -// SELECT * FROM "users" LIMIT 1 -``` - -To collect all rows into an array, we can simply wrap the sequence (though -this is not always the most memory-efficient idea). - -```swift -let all = Array(try db.prepare(users)) -// SELECT * FROM "users" -``` - - -### Building Complex Queries - -[Queries](#queries) have a number of chainable functions that can be used -(with [expressions](#expressions)) to add and modify [a number of -clauses](https://www.sqlite.org/lang_select.html) to the underlying -statement. - -```swift -let query = users.select(email) // SELECT "email" FROM "users" - .filter(name != nil) // WHERE "name" IS NOT NULL - .order(email.desc, name) // ORDER BY "email" DESC, "name" - .limit(5, offset: 1) // LIMIT 5 OFFSET 1 -``` - - -#### Selecting Columns - -By default, [queries](#queries) select every column of the result set (using -`SELECT *`). We can use the `select` function with a list of -[expressions](#expressions) to return specific columns instead. - -```swift -for user in try db.prepare(users.select(id, email)) { - print("id: \(user[id]), email: \(user[email])") - // id: 1, email: alice@mac.com -} -// SELECT "id", "email" FROM "users" -``` - -We can access the results of more complex expressions by holding onto a -reference of the expression itself. - -```swift -let sentence = name + " is " + cast(age) as Expression + " years old!" -for user in users.select(sentence) { - print(user[sentence]) - // Optional("Alice is 30 years old!") -} -// SELECT ((("name" || ' is ') || CAST ("age" AS TEXT)) || ' years old!') FROM "users" -``` - - -#### Joining Other Tables - -We can join tables using a [query’s](#queries) `join` function. - -```swift -users.join(posts, on: user_id == users[id]) -// SELECT * FROM "users" INNER JOIN "posts" ON ("user_id" = "users"."id") -``` - -The `join` function takes a [query](#queries) object (for the table being -joined on), a join condition (`on`), and is prefixed with an optional join -type (default: `.inner`). Join conditions can be built using [filter -operators and functions](#filter-operators-and-functions), generally require -[namespacing](#column-namespacing), and sometimes require -[aliasing](#table-aliasing). - - -##### Column Namespacing - -When joining tables, column names can become ambiguous. _E.g._, both tables -may have an `id` column. - -```swift -let query = users.join(posts, on: user_id == id) -// assertion failure: ambiguous column 'id' -``` - -We can disambiguate by namespacing `id`. - -```swift -let query = users.join(posts, on: user_id == users[id]) -// SELECT * FROM "users" INNER JOIN "posts" ON ("user_id" = "users"."id") -``` - -Namespacing is achieved by subscripting a [query](#queries) with a [column -expression](#expressions) (_e.g._, `users[id]` above becomes `users.id`). - -> _Note:_ We can namespace all of a table’s columns using `*`. -> -> ```swift -> let query = users.select(users[*]) -> // SELECT "users".* FROM "users" -> ``` - - -##### Table Aliasing - -Occasionally, we need to join a table to itself, in which case we must alias -the table with another name. We can achieve this using the -[query’s](#queries) `alias` function. - -```swift -let managers = users.alias("managers") - -let query = users.join(managers, on: managers[id] == users[managerId]) -// SELECT * FROM "users" -// INNER JOIN ("users") AS "managers" ON ("managers"."id" = "users"."manager_id") -``` - -If query results can have ambiguous column names, row values should be -accessed with namespaced [column expressions](#expressions). In the above -case, `SELECT *` immediately namespaces all columns of the result set. - -```swift -let user = try db.pluck(query) -user[id] // fatal error: ambiguous column 'id' - // (please disambiguate: ["users"."id", "managers"."id"]) - -user[users[id]] // returns "users"."id" -user[managers[id]] // returns "managers"."id" -``` - - -#### Filtering Rows - -SQLite.swift filters rows using a [query’s](#queries) `filter` function with -a boolean [expression](#expressions) (`Expression`). - -```swift -users.filter(id == 1) -// SELECT * FROM "users" WHERE ("id" = 1) - -users.filter([1, 2, 3, 4, 5].contains(id)) -// SELECT * FROM "users" WHERE ("id" IN (1, 2, 3, 4, 5)) - -users.filter(email.like("%@mac.com")) -// SELECT * FROM "users" WHERE ("email" LIKE '%@mac.com') - -users.filter(verified && name.lowercaseString == "alice") -// SELECT * FROM "users" WHERE ("verified" AND (lower("name") == 'alice')) - -users.filter(verified || balance >= 10_000) -// SELECT * FROM "users" WHERE ("verified" OR ("balance" >= 10000.0)) -``` - -We can build our own boolean expressions by using one of the many [filter -operators and functions](#filter-operators-and-functions). - -Instead of `filter` we can also use the `where` function which is an alias: - -```swift -users.where(id == 1) -// SELECT * FROM "users" WHERE ("id" = 1) -``` - -##### Filter Operators and Functions - -SQLite.swift defines a number of operators for building filtering predicates. -Operators and functions work together in a type-safe manner, so attempting to -equate or compare different types will prevent compilation. - - -###### Infix Filter Operators - -| Swift | Types | SQLite | -| ----- | -------------------------------- | -------------- | -| `==` | `Equatable -> Bool` | `=`/`IS`* | -| `!=` | `Equatable -> Bool` | `!=`/`IS NOT`* | -| `>` | `Comparable -> Bool` | `>` | -| `>=` | `Comparable -> Bool` | `>=` | -| `<` | `Comparable -> Bool` | `<` | -| `<=` | `Comparable -> Bool` | `<=` | -| `~=` | `(Interval, Comparable) -> Bool` | `BETWEEN` | -| `&&` | `Bool -> Bool` | `AND` | -| `\|\|`| `Bool -> Bool` | `OR` | - -> *When comparing against `nil`, SQLite.swift will use `IS` and `IS NOT` -> accordingly. - - -###### Prefix Filter Operators - -| Swift | Types | SQLite | -| ----- | ------------------ | ------ | -| `!` | `Bool -> Bool` | `NOT` | - - -###### Filtering Functions - -| Swift | Types | SQLite | -| ---------- | ----------------------- | ------- | -| `like` | `String -> Bool` | `LIKE` | -| `glob` | `String -> Bool` | `GLOB` | -| `match` | `String -> Bool` | `MATCH` | -| `contains` | `(Array, T) -> Bool` | `IN` | - - - - - -#### Sorting Rows - -We can pre-sort returned rows using the [query’s](#queries) `order` function. - -_E.g._, to return users sorted by `email`, then `name`, in ascending order: - -```swift -users.order(email, name) -// SELECT * FROM "users" ORDER BY "email", "name" -``` - -The `order` function takes a list of [column expressions](#expressions). - -`Expression` objects have two computed properties to assist sorting: `asc` -and `desc`. These properties append the expression with `ASC` and `DESC` to -mark ascending and descending order respectively. - -```swift -users.order(email.desc, name.asc) -// SELECT * FROM "users" ORDER BY "email" DESC, "name" ASC -``` - - -#### Limiting and Paging Results - -We can limit and skip returned rows using a [query’s](#queries) `limit` -function (and its optional `offset` parameter). - -```swift -users.limit(5) -// SELECT * FROM "users" LIMIT 5 - -users.limit(5, offset: 5) -// SELECT * FROM "users" LIMIT 5 OFFSET 5 -``` - - -#### Aggregation - -[Queries](#queries) come with a number of functions that quickly return -aggregate scalar values from the table. These mirror the [core aggregate -functions](#aggregate-sqlite-functions) and are executed immediately against -the query. - -```swift -let count = try db.scalar(users.count) -// SELECT count(*) FROM "users" -``` - -Filtered queries will appropriately filter aggregate values. - -```swift -let count = try db.scalar(users.filter(name != nil).count) -// SELECT count(*) FROM "users" WHERE "name" IS NOT NULL -``` - - - `count` as a computed property on a query (see examples above) returns - the total number of rows matching the query. - - `count` as a computed property on a column expression returns the total - number of rows where that column is not `NULL`. - - ```swift - let count = try db.scalar(users.select(name.count)) // -> Int - // SELECT count("name") FROM "users" - ``` - - - `max` takes a comparable column expression and returns the largest value - if any exists. - - ```swift - let max = try db.scalar(users.select(id.max)) // -> Int64? - // SELECT max("id") FROM "users" - ``` - - - `min` takes a comparable column expression and returns the smallest value - if any exists. - - ```swift - let min = try db.scalar(users.select(id.min)) // -> Int64? - // SELECT min("id") FROM "users" - ``` - - - `average` takes a numeric column expression and returns the average row - value (as a `Double`) if any exists. - - ```swift - let average = try db.scalar(users.select(balance.average)) // -> Double? - // SELECT avg("balance") FROM "users" - ``` - - - `sum` takes a numeric column expression and returns the sum total of all - rows if any exist. - - ```swift - let sum = try db.scalar(users.select(balance.sum)) // -> Double? - // SELECT sum("balance") FROM "users" - ``` - - - `total`, like `sum`, takes a numeric column expression and returns the - sum total of all rows, but in this case always returns a `Double`, and - returns `0.0` for an empty query. - - ```swift - let total = try db.scalar(users.select(balance.total)) // -> Double - // SELECT total("balance") FROM "users" - ``` - -> _Note:_ Expressions can be prefixed with a `DISTINCT` clause by calling the -> `distinct` computed property. -> -> ```swift -> let count = try db.scalar(users.select(name.distinct.count) // -> Int -> // SELECT count(DISTINCT "name") FROM "users" -> ``` - - -## Updating Rows - -We can update a table’s rows by calling a [query’s](#queries) `update` -function with a list of [setters](#setters)—typically [typed column -expressions](#expressions) and values (which can also be expressions)—each -joined by the `<-` operator. - -When an unscoped query calls `update`, it will update _every_ row in the -table. - -```swift -try db.run(users.update(email <- "alice@me.com")) -// UPDATE "users" SET "email" = 'alice@me.com' -``` - -Be sure to scope `UPDATE` statements beforehand using [the `filter` function -](#filtering-rows). - -```swift -let alice = users.filter(id == 1) -try db.run(alice.update(email <- "alice@me.com")) -// UPDATE "users" SET "email" = 'alice@me.com' WHERE ("id" = 1) -``` - -The `update` function returns an `Int` representing the number of updated -rows. - -```swift -do { - if try db.run(alice.update(email <- "alice@me.com")) > 0 { - print("updated alice") - } else { - print("alice not found") - } -} catch { - print("update failed: \(error)") -} -``` - - -## Deleting Rows - -We can delete rows from a table by calling a [query’s](#queries) `delete` -function. - -When an unscoped query calls `delete`, it will delete _every_ row in the -table. - -```swift -try db.run(users.delete()) -// DELETE FROM "users" -``` - -Be sure to scope `DELETE` statements beforehand using -[the `filter` function](#filtering-rows). - -```swift -let alice = users.filter(id == 1) -try db.run(alice.delete()) -// DELETE FROM "users" WHERE ("id" = 1) -``` - -The `delete` function returns an `Int` representing the number of deleted -rows. - -```swift -do { - if try db.run(alice.delete()) > 0 { - print("deleted alice") - } else { - print("alice not found") - } -} catch { - print("delete failed: \(error)") -} -``` - - -## Transactions and Savepoints - -Using the `transaction` and `savepoint` functions, we can run a series of -statements in a transaction. If a single statement fails or the block throws -an error, the changes will be rolled back. - -```swift -try db.transaction { - let rowid = try db.run(users.insert(email <- "betty@icloud.com")) - try db.run(users.insert(email <- "cathy@icloud.com", managerId <- rowid)) -} -// BEGIN DEFERRED TRANSACTION -// INSERT INTO "users" ("email") VALUES ('betty@icloud.com') -// INSERT INTO "users" ("email", "manager_id") VALUES ('cathy@icloud.com', 2) -// COMMIT TRANSACTION -``` - -> _Note:_ Transactions run in a serial queue. - - -## Altering the Schema - -SQLite.swift comes with several functions (in addition to `Table.create`) for -altering a database schema in a type-safe manner. - - -### Renaming Tables - -We can build an `ALTER TABLE … RENAME TO` statement by calling the `rename` -function on a `Table` or `VirtualTable`. - -```swift -try db.run(users.rename(Table("users_old"))) -// ALTER TABLE "users" RENAME TO "users_old" -``` - - -### Adding Columns - -We can add columns to a table by calling `addColumn` function on a `Table`. -SQLite.swift enforces -[the same limited subset](https://www.sqlite.org/lang_altertable.html) of -`ALTER TABLE` that SQLite supports. - -```swift -try db.run(users.addColumn(suffix)) -// ALTER TABLE "users" ADD COLUMN "suffix" TEXT -``` - - -#### Added Column Constraints - -The `addColumn` function shares several of the same [`column` function -parameters](#column-constraints) used when [creating -tables](#creating-a-table). - - - `check` attaches a `CHECK` constraint to a column definition in the form - of a boolean expression (`Expression`). (See also the `check` - function under [Table Constraints](#table-constraints).) - - ```swift - try db.run(users.addColumn(suffix, check: ["JR", "SR"].contains(suffix))) - // ALTER TABLE "users" ADD COLUMN "suffix" TEXT CHECK ("suffix" IN ('JR', 'SR')) - ``` - - - `defaultValue` adds a `DEFAULT` clause to a column definition and _only_ - accepts a value matching the column’s type. This value is used if none is - explicitly provided during [an `INSERT`](#inserting-rows). - - ```swift - try db.run(users.addColumn(suffix, defaultValue: "SR")) - // ALTER TABLE "users" ADD COLUMN "suffix" TEXT DEFAULT 'SR' - ``` - - > _Note:_ Unlike the [`CREATE TABLE` constraint](#table-constraints), - > default values may not be expression structures (including - > `CURRENT_TIME`, `CURRENT_DATE`, or `CURRENT_TIMESTAMP`). - - - `collate` adds a `COLLATE` clause to `Expression` (and - `Expression`) column definitions with [a collating - sequence](https://www.sqlite.org/datatype3.html#collation) defined in the - `Collation` enumeration. - - ```swift - try db.run(users.addColumn(email, collate: .nocase)) - // ALTER TABLE "users" ADD COLUMN "email" TEXT NOT NULL COLLATE "NOCASE" - - try db.run(users.addColumn(name, collate: .rtrim)) - // ALTER TABLE "users" ADD COLUMN "name" TEXT COLLATE "RTRIM" - ``` - - - `references` adds a `REFERENCES` clause to `Int64` (and `Int64?`) column - definitions and accepts a table or namespaced column expression. (See the - `foreignKey` function under [Table Constraints](#table-constraints) for - non-integer foreign key support.) - - ```swift - try db.run(posts.addColumn(userId, references: users, id) - // ALTER TABLE "posts" ADD COLUMN "user_id" INTEGER REFERENCES "users" ("id") - ``` - - -### Indexes - - -#### Creating Indexes - -We can build -[`CREATE INDEX` statements](https://www.sqlite.org/lang_createindex.html) -by calling the `createIndex` function on a `SchemaType`. - -```swift -try db.run(users.createIndex(email)) -// CREATE INDEX "index_users_on_email" ON "users" ("email") -``` - -The index name is generated automatically based on the table and column -names. - -The `createIndex` function has a couple default parameters we can override. - - - `unique` adds a `UNIQUE` constraint to the index. Default: `false`. - - ```swift - try db.run(users.createIndex(email, unique: true)) - // CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email") - ``` - - - `ifNotExists` adds an `IF NOT EXISTS` clause to the `CREATE TABLE` - statement (which will bail out gracefully if the table already exists). - Default: `false`. - - ```swift - try db.run(users.createIndex(email, ifNotExists: true)) - // CREATE INDEX IF NOT EXISTS "index_users_on_email" ON "users" ("email") - ``` - - -#### Dropping Indexes - -We can build -[`DROP INDEX` statements](https://www.sqlite.org/lang_dropindex.html) by -calling the `dropIndex` function on a `SchemaType`. - -```swift -try db.run(users.dropIndex(email)) -// DROP INDEX "index_users_on_email" -``` - -The `dropIndex` function has one additional parameter, `ifExists`, which -(when `true`) adds an `IF EXISTS` clause to the statement. - -```swift -try db.run(users.dropIndex(email, ifExists: true)) -// DROP INDEX IF EXISTS "index_users_on_email" -``` - - -### Dropping Tables - -We can build -[`DROP TABLE` statements](https://www.sqlite.org/lang_droptable.html) -by calling the `dropTable` function on a `SchemaType`. - -```swift -try db.run(users.drop()) -// DROP TABLE "users" -``` - -The `drop` function has one additional parameter, `ifExists`, which (when -`true`) adds an `IF EXISTS` clause to the statement. - -```swift -try db.run(users.drop(ifExists: true)) -// DROP TABLE IF EXISTS "users" -``` - - -### Migrations and Schema Versioning - -You can add a convenience property on `Connection` to query and set the -[`PRAGMA user_version`](https://sqlite.org/pragma.html#pragma_user_version). - -This is a great way to manage your schema’s version over migrations. - -```swift -extension Connection { - public var userVersion: Int32 { - get { return Int32(try! scalar("PRAGMA user_version") as! Int64)} - set { try! run("PRAGMA user_version = \(newValue)") } - } -} -``` - -Then you can conditionally run your migrations along the lines of: - -```swift -if db.userVersion == 0 { - // handle first migration - db.userVersion = 1 -} -if db.userVersion == 1 { - // handle second migration - db.userVersion = 2 -} -``` - -For more complex migration requirements check out the schema management -system [SQLiteMigrationManager.swift][]. - -## Custom Types - -SQLite.swift supports serializing and deserializing any custom type as long -as it conforms to the `Value` protocol. - -```swift -protocol Value { - typealias Datatype: Binding - class var declaredDatatype: String { get } - class func fromDatatypeValue(datatypeValue: Datatype) -> Self - var datatypeValue: Datatype { get } -} -``` - -The `Datatype` must be one of the basic Swift types that values are bridged -through before serialization and deserialization (see [Building Type-Safe SQL -](#building-type-safe-sql) for a list of types). - -> ⚠ _Note:_ `Binding` is a protocol that SQLite.swift uses internally to -> directly map SQLite types to Swift types. **Do _not_** conform custom types -> to the `Binding` protocol. - - -### Date-Time Values - -In SQLite, `DATETIME` columns can be treated as strings or numbers, so we can -transparently bridge `Date` objects through Swift’s `String` types. - -We can use these types directly in SQLite statements. - -```swift -let published_at = Expression("published_at") - -let published = posts.filter(published_at <= Date()) -// SELECT * FROM "posts" WHERE "published_at" <= '2014-11-18T12:45:30.000' - -let startDate = Date(timeIntervalSince1970: 0) -let published = posts.filter(startDate...Date() ~= published_at) -// SELECT * FROM "posts" WHERE "published_at" BETWEEN '1970-01-01T00:00:00.000' AND '2014-11-18T12:45:30.000' -``` - - -### Binary Data - -We can bridge any type that can be initialized from and encoded to `Data`. - -```swift -extension UIImage: Value { - public class var declaredDatatype: String { - return Blob.declaredDatatype - } - public class func fromDatatypeValue(blobValue: Blob) -> UIImage { - return UIImage(data: Data.fromDatatypeValue(blobValue))! - } - public var datatypeValue: Blob { - return UIImagePNGRepresentation(self)!.datatypeValue - } - -} -``` - -> _Note:_ See the [Archives and Serializations Programming Guide][] for more -> information on encoding and decoding custom types. - - -[Archives and Serializations Programming Guide]: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Archiving.html - -## Codable Types - -[Codable types][Encoding and Decoding Custom Types] were introduced as a part -of Swift 4 to allow serializing and deserializing types. SQLite.swift supports -the insertion, updating, and retrieval of basic Codable types. - -[Encoding and Decoding Custom Types]: https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types - -### Inserting Codable Types - -Queries have a method to allow inserting an [Encodable][] type. - -```swift -struct User: Encodable { - let name: String -} -try db.run(users.insert(User(name: "test"))) - -``` - -There are two other parameters also available to this method: - -- `userInfo` is a dictionary that is passed to the encoder and made available - to encodable types to allow customizing their behavior. - -- `otherSetters` allows you to specify additional setters on top of those - that are generated from the encodable types themselves. - -[Encodable]: https://developer.apple.com/documentation/swift/encodable - -### Updating Codable Types - -Queries have a method to allow updating an Encodable type. - -```swift -try db.run(users.filter(id == userId).update(user)) - -``` - -> ⚠ Unless filtered, using the update method on an instance of a Codable -> type updates all table rows. - -There are two other parameters also available to this method: - -- `userInfo` is a dictionary that is passed to the encoder and made available - to encodable types to allow customizing their behavior. - -- `otherSetters` allows you to specify additional setters on top of those - that are generated from the encodable types themselves. - -### Retrieving Codable Types - -Rows have a method to decode a [Decodable][] type. - -```swift -let loadedUsers: [User] = try db.prepare(users).map { row in - return try row.decode() -} -``` - -You can also create a decoder to use manually yourself. This can be useful -for example if you are using the -[Facade pattern](https://en.wikipedia.org/wiki/Facade_pattern) to hide -subclasses behind a super class. For example, you may want to encode an Image -type that can be multiple different formats such as PNGImage, JPGImage, or -HEIFImage. You will need to determine the correct subclass before you know -which type to decode. - -```swift -enum ImageCodingKeys: String, CodingKey { - case kind -} - -enum ImageKind: Int, Codable { - case png, jpg, heif -} - -let loadedImages: [Image] = try db.prepare(images).map { row in - let decoder = row.decoder() - let container = try decoder.container(keyedBy: ImageCodingKeys.self) - switch try container.decode(ImageKind.self, forKey: .kind) { - case .png: - return try PNGImage(from: decoder) - case .jpg: - return try JPGImage(from: decoder) - case .heif: - return try HEIFImage(from: decoder) - } -} -``` - -Both of the above methods also have the following optional parameter: - -- `userInfo` is a dictionary that is passed to the decoder and made available - to decodable types to allow customizing their behavior. - -[Decodable]: https://developer.apple.com/documentation/swift/decodable - -### Restrictions - -There are a few restrictions on using Codable types: - -- The encodable and decodable objects can only use the following types: - - Int, Bool, Float, Double, String - - Nested Codable types that will be encoded as JSON to a single column -- These methods will not handle object relationships for you. You must write - your own Codable and Decodable implementations if you wish to support this. -- The Codable types may not try to access nested containers or nested unkeyed - containers -- The Codable types may not access single value containers or unkeyed - containers -- The Codable types may not access super decoders or encoders - -## Other Operators - -In addition to [filter operators](#filtering-infix-operators), SQLite.swift -defines a number of operators that can modify expression values with -arithmetic, bitwise operations, and concatenation. - - -###### Other Infix Operators - -| Swift | Types | SQLite | -| ----- | -------------------------------- | -------- | -| `+` | `Number -> Number` | `+` | -| `-` | `Number -> Number` | `-` | -| `*` | `Number -> Number` | `*` | -| `/` | `Number -> Number` | `/` | -| `%` | `Int -> Int` | `%` | -| `<<` | `Int -> Int` | `<<` | -| `>>` | `Int -> Int` | `>>` | -| `&` | `Int -> Int` | `&` | -| `\|` | `Int -> Int` | `\|` | -| `+` | `String -> String` | `\|\|` | - -> _Note:_ SQLite.swift also defines a bitwise XOR operator, `^`, which -> expands the expression `lhs ^ rhs` to `~(lhs & rhs) & (lhs | rhs)`. - - -###### Other Prefix Operators - -| Swift | Types | SQLite | -| ----- | ------------------ | ------ | -| `~` | `Int -> Int` | `~` | -| `-` | `Number -> Number` | `-` | - - -## Core SQLite Functions - -Many of SQLite’s [core functions](https://www.sqlite.org/lang_corefunc.html) -have been surfaced in and type-audited for SQLite.swift. - -> _Note:_ SQLite.swift aliases the `??` operator to the `ifnull` function. -> -> ```swift -> name ?? email // ifnull("name", "email") -> ``` - - -## Aggregate SQLite Functions - -Most of SQLite’s -[aggregate functions](https://www.sqlite.org/lang_aggfunc.html) have been -surfaced in and type-audited for SQLite.swift. - -## Date and Time functions - -SQLite's [date and time](https://www.sqlite.org/lang_datefunc.html) -functions are available: - -```swift -DateFunctions.date("now") -// date('now') -Date().date -// date('2007-01-09T09:41:00.000') -Expression("date").date -// date("date") -``` - -## Custom SQL Functions - -We can create custom SQL functions by calling `createFunction` on a database -connection. - -For example, to give queries access to -[`MobileCoreServices.UTTypeConformsTo`][UTTypeConformsTo], we can -write the following: - -```swift -import MobileCoreServices - -let typeConformsTo: (Expression, Expression) -> Expression = ( - try db.createFunction("typeConformsTo", deterministic: true) { UTI, conformsToUTI in - return UTTypeConformsTo(UTI, conformsToUTI) - } -) -``` - -> _Note:_ The optional `deterministic` parameter is an optimization that -> causes the function to be created with -> [`SQLITE_DETERMINISTIC`](https://www.sqlite.org/c3ref/c_deterministic.html). - -Note `typeConformsTo`’s signature: - -```swift -(Expression, Expression) -> Expression -``` - -Because of this, `createFunction` expects a block with the following -signature: - -```swift -(String, String) -> Bool -``` - -Once assigned, the closure can be called wherever boolean expressions are -accepted. - -```swift -let attachments = Table("attachments") -let UTI = Expression("UTI") - -let images = attachments.filter(typeConformsTo(UTI, kUTTypeImage)) -// SELECT * FROM "attachments" WHERE "typeConformsTo"("UTI", 'public.image') -``` - -> _Note:_ The return type of a function must be -> [a core SQL type](#building-type-safe-sql) or [conform to `Value`](#custom-types). - -We can create loosely-typed functions by handling an array of raw arguments, -instead. - -```swift -db.createFunction("typeConformsTo", deterministic: true) { args in - guard let UTI = args[0] as? String, conformsToUTI = args[1] as? String else { return nil } - return UTTypeConformsTo(UTI, conformsToUTI) -} -``` - -Creating a loosely-typed function cannot return a closure and instead must be -wrapped manually or executed [using raw SQL](#executing-arbitrary-sql). - -```swift -let stmt = try db.prepare("SELECT * FROM attachments WHERE typeConformsTo(UTI, ?)") -for row in stmt.bind(kUTTypeImage) { /* ... */ } -``` - -[UTTypeConformsTo]: https://developer.apple.com/documentation/coreservices/1444079-uttypeconformsto - -## Custom Collations - -We can create custom collating sequences by calling `createCollation` on a -database connection. - -```swift -try db.createCollation("NODIACRITIC") { lhs, rhs in - return lhs.compare(rhs, options: .diacriticInsensitiveSearch) -} -``` - -We can reference a custom collation using the `Custom` member of the -`Collation` enumeration. - -```swift -restaurants.order(collate(.custom("NODIACRITIC"), name)) -// SELECT * FROM "restaurants" ORDER BY "name" COLLATE "NODIACRITIC" -``` - - -## Full-text Search - -We can create a virtual table using the [FTS4 -module](http://www.sqlite.org/fts3.html) by calling `create` on a -`VirtualTable`. - -```swift -let emails = VirtualTable("emails") -let subject = Expression("subject") -let body = Expression("body") - -try db.run(emails.create(.FTS4(subject, body))) -// CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body") -``` - -We can specify a [tokenizer](http://www.sqlite.org/fts3.html#tokenizer) using the `tokenize` parameter. - -```swift -try db.run(emails.create(.FTS4([subject, body], tokenize: .Porter))) -// CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body", tokenize=porter) -``` - -We can set the full range of parameters by creating a `FTS4Config` object. - -```swift -let emails = VirtualTable("emails") -let subject = Expression("subject") -let body = Expression("body") -let config = FTS4Config() - .column(subject) - .column(body, [.unindexed]) - .languageId("lid") - .order(.desc) - -try db.run(emails.create(.FTS4(config)) -// CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body", notindexed="body", languageid="lid", order="desc") -``` - -Once we insert a few rows, we can search using the `match` function, which -takes a table or column as its first argument and a query string as its -second. - -```swift -try db.run(emails.insert( - subject <- "Just Checking In", - body <- "Hey, I was just wondering...did you get my last email?" -)) - -let wonderfulEmails: QueryType = emails.match("wonder*") -// SELECT * FROM "emails" WHERE "emails" MATCH 'wonder*' - -let replies = emails.filter(subject.match("Re:*")) -// SELECT * FROM "emails" WHERE "subject" MATCH 'Re:*' -``` - -### FTS5 - -When linking against a version of SQLite with -[FTS5](http://www.sqlite.org/fts5.html) enabled we can create the virtual -table in a similar fashion. - -```swift -let emails = VirtualTable("emails") -let subject = Expression("subject") -let body = Expression("body") -let config = FTS5Config() - .column(subject) - .column(body, [.unindexed]) - -try db.run(emails.create(.FTS5(config)) -// CREATE VIRTUAL TABLE "emails" USING fts5("subject", "body" UNINDEXED) - -// Note that FTS5 uses a different syntax to select columns, so we need to rewrite -// the last FTS4 query above as: -let replies = emails.filter(emails.match("subject:\"Re:\"*)) -// SELECT * FROM "emails" WHERE "emails" MATCH 'subject:"Re:"*' - -// https://www.sqlite.org/fts5.html#_changes_to_select_statements_ -``` - -## Executing Arbitrary SQL - -Though we recommend you stick with SQLite.swift’s -[type-safe system](#building-type-safe-sql) whenever possible, it is possible -to simply and safely prepare and execute raw SQL statements via a `Database` connection -using the following functions. - - - `execute` runs an arbitrary number of SQL statements as a convenience. - - ```swift - try db.execute(""" - BEGIN TRANSACTION; - CREATE TABLE users ( - id INTEGER PRIMARY KEY NOT NULL, - email TEXT UNIQUE NOT NULL, - name TEXT - ); - CREATE TABLE posts ( - id INTEGER PRIMARY KEY NOT NULL, - title TEXT NOT NULL, - body TEXT NOT NULL, - published_at DATETIME - ); - PRAGMA user_version = 1; - COMMIT TRANSACTION; - """ - ) - ``` - - - `prepare` prepares a single `Statement` object from a SQL string, - optionally binds values to it (using the statement’s `bind` function), - and returns the statement for deferred execution. - - ```swift - let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)") - ``` - - Once prepared, statements may be executed using `run`, binding any - unbound parameters. - - ```swift - try stmt.run("alice@mac.com") - db.changes // -> {Some 1} - ``` - - Statements with results may be iterated over, using the columnNames if - useful. - - ```swift - let stmt = try db.prepare("SELECT id, email FROM users") - for row in stmt { - for (index, name) in stmt.columnNames.enumerated() { - print ("\(name):\(row[index]!)") - // id: Optional(1), email: Optional("alice@mac.com") - } - } - ``` - - - `run` prepares a single `Statement` object from a SQL string, optionally - binds values to it (using the statement’s `bind` function), executes, - and returns the statement. - - ```swift - try db.run("INSERT INTO users (email) VALUES (?)", "alice@mac.com") - ``` - - - `scalar` prepares a single `Statement` object from a SQL string, - optionally binds values to it (using the statement’s `bind` function), - executes, and returns the first value of the first row. - - ```swift - let count = try db.scalar("SELECT count(*) FROM users") as! Int64 - ``` - - Statements also have a `scalar` function, which can optionally re-bind - values at execution. - - ```swift - let stmt = try db.prepare("SELECT count (*) FROM users") - let count = try stmt.scalar() as! Int64 - ``` - - -## Logging - -We can log SQL using the database’s `trace` function. - -```swift -#if DEBUG - db.trace { print($0) } -#endif -``` - - -[ROWID]: https://sqlite.org/lang_createtable.html#rowid -[SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift diff --git a/ios/libs/Sqlite/Documentation/Planning.md b/ios/libs/Sqlite/Documentation/Planning.md deleted file mode 100755 index 5f885de..0000000 --- a/ios/libs/Sqlite/Documentation/Planning.md +++ /dev/null @@ -1,38 +0,0 @@ -# SQLite.swift Planning - -This document captures both near term steps (aka Roadmap) and feature -requests. The goal is to add some visibility and guidance for future -additions and Pull Requests, as well as to keep the Issues list clear of -enhancement requests so that bugs are more visible. - -> ⚠ This document is currently not actively maintained. See -> the [0.13.0 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.0) -> on Github for additional information about planned features for the next release. - -## Roadmap - -_Lists agreed upon next steps in approximate priority order._ - -## Feature Requests - -_A gathering point for ideas for new features. In general, the corresponding -issue will be closed once it is added here, with the assumption that it will -be referred to when it comes time to add the corresponding feature._ - -### Features - - * encapsulate ATTACH DATABASE / DETACH DATABASE as methods, per - [#30](https://github.com/stephencelis/SQLite.swift/issues/30) - * provide separate threads for update vs read, so updates don't block reads, - per [#236](https://github.com/stephencelis/SQLite.swift/issues/236) - * expose triggers, per - [#164](https://github.com/stephencelis/SQLite.swift/issues/164) - -## Suspended Feature Requests - -_Features that are not actively being considered, perhaps because of no clean -type-safe way to implement them with the current Swift, or bugs, or just -general uncertainty._ - - * provide a mechanism for INSERT INTO multiple values, per - [#168](https://github.com/stephencelis/SQLite.swift/issues/168) diff --git a/ios/libs/Sqlite/Documentation/Resources/installation@2x.png b/ios/libs/Sqlite/Documentation/Resources/installation@2x.png deleted file mode 100755 index 6b31f45..0000000 Binary files a/ios/libs/Sqlite/Documentation/Resources/installation@2x.png and /dev/null differ diff --git a/ios/libs/Sqlite/Documentation/Resources/playground@2x.png b/ios/libs/Sqlite/Documentation/Resources/playground@2x.png deleted file mode 100755 index 32646d6..0000000 Binary files a/ios/libs/Sqlite/Documentation/Resources/playground@2x.png and /dev/null differ diff --git a/ios/libs/Sqlite/LICENSE.txt b/ios/libs/Sqlite/LICENSE.txt deleted file mode 100755 index 13303c1..0000000 --- a/ios/libs/Sqlite/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -(The MIT License) - -Copyright (c) 2014-2015 Stephen Celis () - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/ios/libs/Sqlite/Makefile b/ios/libs/Sqlite/Makefile deleted file mode 100755 index 50d0714..0000000 --- a/ios/libs/Sqlite/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -BUILD_TOOL = xcodebuild -BUILD_SCHEME = SQLite Mac -IOS_SIMULATOR = iPhone XS -IOS_VERSION = 12.2 -ifeq ($(BUILD_SCHEME),SQLite iOS) - BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)" -else - BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -endif - -XCPRETTY := $(shell command -v xcpretty) -SWIFTCOV := $(shell command -v swiftcov) -GCOVR := $(shell command -v gcovr) -TEST_ACTIONS := clean build build-for-testing test-without-building - -default: test - -build: - $(BUILD_TOOL) $(BUILD_ARGUMENTS) - -test: -ifdef XCPRETTY - @set -o pipefail && $(BUILD_TOOL) $(BUILD_ARGUMENTS) $(TEST_ACTIONS) | $(XCPRETTY) -c -else - $(BUILD_TOOL) $(BUILD_ARGUMENTS) $(TEST_ACTIONS) -endif - -coverage: -ifdef SWIFTCOV - $(SWIFTCOV) generate --output coverage \ - $(BUILD_TOOL) $(BUILD_ARGUMENTS) -configuration Release test \ - -- ./SQLite/*.swift -ifdef GCOVR - $(GCOVR) \ - --root . \ - --use-gcov-files \ - --html \ - --html-details \ - --output coverage/index.html \ - --keep -else - @echo gcovr must be installed for HTML output: https://github.com/gcovr/gcovr -endif -else - @echo swiftcov must be installed for coverage: https://github.com/realm/SwiftCov - @exit 1 -endif - -clean: - $(BUILD_TOOL) $(BUILD_ARGUMENTS) clean - rm -r coverage - -repl: - @$(BUILD_TOOL) $(BUILD_ARGUMENTS) -derivedDataPath $(TMPDIR)/SQLite.swift > /dev/null && \ - swift -F '$(TMPDIR)/SQLite.swift/Build/Products/Debug' - -sloc: - @zsh -c "grep -vE '^ *//|^$$' SQLite/*/*.{swift,h,m} | wc -l" - -.PHONY: test coverage clean repl sloc diff --git a/ios/libs/Sqlite/Package.swift b/ios/libs/Sqlite/Package.swift deleted file mode 100755 index 430ae6f..0000000 --- a/ios/libs/Sqlite/Package.swift +++ /dev/null @@ -1,24 +0,0 @@ -// swift-tools-version:4.0 -import PackageDescription - -let package = Package( - name: "SQLite.swift", - products: [.library(name: "SQLite", targets: ["SQLite"])], - targets: [ - .target(name: "SQLite", dependencies: ["SQLiteObjc"]), - .target(name: "SQLiteObjc"), - .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests") - ], - swiftLanguageVersions: [4, 5] -) - -#if os(Linux) - package.dependencies = [.package(url: "https://github.com/stephencelis/CSQLite.git", from: "0.0.3")] - package.targets = [ - .target(name: "SQLite", exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]), - .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests", exclude: [ - "FTS4Tests.swift", - "FTS5Tests.swift" - ]) - ] -#endif diff --git a/ios/libs/Sqlite/README.md b/ios/libs/Sqlite/README.md deleted file mode 100755 index b7a18e0..0000000 --- a/ios/libs/Sqlite/README.md +++ /dev/null @@ -1,293 +0,0 @@ -# SQLite.swift - -[![Build Status][TravisBadge]][TravisLink] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift5 compatible][Swift5Badge]][Swift5Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink] - -A type-safe, [Swift][]-language layer over [SQLite3][]. - -[SQLite.swift][] provides compile-time confidence in SQL statement -syntax _and_ intent. - -## Features - - - A pure-Swift interface - - A type-safe, optional-aware SQL expression builder - - A flexible, chainable, lazy-executing query layer - - Automatically-typed data access - - A lightweight, uncomplicated query and parameter binding interface - - Developer-friendly error handling and debugging - - [Full-text search][] support - - [Well-documented][See Documentation] - - Extensively tested - - [SQLCipher][] support via CocoaPods - - Active support at - [StackOverflow](http://stackoverflow.com/questions/tagged/sqlite.swift), - and [Gitter Chat Room](https://gitter.im/stephencelis/SQLite.swift) - (_experimental_) - -[SQLCipher]: https://www.zetetic.net/sqlcipher/ -[Full-text search]: Documentation/Index.md#full-text-search -[See Documentation]: Documentation/Index.md#sqliteswift-documentation - - -## Usage - -```swift -import SQLite - -let db = try Connection("path/to/db.sqlite3") - -let users = Table("users") -let id = Expression("id") -let name = Expression("name") -let email = Expression("email") - -try db.run(users.create { t in - t.column(id, primaryKey: true) - t.column(name) - t.column(email, unique: true) -}) -// CREATE TABLE "users" ( -// "id" INTEGER PRIMARY KEY NOT NULL, -// "name" TEXT, -// "email" TEXT NOT NULL UNIQUE -// ) - -let insert = users.insert(name <- "Alice", email <- "alice@mac.com") -let rowid = try db.run(insert) -// INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice@mac.com') - -for user in try db.prepare(users) { - print("id: \(user[id]), name: \(user[name]), email: \(user[email])") - // id: 1, name: Optional("Alice"), email: alice@mac.com -} -// SELECT * FROM "users" - -let alice = users.filter(id == rowid) - -try db.run(alice.update(email <- email.replace("mac.com", with: "me.com"))) -// UPDATE "users" SET "email" = replace("email", 'mac.com', 'me.com') -// WHERE ("id" = 1) - -try db.run(alice.delete()) -// DELETE FROM "users" WHERE ("id" = 1) - -try db.scalar(users.count) // 0 -// SELECT count(*) FROM "users" -``` - -SQLite.swift also works as a lightweight, Swift-friendly wrapper over the C -API. - -```swift -let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)") -for email in ["betty@icloud.com", "cathy@icloud.com"] { - try stmt.run(email) -} - -db.totalChanges // 3 -db.changes // 1 -db.lastInsertRowid // 3 - -for row in try db.prepare("SELECT id, email FROM users") { - print("id: \(row[0]), email: \(row[1])") - // id: Optional(2), email: Optional("betty@icloud.com") - // id: Optional(3), email: Optional("cathy@icloud.com") -} - -try db.scalar("SELECT count(*) FROM users") // 2 -``` - -[Read the documentation][See Documentation] or explore more, -interactively, from the Xcode project’s playground. - -![SQLite.playground Screen Shot](Documentation/Resources/playground@2x.png) - -For a more comprehensive example, see -[this article][Create a Data Access Layer with SQLite.swift and Swift 2] -and the [companion repository][SQLiteDataAccessLayer2]. - - -[Create a Data Access Layer with SQLite.swift and Swift 2]: http://masteringswift.blogspot.com/2015/09/create-data-access-layer-with.html -[SQLiteDataAccessLayer2]: https://github.com/hoffmanjon/SQLiteDataAccessLayer2/tree/master - -## Installation - -> _Note:_ Version 0.12 requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.2) or greater. Version 0.11.6 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1) or greater. - -### Carthage - -[Carthage][] is a simple, decentralized dependency manager for Cocoa. To -install SQLite.swift with Carthage: - - 1. Make sure Carthage is [installed][Carthage Installation]. - - 2. Update your Cartfile to include the following: - - ```ruby - github "stephencelis/SQLite.swift" ~> 0.12.0 - ``` - - 3. Run `carthage update` and - [add the appropriate framework][Carthage Usage]. - - -[Carthage]: https://github.com/Carthage/Carthage -[Carthage Installation]: https://github.com/Carthage/Carthage#installing-carthage -[Carthage Usage]: https://github.com/Carthage/Carthage#adding-frameworks-to-an-application - - -### CocoaPods - -[CocoaPods][] is a dependency manager for Cocoa projects. To install -SQLite.swift with CocoaPods: - - 1. Make sure CocoaPods is [installed][CocoaPods Installation]. (SQLite.swift - requires version 1.6.1 or greater.) - - ```sh - # Using the default Ruby install will require you to use sudo when - # installing and updating gems. - [sudo] gem install cocoapods - ``` - - 2. Update your Podfile to include the following: - - ```ruby - use_frameworks! - - target 'YourAppTargetName' do - pod 'SQLite.swift', '~> 0.12.0' - end - ``` - - 3. Run `pod install --repo-update`. - -[CocoaPods]: https://cocoapods.org -[CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started - -### Swift Package Manager - -The [Swift Package Manager][] is a tool for managing the distribution of -Swift code. - -1. Add the following to your `Package.swift` file: - - ```swift - dependencies: [ - .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0") - ] - ``` - -2. Build your project: - - ```sh - $ swift build - ``` - -[Swift Package Manager]: https://swift.org/package-manager - -### Manual - -To install SQLite.swift as an Xcode sub-project: - - 1. Drag the **SQLite.xcodeproj** file into your own project. - ([Submodule][], clone, or [download][] the project first.) - - ![Installation Screen Shot](Documentation/Resources/installation@2x.png) - - 2. In your target’s **General** tab, click the **+** button under **Linked - Frameworks and Libraries**. - - 3. Select the appropriate **SQLite.framework** for your platform. - - 4. **Add**. - -Some additional steps are required to install the application on an actual -device: - - 5. In the **General** tab, click the **+** button under **Embedded - Binaries**. - - 6. Select the appropriate **SQLite.framework** for your platform. - - 7. **Add**. - - -[Xcode]: https://developer.apple.com/xcode/downloads/ -[Submodule]: http://git-scm.com/book/en/Git-Tools-Submodules -[download]: https://github.com/stephencelis/SQLite.swift/archive/master.zip - - -## Communication - -[See the planning document] for a roadmap and existing feature requests. - -[Read the contributing guidelines][]. The _TL;DR_ (but please; _R_): - - - Need **help** or have a **general question**? [Ask on Stack - Overflow][] (tag `sqlite.swift`). - - Found a **bug** or have a **feature request**? [Open an issue][]. - - Want to **contribute**? [Submit a pull request][]. - -[See the planning document]: /Documentation/Planning.md -[Read the contributing guidelines]: ./CONTRIBUTING.md#contributing -[Ask on Stack Overflow]: http://stackoverflow.com/questions/tagged/sqlite.swift -[Open an issue]: https://github.com/stephencelis/SQLite.swift/issues/new -[Submit a pull request]: https://github.com/stephencelis/SQLite.swift/fork - - -## Author - - - [Stephen Celis](mailto:stephen@stephencelis.com) - ([@stephencelis](https://twitter.com/stephencelis)) - - -## License - -SQLite.swift is available under the MIT license. See [the LICENSE -file](./LICENSE.txt) for more information. - -## Related - -These projects enhance or use SQLite.swift: - - - [SQLiteMigrationManager.swift][] (inspired by - [FMDBMigrationManager][]) - - -## Alternatives - -Looking for something else? Try another Swift wrapper (or [FMDB][]): - - - [Camembert](https://github.com/remirobert/Camembert) - - [GRDB](https://github.com/groue/GRDB.swift) - - [SQLiteDB](https://github.com/FahimF/SQLiteDB) - - [Squeal](https://github.com/nerdyc/Squeal) - - [SwiftData](https://github.com/ryanfowler/SwiftData) - - [SwiftSQLite](https://github.com/chrismsimpson/SwiftSQLite) - -[Swift]: https://swift.org/ -[SQLite3]: http://www.sqlite.org -[SQLite.swift]: https://github.com/stephencelis/SQLite.swift - -[TravisBadge]: https://img.shields.io/travis/stephencelis/SQLite.swift/master.svg?style=flat -[TravisLink]: https://travis-ci.org/stephencelis/SQLite.swift - -[CocoaPodsVersionBadge]: https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png -[CocoaPodsVersionLink]: http://cocoadocs.org/docsets/SQLite.swift - -[PlatformBadge]: https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png -[PlatformLink]: http://cocoadocs.org/docsets/SQLite.swift - -[CartagheBadge]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat -[CarthageLink]: https://github.com/Carthage/Carthage - -[GitterBadge]: https://badges.gitter.im/stephencelis/SQLite.swift.svg -[GitterLink]: https://gitter.im/stephencelis/SQLite.swift - -[Swift5Badge]: https://img.shields.io/badge/swift-5-orange.svg?style=flat -[Swift5Link]: https://developer.apple.com/swift/ - -[SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift -[FMDB]: https://github.com/ccgus/fmdb -[FMDBMigrationManager]: https://github.com/layerhq/FMDBMigrationManager diff --git a/ios/libs/Sqlite/SQLite.playground/Contents.swift b/ios/libs/Sqlite/SQLite.playground/Contents.swift deleted file mode 100755 index 11e1313..0000000 --- a/ios/libs/Sqlite/SQLite.playground/Contents.swift +++ /dev/null @@ -1,43 +0,0 @@ -import SQLite - -let db = try! Connection() - -db.trace { print($0) } - -let users = Table("users") - -let id = Expression("id") -let email = Expression("email") -let name = Expression("name") - -try! db.run(users.create { t in - t.column(id, primaryKey: true) - t.column(email, unique: true, check: email.like("%@%")) - t.column(name) -}) - -let rowid = try! db.run(users.insert(email <- "alice@mac.com")) -let alice = users.filter(id == rowid) - -for user in try! db.prepare(users) { - print("id: \(user[id]), email: \(user[email])") -} - -let emails = VirtualTable("emails") - -let subject = Expression("subject") -let body = Expression("body") - -try! db.run(emails.create(.FTS4(subject, body))) - -try! db.run(emails.insert( - subject <- "Hello, world!", - body <- "This is a hello world message." -)) - -let row = try! db.pluck(emails.match("hello")) - -let query = try! db.prepare(emails.match("hello")) -for row in query { - print(row[subject]) -} diff --git a/ios/libs/Sqlite/SQLite.playground/contents.xcplayground b/ios/libs/Sqlite/SQLite.playground/contents.xcplayground deleted file mode 100755 index fd676d5..0000000 --- a/ios/libs/Sqlite/SQLite.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/ios/libs/Sqlite/SQLite.swift.podspec b/ios/libs/Sqlite/SQLite.swift.podspec deleted file mode 100755 index 57eda40..0000000 --- a/ios/libs/Sqlite/SQLite.swift.podspec +++ /dev/null @@ -1,69 +0,0 @@ -Pod::Spec.new do |s| - s.name = "SQLite.swift" - s.version = "0.12.0" - s.summary = "A type-safe, Swift-language layer over SQLite3 for iOS and macOS." - - s.description = <<-DESC - SQLite.swift provides compile-time confidence in SQL statement syntax and - intent. - DESC - - s.homepage = "https://github.com/stephencelis/SQLite.swift" - s.license = 'MIT' - s.author = { "Stephen Celis" => "stephen@stephencelis.com" } - s.source = { :git => "https://github.com/stephencelis/SQLite.swift.git", :tag => s.version.to_s } - s.social_media_url = 'https://twitter.com/stephencelis' - - s.module_name = 'SQLite' - s.ios.deployment_target = "8.0" - s.tvos.deployment_target = "9.1" - s.osx.deployment_target = "10.10" - s.watchos.deployment_target = "2.2" - s.default_subspec = 'standard' - s.pod_target_xcconfig = { - 'SWIFT_VERSION' => '5', - } - - s.subspec 'standard' do |ss| - ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}' - ss.exclude_files = 'Sources/**/Cipher.swift' - ss.private_header_files = 'Sources/SQLiteObjc/*.h' - ss.library = 'sqlite3' - - ss.test_spec 'tests' do |test_spec| - test_spec.resources = 'Tests/SQLiteTests/fixtures/*' - test_spec.source_files = 'Tests/SQLiteTests/*.swift' - end - end - - s.subspec 'standalone' do |ss| - ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}' - ss.exclude_files = 'Sources/**/Cipher.swift' - ss.private_header_files = 'Sources/SQLiteObjc/*.h' - - ss.xcconfig = { - 'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE' - } - ss.dependency 'sqlite3' - - ss.test_spec 'tests' do |test_spec| - test_spec.resources = 'Tests/SQLiteTests/fixtures/*' - test_spec.source_files = 'Tests/SQLiteTests/*.swift' - end - end - - s.subspec 'SQLCipher' do |ss| - ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}' - ss.private_header_files = 'Sources/SQLiteObjc/*.h' - ss.xcconfig = { - 'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER', - 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1' - } - ss.dependency 'SQLCipher', '>= 3.4.0' - - ss.test_spec 'tests' do |test_spec| - test_spec.resources = 'Tests/SQLiteTests/fixtures/*' - test_spec.source_files = 'Tests/SQLiteTests/*.swift' - end - end -end diff --git a/ios/libs/Sqlite/SQLite.xcodeproj/project.pbxproj b/ios/libs/Sqlite/SQLite.xcodeproj/project.pbxproj deleted file mode 100755 index 9d38dbc..0000000 --- a/ios/libs/Sqlite/SQLite.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1461 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 03A65E641C6BB0F60062603F /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E5A1C6BB0F50062603F /* SQLite.framework */; }; - 03A65E721C6BB2D30062603F /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 03A65E731C6BB2D80062603F /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; }; - 03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; }; - 03A65E751C6BB2DF0062603F /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 03A65E761C6BB2E60062603F /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; }; - 03A65E771C6BB2E60062603F /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; }; - 03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; }; - 03A65E791C6BB2EF0062603F /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; }; - 03A65E7A1C6BB2F70062603F /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; }; - 03A65E7B1C6BB2F70062603F /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; }; - 03A65E7C1C6BB2F70062603F /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; }; - 03A65E7D1C6BB2F70062603F /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* RTree.swift */; }; - 03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */; }; - 03A65E7F1C6BB2FB0062603F /* Collation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFB1C3F06E900AE3E12 /* Collation.swift */; }; - 03A65E801C6BB2FB0062603F /* CoreFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */; }; - 03A65E811C6BB2FB0062603F /* CustomFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */; }; - 03A65E821C6BB2FB0062603F /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFE1C3F06E900AE3E12 /* Expression.swift */; }; - 03A65E831C6BB2FB0062603F /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFF1C3F06E900AE3E12 /* Operators.swift */; }; - 03A65E841C6BB2FB0062603F /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; }; - 03A65E851C6BB2FB0062603F /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; }; - 03A65E861C6BB2FB0062603F /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; }; - 03A65E871C6BB3030062603F /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */; }; - 03A65E881C6BB3030062603F /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1B1C3F137700AE3E12 /* BlobTests.swift */; }; - 03A65E891C6BB3030062603F /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */; }; - 03A65E8A1C6BB3030062603F /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */; }; - 03A65E8B1C6BB3030062603F /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */; }; - 03A65E8C1C6BB3030062603F /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B201C3F137700AE3E12 /* ExpressionTests.swift */; }; - 03A65E8D1C6BB3030062603F /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B211C3F137700AE3E12 /* FTS4Tests.swift */; }; - 03A65E8E1C6BB3030062603F /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */; }; - 03A65E8F1C6BB3030062603F /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */; }; - 03A65E901C6BB3030062603F /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */; }; - 03A65E911C6BB3030062603F /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */; }; - 03A65E921C6BB3030062603F /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B181C3F134A00AE3E12 /* SetterTests.swift */; }; - 03A65E931C6BB3030062603F /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B321C3F142E00AE3E12 /* StatementTests.swift */; }; - 03A65E941C6BB3030062603F /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; }; - 03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; }; - 03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; }; - 19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; }; - 19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; }; - 19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; }; - 19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; }; - 19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; }; - 19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; }; - 19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; }; - 19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; }; - 19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; }; - 19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; }; - 19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; }; - 19A17408007B182F884E3A53 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; }; - 19A17490543609FCED53CACC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; }; - 19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; }; - 19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; }; - 19A175DFF47B84757E547C62 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; }; - 19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; }; - 19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; }; - 19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; }; - 19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; }; - 19A1785195182AF8731A8BDA /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; }; - 19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; }; - 19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; }; - 19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; }; - 19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; }; - 19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; }; - 19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; }; - 19A17DC282E36C4F41AA440B /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; }; - 19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; }; - 19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; }; - 19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; }; - 19A17F3E1F7ACA33BD43E138 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; }; - 19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; }; - 19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; }; - 19A17FDA323BAFDEC627E76F /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; }; - 19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; }; - 3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */; }; - 3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; }; - 3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; }; - 3D67B3E91DB246D100A4F4C6 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; }; - 3D67B3EA1DB246D100A4F4C6 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; }; - 3D67B3EB1DB246D100A4F4C6 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; }; - 3D67B3EC1DB246D100A4F4C6 /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* RTree.swift */; }; - 3D67B3ED1DB246D100A4F4C6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; }; - 3D67B3EE1DB246D100A4F4C6 /* AggregateFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */; }; - 3D67B3EF1DB246D100A4F4C6 /* Collation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFB1C3F06E900AE3E12 /* Collation.swift */; }; - 3D67B3F01DB246D100A4F4C6 /* CoreFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */; }; - 3D67B3F11DB246D100A4F4C6 /* CustomFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */; }; - 3D67B3F21DB246D100A4F4C6 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFE1C3F06E900AE3E12 /* Expression.swift */; }; - 3D67B3F31DB246D100A4F4C6 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFF1C3F06E900AE3E12 /* Operators.swift */; }; - 3D67B3F41DB246D100A4F4C6 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; }; - 3D67B3F51DB246D100A4F4C6 /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; }; - 3D67B3F61DB246D100A4F4C6 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; }; - 3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; }; - 3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; }; - 3D67B3F91DB246E700A4F4C6 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; }; - 3D67B3FB1DB2470600A4F4C6 /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; }; - 49EB68C41F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; }; - 49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; }; - 49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; }; - 49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; }; - EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; }; - EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; }; - EE247B041C3F06E900AE3E12 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; }; - EE247B051C3F06E900AE3E12 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; }; - EE247B061C3F06E900AE3E12 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; }; - EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; }; - EE247B081C3F06E900AE3E12 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; }; - EE247B091C3F06E900AE3E12 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; }; - EE247B0A1C3F06E900AE3E12 /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* RTree.swift */; }; - EE247B0B1C3F06E900AE3E12 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; }; - EE247B0C1C3F06E900AE3E12 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; }; - EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */; }; - EE247B0E1C3F06E900AE3E12 /* Collation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFB1C3F06E900AE3E12 /* Collation.swift */; }; - EE247B0F1C3F06E900AE3E12 /* CoreFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */; }; - EE247B101C3F06E900AE3E12 /* CustomFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */; }; - EE247B111C3F06E900AE3E12 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFE1C3F06E900AE3E12 /* Expression.swift */; }; - EE247B121C3F06E900AE3E12 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFF1C3F06E900AE3E12 /* Operators.swift */; }; - EE247B131C3F06E900AE3E12 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; }; - EE247B141C3F06E900AE3E12 /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; }; - EE247B151C3F06E900AE3E12 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; }; - EE247B171C3F127200AE3E12 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; }; - EE247B191C3F134A00AE3E12 /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B181C3F134A00AE3E12 /* SetterTests.swift */; }; - EE247B221C3F137700AE3E12 /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */; }; - EE247B231C3F137700AE3E12 /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1B1C3F137700AE3E12 /* BlobTests.swift */; }; - EE247B251C3F137700AE3E12 /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */; }; - EE247B261C3F137700AE3E12 /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */; }; - EE247B271C3F137700AE3E12 /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */; }; - EE247B281C3F137700AE3E12 /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B201C3F137700AE3E12 /* ExpressionTests.swift */; }; - EE247B291C3F137700AE3E12 /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B211C3F137700AE3E12 /* FTS4Tests.swift */; }; - EE247B2E1C3F141E00AE3E12 /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */; }; - EE247B2F1C3F141E00AE3E12 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */; }; - EE247B301C3F141E00AE3E12 /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */; }; - EE247B311C3F141E00AE3E12 /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */; }; - EE247B341C3F142E00AE3E12 /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B321C3F142E00AE3E12 /* StatementTests.swift */; }; - EE247B351C3F142E00AE3E12 /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; }; - EE247B461C3F3ED000AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247B3C1C3F3ED000AE3E12 /* SQLite.framework */; }; - EE247B531C3F3FC700AE3E12 /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */; }; - EE247B541C3F3FC700AE3E12 /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1B1C3F137700AE3E12 /* BlobTests.swift */; }; - EE247B551C3F3FC700AE3E12 /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */; }; - EE247B561C3F3FC700AE3E12 /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */; }; - EE247B571C3F3FC700AE3E12 /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */; }; - EE247B581C3F3FC700AE3E12 /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B201C3F137700AE3E12 /* ExpressionTests.swift */; }; - EE247B591C3F3FC700AE3E12 /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B211C3F137700AE3E12 /* FTS4Tests.swift */; }; - EE247B5A1C3F3FC700AE3E12 /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */; }; - EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */; }; - EE247B5C1C3F3FC700AE3E12 /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */; }; - EE247B5D1C3F3FC700AE3E12 /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */; }; - EE247B5E1C3F3FC700AE3E12 /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B181C3F134A00AE3E12 /* SetterTests.swift */; }; - EE247B5F1C3F3FC700AE3E12 /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B321C3F142E00AE3E12 /* StatementTests.swift */; }; - EE247B601C3F3FC700AE3E12 /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; }; - EE247B611C3F3FC700AE3E12 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; }; - EE247B621C3F3FDB00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE247B631C3F3FDB00AE3E12 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; }; - EE247B641C3F3FDB00AE3E12 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; }; - EE247B651C3F3FEC00AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; }; - EE247B661C3F3FEC00AE3E12 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; }; - EE247B671C3F3FEC00AE3E12 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; }; - EE247B681C3F3FEC00AE3E12 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; }; - EE247B691C3F3FEC00AE3E12 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; }; - EE247B6A1C3F3FEC00AE3E12 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; }; - EE247B6B1C3F3FEC00AE3E12 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; }; - EE247B6C1C3F3FEC00AE3E12 /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* RTree.swift */; }; - EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */; }; - EE247B6E1C3F3FEC00AE3E12 /* Collation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFB1C3F06E900AE3E12 /* Collation.swift */; }; - EE247B6F1C3F3FEC00AE3E12 /* CoreFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */; }; - EE247B701C3F3FEC00AE3E12 /* CustomFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */; }; - EE247B711C3F3FEC00AE3E12 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFE1C3F06E900AE3E12 /* Expression.swift */; }; - EE247B721C3F3FEC00AE3E12 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFF1C3F06E900AE3E12 /* Operators.swift */; }; - EE247B731C3F3FEC00AE3E12 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; }; - EE247B741C3F3FEC00AE3E12 /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; }; - EE247B751C3F3FEC00AE3E12 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; }; - EE91808E1C46E5230038162A /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE91808F1C46E76D0038162A /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE9180941C46EA210038162A /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EE9180931C46EA210038162A /* libsqlite3.tbd */; }; - EE9180951C46EBCC0038162A /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EE9180911C46E9D30038162A /* libsqlite3.tbd */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 03A65E651C6BB0F60062603F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EE247ACA1C3F04ED00AE3E12 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 03A65E591C6BB0F50062603F; - remoteInfo = "SQLite tvOS"; - }; - EE247ADF1C3F04ED00AE3E12 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EE247ACA1C3F04ED00AE3E12 /* Project object */; - proxyType = 1; - remoteGlobalIDString = EE247AD21C3F04ED00AE3E12; - remoteInfo = SQLite; - }; - EE247B471C3F3ED000AE3E12 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = EE247ACA1C3F04ED00AE3E12 /* Project object */; - proxyType = 1; - remoteGlobalIDString = EE247B3B1C3F3ED000AE3E12; - remoteInfo = SQLite; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; }; - 19A1710E73A46D5AC721CDA9 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; - 19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = ""; }; - 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctionTests.swift; sourceTree = ""; }; - 19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = ""; }; - 19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = ""; }; - 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTests.swift; sourceTree = ""; }; - 19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = ""; }; - 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = ""; }; - 19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = ""; }; - 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = ""; }; - 19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = ""; }; - 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; }; - 49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = ""; }; - A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = ""; }; - EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - EE247ADD1C3F04ED00AE3E12 /* SQLiteTests iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - EE247AE41C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - EE247AEE1C3F06E900AE3E12 /* Blob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Blob.swift; sourceTree = ""; }; - EE247AEF1C3F06E900AE3E12 /* Connection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Connection.swift; sourceTree = ""; }; - EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fts3_tokenizer.h; path = ../../SQLiteObjc/fts3_tokenizer.h; sourceTree = ""; }; - EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "SQLite-Bridging.m"; path = "../../SQLiteObjc/SQLite-Bridging.m"; sourceTree = ""; }; - EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statement.swift; sourceTree = ""; }; - EE247AF31C3F06E900AE3E12 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Value.swift; sourceTree = ""; }; - EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4.swift; sourceTree = ""; }; - EE247AF61C3F06E900AE3E12 /* RTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RTree.swift; sourceTree = ""; }; - EE247AF71C3F06E900AE3E12 /* Foundation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Foundation.swift; sourceTree = ""; }; - EE247AF81C3F06E900AE3E12 /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; - EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctions.swift; sourceTree = ""; }; - EE247AFB1C3F06E900AE3E12 /* Collation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Collation.swift; sourceTree = ""; }; - EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreFunctions.swift; sourceTree = ""; }; - EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomFunctions.swift; sourceTree = ""; }; - EE247AFE1C3F06E900AE3E12 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; - EE247AFF1C3F06E900AE3E12 /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = ""; }; - EE247B001C3F06E900AE3E12 /* Query.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Query.swift; sourceTree = ""; }; - EE247B011C3F06E900AE3E12 /* Schema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Schema.swift; sourceTree = ""; }; - EE247B021C3F06E900AE3E12 /* Setter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Setter.swift; sourceTree = ""; }; - EE247B161C3F127200AE3E12 /* TestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = ""; }; - EE247B181C3F134A00AE3E12 /* SetterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetterTests.swift; sourceTree = ""; }; - EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctionsTests.swift; sourceTree = ""; }; - EE247B1B1C3F137700AE3E12 /* BlobTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlobTests.swift; sourceTree = ""; }; - EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionTests.swift; sourceTree = ""; }; - EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreFunctionsTests.swift; sourceTree = ""; }; - EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomFunctionsTests.swift; sourceTree = ""; }; - EE247B201C3F137700AE3E12 /* ExpressionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionTests.swift; sourceTree = ""; }; - EE247B211C3F137700AE3E12 /* FTS4Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4Tests.swift; sourceTree = ""; }; - EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorsTests.swift; sourceTree = ""; }; - EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryTests.swift; sourceTree = ""; }; - EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RTreeTests.swift; sourceTree = ""; }; - EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaTests.swift; sourceTree = ""; }; - EE247B321C3F142E00AE3E12 /* StatementTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementTests.swift; sourceTree = ""; }; - EE247B331C3F142E00AE3E12 /* ValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueTests.swift; sourceTree = ""; }; - EE247B3C1C3F3ED000AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - EE247B451C3F3ED000AE3E12 /* SQLiteTests Mac.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests Mac.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - EE247B771C3F40D700AE3E12 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - EE247B8B1C3F820300AE3E12 /* CONTRIBUTING.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CONTRIBUTING.md; sourceTree = ""; }; - EE247B8C1C3F821200AE3E12 /* .travis.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .travis.yml; sourceTree = ""; }; - EE247B8D1C3F821200AE3E12 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - EE247B8F1C3F822500AE3E12 /* Index.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Index.md; sourceTree = ""; }; - EE247B911C3F822500AE3E12 /* installation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "installation@2x.png"; sourceTree = ""; }; - EE247B921C3F822600AE3E12 /* playground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "playground@2x.png"; sourceTree = ""; }; - EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = SQLite.swift.podspec; sourceTree = ""; }; - EE91808D1C46E5230038162A /* SQLite-Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SQLite-Bridging.h"; path = "../../SQLiteObjc/include/SQLite-Bridging.h"; sourceTree = ""; }; - EE9180911C46E9D30038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; }; - EE9180931C46EA210038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 03A65E561C6BB0F50062603F /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03A65E601C6BB0F60062603F /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03A65E641C6BB0F60062603F /* SQLite.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A121AC411CA35C79005A31D1 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247ACF1C3F04ED00AE3E12 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EE9180941C46EA210038162A /* libsqlite3.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247ADA1C3F04ED00AE3E12 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247B381C3F3ED000AE3E12 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EE9180951C46EBCC0038162A /* libsqlite3.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247B421C3F3ED000AE3E12 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EE247B461C3F3ED000AE3E12 /* SQLite.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 3D67B3E41DB2469200A4F4C6 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */, - ); - name = Frameworks; - sourceTree = ""; - }; - EE247AC91C3F04ED00AE3E12 = { - isa = PBXGroup; - children = ( - EE247AD51C3F04ED00AE3E12 /* SQLite */, - EE247AE11C3F04ED00AE3E12 /* SQLiteTests */, - EE247B8A1C3F81D000AE3E12 /* Metadata */, - EE247AD41C3F04ED00AE3E12 /* Products */, - 3D67B3E41DB2469200A4F4C6 /* Frameworks */, - ); - indentWidth = 4; - sourceTree = ""; - tabWidth = 4; - }; - EE247AD41C3F04ED00AE3E12 /* Products */ = { - isa = PBXGroup; - children = ( - EE247AD31C3F04ED00AE3E12 /* SQLite.framework */, - EE247ADD1C3F04ED00AE3E12 /* SQLiteTests iOS.xctest */, - EE247B3C1C3F3ED000AE3E12 /* SQLite.framework */, - EE247B451C3F3ED000AE3E12 /* SQLiteTests Mac.xctest */, - 03A65E5A1C6BB0F50062603F /* SQLite.framework */, - 03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */, - A121AC451CA35C79005A31D1 /* SQLite.framework */, - ); - name = Products; - sourceTree = ""; - }; - EE247AD51C3F04ED00AE3E12 /* SQLite */ = { - isa = PBXGroup; - children = ( - EE247AD61C3F04ED00AE3E12 /* SQLite.h */, - EE247AF71C3F06E900AE3E12 /* Foundation.swift */, - EE247AF81C3F06E900AE3E12 /* Helpers.swift */, - EE247AD81C3F04ED00AE3E12 /* Info.plist */, - EE247AED1C3F06E900AE3E12 /* Core */, - EE247AF41C3F06E900AE3E12 /* Extensions */, - EE247AF91C3F06E900AE3E12 /* Typed */, - ); - name = SQLite; - path = Sources/SQLite; - sourceTree = ""; - }; - EE247AE11C3F04ED00AE3E12 /* SQLiteTests */ = { - isa = PBXGroup; - children = ( - 19A17E2695737FAB5D6086E3 /* fixtures */, - EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */, - EE247B1B1C3F137700AE3E12 /* BlobTests.swift */, - EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */, - EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */, - EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */, - EE247B201C3F137700AE3E12 /* ExpressionTests.swift */, - EE247B211C3F137700AE3E12 /* FTS4Tests.swift */, - EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */, - EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */, - EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */, - EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */, - EE247B181C3F134A00AE3E12 /* SetterTests.swift */, - EE247B321C3F142E00AE3E12 /* StatementTests.swift */, - EE247B331C3F142E00AE3E12 /* ValueTests.swift */, - EE247B161C3F127200AE3E12 /* TestHelpers.swift */, - EE247AE41C3F04ED00AE3E12 /* Info.plist */, - 19A1721B8984686B9963B45D /* FTS5Tests.swift */, - 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */, - 19A17399EA9E61235D5D77BF /* CipherTests.swift */, - 19A17B93B48B5560E6E51791 /* Fixtures.swift */, - 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */, - 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */, - ); - name = SQLiteTests; - path = Tests/SQLiteTests; - sourceTree = ""; - }; - EE247AED1C3F06E900AE3E12 /* Core */ = { - isa = PBXGroup; - children = ( - EE91808D1C46E5230038162A /* SQLite-Bridging.h */, - EE247AEE1C3F06E900AE3E12 /* Blob.swift */, - EE247AEF1C3F06E900AE3E12 /* Connection.swift */, - EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */, - EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */, - EE247AF21C3F06E900AE3E12 /* Statement.swift */, - EE247AF31C3F06E900AE3E12 /* Value.swift */, - 19A1710E73A46D5AC721CDA9 /* Errors.swift */, - ); - path = Core; - sourceTree = ""; - }; - EE247AF41C3F06E900AE3E12 /* Extensions */ = { - isa = PBXGroup; - children = ( - EE247AF51C3F06E900AE3E12 /* FTS4.swift */, - EE247AF61C3F06E900AE3E12 /* RTree.swift */, - 19A1730E4390C775C25677D1 /* FTS5.swift */, - 19A178A39ACA9667A62663CC /* Cipher.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - EE247AF91C3F06E900AE3E12 /* Typed */ = { - isa = PBXGroup; - children = ( - EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */, - EE247AFB1C3F06E900AE3E12 /* Collation.swift */, - EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */, - EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */, - EE247AFE1C3F06E900AE3E12 /* Expression.swift */, - EE247AFF1C3F06E900AE3E12 /* Operators.swift */, - EE247B001C3F06E900AE3E12 /* Query.swift */, - EE247B011C3F06E900AE3E12 /* Schema.swift */, - EE247B021C3F06E900AE3E12 /* Setter.swift */, - 49EB68C31F7B3CB400D89D40 /* Coding.swift */, - 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */, - ); - path = Typed; - sourceTree = ""; - }; - EE247B8A1C3F81D000AE3E12 /* Metadata */ = { - isa = PBXGroup; - children = ( - EE247B771C3F40D700AE3E12 /* README.md */, - EE247B8B1C3F820300AE3E12 /* CONTRIBUTING.md */, - EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */, - EE247B8C1C3F821200AE3E12 /* .travis.yml */, - EE247B8D1C3F821200AE3E12 /* Makefile */, - EE9180931C46EA210038162A /* libsqlite3.tbd */, - EE9180911C46E9D30038162A /* libsqlite3.tbd */, - 03A65E961C6BB3210062603F /* libsqlite3.tbd */, - EE247B8E1C3F822500AE3E12 /* Documentation */, - ); - name = Metadata; - sourceTree = ""; - }; - EE247B8E1C3F822500AE3E12 /* Documentation */ = { - isa = PBXGroup; - children = ( - EE247B8F1C3F822500AE3E12 /* Index.md */, - EE247B901C3F822500AE3E12 /* Resources */, - ); - path = Documentation; - sourceTree = ""; - }; - EE247B901C3F822500AE3E12 /* Resources */ = { - isa = PBXGroup; - children = ( - EE247B911C3F822500AE3E12 /* installation@2x.png */, - EE247B921C3F822600AE3E12 /* playground@2x.png */, - ); - path = Resources; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 03A65E571C6BB0F50062603F /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */, - 03A65E751C6BB2DF0062603F /* SQLite-Bridging.h in Headers */, - 03A65E721C6BB2D30062603F /* SQLite.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A121AC421CA35C79005A31D1 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 3D67B3FB1DB2470600A4F4C6 /* SQLite-Bridging.h in Headers */, - 3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */, - 3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247AD01C3F04ED00AE3E12 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - EE91808E1C46E5230038162A /* SQLite-Bridging.h in Headers */, - EE247B051C3F06E900AE3E12 /* fts3_tokenizer.h in Headers */, - EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247B391C3F3ED000AE3E12 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - EE247B671C3F3FEC00AE3E12 /* fts3_tokenizer.h in Headers */, - EE247B621C3F3FDB00AE3E12 /* SQLite.h in Headers */, - EE91808F1C46E76D0038162A /* SQLite-Bridging.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 03A65E591C6BB0F50062603F /* SQLite tvOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03A65E6F1C6BB0F60062603F /* Build configuration list for PBXNativeTarget "SQLite tvOS" */; - buildPhases = ( - 03A65E551C6BB0F50062603F /* Sources */, - 03A65E561C6BB0F50062603F /* Frameworks */, - 03A65E571C6BB0F50062603F /* Headers */, - 03A65E581C6BB0F50062603F /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "SQLite tvOS"; - productName = "SQLite tvOS"; - productReference = 03A65E5A1C6BB0F50062603F /* SQLite.framework */; - productType = "com.apple.product-type.framework"; - }; - 03A65E621C6BB0F60062603F /* SQLiteTests tvOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03A65E701C6BB0F60062603F /* Build configuration list for PBXNativeTarget "SQLiteTests tvOS" */; - buildPhases = ( - 03A65E5F1C6BB0F60062603F /* Sources */, - 03A65E601C6BB0F60062603F /* Frameworks */, - 03A65E611C6BB0F60062603F /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 03A65E661C6BB0F60062603F /* PBXTargetDependency */, - ); - name = "SQLiteTests tvOS"; - productName = "SQLite tvOSTests"; - productReference = 03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - A121AC441CA35C79005A31D1 /* SQLite watchOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = A121AC4C1CA35C79005A31D1 /* Build configuration list for PBXNativeTarget "SQLite watchOS" */; - buildPhases = ( - A121AC401CA35C79005A31D1 /* Sources */, - A121AC411CA35C79005A31D1 /* Frameworks */, - A121AC421CA35C79005A31D1 /* Headers */, - A121AC431CA35C79005A31D1 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "SQLite watchOS"; - productName = "SQLite watchOS"; - productReference = A121AC451CA35C79005A31D1 /* SQLite.framework */; - productType = "com.apple.product-type.framework"; - }; - EE247AD21C3F04ED00AE3E12 /* SQLite iOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = EE247AE71C3F04ED00AE3E12 /* Build configuration list for PBXNativeTarget "SQLite iOS" */; - buildPhases = ( - EE247ACE1C3F04ED00AE3E12 /* Sources */, - EE247ACF1C3F04ED00AE3E12 /* Frameworks */, - EE247AD01C3F04ED00AE3E12 /* Headers */, - EE247AD11C3F04ED00AE3E12 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "SQLite iOS"; - productName = SQLite; - productReference = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; - productType = "com.apple.product-type.framework"; - }; - EE247ADC1C3F04ED00AE3E12 /* SQLiteTests iOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = EE247AEA1C3F04ED00AE3E12 /* Build configuration list for PBXNativeTarget "SQLiteTests iOS" */; - buildPhases = ( - EE247AD91C3F04ED00AE3E12 /* Sources */, - EE247ADA1C3F04ED00AE3E12 /* Frameworks */, - EE247ADB1C3F04ED00AE3E12 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - EE247AE01C3F04ED00AE3E12 /* PBXTargetDependency */, - ); - name = "SQLiteTests iOS"; - productName = SQLiteTests; - productReference = EE247ADD1C3F04ED00AE3E12 /* SQLiteTests iOS.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - EE247B3B1C3F3ED000AE3E12 /* SQLite Mac */ = { - isa = PBXNativeTarget; - buildConfigurationList = EE247B511C3F3ED000AE3E12 /* Build configuration list for PBXNativeTarget "SQLite Mac" */; - buildPhases = ( - EE247B371C3F3ED000AE3E12 /* Sources */, - EE247B381C3F3ED000AE3E12 /* Frameworks */, - EE247B391C3F3ED000AE3E12 /* Headers */, - EE247B3A1C3F3ED000AE3E12 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "SQLite Mac"; - productName = SQLite; - productReference = EE247B3C1C3F3ED000AE3E12 /* SQLite.framework */; - productType = "com.apple.product-type.framework"; - }; - EE247B441C3F3ED000AE3E12 /* SQLiteTests Mac */ = { - isa = PBXNativeTarget; - buildConfigurationList = EE247B521C3F3ED000AE3E12 /* Build configuration list for PBXNativeTarget "SQLiteTests Mac" */; - buildPhases = ( - EE247B411C3F3ED000AE3E12 /* Sources */, - EE247B421C3F3ED000AE3E12 /* Frameworks */, - EE247B431C3F3ED000AE3E12 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - EE247B481C3F3ED000AE3E12 /* PBXTargetDependency */, - ); - name = "SQLiteTests Mac"; - productName = SQLiteTests; - productReference = EE247B451C3F3ED000AE3E12 /* SQLiteTests Mac.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - EE247ACA1C3F04ED00AE3E12 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 1020; - TargetAttributes = { - 03A65E591C6BB0F50062603F = { - CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0900; - }; - 03A65E621C6BB0F60062603F = { - CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0900; - }; - A121AC441CA35C79005A31D1 = { - CreatedOnToolsVersion = 7.3; - LastSwiftMigration = 0900; - }; - EE247AD21C3F04ED00AE3E12 = { - CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0900; - }; - EE247ADC1C3F04ED00AE3E12 = { - CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 1020; - }; - EE247B3B1C3F3ED000AE3E12 = { - CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0900; - }; - EE247B441C3F3ED000AE3E12 = { - CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0900; - }; - }; - }; - buildConfigurationList = EE247ACD1C3F04ED00AE3E12 /* Build configuration list for PBXProject "SQLite" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = EE247AC91C3F04ED00AE3E12; - productRefGroup = EE247AD41C3F04ED00AE3E12 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - EE247AD21C3F04ED00AE3E12 /* SQLite iOS */, - EE247ADC1C3F04ED00AE3E12 /* SQLiteTests iOS */, - EE247B3B1C3F3ED000AE3E12 /* SQLite Mac */, - EE247B441C3F3ED000AE3E12 /* SQLiteTests Mac */, - 03A65E591C6BB0F50062603F /* SQLite tvOS */, - 03A65E621C6BB0F60062603F /* SQLiteTests tvOS */, - A121AC441CA35C79005A31D1 /* SQLite watchOS */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 03A65E581C6BB0F50062603F /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03A65E611C6BB0F60062603F /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 19A17F3E1F7ACA33BD43E138 /* fixtures in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A121AC431CA35C79005A31D1 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247AD11C3F04ED00AE3E12 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247ADB1C3F04ED00AE3E12 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 19A17FDA323BAFDEC627E76F /* fixtures in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247B3A1C3F3ED000AE3E12 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247B431C3F3ED000AE3E12 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 19A175DFF47B84757E547C62 /* fixtures in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 03A65E551C6BB0F50062603F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03A65E801C6BB2FB0062603F /* CoreFunctions.swift in Sources */, - 49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */, - 03A65E761C6BB2E60062603F /* Blob.swift in Sources */, - 03A65E7D1C6BB2F70062603F /* RTree.swift in Sources */, - 03A65E791C6BB2EF0062603F /* SQLite-Bridging.m in Sources */, - 03A65E7B1C6BB2F70062603F /* Value.swift in Sources */, - 03A65E821C6BB2FB0062603F /* Expression.swift in Sources */, - 03A65E731C6BB2D80062603F /* Foundation.swift in Sources */, - 03A65E7F1C6BB2FB0062603F /* Collation.swift in Sources */, - 03A65E861C6BB2FB0062603F /* Setter.swift in Sources */, - 03A65E811C6BB2FB0062603F /* CustomFunctions.swift in Sources */, - 03A65E7A1C6BB2F70062603F /* Statement.swift in Sources */, - 03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */, - 03A65E831C6BB2FB0062603F /* Operators.swift in Sources */, - 03A65E851C6BB2FB0062603F /* Schema.swift in Sources */, - 03A65E841C6BB2FB0062603F /* Query.swift in Sources */, - 03A65E7C1C6BB2F70062603F /* FTS4.swift in Sources */, - 03A65E771C6BB2E60062603F /* Connection.swift in Sources */, - 03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */, - 19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */, - 19A179E76EA6207669B60C1B /* Cipher.swift in Sources */, - 19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */, - 19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03A65E5F1C6BB0F60062603F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03A65E881C6BB3030062603F /* BlobTests.swift in Sources */, - 03A65E901C6BB3030062603F /* RTreeTests.swift in Sources */, - 03A65E941C6BB3030062603F /* ValueTests.swift in Sources */, - 03A65E8F1C6BB3030062603F /* QueryTests.swift in Sources */, - 03A65E8B1C6BB3030062603F /* CustomFunctionsTests.swift in Sources */, - 03A65E871C6BB3030062603F /* AggregateFunctionsTests.swift in Sources */, - 03A65E921C6BB3030062603F /* SetterTests.swift in Sources */, - 03A65E891C6BB3030062603F /* ConnectionTests.swift in Sources */, - 03A65E8A1C6BB3030062603F /* CoreFunctionsTests.swift in Sources */, - 03A65E931C6BB3030062603F /* StatementTests.swift in Sources */, - 03A65E911C6BB3030062603F /* SchemaTests.swift in Sources */, - 03A65E8D1C6BB3030062603F /* FTS4Tests.swift in Sources */, - 03A65E8C1C6BB3030062603F /* ExpressionTests.swift in Sources */, - 03A65E8E1C6BB3030062603F /* OperatorsTests.swift in Sources */, - 03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */, - 19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */, - 19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */, - 19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */, - 19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */, - 19A1785195182AF8731A8BDA /* RowTests.swift in Sources */, - 19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A121AC401CA35C79005A31D1 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3D67B3F91DB246E700A4F4C6 /* SQLite-Bridging.m in Sources */, - 49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */, - 3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */, - 3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */, - 3D67B3E91DB246D100A4F4C6 /* Statement.swift in Sources */, - 3D67B3EA1DB246D100A4F4C6 /* Value.swift in Sources */, - 3D67B3EB1DB246D100A4F4C6 /* FTS4.swift in Sources */, - 3D67B3EC1DB246D100A4F4C6 /* RTree.swift in Sources */, - 3D67B3ED1DB246D100A4F4C6 /* FTS5.swift in Sources */, - 3D67B3EE1DB246D100A4F4C6 /* AggregateFunctions.swift in Sources */, - 3D67B3EF1DB246D100A4F4C6 /* Collation.swift in Sources */, - 3D67B3F01DB246D100A4F4C6 /* CoreFunctions.swift in Sources */, - 3D67B3F11DB246D100A4F4C6 /* CustomFunctions.swift in Sources */, - 3D67B3F21DB246D100A4F4C6 /* Expression.swift in Sources */, - 3D67B3F31DB246D100A4F4C6 /* Operators.swift in Sources */, - 3D67B3F41DB246D100A4F4C6 /* Query.swift in Sources */, - 3D67B3F51DB246D100A4F4C6 /* Schema.swift in Sources */, - 3D67B3F61DB246D100A4F4C6 /* Setter.swift in Sources */, - 3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */, - 3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */, - 19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */, - 19A17DC282E36C4F41AA440B /* Errors.swift in Sources */, - 19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247ACE1C3F04ED00AE3E12 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - EE247B0F1C3F06E900AE3E12 /* CoreFunctions.swift in Sources */, - 49EB68C41F7B3CB400D89D40 /* Coding.swift in Sources */, - EE247B0A1C3F06E900AE3E12 /* RTree.swift in Sources */, - EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */, - EE247B0B1C3F06E900AE3E12 /* Foundation.swift in Sources */, - EE247B041C3F06E900AE3E12 /* Connection.swift in Sources */, - EE247B111C3F06E900AE3E12 /* Expression.swift in Sources */, - EE247B0C1C3F06E900AE3E12 /* Helpers.swift in Sources */, - EE247B0E1C3F06E900AE3E12 /* Collation.swift in Sources */, - EE247B151C3F06E900AE3E12 /* Setter.swift in Sources */, - EE247B101C3F06E900AE3E12 /* CustomFunctions.swift in Sources */, - EE247B091C3F06E900AE3E12 /* FTS4.swift in Sources */, - EE247B081C3F06E900AE3E12 /* Value.swift in Sources */, - EE247B121C3F06E900AE3E12 /* Operators.swift in Sources */, - EE247B141C3F06E900AE3E12 /* Schema.swift in Sources */, - EE247B131C3F06E900AE3E12 /* Query.swift in Sources */, - EE247B061C3F06E900AE3E12 /* SQLite-Bridging.m in Sources */, - EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */, - EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */, - 19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */, - 19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */, - 19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */, - 19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247AD91C3F04ED00AE3E12 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - EE247B261C3F137700AE3E12 /* CoreFunctionsTests.swift in Sources */, - EE247B291C3F137700AE3E12 /* FTS4Tests.swift in Sources */, - EE247B191C3F134A00AE3E12 /* SetterTests.swift in Sources */, - EE247B311C3F141E00AE3E12 /* SchemaTests.swift in Sources */, - EE247B171C3F127200AE3E12 /* TestHelpers.swift in Sources */, - EE247B281C3F137700AE3E12 /* ExpressionTests.swift in Sources */, - EE247B271C3F137700AE3E12 /* CustomFunctionsTests.swift in Sources */, - EE247B341C3F142E00AE3E12 /* StatementTests.swift in Sources */, - EE247B301C3F141E00AE3E12 /* RTreeTests.swift in Sources */, - EE247B231C3F137700AE3E12 /* BlobTests.swift in Sources */, - EE247B351C3F142E00AE3E12 /* ValueTests.swift in Sources */, - EE247B2F1C3F141E00AE3E12 /* QueryTests.swift in Sources */, - EE247B221C3F137700AE3E12 /* AggregateFunctionsTests.swift in Sources */, - EE247B2E1C3F141E00AE3E12 /* OperatorsTests.swift in Sources */, - EE247B251C3F137700AE3E12 /* ConnectionTests.swift in Sources */, - 19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */, - 19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */, - 19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */, - 19A17408007B182F884E3A53 /* Fixtures.swift in Sources */, - 19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */, - 19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247B371C3F3ED000AE3E12 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - EE247B6F1C3F3FEC00AE3E12 /* CoreFunctions.swift in Sources */, - 49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */, - EE247B651C3F3FEC00AE3E12 /* Blob.swift in Sources */, - EE247B6C1C3F3FEC00AE3E12 /* RTree.swift in Sources */, - EE247B681C3F3FEC00AE3E12 /* SQLite-Bridging.m in Sources */, - EE247B6A1C3F3FEC00AE3E12 /* Value.swift in Sources */, - EE247B711C3F3FEC00AE3E12 /* Expression.swift in Sources */, - EE247B631C3F3FDB00AE3E12 /* Foundation.swift in Sources */, - EE247B6E1C3F3FEC00AE3E12 /* Collation.swift in Sources */, - EE247B751C3F3FEC00AE3E12 /* Setter.swift in Sources */, - EE247B701C3F3FEC00AE3E12 /* CustomFunctions.swift in Sources */, - EE247B691C3F3FEC00AE3E12 /* Statement.swift in Sources */, - EE247B641C3F3FDB00AE3E12 /* Helpers.swift in Sources */, - EE247B721C3F3FEC00AE3E12 /* Operators.swift in Sources */, - EE247B741C3F3FEC00AE3E12 /* Schema.swift in Sources */, - EE247B731C3F3FEC00AE3E12 /* Query.swift in Sources */, - EE247B6B1C3F3FEC00AE3E12 /* FTS4.swift in Sources */, - EE247B661C3F3FEC00AE3E12 /* Connection.swift in Sources */, - EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */, - 19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */, - 19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */, - 19A17490543609FCED53CACC /* Errors.swift in Sources */, - 19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EE247B411C3F3ED000AE3E12 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - EE247B561C3F3FC700AE3E12 /* CoreFunctionsTests.swift in Sources */, - EE247B5A1C3F3FC700AE3E12 /* OperatorsTests.swift in Sources */, - EE247B541C3F3FC700AE3E12 /* BlobTests.swift in Sources */, - EE247B5D1C3F3FC700AE3E12 /* SchemaTests.swift in Sources */, - EE247B591C3F3FC700AE3E12 /* FTS4Tests.swift in Sources */, - EE247B531C3F3FC700AE3E12 /* AggregateFunctionsTests.swift in Sources */, - EE247B5F1C3F3FC700AE3E12 /* StatementTests.swift in Sources */, - EE247B5C1C3F3FC700AE3E12 /* RTreeTests.swift in Sources */, - EE247B571C3F3FC700AE3E12 /* CustomFunctionsTests.swift in Sources */, - EE247B601C3F3FC700AE3E12 /* ValueTests.swift in Sources */, - EE247B551C3F3FC700AE3E12 /* ConnectionTests.swift in Sources */, - EE247B611C3F3FC700AE3E12 /* TestHelpers.swift in Sources */, - EE247B581C3F3FC700AE3E12 /* ExpressionTests.swift in Sources */, - EE247B5E1C3F3FC700AE3E12 /* SetterTests.swift in Sources */, - EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */, - 19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */, - 19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */, - 19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */, - 19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */, - 19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */, - 19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 03A65E661C6BB0F60062603F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 03A65E591C6BB0F50062603F /* SQLite tvOS */; - targetProxy = 03A65E651C6BB0F60062603F /* PBXContainerItemProxy */; - }; - EE247AE01C3F04ED00AE3E12 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = EE247AD21C3F04ED00AE3E12 /* SQLite iOS */; - targetProxy = EE247ADF1C3F04ED00AE3E12 /* PBXContainerItemProxy */; - }; - EE247B481C3F3ED000AE3E12 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = EE247B3B1C3F3ED000AE3E12 /* SQLite Mac */; - targetProxy = EE247B471C3F3ED000AE3E12 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 03A65E6B1C6BB0F60062603F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite; - PRODUCT_NAME = SQLite; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 9.1; - }; - name = Debug; - }; - 03A65E6C1C6BB0F60062603F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite; - PRODUCT_NAME = SQLite; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 9.1; - }; - name = Release; - }; - 03A65E6D1C6BB0F60062603F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = Tests/SQLiteTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - TVOS_DEPLOYMENT_TARGET = 9.1; - }; - name = Debug; - }; - 03A65E6E1C6BB0F60062603F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = Tests/SQLiteTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - TVOS_DEPLOYMENT_TARGET = 9.1; - }; - name = Release; - }; - A121AC4A1CA35C79005A31D1 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite; - PRODUCT_NAME = SQLite; - SDKROOT = watchos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = 4; - WATCHOS_DEPLOYMENT_TARGET = 2.2; - }; - name = Debug; - }; - A121AC4B1CA35C79005A31D1 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite; - PRODUCT_NAME = SQLite; - SDKROOT = watchos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = 4; - WATCHOS_DEPLOYMENT_TARGET = 2.2; - }; - name = Release; - }; - EE247AE51C3F04ED00AE3E12 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = ""; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2,3"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - EE247AE61C3F04ED00AE3E12 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = ""; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2,3"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - EE247AE81C3F04ED00AE3E12 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ENABLE_MODULES = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite; - PRODUCT_NAME = SQLite; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - EE247AE91C3F04ED00AE3E12 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ENABLE_MODULES = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite; - PRODUCT_NAME = SQLite; - SKIP_INSTALL = YES; - }; - name = Release; - }; - EE247AEB1C3F04ED00AE3E12 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = Tests/SQLiteTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - EE247AEC1C3F04ED00AE3E12 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = Tests/SQLiteTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - EE247B4D1C3F3ED000AE3E12 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CODE_SIGN_IDENTITY = ""; - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite; - PRODUCT_NAME = SQLite; - SDKROOT = macosx; - SKIP_INSTALL = YES; - SWIFT_INCLUDE_PATHS = ""; - }; - name = Debug; - }; - EE247B4E1C3F3ED000AE3E12 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CODE_SIGN_IDENTITY = ""; - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite; - PRODUCT_NAME = SQLite; - SDKROOT = macosx; - SKIP_INSTALL = YES; - SWIFT_INCLUDE_PATHS = ""; - }; - name = Release; - }; - EE247B4F1C3F3ED000AE3E12 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Tests/SQLiteTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - }; - name = Debug; - }; - EE247B501C3F3ED000AE3E12 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Tests/SQLiteTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 03A65E6F1C6BB0F60062603F /* Build configuration list for PBXNativeTarget "SQLite tvOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03A65E6B1C6BB0F60062603F /* Debug */, - 03A65E6C1C6BB0F60062603F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03A65E701C6BB0F60062603F /* Build configuration list for PBXNativeTarget "SQLiteTests tvOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03A65E6D1C6BB0F60062603F /* Debug */, - 03A65E6E1C6BB0F60062603F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - A121AC4C1CA35C79005A31D1 /* Build configuration list for PBXNativeTarget "SQLite watchOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A121AC4A1CA35C79005A31D1 /* Debug */, - A121AC4B1CA35C79005A31D1 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - EE247ACD1C3F04ED00AE3E12 /* Build configuration list for PBXProject "SQLite" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - EE247AE51C3F04ED00AE3E12 /* Debug */, - EE247AE61C3F04ED00AE3E12 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - EE247AE71C3F04ED00AE3E12 /* Build configuration list for PBXNativeTarget "SQLite iOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - EE247AE81C3F04ED00AE3E12 /* Debug */, - EE247AE91C3F04ED00AE3E12 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - EE247AEA1C3F04ED00AE3E12 /* Build configuration list for PBXNativeTarget "SQLiteTests iOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - EE247AEB1C3F04ED00AE3E12 /* Debug */, - EE247AEC1C3F04ED00AE3E12 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - EE247B511C3F3ED000AE3E12 /* Build configuration list for PBXNativeTarget "SQLite Mac" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - EE247B4D1C3F3ED000AE3E12 /* Debug */, - EE247B4E1C3F3ED000AE3E12 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - EE247B521C3F3ED000AE3E12 /* Build configuration list for PBXNativeTarget "SQLiteTests Mac" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - EE247B4F1C3F3ED000AE3E12 /* Debug */, - EE247B501C3F3ED000AE3E12 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = EE247ACA1C3F04ED00AE3E12 /* Project object */; -} diff --git a/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme b/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme deleted file mode 100755 index 4e94e80..0000000 --- a/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme b/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme deleted file mode 100755 index f4ba423..0000000 --- a/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme b/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme deleted file mode 100755 index 7a3ddbf..0000000 --- a/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme b/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme deleted file mode 100755 index ace0271..0000000 --- a/ios/libs/Sqlite/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/libs/Sqlite/SQLite.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/libs/Sqlite/SQLite.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index eb2f43a..0000000 --- a/ios/libs/Sqlite/SQLite.xcodeproj/xcuserdata/nikitasirotkin.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,29 +0,0 @@ - - - - - SchemeUserState - - SQLite Mac.xcscheme_^#shared#^_ - - orderHint - 4 - - SQLite iOS.xcscheme_^#shared#^_ - - orderHint - 3 - - SQLite tvOS.xcscheme_^#shared#^_ - - orderHint - 5 - - SQLite watchOS.xcscheme_^#shared#^_ - - orderHint - 6 - - - - diff --git a/ios/libs/Sqlite/Sources/SQLite/Core/Blob.swift b/ios/libs/Sqlite/Sources/SQLite/Core/Blob.swift deleted file mode 100755 index 2f5d2a1..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Core/Blob.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -public struct Blob { - - public let bytes: [UInt8] - - public init(bytes: [UInt8]) { - self.bytes = bytes - } - - public init(bytes: UnsafeRawPointer, length: Int) { - let i8bufptr = UnsafeBufferPointer(start: bytes.assumingMemoryBound(to: UInt8.self), count: length) - self.init(bytes: [UInt8](i8bufptr)) - } - - public func toHex() -> String { - return bytes.map { - ($0 < 16 ? "0" : "") + String($0, radix: 16, uppercase: false) - }.joined(separator: "") - } - -} - -extension Blob : CustomStringConvertible { - - public var description: String { - return "x'\(toHex())'" - } - -} - -extension Blob : Equatable { - -} - -public func ==(lhs: Blob, rhs: Blob) -> Bool { - return lhs.bytes == rhs.bytes -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Core/Connection.swift b/ios/libs/Sqlite/Sources/SQLite/Core/Connection.swift deleted file mode 100755 index 1bbf7f7..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Core/Connection.swift +++ /dev/null @@ -1,750 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import Foundation -import Dispatch -#if SQLITE_SWIFT_STANDALONE -import sqlite3 -#elseif SQLITE_SWIFT_SQLCIPHER -import SQLCipher -#elseif os(Linux) -import CSQLite -#else -import SQLite3 -#endif - -/// A connection to SQLite. -public final class Connection { - - /// The location of a SQLite database. - public enum Location { - - /// An in-memory database (equivalent to `.uri(":memory:")`). - /// - /// See: - case inMemory - - /// A temporary, file-backed database (equivalent to `.uri("")`). - /// - /// See: - case temporary - - /// A database located at the given URI filename (or path). - /// - /// See: - /// - /// - Parameter filename: A URI filename - case uri(String) - } - - /// An SQL operation passed to update callbacks. - public enum Operation { - - /// An INSERT operation. - case insert - - /// An UPDATE operation. - case update - - /// A DELETE operation. - case delete - - fileprivate init(rawValue:Int32) { - switch rawValue { - case SQLITE_INSERT: - self = .insert - case SQLITE_UPDATE: - self = .update - case SQLITE_DELETE: - self = .delete - default: - fatalError("unhandled operation code: \(rawValue)") - } - } - } - - public var handle: OpaquePointer { return _handle! } - - fileprivate var _handle: OpaquePointer? = nil - - /// Initializes a new SQLite connection. - /// - /// - Parameters: - /// - /// - location: The location of the database. Creates a new database if it - /// doesn’t already exist (unless in read-only mode). - /// - /// Default: `.inMemory`. - /// - /// - readonly: Whether or not to open the database in a read-only state. - /// - /// Default: `false`. - /// - /// - Returns: A new database connection. - public init(_ location: Location = .inMemory, readonly: Bool = false) throws { - let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE - try check(sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil)) - queue.setSpecific(key: Connection.queueKey, value: queueContext) - } - - /// Initializes a new connection to a database. - /// - /// - Parameters: - /// - /// - filename: The location of the database. Creates a new database if - /// it doesn’t already exist (unless in read-only mode). - /// - /// - readonly: Whether or not to open the database in a read-only state. - /// - /// Default: `false`. - /// - /// - Throws: `Result.Error` iff a connection cannot be established. - /// - /// - Returns: A new database connection. - public convenience init(_ filename: String, readonly: Bool = false) throws { - try self.init(.uri(filename), readonly: readonly) - } - - deinit { - sqlite3_close(handle) - } - - // MARK: - - - /// Whether or not the database was opened in a read-only state. - public var readonly: Bool { return sqlite3_db_readonly(handle, nil) == 1 } - - /// The last rowid inserted into the database via this connection. - public var lastInsertRowid: Int64 { - return sqlite3_last_insert_rowid(handle) - } - - /// The last number of changes (inserts, updates, or deletes) made to the - /// database via this connection. - public var changes: Int { - return Int(sqlite3_changes(handle)) - } - - /// The total number of changes (inserts, updates, or deletes) made to the - /// database via this connection. - public var totalChanges: Int { - return Int(sqlite3_total_changes(handle)) - } - - // MARK: - Execute - - /// Executes a batch of SQL statements. - /// - /// - Parameter SQL: A batch of zero or more semicolon-separated SQL - /// statements. - /// - /// - Throws: `Result.Error` if query execution fails. - public func execute(_ SQL: String) throws { - _ = try sync { try self.check(sqlite3_exec(self.handle, SQL, nil, nil, nil)) } - } - - // MARK: - Prepare - - /// Prepares a single SQL statement (with optional parameter bindings). - /// - /// - Parameters: - /// - /// - statement: A single SQL statement. - /// - /// - bindings: A list of parameters to bind to the statement. - /// - /// - Returns: A prepared statement. - public func prepare(_ statement: String, _ bindings: Binding?...) throws -> Statement { - if !bindings.isEmpty { return try prepare(statement, bindings) } - return try Statement(self, statement) - } - - /// Prepares a single SQL statement and binds parameters to it. - /// - /// - Parameters: - /// - /// - statement: A single SQL statement. - /// - /// - bindings: A list of parameters to bind to the statement. - /// - /// - Returns: A prepared statement. - public func prepare(_ statement: String, _ bindings: [Binding?]) throws -> Statement { - return try prepare(statement).bind(bindings) - } - - /// Prepares a single SQL statement and binds parameters to it. - /// - /// - Parameters: - /// - /// - statement: A single SQL statement. - /// - /// - bindings: A dictionary of named parameters to bind to the statement. - /// - /// - Returns: A prepared statement. - public func prepare(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement { - return try prepare(statement).bind(bindings) - } - - // MARK: - Run - - /// Runs a single SQL statement (with optional parameter bindings). - /// - /// - Parameters: - /// - /// - statement: A single SQL statement. - /// - /// - bindings: A list of parameters to bind to the statement. - /// - /// - Throws: `Result.Error` if query execution fails. - /// - /// - Returns: The statement. - @discardableResult public func run(_ statement: String, _ bindings: Binding?...) throws -> Statement { - return try run(statement, bindings) - } - - /// Prepares, binds, and runs a single SQL statement. - /// - /// - Parameters: - /// - /// - statement: A single SQL statement. - /// - /// - bindings: A list of parameters to bind to the statement. - /// - /// - Throws: `Result.Error` if query execution fails. - /// - /// - Returns: The statement. - @discardableResult public func run(_ statement: String, _ bindings: [Binding?]) throws -> Statement { - return try prepare(statement).run(bindings) - } - - /// Prepares, binds, and runs a single SQL statement. - /// - /// - Parameters: - /// - /// - statement: A single SQL statement. - /// - /// - bindings: A dictionary of named parameters to bind to the statement. - /// - /// - Throws: `Result.Error` if query execution fails. - /// - /// - Returns: The statement. - @discardableResult public func run(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement { - return try prepare(statement).run(bindings) - } - - // MARK: - Scalar - - /// Runs a single SQL statement (with optional parameter bindings), - /// returning the first value of the first row. - /// - /// - Parameters: - /// - /// - statement: A single SQL statement. - /// - /// - bindings: A list of parameters to bind to the statement. - /// - /// - Returns: The first value of the first row returned. - public func scalar(_ statement: String, _ bindings: Binding?...) throws -> Binding? { - return try scalar(statement, bindings) - } - - /// Runs a single SQL statement (with optional parameter bindings), - /// returning the first value of the first row. - /// - /// - Parameters: - /// - /// - statement: A single SQL statement. - /// - /// - bindings: A list of parameters to bind to the statement. - /// - /// - Returns: The first value of the first row returned. - public func scalar(_ statement: String, _ bindings: [Binding?]) throws -> Binding? { - return try prepare(statement).scalar(bindings) - } - - /// Runs a single SQL statement (with optional parameter bindings), - /// returning the first value of the first row. - /// - /// - Parameters: - /// - /// - statement: A single SQL statement. - /// - /// - bindings: A dictionary of named parameters to bind to the statement. - /// - /// - Returns: The first value of the first row returned. - public func scalar(_ statement: String, _ bindings: [String: Binding?]) throws -> Binding? { - return try prepare(statement).scalar(bindings) - } - - // MARK: - Transactions - - /// The mode in which a transaction acquires a lock. - public enum TransactionMode : String { - - /// Defers locking the database till the first read/write executes. - case deferred = "DEFERRED" - - /// Immediately acquires a reserved lock on the database. - case immediate = "IMMEDIATE" - - /// Immediately acquires an exclusive lock on all databases. - case exclusive = "EXCLUSIVE" - - } - - // TODO: Consider not requiring a throw to roll back? - /// Runs a transaction with the given mode. - /// - /// - Note: Transactions cannot be nested. To nest transactions, see - /// `savepoint()`, instead. - /// - /// - Parameters: - /// - /// - mode: The mode in which a transaction acquires a lock. - /// - /// Default: `.deferred` - /// - /// - block: A closure to run SQL statements within the transaction. - /// The transaction will be committed when the block returns. The block - /// must throw to roll the transaction back. - /// - /// - Throws: `Result.Error`, and rethrows. - public func transaction(_ mode: TransactionMode = .deferred, block: () throws -> Void) throws { - try transaction("BEGIN \(mode.rawValue) TRANSACTION", block, "COMMIT TRANSACTION", or: "ROLLBACK TRANSACTION") - } - - // TODO: Consider not requiring a throw to roll back? - // TODO: Consider removing ability to set a name? - /// Runs a transaction with the given savepoint name (if omitted, it will - /// generate a UUID). - /// - /// - SeeAlso: `transaction()`. - /// - /// - Parameters: - /// - /// - savepointName: A unique identifier for the savepoint (optional). - /// - /// - block: A closure to run SQL statements within the transaction. - /// The savepoint will be released (committed) when the block returns. - /// The block must throw to roll the savepoint back. - /// - /// - Throws: `SQLite.Result.Error`, and rethrows. - public func savepoint(_ name: String = UUID().uuidString, block: () throws -> Void) throws { - let name = name.quote("'") - let savepoint = "SAVEPOINT \(name)" - - try transaction(savepoint, block, "RELEASE \(savepoint)", or: "ROLLBACK TO \(savepoint)") - } - - fileprivate func transaction(_ begin: String, _ block: () throws -> Void, _ commit: String, or rollback: String) throws { - return try sync { - try self.run(begin) - do { - try block() - try self.run(commit) - } catch { - try self.run(rollback) - throw error - } - } - } - - /// Interrupts any long-running queries. - public func interrupt() { - sqlite3_interrupt(handle) - } - - // MARK: - Handlers - - /// The number of seconds a connection will attempt to retry a statement - /// after encountering a busy signal (lock). - public var busyTimeout: Double = 0 { - didSet { - sqlite3_busy_timeout(handle, Int32(busyTimeout * 1_000)) - } - } - - /// Sets a handler to call after encountering a busy signal (lock). - /// - /// - Parameter callback: This block is executed during a lock in which a - /// busy error would otherwise be returned. It’s passed the number of - /// times it’s been called for this lock. If it returns `true`, it will - /// try again. If it returns `false`, no further attempts will be made. - public func busyHandler(_ callback: ((_ tries: Int) -> Bool)?) { - guard let callback = callback else { - sqlite3_busy_handler(handle, nil, nil) - busyHandler = nil - return - } - - let box: BusyHandler = { callback(Int($0)) ? 1 : 0 } - sqlite3_busy_handler(handle, { callback, tries in - unsafeBitCast(callback, to: BusyHandler.self)(tries) - }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self)) - busyHandler = box - } - fileprivate typealias BusyHandler = @convention(block) (Int32) -> Int32 - fileprivate var busyHandler: BusyHandler? - - /// Sets a handler to call when a statement is executed with the compiled - /// SQL. - /// - /// - Parameter callback: This block is invoked when a statement is executed - /// with the compiled SQL as its argument. - /// - /// db.trace { SQL in print(SQL) } - public func trace(_ callback: ((String) -> Void)?) { - #if SQLITE_SWIFT_SQLCIPHER || os(Linux) - trace_v1(callback) - #else - if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) { - trace_v2(callback) - } else { - trace_v1(callback) - } - #endif - } - - fileprivate func trace_v1(_ callback: ((String) -> Void)?) { - guard let callback = callback else { - sqlite3_trace(handle, nil /* xCallback */, nil /* pCtx */) - trace = nil - return - } - let box: Trace = { (pointer: UnsafeRawPointer) in - callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self))) - } - sqlite3_trace(handle, - { - (C: UnsafeMutableRawPointer?, SQL: UnsafePointer?) in - if let C = C, let SQL = SQL { - unsafeBitCast(C, to: Trace.self)(SQL) - } - }, - unsafeBitCast(box, to: UnsafeMutableRawPointer.self) - ) - trace = box - } - - - - - fileprivate typealias Trace = @convention(block) (UnsafeRawPointer) -> Void - fileprivate var trace: Trace? - - /// Registers a callback to be invoked whenever a row is inserted, updated, - /// or deleted in a rowid table. - /// - /// - Parameter callback: A callback invoked with the `Operation` (one of - /// `.Insert`, `.Update`, or `.Delete`), database name, table name, and - /// rowid. - public func updateHook(_ callback: ((_ operation: Operation, _ db: String, _ table: String, _ rowid: Int64) -> Void)?) { - guard let callback = callback else { - sqlite3_update_hook(handle, nil, nil) - updateHook = nil - return - } - - let box: UpdateHook = { - callback( - Operation(rawValue: $0), - String(cString: $1), - String(cString: $2), - $3 - ) - } - sqlite3_update_hook(handle, { callback, operation, db, table, rowid in - unsafeBitCast(callback, to: UpdateHook.self)(operation, db!, table!, rowid) - }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self)) - updateHook = box - } - fileprivate typealias UpdateHook = @convention(block) (Int32, UnsafePointer, UnsafePointer, Int64) -> Void - fileprivate var updateHook: UpdateHook? - - /// Registers a callback to be invoked whenever a transaction is committed. - /// - /// - Parameter callback: A callback invoked whenever a transaction is - /// committed. If this callback throws, the transaction will be rolled - /// back. - public func commitHook(_ callback: (() throws -> Void)?) { - guard let callback = callback else { - sqlite3_commit_hook(handle, nil, nil) - commitHook = nil - return - } - - let box: CommitHook = { - do { - try callback() - } catch { - return 1 - } - return 0 - } - sqlite3_commit_hook(handle, { callback in - unsafeBitCast(callback, to: CommitHook.self)() - }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self)) - commitHook = box - } - fileprivate typealias CommitHook = @convention(block) () -> Int32 - fileprivate var commitHook: CommitHook? - - /// Registers a callback to be invoked whenever a transaction rolls back. - /// - /// - Parameter callback: A callback invoked when a transaction is rolled - /// back. - public func rollbackHook(_ callback: (() -> Void)?) { - guard let callback = callback else { - sqlite3_rollback_hook(handle, nil, nil) - rollbackHook = nil - return - } - - let box: RollbackHook = { callback() } - sqlite3_rollback_hook(handle, { callback in - unsafeBitCast(callback, to: RollbackHook.self)() - }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self)) - rollbackHook = box - } - fileprivate typealias RollbackHook = @convention(block) () -> Void - fileprivate var rollbackHook: RollbackHook? - - /// Creates or redefines a custom SQL function. - /// - /// - Parameters: - /// - /// - function: The name of the function to create or redefine. - /// - /// - argumentCount: The number of arguments that the function takes. If - /// `nil`, the function may take any number of arguments. - /// - /// Default: `nil` - /// - /// - deterministic: Whether or not the function is deterministic (_i.e._ - /// the function always returns the same result for a given input). - /// - /// Default: `false` - /// - /// - block: A block of code to run when the function is called. The block - /// is called with an array of raw SQL values mapped to the function’s - /// parameters and should return a raw SQL value (or nil). - public func createFunction(_ function: String, argumentCount: UInt? = nil, deterministic: Bool = false, _ block: @escaping (_ args: [Binding?]) -> Binding?) { - let argc = argumentCount.map { Int($0) } ?? -1 - let box: Function = { context, argc, argv in - let arguments: [Binding?] = (0..?) -> Void - fileprivate var functions = [String: [Int: Function]]() - - /// Defines a new collating sequence. - /// - /// - Parameters: - /// - /// - collation: The name of the collation added. - /// - /// - block: A collation function that takes two strings and returns the - /// comparison result. - public func createCollation(_ collation: String, _ block: @escaping (_ lhs: String, _ rhs: String) -> ComparisonResult) throws { - let box: Collation = { (lhs: UnsafeRawPointer, rhs: UnsafeRawPointer) in - let lstr = String(cString: lhs.assumingMemoryBound(to: UInt8.self)) - let rstr = String(cString: rhs.assumingMemoryBound(to: UInt8.self)) - return Int32(block(lstr, rstr).rawValue) - } - try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8, - unsafeBitCast(box, to: UnsafeMutableRawPointer.self), - { (callback: UnsafeMutableRawPointer?, _, lhs: UnsafeRawPointer?, _, rhs: UnsafeRawPointer?) in /* xCompare */ - if let lhs = lhs, let rhs = rhs { - return unsafeBitCast(callback, to: Collation.self)(lhs, rhs) - } else { - fatalError("sqlite3_create_collation_v2 callback called with NULL pointer") - } - }, nil /* xDestroy */)) - collations[collation] = box - } - fileprivate typealias Collation = @convention(block) (UnsafeRawPointer, UnsafeRawPointer) -> Int32 - fileprivate var collations = [String: Collation]() - - // MARK: - Error Handling - - func sync(_ block: () throws -> T) rethrows -> T { - if DispatchQueue.getSpecific(key: Connection.queueKey) == queueContext { - return try block() - } else { - return try queue.sync(execute: block) - } - } - - @discardableResult func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 { - guard let error = Result(errorCode: resultCode, connection: self, statement: statement) else { - return resultCode - } - - throw error - } - - fileprivate var queue = DispatchQueue(label: "SQLite.Database", attributes: []) - - fileprivate static let queueKey = DispatchSpecificKey() - - fileprivate lazy var queueContext: Int = unsafeBitCast(self, to: Int.self) - -} - -extension Connection : CustomStringConvertible { - - public var description: String { - return String(cString: sqlite3_db_filename(handle, nil)) - } - -} - -extension Connection.Location : CustomStringConvertible { - - public var description: String { - switch self { - case .inMemory: - return ":memory:" - case .temporary: - return "" - case .uri(let URI): - return URI - } - } - -} - -public enum Result : Error { - - fileprivate static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE] - - /// Represents a SQLite specific [error code](https://sqlite.org/rescode.html) - /// - /// - message: English-language text that describes the error - /// - /// - code: SQLite [error code](https://sqlite.org/rescode.html#primary_result_code_list) - /// - /// - statement: the statement which produced the error - case error(message: String, code: Int32, statement: Statement?) - - init?(errorCode: Int32, connection: Connection, statement: Statement? = nil) { - guard !Result.successCodes.contains(errorCode) else { return nil } - - let message = String(cString: sqlite3_errmsg(connection.handle)) - self = .error(message: message, code: errorCode, statement: statement) - } - -} - -extension Result : CustomStringConvertible { - - public var description: String { - switch self { - case let .error(message, errorCode, statement): - if let statement = statement { - return "\(message) (\(statement)) (code: \(errorCode))" - } else { - return "\(message) (code: \(errorCode))" - } - } - } -} - -#if !SQLITE_SWIFT_SQLCIPHER && !os(Linux) -@available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) -extension Connection { - fileprivate func trace_v2(_ callback: ((String) -> Void)?) { - guard let callback = callback else { - // If the X callback is NULL or if the M mask is zero, then tracing is disabled. - sqlite3_trace_v2(handle, 0 /* mask */, nil /* xCallback */, nil /* pCtx */) - trace = nil - return - } - - let box: Trace = { (pointer: UnsafeRawPointer) in - callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self))) - } - sqlite3_trace_v2(handle, - UInt32(SQLITE_TRACE_STMT) /* mask */, - { - // A trace callback is invoked with four arguments: callback(T,C,P,X). - // The T argument is one of the SQLITE_TRACE constants to indicate why the - // callback was invoked. The C argument is a copy of the context pointer. - // The P and X arguments are pointers whose meanings depend on T. - (T: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, X: UnsafeMutableRawPointer?) in - if let P = P, - let expandedSQL = sqlite3_expanded_sql(OpaquePointer(P)) { - unsafeBitCast(C, to: Trace.self)(expandedSQL) - sqlite3_free(expandedSQL) - } - return Int32(0) // currently ignored - }, - unsafeBitCast(box, to: UnsafeMutableRawPointer.self) /* pCtx */ - ) - trace = box - } -} -#endif diff --git a/ios/libs/Sqlite/Sources/SQLite/Core/Errors.swift b/ios/libs/Sqlite/Sources/SQLite/Core/Errors.swift deleted file mode 100755 index 3cd7ae9..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Core/Errors.swift +++ /dev/null @@ -1,21 +0,0 @@ -import Foundation - -public enum QueryError: Error, CustomStringConvertible { - case noSuchTable(name: String) - case noSuchColumn(name: String, columns: [String]) - case ambiguousColumn(name: String, similar: [String]) - case unexpectedNullValue(name: String) - - public var description: String { - switch self { - case .noSuchTable(let name): - return "No such table: \(name)" - case .noSuchColumn(let name, let columns): - return "No such column `\(name)` in columns \(columns)" - case .ambiguousColumn(let name, let similar): - return "Ambiguous column `\(name)` (please disambiguate: \(similar))" - case .unexpectedNullValue(let name): - return "Unexpected null value for column `\(name)`" - } - } -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Core/Statement.swift b/ios/libs/Sqlite/Sources/SQLite/Core/Statement.swift deleted file mode 100755 index dc91d3d..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Core/Statement.swift +++ /dev/null @@ -1,317 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#if SQLITE_SWIFT_STANDALONE -import sqlite3 -#elseif SQLITE_SWIFT_SQLCIPHER -import SQLCipher -#elseif os(Linux) -import CSQLite -#else -import SQLite3 -#endif - -/// A single SQL statement. -public final class Statement { - - fileprivate var handle: OpaquePointer? = nil - - fileprivate let connection: Connection - - init(_ connection: Connection, _ SQL: String) throws { - self.connection = connection - try connection.check(sqlite3_prepare_v2(connection.handle, SQL, -1, &handle, nil)) - } - - deinit { - sqlite3_finalize(handle) - } - - public lazy var columnCount: Int = Int(sqlite3_column_count(self.handle)) - - public lazy var columnNames: [String] = (0.. Statement { - return bind(values) - } - - /// Binds a list of parameters to a statement. - /// - /// - Parameter values: A list of parameters to bind to the statement. - /// - /// - Returns: The statement object (useful for chaining). - public func bind(_ values: [Binding?]) -> Statement { - if values.isEmpty { return self } - reset() - guard values.count == Int(sqlite3_bind_parameter_count(handle)) else { - fatalError("\(sqlite3_bind_parameter_count(handle)) values expected, \(values.count) passed") - } - for idx in 1...values.count { bind(values[idx - 1], atIndex: idx) } - return self - } - - /// Binds a dictionary of named parameters to a statement. - /// - /// - Parameter values: A dictionary of named parameters to bind to the - /// statement. - /// - /// - Returns: The statement object (useful for chaining). - public func bind(_ values: [String: Binding?]) -> Statement { - reset() - for (name, value) in values { - let idx = sqlite3_bind_parameter_index(handle, name) - guard idx > 0 else { - fatalError("parameter not found: \(name)") - } - bind(value, atIndex: Int(idx)) - } - return self - } - - fileprivate func bind(_ value: Binding?, atIndex idx: Int) { - if value == nil { - sqlite3_bind_null(handle, Int32(idx)) - } else if let value = value as? Blob { - sqlite3_bind_blob(handle, Int32(idx), value.bytes, Int32(value.bytes.count), SQLITE_TRANSIENT) - } else if let value = value as? Double { - sqlite3_bind_double(handle, Int32(idx), value) - } else if let value = value as? Int64 { - sqlite3_bind_int64(handle, Int32(idx), value) - } else if let value = value as? String { - sqlite3_bind_text(handle, Int32(idx), value, -1, SQLITE_TRANSIENT) - } else if let value = value as? Int { - self.bind(value.datatypeValue, atIndex: idx) - } else if let value = value as? Bool { - self.bind(value.datatypeValue, atIndex: idx) - } else if let value = value { - fatalError("tried to bind unexpected value \(value)") - } - } - - /// - Parameter bindings: A list of parameters to bind to the statement. - /// - /// - Throws: `Result.Error` if query execution fails. - /// - /// - Returns: The statement object (useful for chaining). - @discardableResult public func run(_ bindings: Binding?...) throws -> Statement { - guard bindings.isEmpty else { - return try run(bindings) - } - - reset(clearBindings: false) - repeat {} while try step() - return self - } - - /// - Parameter bindings: A list of parameters to bind to the statement. - /// - /// - Throws: `Result.Error` if query execution fails. - /// - /// - Returns: The statement object (useful for chaining). - @discardableResult public func run(_ bindings: [Binding?]) throws -> Statement { - return try bind(bindings).run() - } - - /// - Parameter bindings: A dictionary of named parameters to bind to the - /// statement. - /// - /// - Throws: `Result.Error` if query execution fails. - /// - /// - Returns: The statement object (useful for chaining). - @discardableResult public func run(_ bindings: [String: Binding?]) throws -> Statement { - return try bind(bindings).run() - } - - /// - Parameter bindings: A list of parameters to bind to the statement. - /// - /// - Returns: The first value of the first row returned. - public func scalar(_ bindings: Binding?...) throws -> Binding? { - guard bindings.isEmpty else { - return try scalar(bindings) - } - - reset(clearBindings: false) - _ = try step() - return row[0] - } - - /// - Parameter bindings: A list of parameters to bind to the statement. - /// - /// - Returns: The first value of the first row returned. - public func scalar(_ bindings: [Binding?]) throws -> Binding? { - return try bind(bindings).scalar() - } - - - /// - Parameter bindings: A dictionary of named parameters to bind to the - /// statement. - /// - /// - Returns: The first value of the first row returned. - public func scalar(_ bindings: [String: Binding?]) throws -> Binding? { - return try bind(bindings).scalar() - } - - public func step() throws -> Bool { - return try connection.sync { try self.connection.check(sqlite3_step(self.handle)) == SQLITE_ROW } - } - - fileprivate func reset(clearBindings shouldClear: Bool = true) { - sqlite3_reset(handle) - if (shouldClear) { sqlite3_clear_bindings(handle) } - } - -} - -extension Statement : Sequence { - - public func makeIterator() -> Statement { - reset(clearBindings: false) - return self - } - -} - -public protocol FailableIterator : IteratorProtocol { - func failableNext() throws -> Self.Element? -} - -extension FailableIterator { - public func next() -> Element? { - return try! failableNext() - } -} - -extension Array { - public init(_ failableIterator: I) throws where I.Element == Element { - self.init() - while let row = try failableIterator.failableNext() { - append(row) - } - } -} - -extension Statement : FailableIterator { - public typealias Element = [Binding?] - public func failableNext() throws -> [Binding?]? { - return try step() ? Array(row) : nil - } -} - -extension Statement : CustomStringConvertible { - - public var description: String { - return String(cString: sqlite3_sql(handle)) - } - -} - -public struct Cursor { - - fileprivate let handle: OpaquePointer - - fileprivate let columnCount: Int - - fileprivate init(_ statement: Statement) { - handle = statement.handle! - columnCount = statement.columnCount - } - - public subscript(idx: Int) -> Double { - return sqlite3_column_double(handle, Int32(idx)) - } - - public subscript(idx: Int) -> Int64 { - return sqlite3_column_int64(handle, Int32(idx)) - } - - public subscript(idx: Int) -> String { - return String(cString: UnsafePointer(sqlite3_column_text(handle, Int32(idx)))) - } - - public subscript(idx: Int) -> Blob { - if let pointer = sqlite3_column_blob(handle, Int32(idx)) { - let length = Int(sqlite3_column_bytes(handle, Int32(idx))) - return Blob(bytes: pointer, length: length) - } else { - // The return value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. - // https://www.sqlite.org/c3ref/column_blob.html - return Blob(bytes: []) - } - } - - // MARK: - - - public subscript(idx: Int) -> Bool { - return Bool.fromDatatypeValue(self[idx]) - } - - public subscript(idx: Int) -> Int { - return Int.fromDatatypeValue(self[idx]) - } - -} - -/// Cursors provide direct access to a statement’s current row. -extension Cursor : Sequence { - - public subscript(idx: Int) -> Binding? { - switch sqlite3_column_type(handle, Int32(idx)) { - case SQLITE_BLOB: - return self[idx] as Blob - case SQLITE_FLOAT: - return self[idx] as Double - case SQLITE_INTEGER: - return self[idx] as Int64 - case SQLITE_NULL: - return nil - case SQLITE_TEXT: - return self[idx] as String - case let type: - fatalError("unsupported column type: \(type)") - } - } - - public func makeIterator() -> AnyIterator { - var idx = 0 - return AnyIterator { - if idx >= self.columnCount { - return Optional.none - } else { - idx += 1 - return self[idx - 1] - } - } - } - -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Core/Value.swift b/ios/libs/Sqlite/Sources/SQLite/Core/Value.swift deleted file mode 100755 index 608f0ce..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Core/Value.swift +++ /dev/null @@ -1,132 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -/// - Warning: `Binding` is a protocol that SQLite.swift uses internally to -/// directly map SQLite types to Swift types. -/// -/// Do not conform custom types to the Binding protocol. See the `Value` -/// protocol, instead. -public protocol Binding {} - -public protocol Number : Binding {} - -public protocol Value : Expressible { // extensions cannot have inheritance clauses - - associatedtype ValueType = Self - - associatedtype Datatype : Binding - - static var declaredDatatype: String { get } - - static func fromDatatypeValue(_ datatypeValue: Datatype) -> ValueType - - var datatypeValue: Datatype { get } - -} - -extension Double : Number, Value { - - public static let declaredDatatype = "REAL" - - public static func fromDatatypeValue(_ datatypeValue: Double) -> Double { - return datatypeValue - } - - public var datatypeValue: Double { - return self - } - -} - -extension Int64 : Number, Value { - - public static let declaredDatatype = "INTEGER" - - public static func fromDatatypeValue(_ datatypeValue: Int64) -> Int64 { - return datatypeValue - } - - public var datatypeValue: Int64 { - return self - } - -} - -extension String : Binding, Value { - - public static let declaredDatatype = "TEXT" - - public static func fromDatatypeValue(_ datatypeValue: String) -> String { - return datatypeValue - } - - public var datatypeValue: String { - return self - } - -} - -extension Blob : Binding, Value { - - public static let declaredDatatype = "BLOB" - - public static func fromDatatypeValue(_ datatypeValue: Blob) -> Blob { - return datatypeValue - } - - public var datatypeValue: Blob { - return self - } - -} - -// MARK: - - -extension Bool : Binding, Value { - - public static var declaredDatatype = Int64.declaredDatatype - - public static func fromDatatypeValue(_ datatypeValue: Int64) -> Bool { - return datatypeValue != 0 - } - - public var datatypeValue: Int64 { - return self ? 1 : 0 - } - -} - -extension Int : Number, Value { - - public static var declaredDatatype = Int64.declaredDatatype - - public static func fromDatatypeValue(_ datatypeValue: Int64) -> Int { - return Int(datatypeValue) - } - - public var datatypeValue: Int64 { - return Int64(self) - } - -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Extensions/Cipher.swift b/ios/libs/Sqlite/Sources/SQLite/Extensions/Cipher.swift deleted file mode 100755 index 44919aa..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Extensions/Cipher.swift +++ /dev/null @@ -1,66 +0,0 @@ -#if SQLITE_SWIFT_SQLCIPHER -import SQLCipher - - -/// Extension methods for [SQLCipher](https://www.zetetic.net/sqlcipher/). -/// @see [sqlcipher api](https://www.zetetic.net/sqlcipher/sqlcipher-api/) -extension Connection { - - /// - Returns: the SQLCipher version - public var cipherVersion: String? { - return (try? scalar("PRAGMA cipher_version")) as? String - } - - /// Specify the key for an encrypted database. This routine should be - /// called right after sqlite3_open(). - /// - /// @param key The key to use.The key itself can be a passphrase, which is converted to a key - /// using [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2) key derivation. The result - /// is used as the encryption key for the database. - /// - /// Alternatively, it is possible to specify an exact byte sequence using a blob literal. - /// With this method, it is the calling application's responsibility to ensure that the data - /// provided is a 64 character hex string, which will be converted directly to 32 bytes (256 bits) - /// of key data. - /// e.g. x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99' - /// @param db name of the database, defaults to 'main' - public func key(_ key: String, db: String = "main") throws { - try _key_v2(db: db, keyPointer: key, keySize: key.utf8.count) - } - - public func key(_ key: Blob, db: String = "main") throws { - try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count) - } - - - /// Change the key on an open database. If the current database is not encrypted, this routine - /// will encrypt it. - /// To change the key on an existing encrypted database, it must first be unlocked with the - /// current encryption key. Once the database is readable and writeable, rekey can be used - /// to re-encrypt every page in the database with a new key. - public func rekey(_ key: String, db: String = "main") throws { - try _rekey_v2(db: db, keyPointer: key, keySize: key.utf8.count) - } - - public func rekey(_ key: Blob, db: String = "main") throws { - try _rekey_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count) - } - - // MARK: - private - private func _key_v2(db: String, keyPointer: UnsafePointer, keySize: Int) throws { - try check(sqlite3_key_v2(handle, db, keyPointer, Int32(keySize))) - try cipher_key_check() - } - - private func _rekey_v2(db: String, keyPointer: UnsafePointer, keySize: Int) throws { - try check(sqlite3_rekey_v2(handle, db, keyPointer, Int32(keySize))) - } - - // When opening an existing database, sqlite3_key_v2 will not immediately throw an error if - // the key provided is incorrect. To test that the database can be successfully opened with the - // provided key, it is necessary to perform some operation on the database (i.e. read from it). - private func cipher_key_check() throws { - let _ = try scalar("SELECT count(*) FROM sqlite_master;") - } -} -#endif diff --git a/ios/libs/Sqlite/Sources/SQLite/Extensions/FTS4.swift b/ios/libs/Sqlite/Sources/SQLite/Extensions/FTS4.swift deleted file mode 100755 index 5ef84dd..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Extensions/FTS4.swift +++ /dev/null @@ -1,352 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#if SWIFT_PACKAGE -import SQLiteObjc -#endif - -extension Module { - - public static func FTS4(_ column: Expressible, _ more: Expressible...) -> Module { - return FTS4([column] + more) - } - - public static func FTS4(_ columns: [Expressible] = [], tokenize tokenizer: Tokenizer? = nil) -> Module { - return FTS4(FTS4Config().columns(columns).tokenizer(tokenizer)) - } - - public static func FTS4(_ config: FTS4Config) -> Module { - return Module(name: "fts4", arguments: config.arguments()) - } -} - -extension VirtualTable { - - /// Builds an expression appended with a `MATCH` query against the given - /// pattern. - /// - /// let emails = VirtualTable("emails") - /// - /// emails.filter(emails.match("Hello")) - /// // SELECT * FROM "emails" WHERE "emails" MATCH 'Hello' - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: An expression appended with a `MATCH` query against the given - /// pattern. - public func match(_ pattern: String) -> Expression { - return "MATCH".infix(tableName(), pattern) - } - - public func match(_ pattern: Expression) -> Expression { - return "MATCH".infix(tableName(), pattern) - } - - public func match(_ pattern: Expression) -> Expression { - return "MATCH".infix(tableName(), pattern) - } - - /// Builds a copy of the query with a `WHERE … MATCH` clause. - /// - /// let emails = VirtualTable("emails") - /// - /// emails.match("Hello") - /// // SELECT * FROM "emails" WHERE "emails" MATCH 'Hello' - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: A query with the given `WHERE … MATCH` clause applied. - public func match(_ pattern: String) -> QueryType { - return filter(match(pattern)) - } - - public func match(_ pattern: Expression) -> QueryType { - return filter(match(pattern)) - } - - public func match(_ pattern: Expression) -> QueryType { - return filter(match(pattern)) - } - -} - -public struct Tokenizer { - - public static let Simple = Tokenizer("simple") - - public static let Porter = Tokenizer("porter") - - public static func Unicode61(removeDiacritics: Bool? = nil, tokenchars: Set = [], separators: Set = []) -> Tokenizer { - var arguments = [String]() - - if let removeDiacritics = removeDiacritics { - arguments.append("removeDiacritics=\(removeDiacritics ? 1 : 0)".quote()) - } - - if !tokenchars.isEmpty { - let joined = tokenchars.map { String($0) }.joined(separator: "") - arguments.append("tokenchars=\(joined)".quote()) - } - - if !separators.isEmpty { - let joined = separators.map { String($0) }.joined(separator: "") - arguments.append("separators=\(joined)".quote()) - } - - return Tokenizer("unicode61", arguments) - } - - public static func Custom(_ name: String) -> Tokenizer { - return Tokenizer(Tokenizer.moduleName.quote(), [name.quote()]) - } - - public let name: String - - public let arguments: [String] - - fileprivate init(_ name: String, _ arguments: [String] = []) { - self.name = name - self.arguments = arguments - } - - fileprivate static let moduleName = "SQLite.swift" - -} - -extension Tokenizer : CustomStringConvertible { - - public var description: String { - return ([name] + arguments).joined(separator: " ") - } - -} - -extension Connection { - - public func registerTokenizer(_ submoduleName: String, next: @escaping (String) -> (String, Range)?) throws { - try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { ( - input: UnsafePointer, offset: UnsafeMutablePointer, length: UnsafeMutablePointer) in - let string = String(cString: input) - - guard let (token, range) = next(string) else { return nil } - - let view:String.UTF8View = string.utf8 - - if let from = range.lowerBound.samePosition(in: view), - let to = range.upperBound.samePosition(in: view) { - offset.pointee += Int32(string[string.startIndex.. Self { - self.columnDefinitions.append((column, options)) - return self - } - - @discardableResult open func columns(_ columns: [Expressible]) -> Self { - for column in columns { - self.column(column) - } - return self - } - - /// [Tokenizers](https://www.sqlite.org/fts3.html#tokenizer) - open func tokenizer(_ tokenizer: Tokenizer?) -> Self { - self.tokenizer = tokenizer - return self - } - - /// [The prefix= option](https://www.sqlite.org/fts3.html#section_6_6) - open func prefix(_ prefix: [Int]) -> Self { - self.prefixes += prefix - return self - } - - /// [The content= option](https://www.sqlite.org/fts3.html#section_6_2) - open func externalContent(_ schema: SchemaType) -> Self { - self.externalContentSchema = schema - return self - } - - /// [Contentless FTS4 Tables](https://www.sqlite.org/fts3.html#section_6_2_1) - open func contentless() -> Self { - self.isContentless = true - return self - } - - func formatColumnDefinitions() -> [Expressible] { - return columnDefinitions.map { $0.0 } - } - - func arguments() -> [Expressible] { - return options().arguments - } - - func options() -> Options { - var options = Options() - options.append(formatColumnDefinitions()) - if let tokenizer = tokenizer { - options.append("tokenize", value: Expression(literal: tokenizer.description)) - } - options.appendCommaSeparated("prefix", values:prefixes.sorted().map { String($0) }) - if isContentless { - options.append("content", value: "") - } else if let externalContentSchema = externalContentSchema { - options.append("content", value: externalContentSchema.tableName()) - } - return options - } - - struct Options { - var arguments = [Expressible]() - - @discardableResult mutating func append(_ columns: [Expressible]) -> Options { - arguments.append(contentsOf: columns) - return self - } - - @discardableResult mutating func appendCommaSeparated(_ key: String, values: [String]) -> Options { - if values.isEmpty { - return self - } else { - return append(key, value: values.joined(separator: ",")) - } - } - - @discardableResult mutating func append(_ key: String, value: CustomStringConvertible?) -> Options { - return append(key, value: value?.description) - } - - @discardableResult mutating func append(_ key: String, value: String?) -> Options { - return append(key, value: value.map { Expression($0) }) - } - - @discardableResult mutating func append(_ key: String, value: Expressible?) -> Options { - if let value = value { - arguments.append("=".join([Expression(literal: key), value])) - } - return self - } - } -} - -/// Configuration for the [FTS4](https://www.sqlite.org/fts3.html) extension. -open class FTS4Config : FTSConfig { - /// [The matchinfo= option](https://www.sqlite.org/fts3.html#section_6_4) - public enum MatchInfo : CustomStringConvertible { - case fts3 - public var description: String { - return "fts3" - } - } - - /// [FTS4 options](https://www.sqlite.org/fts3.html#fts4_options) - public enum Order : CustomStringConvertible { - /// Data structures are optimized for returning results in ascending order by docid (default) - case asc - /// FTS4 stores its data in such a way as to optimize returning results in descending order by docid. - case desc - - public var description: String { - switch self { - case .asc: return "asc" - case .desc: return "desc" - } - } - } - - var compressFunction: String? - var uncompressFunction: String? - var languageId: String? - var matchInfo: MatchInfo? - var order: Order? - - override public init() { - } - - /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1) - open func compress(_ functionName: String) -> Self { - self.compressFunction = functionName - return self - } - - /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1) - open func uncompress(_ functionName: String) -> Self { - self.uncompressFunction = functionName - return self - } - - /// [The languageid= option](https://www.sqlite.org/fts3.html#section_6_3) - open func languageId(_ columnName: String) -> Self { - self.languageId = columnName - return self - } - - /// [The matchinfo= option](https://www.sqlite.org/fts3.html#section_6_4) - open func matchInfo(_ matchInfo: MatchInfo) -> Self { - self.matchInfo = matchInfo - return self - } - - /// [FTS4 options](https://www.sqlite.org/fts3.html#fts4_options) - open func order(_ order: Order) -> Self { - self.order = order - return self - } - - override func options() -> Options { - var options = super.options() - for (column, _) in (columnDefinitions.filter { $0.options.contains(.unindexed) }) { - options.append("notindexed", value: column) - } - options.append("languageid", value: languageId) - options.append("compress", value: compressFunction) - options.append("uncompress", value: uncompressFunction) - options.append("matchinfo", value: matchInfo) - options.append("order", value: order) - return options - } -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Extensions/FTS5.swift b/ios/libs/Sqlite/Sources/SQLite/Extensions/FTS5.swift deleted file mode 100755 index 763927f..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Extensions/FTS5.swift +++ /dev/null @@ -1,97 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -extension Module { - public static func FTS5(_ config: FTS5Config) -> Module { - return Module(name: "fts5", arguments: config.arguments()) - } -} - -/// Configuration for the [FTS5](https://www.sqlite.org/fts5.html) extension. -/// -/// **Note:** this is currently only applicable when using SQLite.swift together with a FTS5-enabled version -/// of SQLite. -open class FTS5Config : FTSConfig { - public enum Detail : CustomStringConvertible { - /// store rowid, column number, term offset - case full - /// store rowid, column number - case column - /// store rowid - case none - - public var description: String { - switch self { - case .full: return "full" - case .column: return "column" - case .none: return "none" - } - } - } - - var detail: Detail? - var contentRowId: Expressible? - var columnSize: Int? - - override public init() { - } - - /// [External Content Tables](https://www.sqlite.org/fts5.html#section_4_4_2) - open func contentRowId(_ column: Expressible) -> Self { - self.contentRowId = column - return self - } - - /// [The Columnsize Option](https://www.sqlite.org/fts5.html#section_4_5) - open func columnSize(_ size: Int) -> Self { - self.columnSize = size - return self - } - - /// [The Detail Option](https://www.sqlite.org/fts5.html#section_4_6) - open func detail(_ detail: Detail) -> Self { - self.detail = detail - return self - } - - override func options() -> Options { - var options = super.options() - options.append("content_rowid", value: contentRowId) - if let columnSize = columnSize { - options.append("columnsize", value: Expression(value: columnSize)) - } - options.append("detail", value: detail) - return options - } - - override func formatColumnDefinitions() -> [Expressible] { - return columnDefinitions.map { definition in - if definition.options.contains(.unindexed) { - return " ".join([definition.0, Expression(literal: "UNINDEXED")]) - } else { - return definition.0 - } - } - } -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Extensions/RTree.swift b/ios/libs/Sqlite/Sources/SQLite/Extensions/RTree.swift deleted file mode 100755 index 4fc1a23..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Extensions/RTree.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -extension Module { - - public static func RTree(_ primaryKey: Expression, _ pairs: (Expression, Expression)...) -> Module where T.Datatype == Int64, U.Datatype == Double { - var arguments: [Expressible] = [primaryKey] - - for pair in pairs { - arguments.append(contentsOf: [pair.0, pair.1] as [Expressible]) - } - - return Module(name: "rtree", arguments: arguments) - } - -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Foundation.swift b/ios/libs/Sqlite/Sources/SQLite/Foundation.swift deleted file mode 100755 index cfb79be..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Foundation.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import Foundation - -extension Data : Value { - - public static var declaredDatatype: String { - return Blob.declaredDatatype - } - - public static func fromDatatypeValue(_ dataValue: Blob) -> Data { - return Data(dataValue.bytes) - } - - public var datatypeValue: Blob { - return withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> Blob in - return Blob(bytes: pointer.baseAddress!, length: count) - } - } - -} - -extension Date : Value { - - public static var declaredDatatype: String { - return String.declaredDatatype - } - - public static func fromDatatypeValue(_ stringValue: String) -> Date { - return dateFormatter.date(from: stringValue)! - } - - public var datatypeValue: String { - return dateFormatter.string(from: self) - } - -} - -/// A global date formatter used to serialize and deserialize `NSDate` objects. -/// If multiple date formats are used in an application’s database(s), use a -/// custom `Value` type per additional format. -public var dateFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS" - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.timeZone = TimeZone(secondsFromGMT: 0) - return formatter -}() diff --git a/ios/libs/Sqlite/Sources/SQLite/Helpers.swift b/ios/libs/Sqlite/Sources/SQLite/Helpers.swift deleted file mode 100755 index 115ea5c..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Helpers.swift +++ /dev/null @@ -1,120 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#if SQLITE_SWIFT_STANDALONE -import sqlite3 -#elseif SQLITE_SWIFT_SQLCIPHER -import SQLCipher -#elseif os(Linux) -import CSQLite -#else -import SQLite3 -#endif - -public typealias Star = (Expression?, Expression?) -> Expression - -public func *(_: Expression?, _: Expression?) -> Expression { - return Expression(literal: "*") -} - -public protocol _OptionalType { - - associatedtype WrappedType - -} - -extension Optional : _OptionalType { - - public typealias WrappedType = Wrapped - -} - -// let SQLITE_STATIC = unsafeBitCast(0, sqlite3_destructor_type.self) -let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self) - -extension String { - - func quote(_ mark: Character = "\"") -> String { - let escaped = reduce("") { string, character in - string + (character == mark ? "\(mark)\(mark)" : "\(character)") - } - return "\(mark)\(escaped)\(mark)" - } - - func join(_ expressions: [Expressible]) -> Expressible { - var (template, bindings) = ([String](), [Binding?]()) - for expressible in expressions { - let expression = expressible.expression - template.append(expression.template) - bindings.append(contentsOf: expression.bindings) - } - return Expression(template.joined(separator: self), bindings) - } - - func infix(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression { - let expression = Expression(" \(self) ".join([lhs, rhs]).expression) - guard wrap else { - return expression - } - return "".wrap(expression) - } - - func prefix(_ expressions: Expressible) -> Expressible { - return "\(self) ".wrap(expressions) as Expression - } - - func prefix(_ expressions: [Expressible]) -> Expressible { - return "\(self) ".wrap(expressions) as Expression - } - - func wrap(_ expression: Expressible) -> Expression { - return Expression("\(self)(\(expression.expression.template))", expression.expression.bindings) - } - - func wrap(_ expressions: [Expressible]) -> Expression { - return wrap(", ".join(expressions)) - } - -} - -func transcode(_ literal: Binding?) -> String { - guard let literal = literal else { return "NULL" } - - switch literal { - case let blob as Blob: - return blob.description - case let string as String: - return string.quote("'") - case let binding: - return "\(binding)" - } -} - -func value(_ v: Binding) -> A { - return A.fromDatatypeValue(v as! A.Datatype) as! A -} - -func value(_ v: Binding?) -> A { - return value(v!) -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Info.plist b/ios/libs/Sqlite/Sources/SQLite/Info.plist deleted file mode 100755 index db84c71..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 0.12.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/ios/libs/Sqlite/Sources/SQLite/SQLite.h b/ios/libs/Sqlite/Sources/SQLite/SQLite.h deleted file mode 100755 index 693ce32..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/SQLite.h +++ /dev/null @@ -1,6 +0,0 @@ -@import Foundation; - -FOUNDATION_EXPORT double SQLiteVersionNumber; -FOUNDATION_EXPORT const unsigned char SQLiteVersionString[]; - -#import diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/AggregateFunctions.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/AggregateFunctions.swift deleted file mode 100755 index 2ec2828..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/AggregateFunctions.swift +++ /dev/null @@ -1,264 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -private enum Function: String { - case count - case max - case min - case avg - case sum - case total - - func wrap(_ expression: Expressible) -> Expression { - return self.rawValue.wrap(expression) - } -} - -extension ExpressionType where UnderlyingType : Value { - - /// Builds a copy of the expression prefixed with the `DISTINCT` keyword. - /// - /// let name = Expression("name") - /// name.distinct - /// // DISTINCT "name" - /// - /// - Returns: A copy of the expression prefixed with the `DISTINCT` - /// keyword. - public var distinct: Expression { - return Expression("DISTINCT \(template)", bindings) - } - - /// Builds a copy of the expression wrapped with the `count` aggregate - /// function. - /// - /// let name = Expression("name") - /// name.count - /// // count("name") - /// name.distinct.count - /// // count(DISTINCT "name") - /// - /// - Returns: A copy of the expression wrapped with the `count` aggregate - /// function. - public var count: Expression { - return Function.count.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Value { - - /// Builds a copy of the expression prefixed with the `DISTINCT` keyword. - /// - /// let name = Expression("name") - /// name.distinct - /// // DISTINCT "name" - /// - /// - Returns: A copy of the expression prefixed with the `DISTINCT` - /// keyword. - public var distinct: Expression { - return Expression("DISTINCT \(template)", bindings) - } - - /// Builds a copy of the expression wrapped with the `count` aggregate - /// function. - /// - /// let name = Expression("name") - /// name.count - /// // count("name") - /// name.distinct.count - /// // count(DISTINCT "name") - /// - /// - Returns: A copy of the expression wrapped with the `count` aggregate - /// function. - public var count: Expression { - return Function.count.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype : Comparable { - - /// Builds a copy of the expression wrapped with the `max` aggregate - /// function. - /// - /// let age = Expression("age") - /// age.max - /// // max("age") - /// - /// - Returns: A copy of the expression wrapped with the `max` aggregate - /// function. - public var max: Expression { - return Function.max.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `min` aggregate - /// function. - /// - /// let age = Expression("age") - /// age.min - /// // min("age") - /// - /// - Returns: A copy of the expression wrapped with the `min` aggregate - /// function. - public var min: Expression { - return Function.min.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Value, UnderlyingType.WrappedType.Datatype : Comparable { - - /// Builds a copy of the expression wrapped with the `max` aggregate - /// function. - /// - /// let age = Expression("age") - /// age.max - /// // max("age") - /// - /// - Returns: A copy of the expression wrapped with the `max` aggregate - /// function. - public var max: Expression { - return Function.max.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `min` aggregate - /// function. - /// - /// let age = Expression("age") - /// age.min - /// // min("age") - /// - /// - Returns: A copy of the expression wrapped with the `min` aggregate - /// function. - public var min: Expression { - return Function.min.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype : Number { - - /// Builds a copy of the expression wrapped with the `avg` aggregate - /// function. - /// - /// let salary = Expression("salary") - /// salary.average - /// // avg("salary") - /// - /// - Returns: A copy of the expression wrapped with the `min` aggregate - /// function. - public var average: Expression { - return Function.avg.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `sum` aggregate - /// function. - /// - /// let salary = Expression("salary") - /// salary.sum - /// // sum("salary") - /// - /// - Returns: A copy of the expression wrapped with the `min` aggregate - /// function. - public var sum: Expression { - return Function.sum.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `total` aggregate - /// function. - /// - /// let salary = Expression("salary") - /// salary.total - /// // total("salary") - /// - /// - Returns: A copy of the expression wrapped with the `min` aggregate - /// function. - public var total: Expression { - return Function.total.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Value, UnderlyingType.WrappedType.Datatype : Number { - - /// Builds a copy of the expression wrapped with the `avg` aggregate - /// function. - /// - /// let salary = Expression("salary") - /// salary.average - /// // avg("salary") - /// - /// - Returns: A copy of the expression wrapped with the `min` aggregate - /// function. - public var average: Expression { - return Function.avg.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `sum` aggregate - /// function. - /// - /// let salary = Expression("salary") - /// salary.sum - /// // sum("salary") - /// - /// - Returns: A copy of the expression wrapped with the `min` aggregate - /// function. - public var sum: Expression { - return Function.sum.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `total` aggregate - /// function. - /// - /// let salary = Expression("salary") - /// salary.total - /// // total("salary") - /// - /// - Returns: A copy of the expression wrapped with the `min` aggregate - /// function. - public var total: Expression { - return Function.total.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType == Int { - - static func count(_ star: Star) -> Expression { - return Function.count.wrap(star(nil, nil)) - } - -} - -/// Builds an expression representing `count(*)` (when called with the `*` -/// function literal). -/// -/// count(*) -/// // count(*) -/// -/// - Returns: An expression returning `count(*)` (when called with the `*` -/// function literal). -public func count(_ star: Star) -> Expression { - return Expression.count(star) -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/Coding.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/Coding.swift deleted file mode 100755 index c3fb931..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/Coding.swift +++ /dev/null @@ -1,340 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import Foundation - -extension QueryType { - /// Creates an `INSERT` statement by encoding the given object - /// This method converts any custom nested types to JSON data and does not handle any sort - /// of object relationships. If you want to support relationships between objects you will - /// have to provide your own Encodable implementations that encode the correct ids. - /// - /// - Parameters: - /// - /// - encodable: An encodable object to insert - /// - /// - userInfo: User info to be passed to encoder - /// - /// - otherSetters: Any other setters to include in the insert - /// - /// - Returns: An `INSERT` statement fort the encodable object - public func insert(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert { - let encoder = SQLiteEncoder(userInfo: userInfo) - try encodable.encode(to: encoder) - return self.insert(encoder.setters + otherSetters) - } - - /// Creates an `UPDATE` statement by encoding the given object - /// This method converts any custom nested types to JSON data and does not handle any sort - /// of object relationships. If you want to support relationships between objects you will - /// have to provide your own Encodable implementations that encode the correct ids. - /// - /// - Parameters: - /// - /// - encodable: An encodable object to insert - /// - /// - userInfo: User info to be passed to encoder - /// - /// - otherSetters: Any other setters to include in the insert - /// - /// - Returns: An `UPDATE` statement fort the encodable object - public func update(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Update { - let encoder = SQLiteEncoder(userInfo: userInfo) - try encodable.encode(to: encoder) - return self.update(encoder.setters + otherSetters) - } -} - -extension Row { - /// Decode an object from this row - /// This method expects any custom nested types to be in the form of JSON data and does not handle - /// any sort of object relationships. If you want to support relationships between objects you will - /// have to provide your own Decodable implementations that decodes the correct columns. - /// - /// - Parameter: userInfo - /// - /// - Returns: a decoded object from this row - public func decode(userInfo: [CodingUserInfoKey: Any] = [:]) throws -> V { - return try V(from: self.decoder(userInfo: userInfo)) - } - - public func decoder(userInfo: [CodingUserInfoKey: Any] = [:]) -> Decoder { - return SQLiteDecoder(row: self, userInfo: userInfo) - } -} - -/// Generates a list of settings for an Encodable object -fileprivate class SQLiteEncoder: Encoder { - class SQLiteKeyedEncodingContainer: KeyedEncodingContainerProtocol { - typealias Key = MyKey - - let encoder: SQLiteEncoder - let codingPath: [CodingKey] = [] - - init(encoder: SQLiteEncoder) { - self.encoder = encoder - } - - func superEncoder() -> Swift.Encoder { - fatalError("SQLiteEncoding does not support super encoders") - } - - func superEncoder(forKey key: Key) -> Swift.Encoder { - fatalError("SQLiteEncoding does not support super encoders") - } - - func encodeNil(forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer.Key) throws { - self.encoder.setters.append(Expression(key.stringValue) <- nil) - } - - func encode(_ value: Int, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer.Key) throws { - self.encoder.setters.append(Expression(key.stringValue) <- value) - } - - func encode(_ value: Bool, forKey key: Key) throws { - self.encoder.setters.append(Expression(key.stringValue) <- value) - } - - func encode(_ value: Float, forKey key: Key) throws { - self.encoder.setters.append(Expression(key.stringValue) <- Double(value)) - } - - func encode(_ value: Double, forKey key: Key) throws { - self.encoder.setters.append(Expression(key.stringValue) <- value) - } - - func encode(_ value: String, forKey key: Key) throws { - self.encoder.setters.append(Expression(key.stringValue) <- value) - } - - func encode(_ value: T, forKey key: Key) throws where T : Swift.Encodable { - if let data = value as? Data { - self.encoder.setters.append(Expression(key.stringValue) <- data) - } - else { - let encoded = try JSONEncoder().encode(value) - let string = String(data: encoded, encoding: .utf8) - self.encoder.setters.append(Expression(key.stringValue) <- string) - } - } - - func encode(_ value: Int8, forKey key: Key) throws { - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int8 is not supported")) - } - - func encode(_ value: Int16, forKey key: Key) throws { - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int16 is not supported")) - } - - func encode(_ value: Int32, forKey key: Key) throws { - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int32 is not supported")) - } - - func encode(_ value: Int64, forKey key: Key) throws { - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int64 is not supported")) - } - - func encode(_ value: UInt, forKey key: Key) throws { - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt is not supported")) - } - - func encode(_ value: UInt8, forKey key: Key) throws { - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt8 is not supported")) - } - - func encode(_ value: UInt16, forKey key: Key) throws { - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt16 is not supported")) - } - - func encode(_ value: UInt32, forKey key: Key) throws { - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt32 is not supported")) - } - - func encode(_ value: UInt64, forKey key: Key) throws { - throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt64 is not supported")) - } - - func nestedContainer(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer where NestedKey : CodingKey { - fatalError("encoding a nested container is not supported") - } - - func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer { - fatalError("encoding nested values is not supported") - } - } - - fileprivate var setters: [Setter] = [] - let codingPath: [CodingKey] = [] - let userInfo: [CodingUserInfoKey: Any] - - init(userInfo: [CodingUserInfoKey: Any]) { - self.userInfo = userInfo - } - - func singleValueContainer() -> SingleValueEncodingContainer { - fatalError("not supported") - } - - func unkeyedContainer() -> UnkeyedEncodingContainer { - fatalError("not supported") - } - - func container(keyedBy type: Key.Type) -> KeyedEncodingContainer where Key : CodingKey { - return KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self)) - } -} - -fileprivate class SQLiteDecoder : Decoder { - class SQLiteKeyedDecodingContainer : KeyedDecodingContainerProtocol { - typealias Key = MyKey - - let codingPath: [CodingKey] = [] - let row: Row - - init(row: Row) { - self.row = row - } - - var allKeys: [Key] { - return self.row.columnNames.keys.compactMap({Key(stringValue: $0)}) - } - - func contains(_ key: Key) -> Bool { - return self.row.hasValue(for: key.stringValue) - } - - func decodeNil(forKey key: Key) throws -> Bool { - return !self.contains(key) - } - - func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { - return try self.row.get(Expression(key.stringValue)) - } - - func decode(_ type: Int.Type, forKey key: Key) throws -> Int { - return try self.row.get(Expression(key.stringValue)) - } - - func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an Int8 is not supported")) - } - - func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an Int16 is not supported")) - } - - func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an Int32 is not supported")) - } - - func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt64 is not supported")) - } - - func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt is not supported")) - - } - - func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt8 is not supported")) - } - - func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt16 is not supported")) - } - - func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt32 is not supported")) - } - - func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt64 is not supported")) - } - - func decode(_ type: Float.Type, forKey key: Key) throws -> Float { - return Float(try self.row.get(Expression(key.stringValue))) - } - - func decode(_ type: Double.Type, forKey key: Key) throws -> Double { - return try self.row.get(Expression(key.stringValue)) - } - - func decode(_ type: String.Type, forKey key: Key) throws -> String { - return try self.row.get(Expression(key.stringValue)) - } - - func decode(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable { - if type == Data.self { - let data = try self.row.get(Expression(key.stringValue)) - return data as! T - } - guard let JSONString = try self.row.get(Expression(key.stringValue)) else { - throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "an unsupported type was found")) - } - guard let data = JSONString.data(using: .utf8) else { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "invalid utf8 data found")) - } - return try JSONDecoder().decode(type, from: data) - } - - func nestedContainer(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer where NestedKey : CodingKey { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding nested containers is not supported")) - } - - func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding unkeyed containers is not supported")) - } - - func superDecoder() throws -> Swift.Decoder { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding super encoders containers is not supported")) - } - - func superDecoder(forKey key: Key) throws -> Swift.Decoder { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding super decoders is not supported")) - } - } - - let row: Row - let codingPath: [CodingKey] = [] - let userInfo: [CodingUserInfoKey: Any] - - init(row: Row, userInfo: [CodingUserInfoKey: Any]) { - self.row = row - self.userInfo = userInfo - } - - func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer where Key : CodingKey { - return KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: self.row)) - } - - func unkeyedContainer() throws -> UnkeyedDecodingContainer { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an unkeyed container is not supported")) - } - - func singleValueContainer() throws -> SingleValueDecodingContainer { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding a single value container is not supported")) - } -} - diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/Collation.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/Collation.swift deleted file mode 100755 index e2ff9d1..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/Collation.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -/// A collating function used to compare to strings. -/// -/// - SeeAlso: -public enum Collation { - - /// Compares string by raw data. - case binary - - /// Like binary, but folds uppercase ASCII letters into their lowercase - /// equivalents. - case nocase - - /// Like binary, but strips trailing space. - case rtrim - - /// A custom collating sequence identified by the given string, registered - /// using `Database.create(collation:…)` - case custom(String) - -} - -extension Collation : Expressible { - - public var expression: Expression { - return Expression(literal: description) - } - -} - -extension Collation : CustomStringConvertible { - - public var description : String { - switch self { - case .binary: - return "BINARY" - case .nocase: - return "NOCASE" - case .rtrim: - return "RTRIM" - case .custom(let collation): - return collation.quote() - } - } - -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/CoreFunctions.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/CoreFunctions.swift deleted file mode 100755 index 068dcf0..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/CoreFunctions.swift +++ /dev/null @@ -1,796 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import Foundation - -private enum Function: String { - case abs - case round - case random - case randomblob - case zeroblob - case length - case lower - case upper - case ltrim - case rtrim - case trim - case replace - case substr - case like = "LIKE" - case `in` = "IN" - case glob = "GLOB" - case match = "MATCH" - case regexp = "REGEXP" - case collate = "COLLATE" - case ifnull - - func infix(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression { - return self.rawValue.infix(lhs, rhs, wrap: wrap) - } - - func wrap(_ expression: Expressible) -> Expression { - return self.rawValue.wrap(expression) - } - - func wrap(_ expressions: [Expressible]) -> Expression { - return self.rawValue.wrap(", ".join(expressions)) - } -} - -extension ExpressionType where UnderlyingType : Number { - - /// Builds a copy of the expression wrapped with the `abs` function. - /// - /// let x = Expression("x") - /// x.absoluteValue - /// // abs("x") - /// - /// - Returns: A copy of the expression wrapped with the `abs` function. - public var absoluteValue : Expression { - return Function.abs.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Number { - - /// Builds a copy of the expression wrapped with the `abs` function. - /// - /// let x = Expression("x") - /// x.absoluteValue - /// // abs("x") - /// - /// - Returns: A copy of the expression wrapped with the `abs` function. - public var absoluteValue : Expression { - return Function.abs.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType == Double { - - /// Builds a copy of the expression wrapped with the `round` function. - /// - /// let salary = Expression("salary") - /// salary.round() - /// // round("salary") - /// salary.round(2) - /// // round("salary", 2) - /// - /// - Returns: A copy of the expression wrapped with the `round` function. - public func round(_ precision: Int? = nil) -> Expression { - guard let precision = precision else { - return Function.round.wrap([self]) - } - return Function.round.wrap([self, Int(precision)]) - } - -} - -extension ExpressionType where UnderlyingType == Double? { - - /// Builds a copy of the expression wrapped with the `round` function. - /// - /// let salary = Expression("salary") - /// salary.round() - /// // round("salary") - /// salary.round(2) - /// // round("salary", 2) - /// - /// - Returns: A copy of the expression wrapped with the `round` function. - public func round(_ precision: Int? = nil) -> Expression { - guard let precision = precision else { - return Function.round.wrap(self) - } - return Function.round.wrap([self, Int(precision)]) - } - -} - -extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype == Int64 { - - /// Builds an expression representing the `random` function. - /// - /// Expression.random() - /// // random() - /// - /// - Returns: An expression calling the `random` function. - public static func random() -> Expression { - return Function.random.wrap([]) - } - -} - -extension ExpressionType where UnderlyingType == Data { - - /// Builds an expression representing the `randomblob` function. - /// - /// Expression.random(16) - /// // randomblob(16) - /// - /// - Parameter length: Length in bytes. - /// - /// - Returns: An expression calling the `randomblob` function. - public static func random(_ length: Int) -> Expression { - return Function.randomblob.wrap([]) - } - - /// Builds an expression representing the `zeroblob` function. - /// - /// Expression.allZeros(16) - /// // zeroblob(16) - /// - /// - Parameter length: Length in bytes. - /// - /// - Returns: An expression calling the `zeroblob` function. - public static func allZeros(_ length: Int) -> Expression { - return Function.zeroblob.wrap([]) - } - - /// Builds a copy of the expression wrapped with the `length` function. - /// - /// let data = Expression("data") - /// data.length - /// // length("data") - /// - /// - Returns: A copy of the expression wrapped with the `length` function. - public var length: Expression { - return Function.length.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType == Data? { - - /// Builds a copy of the expression wrapped with the `length` function. - /// - /// let data = Expression("data") - /// data.length - /// // length("data") - /// - /// - Returns: A copy of the expression wrapped with the `length` function. - public var length: Expression { - return Function.length.wrap(self) - } - -} - -extension ExpressionType where UnderlyingType == String { - - /// Builds a copy of the expression wrapped with the `length` function. - /// - /// let name = Expression("name") - /// name.length - /// // length("name") - /// - /// - Returns: A copy of the expression wrapped with the `length` function. - public var length: Expression { - return Function.length.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `lower` function. - /// - /// let name = Expression("name") - /// name.lowercaseString - /// // lower("name") - /// - /// - Returns: A copy of the expression wrapped with the `lower` function. - public var lowercaseString: Expression { - return Function.lower.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `upper` function. - /// - /// let name = Expression("name") - /// name.uppercaseString - /// // lower("name") - /// - /// - Returns: A copy of the expression wrapped with the `upper` function. - public var uppercaseString: Expression { - return Function.upper.wrap(self) - } - - /// Builds a copy of the expression appended with a `LIKE` query against the - /// given pattern. - /// - /// let email = Expression("email") - /// email.like("%@example.com") - /// // "email" LIKE '%@example.com' - /// email.like("99\\%@%", escape: "\\") - /// // "email" LIKE '99\%@%' ESCAPE '\' - /// - /// - Parameters: - /// - /// - pattern: A pattern to match. - /// - /// - escape: An (optional) character designated for escaping - /// pattern-matching characters (*i.e.*, the `%` and `_` characters). - /// - /// - Returns: A copy of the expression appended with a `LIKE` query against - /// the given pattern. - public func like(_ pattern: String, escape character: Character? = nil) -> Expression { - guard let character = character else { - return "LIKE".infix(self, pattern) - } - return Expression("(\(template) LIKE ? ESCAPE ?)", bindings + [pattern, String(character)]) - } - - /// Builds a copy of the expression appended with a `LIKE` query against the - /// given pattern. - /// - /// let email = Expression("email") - /// let pattern = Expression("pattern") - /// email.like(pattern) - /// // "email" LIKE "pattern" - /// - /// - Parameters: - /// - /// - pattern: A pattern to match. - /// - /// - escape: An (optional) character designated for escaping - /// pattern-matching characters (*i.e.*, the `%` and `_` characters). - /// - /// - Returns: A copy of the expression appended with a `LIKE` query against - /// the given pattern. - public func like(_ pattern: Expression, escape character: Character? = nil) -> Expression { - guard let character = character else { - return Function.like.infix(self, pattern) - } - let like: Expression = Function.like.infix(self, pattern, wrap: false) - return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)]) - } - - /// Builds a copy of the expression appended with a `GLOB` query against the - /// given pattern. - /// - /// let path = Expression("path") - /// path.glob("*.png") - /// // "path" GLOB '*.png' - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: A copy of the expression appended with a `GLOB` query against - /// the given pattern. - public func glob(_ pattern: String) -> Expression { - return Function.glob.infix(self, pattern) - } - - /// Builds a copy of the expression appended with a `MATCH` query against - /// the given pattern. - /// - /// let title = Expression("title") - /// title.match("swift AND programming") - /// // "title" MATCH 'swift AND programming' - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: A copy of the expression appended with a `MATCH` query - /// against the given pattern. - public func match(_ pattern: String) -> Expression { - return Function.match.infix(self, pattern) - } - - /// Builds a copy of the expression appended with a `REGEXP` query against - /// the given pattern. - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: A copy of the expression appended with a `REGEXP` query - /// against the given pattern. - public func regexp(_ pattern: String) -> Expression { - return Function.regexp.infix(self, pattern) - } - - /// Builds a copy of the expression appended with a `COLLATE` clause with - /// the given sequence. - /// - /// let name = Expression("name") - /// name.collate(.Nocase) - /// // "name" COLLATE NOCASE - /// - /// - Parameter collation: A collating sequence. - /// - /// - Returns: A copy of the expression appended with a `COLLATE` clause - /// with the given sequence. - public func collate(_ collation: Collation) -> Expression { - return Function.collate.infix(self, collation) - } - - /// Builds a copy of the expression wrapped with the `ltrim` function. - /// - /// let name = Expression("name") - /// name.ltrim() - /// // ltrim("name") - /// name.ltrim([" ", "\t"]) - /// // ltrim("name", ' \t') - /// - /// - Parameter characters: A set of characters to trim. - /// - /// - Returns: A copy of the expression wrapped with the `ltrim` function. - public func ltrim(_ characters: Set? = nil) -> Expression { - guard let characters = characters else { - return Function.ltrim.wrap(self) - } - return Function.ltrim.wrap([self, String(characters)]) - } - - /// Builds a copy of the expression wrapped with the `rtrim` function. - /// - /// let name = Expression("name") - /// name.rtrim() - /// // rtrim("name") - /// name.rtrim([" ", "\t"]) - /// // rtrim("name", ' \t') - /// - /// - Parameter characters: A set of characters to trim. - /// - /// - Returns: A copy of the expression wrapped with the `rtrim` function. - public func rtrim(_ characters: Set? = nil) -> Expression { - guard let characters = characters else { - return Function.rtrim.wrap(self) - } - return Function.rtrim.wrap([self, String(characters)]) - } - - /// Builds a copy of the expression wrapped with the `trim` function. - /// - /// let name = Expression("name") - /// name.trim() - /// // trim("name") - /// name.trim([" ", "\t"]) - /// // trim("name", ' \t') - /// - /// - Parameter characters: A set of characters to trim. - /// - /// - Returns: A copy of the expression wrapped with the `trim` function. - public func trim(_ characters: Set? = nil) -> Expression { - guard let characters = characters else { - return Function.trim.wrap([self]) - } - return Function.trim.wrap([self, String(characters)]) - } - - /// Builds a copy of the expression wrapped with the `replace` function. - /// - /// let email = Expression("email") - /// email.replace("@mac.com", with: "@icloud.com") - /// // replace("email", '@mac.com', '@icloud.com') - /// - /// - Parameters: - /// - /// - pattern: A pattern to match. - /// - /// - replacement: The replacement string. - /// - /// - Returns: A copy of the expression wrapped with the `replace` function. - public func replace(_ pattern: String, with replacement: String) -> Expression { - return Function.replace.wrap([self, pattern, replacement]) - } - - public func substring(_ location: Int, length: Int? = nil) -> Expression { - guard let length = length else { - return Function.substr.wrap([self, location]) - } - return Function.substr.wrap([self, location, length]) - } - - public subscript(range: Range) -> Expression { - return substring(range.lowerBound, length: range.upperBound - range.lowerBound) - } - -} - -extension ExpressionType where UnderlyingType == String? { - - /// Builds a copy of the expression wrapped with the `length` function. - /// - /// let name = Expression("name") - /// name.length - /// // length("name") - /// - /// - Returns: A copy of the expression wrapped with the `length` function. - public var length: Expression { - return Function.length.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `lower` function. - /// - /// let name = Expression("name") - /// name.lowercaseString - /// // lower("name") - /// - /// - Returns: A copy of the expression wrapped with the `lower` function. - public var lowercaseString: Expression { - return Function.lower.wrap(self) - } - - /// Builds a copy of the expression wrapped with the `upper` function. - /// - /// let name = Expression("name") - /// name.uppercaseString - /// // lower("name") - /// - /// - Returns: A copy of the expression wrapped with the `upper` function. - public var uppercaseString: Expression { - return Function.upper.wrap(self) - } - - /// Builds a copy of the expression appended with a `LIKE` query against the - /// given pattern. - /// - /// let email = Expression("email") - /// email.like("%@example.com") - /// // "email" LIKE '%@example.com' - /// email.like("99\\%@%", escape: "\\") - /// // "email" LIKE '99\%@%' ESCAPE '\' - /// - /// - Parameters: - /// - /// - pattern: A pattern to match. - /// - /// - escape: An (optional) character designated for escaping - /// pattern-matching characters (*i.e.*, the `%` and `_` characters). - /// - /// - Returns: A copy of the expression appended with a `LIKE` query against - /// the given pattern. - public func like(_ pattern: String, escape character: Character? = nil) -> Expression { - guard let character = character else { - return Function.like.infix(self, pattern) - } - return Expression("(\(template) LIKE ? ESCAPE ?)", bindings + [pattern, String(character)]) - } - - /// Builds a copy of the expression appended with a `LIKE` query against the - /// given pattern. - /// - /// let email = Expression("email") - /// let pattern = Expression("pattern") - /// email.like(pattern) - /// // "email" LIKE "pattern" - /// - /// - Parameters: - /// - /// - pattern: A pattern to match. - /// - /// - escape: An (optional) character designated for escaping - /// pattern-matching characters (*i.e.*, the `%` and `_` characters). - /// - /// - Returns: A copy of the expression appended with a `LIKE` query against - /// the given pattern. - public func like(_ pattern: Expression, escape character: Character? = nil) -> Expression { - guard let character = character else { - return Function.like.infix(self, pattern) - } - let like: Expression = Function.like.infix(self, pattern, wrap: false) - return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)]) - } - - /// Builds a copy of the expression appended with a `GLOB` query against the - /// given pattern. - /// - /// let path = Expression("path") - /// path.glob("*.png") - /// // "path" GLOB '*.png' - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: A copy of the expression appended with a `GLOB` query against - /// the given pattern. - public func glob(_ pattern: String) -> Expression { - return Function.glob.infix(self, pattern) - } - - /// Builds a copy of the expression appended with a `MATCH` query against - /// the given pattern. - /// - /// let title = Expression("title") - /// title.match("swift AND programming") - /// // "title" MATCH 'swift AND programming' - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: A copy of the expression appended with a `MATCH` query - /// against the given pattern. - public func match(_ pattern: String) -> Expression { - return Function.match.infix(self, pattern) - } - - /// Builds a copy of the expression appended with a `REGEXP` query against - /// the given pattern. - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: A copy of the expression appended with a `REGEXP` query - /// against the given pattern. - public func regexp(_ pattern: String) -> Expression { - return Function.regexp.infix(self, pattern) - } - - /// Builds a copy of the expression appended with a `COLLATE` clause with - /// the given sequence. - /// - /// let name = Expression("name") - /// name.collate(.Nocase) - /// // "name" COLLATE NOCASE - /// - /// - Parameter collation: A collating sequence. - /// - /// - Returns: A copy of the expression appended with a `COLLATE` clause - /// with the given sequence. - public func collate(_ collation: Collation) -> Expression { - return Function.collate.infix(self, collation) - } - - /// Builds a copy of the expression wrapped with the `ltrim` function. - /// - /// let name = Expression("name") - /// name.ltrim() - /// // ltrim("name") - /// name.ltrim([" ", "\t"]) - /// // ltrim("name", ' \t') - /// - /// - Parameter characters: A set of characters to trim. - /// - /// - Returns: A copy of the expression wrapped with the `ltrim` function. - public func ltrim(_ characters: Set? = nil) -> Expression { - guard let characters = characters else { - return Function.ltrim.wrap(self) - } - return Function.ltrim.wrap([self, String(characters)]) - } - - /// Builds a copy of the expression wrapped with the `rtrim` function. - /// - /// let name = Expression("name") - /// name.rtrim() - /// // rtrim("name") - /// name.rtrim([" ", "\t"]) - /// // rtrim("name", ' \t') - /// - /// - Parameter characters: A set of characters to trim. - /// - /// - Returns: A copy of the expression wrapped with the `rtrim` function. - public func rtrim(_ characters: Set? = nil) -> Expression { - guard let characters = characters else { - return Function.rtrim.wrap(self) - } - return Function.rtrim.wrap([self, String(characters)]) - } - - /// Builds a copy of the expression wrapped with the `trim` function. - /// - /// let name = Expression("name") - /// name.trim() - /// // trim("name") - /// name.trim([" ", "\t"]) - /// // trim("name", ' \t') - /// - /// - Parameter characters: A set of characters to trim. - /// - /// - Returns: A copy of the expression wrapped with the `trim` function. - public func trim(_ characters: Set? = nil) -> Expression { - guard let characters = characters else { - return Function.trim.wrap(self) - } - return Function.trim.wrap([self, String(characters)]) - } - - /// Builds a copy of the expression wrapped with the `replace` function. - /// - /// let email = Expression("email") - /// email.replace("@mac.com", with: "@icloud.com") - /// // replace("email", '@mac.com', '@icloud.com') - /// - /// - Parameters: - /// - /// - pattern: A pattern to match. - /// - /// - replacement: The replacement string. - /// - /// - Returns: A copy of the expression wrapped with the `replace` function. - public func replace(_ pattern: String, with replacement: String) -> Expression { - return Function.replace.wrap([self, pattern, replacement]) - } - - /// Builds a copy of the expression wrapped with the `substr` function. - /// - /// let title = Expression("title") - /// title.substr(-100) - /// // substr("title", -100) - /// title.substr(0, length: 100) - /// // substr("title", 0, 100) - /// - /// - Parameters: - /// - /// - location: The substring’s start index. - /// - /// - length: An optional substring length. - /// - /// - Returns: A copy of the expression wrapped with the `substr` function. - public func substring(_ location: Int, length: Int? = nil) -> Expression { - guard let length = length else { - return Function.substr.wrap([self, location]) - } - return Function.substr.wrap([self, location, length]) - } - - /// Builds a copy of the expression wrapped with the `substr` function. - /// - /// let title = Expression("title") - /// title[0..<100] - /// // substr("title", 0, 100) - /// - /// - Parameter range: The character index range of the substring. - /// - /// - Returns: A copy of the expression wrapped with the `substr` function. - public subscript(range: Range) -> Expression { - return substring(range.lowerBound, length: range.upperBound - range.lowerBound) - } - -} - -extension Collection where Iterator.Element : Value { - - /// Builds a copy of the expression prepended with an `IN` check against the - /// collection. - /// - /// let name = Expression("name") - /// ["alice", "betty"].contains(name) - /// // "name" IN ('alice', 'betty') - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: A copy of the expression prepended with an `IN` check against - /// the collection. - public func contains(_ expression: Expression) -> Expression { - let templates = [String](repeating: "?", count: count).joined(separator: ", ") - return Function.in.infix(expression, Expression("(\(templates))", map { $0.datatypeValue })) - } - - /// Builds a copy of the expression prepended with an `IN` check against the - /// collection. - /// - /// let name = Expression("name") - /// ["alice", "betty"].contains(name) - /// // "name" IN ('alice', 'betty') - /// - /// - Parameter pattern: A pattern to match. - /// - /// - Returns: A copy of the expression prepended with an `IN` check against - /// the collection. - public func contains(_ expression: Expression) -> Expression { - let templates = [String](repeating: "?", count: count).joined(separator: ", ") - return Function.in.infix(expression, Expression("(\(templates))", map { $0.datatypeValue })) - } - -} - -extension String { - - /// Builds a copy of the expression appended with a `LIKE` query against the - /// given pattern. - /// - /// let email = "some@thing.com" - /// let pattern = Expression("pattern") - /// email.like(pattern) - /// // 'some@thing.com' LIKE "pattern" - /// - /// - Parameters: - /// - /// - pattern: A pattern to match. - /// - /// - escape: An (optional) character designated for escaping - /// pattern-matching characters (*i.e.*, the `%` and `_` characters). - /// - /// - Returns: A copy of the expression appended with a `LIKE` query against - /// the given pattern. - public func like(_ pattern: Expression, escape character: Character? = nil) -> Expression { - guard let character = character else { - return Function.like.infix(self, pattern) - } - let like: Expression = Function.like.infix(self, pattern, wrap: false) - return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)]) - } - -} - -/// Builds a copy of the given expressions wrapped with the `ifnull` function. -/// -/// let name = Expression("name") -/// name ?? "An Anonymous Coward" -/// // ifnull("name", 'An Anonymous Coward') -/// -/// - Parameters: -/// -/// - optional: An optional expression. -/// -/// - defaultValue: A fallback value for when the optional expression is -/// `nil`. -/// -/// - Returns: A copy of the given expressions wrapped with the `ifnull` -/// function. -public func ??(optional: Expression, defaultValue: V) -> Expression { - return Function.ifnull.wrap([optional, defaultValue]) -} - -/// Builds a copy of the given expressions wrapped with the `ifnull` function. -/// -/// let nick = Expression("nick") -/// let name = Expression("name") -/// nick ?? name -/// // ifnull("nick", "name") -/// -/// - Parameters: -/// -/// - optional: An optional expression. -/// -/// - defaultValue: A fallback expression for when the optional expression is -/// `nil`. -/// -/// - Returns: A copy of the given expressions wrapped with the `ifnull` -/// function. -public func ??(optional: Expression, defaultValue: Expression) -> Expression { - return Function.ifnull.wrap([optional, defaultValue]) -} - -/// Builds a copy of the given expressions wrapped with the `ifnull` function. -/// -/// let nick = Expression("nick") -/// let name = Expression("name") -/// nick ?? name -/// // ifnull("nick", "name") -/// -/// - Parameters: -/// -/// - optional: An optional expression. -/// -/// - defaultValue: A fallback expression for when the optional expression is -/// `nil`. -/// -/// - Returns: A copy of the given expressions wrapped with the `ifnull` -/// function. -public func ??(optional: Expression, defaultValue: Expression) -> Expression { - return Function.ifnull.wrap([optional, defaultValue]) -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/CustomFunctions.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/CustomFunctions.swift deleted file mode 100755 index 8910a24..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/CustomFunctions.swift +++ /dev/null @@ -1,136 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -public extension Connection { - - /// Creates or redefines a custom SQL function. - /// - /// - Parameters: - /// - /// - function: The name of the function to create or redefine. - /// - /// - deterministic: Whether or not the function is deterministic (_i.e._ - /// the function always returns the same result for a given input). - /// - /// Default: `false` - /// - /// - block: A block of code to run when the function is called. - /// The assigned types must be explicit. - /// - /// - Returns: A closure returning an SQL expression to call the function. - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z) throws -> (() -> Expression) { - let fn = try createFunction(function, 0, deterministic) { _ in block() } - return { fn([]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z?) throws -> (() -> Expression) { - let fn = try createFunction(function, 0, deterministic) { _ in block() } - return { fn([]) } - } - - // MARK: - - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z) throws -> ((Expression) -> Expression) { - let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0])) } - return { arg in fn([arg]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z) throws -> ((Expression) -> Expression) { - let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) } - return { arg in fn([arg]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z?) throws -> ((Expression) -> Expression) { - let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0])) } - return { arg in fn([arg]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z?) throws -> ((Expression) -> Expression) { - let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) } - return { arg in fn([arg]) } - } - - // MARK: - - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z) throws -> (Expression, Expression) -> Expression { - let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), value(args[1])) } - return { a, b in fn([a, b]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z) throws -> (Expression, Expression) -> Expression { - let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), value(args[1])) } - return { a, b in fn([a, b]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z) throws -> (Expression, Expression) -> Expression { - let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), args[1].map(value)) } - return { a, b in fn([a, b]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z?) throws -> (Expression, Expression) -> Expression { - let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), value(args[1])) } - return { a, b in fn([a, b]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z) throws -> (Expression, Expression) -> Expression { - let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), args[1].map(value)) } - return { a, b in fn([a, b]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z?) throws -> (Expression, Expression) -> Expression { - let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), value(args[1])) } - return { a, b in fn([a, b]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z?) throws -> (Expression, Expression) -> Expression { - let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), args[1].map(value)) } - return { a, b in fn([a, b]) } - } - - func createFunction(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z?) throws -> (Expression, Expression) -> Expression { - let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), args[1].map(value)) } - return { a, b in fn([a, b]) } - } - - // MARK: - - - fileprivate func createFunction(_ function: String, _ argumentCount: UInt, _ deterministic: Bool, _ block: @escaping ([Binding?]) -> Z) throws -> (([Expressible]) -> Expression) { - createFunction(function, argumentCount: argumentCount, deterministic: deterministic) { arguments in - block(arguments).datatypeValue - } - return { arguments in - function.quote().wrap(", ".join(arguments)) - } - } - - fileprivate func createFunction(_ function: String, _ argumentCount: UInt, _ deterministic: Bool, _ block: @escaping ([Binding?]) -> Z?) throws -> (([Expressible]) -> Expression) { - createFunction(function, argumentCount: argumentCount, deterministic: deterministic) { arguments in - block(arguments)?.datatypeValue - } - return { arguments in - function.quote().wrap(", ".join(arguments)) - } - } - -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/DateAndTimeFunctions.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/DateAndTimeFunctions.swift deleted file mode 100755 index 0b9a497..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/DateAndTimeFunctions.swift +++ /dev/null @@ -1,106 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import Foundation - -/// All five date and time functions take a time string as an argument. -/// The time string is followed by zero or more modifiers. -/// The strftime() function also takes a format string as its first argument. -/// -/// https://www.sqlite.org/lang_datefunc.html -public class DateFunctions { - /// The date() function returns the date in this format: YYYY-MM-DD. - public static func date(_ timestring: String, _ modifiers: String...) -> Expression { - return timefunction("date", timestring: timestring, modifiers: modifiers) - } - - /// The time() function returns the time as HH:MM:SS. - public static func time(_ timestring: String, _ modifiers: String...) -> Expression { - return timefunction("time", timestring: timestring, modifiers: modifiers) - } - - /// The datetime() function returns "YYYY-MM-DD HH:MM:SS". - public static func datetime(_ timestring: String, _ modifiers: String...) -> Expression { - return timefunction("datetime", timestring: timestring, modifiers: modifiers) - } - - /// The julianday() function returns the Julian day - - /// the number of days since noon in Greenwich on November 24, 4714 B.C. - public static func julianday(_ timestring: String, _ modifiers: String...) -> Expression { - return timefunction("julianday", timestring: timestring, modifiers: modifiers) - } - - /// The strftime() routine returns the date formatted according to the format string specified as the first argument. - public static func strftime(_ format: String, _ timestring: String, _ modifiers: String...) -> Expression { - if !modifiers.isEmpty { - let templates = [String](repeating: "?", count: modifiers.count).joined(separator: ", ") - return Expression("strftime(?, ?, \(templates))", [format, timestring] + modifiers) - } - return Expression("strftime(?, ?)", [format, timestring]) - } - - private static func timefunction(_ name: String, timestring: String, modifiers: [String]) -> Expression { - if !modifiers.isEmpty { - let templates = [String](repeating: "?", count: modifiers.count).joined(separator: ", ") - return Expression("\(name)(?, \(templates))", [timestring] + modifiers) - } - return Expression("\(name)(?)", [timestring]) - } -} - -extension Date { - public var date: Expression { - return DateFunctions.date(dateFormatter.string(from: self)) - } - - public var time: Expression { - return DateFunctions.time(dateFormatter.string(from: self)) - } - - public var datetime: Expression { - return DateFunctions.datetime(dateFormatter.string(from: self)) - } - - public var julianday: Expression { - return DateFunctions.julianday(dateFormatter.string(from: self)) - } -} - -extension Expression where UnderlyingType == Date { - public var date: Expression { - return Expression("date(\(template))", bindings) - } - - public var time: Expression { - return Expression("time(\(template))", bindings) - } - - public var datetime: Expression { - return Expression("datetime(\(template))", bindings) - } - - public var julianday: Expression { - return Expression("julianday(\(template))", bindings) - } -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/Expression.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/Expression.swift deleted file mode 100755 index 76ba04c..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/Expression.swift +++ /dev/null @@ -1,147 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -public protocol ExpressionType : Expressible { // extensions cannot have inheritance clauses - - associatedtype UnderlyingType = Void - - var template: String { get } - var bindings: [Binding?] { get } - - init(_ template: String, _ bindings: [Binding?]) - -} - -extension ExpressionType { - - public init(literal: String) { - self.init(literal, []) - } - - public init(_ identifier: String) { - self.init(literal: identifier.quote()) - } - - public init(_ expression: U) { - self.init(expression.template, expression.bindings) - } - -} - -/// An `Expression` represents a raw SQL fragment and any associated bindings. -public struct Expression : ExpressionType { - - public typealias UnderlyingType = Datatype - - public var template: String - public var bindings: [Binding?] - - public init(_ template: String, _ bindings: [Binding?]) { - self.template = template - self.bindings = bindings - } - -} - -public protocol Expressible { - - var expression: Expression { get } - -} - -extension Expressible { - - // naïve compiler for statements that can’t be bound, e.g., CREATE TABLE - // FIXME: make internal (0.13.0) - public func asSQL() -> String { - let expressed = expression - var idx = 0 - return expressed.template.reduce("") { template, character in - let transcoded: String - - if character == "?" { - transcoded = transcode(expressed.bindings[idx]) - idx += 1 - } else { - transcoded = String(character) - } - return template + transcoded - } - } - -} - -extension ExpressionType { - - public var expression: Expression { - return Expression(template, bindings) - } - - public var asc: Expressible { - return " ".join([self, Expression(literal: "ASC")]) - } - - public var desc: Expressible { - return " ".join([self, Expression(literal: "DESC")]) - } - -} - -extension ExpressionType where UnderlyingType : Value { - - public init(value: UnderlyingType) { - self.init("?", [value.datatypeValue]) - } - -} - -extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Value { - - public static var null: Self { - return self.init(value: nil) - } - - public init(value: UnderlyingType.WrappedType?) { - self.init("?", [value?.datatypeValue]) - } - -} - -extension Value { - - public var expression: Expression { - return Expression(value: self).expression - } - -} - -public let rowid = Expression("ROWID") - -public func cast(_ expression: Expression) -> Expression { - return Expression("CAST (\(expression.template) AS \(U.declaredDatatype))", expression.bindings) -} - -public func cast(_ expression: Expression) -> Expression { - return Expression("CAST (\(expression.template) AS \(U.declaredDatatype))", expression.bindings) -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/Operators.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/Operators.swift deleted file mode 100755 index b5637ea..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/Operators.swift +++ /dev/null @@ -1,605 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -// TODO: use `@warn_unused_result` by the time operator functions support it - -private enum Operator: String { - case plus = "+" - case minus = "-" - case or = "OR" - case and = "AND" - case not = "NOT " - case mul = "*" - case div = "/" - case mod = "%" - case bitwiseLeft = "<<" - case bitwiseRight = ">>" - case bitwiseAnd = "&" - case bitwiseOr = "|" - case bitwiseXor = "~" - case eq = "=" - case neq = "!=" - case gt = ">" - case lt = "<" - case gte = ">=" - case lte = "<=" - case concatenate = "||" - - func infix(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression { - return self.rawValue.infix(lhs, rhs, wrap: wrap) - } - - func wrap(_ expression: Expressible) -> Expression { - return self.rawValue.wrap(expression) - } -} - -public func +(lhs: Expression, rhs: Expression) -> Expression { - return Operator.concatenate.infix(lhs, rhs) -} - -public func +(lhs: Expression, rhs: Expression) -> Expression { - return Operator.concatenate.infix(lhs, rhs) -} -public func +(lhs: Expression, rhs: Expression) -> Expression { - return Operator.concatenate.infix(lhs, rhs) -} -public func +(lhs: Expression, rhs: Expression) -> Expression { - return Operator.concatenate.infix(lhs, rhs) -} -public func +(lhs: Expression, rhs: String) -> Expression { - return Operator.concatenate.infix(lhs, rhs) -} -public func +(lhs: Expression, rhs: String) -> Expression { - return Operator.concatenate.infix(lhs, rhs) -} -public func +(lhs: String, rhs: Expression) -> Expression { - return Operator.concatenate.infix(lhs, rhs) -} -public func +(lhs: String, rhs: Expression) -> Expression { - return Operator.concatenate.infix(lhs, rhs) -} - -// MARK: - - -public func +(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.plus.infix(lhs, rhs) -} -public func +(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.plus.infix(lhs, rhs) -} -public func +(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.plus.infix(lhs, rhs) -} -public func +(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.plus.infix(lhs, rhs) -} -public func +(lhs: Expression, rhs: V) -> Expression where V.Datatype : Number { - return Operator.plus.infix(lhs, rhs) -} -public func +(lhs: Expression, rhs: V) -> Expression where V.Datatype : Number { - return Operator.plus.infix(lhs, rhs) -} -public func +(lhs: V, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.plus.infix(lhs, rhs) -} -public func +(lhs: V, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.plus.infix(lhs, rhs) -} - -public func -(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.minus.infix(lhs, rhs) -} -public func -(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.minus.infix(lhs, rhs) -} -public func -(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.minus.infix(lhs, rhs) -} -public func -(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.minus.infix(lhs, rhs) -} -public func -(lhs: Expression, rhs: V) -> Expression where V.Datatype : Number { - return Operator.minus.infix(lhs, rhs) -} -public func -(lhs: Expression, rhs: V) -> Expression where V.Datatype : Number { - return Operator.minus.infix(lhs, rhs) -} -public func -(lhs: V, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.minus.infix(lhs, rhs) -} -public func -(lhs: V, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.minus.infix(lhs, rhs) -} - -public func *(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.mul.infix(lhs, rhs) -} -public func *(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.mul.infix(lhs, rhs) -} -public func *(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.mul.infix(lhs, rhs) -} -public func *(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.mul.infix(lhs, rhs) -} -public func *(lhs: Expression, rhs: V) -> Expression where V.Datatype : Number { - return Operator.mul.infix(lhs, rhs) -} -public func *(lhs: Expression, rhs: V) -> Expression where V.Datatype : Number { - return Operator.mul.infix(lhs, rhs) -} -public func *(lhs: V, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.mul.infix(lhs, rhs) -} -public func *(lhs: V, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.mul.infix(lhs, rhs) -} - -public func /(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.div.infix(lhs, rhs) -} -public func /(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.div.infix(lhs, rhs) -} -public func /(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.div.infix(lhs, rhs) -} -public func /(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.div.infix(lhs, rhs) -} -public func /(lhs: Expression, rhs: V) -> Expression where V.Datatype : Number { - return Operator.div.infix(lhs, rhs) -} -public func /(lhs: Expression, rhs: V) -> Expression where V.Datatype : Number { - return Operator.div.infix(lhs, rhs) -} -public func /(lhs: V, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.div.infix(lhs, rhs) -} -public func /(lhs: V, rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.div.infix(lhs, rhs) -} - -public prefix func -(rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.minus.wrap(rhs) -} -public prefix func -(rhs: Expression) -> Expression where V.Datatype : Number { - return Operator.minus.wrap(rhs) -} - -// MARK: - - -public func %(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.mod.infix(lhs, rhs) -} -public func %(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.mod.infix(lhs, rhs) -} -public func %(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.mod.infix(lhs, rhs) -} -public func %(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.mod.infix(lhs, rhs) -} -public func %(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.mod.infix(lhs, rhs) -} -public func %(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.mod.infix(lhs, rhs) -} -public func %(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.mod.infix(lhs, rhs) -} -public func %(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.mod.infix(lhs, rhs) -} - -public func <<(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseLeft.infix(lhs, rhs) -} -public func <<(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseLeft.infix(lhs, rhs) -} -public func <<(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseLeft.infix(lhs, rhs) -} -public func <<(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseLeft.infix(lhs, rhs) -} -public func <<(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseLeft.infix(lhs, rhs) -} -public func <<(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseLeft.infix(lhs, rhs) -} -public func <<(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseLeft.infix(lhs, rhs) -} -public func <<(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseLeft.infix(lhs, rhs) -} - -public func >>(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseRight.infix(lhs, rhs) -} -public func >>(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseRight.infix(lhs, rhs) -} -public func >>(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseRight.infix(lhs, rhs) -} -public func >>(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseRight.infix(lhs, rhs) -} -public func >>(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseRight.infix(lhs, rhs) -} -public func >>(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseRight.infix(lhs, rhs) -} -public func >>(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseRight.infix(lhs, rhs) -} -public func >>(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseRight.infix(lhs, rhs) -} - -public func &(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseAnd.infix(lhs, rhs) -} -public func &(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseAnd.infix(lhs, rhs) -} -public func &(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseAnd.infix(lhs, rhs) -} -public func &(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseAnd.infix(lhs, rhs) -} -public func &(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseAnd.infix(lhs, rhs) -} -public func &(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseAnd.infix(lhs, rhs) -} -public func &(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseAnd.infix(lhs, rhs) -} -public func &(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseAnd.infix(lhs, rhs) -} - -public func |(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseOr.infix(lhs, rhs) -} -public func |(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseOr.infix(lhs, rhs) -} -public func |(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseOr.infix(lhs, rhs) -} -public func |(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseOr.infix(lhs, rhs) -} -public func |(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseOr.infix(lhs, rhs) -} -public func |(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseOr.infix(lhs, rhs) -} -public func |(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseOr.infix(lhs, rhs) -} -public func |(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseOr.infix(lhs, rhs) -} - -public func ^(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return (~(lhs & rhs)) & (lhs | rhs) -} -public func ^(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return (~(lhs & rhs)) & (lhs | rhs) -} -public func ^(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return (~(lhs & rhs)) & (lhs | rhs) -} -public func ^(lhs: Expression, rhs: Expression) -> Expression where V.Datatype == Int64 { - return (~(lhs & rhs)) & (lhs | rhs) -} -public func ^(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return (~(lhs & rhs)) & (lhs | rhs) -} -public func ^(lhs: Expression, rhs: V) -> Expression where V.Datatype == Int64 { - return (~(lhs & rhs)) & (lhs | rhs) -} -public func ^(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return (~(lhs & rhs)) & (lhs | rhs) -} -public func ^(lhs: V, rhs: Expression) -> Expression where V.Datatype == Int64 { - return (~(lhs & rhs)) & (lhs | rhs) -} - -public prefix func ~(rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseXor.wrap(rhs) -} -public prefix func ~(rhs: Expression) -> Expression where V.Datatype == Int64 { - return Operator.bitwiseXor.wrap(rhs) -} - -// MARK: - - -public func ==(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.eq.infix(lhs, rhs) -} -public func ==(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.eq.infix(lhs, rhs) -} -public func ==(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.eq.infix(lhs, rhs) -} -public func ==(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.eq.infix(lhs, rhs) -} -public func ==(lhs: Expression, rhs: V) -> Expression where V.Datatype : Equatable { - return Operator.eq.infix(lhs, rhs) -} -public func ==(lhs: Expression, rhs: V?) -> Expression where V.Datatype : Equatable { - guard let rhs = rhs else { return "IS".infix(lhs, Expression(value: nil)) } - return Operator.eq.infix(lhs, rhs) -} -public func ==(lhs: V, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.eq.infix(lhs, rhs) -} -public func ==(lhs: V?, rhs: Expression) -> Expression where V.Datatype : Equatable { - guard let lhs = lhs else { return "IS".infix(Expression(value: nil), rhs) } - return Operator.eq.infix(lhs, rhs) -} - -public func !=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.neq.infix(lhs, rhs) -} -public func !=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.neq.infix(lhs, rhs) -} -public func !=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.neq.infix(lhs, rhs) -} -public func !=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.neq.infix(lhs, rhs) -} -public func !=(lhs: Expression, rhs: V) -> Expression where V.Datatype : Equatable { - return Operator.neq.infix(lhs, rhs) -} -public func !=(lhs: Expression, rhs: V?) -> Expression where V.Datatype : Equatable { - guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression(value: nil)) } - return Operator.neq.infix(lhs, rhs) -} -public func !=(lhs: V, rhs: Expression) -> Expression where V.Datatype : Equatable { - return Operator.neq.infix(lhs, rhs) -} -public func !=(lhs: V?, rhs: Expression) -> Expression where V.Datatype : Equatable { - guard let lhs = lhs else { return "IS NOT".infix(Expression(value: nil), rhs) } - return Operator.neq.infix(lhs, rhs) -} - -public func >(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gt.infix(lhs, rhs) -} -public func >(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gt.infix(lhs, rhs) -} -public func >(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gt.infix(lhs, rhs) -} -public func >(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gt.infix(lhs, rhs) -} -public func >(lhs: Expression, rhs: V) -> Expression where V.Datatype : Comparable { - return Operator.gt.infix(lhs, rhs) -} -public func >(lhs: Expression, rhs: V) -> Expression where V.Datatype : Comparable { - return Operator.gt.infix(lhs, rhs) -} -public func >(lhs: V, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gt.infix(lhs, rhs) -} -public func >(lhs: V, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gt.infix(lhs, rhs) -} - -public func >=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gte.infix(lhs, rhs) -} -public func >=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gte.infix(lhs, rhs) -} -public func >=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gte.infix(lhs, rhs) -} -public func >=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gte.infix(lhs, rhs) -} -public func >=(lhs: Expression, rhs: V) -> Expression where V.Datatype : Comparable { - return Operator.gte.infix(lhs, rhs) -} -public func >=(lhs: Expression, rhs: V) -> Expression where V.Datatype : Comparable { - return Operator.gte.infix(lhs, rhs) -} -public func >=(lhs: V, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gte.infix(lhs, rhs) -} -public func >=(lhs: V, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.gte.infix(lhs, rhs) -} - -public func <(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lt.infix(lhs, rhs) -} -public func <(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lt.infix(lhs, rhs) -} -public func <(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lt.infix(lhs, rhs) -} -public func <(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lt.infix(lhs, rhs) -} -public func <(lhs: Expression, rhs: V) -> Expression where V.Datatype : Comparable { - return Operator.lt.infix(lhs, rhs) -} -public func <(lhs: Expression, rhs: V) -> Expression where V.Datatype : Comparable { - return Operator.lt.infix(lhs, rhs) -} -public func <(lhs: V, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lt.infix(lhs, rhs) -} -public func <(lhs: V, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lt.infix(lhs, rhs) -} - -public func <=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lte.infix(lhs, rhs) -} -public func <=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lte.infix(lhs, rhs) -} -public func <=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lte.infix(lhs, rhs) -} -public func <=(lhs: Expression, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lte.infix(lhs, rhs) -} -public func <=(lhs: Expression, rhs: V) -> Expression where V.Datatype : Comparable { - return Operator.lte.infix(lhs, rhs) -} -public func <=(lhs: Expression, rhs: V) -> Expression where V.Datatype : Comparable { - return Operator.lte.infix(lhs, rhs) -} -public func <=(lhs: V, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lte.infix(lhs, rhs) -} -public func <=(lhs: V, rhs: Expression) -> Expression where V.Datatype : Comparable { - return Operator.lte.infix(lhs, rhs) -} - -public func ~=(lhs: ClosedRange, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue]) -} - -public func ~=(lhs: ClosedRange, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue]) -} - -public func ~=(lhs: Range, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] + rhs.bindings + [lhs.upperBound.datatypeValue]) -} - -public func ~=(lhs: Range, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] + rhs.bindings + [lhs.upperBound.datatypeValue]) -} - -public func ~=(lhs: PartialRangeThrough, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue]) -} - -public func ~=(lhs: PartialRangeThrough, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue]) -} - -public func ~=(lhs: PartialRangeUpTo, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue]) -} - -public func ~=(lhs: PartialRangeUpTo, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue]) -} - -public func ~=(lhs: PartialRangeFrom, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue]) -} - -public func ~=(lhs: PartialRangeFrom, rhs: Expression) -> Expression where V.Datatype : Comparable & Value { - return Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue]) -} - -// MARK: - - -public func &&(lhs: Expression, rhs: Expression) -> Expression { - return Operator.and.infix(lhs, rhs) -} -public func &&(lhs: Expression, rhs: Expression) -> Expression { - return Operator.and.infix(lhs, rhs) -} -public func &&(lhs: Expression, rhs: Expression) -> Expression { - return Operator.and.infix(lhs, rhs) -} -public func &&(lhs: Expression, rhs: Expression) -> Expression { - return Operator.and.infix(lhs, rhs) -} -public func &&(lhs: Expression, rhs: Bool) -> Expression { - return Operator.and.infix(lhs, rhs) -} -public func &&(lhs: Expression, rhs: Bool) -> Expression { - return Operator.and.infix(lhs, rhs) -} -public func &&(lhs: Bool, rhs: Expression) -> Expression { - return Operator.and.infix(lhs, rhs) -} -public func &&(lhs: Bool, rhs: Expression) -> Expression { - return Operator.and.infix(lhs, rhs) -} - -public func ||(lhs: Expression, rhs: Expression) -> Expression { - return Operator.or.infix(lhs, rhs) -} -public func ||(lhs: Expression, rhs: Expression) -> Expression { - return Operator.or.infix(lhs, rhs) -} -public func ||(lhs: Expression, rhs: Expression) -> Expression { - return Operator.or.infix(lhs, rhs) -} -public func ||(lhs: Expression, rhs: Expression) -> Expression { - return Operator.or.infix(lhs, rhs) -} -public func ||(lhs: Expression, rhs: Bool) -> Expression { - return Operator.or.infix(lhs, rhs) -} -public func ||(lhs: Expression, rhs: Bool) -> Expression { - return Operator.or.infix(lhs, rhs) -} -public func ||(lhs: Bool, rhs: Expression) -> Expression { - return Operator.or.infix(lhs, rhs) -} -public func ||(lhs: Bool, rhs: Expression) -> Expression { - return Operator.or.infix(lhs, rhs) -} - -public prefix func !(rhs: Expression) -> Expression { - return Operator.not.wrap(rhs) -} -public prefix func !(rhs: Expression) -> Expression { - return Operator.not.wrap(rhs) -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/Query.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/Query.swift deleted file mode 100755 index f6ef6df..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/Query.swift +++ /dev/null @@ -1,1175 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import Foundation - -public protocol QueryType : Expressible { - - var clauses: QueryClauses { get set } - - init(_ name: String, database: String?) - -} - -public protocol SchemaType : QueryType { - - static var identifier: String { get } - -} - -extension SchemaType { - - /// Builds a copy of the query with the `SELECT` clause applied. - /// - /// let users = Table("users") - /// let id = Expression("id") - /// let email = Expression("email") - /// - /// users.select(id, email) - /// // SELECT "id", "email" FROM "users" - /// - /// - Parameter all: A list of expressions to select. - /// - /// - Returns: A query with the given `SELECT` clause applied. - public func select(_ column1: Expressible, _ more: Expressible...) -> Self { - return select(false, [column1] + more) - } - - /// Builds a copy of the query with the `SELECT DISTINCT` clause applied. - /// - /// let users = Table("users") - /// let email = Expression("email") - /// - /// users.select(distinct: email) - /// // SELECT DISTINCT "email" FROM "users" - /// - /// - Parameter columns: A list of expressions to select. - /// - /// - Returns: A query with the given `SELECT DISTINCT` clause applied. - public func select(distinct column1: Expressible, _ more: Expressible...) -> Self { - return select(true, [column1] + more) - } - - /// Builds a copy of the query with the `SELECT` clause applied. - /// - /// let users = Table("users") - /// let id = Expression("id") - /// let email = Expression("email") - /// - /// users.select([id, email]) - /// // SELECT "id", "email" FROM "users" - /// - /// - Parameter all: A list of expressions to select. - /// - /// - Returns: A query with the given `SELECT` clause applied. - public func select(_ all: [Expressible]) -> Self { - return select(false, all) - } - - /// Builds a copy of the query with the `SELECT DISTINCT` clause applied. - /// - /// let users = Table("users") - /// let email = Expression("email") - /// - /// users.select(distinct: [email]) - /// // SELECT DISTINCT "email" FROM "users" - /// - /// - Parameter columns: A list of expressions to select. - /// - /// - Returns: A query with the given `SELECT DISTINCT` clause applied. - public func select(distinct columns: [Expressible]) -> Self { - return select(true, columns) - } - - /// Builds a copy of the query with the `SELECT *` clause applied. - /// - /// let users = Table("users") - /// - /// users.select(*) - /// // SELECT * FROM "users" - /// - /// - Parameter star: A star literal. - /// - /// - Returns: A query with the given `SELECT *` clause applied. - public func select(_ star: Star) -> Self { - return select([star(nil, nil)]) - } - - /// Builds a copy of the query with the `SELECT DISTINCT *` clause applied. - /// - /// let users = Table("users") - /// - /// users.select(distinct: *) - /// // SELECT DISTINCT * FROM "users" - /// - /// - Parameter star: A star literal. - /// - /// - Returns: A query with the given `SELECT DISTINCT *` clause applied. - public func select(distinct star: Star) -> Self { - return select(distinct: [star(nil, nil)]) - } - - /// Builds a scalar copy of the query with the `SELECT` clause applied. - /// - /// let users = Table("users") - /// let id = Expression("id") - /// - /// users.select(id) - /// // SELECT "id" FROM "users" - /// - /// - Parameter all: A list of expressions to select. - /// - /// - Returns: A query with the given `SELECT` clause applied. - public func select(_ column: Expression) -> ScalarQuery { - return select(false, [column]) - } - public func select(_ column: Expression) -> ScalarQuery { - return select(false, [column]) - } - - /// Builds a scalar copy of the query with the `SELECT DISTINCT` clause - /// applied. - /// - /// let users = Table("users") - /// let email = Expression("email") - /// - /// users.select(distinct: email) - /// // SELECT DISTINCT "email" FROM "users" - /// - /// - Parameter column: A list of expressions to select. - /// - /// - Returns: A query with the given `SELECT DISTINCT` clause applied. - public func select(distinct column: Expression) -> ScalarQuery { - return select(true, [column]) - } - public func select(distinct column: Expression) -> ScalarQuery { - return select(true, [column]) - } - - public var count: ScalarQuery { - return select(Expression.count(*)) - } - -} - -extension QueryType { - - fileprivate func select(_ distinct: Bool, _ columns: [Expressible]) -> Q { - var query = Q.init(clauses.from.name, database: clauses.from.database) - query.clauses = clauses - query.clauses.select = (distinct, columns) - return query - } - - // MARK: UNION - - /// Adds a `UNION` clause to the query. - /// - /// let users = Table("users") - /// let email = Expression("email") - /// - /// users.filter(email == "alice@example.com").union(users.filter(email == "sally@example.com")) - /// // SELECT * FROM "users" WHERE email = 'alice@example.com' UNION SELECT * FROM "users" WHERE email = 'sally@example.com' - /// - /// - Parameters: - /// - /// - table: A query representing the other table. - /// - /// - Returns: A query with the given `UNION` clause applied. - public func union(_ table: QueryType) -> Self { - var query = self - query.clauses.union.append(table) - return query - } - - // MARK: JOIN - - /// Adds a `JOIN` clause to the query. - /// - /// let users = Table("users") - /// let id = Expression("id") - /// let posts = Table("posts") - /// let userId = Expression("user_id") - /// - /// users.join(posts, on: posts[userId] == users[id]) - /// // SELECT * FROM "users" INNER JOIN "posts" ON ("posts"."user_id" = "users"."id") - /// - /// - Parameters: - /// - /// - table: A query representing the other table. - /// - /// - condition: A boolean expression describing the join condition. - /// - /// - Returns: A query with the given `JOIN` clause applied. - public func join(_ table: QueryType, on condition: Expression) -> Self { - return join(table, on: Expression(condition)) - } - - /// Adds a `JOIN` clause to the query. - /// - /// let users = Table("users") - /// let id = Expression("id") - /// let posts = Table("posts") - /// let userId = Expression("user_id") - /// - /// users.join(posts, on: posts[userId] == users[id]) - /// // SELECT * FROM "users" INNER JOIN "posts" ON ("posts"."user_id" = "users"."id") - /// - /// - Parameters: - /// - /// - table: A query representing the other table. - /// - /// - condition: A boolean expression describing the join condition. - /// - /// - Returns: A query with the given `JOIN` clause applied. - public func join(_ table: QueryType, on condition: Expression) -> Self { - return join(.inner, table, on: condition) - } - - /// Adds a `JOIN` clause to the query. - /// - /// let users = Table("users") - /// let id = Expression("id") - /// let posts = Table("posts") - /// let userId = Expression("user_id") - /// - /// users.join(.LeftOuter, posts, on: posts[userId] == users[id]) - /// // SELECT * FROM "users" LEFT OUTER JOIN "posts" ON ("posts"."user_id" = "users"."id") - /// - /// - Parameters: - /// - /// - type: The `JOIN` operator. - /// - /// - table: A query representing the other table. - /// - /// - condition: A boolean expression describing the join condition. - /// - /// - Returns: A query with the given `JOIN` clause applied. - public func join(_ type: JoinType, _ table: QueryType, on condition: Expression) -> Self { - return join(type, table, on: Expression(condition)) - } - - /// Adds a `JOIN` clause to the query. - /// - /// let users = Table("users") - /// let id = Expression("id") - /// let posts = Table("posts") - /// let userId = Expression("user_id") - /// - /// users.join(.LeftOuter, posts, on: posts[userId] == users[id]) - /// // SELECT * FROM "users" LEFT OUTER JOIN "posts" ON ("posts"."user_id" = "users"."id") - /// - /// - Parameters: - /// - /// - type: The `JOIN` operator. - /// - /// - table: A query representing the other table. - /// - /// - condition: A boolean expression describing the join condition. - /// - /// - Returns: A query with the given `JOIN` clause applied. - public func join(_ type: JoinType, _ table: QueryType, on condition: Expression) -> Self { - var query = self - query.clauses.join.append((type: type, query: table, condition: table.clauses.filters.map { condition && $0 } ?? condition as Expressible)) - return query - } - - // MARK: WHERE - - /// Adds a condition to the query’s `WHERE` clause. - /// - /// let users = Table("users") - /// let id = Expression("id") - /// - /// users.filter(id == 1) - /// // SELECT * FROM "users" WHERE ("id" = 1) - /// - /// - Parameter condition: A boolean expression to filter on. - /// - /// - Returns: A query with the given `WHERE` clause applied. - public func filter(_ predicate: Expression) -> Self { - return filter(Expression(predicate)) - } - - /// Adds a condition to the query’s `WHERE` clause. - /// - /// let users = Table("users") - /// let age = Expression("age") - /// - /// users.filter(age >= 35) - /// // SELECT * FROM "users" WHERE ("age" >= 35) - /// - /// - Parameter condition: A boolean expression to filter on. - /// - /// - Returns: A query with the given `WHERE` clause applied. - public func filter(_ predicate: Expression) -> Self { - var query = self - query.clauses.filters = query.clauses.filters.map { $0 && predicate } ?? predicate - return query - } - - /// Adds a condition to the query’s `WHERE` clause. - /// This is an alias for `filter(predicate)` - public func `where`(_ predicate: Expression) -> Self { - return `where`(Expression(predicate)) - } - - /// Adds a condition to the query’s `WHERE` clause. - /// This is an alias for `filter(predicate)` - public func `where`(_ predicate: Expression) -> Self { - return filter(predicate) - } - - // MARK: GROUP BY - - /// Sets a `GROUP BY` clause on the query. - /// - /// - Parameter by: A list of columns to group by. - /// - /// - Returns: A query with the given `GROUP BY` clause applied. - public func group(_ by: Expressible...) -> Self { - return group(by) - } - - /// Sets a `GROUP BY` clause on the query. - /// - /// - Parameter by: A list of columns to group by. - /// - /// - Returns: A query with the given `GROUP BY` clause applied. - public func group(_ by: [Expressible]) -> Self { - return group(by, nil) - } - - /// Sets a `GROUP BY`-`HAVING` clause on the query. - /// - /// - Parameters: - /// - /// - by: A column to group by. - /// - /// - having: A condition determining which groups are returned. - /// - /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied. - public func group(_ by: Expressible, having: Expression) -> Self { - return group([by], having: having) - } - - /// Sets a `GROUP BY`-`HAVING` clause on the query. - /// - /// - Parameters: - /// - /// - by: A column to group by. - /// - /// - having: A condition determining which groups are returned. - /// - /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied. - public func group(_ by: Expressible, having: Expression) -> Self { - return group([by], having: having) - } - - /// Sets a `GROUP BY`-`HAVING` clause on the query. - /// - /// - Parameters: - /// - /// - by: A list of columns to group by. - /// - /// - having: A condition determining which groups are returned. - /// - /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied. - public func group(_ by: [Expressible], having: Expression) -> Self { - return group(by, Expression(having)) - } - - /// Sets a `GROUP BY`-`HAVING` clause on the query. - /// - /// - Parameters: - /// - /// - by: A list of columns to group by. - /// - /// - having: A condition determining which groups are returned. - /// - /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied. - public func group(_ by: [Expressible], having: Expression) -> Self { - return group(by, having) - } - - fileprivate func group(_ by: [Expressible], _ having: Expression?) -> Self { - var query = self - query.clauses.group = (by, having) - return query - } - - // MARK: ORDER BY - - /// Sets an `ORDER BY` clause on the query. - /// - /// let users = Table("users") - /// let email = Expression("email") - /// let name = Expression("name") - /// - /// users.order(email.desc, name.asc) - /// // SELECT * FROM "users" ORDER BY "email" DESC, "name" ASC - /// - /// - Parameter by: An ordered list of columns and directions to sort by. - /// - /// - Returns: A query with the given `ORDER BY` clause applied. - public func order(_ by: Expressible...) -> Self { - return order(by) - } - - /// Sets an `ORDER BY` clause on the query. - /// - /// let users = Table("users") - /// let email = Expression("email") - /// let name = Expression("name") - /// - /// users.order([email.desc, name.asc]) - /// // SELECT * FROM "users" ORDER BY "email" DESC, "name" ASC - /// - /// - Parameter by: An ordered list of columns and directions to sort by. - /// - /// - Returns: A query with the given `ORDER BY` clause applied. - public func order(_ by: [Expressible]) -> Self { - var query = self - query.clauses.order = by - return query - } - - // MARK: LIMIT/OFFSET - - /// Sets the LIMIT clause (and resets any OFFSET clause) on the query. - /// - /// let users = Table("users") - /// - /// users.limit(20) - /// // SELECT * FROM "users" LIMIT 20 - /// - /// - Parameter length: The maximum number of rows to return (or `nil` to - /// return unlimited rows). - /// - /// - Returns: A query with the given LIMIT clause applied. - public func limit(_ length: Int?) -> Self { - return limit(length, nil) - } - - /// Sets LIMIT and OFFSET clauses on the query. - /// - /// let users = Table("users") - /// - /// users.limit(20, offset: 20) - /// // SELECT * FROM "users" LIMIT 20 OFFSET 20 - /// - /// - Parameters: - /// - /// - length: The maximum number of rows to return. - /// - /// - offset: The number of rows to skip. - /// - /// - Returns: A query with the given LIMIT and OFFSET clauses applied. - public func limit(_ length: Int, offset: Int) -> Self { - return limit(length, offset) - } - - // prevents limit(nil, offset: 5) - fileprivate func limit(_ length: Int?, _ offset: Int?) -> Self { - var query = self - query.clauses.limit = length.map { ($0, offset) } - return query - } - - // MARK: - Clauses - // - // MARK: SELECT - - // MARK: - - - fileprivate var selectClause: Expressible { - return " ".join([ - Expression(literal: clauses.select.distinct ? "SELECT DISTINCT" : "SELECT"), - ", ".join(clauses.select.columns), - Expression(literal: "FROM"), - tableName(alias: true) - ]) - } - - fileprivate var joinClause: Expressible? { - guard !clauses.join.isEmpty else { - return nil - } - - return " ".join(clauses.join.map { arg in - let (type, query, condition) = arg - return " ".join([ - Expression(literal: "\(type.rawValue) JOIN"), - query.tableName(alias: true), - Expression(literal: "ON"), - condition - ]) - }) - } - - fileprivate var whereClause: Expressible? { - guard let filters = clauses.filters else { - return nil - } - - return " ".join([ - Expression(literal: "WHERE"), - filters - ]) - } - - fileprivate var groupByClause: Expressible? { - guard let group = clauses.group else { - return nil - } - - let groupByClause = " ".join([ - Expression(literal: "GROUP BY"), - ", ".join(group.by) - ]) - - guard let having = group.having else { - return groupByClause - } - - return " ".join([ - groupByClause, - " ".join([ - Expression(literal: "HAVING"), - having - ]) - ]) - } - - fileprivate var orderClause: Expressible? { - guard !clauses.order.isEmpty else { - return nil - } - - return " ".join([ - Expression(literal: "ORDER BY"), - ", ".join(clauses.order) - ]) - } - - fileprivate var limitOffsetClause: Expressible? { - guard let limit = clauses.limit else { - return nil - } - - let limitClause = Expression(literal: "LIMIT \(limit.length)") - - guard let offset = limit.offset else { - return limitClause - } - - return " ".join([ - limitClause, - Expression(literal: "OFFSET \(offset)") - ]) - } - - fileprivate var unionClause: Expressible? { - guard !clauses.union.isEmpty else { - return nil - } - - return " ".join(clauses.union.map { query in - " ".join([ - Expression(literal: "UNION"), - query - ]) - }) - } - - // MARK: - - - public func alias(_ aliasName: String) -> Self { - var query = self - query.clauses.from = (clauses.from.name, aliasName, clauses.from.database) - return query - } - - // MARK: - Operations - // - // MARK: INSERT - - public func insert(_ value: Setter, _ more: Setter...) -> Insert { - return insert([value] + more) - } - - public func insert(_ values: [Setter]) -> Insert { - return insert(nil, values) - } - - public func insert(or onConflict: OnConflict, _ values: Setter...) -> Insert { - return insert(or: onConflict, values) - } - - public func insert(or onConflict: OnConflict, _ values: [Setter]) -> Insert { - return insert(onConflict, values) - } - - fileprivate func insert(_ or: OnConflict?, _ values: [Setter]) -> Insert { - let insert = values.reduce((columns: [Expressible](), values: [Expressible]())) { insert, setter in - (insert.columns + [setter.column], insert.values + [setter.value]) - } - - let clauses: [Expressible?] = [ - Expression(literal: "INSERT"), - or.map { Expression(literal: "OR \($0.rawValue)") }, - Expression(literal: "INTO"), - tableName(), - "".wrap(insert.columns) as Expression, - Expression(literal: "VALUES"), - "".wrap(insert.values) as Expression, - whereClause - ] - - return Insert(" ".join(clauses.compactMap { $0 }).expression) - } - - /// Runs an `INSERT` statement against the query with `DEFAULT VALUES`. - public func insert() -> Insert { - return Insert(" ".join([ - Expression(literal: "INSERT INTO"), - tableName(), - Expression(literal: "DEFAULT VALUES") - ]).expression) - } - - /// Runs an `INSERT` statement against the query with the results of another - /// query. - /// - /// - Parameter query: A query to `SELECT` results from. - /// - /// - Returns: The number of updated rows and statement. - public func insert(_ query: QueryType) -> Update { - return Update(" ".join([ - Expression(literal: "INSERT INTO"), - tableName(), - query.expression - ]).expression) - } - - // MARK: UPDATE - - public func update(_ values: Setter...) -> Update { - return update(values) - } - - public func update(_ values: [Setter]) -> Update { - let clauses: [Expressible?] = [ - Expression(literal: "UPDATE"), - tableName(), - Expression(literal: "SET"), - ", ".join(values.map { " = ".join([$0.column, $0.value]) }), - whereClause, - orderClause, - limitOffsetClause - ] - - return Update(" ".join(clauses.compactMap { $0 }).expression) - } - - // MARK: DELETE - - public func delete() -> Delete { - let clauses: [Expressible?] = [ - Expression(literal: "DELETE FROM"), - tableName(), - whereClause, - orderClause, - limitOffsetClause - ] - - return Delete(" ".join(clauses.compactMap { $0 }).expression) - } - - // MARK: EXISTS - - public var exists: Select { - return Select(" ".join([ - Expression(literal: "SELECT EXISTS"), - "".wrap(expression) as Expression - ]).expression) - } - - // MARK: - - - /// Prefixes a column expression with the query’s table name or alias. - /// - /// - Parameter column: A column expression. - /// - /// - Returns: A column expression namespaced with the query’s table name or - /// alias. - public func namespace(_ column: Expression) -> Expression { - return Expression(".".join([tableName(), column]).expression) - } - - public subscript(column: Expression) -> Expression { - return namespace(column) - } - - public subscript(column: Expression) -> Expression { - return namespace(column) - } - - /// Prefixes a star with the query’s table name or alias. - /// - /// - Parameter star: A literal `*`. - /// - /// - Returns: A `*` expression namespaced with the query’s table name or - /// alias. - public subscript(star: Star) -> Expression { - return namespace(star(nil, nil)) - } - - // MARK: - - - // TODO: alias support - func tableName(alias aliased: Bool = false) -> Expressible { - guard let alias = clauses.from.alias , aliased else { - return database(namespace: clauses.from.alias ?? clauses.from.name) - } - - return " ".join([ - database(namespace: clauses.from.name), - Expression(literal: "AS"), - Expression(alias) - ]) - } - - func tableName(qualified: Bool) -> Expressible { - if qualified { - return tableName() - } - return Expression(clauses.from.alias ?? clauses.from.name) - } - - func database(namespace name: String) -> Expressible { - let name = Expression(name) - - guard let database = clauses.from.database else { - return name - } - - return ".".join([Expression(database), name]) - } - - public var expression: Expression { - let clauses: [Expressible?] = [ - selectClause, - joinClause, - whereClause, - groupByClause, - unionClause, - orderClause, - limitOffsetClause - ] - - return " ".join(clauses.compactMap { $0 }).expression - } - -} - -// TODO: decide: simplify the below with a boxed type instead - -/// Queries a collection of chainable helper functions and expressions to build -/// executable SQL statements. -public struct Table : SchemaType { - - public static let identifier = "TABLE" - - public var clauses: QueryClauses - - public init(_ name: String, database: String? = nil) { - clauses = QueryClauses(name, alias: nil, database: database) - } - -} - -public struct View : SchemaType { - - public static let identifier = "VIEW" - - public var clauses: QueryClauses - - public init(_ name: String, database: String? = nil) { - clauses = QueryClauses(name, alias: nil, database: database) - } - -} - -public struct VirtualTable : SchemaType { - - public static let identifier = "VIRTUAL TABLE" - - public var clauses: QueryClauses - - public init(_ name: String, database: String? = nil) { - clauses = QueryClauses(name, alias: nil, database: database) - } - -} - -// TODO: make `ScalarQuery` work in `QueryType.select()`, `.filter()`, etc. - -public struct ScalarQuery : QueryType { - - public var clauses: QueryClauses - - public init(_ name: String, database: String? = nil) { - clauses = QueryClauses(name, alias: nil, database: database) - } - -} - -// TODO: decide: simplify the below with a boxed type instead - -public struct Select : ExpressionType { - - public var template: String - public var bindings: [Binding?] - - public init(_ template: String, _ bindings: [Binding?]) { - self.template = template - self.bindings = bindings - } - -} - -public struct Insert : ExpressionType { - - public var template: String - public var bindings: [Binding?] - - public init(_ template: String, _ bindings: [Binding?]) { - self.template = template - self.bindings = bindings - } - -} - -public struct Update : ExpressionType { - - public var template: String - public var bindings: [Binding?] - - public init(_ template: String, _ bindings: [Binding?]) { - self.template = template - self.bindings = bindings - } - -} - -public struct Delete : ExpressionType { - - public var template: String - public var bindings: [Binding?] - - public init(_ template: String, _ bindings: [Binding?]) { - self.template = template - self.bindings = bindings - } - -} - - -public struct RowIterator: FailableIterator { - public typealias Element = Row - let statement: Statement - let columnNames: [String: Int] - - public func failableNext() throws -> Row? { - return try statement.failableNext().flatMap { Row(columnNames, $0) } - } - - public func map(_ transform: (Element) throws -> T) throws -> [T] { - var elements = [T]() - while let row = try failableNext() { - elements.append(try transform(row)) - } - return elements - } -} - -extension Connection { - - public func prepare(_ query: QueryType) throws -> AnySequence { - let expression = query.expression - let statement = try prepare(expression.template, expression.bindings) - - let columnNames = try columnNamesForQuery(query) - - return AnySequence { - AnyIterator { statement.next().map { Row(columnNames, $0) } } - } - } - - - public func prepareRowIterator(_ query: QueryType) throws -> RowIterator { - let expression = query.expression - let statement = try prepare(expression.template, expression.bindings) - return RowIterator(statement: statement, columnNames: try columnNamesForQuery(query)) - } - - private func columnNamesForQuery(_ query: QueryType) throws -> [String: Int] { - var (columnNames, idx) = ([String: Int](), 0) - column: for each in query.clauses.select.columns { - var names = each.expression.template.split { $0 == "." }.map(String.init) - let column = names.removeLast() - let namespace = names.joined(separator: ".") - - func expandGlob(_ namespace: Bool) -> ((QueryType) throws -> Void) { - return { (query: QueryType) throws -> (Void) in - var q = type(of: query).init(query.clauses.from.name, database: query.clauses.from.database) - q.clauses.select = query.clauses.select - let e = q.expression - var names = try self.prepare(e.template, e.bindings).columnNames.map { $0.quote() } - if namespace { names = names.map { "\(query.tableName().expression.template).\($0)" } } - for name in names { columnNames[name] = idx; idx += 1 } - } - } - - if column == "*" { - var select = query - select.clauses.select = (false, [Expression(literal: "*") as Expressible]) - let queries = [select] + query.clauses.join.map { $0.query } - if !namespace.isEmpty { - for q in queries { - if q.tableName().expression.template == namespace { - try expandGlob(true)(q) - continue column - } - throw QueryError.noSuchTable(name: namespace) - } - throw QueryError.noSuchTable(name: namespace) - } - for q in queries { - try expandGlob(query.clauses.join.count > 0)(q) - } - continue - } - - columnNames[each.expression.template] = idx - idx += 1 - } - return columnNames - } - - public func scalar(_ query: ScalarQuery) throws -> V { - let expression = query.expression - return value(try scalar(expression.template, expression.bindings)) - } - - public func scalar(_ query: ScalarQuery) throws -> V.ValueType? { - let expression = query.expression - guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil } - return V.fromDatatypeValue(value) - } - - public func scalar(_ query: Select) throws -> V { - let expression = query.expression - return value(try scalar(expression.template, expression.bindings)) - } - - public func scalar(_ query: Select) throws -> V.ValueType? { - let expression = query.expression - guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil } - return V.fromDatatypeValue(value) - } - - public func pluck(_ query: QueryType) throws -> Row? { - return try prepareRowIterator(query.limit(1, query.clauses.limit?.offset)).failableNext() - } - - /// Runs an `Insert` query. - /// - /// - SeeAlso: `QueryType.insert(value:_:)` - /// - SeeAlso: `QueryType.insert(values:)` - /// - SeeAlso: `QueryType.insert(or:_:)` - /// - SeeAlso: `QueryType.insert()` - /// - /// - Parameter query: An insert query. - /// - /// - Returns: The insert’s rowid. - @discardableResult public func run(_ query: Insert) throws -> Int64 { - let expression = query.expression - return try sync { - try self.run(expression.template, expression.bindings) - return self.lastInsertRowid - } - } - - /// Runs an `Update` query. - /// - /// - SeeAlso: `QueryType.insert(query:)` - /// - SeeAlso: `QueryType.update(values:)` - /// - /// - Parameter query: An update query. - /// - /// - Returns: The number of updated rows. - @discardableResult public func run(_ query: Update) throws -> Int { - let expression = query.expression - return try sync { - try self.run(expression.template, expression.bindings) - return self.changes - } - } - - /// Runs a `Delete` query. - /// - /// - SeeAlso: `QueryType.delete()` - /// - /// - Parameter query: A delete query. - /// - /// - Returns: The number of deleted rows. - @discardableResult public func run(_ query: Delete) throws -> Int { - let expression = query.expression - return try sync { - try self.run(expression.template, expression.bindings) - return self.changes - } - } - -} - -public struct Row { - - let columnNames: [String: Int] - - fileprivate let values: [Binding?] - - internal init(_ columnNames: [String: Int], _ values: [Binding?]) { - self.columnNames = columnNames - self.values = values - } - - func hasValue(for column: String) -> Bool { - guard let idx = columnNames[column.quote()] else { - return false - } - return values[idx] != nil - } - - /// Returns a row’s value for the given column. - /// - /// - Parameter column: An expression representing a column selected in a Query. - /// - /// - Returns: The value for the given column. - public func get(_ column: Expression) throws -> V { - if let value = try get(Expression(column)) { - return value - } else { - throw QueryError.unexpectedNullValue(name: column.template) - } - } - - public func get(_ column: Expression) throws -> V? { - func valueAtIndex(_ idx: Int) -> V? { - guard let value = values[idx] as? V.Datatype else { return nil } - return V.fromDatatypeValue(value) as? V - } - - guard let idx = columnNames[column.template] else { - let similar = Array(columnNames.keys).filter { $0.hasSuffix(".\(column.template)") } - - switch similar.count { - case 0: - throw QueryError.noSuchColumn(name: column.template, columns: columnNames.keys.sorted()) - case 1: - return valueAtIndex(columnNames[similar[0]]!) - default: - throw QueryError.ambiguousColumn(name: column.template, similar: similar) - } - } - - return valueAtIndex(idx) - } - - public subscript(column: Expression) -> T { - return try! get(column) - } - - public subscript(column: Expression) -> T? { - return try! get(column) - } -} - -/// Determines the join operator for a query’s `JOIN` clause. -public enum JoinType : String { - - /// A `CROSS` join. - case cross = "CROSS" - - /// An `INNER` join. - case inner = "INNER" - - /// A `LEFT OUTER` join. - case leftOuter = "LEFT OUTER" - -} - -/// ON CONFLICT resolutions. -public enum OnConflict: String { - - case replace = "REPLACE" - - case rollback = "ROLLBACK" - - case abort = "ABORT" - - case fail = "FAIL" - - case ignore = "IGNORE" - -} - -// MARK: - Private - -public struct QueryClauses { - - var select = (distinct: false, columns: [Expression(literal: "*") as Expressible]) - - var from: (name: String, alias: String?, database: String?) - - var join = [(type: JoinType, query: QueryType, condition: Expressible)]() - - var filters: Expression? - - var group: (by: [Expressible], having: Expression?)? - - var order = [Expressible]() - - var limit: (length: Int, offset: Int?)? - - var union = [QueryType]() - - fileprivate init(_ name: String, alias: String?, database: String?) { - self.from = (name, alias, database) - } - -} - diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/Schema.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/Schema.swift deleted file mode 100755 index febfe68..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/Schema.swift +++ /dev/null @@ -1,517 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -extension SchemaType { - - // MARK: - DROP TABLE / VIEW / VIRTUAL TABLE - - public func drop(ifExists: Bool = false) -> String { - return drop("TABLE", tableName(), ifExists) - } - -} - -extension Table { - - // MARK: - CREATE TABLE - - public func create(temporary: Bool = false, ifNotExists: Bool = false, withoutRowid: Bool = false, block: (TableBuilder) -> Void) -> String { - let builder = TableBuilder() - - block(builder) - - let clauses: [Expressible?] = [ - create(Table.identifier, tableName(), temporary ? .temporary : nil, ifNotExists), - "".wrap(builder.definitions) as Expression, - withoutRowid ? Expression(literal: "WITHOUT ROWID") : nil - ] - - return " ".join(clauses.compactMap { $0 }).asSQL() - } - - public func create(_ query: QueryType, temporary: Bool = false, ifNotExists: Bool = false) -> String { - let clauses: [Expressible?] = [ - create(Table.identifier, tableName(), temporary ? .temporary : nil, ifNotExists), - Expression(literal: "AS"), - query - ] - - return " ".join(clauses.compactMap { $0 }).asSQL() - } - - // MARK: - ALTER TABLE … ADD COLUMN - - public func addColumn(_ name: Expression, check: Expression? = nil, defaultValue: V) -> String { - return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil)) - } - - public func addColumn(_ name: Expression, check: Expression, defaultValue: V) -> String { - return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil)) - } - - public func addColumn(_ name: Expression, check: Expression? = nil, defaultValue: V? = nil) -> String { - return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil)) - } - - public func addColumn(_ name: Expression, check: Expression, defaultValue: V? = nil) -> String { - return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil)) - } - - public func addColumn(_ name: Expression, unique: Bool = false, check: Expression? = nil, references table: QueryType, _ other: Expression) -> String where V.Datatype == Int64 { - return addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil)) - } - - public func addColumn(_ name: Expression, unique: Bool = false, check: Expression, references table: QueryType, _ other: Expression) -> String where V.Datatype == Int64 { - return addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil)) - } - - public func addColumn(_ name: Expression, unique: Bool = false, check: Expression? = nil, references table: QueryType, _ other: Expression) -> String where V.Datatype == Int64 { - return addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil)) - } - - public func addColumn(_ name: Expression, unique: Bool = false, check: Expression, references table: QueryType, _ other: Expression) -> String where V.Datatype == Int64 { - return addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil)) - } - - public func addColumn(_ name: Expression, check: Expression? = nil, defaultValue: V, collate: Collation) -> String where V.Datatype == String { - return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate)) - } - - public func addColumn(_ name: Expression, check: Expression, defaultValue: V, collate: Collation) -> String where V.Datatype == String { - return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate)) - } - - public func addColumn(_ name: Expression, check: Expression? = nil, defaultValue: V? = nil, collate: Collation) -> String where V.Datatype == String { - return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate)) - } - - public func addColumn(_ name: Expression, check: Expression, defaultValue: V? = nil, collate: Collation) -> String where V.Datatype == String { - return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate)) - } - - fileprivate func addColumn(_ expression: Expressible) -> String { - return " ".join([ - Expression(literal: "ALTER TABLE"), - tableName(), - Expression(literal: "ADD COLUMN"), - expression - ]).asSQL() - } - - // MARK: - ALTER TABLE … RENAME TO - - public func rename(_ to: Table) -> String { - return rename(to: to) - } - - // MARK: - CREATE INDEX - - public func createIndex(_ columns: Expressible..., unique: Bool = false, ifNotExists: Bool = false) -> String { - let clauses: [Expressible?] = [ - create("INDEX", indexName(columns), unique ? .unique : nil, ifNotExists), - Expression(literal: "ON"), - tableName(qualified: false), - "".wrap(columns) as Expression - ] - - return " ".join(clauses.compactMap { $0 }).asSQL() - } - - // MARK: - DROP INDEX - - - public func dropIndex(_ columns: Expressible..., ifExists: Bool = false) -> String { - return drop("INDEX", indexName(columns), ifExists) - } - - fileprivate func indexName(_ columns: [Expressible]) -> Expressible { - let string = (["index", clauses.from.name, "on"] + columns.map { $0.expression.template }).joined(separator: " ").lowercased() - - let index = string.reduce("") { underscored, character in - guard character != "\"" else { - return underscored - } - guard "a"..."z" ~= character || "0"..."9" ~= character else { - return underscored + "_" - } - return underscored + String(character) - } - - return database(namespace: index) - } - -} - -extension View { - - // MARK: - CREATE VIEW - - public func create(_ query: QueryType, temporary: Bool = false, ifNotExists: Bool = false) -> String { - let clauses: [Expressible?] = [ - create(View.identifier, tableName(), temporary ? .temporary : nil, ifNotExists), - Expression(literal: "AS"), - query - ] - - return " ".join(clauses.compactMap { $0 }).asSQL() - } - - // MARK: - DROP VIEW - - public func drop(ifExists: Bool = false) -> String { - return drop("VIEW", tableName(), ifExists) - } - -} - -extension VirtualTable { - - // MARK: - CREATE VIRTUAL TABLE - - public func create(_ using: Module, ifNotExists: Bool = false) -> String { - let clauses: [Expressible?] = [ - create(VirtualTable.identifier, tableName(), nil, ifNotExists), - Expression(literal: "USING"), - using - ] - - return " ".join(clauses.compactMap { $0 }).asSQL() - } - - // MARK: - ALTER TABLE … RENAME TO - - public func rename(_ to: VirtualTable) -> String { - return rename(to: to) - } - -} - -public final class TableBuilder { - - fileprivate var definitions = [Expressible]() - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: Expression? = nil) { - column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: V) { - column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: Expression? = nil) { - column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: V) { - column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: Expression? = nil) { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: Expression) { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: V) { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: Expression? = nil) { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: Expression) { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: V) { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, primaryKey: Bool, check: Expression? = nil, defaultValue: Expression? = nil) { - column(name, V.declaredDatatype, primaryKey ? .default : nil, false, false, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, primaryKey: Bool, check: Expression, defaultValue: Expression? = nil) { - column(name, V.declaredDatatype, primaryKey ? .default : nil, false, false, check, defaultValue, nil, nil) - } - - public func column(_ name: Expression, primaryKey: PrimaryKey, check: Expression? = nil) where V.Datatype == Int64 { - column(name, V.declaredDatatype, primaryKey, false, false, check, nil, nil, nil) - } - - public func column(_ name: Expression, primaryKey: PrimaryKey, check: Expression) where V.Datatype == Int64 { - column(name, V.declaredDatatype, primaryKey, false, false, check, nil, nil, nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, references table: QueryType, _ other: Expression) where V.Datatype == Int64 { - column(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, references table: QueryType, _ other: Expression) where V.Datatype == Int64 { - column(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, references table: QueryType, _ other: Expression) where V.Datatype == Int64 { - column(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, references table: QueryType, _ other: Expression) where V.Datatype == Int64 { - column(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: Expression? = nil, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: V, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: Expression? = nil, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: V, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: Expression? = nil, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: Expression, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression? = nil, defaultValue: V, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: Expression? = nil, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: Expression, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate) - } - - public func column(_ name: Expression, unique: Bool = false, check: Expression, defaultValue: V, collate: Collation) where V.Datatype == String { - column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate) - } - - fileprivate func column(_ name: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?) { - definitions.append(definition(name, datatype, primaryKey, null, unique, check, defaultValue, references, collate)) - } - - // MARK: - - - public func primaryKey(_ column: Expression) { - primaryKey([column]) - } - - public func primaryKey(_ compositeA: Expression, _ b: Expression) { - primaryKey([compositeA, b]) - } - - public func primaryKey(_ compositeA: Expression, _ b: Expression, _ c: Expression) { - primaryKey([compositeA, b, c]) - } - - public func primaryKey(_ compositeA: Expression, _ b: Expression, _ c: Expression, _ d: Expression) { - primaryKey([compositeA, b, c, d]) - } - - fileprivate func primaryKey(_ composite: [Expressible]) { - definitions.append("PRIMARY KEY".prefix(composite)) - } - - public func unique(_ columns: Expressible...) { - unique(columns) - } - - public func unique(_ columns: [Expressible]) { - definitions.append("UNIQUE".prefix(columns)) - } - - public func check(_ condition: Expression) { - check(Expression(condition)) - } - - public func check(_ condition: Expression) { - definitions.append("CHECK".prefix(condition)) - } - - public enum Dependency: String { - - case noAction = "NO ACTION" - - case restrict = "RESTRICT" - - case setNull = "SET NULL" - - case setDefault = "SET DEFAULT" - - case cascade = "CASCADE" - - } - - public func foreignKey(_ column: Expression, references table: QueryType, _ other: Expression, update: Dependency? = nil, delete: Dependency? = nil) { - foreignKey(column, (table, other), update, delete) - } - - public func foreignKey(_ column: Expression, references table: QueryType, _ other: Expression, update: Dependency? = nil, delete: Dependency? = nil) { - foreignKey(column, (table, other), update, delete) - } - - public func foreignKey(_ composite: (Expression, Expression), references table: QueryType, _ other: (Expression, Expression), update: Dependency? = nil, delete: Dependency? = nil) { - let composite = ", ".join([composite.0, composite.1]) - let references = (table, ", ".join([other.0, other.1])) - - foreignKey(composite, references, update, delete) - } - - public func foreignKey(_ composite: (Expression, Expression, Expression), references table: QueryType, _ other: (Expression, Expression, Expression), update: Dependency? = nil, delete: Dependency? = nil) { - let composite = ", ".join([composite.0, composite.1, composite.2]) - let references = (table, ", ".join([other.0, other.1, other.2])) - - foreignKey(composite, references, update, delete) - } - - fileprivate func foreignKey(_ column: Expressible, _ references: (QueryType, Expressible), _ update: Dependency?, _ delete: Dependency?) { - let clauses: [Expressible?] = [ - "FOREIGN KEY".prefix(column), - reference(references), - update.map { Expression(literal: "ON UPDATE \($0.rawValue)") }, - delete.map { Expression(literal: "ON DELETE \($0.rawValue)") } - ] - - definitions.append(" ".join(clauses.compactMap { $0 })) - } - -} - -public enum PrimaryKey { - - case `default` - - case autoincrement - -} - -public struct Module { - - fileprivate let name: String - - fileprivate let arguments: [Expressible] - - public init(_ name: String, _ arguments: [Expressible]) { - self.init(name: name.quote(), arguments: arguments) - } - - init(name: String, arguments: [Expressible]) { - self.name = name - self.arguments = arguments - } - -} - -extension Module : Expressible { - - public var expression: Expression { - return name.wrap(arguments) - } - -} - -// MARK: - Private - -private extension QueryType { - - func create(_ identifier: String, _ name: Expressible, _ modifier: Modifier?, _ ifNotExists: Bool) -> Expressible { - let clauses: [Expressible?] = [ - Expression(literal: "CREATE"), - modifier.map { Expression(literal: $0.rawValue) }, - Expression(literal: identifier), - ifNotExists ? Expression(literal: "IF NOT EXISTS") : nil, - name - ] - - return " ".join(clauses.compactMap { $0 }) - } - - func rename(to: Self) -> String { - return " ".join([ - Expression(literal: "ALTER TABLE"), - tableName(), - Expression(literal: "RENAME TO"), - Expression(to.clauses.from.name) - ]).asSQL() - } - - func drop(_ identifier: String, _ name: Expressible, _ ifExists: Bool) -> String { - let clauses: [Expressible?] = [ - Expression(literal: "DROP \(identifier)"), - ifExists ? Expression(literal: "IF EXISTS") : nil, - name - ] - - return " ".join(clauses.compactMap { $0 }).asSQL() - } - -} - -private func definition(_ column: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?) -> Expressible { - let clauses: [Expressible?] = [ - column, - Expression(literal: datatype), - primaryKey.map { Expression(literal: $0 == .autoincrement ? "PRIMARY KEY AUTOINCREMENT" : "PRIMARY KEY") }, - null ? nil : Expression(literal: "NOT NULL"), - unique ? Expression(literal: "UNIQUE") : nil, - check.map { " ".join([Expression(literal: "CHECK"), $0]) }, - defaultValue.map { "DEFAULT".prefix($0) }, - references.map(reference), - collate.map { " ".join([Expression(literal: "COLLATE"), $0]) } - ] - - return " ".join(clauses.compactMap { $0 }) -} - -private func reference(_ primary: (QueryType, Expressible)) -> Expressible { - return " ".join([ - Expression(literal: "REFERENCES"), - primary.0.tableName(qualified: false), - "".wrap(primary.1) as Expression - ]) -} - -private enum Modifier : String { - - case unique = "UNIQUE" - - case temporary = "TEMPORARY" - -} diff --git a/ios/libs/Sqlite/Sources/SQLite/Typed/Setter.swift b/ios/libs/Sqlite/Sources/SQLite/Typed/Setter.swift deleted file mode 100755 index 86f16fc..0000000 --- a/ios/libs/Sqlite/Sources/SQLite/Typed/Setter.swift +++ /dev/null @@ -1,277 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -precedencegroup ColumnAssignment { - associativity: left - assignment: true - lowerThan: AssignmentPrecedence -} - -infix operator <- : ColumnAssignment - -public struct Setter { - - let column: Expressible - let value: Expressible - - fileprivate init(column: Expression, value: Expression) { - self.column = column - self.value = value - } - - fileprivate init(column: Expression, value: V) { - self.column = column - self.value = value - } - - fileprivate init(column: Expression, value: Expression) { - self.column = column - self.value = value - } - - fileprivate init(column: Expression, value: Expression) { - self.column = column - self.value = value - } - - fileprivate init(column: Expression, value: V?) { - self.column = column - self.value = Expression(value: value) - } - -} - -extension Setter : Expressible { - - public var expression: Expression { - return "=".infix(column, value, wrap: false) - } - -} - -public func <-(column: Expression, value: Expression) -> Setter { - return Setter(column: column, value: value) -} -public func <-(column: Expression, value: V) -> Setter { - return Setter(column: column, value: value) -} -public func <-(column: Expression, value: Expression) -> Setter { - return Setter(column: column, value: value) -} -public func <-(column: Expression, value: Expression) -> Setter { - return Setter(column: column, value: value) -} -public func <-(column: Expression, value: V?) -> Setter { - return Setter(column: column, value: value) -} - -public func +=(column: Expression, value: Expression) -> Setter { - return column <- column + value -} -public func +=(column: Expression, value: String) -> Setter { - return column <- column + value -} -public func +=(column: Expression, value: Expression) -> Setter { - return column <- column + value -} -public func +=(column: Expression, value: Expression) -> Setter { - return column <- column + value -} -public func +=(column: Expression, value: String) -> Setter { - return column <- column + value -} - -public func +=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column + value -} -public func +=(column: Expression, value: V) -> Setter where V.Datatype : Number { - return column <- column + value -} -public func +=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column + value -} -public func +=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column + value -} -public func +=(column: Expression, value: V) -> Setter where V.Datatype : Number { - return column <- column + value -} - -public func -=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column - value -} -public func -=(column: Expression, value: V) -> Setter where V.Datatype : Number { - return column <- column - value -} -public func -=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column - value -} -public func -=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column - value -} -public func -=(column: Expression, value: V) -> Setter where V.Datatype : Number { - return column <- column - value -} - -public func *=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column * value -} -public func *=(column: Expression, value: V) -> Setter where V.Datatype : Number { - return column <- column * value -} -public func *=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column * value -} -public func *=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column * value -} -public func *=(column: Expression, value: V) -> Setter where V.Datatype : Number { - return column <- column * value -} - -public func /=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column / value -} -public func /=(column: Expression, value: V) -> Setter where V.Datatype : Number { - return column <- column / value -} -public func /=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column / value -} -public func /=(column: Expression, value: Expression) -> Setter where V.Datatype : Number { - return column <- column / value -} -public func /=(column: Expression, value: V) -> Setter where V.Datatype : Number { - return column <- column / value -} - -public func %=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column % value -} -public func %=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column % value -} -public func %=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column % value -} -public func %=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column % value -} -public func %=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column % value -} - -public func <<=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column << value -} -public func <<=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column << value -} -public func <<=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column << value -} -public func <<=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column << value -} -public func <<=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column << value -} - -public func >>=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column >> value -} -public func >>=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column >> value -} -public func >>=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column >> value -} -public func >>=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column >> value -} -public func >>=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column >> value -} - -public func &=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column & value -} -public func &=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column & value -} -public func &=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column & value -} -public func &=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column & value -} -public func &=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column & value -} - -public func |=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column | value -} -public func |=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column | value -} -public func |=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column | value -} -public func |=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column | value -} -public func |=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column | value -} - -public func ^=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column ^ value -} -public func ^=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column ^ value -} -public func ^=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column ^ value -} -public func ^=(column: Expression, value: Expression) -> Setter where V.Datatype == Int64 { - return column <- column ^ value -} -public func ^=(column: Expression, value: V) -> Setter where V.Datatype == Int64 { - return column <- column ^ value -} - -public postfix func ++(column: Expression) -> Setter where V.Datatype == Int64 { - return Expression(column) += 1 -} -public postfix func ++(column: Expression) -> Setter where V.Datatype == Int64 { - return Expression(column) += 1 -} - -public postfix func --(column: Expression) -> Setter where V.Datatype == Int64 { - return Expression(column) -= 1 -} -public postfix func --(column: Expression) -> Setter where V.Datatype == Int64 { - return Expression(column) -= 1 -} diff --git a/ios/libs/Sqlite/Sources/SQLiteObjc/SQLite-Bridging.m b/ios/libs/Sqlite/Sources/SQLiteObjc/SQLite-Bridging.m deleted file mode 100755 index e00a731..0000000 --- a/ios/libs/Sqlite/Sources/SQLiteObjc/SQLite-Bridging.m +++ /dev/null @@ -1,138 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#import "SQLite-Bridging.h" -#import "fts3_tokenizer.h" - -#pragma mark - FTS - -typedef struct __SQLiteTokenizer { - sqlite3_tokenizer base; - __unsafe_unretained _SQLiteTokenizerNextCallback callback; -} __SQLiteTokenizer; - -typedef struct __SQLiteTokenizerCursor { - void * base; - const char * input; - int inputOffset; - int inputLength; - int idx; -} __SQLiteTokenizerCursor; - -static NSMutableDictionary * __SQLiteTokenizerMap; - -static int __SQLiteTokenizerCreate(int argc, const char * const * argv, sqlite3_tokenizer ** ppTokenizer) { - __SQLiteTokenizer * tokenizer = (__SQLiteTokenizer *)sqlite3_malloc(sizeof(__SQLiteTokenizer)); - if (!tokenizer) { - return SQLITE_NOMEM; - } - memset(tokenizer, 0, sizeof(* tokenizer)); - - NSString * key = [NSString stringWithUTF8String:argv[0]]; - tokenizer->callback = [__SQLiteTokenizerMap objectForKey:key]; - if (!tokenizer->callback) { - return SQLITE_ERROR; - } - - *ppTokenizer = &tokenizer->base; - return SQLITE_OK; -} - -static int __SQLiteTokenizerDestroy(sqlite3_tokenizer * pTokenizer) { - sqlite3_free(pTokenizer); - return SQLITE_OK; -} - -static int __SQLiteTokenizerOpen(sqlite3_tokenizer * pTokenizer, const char * pInput, int nBytes, sqlite3_tokenizer_cursor ** ppCursor) { - __SQLiteTokenizerCursor * cursor = (__SQLiteTokenizerCursor *)sqlite3_malloc(sizeof(__SQLiteTokenizerCursor)); - if (!cursor) { - return SQLITE_NOMEM; - } - - cursor->input = pInput; - cursor->inputOffset = 0; - cursor->inputLength = 0; - cursor->idx = 0; - - *ppCursor = (sqlite3_tokenizer_cursor *)cursor; - return SQLITE_OK; -} - -static int __SQLiteTokenizerClose(sqlite3_tokenizer_cursor * pCursor) { - sqlite3_free(pCursor); - return SQLITE_OK; -} - -static int __SQLiteTokenizerNext(sqlite3_tokenizer_cursor * pCursor, const char ** ppToken, int * pnBytes, int * piStartOffset, int * piEndOffset, int * piPosition) { - __SQLiteTokenizerCursor * cursor = (__SQLiteTokenizerCursor *)pCursor; - __SQLiteTokenizer * tokenizer = (__SQLiteTokenizer *)cursor->base; - - cursor->inputOffset += cursor->inputLength; - const char * input = cursor->input + cursor->inputOffset; - const char * token = [tokenizer->callback(input, &cursor->inputOffset, &cursor->inputLength) cStringUsingEncoding:NSUTF8StringEncoding]; - if (!token) { - return SQLITE_DONE; - } - - *ppToken = token; - *pnBytes = (int)strlen(token); - *piStartOffset = cursor->inputOffset; - *piEndOffset = cursor->inputOffset + cursor->inputLength; - *piPosition = cursor->idx++; - return SQLITE_OK; -} - -static const sqlite3_tokenizer_module __SQLiteTokenizerModule = { - 0, - __SQLiteTokenizerCreate, - __SQLiteTokenizerDestroy, - __SQLiteTokenizerOpen, - __SQLiteTokenizerClose, - __SQLiteTokenizerNext -}; - -int _SQLiteRegisterTokenizer(sqlite3 *db, const char * moduleName, const char * submoduleName, _SQLiteTokenizerNextCallback callback) { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - __SQLiteTokenizerMap = [NSMutableDictionary new]; - }); - - sqlite3_stmt * stmt; - int status = sqlite3_prepare_v2(db, "SELECT fts3_tokenizer(?, ?)", -1, &stmt, 0); - if (status != SQLITE_OK ){ - return status; - } - const sqlite3_tokenizer_module * pModule = &__SQLiteTokenizerModule; - sqlite3_bind_text(stmt, 1, moduleName, -1, SQLITE_STATIC); - sqlite3_bind_blob(stmt, 2, &pModule, sizeof(pModule), SQLITE_STATIC); - sqlite3_step(stmt); - status = sqlite3_finalize(stmt); - if (status != SQLITE_OK ){ - return status; - } - - [__SQLiteTokenizerMap setObject:[callback copy] forKey:[NSString stringWithUTF8String:submoduleName]]; - - return SQLITE_OK; -} diff --git a/ios/libs/Sqlite/Sources/SQLiteObjc/fts3_tokenizer.h b/ios/libs/Sqlite/Sources/SQLiteObjc/fts3_tokenizer.h deleted file mode 100755 index d8a1e44..0000000 --- a/ios/libs/Sqlite/Sources/SQLiteObjc/fts3_tokenizer.h +++ /dev/null @@ -1,161 +0,0 @@ -/* -** 2006 July 10 -** -** The author disclaims copyright to this source code. -** -************************************************************************* -** Defines the interface to tokenizers used by fulltext-search. There -** are three basic components: -** -** sqlite3_tokenizer_module is a singleton defining the tokenizer -** interface functions. This is essentially the class structure for -** tokenizers. -** -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps -** including customization information defined at creation time. -** -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate -** tokens from a particular input. -*/ -#ifndef _FTS3_TOKENIZER_H_ -#define _FTS3_TOKENIZER_H_ - -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. -** If tokenizers are to be allowed to call sqlite3_*() functions, then -** we will need a way to register the API consistently. -*/ -#import "sqlite3.h" - -/* -** Structures used by the tokenizer interface. When a new tokenizer -** implementation is registered, the caller provides a pointer to -** an sqlite3_tokenizer_module containing pointers to the callback -** functions that make up an implementation. -** -** When an fts3 table is created, it passes any arguments passed to -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an -** sqlite3_tokenizer structure representing the specific tokenizer to -** be used for the fts3 table (customized by the tokenizer clause arguments). -** -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() -** method is called. It returns an sqlite3_tokenizer_cursor object -** that may be used to tokenize a specific input buffer based on -** the tokenization rules supplied by a specific sqlite3_tokenizer -** object. -*/ -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; -typedef struct sqlite3_tokenizer sqlite3_tokenizer; -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; - -struct sqlite3_tokenizer_module { - - /* - ** Structure version. Should always be set to 0 or 1. - */ - int iVersion; - - /* - ** Create a new tokenizer. The values in the argv[] array are the - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL - ** TABLE statement that created the fts3 table. For example, if - ** the following SQL is executed: - ** - ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) - ** - ** then argc is set to 2, and the argv[] array contains pointers - ** to the strings "arg1" and "arg2". - ** - ** This method should return either SQLITE_OK (0), or an SQLite error - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set - ** to point at the newly created tokenizer structure. The generic - ** sqlite3_tokenizer.pModule variable should not be initialized by - ** this callback. The caller will do so. - */ - int (*xCreate)( - int argc, /* Size of argv array */ - const char *const*argv, /* Tokenizer argument strings */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ - ); - - /* - ** Destroy an existing tokenizer. The fts3 module calls this method - ** exactly once for each successful call to xCreate(). - */ - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); - - /* - ** Create a tokenizer cursor to tokenize an input buffer. The caller - ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). - */ - int (*xOpen)( - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ - const char *pInput, int nBytes, /* Input buffer */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ - ); - - /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this - ** method exactly once for each successful call to xOpen(). - */ - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); - - /* - ** Retrieve the next token from the tokenizer cursor pCursor. This - ** method should either return SQLITE_OK and set the values of the - ** "OUT" variables identified below, or SQLITE_DONE to indicate that - ** the end of the buffer has been reached, or an SQLite error code. - ** - ** *ppToken should be set to point at a buffer containing the - ** normalized version of the token (i.e. after any case-folding and/or - ** stemming has been performed). *pnBytes should be set to the length - ** of this buffer in bytes. The input text that generated the token is - ** identified by the byte offsets returned in *piStartOffset and - ** *piEndOffset. *piStartOffset should be set to the index of the first - ** byte of the token in the input buffer. *piEndOffset should be set - ** to the index of the first byte just past the end of the token in - ** the input buffer. - ** - ** The buffer *ppToken is set to point at is managed by the tokenizer - ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). - */ - /* TODO(shess) current implementation requires pInput to be - ** nul-terminated. This should either be fixed, or pInput/nBytes - ** should be converted to zInput. - */ - int (*xNext)( - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ - int *piPosition /* OUT: Number of tokens returned before this one */ - ); - - /*********************************************************************** - ** Methods below this point are only available if iVersion>=1. - */ - - /* - ** Configure the language id of a tokenizer cursor. - */ - int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid); -}; - -struct sqlite3_tokenizer { - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ - /* Tokenizer implementations will typically add additional fields */ -}; - -struct sqlite3_tokenizer_cursor { - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ - /* Tokenizer implementations will typically add additional fields */ -}; - -int fts3_global_term_cnt(int iTerm, int iCol); -int fts3_term_cnt(int iTerm, int iCol); - - -#endif /* _FTS3_TOKENIZER_H_ */ diff --git a/ios/libs/Sqlite/Sources/SQLiteObjc/include/SQLite-Bridging.h b/ios/libs/Sqlite/Sources/SQLiteObjc/include/SQLite-Bridging.h deleted file mode 100755 index f8c2a3b..0000000 --- a/ios/libs/Sqlite/Sources/SQLiteObjc/include/SQLite-Bridging.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// SQLite.swift -// https://github.com/stephencelis/SQLite.swift -// Copyright © 2014-2015 Stephen Celis. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -@import Foundation; -@import SQLite3; - -NS_ASSUME_NONNULL_BEGIN -typedef NSString * _Nullable (^_SQLiteTokenizerNextCallback)(const char *input, int *inputOffset, int *inputLength); -int _SQLiteRegisterTokenizer(sqlite3 *db, const char *module, const char *tokenizer, _Nullable _SQLiteTokenizerNextCallback callback); -NS_ASSUME_NONNULL_END - diff --git a/ios/libs/Sqlite/Tests/Carthage/.gitignore b/ios/libs/Sqlite/Tests/Carthage/.gitignore deleted file mode 100755 index 2d43454..0000000 --- a/ios/libs/Sqlite/Tests/Carthage/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -Carthage/ -Cartfile -Cartfile.resolved diff --git a/ios/libs/Sqlite/Tests/Carthage/Makefile b/ios/libs/Sqlite/Tests/Carthage/Makefile deleted file mode 100755 index f28eb25..0000000 --- a/ios/libs/Sqlite/Tests/Carthage/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -CARTHAGE := /usr/local/bin/carthage -CARTHAGE_PLATFORM := iOS -CARTHAGE_CONFIGURATION := Release -CARTHAGE_DIR := Carthage -CARTHAGE_ARGS := --no-use-binaries -CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.Swift_3_0 -CARTHAGE_CMDLINE := --configuration $(CARTHAGE_CONFIGURATION) --platform $(CARTHAGE_PLATFORM) --toolchain $(CARTHAGE_TOOLCHAIN) $(CARTHAGE_ARGS) - -test: $(CARTHAGE) Cartfile - $< bootstrap $(CARTHAGE_CMDLINE) - -Cartfile: - echo 'git "$(TRAVIS_BUILD_DIR)" "HEAD"' > $@ - -clean: - @rm -f Cartfile Cartfile.resolved diff --git a/ios/libs/Sqlite/Tests/CocoaPods/.gitignore b/ios/libs/Sqlite/Tests/CocoaPods/.gitignore deleted file mode 100755 index 4cf24de..0000000 --- a/ios/libs/Sqlite/Tests/CocoaPods/.gitignore +++ /dev/null @@ -1 +0,0 @@ -gems/ diff --git a/ios/libs/Sqlite/Tests/CocoaPods/Gemfile b/ios/libs/Sqlite/Tests/CocoaPods/Gemfile deleted file mode 100755 index 77d90ee..0000000 --- a/ios/libs/Sqlite/Tests/CocoaPods/Gemfile +++ /dev/null @@ -1,4 +0,0 @@ -source 'https://rubygems.org' - -gem 'cocoapods', '~> 1.6.1' -gem 'minitest' diff --git a/ios/libs/Sqlite/Tests/CocoaPods/Gemfile.lock b/ios/libs/Sqlite/Tests/CocoaPods/Gemfile.lock deleted file mode 100755 index b517214..0000000 --- a/ios/libs/Sqlite/Tests/CocoaPods/Gemfile.lock +++ /dev/null @@ -1,77 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - CFPropertyList (3.0.0) - activesupport (4.2.11) - i18n (~> 0.7) - minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) - tzinfo (~> 1.1) - atomos (0.1.3) - claide (1.0.2) - cocoapods (1.6.0.beta.2) - activesupport (>= 4.0.2, < 5) - claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.6.0.beta.2) - cocoapods-deintegrate (>= 1.0.2, < 2.0) - cocoapods-downloader (>= 1.2.2, < 2.0) - cocoapods-plugins (>= 1.0.0, < 2.0) - cocoapods-search (>= 1.0.0, < 2.0) - cocoapods-stats (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.3.1, < 2.0) - cocoapods-try (>= 1.1.0, < 2.0) - colored2 (~> 3.1) - escape (~> 0.0.4) - fourflusher (~> 2.0.1) - gh_inspector (~> 1.0) - molinillo (~> 0.6.6) - nap (~> 1.0) - ruby-macho (~> 1.3, >= 1.3.1) - xcodeproj (>= 1.7.0, < 2.0) - cocoapods-core (1.6.0.beta.2) - activesupport (>= 4.0.2, < 6) - fuzzy_match (~> 2.0.4) - nap (~> 1.0) - cocoapods-deintegrate (1.0.2) - cocoapods-downloader (1.2.2) - cocoapods-plugins (1.0.0) - nap - cocoapods-search (1.0.0) - cocoapods-stats (1.0.0) - cocoapods-trunk (1.3.1) - nap (>= 0.8, < 2.0) - netrc (~> 0.11) - cocoapods-try (1.1.0) - colored2 (3.1.2) - concurrent-ruby (1.1.4) - escape (0.0.4) - fourflusher (2.0.1) - fuzzy_match (2.0.4) - gh_inspector (1.1.3) - i18n (0.9.5) - concurrent-ruby (~> 1.0) - minitest (5.11.3) - molinillo (0.6.6) - nanaimo (0.2.6) - nap (1.1.0) - netrc (0.11.0) - ruby-macho (1.3.1) - thread_safe (0.3.6) - tzinfo (1.2.5) - thread_safe (~> 0.1) - xcodeproj (1.7.0) - CFPropertyList (>= 2.3.3, < 4.0) - atomos (~> 0.1.3) - claide (>= 1.0.2, < 2.0) - colored2 (~> 3.1) - nanaimo (~> 0.2.6) - -PLATFORMS - ruby - -DEPENDENCIES - cocoapods (~> 1.6.0beta2) - minitest - -BUNDLED WITH - 1.17.1 diff --git a/ios/libs/Sqlite/Tests/CocoaPods/Makefile b/ios/libs/Sqlite/Tests/CocoaPods/Makefile deleted file mode 100755 index 532dcbf..0000000 --- a/ios/libs/Sqlite/Tests/CocoaPods/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -XCPRETTY := $(shell command -v xcpretty) - -test: install repo_update - @set -e; \ - for test in *_test.rb; do \ - bundle exec ./$$test | $(XCPRETTY) -c; \ - done - -repo_update: - @bundle exec pod repo update --silent - -install: - @bundle install --path gems - -.PHONY: test install diff --git a/ios/libs/Sqlite/Tests/CocoaPods/integration_test.rb b/ios/libs/Sqlite/Tests/CocoaPods/integration_test.rb deleted file mode 100755 index 98a539b..0000000 --- a/ios/libs/Sqlite/Tests/CocoaPods/integration_test.rb +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env ruby - -require 'cocoapods' -require 'cocoapods/validator' -require 'minitest/autorun' - -class IntegrationTest < Minitest::Test - - def test_validate_project - assert validator.validate, "validation failed: #{validator.failure_reason}" - end - - private - - def validator - @validator ||= CustomValidator.new(podspec, ['https://github.com/CocoaPods/Specs.git']).tap do |validator| - validator.config.verbose = true - validator.no_clean = true - validator.use_frameworks = true - validator.fail_fast = true - validator.local = true - validator.allow_warnings = true - subspec = ENV['VALIDATOR_SUBSPEC'] - if subspec == 'none' - validator.no_subspecs = true - else - validator.only_subspec = subspec - end - end - end - - def podspec - File.expand_path(File.dirname(__FILE__) + '/../../SQLite.swift.podspec') - end - - - class CustomValidator < Pod::Validator - def test_pod - # https://github.com/CocoaPods/CocoaPods/issues/7009 - super unless consumer.platform_name == :watchos - end - - def xcodebuild(action, scheme, configuration) - require 'fourflusher' - command = %W(#{action} -workspace #{File.join(validation_dir, 'App.xcworkspace')} -scheme #{scheme} -configuration #{configuration}) - case consumer.platform_name - when :osx, :macos - command += %w(CODE_SIGN_IDENTITY=) - when :ios - command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator) - command += Fourflusher::SimControl.new.destination(nil, 'iOS', deployment_target) - when :watchos - command += %w(CODE_SIGN_IDENTITY=- -sdk watchsimulator) - command += Fourflusher::SimControl.new.destination(:oldest, 'watchOS', deployment_target) - when :tvos - command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator) - command += Fourflusher::SimControl.new.destination(:oldest, 'tvOS', deployment_target) - end - - begin - _xcodebuild(command, true) - rescue => e - message = 'Returned an unsuccessful exit code.' - message += ' You can use `--verbose` for more information.' unless config.verbose? - error('xcodebuild', message) - e.message - end - end - end -end diff --git a/ios/libs/Sqlite/Tests/LinuxMain.swift b/ios/libs/Sqlite/Tests/LinuxMain.swift deleted file mode 100755 index 59796fd..0000000 --- a/ios/libs/Sqlite/Tests/LinuxMain.swift +++ /dev/null @@ -1,6 +0,0 @@ -import XCTest -@testable import SQLiteTests - -XCTMain([ -testCase([ -])]) diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/AggregateFunctionsTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/AggregateFunctionsTests.swift deleted file mode 100755 index 6b583cc..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/AggregateFunctionsTests.swift +++ /dev/null @@ -1,68 +0,0 @@ -import XCTest -import SQLite - -class AggregateFunctionsTests : XCTestCase { - - func test_distinct_prependsExpressionsWithDistinctKeyword() { - AssertSQL("DISTINCT \"int\"", int.distinct) - AssertSQL("DISTINCT \"intOptional\"", intOptional.distinct) - AssertSQL("DISTINCT \"double\"", double.distinct) - AssertSQL("DISTINCT \"doubleOptional\"", doubleOptional.distinct) - AssertSQL("DISTINCT \"string\"", string.distinct) - AssertSQL("DISTINCT \"stringOptional\"", stringOptional.distinct) - } - - func test_count_wrapsOptionalExpressionsWithCountFunction() { - AssertSQL("count(\"intOptional\")", intOptional.count) - AssertSQL("count(\"doubleOptional\")", doubleOptional.count) - AssertSQL("count(\"stringOptional\")", stringOptional.count) - } - - func test_max_wrapsComparableExpressionsWithMaxFunction() { - AssertSQL("max(\"int\")", int.max) - AssertSQL("max(\"intOptional\")", intOptional.max) - AssertSQL("max(\"double\")", double.max) - AssertSQL("max(\"doubleOptional\")", doubleOptional.max) - AssertSQL("max(\"string\")", string.max) - AssertSQL("max(\"stringOptional\")", stringOptional.max) - AssertSQL("max(\"date\")", date.max) - AssertSQL("max(\"dateOptional\")", dateOptional.max) - } - - func test_min_wrapsComparableExpressionsWithMinFunction() { - AssertSQL("min(\"int\")", int.min) - AssertSQL("min(\"intOptional\")", intOptional.min) - AssertSQL("min(\"double\")", double.min) - AssertSQL("min(\"doubleOptional\")", doubleOptional.min) - AssertSQL("min(\"string\")", string.min) - AssertSQL("min(\"stringOptional\")", stringOptional.min) - AssertSQL("min(\"date\")", date.min) - AssertSQL("min(\"dateOptional\")", dateOptional.min) - } - - func test_average_wrapsNumericExpressionsWithAvgFunction() { - AssertSQL("avg(\"int\")", int.average) - AssertSQL("avg(\"intOptional\")", intOptional.average) - AssertSQL("avg(\"double\")", double.average) - AssertSQL("avg(\"doubleOptional\")", doubleOptional.average) - } - - func test_sum_wrapsNumericExpressionsWithSumFunction() { - AssertSQL("sum(\"int\")", int.sum) - AssertSQL("sum(\"intOptional\")", intOptional.sum) - AssertSQL("sum(\"double\")", double.sum) - AssertSQL("sum(\"doubleOptional\")", doubleOptional.sum) - } - - func test_total_wrapsNumericExpressionsWithTotalFunction() { - AssertSQL("total(\"int\")", int.total) - AssertSQL("total(\"intOptional\")", intOptional.total) - AssertSQL("total(\"double\")", double.total) - AssertSQL("total(\"doubleOptional\")", doubleOptional.total) - } - - func test_count_withStar_wrapsStarWithCountFunction() { - AssertSQL("count(*)", count(*)) - } - -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/BlobTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/BlobTests.swift deleted file mode 100755 index 817205d..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/BlobTests.swift +++ /dev/null @@ -1,23 +0,0 @@ -import XCTest -import SQLite - -class BlobTests : XCTestCase { - - func test_toHex() { - let blob = Blob(bytes: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 250, 255]) - - XCTAssertEqual(blob.toHex(), "000a141e28323c46505a6496faff") - } - - func test_init_array() { - let blob = Blob(bytes: [42, 42, 42]) - XCTAssertEqual(blob.bytes, [42, 42, 42]) - } - - func test_init_unsafeRawPointer() { - let pointer = UnsafeMutablePointer.allocate(capacity: 3) - pointer.initialize(repeating: 42, count: 3) - let blob = Blob(bytes: pointer, length: 3) - XCTAssertEqual(blob.bytes, [42, 42, 42]) - } -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/CipherTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/CipherTests.swift deleted file mode 100755 index abecffb..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/CipherTests.swift +++ /dev/null @@ -1,104 +0,0 @@ -#if SQLITE_SWIFT_SQLCIPHER -import XCTest -import SQLite -import SQLCipher - -class CipherTests: XCTestCase { - - let db1 = try! Connection() - let db2 = try! Connection() - - override func setUp() { - // db - - try! db1.key("hello") - - try! db1.run("CREATE TABLE foo (bar TEXT)") - try! db1.run("INSERT INTO foo (bar) VALUES ('world')") - - // db2 - let key2 = keyData() - try! db2.key(Blob(bytes: key2.bytes, length: key2.length)) - - try! db2.run("CREATE TABLE foo (bar TEXT)") - try! db2.run("INSERT INTO foo (bar) VALUES ('world')") - - super.setUp() - } - - func test_key() { - XCTAssertEqual(1, try! db1.scalar("SELECT count(*) FROM foo") as? Int64) - } - - func test_key_blob_literal() { - let db = try! Connection() - try! db.key("x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'") - } - - func test_rekey() { - try! db1.rekey("goodbye") - XCTAssertEqual(1, try! db1.scalar("SELECT count(*) FROM foo") as? Int64) - } - - func test_data_key() { - XCTAssertEqual(1, try! db2.scalar("SELECT count(*) FROM foo") as? Int64) - } - - func test_data_rekey() { - let newKey = keyData() - try! db2.rekey(Blob(bytes: newKey.bytes, length: newKey.length)) - XCTAssertEqual(1, try! db2.scalar("SELECT count(*) FROM foo") as? Int64) - } - - func test_keyFailure() { - let path = "\(NSTemporaryDirectory())/db.sqlite3" - _ = try? FileManager.default.removeItem(atPath: path) - - let connA = try! Connection(path) - defer { try! FileManager.default.removeItem(atPath: path) } - - try! connA.key("hello") - try! connA.run("CREATE TABLE foo (bar TEXT)") - - let connB = try! Connection(path, readonly: true) - - do { - try connB.key("world") - XCTFail("expected exception") - } catch Result.error(_, let code, _) { - XCTAssertEqual(SQLITE_NOTADB, code) - } catch { - XCTFail("unexpected error: \(error)") - } - } - - func test_open_db_encrypted_with_sqlcipher() { - // $ sqlcipher Tests/SQLiteTests/fixtures/encrypted-[version].x.sqlite - // sqlite> pragma key = 'sqlcipher-test'; - // sqlite> CREATE TABLE foo (bar TEXT); - // sqlite> INSERT INTO foo (bar) VALUES ('world'); - guard let cipherVersion:String = db1.cipherVersion, - cipherVersion.starts(with: "3.") || cipherVersion.starts(with: "4.") - else { return } - - let encryptedFile = cipherVersion.starts(with: "3.") ? - fixture("encrypted-3.x", withExtension: "sqlite") : - fixture("encrypted-4.x", withExtension: "sqlite") - - try! FileManager.default.setAttributes([FileAttributeKey.immutable : 1], ofItemAtPath: encryptedFile) - XCTAssertFalse(FileManager.default.isWritableFile(atPath: encryptedFile)) - - let conn = try! Connection(encryptedFile) - try! conn.key("sqlcipher-test") - XCTAssertEqual(1, try! conn.scalar("SELECT count(*) FROM foo") as? Int64) - } - - private func keyData(length: Int = 64) -> NSMutableData { - let keyData = NSMutableData(length: length)! - let result = SecRandomCopyBytes(kSecRandomDefault, length, - keyData.mutableBytes.assumingMemoryBound(to: UInt8.self)) - XCTAssertEqual(0, result) - return keyData - } -} -#endif diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/ConnectionTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/ConnectionTests.swift deleted file mode 100755 index eab3cf0..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/ConnectionTests.swift +++ /dev/null @@ -1,451 +0,0 @@ -import XCTest -import Foundation -import Dispatch -@testable import SQLite - -#if SQLITE_SWIFT_STANDALONE -import sqlite3 -#elseif SQLITE_SWIFT_SQLCIPHER -import SQLCipher -#elseif os(Linux) -import CSQLite -#else -import SQLite3 -#endif - -class ConnectionTests : SQLiteTestCase { - - override func setUp() { - super.setUp() - - CreateUsersTable() - } - - func test_init_withInMemory_returnsInMemoryConnection() { - let db = try! Connection(.inMemory) - XCTAssertEqual("", db.description) - } - - func test_init_returnsInMemoryByDefault() { - let db = try! Connection() - XCTAssertEqual("", db.description) - } - - func test_init_withTemporary_returnsTemporaryConnection() { - let db = try! Connection(.temporary) - XCTAssertEqual("", db.description) - } - - func test_init_withURI_returnsURIConnection() { - let db = try! Connection(.uri("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")) - XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description) - } - - func test_init_withString_returnsURIConnection() { - let db = try! Connection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3") - XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description) - } - - func test_readonly_returnsFalseOnReadWriteConnections() { - XCTAssertFalse(db.readonly) - } - - func test_readonly_returnsTrueOnReadOnlyConnections() { - let db = try! Connection(readonly: true) - XCTAssertTrue(db.readonly) - } - - func test_changes_returnsZeroOnNewConnections() { - XCTAssertEqual(0, db.changes) - } - - func test_lastInsertRowid_returnsLastIdAfterInserts() { - try! InsertUser("alice") - XCTAssertEqual(1, db.lastInsertRowid) - } - - func test_lastInsertRowid_doesNotResetAfterError() { - XCTAssert(db.lastInsertRowid == 0) - try! InsertUser("alice") - XCTAssertEqual(1, db.lastInsertRowid) - XCTAssertThrowsError( - try db.run("INSERT INTO \"users\" (email, age, admin) values ('invalid@example.com', 12, 'invalid')") - ) { error in - if case SQLite.Result.error(_, let code, _) = error { - XCTAssertEqual(SQLITE_CONSTRAINT, code) - } else { - XCTFail("expected error") - } - } - XCTAssertEqual(1, db.lastInsertRowid) - } - - func test_changes_returnsNumberOfChanges() { - try! InsertUser("alice") - XCTAssertEqual(1, db.changes) - try! InsertUser("betsy") - XCTAssertEqual(1, db.changes) - } - - func test_totalChanges_returnsTotalNumberOfChanges() { - XCTAssertEqual(0, db.totalChanges) - try! InsertUser("alice") - XCTAssertEqual(1, db.totalChanges) - try! InsertUser("betsy") - XCTAssertEqual(2, db.totalChanges) - } - - func test_prepare_preparesAndReturnsStatements() { - _ = try! db.prepare("SELECT * FROM users WHERE admin = 0") - _ = try! db.prepare("SELECT * FROM users WHERE admin = ?", 0) - _ = try! db.prepare("SELECT * FROM users WHERE admin = ?", [0]) - _ = try! db.prepare("SELECT * FROM users WHERE admin = $admin", ["$admin": 0]) - } - - func test_run_preparesRunsAndReturnsStatements() { - try! db.run("SELECT * FROM users WHERE admin = 0") - try! db.run("SELECT * FROM users WHERE admin = ?", 0) - try! db.run("SELECT * FROM users WHERE admin = ?", [0]) - try! db.run("SELECT * FROM users WHERE admin = $admin", ["$admin": 0]) - AssertSQL("SELECT * FROM users WHERE admin = 0", 4) - } - - func test_scalar_preparesRunsAndReturnsScalarValues() { - XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = 0") as? Int64) - XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = ?", 0) as? Int64) - XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = ?", [0]) as? Int64) - XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = $admin", ["$admin": 0]) as? Int64) - AssertSQL("SELECT count(*) FROM users WHERE admin = 0", 4) - } - - func test_execute_comment() { - try! db.run("-- this is a comment\nSELECT 1") - AssertSQL("-- this is a comment", 0) - AssertSQL("SELECT 1", 0) - } - - func test_transaction_executesBeginDeferred() { - try! db.transaction(.deferred) {} - - AssertSQL("BEGIN DEFERRED TRANSACTION") - } - - func test_transaction_executesBeginImmediate() { - try! db.transaction(.immediate) {} - - AssertSQL("BEGIN IMMEDIATE TRANSACTION") - } - - func test_transaction_executesBeginExclusive() { - try! db.transaction(.exclusive) {} - - AssertSQL("BEGIN EXCLUSIVE TRANSACTION") - } - - func test_transaction_beginsAndCommitsTransactions() { - let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com") - - try! db.transaction { - try stmt.run() - } - - AssertSQL("BEGIN DEFERRED TRANSACTION") - AssertSQL("INSERT INTO users (email) VALUES ('alice@example.com')") - AssertSQL("COMMIT TRANSACTION") - AssertSQL("ROLLBACK TRANSACTION", 0) - } - - func test_transaction_rollsBackTransactionsIfCommitsFail() { - let sqliteVersion = String(describing: try! db.scalar("SELECT sqlite_version()")!) - .split(separator: ".").compactMap { Int($0) } - // PRAGMA defer_foreign_keys only supported in SQLite >= 3.8.0 - guard sqliteVersion[0] == 3 && sqliteVersion[1] >= 8 else { - NSLog("skipping test for SQLite version \(sqliteVersion)") - return - } - // This test case needs to emulate an environment where the individual statements succeed, but committing the - // transaction fails. Using deferred foreign keys is one option to achieve this. - try! db.execute("PRAGMA foreign_keys = ON;") - try! db.execute("PRAGMA defer_foreign_keys = ON;") - let stmt = try! db.prepare("INSERT INTO users (email, manager_id) VALUES (?, ?)", "alice@example.com", 100) - - do { - try db.transaction { - try stmt.run() - } - XCTFail("expected error") - } catch let Result.error(_, code, _) { - XCTAssertEqual(SQLITE_CONSTRAINT, code) - } catch let error { - XCTFail("unexpected error: \(error)") - } - - AssertSQL("BEGIN DEFERRED TRANSACTION") - AssertSQL("INSERT INTO users (email, manager_id) VALUES ('alice@example.com', 100)") - AssertSQL("COMMIT TRANSACTION") - AssertSQL("ROLLBACK TRANSACTION") - - // Run another transaction to ensure that a subsequent transaction does not fail with an "cannot start a - // transaction within a transaction" error. - let stmt2 = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com") - try! db.transaction { - try stmt2.run() - } - } - - func test_transaction_beginsAndRollsTransactionsBack() { - let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com") - - do { - try db.transaction { - try stmt.run() - try stmt.run() - } - } catch { - } - - AssertSQL("BEGIN DEFERRED TRANSACTION") - AssertSQL("INSERT INTO users (email) VALUES ('alice@example.com')", 2) - AssertSQL("ROLLBACK TRANSACTION") - AssertSQL("COMMIT TRANSACTION", 0) - } - - func test_savepoint_beginsAndCommitsSavepoints() { - let db:Connection = self.db - - try! db.savepoint("1") { - try db.savepoint("2") { - try db.run("INSERT INTO users (email) VALUES (?)", "alice@example.com") - } - } - - AssertSQL("SAVEPOINT '1'") - AssertSQL("SAVEPOINT '2'") - AssertSQL("INSERT INTO users (email) VALUES ('alice@example.com')") - AssertSQL("RELEASE SAVEPOINT '2'") - AssertSQL("RELEASE SAVEPOINT '1'") - AssertSQL("ROLLBACK TO SAVEPOINT '2'", 0) - AssertSQL("ROLLBACK TO SAVEPOINT '1'", 0) - } - - func test_savepoint_beginsAndRollsSavepointsBack() { - let db:Connection = self.db - let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com") - - do { - try db.savepoint("1") { - try db.savepoint("2") { - try stmt.run() - try stmt.run() - try stmt.run() - } - try db.savepoint("2") { - try stmt.run() - try stmt.run() - try stmt.run() - } - } - } catch { - } - - AssertSQL("SAVEPOINT '1'") - AssertSQL("SAVEPOINT '2'") - AssertSQL("INSERT INTO users (email) VALUES ('alice@example.com')", 2) - AssertSQL("ROLLBACK TO SAVEPOINT '2'") - AssertSQL("ROLLBACK TO SAVEPOINT '1'") - AssertSQL("RELEASE SAVEPOINT '2'", 0) - AssertSQL("RELEASE SAVEPOINT '1'", 0) - } - - func test_updateHook_setsUpdateHook_withInsert() { - async { done in - db.updateHook { operation, db, table, rowid in - XCTAssertEqual(Connection.Operation.insert, operation) - XCTAssertEqual("main", db) - XCTAssertEqual("users", table) - XCTAssertEqual(1, rowid) - done() - } - try! InsertUser("alice") - } - } - - func test_updateHook_setsUpdateHook_withUpdate() { - try! InsertUser("alice") - async { done in - db.updateHook { operation, db, table, rowid in - XCTAssertEqual(Connection.Operation.update, operation) - XCTAssertEqual("main", db) - XCTAssertEqual("users", table) - XCTAssertEqual(1, rowid) - done() - } - try! db.run("UPDATE users SET email = 'alice@example.com'") - } - } - - func test_updateHook_setsUpdateHook_withDelete() { - try! InsertUser("alice") - async { done in - db.updateHook { operation, db, table, rowid in - XCTAssertEqual(Connection.Operation.delete, operation) - XCTAssertEqual("main", db) - XCTAssertEqual("users", table) - XCTAssertEqual(1, rowid) - done() - } - try! db.run("DELETE FROM users WHERE id = 1") - } - } - - func test_commitHook_setsCommitHook() { - async { done in - db.commitHook { - done() - } - try! db.transaction { - try self.InsertUser("alice") - } - XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM users") as? Int64) - } - } - - func test_rollbackHook_setsRollbackHook() { - async { done in - db.rollbackHook(done) - do { - try db.transaction { - try self.InsertUser("alice") - try self.InsertUser("alice") // throw - } - } catch { - } - XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users") as? Int64) - } - } - - func test_commitHook_withRollback_rollsBack() { - async { done in - db.commitHook { - throw NSError(domain: "com.stephencelis.SQLiteTests", code: 1, userInfo: nil) - } - db.rollbackHook(done) - do { - try db.transaction { - try self.InsertUser("alice") - } - } catch { - } - XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users") as? Int64) - } - } - - func test_createFunction_withArrayArguments() { - db.createFunction("hello") { $0[0].map { "Hello, \($0)!" } } - - XCTAssertEqual("Hello, world!", try! db.scalar("SELECT hello('world')") as? String) - XCTAssert(try! db.scalar("SELECT hello(NULL)") == nil) - } - - func test_createFunction_createsQuotableFunction() { - db.createFunction("hello world") { $0[0].map { "Hello, \($0)!" } } - - XCTAssertEqual("Hello, world!", try! db.scalar("SELECT \"hello world\"('world')") as? String) - XCTAssert(try! db.scalar("SELECT \"hello world\"(NULL)") == nil) - } - - func test_createCollation_createsCollation() { - try! db.createCollation("NODIACRITIC") { lhs, rhs in - return lhs.compare(rhs, options: .diacriticInsensitive) - } - XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE NODIACRITIC", "cafe", "café") as? Int64) - } - - func test_createCollation_createsQuotableCollation() { - try! db.createCollation("NO DIACRITIC") { lhs, rhs in - return lhs.compare(rhs, options: .diacriticInsensitive) - } - XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE \"NO DIACRITIC\"", "cafe", "café") as? Int64) - } - - func test_interrupt_interruptsLongRunningQuery() { - let semaphore = DispatchSemaphore(value: 0) - db.createFunction("sleep") { args in - DispatchQueue.global(qos: .background).async { - self.db.interrupt() - semaphore.signal() - } - semaphore.wait() - return nil - } - let stmt = try! db.prepare("SELECT sleep()") - XCTAssertThrowsError(try stmt.run()) { error in - if case Result.error(_, let code, _) = error { - XCTAssertEqual(code, SQLITE_INTERRUPT) - } else { - XCTFail("unexpected error: \(error)") - } - } - } - - func test_concurrent_access_single_connection() { - // test can fail on iOS/tvOS 9.x: SQLite compile-time differences? - guard #available(iOS 10.0, OSX 10.10, tvOS 10.0, watchOS 2.2, *) else { return } - - let conn = try! Connection("\(NSTemporaryDirectory())/\(UUID().uuidString)") - try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);") - try! conn.run("INSERT INTO test(value) VALUES(?)", 0) - let queue = DispatchQueue(label: "Readers", attributes: [.concurrent]) - - let nReaders = 5 - let semaphores = Array(repeating: DispatchSemaphore(value: 100), count: nReaders) - for index in 0...random()) - AssertSQL("random()", Expression.random()) - } - - func test_length_wrapsStringExpressionWithLengthFunction() { - AssertSQL("length(\"string\")", string.length) - AssertSQL("length(\"stringOptional\")", stringOptional.length) - } - - func test_lowercaseString_wrapsStringExpressionWithLowerFunction() { - AssertSQL("lower(\"string\")", string.lowercaseString) - AssertSQL("lower(\"stringOptional\")", stringOptional.lowercaseString) - } - - func test_uppercaseString_wrapsStringExpressionWithUpperFunction() { - AssertSQL("upper(\"string\")", string.uppercaseString) - AssertSQL("upper(\"stringOptional\")", stringOptional.uppercaseString) - } - - func test_like_buildsExpressionWithLikeOperator() { - AssertSQL("(\"string\" LIKE 'a%')", string.like("a%")) - AssertSQL("(\"stringOptional\" LIKE 'b%')", stringOptional.like("b%")) - - AssertSQL("(\"string\" LIKE '%\\%' ESCAPE '\\')", string.like("%\\%", escape: "\\")) - AssertSQL("(\"stringOptional\" LIKE '_\\_' ESCAPE '\\')", stringOptional.like("_\\_", escape: "\\")) - - AssertSQL("(\"string\" LIKE \"a\")", string.like(Expression("a"))) - AssertSQL("(\"stringOptional\" LIKE \"a\")", stringOptional.like(Expression("a"))) - - AssertSQL("(\"string\" LIKE \"a\" ESCAPE '\\')", string.like(Expression("a"), escape: "\\")) - AssertSQL("(\"stringOptional\" LIKE \"a\" ESCAPE '\\')", stringOptional.like(Expression("a"), escape: "\\")) - - AssertSQL("('string' LIKE \"a\")", "string".like(Expression("a"))) - AssertSQL("('string' LIKE \"a\" ESCAPE '\\')", "string".like(Expression("a"), escape: "\\")) - } - - func test_glob_buildsExpressionWithGlobOperator() { - AssertSQL("(\"string\" GLOB 'a*')", string.glob("a*")) - AssertSQL("(\"stringOptional\" GLOB 'b*')", stringOptional.glob("b*")) - } - - func test_match_buildsExpressionWithMatchOperator() { - AssertSQL("(\"string\" MATCH 'a*')", string.match("a*")) - AssertSQL("(\"stringOptional\" MATCH 'b*')", stringOptional.match("b*")) - } - - func test_regexp_buildsExpressionWithRegexpOperator() { - AssertSQL("(\"string\" REGEXP '^.+@.+\\.com$')", string.regexp("^.+@.+\\.com$")) - AssertSQL("(\"stringOptional\" REGEXP '^.+@.+\\.net$')", stringOptional.regexp("^.+@.+\\.net$")) - } - - func test_collate_buildsExpressionWithCollateOperator() { - AssertSQL("(\"string\" COLLATE BINARY)", string.collate(.binary)) - AssertSQL("(\"string\" COLLATE NOCASE)", string.collate(.nocase)) - AssertSQL("(\"string\" COLLATE RTRIM)", string.collate(.rtrim)) - AssertSQL("(\"string\" COLLATE \"CUSTOM\")", string.collate(.custom("CUSTOM"))) - - AssertSQL("(\"stringOptional\" COLLATE BINARY)", stringOptional.collate(.binary)) - AssertSQL("(\"stringOptional\" COLLATE NOCASE)", stringOptional.collate(.nocase)) - AssertSQL("(\"stringOptional\" COLLATE RTRIM)", stringOptional.collate(.rtrim)) - AssertSQL("(\"stringOptional\" COLLATE \"CUSTOM\")", stringOptional.collate(.custom("CUSTOM"))) - } - - func test_ltrim_wrapsStringWithLtrimFunction() { - AssertSQL("ltrim(\"string\")", string.ltrim()) - AssertSQL("ltrim(\"stringOptional\")", stringOptional.ltrim()) - - AssertSQL("ltrim(\"string\", ' ')", string.ltrim([" "])) - AssertSQL("ltrim(\"stringOptional\", ' ')", stringOptional.ltrim([" "])) - } - - func test_ltrim_wrapsStringWithRtrimFunction() { - AssertSQL("rtrim(\"string\")", string.rtrim()) - AssertSQL("rtrim(\"stringOptional\")", stringOptional.rtrim()) - - AssertSQL("rtrim(\"string\", ' ')", string.rtrim([" "])) - AssertSQL("rtrim(\"stringOptional\", ' ')", stringOptional.rtrim([" "])) - } - - func test_ltrim_wrapsStringWithTrimFunction() { - AssertSQL("trim(\"string\")", string.trim()) - AssertSQL("trim(\"stringOptional\")", stringOptional.trim()) - - AssertSQL("trim(\"string\", ' ')", string.trim([" "])) - AssertSQL("trim(\"stringOptional\", ' ')", stringOptional.trim([" "])) - } - - func test_replace_wrapsStringWithReplaceFunction() { - AssertSQL("replace(\"string\", '@example.com', '@example.net')", string.replace("@example.com", with: "@example.net")) - AssertSQL("replace(\"stringOptional\", '@example.net', '@example.com')", stringOptional.replace("@example.net", with: "@example.com")) - } - - func test_substring_wrapsStringWithSubstrFunction() { - AssertSQL("substr(\"string\", 1, 2)", string.substring(1, length: 2)) - AssertSQL("substr(\"stringOptional\", 2, 1)", stringOptional.substring(2, length: 1)) - } - - func test_subscriptWithRange_wrapsStringWithSubstrFunction() { - AssertSQL("substr(\"string\", 1, 2)", string[1..<3]) - AssertSQL("substr(\"stringOptional\", 2, 1)", stringOptional[2..<3]) - } - - func test_nilCoalescingOperator_wrapsOptionalsWithIfnullFunction() { - AssertSQL("ifnull(\"intOptional\", 1)", intOptional ?? 1) - // AssertSQL("ifnull(\"doubleOptional\", 1.0)", doubleOptional ?? 1) // rdar://problem/21677256 - XCTAssertEqual("ifnull(\"doubleOptional\", 1.0)", (doubleOptional ?? 1).asSQL()) - AssertSQL("ifnull(\"stringOptional\", 'literal')", stringOptional ?? "literal") - - AssertSQL("ifnull(\"intOptional\", \"int\")", intOptional ?? int) - AssertSQL("ifnull(\"doubleOptional\", \"double\")", doubleOptional ?? double) - AssertSQL("ifnull(\"stringOptional\", \"string\")", stringOptional ?? string) - - AssertSQL("ifnull(\"intOptional\", \"intOptional\")", intOptional ?? intOptional) - AssertSQL("ifnull(\"doubleOptional\", \"doubleOptional\")", doubleOptional ?? doubleOptional) - AssertSQL("ifnull(\"stringOptional\", \"stringOptional\")", stringOptional ?? stringOptional) - } - - func test_absoluteValue_wrapsNumberWithAbsFucntion() { - AssertSQL("abs(\"int\")", int.absoluteValue) - AssertSQL("abs(\"intOptional\")", intOptional.absoluteValue) - - AssertSQL("abs(\"double\")", double.absoluteValue) - AssertSQL("abs(\"doubleOptional\")", doubleOptional.absoluteValue) - } - - func test_contains_buildsExpressionWithInOperator() { - AssertSQL("(\"string\" IN ('hello', 'world'))", ["hello", "world"].contains(string)) - AssertSQL("(\"stringOptional\" IN ('hello', 'world'))", ["hello", "world"].contains(stringOptional)) - } - -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/CustomFunctionsTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/CustomFunctionsTests.swift deleted file mode 100755 index 919986b..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/CustomFunctionsTests.swift +++ /dev/null @@ -1,137 +0,0 @@ -import XCTest -import SQLite - -class CustomFunctionNoArgsTests : SQLiteTestCase { - typealias FunctionNoOptional = () -> Expression - typealias FunctionResultOptional = () -> Expression - - func testFunctionNoOptional() { - let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) { - return "a" - } - let result = try! db.prepare("SELECT test()").scalar() as! String - XCTAssertEqual("a", result) - } - - func testFunctionResultOptional() { - let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) { - return "a" - } - let result = try! db.prepare("SELECT test()").scalar() as! String? - XCTAssertEqual("a", result) - } -} - -class CustomFunctionWithOneArgTests : SQLiteTestCase { - typealias FunctionNoOptional = (Expression) -> Expression - typealias FunctionLeftOptional = (Expression) -> Expression - typealias FunctionResultOptional = (Expression) -> Expression - typealias FunctionLeftResultOptional = (Expression) -> Expression - - func testFunctionNoOptional() { - let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) { a in - return "b"+a - } - let result = try! db.prepare("SELECT test(?)").scalar("a") as! String - XCTAssertEqual("ba", result) - } - - func testFunctionLeftOptional() { - let _: FunctionLeftOptional = try! db.createFunction("test", deterministic: true) { a in - return "b"+a! - } - let result = try! db.prepare("SELECT test(?)").scalar("a") as! String - XCTAssertEqual("ba", result) - } - - func testFunctionResultOptional() { - let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) { a in - return "b"+a - } - let result = try! db.prepare("SELECT test(?)").scalar("a") as! String - XCTAssertEqual("ba", result) - } - - func testFunctionLeftResultOptional() { - let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { (a:String?) -> String? in - return "b"+a! - } - let result = try! db.prepare("SELECT test(?)").scalar("a") as! String - XCTAssertEqual("ba", result) - } -} - -class CustomFunctionWithTwoArgsTests : SQLiteTestCase { - typealias FunctionNoOptional = (Expression, Expression) -> Expression - typealias FunctionLeftOptional = (Expression, Expression) -> Expression - typealias FunctionRightOptional = (Expression, Expression) -> Expression - typealias FunctionResultOptional = (Expression, Expression) -> Expression - typealias FunctionLeftRightOptional = (Expression, Expression) -> Expression - typealias FunctionLeftResultOptional = (Expression, Expression) -> Expression - typealias FunctionRightResultOptional = (Expression, Expression) -> Expression - typealias FunctionLeftRightResultOptional = (Expression, Expression) -> Expression - - func testNoOptional() { - let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) { a, b in - return a+b - } - let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String - XCTAssertEqual("ab", result) - } - - func testLeftOptional() { - let _: FunctionLeftOptional = try! db.createFunction("test", deterministic: true) { a, b in - return a!+b - } - let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String - XCTAssertEqual("ab", result) - } - - func testRightOptional() { - let _: FunctionRightOptional = try! db.createFunction("test", deterministic: true) { a, b in - return a+b! - } - let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String - XCTAssertEqual("ab", result) - } - - func testResultOptional() { - let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) { a, b in - return a+b - } - let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String? - XCTAssertEqual("ab", result) - } - - func testFunctionLeftRightOptional() { - let _: FunctionLeftRightOptional = try! db.createFunction("test", deterministic: true) { a, b in - return a!+b! - } - let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String - XCTAssertEqual("ab", result) - } - - func testFunctionLeftResultOptional() { - let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { a, b in - return a!+b - } - let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String? - XCTAssertEqual("ab", result) - } - - func testFunctionRightResultOptional() { - let _: FunctionRightResultOptional = try! db.createFunction("test", deterministic: true) { a, b in - return a+b! - } - let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String? - XCTAssertEqual("ab", result) - } - - func testFunctionLeftRightResultOptional() { - let _: FunctionLeftRightResultOptional = try! db.createFunction("test", deterministic: true) { a, b in - return a!+b! - } - let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String? - XCTAssertEqual("ab", result) - } -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/DateAndTimeFunctionTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/DateAndTimeFunctionTests.swift deleted file mode 100755 index 628b591..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/DateAndTimeFunctionTests.swift +++ /dev/null @@ -1,66 +0,0 @@ -import XCTest -@testable import SQLite - -class DateAndTimeFunctionsTests : XCTestCase { - - func test_date() { - AssertSQL("date('now')", DateFunctions.date("now")) - AssertSQL("date('now', 'localtime')", DateFunctions.date("now", "localtime")) - } - - func test_time() { - AssertSQL("time('now')", DateFunctions.time("now")) - AssertSQL("time('now', 'localtime')", DateFunctions.time("now", "localtime")) - } - - func test_datetime() { - AssertSQL("datetime('now')", DateFunctions.datetime("now")) - AssertSQL("datetime('now', 'localtime')", DateFunctions.datetime("now", "localtime")) - } - - func test_julianday() { - AssertSQL("julianday('now')", DateFunctions.julianday("now")) - AssertSQL("julianday('now', 'localtime')", DateFunctions.julianday("now", "localtime")) - } - - func test_strftime() { - AssertSQL("strftime('%Y-%m-%d', 'now')", DateFunctions.strftime("%Y-%m-%d", "now")) - AssertSQL("strftime('%Y-%m-%d', 'now', 'localtime')", DateFunctions.strftime("%Y-%m-%d", "now", "localtime")) - } -} - -class DateExtensionTests : XCTestCase { - func test_time() { - AssertSQL("time('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).time) - } - - func test_date() { - AssertSQL("date('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).date) - } - - func test_datetime() { - AssertSQL("datetime('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).datetime) - } - - func test_julianday() { - AssertSQL("julianday('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).julianday) - } -} - -class DateExpressionTests : XCTestCase { - func test_date() { - AssertSQL("date(\"date\")", date.date) - } - - func test_time() { - AssertSQL("time(\"date\")", date.time) - } - - func test_datetime() { - AssertSQL("datetime(\"date\")", date.datetime) - } - - func test_julianday() { - AssertSQL("julianday(\"date\")", date.julianday) - } -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/ExpressionTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/ExpressionTests.swift deleted file mode 100755 index 036e10c..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/ExpressionTests.swift +++ /dev/null @@ -1,6 +0,0 @@ -import XCTest -import SQLite - -class ExpressionTests : XCTestCase { - -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/FTS4Tests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/FTS4Tests.swift deleted file mode 100755 index 79f0a8e..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/FTS4Tests.swift +++ /dev/null @@ -1,208 +0,0 @@ -import XCTest -import SQLite - -class FTS4Tests : XCTestCase { - - func test_create_onVirtualTable_withFTS4_compilesCreateVirtualTableExpression() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4()", - virtualTable.create(.FTS4()) - ) - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"string\")", - virtualTable.create(.FTS4(string)) - ) - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=simple)", - virtualTable.create(.FTS4(tokenize: .Simple)) - ) - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"string\", tokenize=porter)", - virtualTable.create(.FTS4([string], tokenize: .Porter)) - ) - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=0\")", - virtualTable.create(.FTS4(tokenize: .Unicode61(removeDiacritics: false))) - ) - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=1\" \"tokenchars=.\" \"separators=X\")", - virtualTable.create(.FTS4(tokenize: .Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"]))) - ) - } - - func test_match_onVirtualTableAsExpression_compilesMatchExpression() { - AssertSQL("(\"virtual_table\" MATCH 'string')", virtualTable.match("string") as Expression) - AssertSQL("(\"virtual_table\" MATCH \"string\")", virtualTable.match(string) as Expression) - AssertSQL("(\"virtual_table\" MATCH \"stringOptional\")", virtualTable.match(stringOptional) as Expression) - } - - func test_match_onVirtualTableAsQueryType_compilesMatchExpression() { - AssertSQL("SELECT * FROM \"virtual_table\" WHERE (\"virtual_table\" MATCH 'string')", virtualTable.match("string") as QueryType) - AssertSQL("SELECT * FROM \"virtual_table\" WHERE (\"virtual_table\" MATCH \"string\")", virtualTable.match(string) as QueryType) - AssertSQL("SELECT * FROM \"virtual_table\" WHERE (\"virtual_table\" MATCH \"stringOptional\")", virtualTable.match(stringOptional) as QueryType) - } - -} - -class FTS4ConfigTests : XCTestCase { - var config: FTS4Config! - - override func setUp() { - super.setUp() - config = FTS4Config() - } - - func test_empty_config() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4()", - sql(config)) - } - - func test_config_column() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"string\")", - sql(config.column(string))) - } - - func test_config_columns() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"string\", \"int\")", - sql(config.columns([string, int]))) - } - - func test_config_unindexed_column() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"string\", notindexed=\"string\")", - sql(config.column(string, [.unindexed]))) - } - - func test_external_content_view() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(content=\"view\")", - sql(config.externalContent(_view ))) - } - - func test_external_content_virtual_table() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(content=\"virtual_table\")", - sql(config.externalContent(virtualTable))) - } - - func test_tokenizer_simple() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=simple)", - sql(config.tokenizer(.Simple))) - } - - func test_tokenizer_porter() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=porter)", - sql(config.tokenizer(.Porter))) - } - - func test_tokenizer_unicode61() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61)", - sql(config.tokenizer(.Unicode61()))) - } - - func test_tokenizer_unicode61_with_options() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=1\" \"tokenchars=.\" \"separators=X\")", - sql(config.tokenizer(.Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"])))) - } - - func test_content_less() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(content=\"\")", - sql(config.contentless())) - } - - func test_config_matchinfo() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(matchinfo=\"fts3\")", - sql(config.matchInfo(.fts3))) - } - - func test_config_order_asc() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(order=\"asc\")", - sql(config.order(.asc))) - } - - func test_config_order_desc() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(order=\"desc\")", - sql(config.order(.desc))) - } - - func test_config_compress() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(compress=\"compress_foo\")", - sql(config.compress("compress_foo"))) - } - - func test_config_uncompress() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(uncompress=\"uncompress_foo\")", - sql(config.uncompress("uncompress_foo"))) - } - - func test_config_languageId() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(languageid=\"lid\")", - sql(config.languageId("lid"))) - } - - func test_config_all() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"int\", \"string\", \"date\", tokenize=porter, prefix=\"2,4\", content=\"table\", notindexed=\"string\", notindexed=\"date\", languageid=\"lid\", matchinfo=\"fts3\", order=\"desc\")", - sql(config - .tokenizer(.Porter) - .column(int) - .column(string, [.unindexed]) - .column(date, [.unindexed]) - .externalContent(table) - .matchInfo(.fts3) - .languageId("lid") - .order(.desc) - .prefix([2, 4])) - ) - } - - func sql(_ config: FTS4Config) -> String { - return virtualTable.create(.FTS4(config)) - } -} - -class FTS4IntegrationTests : SQLiteTestCase { -#if !SQLITE_SWIFT_STANDALONE && !SQLITE_SWIFT_SQLCIPHER - func test_registerTokenizer_registersTokenizer() { - let emails = VirtualTable("emails") - let subject = Expression("subject") - let body = Expression("body") - - let locale = CFLocaleCopyCurrent() - let tokenizerName = "tokenizer" - let tokenizer = CFStringTokenizerCreate(nil, "" as CFString, CFRangeMake(0, 0), UInt(kCFStringTokenizerUnitWord), locale) - try! db.registerTokenizer(tokenizerName) { string in - CFStringTokenizerSetString(tokenizer, string as CFString, CFRangeMake(0, CFStringGetLength(string as CFString))) - if CFStringTokenizerAdvanceToNextToken(tokenizer).isEmpty { - return nil - } - let range = CFStringTokenizerGetCurrentTokenRange(tokenizer) - let input = CFStringCreateWithSubstring(kCFAllocatorDefault, string as CFString, range)! - let token = CFStringCreateMutableCopy(nil, range.length, input)! - CFStringLowercase(token, locale) - CFStringTransform(token, nil, kCFStringTransformStripDiacritics, false) - return (token as String, string.range(of: input as String)!) - } - - try! db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName)))) - AssertSQL("CREATE VIRTUAL TABLE \"emails\" USING fts4(\"subject\", \"body\", tokenize=\"SQLite.swift\" \"tokenizer\")") - - try! _ = db.run(emails.insert(subject <- "Aún más cáfe!")) - XCTAssertEqual(1, try! db.scalar(emails.filter(emails.match("aun")).count)) - } -#endif -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/FTS5Tests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/FTS5Tests.swift deleted file mode 100755 index 63d8dc4..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/FTS5Tests.swift +++ /dev/null @@ -1,124 +0,0 @@ -import XCTest -import SQLite - -class FTS5Tests: XCTestCase { - var config: FTS5Config! - - override func setUp() { - super.setUp() - config = FTS5Config() - } - - func test_empty_config() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5()", - sql(config)) - } - - func test_config_column() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"string\")", - sql(config.column(string))) - } - - func test_config_columns() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"string\", \"int\")", - sql(config.columns([string, int]))) - } - - func test_config_unindexed_column() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"string\" UNINDEXED)", - sql(config.column(string, [.unindexed]))) - } - - func test_external_content_table() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content=\"table\")", - sql(config.externalContent(table))) - } - - func test_external_content_view() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content=\"view\")", - sql(config.externalContent(_view))) - } - - func test_external_content_virtual_table() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content=\"virtual_table\")", - sql(config.externalContent(virtualTable))) - } - - func test_content_less() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content=\"\")", - sql(config.contentless())) - } - - func test_content_rowid() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content_rowid=\"string\")", - sql(config.contentRowId(string))) - } - - func test_tokenizer_porter() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=porter)", - sql(config.tokenizer(.Porter))) - } - - func test_tokenizer_unicode61() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=unicode61)", - sql(config.tokenizer(.Unicode61()))) - } - - func test_tokenizer_unicode61_with_options() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=unicode61 \"removeDiacritics=1\" \"tokenchars=.\" \"separators=X\")", - sql(config.tokenizer(.Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"])))) - } - - func test_column_size() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(columnsize=1)", - sql(config.columnSize(1))) - } - - func test_detail_full() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(detail=\"full\")", - sql(config.detail(.full))) - } - - func test_detail_column() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(detail=\"column\")", - sql(config.detail(.column))) - } - - func test_detail_none() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(detail=\"none\")", - sql(config.detail(.none))) - } - - func test_fts5_config_all() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"int\", \"string\" UNINDEXED, \"date\" UNINDEXED, tokenize=porter, prefix=\"2,4\", content=\"table\")", - sql(config - .tokenizer(.Porter) - .column(int) - .column(string, [.unindexed]) - .column(date, [.unindexed]) - .externalContent(table) - .prefix([2, 4])) - ) - } - - func sql(_ config: FTS5Config) -> String { - return virtualTable.create(.FTS5(config)) - } -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/Fixtures.swift b/ios/libs/Sqlite/Tests/SQLiteTests/Fixtures.swift deleted file mode 100755 index d068313..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/Fixtures.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -func fixture(_ name: String, withExtension: String?) -> String { - let testBundle = Bundle(for: SQLiteTestCase.self) - return testBundle.url( - forResource: name, - withExtension: withExtension)!.path -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/FoundationTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/FoundationTests.swift deleted file mode 100755 index dd80afc..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/FoundationTests.swift +++ /dev/null @@ -1,16 +0,0 @@ -import XCTest -import SQLite - -class FoundationTests : XCTestCase { - func testDataFromBlob() { - let data = Data([1, 2, 3]) - let blob = data.datatypeValue - XCTAssertEqual([1, 2, 3], blob.bytes) - } - - func testBlobToData() { - let blob = Blob(bytes: [1, 2, 3]) - let data = Data.fromDatatypeValue(blob) - XCTAssertEqual(Data([1, 2, 3]), data) - } -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/Info.plist b/ios/libs/Sqlite/Tests/SQLiteTests/Info.plist deleted file mode 100755 index ba72822..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/OperatorsTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/OperatorsTests.swift deleted file mode 100755 index 948eb0a..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/OperatorsTests.swift +++ /dev/null @@ -1,342 +0,0 @@ -import XCTest -import SQLite - -class OperatorsTests : XCTestCase { - - func test_stringExpressionPlusStringExpression_buildsConcatenatingStringExpression() { - AssertSQL("(\"string\" || \"string\")", string + string) - AssertSQL("(\"string\" || \"stringOptional\")", string + stringOptional) - AssertSQL("(\"stringOptional\" || \"string\")", stringOptional + string) - AssertSQL("(\"stringOptional\" || \"stringOptional\")", stringOptional + stringOptional) - AssertSQL("(\"string\" || 'literal')", string + "literal") - AssertSQL("(\"stringOptional\" || 'literal')", stringOptional + "literal") - AssertSQL("('literal' || \"string\")", "literal" + string) - AssertSQL("('literal' || \"stringOptional\")", "literal" + stringOptional) - } - - func test_numberExpression_plusNumberExpression_buildsAdditiveNumberExpression() { - AssertSQL("(\"int\" + \"int\")", int + int) - AssertSQL("(\"int\" + \"intOptional\")", int + intOptional) - AssertSQL("(\"intOptional\" + \"int\")", intOptional + int) - AssertSQL("(\"intOptional\" + \"intOptional\")", intOptional + intOptional) - AssertSQL("(\"int\" + 1)", int + 1) - AssertSQL("(\"intOptional\" + 1)", intOptional + 1) - AssertSQL("(1 + \"int\")", 1 + int) - AssertSQL("(1 + \"intOptional\")", 1 + intOptional) - - AssertSQL("(\"double\" + \"double\")", double + double) - AssertSQL("(\"double\" + \"doubleOptional\")", double + doubleOptional) - AssertSQL("(\"doubleOptional\" + \"double\")", doubleOptional + double) - AssertSQL("(\"doubleOptional\" + \"doubleOptional\")", doubleOptional + doubleOptional) - AssertSQL("(\"double\" + 1.0)", double + 1) - AssertSQL("(\"doubleOptional\" + 1.0)", doubleOptional + 1) - AssertSQL("(1.0 + \"double\")", 1 + double) - AssertSQL("(1.0 + \"doubleOptional\")", 1 + doubleOptional) - } - - func test_numberExpression_minusNumberExpression_buildsSubtractiveNumberExpression() { - AssertSQL("(\"int\" - \"int\")", int - int) - AssertSQL("(\"int\" - \"intOptional\")", int - intOptional) - AssertSQL("(\"intOptional\" - \"int\")", intOptional - int) - AssertSQL("(\"intOptional\" - \"intOptional\")", intOptional - intOptional) - AssertSQL("(\"int\" - 1)", int - 1) - AssertSQL("(\"intOptional\" - 1)", intOptional - 1) - AssertSQL("(1 - \"int\")", 1 - int) - AssertSQL("(1 - \"intOptional\")", 1 - intOptional) - - AssertSQL("(\"double\" - \"double\")", double - double) - AssertSQL("(\"double\" - \"doubleOptional\")", double - doubleOptional) - AssertSQL("(\"doubleOptional\" - \"double\")", doubleOptional - double) - AssertSQL("(\"doubleOptional\" - \"doubleOptional\")", doubleOptional - doubleOptional) - AssertSQL("(\"double\" - 1.0)", double - 1) - AssertSQL("(\"doubleOptional\" - 1.0)", doubleOptional - 1) - AssertSQL("(1.0 - \"double\")", 1 - double) - AssertSQL("(1.0 - \"doubleOptional\")", 1 - doubleOptional) - } - - func test_numberExpression_timesNumberExpression_buildsMultiplicativeNumberExpression() { - AssertSQL("(\"int\" * \"int\")", int * int) - AssertSQL("(\"int\" * \"intOptional\")", int * intOptional) - AssertSQL("(\"intOptional\" * \"int\")", intOptional * int) - AssertSQL("(\"intOptional\" * \"intOptional\")", intOptional * intOptional) - AssertSQL("(\"int\" * 1)", int * 1) - AssertSQL("(\"intOptional\" * 1)", intOptional * 1) - AssertSQL("(1 * \"int\")", 1 * int) - AssertSQL("(1 * \"intOptional\")", 1 * intOptional) - - AssertSQL("(\"double\" * \"double\")", double * double) - AssertSQL("(\"double\" * \"doubleOptional\")", double * doubleOptional) - AssertSQL("(\"doubleOptional\" * \"double\")", doubleOptional * double) - AssertSQL("(\"doubleOptional\" * \"doubleOptional\")", doubleOptional * doubleOptional) - AssertSQL("(\"double\" * 1.0)", double * 1) - AssertSQL("(\"doubleOptional\" * 1.0)", doubleOptional * 1) - AssertSQL("(1.0 * \"double\")", 1 * double) - AssertSQL("(1.0 * \"doubleOptional\")", 1 * doubleOptional) - } - - func test_numberExpression_dividedByNumberExpression_buildsDivisiveNumberExpression() { - AssertSQL("(\"int\" / \"int\")", int / int) - AssertSQL("(\"int\" / \"intOptional\")", int / intOptional) - AssertSQL("(\"intOptional\" / \"int\")", intOptional / int) - AssertSQL("(\"intOptional\" / \"intOptional\")", intOptional / intOptional) - AssertSQL("(\"int\" / 1)", int / 1) - AssertSQL("(\"intOptional\" / 1)", intOptional / 1) - AssertSQL("(1 / \"int\")", 1 / int) - AssertSQL("(1 / \"intOptional\")", 1 / intOptional) - - AssertSQL("(\"double\" / \"double\")", double / double) - AssertSQL("(\"double\" / \"doubleOptional\")", double / doubleOptional) - AssertSQL("(\"doubleOptional\" / \"double\")", doubleOptional / double) - AssertSQL("(\"doubleOptional\" / \"doubleOptional\")", doubleOptional / doubleOptional) - AssertSQL("(\"double\" / 1.0)", double / 1) - AssertSQL("(\"doubleOptional\" / 1.0)", doubleOptional / 1) - AssertSQL("(1.0 / \"double\")", 1 / double) - AssertSQL("(1.0 / \"doubleOptional\")", 1 / doubleOptional) - } - - func test_numberExpression_prefixedWithMinus_buildsInvertedNumberExpression() { - AssertSQL("-(\"int\")", -int) - AssertSQL("-(\"intOptional\")", -intOptional) - - AssertSQL("-(\"double\")", -double) - AssertSQL("-(\"doubleOptional\")", -doubleOptional) - } - - func test_integerExpression_moduloIntegerExpression_buildsModuloIntegerExpression() { - AssertSQL("(\"int\" % \"int\")", int % int) - AssertSQL("(\"int\" % \"intOptional\")", int % intOptional) - AssertSQL("(\"intOptional\" % \"int\")", intOptional % int) - AssertSQL("(\"intOptional\" % \"intOptional\")", intOptional % intOptional) - AssertSQL("(\"int\" % 1)", int % 1) - AssertSQL("(\"intOptional\" % 1)", intOptional % 1) - AssertSQL("(1 % \"int\")", 1 % int) - AssertSQL("(1 % \"intOptional\")", 1 % intOptional) - } - - func test_integerExpression_bitShiftLeftIntegerExpression_buildsLeftShiftedIntegerExpression() { - AssertSQL("(\"int\" << \"int\")", int << int) - AssertSQL("(\"int\" << \"intOptional\")", int << intOptional) - AssertSQL("(\"intOptional\" << \"int\")", intOptional << int) - AssertSQL("(\"intOptional\" << \"intOptional\")", intOptional << intOptional) - AssertSQL("(\"int\" << 1)", int << 1) - AssertSQL("(\"intOptional\" << 1)", intOptional << 1) - AssertSQL("(1 << \"int\")", 1 << int) - AssertSQL("(1 << \"intOptional\")", 1 << intOptional) - } - - func test_integerExpression_bitShiftRightIntegerExpression_buildsRightShiftedIntegerExpression() { - AssertSQL("(\"int\" >> \"int\")", int >> int) - AssertSQL("(\"int\" >> \"intOptional\")", int >> intOptional) - AssertSQL("(\"intOptional\" >> \"int\")", intOptional >> int) - AssertSQL("(\"intOptional\" >> \"intOptional\")", intOptional >> intOptional) - AssertSQL("(\"int\" >> 1)", int >> 1) - AssertSQL("(\"intOptional\" >> 1)", intOptional >> 1) - AssertSQL("(1 >> \"int\")", 1 >> int) - AssertSQL("(1 >> \"intOptional\")", 1 >> intOptional) - } - - func test_integerExpression_bitwiseAndIntegerExpression_buildsAndedIntegerExpression() { - AssertSQL("(\"int\" & \"int\")", int & int) - AssertSQL("(\"int\" & \"intOptional\")", int & intOptional) - AssertSQL("(\"intOptional\" & \"int\")", intOptional & int) - AssertSQL("(\"intOptional\" & \"intOptional\")", intOptional & intOptional) - AssertSQL("(\"int\" & 1)", int & 1) - AssertSQL("(\"intOptional\" & 1)", intOptional & 1) - AssertSQL("(1 & \"int\")", 1 & int) - AssertSQL("(1 & \"intOptional\")", 1 & intOptional) - } - - func test_integerExpression_bitwiseOrIntegerExpression_buildsOredIntegerExpression() { - AssertSQL("(\"int\" | \"int\")", int | int) - AssertSQL("(\"int\" | \"intOptional\")", int | intOptional) - AssertSQL("(\"intOptional\" | \"int\")", intOptional | int) - AssertSQL("(\"intOptional\" | \"intOptional\")", intOptional | intOptional) - AssertSQL("(\"int\" | 1)", int | 1) - AssertSQL("(\"intOptional\" | 1)", intOptional | 1) - AssertSQL("(1 | \"int\")", 1 | int) - AssertSQL("(1 | \"intOptional\")", 1 | intOptional) - } - - func test_integerExpression_bitwiseExclusiveOrIntegerExpression_buildsOredIntegerExpression() { - AssertSQL("(~((\"int\" & \"int\")) & (\"int\" | \"int\"))", int ^ int) - AssertSQL("(~((\"int\" & \"intOptional\")) & (\"int\" | \"intOptional\"))", int ^ intOptional) - AssertSQL("(~((\"intOptional\" & \"int\")) & (\"intOptional\" | \"int\"))", intOptional ^ int) - AssertSQL("(~((\"intOptional\" & \"intOptional\")) & (\"intOptional\" | \"intOptional\"))", intOptional ^ intOptional) - AssertSQL("(~((\"int\" & 1)) & (\"int\" | 1))", int ^ 1) - AssertSQL("(~((\"intOptional\" & 1)) & (\"intOptional\" | 1))", intOptional ^ 1) - AssertSQL("(~((1 & \"int\")) & (1 | \"int\"))", 1 ^ int) - AssertSQL("(~((1 & \"intOptional\")) & (1 | \"intOptional\"))", 1 ^ intOptional) - } - - func test_bitwiseNot_integerExpression_buildsComplementIntegerExpression() { - AssertSQL("~(\"int\")", ~int) - AssertSQL("~(\"intOptional\")", ~intOptional) - } - - func test_equalityOperator_withEquatableExpressions_buildsBooleanExpression() { - AssertSQL("(\"bool\" = \"bool\")", bool == bool) - AssertSQL("(\"bool\" = \"boolOptional\")", bool == boolOptional) - AssertSQL("(\"boolOptional\" = \"bool\")", boolOptional == bool) - AssertSQL("(\"boolOptional\" = \"boolOptional\")", boolOptional == boolOptional) - AssertSQL("(\"bool\" = 1)", bool == true) - AssertSQL("(\"boolOptional\" = 1)", boolOptional == true) - AssertSQL("(1 = \"bool\")", true == bool) - AssertSQL("(1 = \"boolOptional\")", true == boolOptional) - - AssertSQL("(\"boolOptional\" IS NULL)", boolOptional == nil) - AssertSQL("(NULL IS \"boolOptional\")", nil == boolOptional) - } - - func test_inequalityOperator_withEquatableExpressions_buildsBooleanExpression() { - AssertSQL("(\"bool\" != \"bool\")", bool != bool) - AssertSQL("(\"bool\" != \"boolOptional\")", bool != boolOptional) - AssertSQL("(\"boolOptional\" != \"bool\")", boolOptional != bool) - AssertSQL("(\"boolOptional\" != \"boolOptional\")", boolOptional != boolOptional) - AssertSQL("(\"bool\" != 1)", bool != true) - AssertSQL("(\"boolOptional\" != 1)", boolOptional != true) - AssertSQL("(1 != \"bool\")", true != bool) - AssertSQL("(1 != \"boolOptional\")", true != boolOptional) - - AssertSQL("(\"boolOptional\" IS NOT NULL)", boolOptional != nil) - AssertSQL("(NULL IS NOT \"boolOptional\")", nil != boolOptional) - } - - func test_greaterThanOperator_withComparableExpressions_buildsBooleanExpression() { - AssertSQL("(\"bool\" > \"bool\")", bool > bool) - AssertSQL("(\"bool\" > \"boolOptional\")", bool > boolOptional) - AssertSQL("(\"boolOptional\" > \"bool\")", boolOptional > bool) - AssertSQL("(\"boolOptional\" > \"boolOptional\")", boolOptional > boolOptional) - AssertSQL("(\"bool\" > 1)", bool > true) - AssertSQL("(\"boolOptional\" > 1)", boolOptional > true) - AssertSQL("(1 > \"bool\")", true > bool) - AssertSQL("(1 > \"boolOptional\")", true > boolOptional) - } - - func test_greaterThanOrEqualToOperator_withComparableExpressions_buildsBooleanExpression() { - AssertSQL("(\"bool\" >= \"bool\")", bool >= bool) - AssertSQL("(\"bool\" >= \"boolOptional\")", bool >= boolOptional) - AssertSQL("(\"boolOptional\" >= \"bool\")", boolOptional >= bool) - AssertSQL("(\"boolOptional\" >= \"boolOptional\")", boolOptional >= boolOptional) - AssertSQL("(\"bool\" >= 1)", bool >= true) - AssertSQL("(\"boolOptional\" >= 1)", boolOptional >= true) - AssertSQL("(1 >= \"bool\")", true >= bool) - AssertSQL("(1 >= \"boolOptional\")", true >= boolOptional) - } - - func test_lessThanOperator_withComparableExpressions_buildsBooleanExpression() { - AssertSQL("(\"bool\" < \"bool\")", bool < bool) - AssertSQL("(\"bool\" < \"boolOptional\")", bool < boolOptional) - AssertSQL("(\"boolOptional\" < \"bool\")", boolOptional < bool) - AssertSQL("(\"boolOptional\" < \"boolOptional\")", boolOptional < boolOptional) - AssertSQL("(\"bool\" < 1)", bool < true) - AssertSQL("(\"boolOptional\" < 1)", boolOptional < true) - AssertSQL("(1 < \"bool\")", true < bool) - AssertSQL("(1 < \"boolOptional\")", true < boolOptional) - } - - func test_lessThanOrEqualToOperator_withComparableExpressions_buildsBooleanExpression() { - AssertSQL("(\"bool\" <= \"bool\")", bool <= bool) - AssertSQL("(\"bool\" <= \"boolOptional\")", bool <= boolOptional) - AssertSQL("(\"boolOptional\" <= \"bool\")", boolOptional <= bool) - AssertSQL("(\"boolOptional\" <= \"boolOptional\")", boolOptional <= boolOptional) - AssertSQL("(\"bool\" <= 1)", bool <= true) - AssertSQL("(\"boolOptional\" <= 1)", boolOptional <= true) - AssertSQL("(1 <= \"bool\")", true <= bool) - AssertSQL("(1 <= \"boolOptional\")", true <= boolOptional) - } - - func test_patternMatchingOperator_withComparableCountableClosedRange_buildsBetweenBooleanExpression() { - AssertSQL("\"int\" BETWEEN 0 AND 5", 0...5 ~= int) - AssertSQL("\"intOptional\" BETWEEN 0 AND 5", 0...5 ~= intOptional) - } - - func test_patternMatchingOperator_withComparableClosedRange_buildsBetweenBooleanExpression() { - AssertSQL("\"double\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= double) - AssertSQL("\"doubleOptional\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= doubleOptional) - } - - func test_patternMatchingOperator_withComparableRange_buildsBooleanExpression() { - AssertSQL("\"double\" >= 1.2 AND \"double\" < 4.5", 1.2..<4.5 ~= double) - AssertSQL("\"doubleOptional\" >= 1.2 AND \"doubleOptional\" < 4.5", 1.2..<4.5 ~= doubleOptional) - } - - func test_patternMatchingOperator_withComparablePartialRangeThrough_buildsBooleanExpression() { - AssertSQL("\"double\" <= 4.5", ...4.5 ~= double) - AssertSQL("\"doubleOptional\" <= 4.5", ...4.5 ~= doubleOptional) - } - - func test_patternMatchingOperator_withComparablePartialRangeUpTo_buildsBooleanExpression() { - AssertSQL("\"double\" < 4.5", ..<4.5 ~= double) - AssertSQL("\"doubleOptional\" < 4.5", ..<4.5 ~= doubleOptional) - } - - func test_patternMatchingOperator_withComparablePartialRangeFrom_buildsBooleanExpression() { - AssertSQL("\"double\" >= 4.5", 4.5... ~= double) - AssertSQL("\"doubleOptional\" >= 4.5", 4.5... ~= doubleOptional) - } - - func test_patternMatchingOperator_withComparableClosedRangeString_buildsBetweenBooleanExpression() { - AssertSQL("\"string\" BETWEEN 'a' AND 'b'", "a"..."b" ~= string) - AssertSQL("\"stringOptional\" BETWEEN 'a' AND 'b'", "a"..."b" ~= stringOptional) - } - - func test_doubleAndOperator_withBooleanExpressions_buildsCompoundExpression() { - AssertSQL("(\"bool\" AND \"bool\")", bool && bool) - AssertSQL("(\"bool\" AND \"boolOptional\")", bool && boolOptional) - AssertSQL("(\"boolOptional\" AND \"bool\")", boolOptional && bool) - AssertSQL("(\"boolOptional\" AND \"boolOptional\")", boolOptional && boolOptional) - AssertSQL("(\"bool\" AND 1)", bool && true) - AssertSQL("(\"boolOptional\" AND 1)", boolOptional && true) - AssertSQL("(1 AND \"bool\")", true && bool) - AssertSQL("(1 AND \"boolOptional\")", true && boolOptional) - } - - func test_doubleOrOperator_withBooleanExpressions_buildsCompoundExpression() { - AssertSQL("(\"bool\" OR \"bool\")", bool || bool) - AssertSQL("(\"bool\" OR \"boolOptional\")", bool || boolOptional) - AssertSQL("(\"boolOptional\" OR \"bool\")", boolOptional || bool) - AssertSQL("(\"boolOptional\" OR \"boolOptional\")", boolOptional || boolOptional) - AssertSQL("(\"bool\" OR 1)", bool || true) - AssertSQL("(\"boolOptional\" OR 1)", boolOptional || true) - AssertSQL("(1 OR \"bool\")", true || bool) - AssertSQL("(1 OR \"boolOptional\")", true || boolOptional) - } - - func test_unaryNotOperator_withBooleanExpressions_buildsNotExpression() { - AssertSQL("NOT (\"bool\")", !bool) - AssertSQL("NOT (\"boolOptional\")", !boolOptional) - } - - func test_precedencePreserved() { - let n = Expression(value: 1) - AssertSQL("(((1 = 1) AND (1 = 1)) OR (1 = 1))", (n == n && n == n) || n == n) - AssertSQL("((1 = 1) AND ((1 = 1) OR (1 = 1)))", n == n && (n == n || n == n)) - } - - func test_dateExpressionLessGreater() { - let begin = Date(timeIntervalSince1970: 0) - AssertSQL("(\"date\" < '1970-01-01T00:00:00.000')", date < begin) - AssertSQL("(\"date\" > '1970-01-01T00:00:00.000')", date > begin) - AssertSQL("(\"date\" >= '1970-01-01T00:00:00.000')", date >= begin) - AssertSQL("(\"date\" <= '1970-01-01T00:00:00.000')", date <= begin) - } - - func test_dateExpressionRange() { - let begin = Date(timeIntervalSince1970: 0) - let end = Date(timeIntervalSince1970: 5000) - AssertSQL( - "\"date\" >= '1970-01-01T00:00:00.000' AND \"date\" < '1970-01-01T01:23:20.000'", - (begin..("id") - let email = Expression("email") - let age = Expression("age") - let admin = Expression("admin") - let optionalAdmin = Expression("admin") - - let posts = Table("posts") - let userId = Expression("user_id") - let categoryId = Expression("category_id") - let published = Expression("published") - - let categories = Table("categories") - let tag = Expression("tag") - - func test_select_withExpression_compilesSelectClause() { - AssertSQL("SELECT \"email\" FROM \"users\"", users.select(email)) - } - - func test_select_withStarExpression_compilesSelectClause() { - AssertSQL("SELECT * FROM \"users\"", users.select(*)) - } - - func test_select_withNamespacedStarExpression_compilesSelectClause() { - AssertSQL("SELECT \"users\".* FROM \"users\"", users.select(users[*])) - } - - func test_select_withVariadicExpressions_compilesSelectClause() { - AssertSQL("SELECT \"email\", count(*) FROM \"users\"", users.select(email, count(*))) - } - - func test_select_withExpressions_compilesSelectClause() { - AssertSQL("SELECT \"email\", count(*) FROM \"users\"", users.select([email, count(*)])) - } - - func test_selectDistinct_withExpression_compilesSelectClause() { - AssertSQL("SELECT DISTINCT \"age\" FROM \"users\"", users.select(distinct: age)) - } - - func test_selectDistinct_withExpressions_compilesSelectClause() { - AssertSQL("SELECT DISTINCT \"age\", \"admin\" FROM \"users\"", users.select(distinct: [age, admin])) - } - - func test_selectDistinct_withStar_compilesSelectClause() { - AssertSQL("SELECT DISTINCT * FROM \"users\"", users.select(distinct: *)) - } - - func test_join_compilesJoinClause() { - AssertSQL( - "SELECT * FROM \"users\" INNER JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\")", - users.join(posts, on: posts[userId] == users[id]) - ) - } - - func test_join_withExplicitType_compilesJoinClauseWithType() { - AssertSQL( - "SELECT * FROM \"users\" LEFT OUTER JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\")", - users.join(.leftOuter, posts, on: posts[userId] == users[id]) - ) - - AssertSQL( - "SELECT * FROM \"users\" CROSS JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\")", - users.join(.cross, posts, on: posts[userId] == users[id]) - ) - } - - func test_join_withTableCondition_compilesJoinClauseWithTableCondition() { - AssertSQL( - "SELECT * FROM \"users\" INNER JOIN \"posts\" ON ((\"posts\".\"user_id\" = \"users\".\"id\") AND \"published\")", - users.join(posts.filter(published), on: posts[userId] == users[id]) - ) - } - - func test_join_whenChained_compilesAggregateJoinClause() { - AssertSQL( - "SELECT * FROM \"users\" " + - "INNER JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\") " + - "INNER JOIN \"categories\" ON (\"categories\".\"id\" = \"posts\".\"category_id\")", - users.join(posts, on: posts[userId] == users[id]).join(categories, on: categories[id] == posts[categoryId]) - ) - } - - func test_filter_compilesWhereClause() { - AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.filter(admin == true)) - } - - func test_filter_compilesWhereClause_false() { - AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.filter(admin == false)) - } - - func test_filter_compilesWhereClause_optional() { - AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.filter(optionalAdmin == true)) - } - - func test_filter_compilesWhereClause_optional_false() { - AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.filter(optionalAdmin == false)) - } - - func test_where_compilesWhereClause() { - AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.where(admin == true)) - } - - func test_where_compilesWhereClause_false() { - AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.where(admin == false)) - } - - func test_where_compilesWhereClause_optional() { - AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.where(optionalAdmin == true)) - } - - func test_where_compilesWhereClause_optional_false() { - AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.where(optionalAdmin == false)) - } - - func test_filter_whenChained_compilesAggregateWhereClause() { - AssertSQL( - "SELECT * FROM \"users\" WHERE ((\"age\" >= 35) AND \"admin\")", - users.filter(age >= 35).filter(admin) - ) - } - - func test_group_withSingleExpressionName_compilesGroupClause() { - AssertSQL("SELECT * FROM \"users\" GROUP BY \"age\"", - users.group(age)) - } - - func test_group_withVariadicExpressionNames_compilesGroupClause() { - AssertSQL("SELECT * FROM \"users\" GROUP BY \"age\", \"admin\"", users.group(age, admin)) - } - - func test_group_withExpressionNameAndHavingBindings_compilesGroupClause() { - AssertSQL("SELECT * FROM \"users\" GROUP BY \"age\" HAVING \"admin\"", users.group(age, having: admin)) - AssertSQL("SELECT * FROM \"users\" GROUP BY \"age\" HAVING (\"age\" >= 30)", users.group(age, having: age >= 30)) - } - - func test_group_withExpressionNamesAndHavingBindings_compilesGroupClause() { - AssertSQL( - "SELECT * FROM \"users\" GROUP BY \"age\", \"admin\" HAVING \"admin\"", - users.group([age, admin], having: admin) - ) - AssertSQL( - "SELECT * FROM \"users\" GROUP BY \"age\", \"admin\" HAVING (\"age\" >= 30)", - users.group([age, admin], having: age >= 30) - ) - } - - func test_order_withSingleExpressionName_compilesOrderClause() { - AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\"", users.order(age)) - } - - func test_order_withVariadicExpressionNames_compilesOrderClause() { - AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\", \"email\"", users.order(age, email)) - } - - func test_order_withArrayExpressionNames_compilesOrderClause() { - AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\", \"email\"", users.order([age, email])) - } - - func test_order_withExpressionAndSortDirection_compilesOrderClause() { -// AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\" DESC, \"email\" ASC", users.order(age.desc, email.asc)) - } - - func test_order_whenChained_resetsOrderClause() { - AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\"", users.order(email).order(age)) - } - - func test_reverse_withoutOrder_ordersByRowIdDescending() { -// AssertSQL("SELECT * FROM \"users\" ORDER BY \"ROWID\" DESC", users.reverse()) - } - - func test_reverse_withOrder_reversesOrder() { -// AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\" DESC, \"email\" ASC", users.order(age, email.desc).reverse()) - } - - func test_limit_compilesLimitClause() { - AssertSQL("SELECT * FROM \"users\" LIMIT 5", users.limit(5)) - } - - func test_limit_withOffset_compilesOffsetClause() { - AssertSQL("SELECT * FROM \"users\" LIMIT 5 OFFSET 5", users.limit(5, offset: 5)) - } - - func test_limit_whenChained_overridesLimit() { - let query = users.limit(5) - - AssertSQL("SELECT * FROM \"users\" LIMIT 10", query.limit(10)) - AssertSQL("SELECT * FROM \"users\"", query.limit(nil)) - } - - func test_limit_whenChained_withOffset_overridesOffset() { - let query = users.limit(5, offset: 5) - - AssertSQL("SELECT * FROM \"users\" LIMIT 10 OFFSET 20", query.limit(10, offset: 20)) - AssertSQL("SELECT * FROM \"users\"", query.limit(nil)) - } - - func test_alias_aliasesTable() { - let managerId = Expression("manager_id") - - let managers = users.alias("managers") - - AssertSQL( - "SELECT * FROM \"users\" " + - "INNER JOIN \"users\" AS \"managers\" ON (\"managers\".\"id\" = \"users\".\"manager_id\")", - users.join(managers, on: managers[id] == users[managerId]) - ) - } - - func test_insert_compilesInsertExpression() { - AssertSQL( - "INSERT INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30)", - users.insert(email <- "alice@example.com", age <- 30) - ) - } - - func test_insert_withOnConflict_compilesInsertOrOnConflictExpression() { - AssertSQL( - "INSERT OR REPLACE INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30)", - users.insert(or: .replace, email <- "alice@example.com", age <- 30) - ) - } - - func test_insert_compilesInsertExpressionWithDefaultValues() { - AssertSQL("INSERT INTO \"users\" DEFAULT VALUES", users.insert()) - } - - func test_insert_withQuery_compilesInsertExpressionWithSelectStatement() { - let emails = Table("emails") - - AssertSQL( - "INSERT INTO \"emails\" SELECT \"email\" FROM \"users\" WHERE \"admin\"", - emails.insert(users.select(email).filter(admin)) - ) - } - - func test_insert_encodable() throws { - let emails = Table("emails") - let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil) - let insert = try emails.insert(value) - AssertSQL( - "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\") VALUES (1, '2', 1, 3.0, 4.0)", - insert - ) - } - - func test_insert_encodable_with_nested_encodable() throws { - let emails = Table("emails") - let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil) - let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: "optional", sub: value1) - let insert = try emails.insert(value) - let encodedJSON = try JSONEncoder().encode(value1) - let encodedJSONString = String(data: encodedJSON, encoding: .utf8)! - AssertSQL( - "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"optional\", \"sub\") VALUES (1, '2', 1, 3.0, 4.0, 'optional', '\(encodedJSONString)')", - insert - ) - } - - func test_update_compilesUpdateExpression() { - AssertSQL( - "UPDATE \"users\" SET \"age\" = 30, \"admin\" = 1 WHERE (\"id\" = 1)", - users.filter(id == 1).update(age <- 30, admin <- true) - ) - } - - func test_update_compilesUpdateLimitOrderExpression() { - AssertSQL( - "UPDATE \"users\" SET \"age\" = 30 ORDER BY \"id\" LIMIT 1", - users.order(id).limit(1).update(age <- 30) - ) - } - - func test_update_encodable() throws { - let emails = Table("emails") - let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil) - let update = try emails.update(value) - AssertSQL( - "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0", - update - ) - } - - func test_update_encodable_with_nested_encodable() throws { - let emails = Table("emails") - let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil) - let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: value1) - let update = try emails.update(value) - let encodedJSON = try JSONEncoder().encode(value1) - let encodedJSONString = String(data: encodedJSON, encoding: .utf8)! - AssertSQL( - "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"sub\" = '\(encodedJSONString)'", - update - ) - } - - func test_delete_compilesDeleteExpression() { - AssertSQL( - "DELETE FROM \"users\" WHERE (\"id\" = 1)", - users.filter(id == 1).delete() - ) - } - - func test_delete_compilesDeleteLimitOrderExpression() { - AssertSQL( - "DELETE FROM \"users\" ORDER BY \"id\" LIMIT 1", - users.order(id).limit(1).delete() - ) - } - - func test_delete_compilesExistsExpression() { - AssertSQL( - "SELECT EXISTS (SELECT * FROM \"users\")", - users.exists - ) - } - - func test_count_returnsCountExpression() { - AssertSQL("SELECT count(*) FROM \"users\"", users.count) - } - - func test_scalar_returnsScalarExpression() { - AssertSQL("SELECT \"int\" FROM \"table\"", table.select(int) as ScalarQuery) - AssertSQL("SELECT \"intOptional\" FROM \"table\"", table.select(intOptional) as ScalarQuery) - AssertSQL("SELECT DISTINCT \"int\" FROM \"table\"", table.select(distinct: int) as ScalarQuery) - AssertSQL("SELECT DISTINCT \"intOptional\" FROM \"table\"", table.select(distinct: intOptional) as ScalarQuery) - } - - func test_subscript_withExpression_returnsNamespacedExpression() { - let query = Table("query") - - AssertSQL("\"query\".\"blob\"", query[data]) - AssertSQL("\"query\".\"blobOptional\"", query[dataOptional]) - - AssertSQL("\"query\".\"bool\"", query[bool]) - AssertSQL("\"query\".\"boolOptional\"", query[boolOptional]) - - AssertSQL("\"query\".\"date\"", query[date]) - AssertSQL("\"query\".\"dateOptional\"", query[dateOptional]) - - AssertSQL("\"query\".\"double\"", query[double]) - AssertSQL("\"query\".\"doubleOptional\"", query[doubleOptional]) - - AssertSQL("\"query\".\"int\"", query[int]) - AssertSQL("\"query\".\"intOptional\"", query[intOptional]) - - AssertSQL("\"query\".\"int64\"", query[int64]) - AssertSQL("\"query\".\"int64Optional\"", query[int64Optional]) - - AssertSQL("\"query\".\"string\"", query[string]) - AssertSQL("\"query\".\"stringOptional\"", query[stringOptional]) - - AssertSQL("\"query\".*", query[*]) - } - - func test_tableNamespacedByDatabase() { - let table = Table("table", database: "attached") - - AssertSQL("SELECT * FROM \"attached\".\"table\"", table) - } - -} - -class QueryIntegrationTests : SQLiteTestCase { - - let id = Expression("id") - let email = Expression("email") - - override func setUp() { - super.setUp() - - CreateUsersTable() - } - - // MARK: - - - func test_select() { - let managerId = Expression("manager_id") - let managers = users.alias("managers") - - let alice = try! db.run(users.insert(email <- "alice@example.com")) - _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice)) - - for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) { - _ = user[users[managerId]] - } - } - - func test_prepareRowIterator() { - let names = ["a", "b", "c"] - try! InsertUsers(names) - - let emailColumn = Expression("email") - let emails = try! db.prepareRowIterator(users).map { $0[emailColumn] } - - XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted()) - } - - func test_ambiguousMap() { - let names = ["a", "b", "c"] - try! InsertUsers(names) - - let emails = try! db.prepare("select email from users", []).map { $0[0] as! String } - - XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted()) - } - - func test_select_optional() { - let managerId = Expression("manager_id") - let managers = users.alias("managers") - - let alice = try! db.run(users.insert(email <- "alice@example.com")) - _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice)) - - for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) { - _ = user[users[managerId]] - } - } - - func test_select_codable() throws { - let table = Table("codable") - try db.run(table.create { builder in - builder.column(Expression("int")) - builder.column(Expression("string")) - builder.column(Expression("bool")) - builder.column(Expression("float")) - builder.column(Expression("double")) - builder.column(Expression("optional")) - builder.column(Expression("sub")) - }) - - let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil) - let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8, optional: "optional", sub: value1) - - try db.run(table.insert(value)) - - let rows = try db.prepare(table) - let values: [TestCodable] = try rows.map({ try $0.decode() }) - XCTAssertEqual(values.count, 1) - XCTAssertEqual(values[0].int, 5) - XCTAssertEqual(values[0].string, "6") - XCTAssertEqual(values[0].bool, true) - XCTAssertEqual(values[0].float, 7) - XCTAssertEqual(values[0].double, 8) - XCTAssertEqual(values[0].optional, "optional") - XCTAssertEqual(values[0].sub?.int, 1) - XCTAssertEqual(values[0].sub?.string, "2") - XCTAssertEqual(values[0].sub?.bool, true) - XCTAssertEqual(values[0].sub?.float, 3) - XCTAssertEqual(values[0].sub?.double, 4) - XCTAssertNil(values[0].sub?.optional) - XCTAssertNil(values[0].sub?.sub) - } - - func test_scalar() { - XCTAssertEqual(0, try! db.scalar(users.count)) - XCTAssertEqual(false, try! db.scalar(users.exists)) - - try! InsertUsers("alice") - XCTAssertEqual(1, try! db.scalar(users.select(id.average))) - } - - func test_pluck() { - let rowid = try! db.run(users.insert(email <- "alice@example.com")) - XCTAssertEqual(rowid, try! db.pluck(users)![id]) - } - - func test_insert() { - let id = try! db.run(users.insert(email <- "alice@example.com")) - XCTAssertEqual(1, id) - } - - func test_update() { - let changes = try! db.run(users.update(email <- "alice@example.com")) - XCTAssertEqual(0, changes) - } - - func test_delete() { - let changes = try! db.run(users.delete()) - XCTAssertEqual(0, changes) - } - - func test_union() throws { - let expectedIDs = [ - try db.run(users.insert(email <- "alice@example.com")), - try db.run(users.insert(email <- "sally@example.com")) - ] - - let query1 = users.filter(email == "alice@example.com") - let query2 = users.filter(email == "sally@example.com") - - let actualIDs = try db.prepare(query1.union(query2)).map { $0[id] } - XCTAssertEqual(expectedIDs, actualIDs) - - let query3 = users.select(users[*], Expression(literal: "1 AS weight")).filter(email == "sally@example.com") - let query4 = users.select(users[*], Expression(literal: "2 AS weight")).filter(email == "alice@example.com") - - print(query3.union(query4).order(Expression(literal: "weight")).asSQL()) - - let orderedIDs = try db.prepare(query3.union(query4).order(Expression(literal: "weight"), email)).map { $0[id] } - XCTAssertEqual(Array(expectedIDs.reversed()), orderedIDs) - } - - func test_no_such_column() throws { - let doesNotExist = Expression("doesNotExist") - try! InsertUser("alice") - let row = try! db.pluck(users.filter(email == "alice@example.com"))! - - XCTAssertThrowsError(try row.get(doesNotExist)) { error in - if case QueryError.noSuchColumn(let name, _) = error { - XCTAssertEqual("\"doesNotExist\"", name) - } else { - XCTFail("unexpected error: \(error)") - } - } - } - - func test_catchConstraintError() { - try! db.run(users.insert(email <- "alice@example.com")) - do { - try db.run(users.insert(email <- "alice@example.com")) - XCTFail("expected error") - } catch let Result.error(_, code, _) where code == SQLITE_CONSTRAINT { - // expected - } catch let error { - XCTFail("unexpected error: \(error)") - } - } -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/RTreeTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/RTreeTests.swift deleted file mode 100755 index 7147533..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/RTreeTests.swift +++ /dev/null @@ -1,17 +0,0 @@ -import XCTest -import SQLite - -class RTreeTests : XCTestCase { - - func test_create_onVirtualTable_withRTree_createVirtualTableExpression() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING rtree(\"int64\", \"double\", \"double\")", - virtualTable.create(.RTree(int64, (double, double))) - ) - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING rtree(\"int64\", \"double\", \"double\", \"double\", \"double\")", - virtualTable.create(.RTree(int64, (double, double), (double, double))) - ) - } - -} \ No newline at end of file diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/RowTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/RowTests.swift deleted file mode 100755 index 17873e7..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/RowTests.swift +++ /dev/null @@ -1,88 +0,0 @@ -import XCTest -@testable import SQLite - -class RowTests : XCTestCase { - - public func test_get_value() { - let row = Row(["\"foo\"": 0], ["value"]) - let result = try! row.get(Expression("foo")) - - XCTAssertEqual("value", result) - } - - public func test_get_value_subscript() { - let row = Row(["\"foo\"": 0], ["value"]) - let result = row[Expression("foo")] - - XCTAssertEqual("value", result) - } - - public func test_get_value_optional() { - let row = Row(["\"foo\"": 0], ["value"]) - let result = try! row.get(Expression("foo")) - - XCTAssertEqual("value", result) - } - - public func test_get_value_optional_subscript() { - let row = Row(["\"foo\"": 0], ["value"]) - let result = row[Expression("foo")] - - XCTAssertEqual("value", result) - } - - public func test_get_value_optional_nil() { - let row = Row(["\"foo\"": 0], [nil]) - let result = try! row.get(Expression("foo")) - - XCTAssertNil(result) - } - - public func test_get_value_optional_nil_subscript() { - let row = Row(["\"foo\"": 0], [nil]) - let result = row[Expression("foo")] - - XCTAssertNil(result) - } - - public func test_get_type_mismatch_throws_unexpected_null_value() { - let row = Row(["\"foo\"": 0], ["value"]) - XCTAssertThrowsError(try row.get(Expression("foo"))) { error in - if case QueryError.unexpectedNullValue(let name) = error { - XCTAssertEqual("\"foo\"", name) - } else { - XCTFail("unexpected error: \(error)") - } - } - } - - public func test_get_type_mismatch_optional_returns_nil() { - let row = Row(["\"foo\"": 0], ["value"]) - let result = try! row.get(Expression("foo")) - XCTAssertNil(result) - } - - public func test_get_non_existent_column_throws_no_such_column() { - let row = Row(["\"foo\"": 0], ["value"]) - XCTAssertThrowsError(try row.get(Expression("bar"))) { error in - if case QueryError.noSuchColumn(let name, let columns) = error { - XCTAssertEqual("\"bar\"", name) - XCTAssertEqual(["\"foo\""], columns) - } else { - XCTFail("unexpected error: \(error)") - } - } - } - - public func test_get_ambiguous_column_throws() { - let row = Row(["table1.\"foo\"": 0, "table2.\"foo\"": 1], ["value"]) - XCTAssertThrowsError(try row.get(Expression("foo"))) { error in - if case QueryError.ambiguousColumn(let name, let columns) = error { - XCTAssertEqual("\"foo\"", name) - XCTAssertEqual(["table1.\"foo\"", "table2.\"foo\""], columns.sorted()) - } else { - XCTFail("unexpected error: \(error)") - } - } - } -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/SchemaTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/SchemaTests.swift deleted file mode 100755 index 30646b9..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/SchemaTests.swift +++ /dev/null @@ -1,788 +0,0 @@ -import XCTest -import SQLite - -class SchemaTests : XCTestCase { - - func test_drop_compilesDropTableExpression() { - XCTAssertEqual("DROP TABLE \"table\"", table.drop()) - XCTAssertEqual("DROP TABLE IF EXISTS \"table\"", table.drop(ifExists: true)) - } - - func test_drop_compilesDropVirtualTableExpression() { - XCTAssertEqual("DROP TABLE \"virtual_table\"", virtualTable.drop()) - XCTAssertEqual("DROP TABLE IF EXISTS \"virtual_table\"", virtualTable.drop(ifExists: true)) - } - - func test_drop_compilesDropViewExpression() { - XCTAssertEqual("DROP VIEW \"view\"", _view.drop()) - XCTAssertEqual("DROP VIEW IF EXISTS \"view\"", _view.drop(ifExists: true)) - } - - func test_create_withBuilder_compilesCreateTableExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" (" + - "\"blob\" BLOB NOT NULL, " + - "\"blobOptional\" BLOB, " + - "\"double\" REAL NOT NULL, " + - "\"doubleOptional\" REAL, " + - "\"int64\" INTEGER NOT NULL, " + - "\"int64Optional\" INTEGER, " + - "\"string\" TEXT NOT NULL, " + - "\"stringOptional\" TEXT" + - ")", - table.create { t in - t.column(data) - t.column(dataOptional) - t.column(double) - t.column(doubleOptional) - t.column(int64) - t.column(int64Optional) - t.column(string) - t.column(stringOptional) - } - ) - XCTAssertEqual( - "CREATE TEMPORARY TABLE \"table\" (\"int64\" INTEGER NOT NULL)", - table.create(temporary: true) { $0.column(int64) } - ) - XCTAssertEqual( - "CREATE TABLE IF NOT EXISTS \"table\" (\"int64\" INTEGER NOT NULL)", - table.create(ifNotExists: true) { $0.column(int64) } - ) - XCTAssertEqual( - "CREATE TEMPORARY TABLE IF NOT EXISTS \"table\" (\"int64\" INTEGER NOT NULL)", - table.create(temporary: true, ifNotExists: true) { $0.column(int64) } - ) - - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL) WITHOUT ROWID", - table.create(withoutRowid: true) { $0.column(int64) } - ) - XCTAssertEqual( - "CREATE TEMPORARY TABLE IF NOT EXISTS \"table\" (\"int64\" INTEGER NOT NULL) WITHOUT ROWID", - table.create(temporary: true, ifNotExists: true, withoutRowid: true) { $0.column(int64) } - ) - } - - func test_create_withQuery_compilesCreateTableExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" AS SELECT \"int64\" FROM \"view\"", - table.create(_view.select(int64)) - ) - } - - // thoroughness test for ambiguity - func test_column_compilesColumnDefinitionExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL)", - table.create { t in t.column(int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE)", - table.create { t in t.column(int64, unique: true) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL CHECK (\"int64\" > 0))", - table.create { t in t.column(int64, check: int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL CHECK (\"int64Optional\" > 0))", - table.create { t in t.column(int64, check: int64Optional > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL DEFAULT (\"int64\"))", - table.create { t in t.column(int64, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL DEFAULT (0))", - table.create { t in t.column(int64, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64\" > 0))", - table.create { t in t.column(int64, unique: true, check: int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64Optional\" > 0))", - table.create { t in t.column(int64, unique: true, check: int64Optional > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE DEFAULT (\"int64\"))", - table.create { t in t.column(int64, unique: true, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE DEFAULT (0))", - table.create { t in t.column(int64, unique: true, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64\" > 0))", - table.create { t in t.column(int64, unique: true, check: int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64Optional\" > 0))", - table.create { t in t.column(int64, unique: true, check: int64Optional > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64, unique: true, check: int64 > 0, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64Optional\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64, unique: true, check: int64Optional > 0, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64\" > 0) DEFAULT (0))", - table.create { t in t.column(int64, unique: true, check: int64 > 0, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64Optional\" > 0) DEFAULT (0))", - table.create { t in t.column(int64, unique: true, check: int64Optional > 0, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL CHECK (\"int64\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64, check: int64 > 0, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL CHECK (\"int64Optional\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64, check: int64Optional > 0, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL CHECK (\"int64\" > 0) DEFAULT (0))", - table.create { t in t.column(int64, check: int64 > 0, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL CHECK (\"int64Optional\" > 0) DEFAULT (0))", - table.create { t in t.column(int64, check: int64Optional > 0, defaultValue: 0) } - ) - - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL CHECK (\"int64\" > 0))", - table.create { t in t.column(int64, primaryKey: true, check: int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL CHECK (\"int64Optional\" > 0))", - table.create { t in t.column(int64, primaryKey: true, check: int64Optional > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL DEFAULT (\"int64\"))", - table.create { t in t.column(int64, primaryKey: true, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL CHECK (\"int64\" > 0))", - table.create { t in t.column(int64, primaryKey: true, check: int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL CHECK (\"int64Optional\" > 0))", - table.create { t in t.column(int64, primaryKey: true, check: int64Optional > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL CHECK (\"int64\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64, primaryKey: true, check: int64 > 0, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL CHECK (\"int64Optional\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64, primaryKey: true, check: int64Optional > 0, defaultValue: int64) } - ) - - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER)", - table.create { t in t.column(int64Optional) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE)", - table.create { t in t.column(int64Optional, unique: true) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64\" > 0))", - table.create { t in t.column(int64Optional, check: int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64Optional\" > 0))", - table.create { t in t.column(int64Optional, check: int64Optional > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER DEFAULT (\"int64\"))", - table.create { t in t.column(int64Optional, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER DEFAULT (\"int64Optional\"))", - table.create { t in t.column(int64Optional, defaultValue: int64Optional) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER DEFAULT (0))", - table.create { t in t.column(int64Optional, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64\" > 0))", - table.create { t in t.column(int64Optional, unique: true, check: int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64Optional\" > 0))", - table.create { t in t.column(int64Optional, unique: true, check: int64Optional > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE DEFAULT (\"int64\"))", - table.create { t in t.column(int64Optional, unique: true, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE DEFAULT (\"int64Optional\"))", - table.create { t in t.column(int64Optional, unique: true, defaultValue: int64Optional) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE DEFAULT (0))", - table.create { t in t.column(int64Optional, unique: true, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64\" > 0))", - table.create { t in t.column(int64Optional, unique: true, check: int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64Optional\" > 0))", - table.create { t in t.column(int64Optional, unique: true, check: int64Optional > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64Optional, unique: true, check: int64 > 0, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64\" > 0) DEFAULT (\"int64Optional\"))", - table.create { t in t.column(int64Optional, unique: true, check: int64 > 0, defaultValue: int64Optional) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64Optional\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64Optional, unique: true, check: int64Optional > 0, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64Optional\" > 0) DEFAULT (\"int64Optional\"))", - table.create { t in t.column(int64Optional, unique: true, check: int64Optional > 0, defaultValue: int64Optional) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64\" > 0) DEFAULT (0))", - table.create { t in t.column(int64Optional, unique: true, check: int64 > 0, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64Optional\" > 0) DEFAULT (0))", - table.create { t in t.column(int64Optional, unique: true, check: int64Optional > 0, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64Optional, check: int64 > 0, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64Optional\" > 0) DEFAULT (\"int64\"))", - table.create { t in t.column(int64Optional, check: int64Optional > 0, defaultValue: int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64\" > 0) DEFAULT (\"int64Optional\"))", - table.create { t in t.column(int64Optional, check: int64 > 0, defaultValue: int64Optional) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64Optional\" > 0) DEFAULT (\"int64Optional\"))", - table.create { t in t.column(int64Optional, check: int64Optional > 0, defaultValue: int64Optional) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64\" > 0) DEFAULT (0))", - table.create { t in t.column(int64Optional, check: int64 > 0, defaultValue: 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64Optional\" > 0) DEFAULT (0))", - table.create { t in t.column(int64Optional, check: int64Optional > 0, defaultValue: 0) } - ) - } - - func test_column_withIntegerExpression_compilesPrimaryKeyAutoincrementColumnDefinitionExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - table.create { t in t.column(int64, primaryKey: .autoincrement) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK (\"int64\" > 0))", - table.create { t in t.column(int64, primaryKey: .autoincrement, check: int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK (\"int64Optional\" > 0))", - table.create { t in t.column(int64, primaryKey: .autoincrement, check: int64Optional > 0) } - ) - } - - func test_column_withIntegerExpression_compilesReferentialColumnDefinitionExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64, references: qualifiedTable, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64, unique: true, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64, check: int64 > 0, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64, check: int64Optional > 0, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64, unique: true, check: int64 > 0, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64, unique: true, check: int64Optional > 0, references: table, int64) } - ) - - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64Optional, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64Optional, unique: true, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64Optional, check: int64 > 0, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64Optional, check: int64Optional > 0, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64Optional, unique: true, check: int64 > 0, references: table, int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\"))", - table.create { t in t.column(int64Optional, unique: true, check: int64Optional > 0, references: table, int64) } - ) - } - - func test_column_withStringExpression_compilesCollatedColumnDefinitionExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL COLLATE RTRIM)", - table.create { t in t.column(string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE COLLATE RTRIM)", - table.create { t in t.column(string, unique: true, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"string\" != '') COLLATE RTRIM)", - table.create { t in t.column(string, check: string != "", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"stringOptional\" != '') COLLATE RTRIM)", - table.create { t in t.column(string, check: stringOptional != "", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(string, defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(string, defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') COLLATE RTRIM)", - table.create { t in t.column(string, unique: true, check: string != "", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') COLLATE RTRIM)", - table.create { t in t.column(string, unique: true, check: stringOptional != "", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(string, unique: true, defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(string, unique: true, defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(string, unique: true, check: string != "", defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(string, unique: true, check: stringOptional != "", defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(string, unique: true, check: string != "", defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(string, unique: true, check: stringOptional != "", defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(string, check: string != "", defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(string, check: stringOptional != "", defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(string, check: string != "", defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(string, check: stringOptional != "", defaultValue: "string", collate: .rtrim) } - ) - - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT COLLATE RTRIM)", - table.create { t in t.column(stringOptional, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, check: string != "", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, check: stringOptional != "", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT DEFAULT (\"stringOptional\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, defaultValue: stringOptional, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, check: string != "", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE DEFAULT (\"stringOptional\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, defaultValue: stringOptional, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: stringOptional, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: stringOptional, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, check: string != "", defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: string, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, check: string != "", defaultValue: stringOptional, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)", - table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: stringOptional, collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, check: string != "", defaultValue: "string", collate: .rtrim) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)", - table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: "string", collate: .rtrim) } - ) - } - - func test_primaryKey_compilesPrimaryKeyExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" (PRIMARY KEY (\"int64\"))", - table.create { t in t.primaryKey(int64) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (PRIMARY KEY (\"int64\", \"string\"))", - table.create { t in t.primaryKey(int64, string) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (PRIMARY KEY (\"int64\", \"string\", \"double\"))", - table.create { t in t.primaryKey(int64, string, double) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (PRIMARY KEY (\"int64\", \"string\", \"double\", \"date\"))", - table.create { t in t.primaryKey(int64, string, double, date) } - ) - } - - func test_unique_compilesUniqueExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" (UNIQUE (\"int64\"))", - table.create { t in t.unique(int64) } - ) - } - - func test_check_compilesCheckExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" (CHECK ((\"int64\" > 0)))", - table.create { t in t.check(int64 > 0) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (CHECK ((\"int64Optional\" > 0)))", - table.create { t in t.check(int64Optional > 0) } - ) - } - - func test_foreignKey_compilesForeignKeyExpression() { - XCTAssertEqual( - "CREATE TABLE \"table\" (FOREIGN KEY (\"string\") REFERENCES \"table\" (\"string\"))", - table.create { t in t.foreignKey(string, references: table, string) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (FOREIGN KEY (\"stringOptional\") REFERENCES \"table\" (\"string\"))", - table.create { t in t.foreignKey(stringOptional, references: table, string) } - ) - - XCTAssertEqual( - "CREATE TABLE \"table\" (FOREIGN KEY (\"string\") REFERENCES \"table\" (\"string\") ON UPDATE CASCADE ON DELETE SET NULL)", - table.create { t in t.foreignKey(string, references: table, string, update: .cascade, delete: .setNull) } - ) - - XCTAssertEqual( - "CREATE TABLE \"table\" (FOREIGN KEY (\"string\", \"string\") REFERENCES \"table\" (\"string\", \"string\"))", - table.create { t in t.foreignKey((string, string), references: table, (string, string)) } - ) - XCTAssertEqual( - "CREATE TABLE \"table\" (FOREIGN KEY (\"string\", \"string\", \"string\") REFERENCES \"table\" (\"string\", \"string\", \"string\"))", - table.create { t in t.foreignKey((string, string, string), references: table, (string, string, string)) } - ) - } - - func test_addColumn_compilesAlterTableExpression() { - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64\" INTEGER NOT NULL DEFAULT (1)", - table.addColumn(int64, defaultValue: 1) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64\" INTEGER NOT NULL CHECK (\"int64\" > 0) DEFAULT (1)", - table.addColumn(int64, check: int64 > 0, defaultValue: 1) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64\" INTEGER NOT NULL CHECK (\"int64Optional\" > 0) DEFAULT (1)", - table.addColumn(int64, check: int64Optional > 0, defaultValue: 1) - ) - - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER", - table.addColumn(int64Optional) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER CHECK (\"int64\" > 0)", - table.addColumn(int64Optional, check: int64 > 0) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER CHECK (\"int64Optional\" > 0)", - table.addColumn(int64Optional, check: int64Optional > 0) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER DEFAULT (1)", - table.addColumn(int64Optional, defaultValue: 1) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER CHECK (\"int64\" > 0) DEFAULT (1)", - table.addColumn(int64Optional, check: int64 > 0, defaultValue: 1) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER CHECK (\"int64Optional\" > 0) DEFAULT (1)", - table.addColumn(int64Optional, check: int64Optional > 0, defaultValue: 1) - ) - } - - func test_addColumn_withIntegerExpression_compilesReferentialAlterTableExpression() { - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64\" INTEGER NOT NULL REFERENCES \"table\" (\"int64\")", - table.addColumn(int64, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64\" INTEGER NOT NULL UNIQUE REFERENCES \"table\" (\"int64\")", - table.addColumn(int64, unique: true, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64\" INTEGER NOT NULL CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\")", - table.addColumn(int64, check: int64 > 0, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64\" INTEGER NOT NULL CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\")", - table.addColumn(int64, check: int64Optional > 0, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\")", - table.addColumn(int64, unique: true, check: int64 > 0, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\")", - table.addColumn(int64, unique: true, check: int64Optional > 0, references: table, int64) - ) - - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER REFERENCES \"table\" (\"int64\")", - table.addColumn(int64Optional, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER UNIQUE REFERENCES \"table\" (\"int64\")", - table.addColumn(int64Optional, unique: true, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\")", - table.addColumn(int64Optional, check: int64 > 0, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\")", - table.addColumn(int64Optional, check: int64Optional > 0, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER UNIQUE CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\")", - table.addColumn(int64Optional, unique: true, check: int64 > 0, references: table, int64) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"int64Optional\" INTEGER UNIQUE CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\")", - table.addColumn(int64Optional, unique: true, check: int64Optional > 0, references: table, int64) - ) - } - - func test_addColumn_withStringExpression_compilesCollatedAlterTableExpression() { - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"string\" TEXT NOT NULL DEFAULT ('string') COLLATE RTRIM", - table.addColumn(string, defaultValue: "string", collate: .rtrim) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"string\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM", - table.addColumn(string, check: string != "", defaultValue: "string", collate: .rtrim) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"string\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM", - table.addColumn(string, check: stringOptional != "", defaultValue: "string", collate: .rtrim) - ) - - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT COLLATE RTRIM", - table.addColumn(stringOptional, collate: .rtrim) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT CHECK (\"string\" != '') COLLATE RTRIM", - table.addColumn(stringOptional, check: string != "", collate: .rtrim) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT CHECK (\"stringOptional\" != '') COLLATE RTRIM", - table.addColumn(stringOptional, check: stringOptional != "", collate: .rtrim) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM", - table.addColumn(stringOptional, check: string != "", defaultValue: "string", collate: .rtrim) - ) - XCTAssertEqual( - "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM", - table.addColumn(stringOptional, check: stringOptional != "", defaultValue: "string", collate: .rtrim) - ) - } - - func test_rename_compilesAlterTableRenameToExpression() { - XCTAssertEqual("ALTER TABLE \"old\" RENAME TO \"table\"", Table("old").rename(table)) - } - - func test_createIndex_compilesCreateIndexExpression() { - XCTAssertEqual("CREATE INDEX \"index_table_on_int64\" ON \"table\" (\"int64\")", table.createIndex(int64)) - - XCTAssertEqual( - "CREATE UNIQUE INDEX \"index_table_on_int64\" ON \"table\" (\"int64\")", - table.createIndex(int64, unique: true) - ) - XCTAssertEqual( - "CREATE INDEX IF NOT EXISTS \"index_table_on_int64\" ON \"table\" (\"int64\")", - table.createIndex(int64, ifNotExists: true) - ) - XCTAssertEqual( - "CREATE UNIQUE INDEX IF NOT EXISTS \"index_table_on_int64\" ON \"table\" (\"int64\")", - table.createIndex(int64, unique: true, ifNotExists: true) - ) - XCTAssertEqual( - "CREATE UNIQUE INDEX IF NOT EXISTS \"main\".\"index_table_on_int64\" ON \"table\" (\"int64\")", - qualifiedTable.createIndex(int64, unique: true, ifNotExists: true) - ) - } - - func test_dropIndex_compilesCreateIndexExpression() { - XCTAssertEqual("DROP INDEX \"index_table_on_int64\"", table.dropIndex(int64)) - XCTAssertEqual("DROP INDEX IF EXISTS \"index_table_on_int64\"", table.dropIndex(int64, ifExists: true)) - } - - func test_create_onView_compilesCreateViewExpression() { - XCTAssertEqual( - "CREATE VIEW \"view\" AS SELECT \"int64\" FROM \"table\"", - _view.create(table.select(int64)) - ) - XCTAssertEqual( - "CREATE TEMPORARY VIEW \"view\" AS SELECT \"int64\" FROM \"table\"", - _view.create(table.select(int64), temporary: true) - ) - XCTAssertEqual( - "CREATE VIEW IF NOT EXISTS \"view\" AS SELECT \"int64\" FROM \"table\"", - _view.create(table.select(int64), ifNotExists: true) - ) - XCTAssertEqual( - "CREATE TEMPORARY VIEW IF NOT EXISTS \"view\" AS SELECT \"int64\" FROM \"table\"", - _view.create(table.select(int64), temporary: true, ifNotExists: true) - ) - } - - func test_create_onVirtualTable_compilesCreateVirtualTableExpression() { - XCTAssertEqual( - "CREATE VIRTUAL TABLE \"virtual_table\" USING \"custom\"('foo', 'bar')", - virtualTable.create(Module("custom", ["foo", "bar"])) - ) - } - - func test_rename_onVirtualTable_compilesAlterTableRenameToExpression() { - XCTAssertEqual( - "ALTER TABLE \"old\" RENAME TO \"virtual_table\"", - VirtualTable("old").rename(virtualTable) - ) - } - -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/SetterTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/SetterTests.swift deleted file mode 100755 index d4f189d..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/SetterTests.swift +++ /dev/null @@ -1,137 +0,0 @@ -import XCTest -import SQLite - -class SetterTests : XCTestCase { - - func test_setterAssignmentOperator_buildsSetter() { - AssertSQL("\"int\" = \"int\"", int <- int) - AssertSQL("\"int\" = 1", int <- 1) - AssertSQL("\"intOptional\" = \"int\"", intOptional <- int) - AssertSQL("\"intOptional\" = \"intOptional\"", intOptional <- intOptional) - AssertSQL("\"intOptional\" = 1", intOptional <- 1) - AssertSQL("\"intOptional\" = NULL", intOptional <- nil) - } - - func test_plusEquals_withStringExpression_buildsSetter() { - AssertSQL("\"string\" = (\"string\" || \"string\")", string += string) - AssertSQL("\"string\" = (\"string\" || 'literal')", string += "literal") - AssertSQL("\"stringOptional\" = (\"stringOptional\" || \"string\")", stringOptional += string) - AssertSQL("\"stringOptional\" = (\"stringOptional\" || \"stringOptional\")", stringOptional += stringOptional) - AssertSQL("\"stringOptional\" = (\"stringOptional\" || 'literal')", stringOptional += "literal") - } - - func test_plusEquals_withNumberExpression_buildsSetter() { - AssertSQL("\"int\" = (\"int\" + \"int\")", int += int) - AssertSQL("\"int\" = (\"int\" + 1)", int += 1) - AssertSQL("\"intOptional\" = (\"intOptional\" + \"int\")", intOptional += int) - AssertSQL("\"intOptional\" = (\"intOptional\" + \"intOptional\")", intOptional += intOptional) - AssertSQL("\"intOptional\" = (\"intOptional\" + 1)", intOptional += 1) - - AssertSQL("\"double\" = (\"double\" + \"double\")", double += double) - AssertSQL("\"double\" = (\"double\" + 1.0)", double += 1) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" + \"double\")", doubleOptional += double) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" + \"doubleOptional\")", doubleOptional += doubleOptional) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" + 1.0)", doubleOptional += 1) - } - - func test_minusEquals_withNumberExpression_buildsSetter() { - AssertSQL("\"int\" = (\"int\" - \"int\")", int -= int) - AssertSQL("\"int\" = (\"int\" - 1)", int -= 1) - AssertSQL("\"intOptional\" = (\"intOptional\" - \"int\")", intOptional -= int) - AssertSQL("\"intOptional\" = (\"intOptional\" - \"intOptional\")", intOptional -= intOptional) - AssertSQL("\"intOptional\" = (\"intOptional\" - 1)", intOptional -= 1) - - AssertSQL("\"double\" = (\"double\" - \"double\")", double -= double) - AssertSQL("\"double\" = (\"double\" - 1.0)", double -= 1) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" - \"double\")", doubleOptional -= double) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" - \"doubleOptional\")", doubleOptional -= doubleOptional) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" - 1.0)", doubleOptional -= 1) - } - - func test_timesEquals_withNumberExpression_buildsSetter() { - AssertSQL("\"int\" = (\"int\" * \"int\")", int *= int) - AssertSQL("\"int\" = (\"int\" * 1)", int *= 1) - AssertSQL("\"intOptional\" = (\"intOptional\" * \"int\")", intOptional *= int) - AssertSQL("\"intOptional\" = (\"intOptional\" * \"intOptional\")", intOptional *= intOptional) - AssertSQL("\"intOptional\" = (\"intOptional\" * 1)", intOptional *= 1) - - AssertSQL("\"double\" = (\"double\" * \"double\")", double *= double) - AssertSQL("\"double\" = (\"double\" * 1.0)", double *= 1) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" * \"double\")", doubleOptional *= double) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" * \"doubleOptional\")", doubleOptional *= doubleOptional) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" * 1.0)", doubleOptional *= 1) - } - - func test_dividedByEquals_withNumberExpression_buildsSetter() { - AssertSQL("\"int\" = (\"int\" / \"int\")", int /= int) - AssertSQL("\"int\" = (\"int\" / 1)", int /= 1) - AssertSQL("\"intOptional\" = (\"intOptional\" / \"int\")", intOptional /= int) - AssertSQL("\"intOptional\" = (\"intOptional\" / \"intOptional\")", intOptional /= intOptional) - AssertSQL("\"intOptional\" = (\"intOptional\" / 1)", intOptional /= 1) - - AssertSQL("\"double\" = (\"double\" / \"double\")", double /= double) - AssertSQL("\"double\" = (\"double\" / 1.0)", double /= 1) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" / \"double\")", doubleOptional /= double) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" / \"doubleOptional\")", doubleOptional /= doubleOptional) - AssertSQL("\"doubleOptional\" = (\"doubleOptional\" / 1.0)", doubleOptional /= 1) - } - - func test_moduloEquals_withIntegerExpression_buildsSetter() { - AssertSQL("\"int\" = (\"int\" % \"int\")", int %= int) - AssertSQL("\"int\" = (\"int\" % 1)", int %= 1) - AssertSQL("\"intOptional\" = (\"intOptional\" % \"int\")", intOptional %= int) - AssertSQL("\"intOptional\" = (\"intOptional\" % \"intOptional\")", intOptional %= intOptional) - AssertSQL("\"intOptional\" = (\"intOptional\" % 1)", intOptional %= 1) - } - - func test_leftShiftEquals_withIntegerExpression_buildsSetter() { - AssertSQL("\"int\" = (\"int\" << \"int\")", int <<= int) - AssertSQL("\"int\" = (\"int\" << 1)", int <<= 1) - AssertSQL("\"intOptional\" = (\"intOptional\" << \"int\")", intOptional <<= int) - AssertSQL("\"intOptional\" = (\"intOptional\" << \"intOptional\")", intOptional <<= intOptional) - AssertSQL("\"intOptional\" = (\"intOptional\" << 1)", intOptional <<= 1) - } - - func test_rightShiftEquals_withIntegerExpression_buildsSetter() { - AssertSQL("\"int\" = (\"int\" >> \"int\")", int >>= int) - AssertSQL("\"int\" = (\"int\" >> 1)", int >>= 1) - AssertSQL("\"intOptional\" = (\"intOptional\" >> \"int\")", intOptional >>= int) - AssertSQL("\"intOptional\" = (\"intOptional\" >> \"intOptional\")", intOptional >>= intOptional) - AssertSQL("\"intOptional\" = (\"intOptional\" >> 1)", intOptional >>= 1) - } - - func test_bitwiseAndEquals_withIntegerExpression_buildsSetter() { - AssertSQL("\"int\" = (\"int\" & \"int\")", int &= int) - AssertSQL("\"int\" = (\"int\" & 1)", int &= 1) - AssertSQL("\"intOptional\" = (\"intOptional\" & \"int\")", intOptional &= int) - AssertSQL("\"intOptional\" = (\"intOptional\" & \"intOptional\")", intOptional &= intOptional) - AssertSQL("\"intOptional\" = (\"intOptional\" & 1)", intOptional &= 1) - } - - func test_bitwiseOrEquals_withIntegerExpression_buildsSetter() { - AssertSQL("\"int\" = (\"int\" | \"int\")", int |= int) - AssertSQL("\"int\" = (\"int\" | 1)", int |= 1) - AssertSQL("\"intOptional\" = (\"intOptional\" | \"int\")", intOptional |= int) - AssertSQL("\"intOptional\" = (\"intOptional\" | \"intOptional\")", intOptional |= intOptional) - AssertSQL("\"intOptional\" = (\"intOptional\" | 1)", intOptional |= 1) - } - - func test_bitwiseExclusiveOrEquals_withIntegerExpression_buildsSetter() { - AssertSQL("\"int\" = (~((\"int\" & \"int\")) & (\"int\" | \"int\"))", int ^= int) - AssertSQL("\"int\" = (~((\"int\" & 1)) & (\"int\" | 1))", int ^= 1) - AssertSQL("\"intOptional\" = (~((\"intOptional\" & \"int\")) & (\"intOptional\" | \"int\"))", intOptional ^= int) - AssertSQL("\"intOptional\" = (~((\"intOptional\" & \"intOptional\")) & (\"intOptional\" | \"intOptional\"))", intOptional ^= intOptional) - AssertSQL("\"intOptional\" = (~((\"intOptional\" & 1)) & (\"intOptional\" | 1))", intOptional ^= 1) - } - - func test_postfixPlus_withIntegerValue_buildsSetter() { - AssertSQL("\"int\" = (\"int\" + 1)", int++) - AssertSQL("\"intOptional\" = (\"intOptional\" + 1)", intOptional++) - } - - func test_postfixMinus_withIntegerValue_buildsSetter() { - AssertSQL("\"int\" = (\"int\" - 1)", int--) - AssertSQL("\"intOptional\" = (\"intOptional\" - 1)", intOptional--) - } - -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/StatementTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/StatementTests.swift deleted file mode 100755 index 326259b..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/StatementTests.swift +++ /dev/null @@ -1,26 +0,0 @@ -import XCTest -import SQLite - -class StatementTests : SQLiteTestCase { - override func setUp() { - super.setUp() - CreateUsersTable() - } - - func test_cursor_to_blob() { - try! InsertUsers("alice") - let statement = try! db.prepare("SELECT email FROM users") - XCTAssert(try! statement.step()) - let blob = statement.row[0] as Blob - XCTAssertEqual("alice@example.com", String(bytes: blob.bytes, encoding: .utf8)!) - } - - func test_zero_sized_blob_returns_null() { - let blobs = Table("blobs") - let blobColumn = Expression("blob_column") - try! db.run(blobs.create { $0.column(blobColumn) }) - try! db.run(blobs.insert(blobColumn <- Blob(bytes: []))) - let blobValue = try! db.scalar(blobs.select(blobColumn).limit(1, offset: 0)) - XCTAssertEqual([], blobValue.bytes) - } -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/TestHelpers.swift b/ios/libs/Sqlite/Tests/SQLiteTests/TestHelpers.swift deleted file mode 100755 index 2e491b0..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/TestHelpers.swift +++ /dev/null @@ -1,126 +0,0 @@ -import XCTest -@testable import SQLite - -class SQLiteTestCase : XCTestCase { - private var trace:[String: Int]! - var db:Connection! - let users = Table("users") - - override func setUp() { - super.setUp() - db = try! Connection() - trace = [String:Int]() - - db.trace { SQL in - print(SQL) - self.trace[SQL, default: 0] += 1 - } - } - - func CreateUsersTable() { - try! db.execute(""" - CREATE TABLE users ( - id INTEGER PRIMARY KEY, - email TEXT NOT NULL UNIQUE, - age INTEGER, - salary REAL, - admin BOOLEAN NOT NULL DEFAULT 0 CHECK (admin IN (0, 1)), - manager_id INTEGER, - FOREIGN KEY(manager_id) REFERENCES users(id) - ) - """ - ) - } - - func InsertUsers(_ names: String...) throws { - try InsertUsers(names) - } - - func InsertUsers(_ names: [String]) throws { - for name in names { try InsertUser(name) } - } - - @discardableResult func InsertUser(_ name: String, age: Int? = nil, admin: Bool = false) throws -> Statement { - return try db.run( - "INSERT INTO \"users\" (email, age, admin) values (?, ?, ?)", - "\(name)@example.com", age?.datatypeValue, admin.datatypeValue - ) - } - - func AssertSQL(_ SQL: String, _ executions: Int = 1, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( - executions, trace[SQL] ?? 0, - message ?? SQL, - file: file, line: line - ) - } - - func AssertSQL(_ SQL: String, _ statement: Statement, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) { - try! statement.run() - AssertSQL(SQL, 1, message, file: file, line: line) - if let count = trace[SQL] { trace[SQL] = count - 1 } - } - -// func AssertSQL(SQL: String, _ query: Query, _ message: String? = nil, file: String = __FILE__, line: UInt = __LINE__) { -// for _ in query {} -// AssertSQL(SQL, 1, message, file: file, line: line) -// if let count = trace[SQL] { trace[SQL] = count - 1 } -// } - - func async(expect description: String = "async", timeout: Double = 5, block: (@escaping () -> Void) -> Void) { - let expectation = self.expectation(description: description) - block({ expectation.fulfill() }) - waitForExpectations(timeout: timeout, handler: nil) - } - -} - -let bool = Expression("bool") -let boolOptional = Expression("boolOptional") - -let data = Expression("blob") -let dataOptional = Expression("blobOptional") - -let date = Expression("date") -let dateOptional = Expression("dateOptional") - -let double = Expression("double") -let doubleOptional = Expression("doubleOptional") - -let int = Expression("int") -let intOptional = Expression("intOptional") - -let int64 = Expression("int64") -let int64Optional = Expression("int64Optional") - -let string = Expression("string") -let stringOptional = Expression("stringOptional") - -func AssertSQL(_ expression1: @autoclosure () -> String, _ expression2: @autoclosure () -> Expressible, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(expression1(), expression2().asSQL(), file: file, line: line) -} - -let table = Table("table") -let qualifiedTable = Table("table", database: "main") -let virtualTable = VirtualTable("virtual_table") -let _view = View("view") // avoid Mac XCTestCase collision - -class TestCodable: Codable { - let int: Int - let string: String - let bool: Bool - let float: Float - let double: Double - let optional: String? - let sub: TestCodable? - - init(int: Int, string: String, bool: Bool, float: Float, double: Double, optional: String?, sub: TestCodable?) { - self.int = int - self.string = string - self.bool = bool - self.float = float - self.double = double - self.optional = optional - self.sub = sub - } -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/ValueTests.swift b/ios/libs/Sqlite/Tests/SQLiteTests/ValueTests.swift deleted file mode 100755 index bda2b4b..0000000 --- a/ios/libs/Sqlite/Tests/SQLiteTests/ValueTests.swift +++ /dev/null @@ -1,6 +0,0 @@ -import XCTest -import SQLite - -class ValueTests : XCTestCase { - -} diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/fixtures/encrypted-3.x.sqlite b/ios/libs/Sqlite/Tests/SQLiteTests/fixtures/encrypted-3.x.sqlite deleted file mode 100755 index 4b3c4d0..0000000 Binary files a/ios/libs/Sqlite/Tests/SQLiteTests/fixtures/encrypted-3.x.sqlite and /dev/null differ diff --git a/ios/libs/Sqlite/Tests/SQLiteTests/fixtures/encrypted-4.x.sqlite b/ios/libs/Sqlite/Tests/SQLiteTests/fixtures/encrypted-4.x.sqlite deleted file mode 100755 index 3689036..0000000 Binary files a/ios/libs/Sqlite/Tests/SQLiteTests/fixtures/encrypted-4.x.sqlite and /dev/null differ diff --git a/ios/libs/Sqlite/run-tests.sh b/ios/libs/Sqlite/run-tests.sh deleted file mode 100755 index 0a105c4..0000000 --- a/ios/libs/Sqlite/run-tests.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -set -ev -if [ -n "$BUILD_SCHEME" ]; then - if [ -n "$IOS_SIMULATOR" ]; then - make test BUILD_SCHEME="$BUILD_SCHEME" IOS_SIMULATOR="$IOS_SIMULATOR" IOS_VERSION="$IOS_VERSION" - else - make test BUILD_SCHEME="$BUILD_SCHEME" - fi -elif [ -n "$VALIDATOR_SUBSPEC" ]; then - cd Tests/CocoaPods && make test -elif [ -n "$CARTHAGE_PLATFORM" ]; then - cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM" -elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then - swift ${PACKAGE_MANAGER_COMMAND} -fi diff --git a/ios/libs/Webim/Cartfile b/ios/libs/Webim/Cartfile deleted file mode 100755 index 9f85bbe..0000000 --- a/ios/libs/Webim/Cartfile +++ /dev/null @@ -1 +0,0 @@ -github "stephencelis/SQLite.swift" == 0.11.5 diff --git a/ios/libs/Webim/Cartfile.resolved b/ios/libs/Webim/Cartfile.resolved deleted file mode 100755 index 438fb56..0000000 --- a/ios/libs/Webim/Cartfile.resolved +++ /dev/null @@ -1 +0,0 @@ -github "stephencelis/SQLite.swift" "0.11.4" diff --git a/ios/libs/Webim/Documentation/Images/Logo.png b/ios/libs/Webim/Documentation/Images/Logo.png deleted file mode 100755 index feb4675..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Logo.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/ChatScreenClassic.png b/ios/libs/Webim/Documentation/Images/Screenshots/ChatScreenClassic.png deleted file mode 100755 index f11a5d2..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/ChatScreenClassic.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/ChatScreenDark.png b/ios/libs/Webim/Documentation/Images/Screenshots/ChatScreenDark.png deleted file mode 100755 index b050e49..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/ChatScreenDark.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/ImageScreenClassic.png b/ios/libs/Webim/Documentation/Images/Screenshots/ImageScreenClassic.png deleted file mode 100755 index 2cf2a21..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/ImageScreenClassic.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/ImageScreenDark.png b/ios/libs/Webim/Documentation/Images/Screenshots/ImageScreenDark.png deleted file mode 100755 index 9e7a868..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/ImageScreenDark.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/RatingScreenClassic.png b/ios/libs/Webim/Documentation/Images/Screenshots/RatingScreenClassic.png deleted file mode 100755 index 0393cbf..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/RatingScreenClassic.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/RatingScreenDark.png b/ios/libs/Webim/Documentation/Images/Screenshots/RatingScreenDark.png deleted file mode 100755 index 98bceea..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/RatingScreenDark.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/SettingsScreenClassic.png b/ios/libs/Webim/Documentation/Images/Screenshots/SettingsScreenClassic.png deleted file mode 100755 index 88101b6..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/SettingsScreenClassic.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/SettingsScreenDark.png b/ios/libs/Webim/Documentation/Images/Screenshots/SettingsScreenDark.png deleted file mode 100755 index 336b879..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/SettingsScreenDark.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/StartScreenClassic.png b/ios/libs/Webim/Documentation/Images/Screenshots/StartScreenClassic.png deleted file mode 100755 index 2beacdf..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/StartScreenClassic.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Images/Screenshots/StartScreenDark.png b/ios/libs/Webim/Documentation/Images/Screenshots/StartScreenDark.png deleted file mode 100755 index 3fba716..0000000 Binary files a/ios/libs/Webim/Documentation/Images/Screenshots/StartScreenDark.png and /dev/null differ diff --git a/ios/libs/Webim/Documentation/Index.md b/ios/libs/Webim/Documentation/Index.md deleted file mode 100755 index 039c600..0000000 --- a/ios/libs/Webim/Documentation/Index.md +++ /dev/null @@ -1,1736 +0,0 @@ -# _WebimClientLibrary_ Reference Book - -

Table of contents

- -- [Webim class](#webim) - - [Class method newSessionBuilder()](#new-session-builder) - - [Class method parse(remoteNotification:visitorId:)](#parse-remote-notification) - - [Class method isWebim(remoteNotification:)](#is-webim-remote-notification) - - [RemoteNotificationSystem enum](#remote-notification-system) - - [APNS case](#apns) - - [NONE case](#none) -- [SessionBuilder class](#session-builder) - - [Instance method set(accountName:)](#set-account-name) - - [Instance method set(location:)](#set-location) - - [Instance method set(prechat:)](#set-prechat) - - [Instance method set(appVersion:)](#set-app-version) - - [Instance method set(visitorFieldsJSONString:)](#set-visitor-fields-json-string-json-string) - - [Instance method set(visitorFieldsJSONData:)](#set-visitor-fields-json-data-json-data) - - [Instance method set(providedAuthorizationTokenStateListener:providedAuthorizationToken:)](#set-provided-authorization-token-state-listener-provided-authorization-token) - - [Instance method set(pageTitle:)](#set-page-title) - - [Instance method set(fatalErrorHandler:)](#set-fatal-error-handler) - - [Instance method set(remoteNotificationSystem:)](#set-remote-notification-system) - - [Instance method set(deviceToken:)](#set-device-token) - - [Instance method set(isLocalHistoryStoragingEnabled:)](#set-is-local-history-storaging-enabled) - - [Instance method set(isVisitorDataClearingEnabled:)](#set-is-visitor-data-clearing-enabled) - - [Instance method set(webimLogger:verbosityLevel:)](#set-webim-logger-verbosity-level) - - [Instance method build()](#build) - - [WebimLoggerVerbosityLevel enum](#webim-logger-verbosity-level) - - [VERBOSE case](#verbose) - - [DEBUG case](#debug) - - [INFO](#info) - - [WARNING case](#warning) - - [ERROR case](#error) - - [SessionBuilderError enum](#session-builder-error) - - [NIL_ACCOUNT_NAME case](#nil-account-name) - - [NIL_LOCATION case](#nil-location) - - [INVALID_AUTHENTICATION_PARAMETERS](#invalid-authentication-parameters) - - [INVALID_REMOTE_NOTIFICATION_CONFIGURATION case](#invalid-remote-notification-configuration) -- [ProvidedAuthorizationTokenStateListener protocol](#provided-authorization-token-state-listener) - - [update(providedAuthorizationToken:) method](#update-provided-authorization-token) -- [WebimSession protocol](#webim-session) - - [resume() method](#resume) - - [pause() method](#pause) - - [destroy() method](#destroy) - - [destroyWithClearVisitorData() method](#destroy-with-clear-visitor-data) - - [getStream() method](#get-stream) - - [change(location:) method](#change-location) - - [set(deviceToken:) method](#set-device-token) -- [MessageStream protocol](#message-stream) - - [getVisitSessionState() method](#get-visit-session-state) - - [getChatState() method](#get-chat-state) - - [getUnreadByOperatorTimestamp() method](#get-unread-by-operator-timestamp) - - [getUnreadByVisitorMessageCount() method](#get-unread-by-visitor-message-count) - - [getUnreadByVisitorTimestamp() method](#get-unread-by-visitor-timestamp) - - [getDepartmentList() method](#get-department-list) - - [getLocationSettings() method](#get-location-settings) - - [getCurrentOperator() method](#get-current-operator) - - [getLastRatingOfOperatorWith(id:) method](#get-last-rating-of-operator-with-id) - - [rateOperatorWith(id:byRating:completionHandler:) method](#rate-operator-with-id-by-rating-rating) - - [respondSentryCall(id:) method](#respond-sentry-call) - - [startChat() method](#start-chat) - - [startChat(firstQuestion:) method](#start-chat-first-question) - - [startChat(customFields:) method](#start-chat-custom-fields) - - [startChat(departmentKey:) method](#start-chat-department-key) - - [startChat(departmentKey:firstQuestion:) method](#start-chat-department-key-first-question) - - [startChat(firstQuestion:customFields) method](#start-chat-first-question-custom-fields) - - [startChat(departmentKey:customFields) method](#start-chat-department-key-custom-fields) - - [startChat(departmentKey:firstQuestion:customFields) method](#start-chat-department-key-first-question-custom-fields) - - [closeChat() method](#close-chat) - - [send(message:) method](#send-message) - - [setVisitorTyping(draftMessage:) method](#set-visitor-typing-draft-message) - - [send(message:data:completionHandler:) method](#send-message-data) - - [send(message:isHintQuestion:) method](#send-message-is-hint-question) - - [send(file:filename:mimeType:completionHandler:) method](#send-file-filename-mime-type-completion-handler) - - [udpateWidgetStatus(data:) method](#update-widget-status) - - [edit(message:text:completionHandler:) method](#edit-message) - - [delete(message:completionHandler:) method](#delete-message) - - [setChatRead() method](#set-chat-read) - - [set(prechatFields:) method](#set-prechat-fields) - - [newMessageTracker(messageListener:) method](#new-message-tracker-message-listener) - - [set(visitSessionStateListener:)](#set-visit-session-state-listener) - - [set(chatStateListener:) method](#set-chat-state-listener) - - [set(currentOperatorChangeListener:) method](#set-current-operator-change-listener) - - [set(departmentListChangeListener:)](#set-department-list-change-listener) - - [set(operatorTypingListener:) method](#set-operator-typing-listener) - - [set(locationSettingsChangeListener:) method](#set-location-settings-change-listener) - - [set(onlineStatusChangeListener:) method](#set-online-status-change-listener) - - [set(unreadByOperatorTimestampChangeListener:) method](#set-unread-by-operator-timestamp-change-listener) - - [set(unreadByVisitorMessageCountChangeListener:) method](#set-unread-by-visitor-message-count-change-listener) - - [set(unreadByVisitorTimestampChangeListener:) method](#set-unread-by-visitor-timestamp-change-listener) -- [DataMessageCompletionHandler protocol](#data-message-completion-handler) - - [onSuccess(messageID:) method](#on-success-message-id-data-message-completion-handler) - - [onFailure(messageID:,error:) method](#on-failure-message-id-error-data-message-completion-handler) -- [EditMessageCompletionHandler protocol](#edit-message-completion-handler) - - [onSuccess(messageID:) method](#on-success-message-id-edit-message-completion-handler) - - [onFailure(messageID:,error:) method](#on-failure-message-id-error-edit-message-completion-handler) -- [DeleteMessageCompletionHandler protocol](#delete-message-completion-handler) - - [onSuccess(messageID:) method](#on-success-message-id-delete-message-completion-handler) - - [onFailure(messageID:,error:) method](#on-failure-message-id-error-delete-message-completion-handler) -- [SendFileCompletionHandler protocol](#send-file-completion-handler) - - [onSuccess(messageID:) method](#on-success-message-id) - - [onFailure(messageID:,error:) method](#on-failure-message-id-error) -- [RateOperatorCompletionHandler protocol](#rate-operator-completion-handler) - - [onSuccess() method](#on-success) - - [onFailure(error:) method](#on-failure-error) -- [VisitSessionStateListener protocol](#visit-session-state-listener) - - [changed(state:to:)](#changed-state-previous-state-to-new-state-visit-session-state-listener) -- [DepartmentListChangeListener protocol](#department-list-change-listener) - - [received(departmentList:) method](#received-department-list) -- [LocationSettings protocol](#location-settings) - - [areHintsEnabled() method](#are-hints-enabled) -- [ChatStateListener protocol](#chat-state-listener) - - [changed(state:to:) method](#changed-state-previous-state-to-new-state) -- [CurrentOperatorChangeListener protocol](#current-operator-change-listener) - - [changed(operator:to:) method](#changed-operator-previous-operator-to-new-operator) -- [OperatorTypingListener protocol](#operator-typing-listener) - - [onOperatorTypingStateChanged(isTyping:) method](#on-operator-typing-state-changed-is-typing) -- [LocationSettingsChangeListener protocol](#location-settings-shange-listener) - - [changed(locationSettings:to:) method](#changed-location-settings-previous-location-settings-to-new-location-settings) -- [OnlineStatusChangeListener protocol](#online-status-change-listener) - - [changed(onlineStatus:to:) method](#changed-session-online-status-previous-session-online-status-to-new-session-online-status) -- [UnreadByOperatorTimestampChangeListener protocol](#unread-by-operator-timestamp-change-listener) - - [changedUnreadByOperatorTimestampTo(newValue:) method](#changed-unread-by-operator-timestamp-to-new-value) -- [UnreadByVisitorMessageCountChangeListener protocol](#unread-by-visitor-message-count-change-listener) - - [changedUnreadByVisitorMessageCountTo(newValue:) method](#changed-unread-by-visitor-message-count-to-new-value) -- [UnreadByVisitorTimestampChangeListener protocol](#unread-by-visitor-timestamp-change-listener) - - [changedUnreadByVisitorTimestampTo(newValue:) method](#changed-unread-by-visitor-timestamp-to-new-value) -- [ChatState enum](#chat-state) - - [CHATTING case](#chatting) - - [CHATTING_WITH_ROBOT](#chatting-with-robot) - - [CLOSED_BY_OPERATOR case](#closed-by-operator) - - [CLOSED_BY_VISITOR case](#closed-by-visitor) - - [INVITATION case](#invitation) - - [NONE case](#none-chat-state) - - [QUEUE case](#queue) - - [UNKNOWN case](#unknown) -- [OnlineStatus enum](#session-online-status) - - [BUSY_OFFLINE case](#busy-offline) - - [BUSY_ONLINE case](#busy-online) - - [OFFLINE case](#offline) - - [ONLINE case](#online) - - [UNKNOWN case](#unknown-session-online-status) -- [VisitSessionState enum](#visit-session-state) - - [CHAT case](#chat-visit-session-state) - - [DEPARTMENT_SELECTION case](#department-selection) - - [IDLE case](#idle) - - [IDLE_AFTER_CHAT case](#idle-after-chat) - - [OFFLINE_MESSAGE case](#offline-message) - - [UNKNOWN case](#unknown-visit-session-state) -- [DataMessageError enum](#data-message-error) - - [UNKNOWN case](#unknown-data-message-error) - - [QUOTED_MESSAGE_CANNOT_BE_REPLIED case](#quoted-message-cannot-be-replied) - - [QUOTED_MESSAGE_FROM_ANOTHER_VISITOR case](#quoted-message-from-another-visitor) - - [QUOTED_MESSAGE_MULTIPLE_IDS case](#quoted-message-multiple-ids) - - [QUOTED_MESSAGE_REQUIRED_ARGUMENTS_MISSING case](#quoted-message-required-arguments-missing) - - [QUOTED_MESSAGE_WRONG_ID case](#quoted-message-wrong-id) -- [EditMessageError enum](#edit-message-error) - - [UNKNOWN case](#unknown-edit-message-error) - - [NOT_ALLOWED case](#not-allowed-edit-message-error) - - [MESSAGE_EMPTY case](#message_empty-edit-message-error) - - [MESSAGE_NOT_OWNED case](#message-not-owned-edit-message-error) - - [MAX_LENGTH_EXCEEDED case](#max-length-exceeded-edit-message-error) - - [WRONG_MESSAGE_KIND case](#wrong-message-kind-edit-message-error) -- [DeleteMessageError enum](#delete-message-error) - - [UNKNOWN case](#unknown-delete-message-error) - - [NOT_ALLOWED case](#not-allowed-delete-message-error) - - [MESSAGE_NOT_OWNED case](#message-not-owned-delete-message-error) - - [MESSAGE_NOT_FOUND](#message-not-found-delete-message-error) -- [SendFileError enum](#send-file-error) - - [FILE_SIZE_EXCEEDED case](#file-size-exceeded) - - [FILE_TYPE_NOT_ALLOWED case](#file-type-not-allowed) - - [UPLOADED_FILE_NOT_FOUND case](#uploaded-file-not-found) - - [UNKNOWN case](#file-sending-unknown) -- [RateOperatorError enum](#rate-operator-error) - - [NO_CHAT case](#no-chat) - - [WRONG_OPERATOR_ID case](#wrong-operator-id) -- [MessageTracker protocol](#message-tracker) -- [getLastMessages(byLimit:completion:) method](#get-last-messages-by-limit-limit-of-messages-completion) -- [getNextMessages(byLimit:completion:) method](#get-next-nessages-by-limit-limit-of-messages-completion) - - [getAllMessages(completion:) method](#get-all-messages-completion) - - [resetTo(message:) method](#reset-to-message) - - [destroy() method](#destroy-message-tracker) -- [MessageListener protocol](#message-listener) - - [added(message:after:) method](#added-message-new-message-after-previous-message) - - [removed(message:) method](#removed-message) - - [removedAllMessages() method](#removed-all-messages) - - [changed(message:to:) method](#changed-message-old-version-to-new-version) -- [Message protocol](#message) - - [getAttachment() method](#get-attachment) - - [getData() method](#get-data) - - [getID() method](#get-id) - - [getOperatorID() method](#get-operator-id) - - [getSenderAvatarFullURL() method](#get-sender-avatar-full-url) - - [getSenderName() method](#get-sender-name) - - [getSendStatus() method](#get-send-status) - - [getText() method](#get-text) - - [getTime() method](#get-time) - - [getType() method](#get-type) - - [isEqual(to:) method](#is-equal-to-message) - - [isReadByOperator() method](#is-read-by-operator) - - [canBeEdited() method](#can-be-edited) -- [MessageAttachment protocol](#message-attachment) - - [getContentType() method](#get-content-type) - - [getFileName() method](#get-file-name) - - [getImageInfo() method](#get-image-info) - - [getSize() method](#get-size) - - [getURL() method](#get-url-string) -- [ImageInfo protocol](#image-info) - - [getThumbURL() method](#get-thumb-url-string) - - [getHeight() method](#get-height) - - [getWidth() method](#get-width) -- [MessageType enum](#message-type) - - [ACTION_REQUEST case](#action-request) - - [CONTACTS_REQUEST case](#contacts-request) - - [FILE_FROM_OPERATOR case](#file-from-operator) - - [FILE_FROM_VISITOR case](#file-from-visitor) - - [INFO case](#info) - - [OPERATOR case](#operator) - - [OPERATOR_BUSY case](#operator-busy) - - [VISITOR case](#visitor) -- [MessageSendStatus enum](#message-send-status) - - [SENDING case](#sending) - - [SENT case](#sent) -- [Department protocol](#department) - - [getKey() method](#get-key) - - [getName() method](#get-name-department) - - [getDepartmentOnlineStatus() method](#get-department-online-status) - - [getOrder() method](#get-order) - - [getLocalizedNames() method](#get-localized-names) - - [getLogo() method](#get-logo) -- [DepartmentOnlineStatus enum](#department-online-status) - - [BUSY_OFFLINE case](#busy-offline-department-online-status) - - [BUSY_ONLINE case](#busy-online-department-online-status) - - [OFFLINE case](#offline-department-online-status) - - [ONLINE case](#online-department-online-status) - - [UNKNOWN case](#unknown-department-online-status) -- [Operator protocol](#operator-protocol) - - [getID() method](#get-id-operator) - - [getName() method](#get-name) - - [getAvatarURL() method](#get-avatar-url) -- [WebimRemoteNotification protocol](#webim-remote-notification) - - [getType() method](#get-type-webim-remote-notification) - - [getEvent() method](#get-event) - - [getParameters() method](#get-parameters) -- [NotificationType enum](#notification-type) - - [CONTACT_INFORMATION_REQUEST](#contact-information-request) - - [OPERATOR_ACCEPTED case](#operator-accepted) - - [OPERATOR_FILE case](#operator-file) - - [OPERATOR_MESSAGE case](#operator-message) - - [WIDGET case](#widget) -- [NotificationEvent enum](#notification-event) - - [ADD case](#add) - - [DELETE case](#delete) -- [FatalErrorHandler protocol](#fatal-error-handler) - - [on(error:) method](#on-error) -- [FatalErrorType enum](#fatal-error-type) - - [ACCOUNT_BLOCKED case](#account-blocked) - - [NO_CHAT case](#no-chat) - - [PROVIDED_VISITOR_FIELDS_EXPIRED case](#provided-visitor-fields-expired) - - [UNKNOWN case](#unknown-fatal-error-type) - - [VISITOR_BANNED case](#visitor-banned) - - [WRONG_PROVIDED_VISITOR_HASH case](#wrong-provided-visitor-hash) -- [WebimError protocol](#webim-error) - - [getErrorType() method](#get-error-type) - - [getErrorString() method](#get-error-string) -- [AccessError enum](#access-error) - - [INVALID_THREAD case](#invalid-thread) - - [INVALID_SESSION case](#invalid-session) -- [WebimLogger protocol](#webim-logger) - - [log(entry:) method](#log-entry) - -

Webim class

- -Set of static methods which are used for session object creating and working with remote notifications that are sent by _Webim_ service. - -

Class method newSessionBuilder()

- -Returns [SessionBuilder class](#session-builder) instance that is necessary to create `WebimSession` class instance. - -

Class method parse(remoteNotification:visitorId)

- -Converts _iOS_ remote notification object into [WebimRemoteNotification](#webim-remote-notification) object. -`remoteNotification` parameter takes `[AnyHashable: Any]` dictionary (which can be taken inside `application(_ application:,didReceiveRemoteNotification userInfo:)` `AppDelegate` class method from `userInfo` parameter). -Method can return `nil` if `remoteNotification` parameter value doesn't fit to _Webim_ service remote notification format or if it doesn't contain any useful payload or visitor ID from notification doesn't equals `visitorId `. -Preliminarily you can call [method isWebim(remoteNotification:)](#is-webim-remote-notification) on this value to know if this notification is send by _Webim_ service. - -

Class method isWebim(remoteNotification:)

- -Allows to know if particular remote notification object represents Webim service remote notification. -`remoteNotification` parameter takes `[AnyHashable: Any]` dictionary (which can be taken inside `application(_ application:,didReceiveRemoteNotification userInfo:)` `AppDelegate` class method from `userInfo` parameter). -Returns `true` or `false`. - -

RemoteNotificationSystem enum

- -Enumerates push notifications systems that can be used with _WebimClientLibrary_. Enum values are used to be passed to [method set(remoteNotificationSystem:)](#set-remote-notification-system) [SessionBuilder class](#session-builder) instance method. - -

APNS case

- -_Apple Push Notification System_. - -

NONE case

- -App does not receive remote notification from _Webim_ service. - -[Go to table of contents](#table-of-contents) - -

SessionBuilder class

- -Instance of this class is used to get [WebimSession](#webim-session) object. [SessionBuilder class](#session-builder) instance can be retreived with [newSessionBuilder()](#new-session-builder) [Webim class](#webim) method. - -

Instance method set(accountName:)

- -Sets _Webim_ service account name. -`accountName` parameter – `String`-typed account name. Usually is represented by server URL (e.g. "https://demo.webim.ru"), but also can be just one word (e.g. "demo") -Returns `self` with account name set. -Method is mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(location:)

- -Sets [location](https://webim.ru/help/help-terms/) name for the session. -`location` parameter – `String`-typed location name. Usually default available location names are "mobile" and "default". To create any other one you can contact service support. -Returns `self` with location name set. -Method is mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(prechat:)

-Sets prechat fields for the session. -`prechat` parameter – `String`-typed prechat fields in JSON format. -Returns `self` with location name set. -Method is mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(appVersion:)

- -Sets app version number if it is necessary to differentiate its values inside _Webim_ service. -`appVersion` parameter – optional `String`-typed app version. -Returns `self` with app version set. When passed `nil` it does nothing. -Method is not mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(visitorFieldsJSONString:)

- -Sets visitor authorization data. -Without this method calling a visitor is anonymous, with randomly generated ID. This ID is saved inside app UserDefaults and can be lost (e.g. when app is uninstalled), thereby message history is lost too. -Authorized visitor data are saved by server and available with any device. -`jsonString` parameter – _JSON_-formatted `String`-typed [visitor fields](https://webim.ru/help/identification/). -Returns `self` with visitor authorization data set. -Method is not mandatory to create [WebimSession](#webim-session) object. -Can't be used simultanously with [set(providedAuthorizationTokenStateListener:,providedAuthorizationToken:) method](#set-provided-authorization-token-state-listener-provided-authorization-token). - -

Instance method set(visitorFieldsJSONData:)

- -Absolutely similar to [method set(visitorFieldsJSONString jsonString:)](#set-visitor-fields-json-string-json-string). -`jsonData` parameter – _JSON_-formatted `Data`-typed [visitor fields](https://webim.ru/help/identification/). - -

Instance method set(providedAuthorizationTokenStateListener:providedAuthorizationToken:)

- -When client provides custom visitor authorization mechanism, it can be realised by providing custom authorization token which is used instead of visitor fields. -Method sets [ProvidedAuthorizationTokenStateListener](#provided-authorization-token-state-listener) object and provided authorization token. Setting custom token is optional, if is not set, library generates its own. -Returns `self` with visitor authorization data set. -Method is not mandatory to create [WebimSession](#webim-session) object. -Can't be used simultaneously with [set(visitorFieldsJSONString:)](#set-visitor-fields-json-string-json-string) or [set(visitorFieldsJSONString:)](#set-visitor-fields-json-data-json-data). - -

Instance method set(pageTitle:)

- -Sets chat title which is visible by an operator. Default value is "iOS Client" -`pageTitle` – `String`-typed chat title. -Returns `self` with chat title set. -Method is not mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(fatalErrorHandler:)

- -Sets [FatalErrorHandler](#fatal-error-handler) object for session. -`fatalErrorHandler` parameter – any object of a class or struct that conforms to `FatalErrorHandler` protocol (or `nil`). -Returns `self` with `FatalErrorHandler` set. When `nil` passed it does nothing. -Method is not mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(remoteNotificationSystem:)

- -Sets remote notification system to use for receiving push notifications from _Webim_ service. -`remoteNotificationSystem` parameter – [RemoteNotificationSystem](#remote-notification-system) enum value. If parameter value is not [NONE](#none), [set(deviceToken:)](#set-device-token) method is mandatory to be called too. With [NONE](#none) value passed it does nothing. -Method is not mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(deviceToken:)

- -Sets device token for push notification receiving. -`deviceToken` parameter – `String`-typed device token in hexadecimal format and without any spaces and service symbols. -Code example to convert device token to the right format: -```` -let deviceToken = deviceToken.map { String(format: "%02.2hhx", $0) }.joined() -```` -Returns `self` with device token set. -For the proper remote notifications configuration this method call is not sufficient. You have to call `set(remoteNotificationSystem:)` method too. -Method is not mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(isLocalHistoryStoragingEnabled:)

- -By default session saves message history inside SQLite DB file. To deactivate this functionality you can use this method with false parameter isLocalHistoryStoragingEnabled value (with true value passed it does nothing). -Returns `self` with the functionality activation setting. -Method is not mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(isVisitorDataClearingEnabled:)

- -Sets necesarity to clear all visitor data before session is created. -With false `isVisitorDataClearingEnabled` parameter value passed it does nothing. -Returns `self` with the functionality activation setting. -Method is not mandatory to create [WebimSession](#webim-session) object. - -

Instance method set(webimLogger:verbosityLevel:)

- -Method to pass [WebimLogger](#webim-logger) object. -Parameter `verbosityLevel` – [WebimLoggerVerbosityLevel](#webim-logger-verbosity-level) case (can be skipped). -Returns `self` with the functionality activation setting. -Method is not mandatory to create [WebimSession](#webim-session) object. - -

Instance method build()

- -Final method that returns [WebimSession](#webim-session) object. -Can throw errors of [SessionBuilderError](#session-builder-error) type. -The only two mandatory method to call preliminarily are [set(accountName:)](#set-account-name) and [set(location:)](#set-location). - -

WebimLoggerVerbosityLevel enum

- -Verbosity level of [WebimLogger](#webim-logger). - -

VERBOSE case

- -All available information will be delivered to [WebimLogger](#webim-logger) instance with maximum verbosity level: -* session network setup parameters; -* network requests' URLs, HTTP method and parameters; -* network responses' HTTP codes, received data and errors; -* SQL queries and errors; -* full debug information and additional notes. - -

DEBUG case

- -All information which is useful when debugging will be delivered to [WebimLogger](#webim-logger) instance with necessary verbosity level: -* session network setup parameters; -* network requests' URLs, HTTP method and parameters; -* network responses' HTTP codes, received data and errors; -* SQL queries and errors; -* moderate debug information. - -

INFO case

- -Reference information and all warnings and errors will be delivered to [WebimLogger](#webim-logger) instance: -* network requests' URLS, HTTP method and parameters; -* HTTP codes and errors descriptions of failed requests. -* SQL errors. - -

WARNING case

- -Errors and warnings only will be delivered to [WebimLogger](#webim-logger) instance: -* network requests' URLs, HTTP method, parameters, HTTP code and error description. -* SQL errors. - -

ERROR case

- -Only errors will be delivered to [WebimLogger](#webim-logger) instance: -* network requests' URLs, HTTP method, parameters, HTTP code and error description. - -

SessionBuilderError enum

- -Error types that can be throwed by [SessionBuilder](#session-builder) [method build()](#build). - -

NIL_ACCOUNT_NAME case

- -Error that is thrown when trying to create session object with `nil` account name. - -

NIL_LOCATION case

- -Error that is thrown when trying to create session object with `nil` location name. - -

INVALID_AUTHENTICATION_PARAMETERS case

- -Error that is thrown when trying to use standard and custom visitor fields authentication simultaneously. - -

INVALID_REMOTE_NOTIFICATION_CONFIGURATION case

- -Error that is thrown when trying to create session object with invalid remote notifications configuration. - -[Go to table of contents](#table-of-contents) - -

ProvidedAuthorizationTokenStateListener protocol

- -When client provides custom visitor authorization mechanism, it can be realised by providing custom authorization token which is used instead of visitor fields. -When provided authorization token is generated (or passed to session by client app), `update(providedAuthorizationToken:)` method is called. This method call indicates that client app must send provided authorisation token to its server which is responsible to send it to Webim service. -This mechanism can't be used as is. It requires that client server to support this mecahnism. - -

update(providedAuthorizationToken:) method

- -Method is called in two cases: -1. Provided authorization token is genrated (or set by client app) and must be sent to client server which is responsible to send it to Webim service. -2. Passed provided authorization token is not valid. Provided authorization token can be invalid if Webim service did not receive it from client server yet. -When this method is called, client server must send provided authorization token to Webim service. -`providedAuthorizationToken` parameter contains provided authentication token which is set and which must be sent to _Webim_ service by client server. - -[Go to table of contents](#table-of-contents) - -

WebimSession protocol

- -Provides methods to manipulate with [WebimSession](#webim-session) object. - -

resume() method

- -Resumes session networking -Session is created as paused. To start using it firstly you should call this method. -Can throw errors of [AccessError](#access-error) type. - -

pause() method

- -Pauses session networking. If is already paused the method does nothing. -Can throw errors of [AccessError](#access-error) type. - -

destroy() method

- -Deactivates session. After that any session methods are not available. -Can throw errors of [AccessError](#access-error) type. - -

destroyWithClearVisitorData() method

- -Deactivates session, performing a cleanup. After that any session methods are not available. -Can throw errors of [AccessError](#access-error) type. - - -

getStream() method

- -Returns [MessageStream](#message-stream) object attached to this session. Each invocation of this method returns the same object. - -

change(location:) method

- -Changes [location](https://webim.ru/help/help-terms/) without creating a new session. -`location` parameter – new location name of `String` type. -Can throw errors of [AccessError](#access-error) type. - -

set(deviceToken:) method

- -Sets device token. - -[Go to table of contents](#table-of-contents) - -

MessageStream protocol

- -Provides methods to interact with _Webim_ service. - -

getVisitSessionState() method

- -Returns current session state ([VisitSessionState type](#visit-session-state). - -

getChatState() method

- -Returns current chat state of [ChatState](#chat-state) type. - -

getUnreadByOperatorTimestamp() method

- -Returns timestamp (of type `Date`) after which all chat messages are unread by operator (at the moment of last server update recieved). - -

getUnreadByVisitorMessageCount() method

- -Returns unread by visitor message count. - -

getUnreadByVisitorTimestamp() method

- -Returns timestamp (of type `Date`) after which all chat messages are unread by visitor (at the moment of last server update recieved) or `nil` if there's no unread by visitor messages. - -

getDepartmentList() method

- -Returns array of departments ([Department](#department)) or `nil` if there're any or department list is not recieved yet. - -

getLocationSettings() method

- -Returns current [LocationSettings](#location-settings) object. - -

getCurrentOperator() method

- -Returns [Operator](#operator-protocol) object of the current chat or `nil` if one does not exist. - -

getLastRatingOfOperatorWith(id:) method

- -Returns previous rating of the operator or `0` if it was not rated before. -`id` parameter – `String`-typed ID of operator. - -

rateOperatorWith(id:byRating:completionHandler:) method

- -Rates an operator. -To get an ID of the current operator call [getCurrentOperator()](#get-current-operator). -`id` parameter – String-typed ID of the operator to be rated. Optional: if `nil` is passed, current chat operator will be rated. -`rating` parameter – a number in range (1...5) that represents an operator rating. If the number is out of range, rating will not be sent to a server. -`completionHandler` parameter – [RateOperatorCompletionHandler](#rate-operator-completion-handler) object. -Can throw errors of [AccessError](#access-error) type. - -

respondSentryCall(id:) method

- -Respond sentry call. -`id` parameter – String-typed ID of redirect to sentry message. -Can throw errors of [AccessError](#access-error) type. - -

startChat() method

- -Changes [ChatState](#chat-state) to [QUEUE](#queue). -Method call is not mandatory, send message or send file methods start chat automatically. If account settings provide automatic complimentary message it won't be sent before any "startChat" method or first sent message. -Can throw errors of [AccessError](#access-error) type. - -

startChat(firstQuestion:) method

- -Changes [ChatState](#chat-state) to [QUEUE](#queue). Starts chat and sends first message simultaneously. -Method call is not mandatory, send message or send file methods start chat automatically. If account settings provide automatic complimentary message it won't be sent before any "startChat" method or first sent message. -Can throw errors of [AccessError](#access-error) type. - -

startChat(customFields:) method

- -Changes [ChatState](#chat-state) to [QUEUE](#queue). Starts chat with custom fields. -Method call is not mandatory. Starts chat with custom fields. -`customFields` paramater – String-typed custom fields in JSON format. -Can throw errors of [AccessError](#access-error) type. - -

startChat(departmentKey:) method

- -Starts chat with particular department. Department is identified by `departmentKey` parameter (see [getKey()](#get-key) of [Department](#department) protocol) -Changes [ChatState](#chat-state) to [QUEUE](#queue). -In most cases method call is not mandatory, send message or send file methods start chat automatically. But it is mandatory when [VisitSessionState](#visit-session-state) is in [DEPARTMENT_SELECTION state](#department-selection). -If account settings provide automatic complimentary message it won't be sent before any "startChat" method or first sent message. -Can throw errors of [AccessError](#access-error) type. - -

startChat(departmentKey:firstQuestion:) method

- -Starts chat with particular department and sends first message simultaneously. Department is identified by `departmentKey` parameter (see [getKey()](#get-key) of [Department](#department) protocol) -Changes [ChatState](#chat-state) to [QUEUE](#queue). -In most cases method call is not mandatory, send message or send file methods start chat automatically. But it is mandatory when [VisitSessionState](#visit-session-state) is in [DEPARTMENT_SELECTION state](#department-selection). -If account settings provide automatic complimentary message it won't be sent before any "startChat" method or first sent message. -Can throw errors of [AccessError](#access-error) type. - -

startChat(firstQuestion:customFields:) method

- -Starts chat with custom fields and sends first message simultaneously. -Changes [ChatState](#chat-state) to [QUEUE](#queue). -If account settings provide automatic complimentary message it won't be sent before any "startChat" method or first sent message. -Can throw errors of [AccessError](#access-error) type. - -

startChat(departmentKey:customFields:) method

- -Starts chat with particular department and custom fields. Department is identified by `departmentKey` parameter (see [getKey()](#get-key) of [Department](#department) protocol) -Changes [ChatState](#chat-state) to [QUEUE](#queue). -In most cases method call is not mandatory, send message or send file methods start chat automatically. But it is mandatory when [VisitSessionState](#visit-session-state) is in [DEPARTMENT_SELECTION state](#department-selection). -If account settings provide automatic complimentary message it won't be sent before any "startChat" method or first sent message. -Can throw errors of [AccessError](#access-error) type. - -

startChat(departmentKey:firstQuestion:customFields:) method

- -Starts chat with particular department and customFields and sends first message simultaneously. Department is identified by `departmentKey` parameter (see [getKey()](#get-key) of [Department](#department) protocol) -Changes [ChatState](#chat-state) to [QUEUE](#queue). -In most cases method call is not mandatory, send message or send file methods start chat automatically. But it is mandatory when [VisitSessionState](#visit-session-state) is in [DEPARTMENT_SELECTION state](#department-selection). -If account settings provide automatic complimentary message it won't be sent before any "startChat" method or first sent message. -Can throw errors of [AccessError](#access-error) type. - -

closeChat() method

- -Changes [ChatState](#chat-state) to [CLOSED_BY_VISITOR](#closed-by-visitor). -Can throw errors of [AccessError](#access-error) type. - -

setVisitorTyping(draftMessage:) method

- -This method must be called whenever there is a change of the input field of a message transferring current content of a message as a parameter. When `nil` value passed it means that visitor stopped to type a message or deleted it. -When there's multiple calls of this method occured, draft message is sending to service one time per second. -Can throw errors of [AccessError](#access-error) type. - -

send(message:data:completionHandler:) method

- -Sends a text message. -When calling this method, if there is an active [MessageTracker](#message-tracker) object. [added(message newMessage:,after previousMessage:) method](#added-message-new-message-after-previous-message)) with a message [SENDING case](#sending) in the status is also called. -`message` parameter – `String`-typed message text. -`data` parameter is optional, custom message parameters dictionary. Note that this functionality does not work as is – server version must support it. -`completionHandler` parameter – optional [DataMessageCompletionHandler](#data-message-completion-handler) object. -Returns randomly generated `String`-typed ID of the message. -Can throw errors of [AccessError](#access-error) type. - -

send(message:isHintQuestion:) method

- -Sends a text message. -When calling this method, if there is an active [MessageTracker](#message-tracker) object. [added(message newMessage:,after previousMessage:) method](#added-message-new-message-after-previous-message)) with a message [SENDING case](#sending) in the status is also called. -`message` parameter – `String`-typed message text. -`isHintQuestion` parameter shows to server if a visitor chose a hint (true value) or wrote his own text (`false`). Optional to use. -Returns randomly generated `String`-typed ID of the message. -Can throw errors of [AccessError](#access-error) type. - -

send(file:filename:mimeType:completionHandler:) method

- -Sends a file message. -When calling this method, if there is an active [MessageTracker](#message-tracker) object. [added(message newMessage:,after previousMessage:) method](#added-message-new-message-after-previous-message)) with a message [SENDING case](#sending) in the status is also called. -`file` parameter – file represented in `Data` type. -`filename` parameter – file name of `String` type. -`mimeType` parameter – MIME type of the file to send of `String` type. -`completionHandler` parameter – optional [SendFileCompletionHandler](#send-file-completion-handler) object. -Returns randomly generated `String`-typed ID of the message. -Can throw errors of [AccessError](#access-error) type. - -

updateWidgetStatus(data:) method

- -Update widget status. The change is displayed by the operator.. -`data` parameter – JSON string with new widget status. -Can throw errors of [AccessError](#access-error) type. - -

edit(message:text:completionHandler:) method

- -Edits a text message. -Before calling this method recommended to find out the possibility of editing the message using [canBeEdited() method](#can-be-edited). -When calling this method, if there is an active [MessageTracker](#message-tracker) object. [changed(message:,to:) method](changed-message-old-version-to-new-version) with a message [SENDING case](#sending) in the status is also called. -`message` parameter – message in `Message` type. -`text` parameter – new message text of `String` type. -`completionHandler` parameter – optional [EditMessageCompletionHandler](#edit-message-completion-handler) object. -Returns true if message can be edited. -Can throw errors of [AccessError](#access-error) type. - -

edit(message:text:completionHandler:) method

- -Deletes a text message. -Before calling this method recommended to find out the possibility of editing the message using [canBeEdited() method](#can-be-edited). -When calling this method, if there is an active [MessageTracker](#message-tracker) object. [removed(message:) method](#removed-message) with a message [SENT case](#sent) in the status is also called. -`message` parameter – message in `Message` type. -`completionHandler` parameter – optional [DeleteMessageCompletionHandler](#delete-message-completion-handler) object. -Returns true if message can be deleted. -Can throw errors of [AccessError](#access-error) type. - -

setChatRead() method

- -Set chat has been read by visitor. -Can throw errors of [AccessError](#access-error) type. - -

set(prechatFields:) method

- -Sends prechat fields to server. -Can throw errors of [AccessError](#access-error) type. - -

newMessageTracker(messageListener:) method

- -Returns [MessageTracker](#message-tracker) object wich (via [getNextMessages(byLimit limitOfMessages:,completion:)](#get-next-nessages-by-limit-limit-of-messages-completion)) allows to request the messages from above in the history. Each next call [getNextMessages(byLimit limitOfMessages:,completion:)](#get-next-nessages-by-limit-limit-of-messages-completion) returns earlier messages in relation to the already requested ones. -Changes of user-visible messages (e.g. ever requested from [MessageTracker](#message-tracker)) are transmitted to [MessageListener](#message-listener). That is why [MessageListener](#message-listener) object is needed when creating [MessageTracker](#message-tracker). -For each [MessageStream](#message-stream) at every single moment can exist the only one active [MessageTracker](#message-tracker). When creating a new one at the previous there will be automatically called [destroy()](#destroy-message-tracker). -Can throw errors of [AccessError](#access-error) type. - -

set(visitSessionStateListener:) method

- -Sets [VisitSessionStateListener](#visit-session-state-listener) object to track changes of [VisitSessionState](#visit-session-state). - -

set(chatStateListener:) method

- -Sets [ChatStateListener](#chat-state-listener) object. - -

set(currentOperatorChangeListener:) method

- -Sets [CurrentOperatorChangeListener](#current-operator-change-listener) object. - -

set(departmentListChangeListener:) method

- -Sets [DepartmentListChangeListener](#department-list-change-listener) object to track changes of department list. - -

set(operatorTypingListener:) method

- -Sets [OperatorTypingListener](#operator-typing-listener) object. - -

set(locationSettingsChangeListener:) method

- -Sets [LocationSettingsChangeListener](#location-settings-shange-listener) object. - -

set(onlineStatusChangeListener:) method

- -Sets [OnlineStatusChangeListener](#session-online-status-change-listener) object. - -

set(unreadByOperatorTimestampChangeListener:) method

- -Sets [UnreadByOperatorTimestampChangeListener](#unread-by-operator-timestamp-change-listener) object. - -

set(unreadByVisitorMessageCountChangeListener:) method

- -Sets [UnreadByVisitorMessageCountChangeListener](#unread-by-visitor-message-count-change-listener) object. - -

set(unreadByVisitorTimestampChangeListener:) method

- -Sets [UnreadByVisitorTimestampChangeListener](#unread-by-visitor-timestamp-change-listener) object. - -[Go to table of contents](#table-of-contents) - -

DataMessageCompletionHandler protocol

- -Protocol which methods are called after [send(message:data:completionHandler:)](#send-message-data) method is finished. Must be adopted. - -

onSuccess(messageID:) method

- -Executed when operation is done successfully. -`messageID` parameter – ID of the appropriate message of `String` type. - -

onFailure(messageID:error:) method

- -Executed when operation is failed. -`messageID` parameter – ID of the appropriate message of `String` type. -`error` parameter – appropriate [DataMessageError](#data-message-error) value. - -[Go to table of contents](#table-of-contents) - -

EditMessageCompletionHandler protocol

- -Protocol which methods are called after [edit(message:text:completionHandler:)](#edit-message) method is finished. Must be adopted. - -

onSuccess(messageID:) method

- -Executed when operation is done successfully. -`messageID` parameter – ID of the appropriate message of `String` type. - -

onFailure(messageID:error:) method

- -Executed when operation is failed. -`messageID` parameter – ID of the appropriate message of `String` type. -`error` parameter – appropriate [EditMessageError](#edit-message-error) value. - -[Go to table of contents](#table-of-contents) - -

DeleteMessageCompletionHandler protocol

- -Protocol which methods are called after [delete(message:completionHandler:)](#delete-message) method is finished. Must be adopted. - -

onSuccess(messageID:) method

- -Executed when operation is done successfully. -`messageID` parameter – ID of the appropriate message of `String` type. - -

onFailure(messageID:error:) method

- -Executed when operation is failed. -`messageID` parameter – ID of the appropriate message of `String` type. -`error` parameter – appropriate [DeleteMessageError](#delete-message-error) value. - -[Go to table of contents](#table-of-contents) - -

SendFileCompletionHandler protocol

- -Protocol which methods are called after [send(file:filename:mimeType:completionHandler:)](#send-file-filename-mime-type-completion-handler) method is finished. Must be adopted. - -

onSuccess(messageID:) method

- -Executed when operation is done successfully. -`messageID` parameter – ID of the appropriate message of `String` type. - -

onFailure(messageID:error:) method

- -Executed when operation is failed. -`messageID` parameter – ID of the appropriate message of `String` type. -`error` parameter – appropriate [SendFileError](#send-file-error) value. - -[Go to table of contents](#table-of-contents) - -

RateOperatorCompletionHandler protocol

- -Protocol which methods are called after [rateOperatorWith(id:byRating:completionHandler:)](#rate-operator-with-id-by-rating-rating) method is finished. Must be adopted. - -

onSuccess() method

- -Executed when operation is done successfully. - -

onFailure(error:) method

- -Executed when operation is failed. -`error` parameter – appropriate [RateOperatorError](#rate-operator-error) value. - -[Go to table of contents](#table-of-contents) - -

VisitSessionStateListener protocol

- -Provides methods to track changes of [VisitSessionState](#visit-session-state) status. - -

changed(state:to:) method

- -Called when [VisitSessionState](#visit-session-state) status is changed. Parameters contain its previous and new values. - -[Go to table of contents](#table-of-contents) - -

DepartmentListChangeListener protocol

- -Provides methods to track changes in departments list. - -

received(departmentList:) method

- -Called when department list is received. Current department list passed inside `departmentList` parameter and presents array of [Department](#department) objects. - -[Go to table of contents](#table-of-contents) - -

LocationSettings protocol

- -Interface that provides methods for handling [LocationSettings](#location-settings) which are received from server. - -

areHintsEnabled() method

- -This method shows to an app if it should show hint questions to visitor. Returns `true` if an app should show hint questions to visitor, `false` otherwise. - -[Go to table of contents](#table-of-contents) - -

ChatStateListener protocol

- -Protocol that is to be adopted to track [ChatState](#chat-state) changes. - -

changed(state:to:) method

- -Called during [ChatState](#chat-state)transition. Parameters are of [ChatState](#chat-state) type. - -[Go to table of contents](#table-of-contents) - -

CurrentOperatorChangeListener protocol

- -Protocol that is to be adopted to track if current [Operator](#operator-protocol) object is changed. - -

changed(operator:to:) method

- -Called when [Operator](#operator-protocol) object of the current chat changed. Values can be `nil` (if an operator leaved the chat or there was no operator before). - -[Go to table of contents](#table-of-contents) - -

OperatorTypingListener protocol

- -Protocol that is to be adopted to track if the operator started or ended to type a message. - -

onOperatorTypingStateChanged(isTyping:) method

- -Called when operator typing state changed. -Parameter `isTyping` is `true` if operator is typing, `false` otherwise. - -[Go to table of contents](#table-of-contents) - -

LocationSettingsChangeListener protocol

- -Interface that provides methods for handling changes in [LocationSettings](#location-settings). - -

changed(locationSettings:to:) method

- -Method called by an app when new [LocationSettings](#location-settings) object is received with parameters that represent previous and new [LocationSettings](#location-settings) objects. - -[Go to table of contents](#table-of-contents) - -

OnlineStatusChangeListener protocol

- -Interface that provides methods for handling changes of session status. - -

changed(onlineStatus:to:) method

- -Called when new session status is received with parameters that represent previous and new [OnlineStatus](#session-online-status) values. - -[Go to table of contents](#table-of-contents) - -

UnreadByOperatorTimestampChangeListener protocol

- -Interface that provides methods for handling changes of parameter that is to be returned by [getUnreadByOperatorTimestamp() method](#get-unread-by-operator-timestamp). -Can be set by [set(unreadByOperatorTimestampChangeListener:) method](#set-unread-by-operator-timestamp-change-listener). - -

changedUnreadByOperatorTimestampTo(newValue:) method

- -Method to be called when parameter that is to be returned by [getUnreadByOperatorTimestamp() method](#get-unread-by-operator-timestamp) method is changed. - -[Go to table of contents](#table-of-contents) - -

UnreadByVisitorMessageCountChangeListener protocol

- -Interface that provides methods for handling changes of parameter that is to be returned by [getUnreadByVisitorMessageCount() method](#get-unread-by-visitor-message-count). -Can be set by [set(unreadByVisitorMessageCountChangeListener:) method](#set-unread-by-visitor-message-count-change-listener). - -

changedUnreadByVisitorMessageCountTo(newValue:) method

- -Method to be called when parameter that is to be returned by [getUnreadByVisitorMessageCount() method](#get-unread-by-visitor-message-count) method is changed. - -[Go to table of contents](#table-of-contents) - -

UnreadByVisitorTimestampChangeListener protocol

- -Interface that provides methods for handling changes of parameter that is to be returned by [getUnreadByVisitorTimestamp() method](#get-unread-by-visitor-timestamp). -Can be set by [set(unreadByVisitorTimestampChangeListener:) method](#set-unread-by-visitor-timestamp-change-listener). - -

changedUnreadByVisitorTimestampTo(newValue:) method

- -Method to be called when parameter that is to be returned by [getUnreadByVisitorTimestamp() method](#get-unread-by-visitor-timestamp) method is changed. - -[Go to table of contents](#table-of-contents) - -

ChatState enum

- -A chat is seen in different ways by an operator depending on ChatState. -The initial state is [NONE](#none-chat-state). -Then if a visitor sends a message ([send(message:isHintQuestion:)](#send-message-is-hint-question)), the chat changes it's state to [QUEUE](#queue). The chat can be turned into this state by calling [startChat() method](#start-chat). -After that, if an operator takes the chat to process, the state changes to [CHATTING](#chatting). The chat is being in this state until the visitor or the operator closes it. -When closing a chat by the visitor [closeChat() method](#close-chat) it turns into the state [CLOSED_BY_VISITOR](#closed-by-visitor), by the operator - [CLOSED_BY_OPERATOR](#closed-by-operator). -When both the visitor and the operator close the chat, it's state changes to the initial – [NONE](#none-chat-state). A chat can also automatically turn into the initial state during long-term absence of activity in it. -Furthermore, the first message can be sent not only by a visitor but also by an operator. In this case the state will change from the initial to [INVITATION](#invitation), and then, after the first message of the visitor, it changes to [CHATTING](#chatting). - -

CHATTING case

- -Means that an operator has taken a chat for processing. -From this state a chat can be turned into: -* [CHATTING](#chatting), if an operator intercepted the chat; -* [CLOSED_BY_VISITOR](#closed-by-visitor), if a visitor closes the chat ([closeChat() method](#close-chat)); -* [NONE](#none-chat-state), automatically during long-term absence of activity. - -

CHATTING_WITH_ROBOT case

- -Means that chat is picked up by a bot. -From this state a chat can be turned into: -* [CLOSED_BY_OPERATOR](#closed-by-operator), if an operator closes the chat; -* [CLOSED_BY_VISITOR](#closed-by-visitor), if a visitor closes the chat ([closeChat() method](#close-chat)); -* [NONE](#none-chat-state), automatically during long-term absence of activity. - -

CLOSED_BY_OPERATOR case

- -Means that an operator has closed the chat. -From this state a chat can be turned into: -* [NONE](#none-chat-state), if the chat is also closed by a visitor ([closeChat() method](#close-chat)), or automatically during long-term absence of activity; -* [QUEUE](#queue), if a visitor sends a new message ([send(message:isHintQuestion:) method](#send-message-is-hint-question)). - -

CLOSED_BY_VISITOR case

- -Means that a visitor has closed the chat. -From this state a chat can be turned into: -* [NONE](#none-chat-state), if the chat is also closed by an operator or automatically during long-term absence of activity; -* [QUEUE](#queue), if a visitor sends a new message ([send(message:isHintQuestion:) method](#send-message-is-hint-question)). - -

INVITATION case

- -Means that a chat has been started by an operator and at this moment is waiting for a visitor's response. -From this state a chat can be turned into: -* [CHATTING](#chatting), if a visitor sends a message ([send(message:isHintQuestion:) method](#send-message-is-hint-question)); -* [NONE](#none-chat-state), if an operator or a visitor closes the chat ([closeChat() method](#close-chat)). - -

NONE case

- -Means the absence of a chat as such, e.g. a chat has not been started by a visitor nor by an operator. -From this state a chat can be turned into: -* [QUEUE](#queue), if the chat is started by a visitor (by the first message or by calling [startChat() method](#start-chat)); -* [INVITATION](#invitation), if the chat is started by an operator. - -

QUEUE case

- -Means that a chat has been started by a visitor and at this moment is being in the queue for processing by an operator. -From this state a chat can be turned into: -* [CHATTING](#chatting), if an operator takes the chat for processing; -* [NONE](#none-chat-state), if a visitor closes the chat (by calling ([closeChat() method](#close-chat)) before it is taken for processing; -* [CLOSED_BY_OPERATOR](#closed-by-operator), if an operator closes the chat without taking it for processing. - -

UNKNOWN case

- -The state is undefined. -This state is set as the initial when creating a new session, until the first response of the server containing the actual state is got. This state is also used as a fallback if _WebimClientLibrary_ can not identify the server state (e.g. if the server has been updated to a version that contains new states). - -[Go to table of contents](#table-of-contents) - -

OnlineStatus enum

- -Online state possible cases. - -

BUSY_OFFLINE case

- -Offline state with chats' count limit exceeded. -Means that visitor is not able to send messages at all. - -

BUSY_ONLINE case

- -Online state with chats' count limit exceeded. -Visitor is able send offline messages, but the server can reject it. - -

OFFLINE case

- -Visitor is able send offline messages. - -

ONLINE case

- -Visitor is able to send both online and offline messages. - -

UNKNOWN case

- -Session has not received first session status yet or session status is not supported by this version of the library. - -[Go to table of contents](#table-of-contents) - -

VisitSessionState enum

- -Session possible states. - -

CHAT case

- -Chat in progress. - -

DEPARTMENT_SELECTION case

- -Chat must be started with department selected (there was a try to start chat without department selected). - -

IDLE case

- -Session is active but no chat is occuring (chat was not started yet). - -

IDLE_AFTER_CHAT case

- -Session is active but no chat is occuring (chat was closed recently). - -

OFFLINE_MESSAGE case

- -Offline state. - -

UNKNOWN case

- -First status is not recieved yet or status is not supported by this version of the library. - -[Go to table of contents](#table-of-contents) - -

DataMessageError enum

- -Error types that could be passed in [onFailure(messageID:error:) method](#on-failure-message-id-error-data-message-completion-handler). - -

UNKNOWN case

- -Received error is not supported by current WebimClientLibrary version. - -

Quoted message errors.

- -

QUOTED_MESSAGE_CANNOT_BE_REPLIED case

- -To be raised when quoted message ID belongs to a message without `canBeReplied` flag set to `true` (this flag is to be set on the server-side). - -

QUOTED_MESSAGE_FROM_ANOTHER_VISITOR case

- -To be raised when quoted message ID belongs to another visitor chat. - -

QUOTED_MESSAGE_MULTIPLE_IDS case

- -To be raised when quoted message ID belongs to multiple messages (server data base error). - -

QUOTED_MESSAGE_REQUIRED_ARGUMENTS_MISSING case

- -To be raised when one or more required arguments of quoting mechanism are missing. - -

QUOTED_MESSAGE_WRONG_ID case

- -To be raised when wrong quoted message ID is sent. - -[Go to table of contents](#table-of-contents) - -

EditMessageError enum

- -Error types that could be passed in [onFailure(messageID:error:) method](#on-failure-message-id-error-edit-message-completion-handler). - -

UNKNOWN case

- -Received error is not supported by current WebimClientLibrary version. - -

NOT_ALLOWED case

- -Editing messages by visitor is turned off on the server. - -

MESSAGE_EMPTY case

- -Editing message is empty. - -

MESSAGE_NOT_OWNED case

- -Visitor can edit only his messages. The specified id belongs to someone else's message. - -

MAX_LENGTH_EXCEEDED case

- -The server may deny a request if the message size exceeds a limit. The maximum size of a message is configured on the server. - -

WRONG_MESSAGE_KIND case

- -Visitor can edit only text messages. - -[Go to table of contents](#table-of-contents) - -

DeleteMessageError enum

- -Error types that could be passed in [onFailure(messageID:error:) method](#on-failure-message-id-error-delete-message-completion-handler). - -

UNKNOWN case

- -Received error is not supported by current WebimClientLibrary version. - -

NOT_ALLOWED case

- -Editing messages by visitor is turned off on the server. - -

MESSAGE_NOT_OWNED case

- -Visitor can edit only his messages. The specified id belongs to someone else's message. - -

MESSAGE_NOT_FOUND case

- -Message with the specified id is not found in history. - -[Go to table of contents](#table-of-contents) - -

SendFileError enum

- -Error types that could be passed in [onFailure(messageID:error:) method](#on-failure-message-id-error). - -

FILE_SIZE_EXCEEDED case

- -The server may deny a request if the file size exceeds a limit. -The maximum size of a file is configured on the server. - -

FILE_TYPE_NOT_ALLOWED case

- -The server may deny a request if the file type is not allowed. -The list of allowed file types is configured on the server. - -

UPLOADED_FILE_NOT_FOUND case

- -Sending files in body is not supported. Use multipart form only. - -

UNKNOWN case

- -Received error is not supported by current WebimClientLibrary version. - -[Go to table of contents](#table-of-contents) - -

RateOperatorError enum

- -Error types that could be passed in [onFailure(error:) method](#on-failure-error). - -

NO_CHAT case

- -Arised when trying to send operator rating request if no chat is exists. - -

WRONG_OPERATOR_ID case

- -Arised when trying to send operator rating request if passed operator ID doesn't belong to existing chat operator (or, in the same place, chat doesn't have an operator at all). - -[Go to table of contents](#table-of-contents) - -

MessageTracker protocol

- -[MessageTracker](#message-tracker) object has two purposes: -- it allows to request the messages which are above in the history; -- it defines an interval within which message changes are transmitted to the listener (see [newMessageTracker(messageListener:) method](#new-message-tracker-message-listener)). - -

getLastMessages(byLimit:completion:) method

- -Requests last messages from history. Returns not more than `limitOfMessages` of messages. If an empty list is passed inside completion, there no messages in history yet. -If there is any previous [MessageTracker](#message-tracker) request that is not completed, or limit of messages is less than 1, or current [MessageTracker](#message-tracker) has been destroyed, this method will do nothing. -Following history request can be fulfilled by [getLastMessages(byLimit:completion:)](#get-last-messages-by-limit-limit-of-messages-completion) method. -Completion is called with received array of [Message](#message) objects as the parameter. It is guaranteed that completion will be called with empty or not result if call didn't throw an error. If current `MessageTracker` is destroyed completion will be called on empty result. -Can throw errors of [AccessError](#access-error) type. - -

getNextMessages(byLimit:completion:) method

- -Requests the messages above in history. Returns not more than `limitOfMessages` of messages. If an empty list is passed inside completion, the end of the message history is reached. -If there is any previous [MessageTracker](#message-tracker) request that is not completed, or limit of messages is less than 1, or current [MessageTracker](#message-tracker) has been destroyed, this method will do nothing. -Notice that this method can not be called again until the callback for the previous call will be invoked. -Completion is called with received array of [Message](#message) objects as the parameter. It is guaranteed that completion will be called with empty or not result if call didn't throw an error. If current `MessageTracker` is destroyed completion will be called on empty result. -Can throw errors of [AccessError](#access-error) type. - -

getAllMessages(completion:) method

- -Requests all messages from history. If an empty list is passed inside completion, there no messages in history yet. -If there is any previous [MessageTracker](#message-tracker) request that is not completed, or current [MessageTracker](#message-tracker) has been destroyed, this method will do nothing. -This method is totally independent on [getLastMessages(byLimit:completion:)](#get-last-messages-by-limit-limit-of-messages-completion) and [getNextMessages(byLimit:completion:)](#get-next-nessages-by-limit-limit-of-messages-completion) methods calls. -Completion is called with received array of [Message](#message) objects as the parameter. It is guaranteed that completion will be called with empty or not result if call didn't throw an error. If current `MessageTracker` is destroyed completion will be called on empty result. -Can throw errors of [AccessError](#access-error) type. - -

resetTo(message:) method

- -[MessageTracker](#message-tracker) retains some range of messages. By using this method one can move the upper limit of this range to another message. -If there is any previous [MessageTracker](#message-tracker) request that is not completed, this method will do nothing. -Notice that this method can not be used unless the previous call [getNextMessages(byLimit:completion:)](#get-next-nessages-by-limit-limit-of-messages-completion) was finished (completion handler was invoked). -Parameter `message` – [Message](#message) object reset to. -Can throw errors of [AccessError](#access-error) type. - -

destroy() method

- -Destroys the [MessageTracker](#message-tracker). It is impossible to use any [MessageTracker](#message-tracker) methods after it was destroyed. -Isn't mandatory to be called. - -[Go to table of contents](#table-of-contents) - -

MessageListener protocol

- -Should be adopted. Provides methods to track changes inside message stream. - -

added(message:after:) method

- -Called when added a new message. -If `previousMessage == nil` then it should be added to the end of message history (the lowest message is added), in other cases the message should be inserted before the message (i.e. above in history) which was given as a parameter `previousMessage`. -Notice that this is a logical insertion of a message. I.e. calling this method does not necessarily mean receiving a new (unread) message. Moreover, at the first call [getNextMessages(byLimit:completion:)](#get-next-nessages-by-limit-limit-of-messages-completion) most often the last messages of a local history (i.e. which is stored on a user's device) are returned, and this method will be called for each message received from a server after a successful connection. -Parameters are of type [Message](#message). `previousMessage` represents a message after which it is needed to make a message insert. If `nil` then an insert is performed at the end of the list. - -

removed(message:) method

- -Called when removing a message. -`message` parameter is of type [Message](#message). - -

removedAllMessages() method

- -Called when removed all the messages. - -

changed(message:to:) method

- -Called when changing a message. -[Message](#message) is an immutable type and field values can not be changed. That is why message changing occurs as replacing one object with another. Thereby you can find out, for example, which certain message fields have changed by comparing an old and a new object values. -Parameters are of type [Message](#message). - -[Go to table of contents](#table-of-contents) - -

Message protocol

- -Abstracts a single message in the message history. -A message is an immutable object. It means that changing some of the message fields creates a new object. Messages can be compared by using [isEqual(to:)](#is-equal-to-message) method for searching messages with the same set of fields or by ID (`message1.getID() == message2.getID()`) for searching logically identical messages. ID is formed on the client side when sending a message ([send(message:isHintQuestion:)](#send-message-is-hint-question) or [send(file:filename:mimeType:completionHandler:)](#send-file-filename-mime-type-completion-handler)). - -

getAttachment() method

- -Messages of the types [FILE_FROM_OPERATOR](#file-from-operator) and [FILE_FROM_VISITOR](#file-from-visitor) can contain attachments. -Returns [MessageAttachment](#message-attachment) object. Notice that this method may return nil even in the case of previously listed types of messages. E.g. if a file is being sent. - -

getData() method

- -Messages of type [ACTION_REQUEST](#action-request) contain custom dictionary. -Returns dictionary which contains custom fields or `nil` if there's no such custom fields. - -

getID() method

- -Every message can be uniquefied by its ID. Messages also can be lined up by its IDs. ID doesn’t change while changing the content of a message. -Returns unique ID of the message of type `String`. - -

getOperatorID() method

- -Returns ID of a message sender, if the sender is an operator, of type `String`. - -

getSenderAvatarFullURL() method

- -Returns `URL` of a sender's avatar or `nil` if one does not exist. - -

getSenderName() method

- -Returns name of a message sender of type `String`. - -

getSendStatus() method

- -Returns [SENT](#sent) if a message had been sent to the server, was received by the server and was delivered to all the clients; [SENDING](#sending) if not. - -

getText() method

- -Returns text of the message of type `String`. - -

getTime() method

- -Returns `Date` the message was processed by the server. - -

getType() method

- -Returns type of a message of [MessageType](#message-type) type. - -

isEqual(to:) method

- -Method which can be used to compare if two [Message](#message) objects have identical contents. -Returns `true` if two [Message](#message) objects are identical and `false` otherwise. - -Example code: -```` -if messageOne.isEqual(to: messageTwo) { /* … */ } -```` -Where `messageOne` and `messageTwo` are any `Message` objects. - -

isReadByOperator() method

- -Returns true if visitor message read by operator or this message is not by visitor and false otherwise. - -[Go to table of contents](#table-of-contents) - -

canBeEdited() method

- -Returns true if message can be edited and false otherwise. - -[Go to table of contents](#table-of-contents) - -

MessageAttachment protocol

- -Contains information about an attachment file. - -

getContentType() method

- -Returns MIME-type of an attachment file of optional `String` type. - -

getFileName() method

- -Returns name of an attachment file of optional `String` type. - -

getImageInfo() method

- -If a file is an image, returns [ImageInfo](#image-info) object; in other cases returns nil. - -

getSize() method

- -Returns attachment file size in bytes of `Int64` type. - -

getURLString() method

- -Returns `URL` of the file or `nil`. -Notice that this URL is short-living and is tied to a session. - -[Go to table of contents](#table-of-contents) - -

ImageInfo protocol

- -Provides information about an image. - -

getThumbURL() method

- -Returns a URL of an image thumbnail. -The maximum width and height is usually 300 px but it can be adjusted at server settings. -To get an actual preview size before file uploading is completed, use the following code: -```` -let THUMB_SIZE = 300 -var width = imageInfo.getWidth() -var height = imageInfo.getHeight() -if (height > width) { - width = (THUMB_SIZE * width) / height - height = THUMB_SIZE -} else { - height = (THUMB_SIZE * height) / width - width = THUMB_SIZE -} -```` -Notice that this URL is short-living and is tied to a session. - -

getHeight() method

- -Returns height of an image in pixels of `Int` type or `nil`. - -

getWidth() method

- -Returns width of an image in pixels of `Int` type or `nil`. - -[Go to table of contents](#table-of-contents) - -

MessageType enum

- -Message type representation. - -

ACTION_REQUEST case

- -A message from operator which requests some actions from a visitor. -E.g. choose an operator group by clicking on a button in this message. - -

CONTACTS_REQUEST case

-Message type that is received after operator clicked contacts request button. -There's no this functionality automatic support yet. All payload is transfered inside standard text field. - -

FILE_FROM_OPERATOR case

- -A message sent by an operator which contains an attachment. - -

FILE_FROM_VISITOR case

- -A message sent by a visitor which contains an attachment. - -

INFO case

- -A system information message. -Messages of this type are automatically sent at specific events. E.g. when starting a chat, closing a chat or when an operator joins a chat. - -

OPERATOR case

- -A text message sent by an operator. - -

OPERATOR_BUSY case

- -A system information message which indicates that an operator is busy and can't reply to a visitor at the moment. - -

VISITOR case

- -A text message sent by a visitor. - -[Go to table of contents](#table-of-contents) - -

MessageSendStatus enum

- -Until a message is sent to the server, is received by the server and is spreaded among clients, message can be seen as "being send"; at the same time `Message.getSendStatus()` will return [SENDING](#sending). In other cases - [SENT](#sent). - -

SENDING case

- -A message is being sent. - -

SENT case

- -A message had been sent to the server, received by the server and was spreaded among clients. - -[Go to table of contents](#table-of-contents) - -

Department protocol

- -Single department entity. Provides methods to get department information. -Department objects can be received through [DepartmentListChangeListener protocol](#department-list-change-listener) methods and [getDepartmentList() method](#get-department-list) of [MessageStream protocol](#message-stream). - -

getKey() method

- -Department key is used to start chat with some department. Presented by `String` object. -Used for [startChat(departmentKey:) method](#start-chat-department-key) of [MessageStream protocol](#message-stream) call. - -

getName() method

- -Returns department public name. Presented by `String` object. - -

getDepartmentOnlineStatus() method

- -Returns department online status. Presented by [DepartmentOnlineStatus](#department-online-status) object. - -

getOrder() method

- -Returns order number. -Presented by `Int` value. Higher numbers match higher priority. - -

getLocalizedNames() method

- -Returns dictionary of department localized names (if exists). -Presented by `[String: String]` dictonary. Key is custom locale descriptor, value is matching name. - - - -Returns department logo _URL_ (if exists). -Presented by `URL` object. - -[Go to table of contents](#table-of-contents) - -

DepartmentOnlineStatus enum

- -Possible department online statuses. -Can be retreived by [getDepartmentOnlineStatus() method](#get-department-online-status) of [Department protocol](#department). - -

BUSY_OFFLINE case

- -Offline state with chats' count limit exceeded. - -

BUSY_ONLINE case

- -Online state with chats' count limit exceeded. - -

OFFLINE case

- -Visitor is able to send offline messages. - -

ONLINE case

- -Visitor is able to send both online and offline messages. - -

UNKNOWN case

- -Any status that is not supported by this version of the library. - -[Go to table of contents](#table-of-contents) - -

Operator protocol

- -Presents chat operator object. - -

getID() method

- -Returns unique ID of the operator of `String` type. - -

getName() method

- -Returns display name of the operator of `String` type. - -

getAvatarURL() method

- -Returns `URL` of the operator’s avatar or `nil` if does not exist. - -[Go to table of contents](#table-of-contents) - -

WebimRemoteNotification protocol

- -Abstracts a remote notifications from _Webim_ service. - -

getType() method

- -Returns type of this remote notification of [NotificationType](#notification-type) type. - -

getEvent() method

- -Returns event of this remote notification of [NotificationEvent](#notification-event) type or `nil`. - -

getParameters() method

- -Returns parameters of this remote notification of array of type `String` type. Each [NotificationType](#notification-type) has specific list of parameters. - -[Go to table of contents](#table-of-contents) - -

NotificationType enum

- -Represents payload type of remote notification. - -

CONTACT_INFORMATION_REQUEST case

- -This notification type indicated that contact information request is sent to a visitor. - -Parameters: empty. - -

OPERATOR_ACCEPTED case

- -This notification type indicated that an operator has connected to a dialogue. - -Parameters: -* Operator's name. - -

OPERATOR_FILE case

- -This notification type indicated that an operator has sent a file. - -Parameters: -* Operator's name; -* File name. - -

OPERATOR_MESSAGE case

- -This notification type indicated that an operator has sent a text message. - -Parameters: -* Operator's name; -* Message text. - -

WIDGET case

- -This notification type indicated that an operator has sent a widget message. -This type can be received only if server supports this functionality. - -Parameters: empty. - -[Go to table of contents](#table-of-contents) - -

NotificationEvent enum

- -Represents meaned type of action when remote notification is received. - -

ADD case

- -Means that a notification should be added by current remote notification. - -

DELETE case

- -Means that a notification should be deleted by current remote notification. - -[Go to table of contents](#table-of-contents) - -

FatalErrorHandler protocol

- -Must be adopted to handle service errors that can occur. - -

on(error:) method

- -This method is to be called when Webim service error is received. -Notice that method called NOT FROM THE MAIN THREAD! - -`error` parameter is of [`WebimError` type](#webim-error). - -[Go to table of contents](#table-of-contents) - -

FatalErrorType enum

- -Webim service error types. -Mind that most of this errors causes session to destroy. - -

ACCOUNT_BLOCKED case

- -Indicates that the account in Webim service has been disabled (e.g. for non-payment). The error is unrelated to the user’s actions. -Recommended response is to show the user an error message with a recommendation to try using the chat later. - -Notice that the session will be destroyed if this error occured. - -

NO_CHAT case

- -Indicates that there was a try to perform action that requires existing chat, but there's no chat. -E.g. see [rateOperatorWith(id:,byRating rating:) method](#rate-operator-with-id-by-rating-rating) of [MessageStream protocol](#message-stream). - -

PROVIDED_VISITOR_FIELDS_EXPIRED case

- -Indicates an expired authorization of a visitor. -The recommended response is to re-authorize it and to re-create session object. - -Notice that the session will be destroyed if this error occured. - -

UNKNOWN case

- -Indicates the occurrence of an unknown error. -Recommended response is to send an automatic bug report and show to a user an error message with the recommendation to try using the chat later. - -Notice that the session will be destroyed if this error occured. - -

VISITOR_BANNED case

- -Indicates that a visitor was banned by an operator and can't send messages to a chat anymore. -Occurs when a user tries to open the chat or write a message after that. -Recommended response is to show the user an error message with the recommendation to try using the chat later or explain to the user that it was blocked for some reason. - -Notice that the session will be destroyed if this error occured. - -

WRONG_PROVIDED_VISITOR_HASH case

- -Indicates a problem of your application authorization mechanism and is unrelated to the user’s actions. -Occurs when trying to authorize a visitor with a non-valid signature. -Recommended response is to send an automatic bug report and show the user an error message with the recommendation to try using the chat later. - -Notice that the session will be destroyed if this error occured. - -[Go to table of contents](#table-of-contents) - -

WebimError protocol

- -Abstracts _Webim_ service possible fatal error. - -

getErrorType() method

- -Returns parsed type of the error of [FatalErrorType](#fatal-error-type) type. - -

getErrorString() method

- -Returns `String` representation of an error. Mostly useful if the error type is unknown. - -[Go to table of contents](#table-of-contents) - -

AccessError enum

- -Error types that can be throwed by [MessageStream](#message-stream) methods. - -

INVALID_THREAD case

- -Error that is thrown if the method was called not from the thread the [WebimSession](#webim-session) object was created in. - -

INVALID_SESSION case

- -Error that is thrown if [WebimSession](#webim-session) object was destroyed. - -[Go to table of contents](#table-of-contents) - -

WebimLogger protocol

- -Protocol that provides methods for implementing custom _WebimClientLibrary_ network requests logging. -It can be useful for debugging production releases if debug logs are not available. - -

log(entry:) method

- -Method which is called after new _WebimClientLibrary_ network request log entry came out. -New log entry passed inside `entry` parameter. diff --git a/ios/libs/Webim/Example/Podfile b/ios/libs/Webim/Example/Podfile deleted file mode 100755 index ff1312f..0000000 --- a/ios/libs/Webim/Example/Podfile +++ /dev/null @@ -1,49 +0,0 @@ -platform :ios, '9.0' - -use_frameworks! - -target 'WebimClientLibrary_Example' do - - pod 'WebimClientLibrary', :path => '../' - - pod 'Cosmos', '~> 16.0.0', :inhibit_warnings => true - pod 'Crashlytics' - pod 'Fabric' - pod 'SlackTextViewController', :inhibit_warnings => true - pod 'SnapKit', :inhibit_warnings => true - pod 'SQLite.swift', '0.11.5', :inhibit_warnings => true # WebimClientLibrary dependency – added to inhibit its warnings. - pod 'PopupDialog', '~> 0.6.2', :inhibit_warnings => true - - - target 'WebimClientLibrary_Tests' do - inherit! :search_paths - end - - post_install do |installer| - installer.pods_project.targets.each do |target| - if target.name =='WebimClientLibrary' - target.build_configurations.each do |config| - config.build_settings['SWIFT_VERSION'] = '4.2' - end - else - if target.name == 'Cosmos' || target.name == 'SnapKit' || target.name == 'WebimClientLibrary' - target.build_configurations.each do |config| - config.build_settings['SWIFT_VERSION'] = '4.0' - end - else - target.build_configurations.each do |config| - config.build_settings['SWIFT_VERSION'] = '3.2' - end - end - end - - target.build_configurations.each do |config| - if config.name == 'Debug' - config.build_settings['OTHER_SWIFT_FLAGS'] = ['$(inherited)', '-Onone'] - config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Owholemodule' - end - end - end - end - -end diff --git a/ios/libs/Webim/Example/Podfile.lock b/ios/libs/Webim/Example/Podfile.lock deleted file mode 100755 index b25b03c..0000000 --- a/ios/libs/Webim/Example/Podfile.lock +++ /dev/null @@ -1,51 +0,0 @@ -PODS: - - Cosmos (16.0.0) - - Crashlytics (3.13.0): - - Fabric (~> 1.10.0) - - Fabric (1.10.0) - - PopupDialog (0.6.2) - - SlackTextViewController (1.9.6) - - SnapKit (4.2.0) - - SQLite.swift (0.11.5): - - SQLite.swift/standard (= 0.11.5) - - SQLite.swift/standard (0.11.5) - - WebimClientLibrary (3.24.7): - - SQLite.swift (= 0.11.5) - -DEPENDENCIES: - - Cosmos (~> 16.0.0) - - Crashlytics - - Fabric - - PopupDialog (~> 0.6.2) - - SlackTextViewController - - SnapKit - - SQLite.swift (= 0.11.5) - - WebimClientLibrary (from `../`) - -SPEC REPOS: - https://github.com/cocoapods/specs.git: - - Cosmos - - Crashlytics - - Fabric - - PopupDialog - - SlackTextViewController - - SnapKit - - SQLite.swift - -EXTERNAL SOURCES: - WebimClientLibrary: - :path: "../" - -SPEC CHECKSUMS: - Cosmos: 7bcee0fa858a9355a214f2a181be5dffcee42c81 - Crashlytics: 1f5f752c7feac0add0cc1774756f96444fa3b1a7 - Fabric: 09de1e053eb7dc415593166ad3e53d4c88123405 - PopupDialog: d4336d7274a6aa3af4cb26d8b6691510eba90cc3 - SlackTextViewController: b854e62c1c156336bc4fd409c6ca79b5773e8f9d - SnapKit: fe8a619752f3f27075cc9a90244d75c6c3f27e2a - SQLite.swift: 6e5356850bb1791459f8c16d6ee9195b28714a2e - WebimClientLibrary: 70b569ce3f19b21b0e1f2488736d326c4c6cfd6f - -PODFILE CHECKSUM: f54174e617f57584e01671510a3b29c91c213194 - -COCOAPODS: 1.6.1 diff --git a/ios/libs/Webim/Example/Tests/AbstractRequestLoopTests.swift b/ios/libs/Webim/Example/Tests/AbstractRequestLoopTests.swift deleted file mode 100755 index db9e567..0000000 --- a/ios/libs/Webim/Example/Tests/AbstractRequestLoopTests.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// AbstractRequestLoopTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 30.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class AbstractRequestLoopTests: XCTestCase { - - // MARK: - Properties - private let abstractRequestLoop = AbstractRequestLoopForTests() - - // MARK: - Tests - - func testResume() { - abstractRequestLoop.resume() - abstractRequestLoop.pause() - abstractRequestLoop.resume() - - XCTAssertFalse(abstractRequestLoop.isPaused()) - } - - func testPause() { - abstractRequestLoop.resume() - abstractRequestLoop.pause() - - XCTAssertTrue(abstractRequestLoop.isPaused()) - } - -} - -// MARK: - Mocking AbstractRequestLoop -fileprivate final class AbstractRequestLoopForTests: AbstractRequestLoop { - - // MARK: - Methods - func isPaused() -> Bool { - return paused - } - -} diff --git a/ios/libs/Webim/Example/Tests/AccessCheckerTests.swift b/ios/libs/Webim/Example/Tests/AccessCheckerTests.swift deleted file mode 100755 index 40796f0..0000000 --- a/ios/libs/Webim/Example/Tests/AccessCheckerTests.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// AccessCheckerTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 21.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -@available(iOS 10.0, *) -class AccessCheckerTests: XCTestCase { - - func testCheckAccess() { - let thread1 = Thread.current - let sessionDestroyer = SessionDestroyer() - let accessChecker = AccessChecker(thread: thread1, - sessionDestroyer: sessionDestroyer) - - // MARK: Test 1 - let expectation = XCTestExpectation() - func mustThrow2() { - XCTAssertThrowsError(try accessChecker.checkAccess()) - expectation.fulfill() - } - let thread2 = Thread() { - mustThrow2() - } - thread2.start() - wait(for: [expectation], - timeout: 1.0) - - // MARK: Test 2 - sessionDestroyer.destroy() - XCTAssertThrowsError(try accessChecker.checkAccess()) - } - -} diff --git a/ios/libs/Webim/Example/Tests/ActionRequestLoopTests.swift b/ios/libs/Webim/Example/Tests/ActionRequestLoopTests.swift deleted file mode 100755 index c5fd4d6..0000000 --- a/ios/libs/Webim/Example/Tests/ActionRequestLoopTests.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// ActionRequestLoopTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 30.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class ActionRequestLoopTests: XCTestCase { - - // MARK: - Properties - private let actionRequestLoop = ActionRequestLoopForTests(completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: SessionDestroyer(), - queue: DispatchQueue.global()), - internalErrorListener: InternalErrorListenerForTests() as InternalErrorListener) - - // MARK: - Tests - func testStart() { - // MARK: Test 1 - - // When: ActionRequestLoop is started. - actionRequestLoop.start() - - // Then: ActionRequestLoop OperationQueue shouldn't be nil and has to have .userInitiated QoS. - let operationQueue = actionRequestLoop.operationQueue - XCTAssertNotNil(operationQueue) - XCTAssertEqual(operationQueue!.qualityOfService, - QualityOfService.userInitiated) - - // MARK: Test 2 - - // When: ActionRequestLoop is tryed to start again. - actionRequestLoop.start() - - // Then: ActionRequestLoop OperationQueue stays the same. - XCTAssertEqual(operationQueue, - actionRequestLoop.operationQueue) - } - - func testStop() { - // When: ActionRequestLoop is stopped. - actionRequestLoop.stop() - - // Then: ActionRequestLoop OperationQueue should be nil. - XCTAssertNil(actionRequestLoop.operationQueue) - } - -} diff --git a/ios/libs/Webim/Example/Tests/AuthorizationDataTests.swift b/ios/libs/Webim/Example/Tests/AuthorizationDataTests.swift deleted file mode 100755 index 814d43c..0000000 --- a/ios/libs/Webim/Example/Tests/AuthorizationDataTests.swift +++ /dev/null @@ -1,142 +0,0 @@ -// -// AuthorizationDataTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 31.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class AuthorizationDataTests: XCTestCase { - - // MARK: - Tests - - func testInitialization() { - // MARK: Test 1 - - // When: Page ID and authorization token are nil. - var pageID: String? = nil - var authorizationToken: String? = nil - var authorizationData = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken) - - // Then: Authorization data should be nil. - XCTAssertNil(authorizationData) - - // MARK: Test 2 - - // When: Authorization token is nil. - pageID = "page_id" - authorizationToken = nil - authorizationData = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken) - - // Then: Authorization data should be nil. - XCTAssertNil(authorizationData) - - // MARK: Test 3 - - // When: Authorization token is nil. - pageID = nil - authorizationToken = "auth_token" - authorizationData = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken) - - // Then: Authorization data should be nil. - XCTAssertNil(authorizationData) - - // MARK: Test 4 - - // When: Page ID and authorization token aren't nil. - pageID = "page_id" - authorizationToken = "auth_token" - authorizationData = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken) - - // Then: Authorization data shouldn't be nil. - XCTAssertNotNil(authorizationData) - XCTAssertEqual(authorizationData!.getPageID(), - "page_id") - XCTAssertEqual(authorizationData!.getAuthorizationToken(), - "auth_token") - } - - func testEquals() { - // MARK: Test 1 - - // When: Page IDs and authorization tokens are the same. - var pageID = "page_id" - var authorizationToken = "auth_token" - var authorizationData1 = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken) - var authorizationData2 = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken) - - // Then: Thwo AuthorizationData objects must be equal. - XCTAssertTrue(authorizationData1 == authorizationData2) - - // MARK: Test 2 - - // When: Page IDs are the same but authorization tokents aren't. - let pageID1 = "page_id1" - let pageID2 = "page_id2" - authorizationToken = "auth_token" - authorizationData1 = AuthorizationData(pageID: pageID1, - authorizationToken: authorizationToken) - authorizationData2 = AuthorizationData(pageID: pageID2, - authorizationToken: authorizationToken) - - // Then: Thwo AuthorizationData objects must be not equal. - XCTAssertTrue(authorizationData1 != authorizationData2) - - // MARK: Test 3 - - // When: Page IDs aren't the same but authorization tokents are. - pageID = "page_id" - let authorizationToken1 = "auth_token1" - let authorizationToken2 = "auth_token2" - authorizationData1 = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken1) - authorizationData2 = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken2) - - // Then: Thwo AuthorizationData objects must be not equal. - XCTAssertTrue(authorizationData1 != authorizationData2) - - // MARK: Test 4 - - // When: One AuthorizationData object is nil. - pageID = "page_id" - authorizationToken = "auth_token" - authorizationData1 = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken) - authorizationData2 = nil - - // Then: Thwo AuthorizationData objects must be not equal. - XCTAssertNotNil(authorizationData1) - XCTAssertNil(authorizationData2) - XCTAssertTrue(authorizationData1 != authorizationData2) - } - -} diff --git a/ios/libs/Webim/Example/Tests/ChatItemTests.swift b/ios/libs/Webim/Example/Tests/ChatItemTests.swift deleted file mode 100755 index 3a39de0..0000000 --- a/ios/libs/Webim/Example/Tests/ChatItemTests.swift +++ /dev/null @@ -1,230 +0,0 @@ -// -// ChatItemTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 15.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class ChatItemTests: XCTestCase { - - // MARK: - Constants - static let CHAT_ITEM_JSON_STRING = """ -{ - "readByVisitor" : true, - "category" : null, - "subject" : null, - "operatorTyping" : false, - "clientSideId" : "95f308d22be1a388c66e875fd71e466c", - "state" : "chatting", - "needToBeClosed" : false, - "visitorTyping" : null, - "messages" : [ - { - "avatar" : null, - "authorId" : null, - "ts" : 1518713140.778348, - "sessionId" : "72b6946234214a24b8d067a406ffcd53", - "id" : "72b6946234214a24b8d067a406ffcd53_2", - "text" : "Текст", - "kind" : "info", - "name" : "" - }, - { - "avatar" : null, - "authorId" : null, - "ts" : 1518713140.7789431, - "sessionId" : "72b6946234214a24b8d067a406ffcd53", - "id" : "72b6946234214a24b8d067a406ffcd53_3", - "text" : "Пожалуйста, подождите немного, к Вам присоединится оператор..", - "clientSideId" : "12af770c26754a5597ecd34b312ba758", - "kind" : "info", - "name" : "" - } - ], - "offline" : false, - "visitorMessageDraft" : null, - "id" : 2530, - "unreadByVisitorSinceTs" : null, - "operatorIdToRate" : { }, - "creationTs" : 1518713140.777204, - "subcategory" : null, - "requestedForm" : null, - "unreadByOperatorSinceTs" : null, - "operator" : { - "avatar" : "/webim/images/avatar/demo_33201.png", - "fullname" : "Administrator", - "id" : 33201, - "robotType" : null, - "departmentKeys" : [ - "telegram", - "test3", - "test2" - ], - "langToFullname" : { }, - "sip" : "10002715000033201" - } -} -""" - private static let MESSAGE_JSON_STRING = """ -{ - "avatar" : null, - "authorId" : null, - "ts" : 1518713140.778348, - "sessionId" : "72b6946234214a24b8d067a406ffcd53", - "id" : "72b6946234214a24b8d067a406ffcd53_2", - "text" : "Текст", - "kind" : "info", - "name" : "" -} -""" - private static let OPERATOR_JSON_STRING = """ -{ - "avatar" : "/webim/images/avatar/demo_33201.png", - "fullname" : "Administrator 2", - "id" : 33201, - "robotType" : null, - "departmentKeys" : [ - "telegram", - "test3", - "test2" - ], - "langToFullname" : { }, - "sip" : "10002715000033201" -} -""" - - // MARK: - Properties - private let chatItemDictionary = try! JSONSerialization.jsonObject(with: ChatItemTests.CHAT_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - - // MARK: - Tests - - func testInit() { - let chatItem = ChatItem(jsonDictionary: chatItemDictionary) - - XCTAssertFalse(chatItem.isOperatorTyping()) - XCTAssertEqual(chatItem.getState(), - ChatItem.ChatItemState.chatting) - XCTAssertEqual(chatItem.getOperator()!.getID(), - "33201") - XCTAssertTrue(chatItem.getReadByVisitor()!) - XCTAssertTrue(chatItem.getOperatorIDToRate()!.isEmpty) - XCTAssertNil(chatItem.getUnreadByVisitorTimestamp()) - XCTAssertNil(chatItem.getUnreadByOperatorTimestamp()) - XCTAssertTrue(chatItem.getOperatorIDToRate()!.isEmpty) - } - - func testGetSetMessages() { - let chatItem = ChatItem(jsonDictionary: chatItemDictionary) - - let messageDictionary = try! JSONSerialization.jsonObject(with: ChatItemTests.MESSAGE_JSON_STRING.data(using: .utf8)!, - options: []) as! [String: Any?] - let message = MessageItem(jsonDictionary: messageDictionary) - chatItem.set(messages: [message]) - - XCTAssertEqual(chatItem.getMessages(), - [message]) - } - - func testAddMessage() { - let chatItem = ChatItem(jsonDictionary: chatItemDictionary) - let messageDictionary = try! JSONSerialization.jsonObject(with: ChatItemTests.MESSAGE_JSON_STRING.data(using: .utf8)!, - options: []) as! [String: Any?] - let message = MessageItem(jsonDictionary: messageDictionary) - - chatItem.add(message: message, - atPosition: chatItem.getMessages().count) - XCTAssertTrue(message == chatItem.getMessages()[2]) - - chatItem.add(message: message) - XCTAssertTrue(message == chatItem.getMessages().last!) - } - - func testSetOperatorTyping() { - let chatItem = ChatItem(jsonDictionary: chatItemDictionary) - - XCTAssertFalse(chatItem.isOperatorTyping()) - - chatItem.set(operatorTyping: true) - XCTAssertTrue(chatItem.isOperatorTyping()) - } - - func testSetChatState() { - let chatItem = ChatItem(jsonDictionary: chatItemDictionary) - - XCTAssertEqual(chatItem.getState(), - ChatItem.ChatItemState.chatting) - - chatItem.set(state: .closed) - XCTAssertEqual(chatItem.getState(), - ChatItem.ChatItemState.closed) - } - - func testSetOperator() { - let chatItem = ChatItem(jsonDictionary: chatItemDictionary) - - XCTAssertEqual(chatItem.getOperator()?.getFullName(), - "Administrator") - - let operatorDictionary = try! JSONSerialization.jsonObject(with: ChatItemTests.OPERATOR_JSON_STRING.data(using: .utf8)!, - options: []) as! [String: Any?] - let operatorItem = OperatorItem(jsonDictionary: operatorDictionary)! - chatItem.set(operator: operatorItem) - XCTAssertEqual(chatItem.getOperator()?.getFullName(), - "Administrator 2") - } - - func testSetReadByVisitor() { - let chatItem = ChatItem(jsonDictionary: chatItemDictionary) - - XCTAssertTrue(chatItem.getReadByVisitor()!) - - chatItem.set(readByVisitor: false) - XCTAssertFalse(chatItem.getReadByVisitor()!) - } - - func testSetUnreadByOperatorTimestamp() { - let chatItem = ChatItem(jsonDictionary: chatItemDictionary) - chatItem.set(unreadByOperatorTimestamp: 1.0) - - XCTAssertEqual(chatItem.getUnreadByOperatorTimestamp(), - 1.0) - } - - // MARK: ChatItemState tests - - func testInitChatItemState() { - XCTAssertEqual(ChatItem.ChatItemState(withType: "new_state").rawValue, - "unknown") // Some unsupported value. - } - - func testIsClosed() { - let chatItemState = ChatItem.ChatItemState(withType: "chatting") - - XCTAssertFalse(chatItemState.isClosed()) - } - -} diff --git a/ios/libs/Webim/Example/Tests/ClientSideIDTests.swift b/ios/libs/Webim/Example/Tests/ClientSideIDTests.swift deleted file mode 100755 index 09ddcd6..0000000 --- a/ios/libs/Webim/Example/Tests/ClientSideIDTests.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// ClientSideIDTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 31.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class ClientSideIDTests: XCTestCase { - - // MARK: - Tests - - func testLength() { - let length = 10 - - XCTAssertEqual(ClientSideID.generateRandomString(ofCharactersNumber: length).count, - length) - } - - func testCorrectSymbols() { - var clientSideID = ClientSideID.generateClientSideID() - let letters = "abcdef0123456789" - for letter in letters { - clientSideID = clientSideID.replacingOccurrences(of: String(letter), - with: "", - options: [], - range: nil) - } - - XCTAssertTrue(clientSideID.count == 0) - } - -} diff --git a/ios/libs/Webim/Example/Tests/DeltaItemTests.swift b/ios/libs/Webim/Example/Tests/DeltaItemTests.swift deleted file mode 100755 index 1e260e0..0000000 --- a/ios/libs/Webim/Example/Tests/DeltaItemTests.swift +++ /dev/null @@ -1,91 +0,0 @@ -// -// DeltaItemTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class DeltaItemTests: XCTestCase { - - // MARK: - Tests - - func testInit() { - let deltaItemJSONString = """ -{ - "id" : "80a332f6fced40f290a5e8ace4a6d11c_5", - "data" : { - "avatar" : null, - "authorId" : null, - "ts" : 1519043833.694463, - "sessionId" : "80a332f6fced40f290a5e8ace4a6d11c", - "id" : "80a332f6fced40f290a5e8ace4a6d11c_5", - "text" : "10", - "clientSideId" : "fbaa9bb54d47008b5bf56a5830510c64", - "kind" : "visitor", - "name" : "Никита" - }, - "event" : "add", - "objectType" : "CHAT_MESSAGE" -} -""" - let deltaItemDictionary = try! JSONSerialization.jsonObject(with: deltaItemJSONString.data(using: .utf8)!, - options: []) as! [String : Any?] - let deltaItem = DeltaItem(jsonDictionary: deltaItemDictionary)! - - XCTAssertEqual(deltaItem.getDeltaType(), - DeltaItem.DeltaType.chatMessage) - XCTAssertEqual(deltaItem.getEvent(), - DeltaItem.Event.add) - XCTAssertEqual(deltaItem.getID(), - "80a332f6fced40f290a5e8ace4a6d11c_5") - XCTAssertNotNil(deltaItem.getData()) - } - - func testInitFails() { - let deltaItemJSONString = """ -{ - "id" : "80a332f6fced40f290a5e8ace4a6d11c_5", - "data" : { - "avatar" : null, - "authorId" : null, - "ts" : 1519043833.694463, - "sessionId" : "80a332f6fced40f290a5e8ace4a6d11c", - "id" : "80a332f6fced40f290a5e8ace4a6d11c_5", - "text" : "10", - "clientSideId" : "fbaa9bb54d47008b5bf56a5830510c64", - "kind" : "visitor", - "name" : "Никита" - }, - "objectType" : "CHAT_MESSAGE" -} -""" - let deltaItemDictionary = try! JSONSerialization.jsonObject(with: deltaItemJSONString.data(using: .utf8)!, - options: []) as! [String : Any?] - - XCTAssertNil(DeltaItem(jsonDictionary: deltaItemDictionary)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/DeltaRequestLoopTests.swift b/ios/libs/Webim/Example/Tests/DeltaRequestLoopTests.swift deleted file mode 100755 index 12a649b..0000000 --- a/ios/libs/Webim/Example/Tests/DeltaRequestLoopTests.swift +++ /dev/null @@ -1,147 +0,0 @@ -// -// DeltaRequestLoopTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 31.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class DeltaRequestLoopTests: XCTestCase { - - // MARK: - Properties - private var deltaRequestLoop: DeltaRequestLoopForTests? - - // MARK: - Methods - - override func setUp() { - super.setUp() - - deltaRequestLoop = DeltaRequestLoopForTests(deltaCallback: DeltaCallback(currentChatMessageMapper: CurrentChatMessageMapper(withServerURLString: "https://demo.webim.ru")), - completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: SessionDestroyer(), - queue: DispatchQueue.global()), - sessionParametersListener: nil, - internalErrorListener: InternalErrorListenerForTests() as InternalErrorListener, - baseURL: "https://demo.webim.ru", - title: "Page Title", - location: "mobile", - appVersion: "1.0.0", - visitorFieldsJSONString: nil, - providedAuthenticationTokenStateListener: nil, - providedAuthenticationToken: nil, - deviceID: "device_id", - deviceToken: nil, - visitorJSONString: nil, - sessionID: nil, - authorizationData: nil) - } - - override func tearDown() { - deltaRequestLoop = nil - - super.tearDown() - } - - // MARK: - Tests - - func testStart() { - // MARK: Test 1 - - // When: DeltaRequestLoop is started. - deltaRequestLoop!.start() - let queue = deltaRequestLoop!.queue - - // Then: Queue shouldn't be nil. - XCTAssertNotNil(queue) - - // MARK: Test 2 - - // When: DeltaRequestLoop is started again. - deltaRequestLoop!.start() - - // Then: Queue should remain the same. - XCTAssertEqual(deltaRequestLoop!.queue, - queue) - } - - func testStop() { - deltaRequestLoop!.start() - deltaRequestLoop!.stop() - - XCTAssertNil(deltaRequestLoop!.queue) - } - - func testChangeLocation() { - try? deltaRequestLoop?.change(location: "location") - - XCTAssertNil(deltaRequestLoop?.getAuthorizationData()) - XCTAssertEqual(deltaRequestLoop!.since, - 0) - XCTAssertTrue(deltaRequestLoop!.initializationRunned) - } - - func testRunMethod() { - // MARK: Test 1 - - // When: DeltaRequestLoop started without AuthorizationData. - deltaRequestLoop?.start() - usleep(1_000_000) - - // Then: Initialization should be requested, but delta should not. - XCTAssertNil(deltaRequestLoop?.getAuthorizationData()) - XCTAssertTrue(deltaRequestLoop!.initializationRunned) - XCTAssertFalse(deltaRequestLoop!.deltaRequestingRunned) - - // MARK: Test 2 - - // When: AuthorizationData is setted. - deltaRequestLoop?.authorizationData = AuthorizationData(pageID: "page_id", - authorizationToken: "auth_token") - usleep(1_000_000) - - // Then: Delta should be requested. - XCTAssertNotNil(deltaRequestLoop?.getAuthorizationData()) - XCTAssertTrue(deltaRequestLoop!.initializationRunned) - } - -} - -// MARK: Mocking DeltaRequestLoop -final fileprivate class DeltaRequestLoopForTests: DeltaRequestLoop { - - // MARK: - Properties - var initializationRunned = false - var deltaRequestingRunned = false - - // MARK: - Methods - - override func requestInitialization() { - initializationRunned = true - } - - override func requestDelta() { - deltaRequestingRunned = true - } - -} diff --git a/ios/libs/Webim/Example/Tests/DeltaResponseTests.swift b/ios/libs/Webim/Example/Tests/DeltaResponseTests.swift deleted file mode 100755 index 1fab76a..0000000 --- a/ios/libs/Webim/Example/Tests/DeltaResponseTests.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// DeltaResponseTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class DeltaResponseTests: XCTestCase { - - // MARK: - Constants - private static let DELTA_RESPONSE_JSON_STRING = """ -{ - "revision" : 12, - "deltaList" : [ - { - "id" : "80a332f6fced40f290a5e8ace4a6d11c", - "data" : null, - "event" : "upd", - "objectType" : "CHAT_OPERATOR" - }, - { - "id" : "80a332f6fced40f290a5e8ace4a6d11c", - "data" : "queue", - "event" : "upd", - "objectType" : "CHAT_STATE" - }, - { - "id" : "80a332f6fced40f290a5e8ace4a6d11c_8", - "data" : { - "avatar" : null, - "authorId" : null, - "ts" : 1519046868.2501681, - "sessionId" : "80a332f6fced40f290a5e8ace4a6d11c", - "id" : "80a332f6fced40f290a5e8ace4a6d11c_8", - "text" : "11", - "clientSideId" : "578150796321959ef8b445866738381b", - "kind" : "visitor", - "name" : "Никита" - }, - "event" : "add", - "objectType" : "CHAT_MESSAGE" - } - ] -} -""" - - // MARK: - Properties - private let deltaResponseDictionary = try! JSONSerialization.jsonObject(with: DeltaResponseTests.DELTA_RESPONSE_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - - // MARK: - Tests - func testInit() { - let deltaResponseItem = DeltaResponse(jsonDictionary: deltaResponseDictionary) - - XCTAssertEqual(deltaResponseItem.getRevision(), - 12) - XCTAssertNil(deltaResponseItem.getFullUpdate()) - XCTAssertEqual(deltaResponseItem.getDeltaList()!.count, - 3) - } - -} diff --git a/ios/libs/Webim/Example/Tests/DepartmentFactoryTests.swift b/ios/libs/Webim/Example/Tests/DepartmentFactoryTests.swift deleted file mode 100755 index f2eab30..0000000 --- a/ios/libs/Webim/Example/Tests/DepartmentFactoryTests.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// DepartmentFactoryTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 20.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class DepartmentFactoryTests: XCTestCase { - - // MARK: - Constants - private static let SERVER_URL_STRING = "https://demo.webim.ru" - - // MARK: - Properties - private let departmentFactory = DepartmentFactory(serverURLString: DepartmentFactoryTests.SERVER_URL_STRING) - private let departmentItemDictionary = try! JSONSerialization.jsonObject(with: DEPARTMENT_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - - // MARK: - Tests - func testConvert() { - let departmentItem = DepartmentItem(jsonDictionary: departmentItemDictionary)! - let department = departmentFactory.convert(departmentItem: departmentItem) - - XCTAssertEqual(department.getDepartmentOnlineStatus(), - DepartmentOnlineStatus.OFFLINE) - XCTAssertEqual(department.getKey(), - "mobile_test_1") - XCTAssertEqual(department.getLocalizedNames()!.count, - 1) - XCTAssertEqual(department.getLogoURL()!, - URL(string: DepartmentFactoryTests.SERVER_URL_STRING + "/webim/images/department_logo/wmtest2_1.png")!) - XCTAssertEqual(department.getName(), - "Mobile Test 1") - XCTAssertEqual(department.getOrder(), - 100) - } - -} diff --git a/ios/libs/Webim/Example/Tests/DepartmentItemTests.swift b/ios/libs/Webim/Example/Tests/DepartmentItemTests.swift deleted file mode 100755 index 36a9b06..0000000 --- a/ios/libs/Webim/Example/Tests/DepartmentItemTests.swift +++ /dev/null @@ -1,107 +0,0 @@ -// -// DepartmentItemTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 16.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -// MARK: - Global constants -let DEPARTMENT_ITEM_JSON_STRING = """ -{ - "localeToName" : { - "ru" : "Mobile Test 1" - }, - "key" : "mobile_test_1", - "online" : "offline", - "name" : "Mobile Test 1", - "order" : 100, - "logo" : "/webim/images/department_logo/wmtest2_1.png" -} -""" -let DEPARTMENT_ITEM_WITH_UNKNOWN_ONLINE_STATUS_JSON_STRING = """ -{ - "localeToName" : { - "ru" : "Mobile Test 1" - }, - "key" : "mobile_test_1", - "online" : "new_status", - "name" : "Mobile Test 1", - "order" : 100, - "logo" : "/webim/images/department_logo/wmtest2_1.png" -} -""" -let INCORRECT_DEPARTMENT_ITEM_JSON_STRING = """ -{ - "localeToName" : { - "ru" : "Mobile Test 1" - }, - "online" : "offline", - "name" : "Mobile Test 1", - "order" : 100, - "logo" : "/webim/images/department_logo/wmtest2_1.png" -} -""" - -class DepartmentItemTests: XCTestCase { - - // MARK: - Tests - - func testInit() { - let departmentItemDictionary = try! JSONSerialization.jsonObject(with: DEPARTMENT_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - let departmentItem = DepartmentItem(jsonDictionary: departmentItemDictionary) - - XCTAssertEqual(departmentItem!.getKey(), - "mobile_test_1") - XCTAssertEqual(departmentItem!.getName(), - "Mobile Test 1") - XCTAssertEqual(departmentItem!.getOnlineStatus(), - DepartmentItem.InternalDepartmentOnlineStatus.offline) - XCTAssertEqual(departmentItem!.getOrder(), - 100) - XCTAssertEqual(departmentItem!.getLocalizedNames()!, - ["ru" : "Mobile Test 1"]) - XCTAssertEqual(departmentItem!.getLogoURLString()!, - "/webim/images/department_logo/wmtest2_1.png") - } - - func testUnknownOnlineStatus() { - let departmentItemDictionary = try! JSONSerialization.jsonObject(with: DEPARTMENT_ITEM_WITH_UNKNOWN_ONLINE_STATUS_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - let departmentItem = DepartmentItem(jsonDictionary: departmentItemDictionary) - - XCTAssertEqual(departmentItem!.getOnlineStatus(), - DepartmentItem.InternalDepartmentOnlineStatus.unknown) - } - - func testInitFails() { - let departmentItemDictionary = try! JSONSerialization.jsonObject(with: INCORRECT_DEPARTMENT_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - - XCTAssertNil(DepartmentItem(jsonDictionary: departmentItemDictionary)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/ExampleTests/ChatViewControllerTests.swift b/ios/libs/Webim/Example/Tests/ExampleTests/ChatViewControllerTests.swift deleted file mode 100755 index 9156447..0000000 --- a/ios/libs/Webim/Example/Tests/ExampleTests/ChatViewControllerTests.swift +++ /dev/null @@ -1,87 +0,0 @@ -// -// ChatViewControllerTests.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 15.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit -import XCTest -@testable import WebimClientLibrary -@testable import WebimClientLibrary_Example - -class ChatViewControllerTests: XCTestCase { - - // MARK: - Properties - var chatViewController: ChatViewController! - - // MARK: - Methods - override func setUp() { - super.setUp() - - let storyboard = UIStoryboard(name: "Main", - bundle: nil) - chatViewController = storyboard.instantiateViewController(withIdentifier: "ChatViewController") as! ChatViewController - } - - // MARK: - Tests - - func testBackgroundViewNotEmpty() { - // When: Table view is empty. - let tableView = chatViewController.tableView! - tableView.reloadData() - - // Then: Table view background has the message. - let label = tableView.backgroundView as! UILabel - XCTAssertEqual(label.attributedText?.string, - "Send first message to start chat.") - } - - func testBackgroundViewEmpty() { - // MARK: Set up - var messages = [Message]() - for index in 0 ... 2 { - let message = MessageImpl(serverURLString: "http://demo.webim.ru/", - id: String(index), - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Sender name", - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: Int64(index), - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - messages.append(message as Message) - } - - // When: Table view is not empty. - chatViewController.set(messages: messages) - chatViewController.tableView?.reloadData() - - // Then: Table view background view is empty. - XCTAssertNil(chatViewController.tableView!.backgroundView) - } - -} diff --git a/ios/libs/Webim/Example/Tests/ExampleTests/DecodePercentEscapedLinksIfPresentTests.swift b/ios/libs/Webim/Example/Tests/ExampleTests/DecodePercentEscapedLinksIfPresentTests.swift deleted file mode 100755 index fd1d10e..0000000 --- a/ios/libs/Webim/Example/Tests/ExampleTests/DecodePercentEscapedLinksIfPresentTests.swift +++ /dev/null @@ -1,99 +0,0 @@ -// -// DecodePercentEscapedLinksIfPresentTests.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 31.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import WebimClientLibrary_Example -import XCTest - -class DecodePercentEscapedLinksIfPresentTests: XCTestCase { - - // MARK: - Tests - - func testNormalString() { - let initialString = "Normal string" - let expectedString = initialString - - XCTAssertEqual(initialString.decodePercentEscapedLinksIfPresent(), - expectedString) - } - - func testOneLinkWithoutPercentEscapingOnlyString() { - let initialString = "https://www.webim.ru/" - let expectedString = initialString - - XCTAssertEqual(initialString.decodePercentEscapedLinksIfPresent(), - expectedString) - } - - func testOneLinkWithPercentEscapingOnlyString() { - let initialString = "https://www.webim.ru/%D1%82%D0%B5%D1%81%D1%82/" - let expectedString = "https://www.webim.ru/тест/" - - XCTAssertEqual(initialString.decodePercentEscapedLinksIfPresent(), - expectedString) - } - - func testOneLinkWithPercentEscapingAndStartingTextString() { - let initialString = "Link: https://www.webim.ru/%D1%82%D0%B5%D1%81%D1%82/" - let expectedString = "Link: https://www.webim.ru/тест/" - - XCTAssertEqual(initialString.decodePercentEscapedLinksIfPresent(), - expectedString) - } - - func testOneLinkWithPercentEscapingAndClosingTextString() { - let initialString = "https://www.webim.ru/%D1%82%D0%B5%D1%81%D1%82/ – link" - let expectedString = "https://www.webim.ru/тест/ – link" - - XCTAssertEqual(initialString.decodePercentEscapedLinksIfPresent(), - expectedString) - } - - func testOneLinkWithPercentEscapingInsideTextString() { - let initialString = "Link: https://www.webim.ru/%D1%82%D0%B5%D1%81%D1%82/ – check it!" - let expectedString = "Link: https://www.webim.ru/тест/ – check it!" - - XCTAssertEqual(initialString.decodePercentEscapedLinksIfPresent(), - expectedString) - } - - func testMultipleLinksWithPercentEscapingString() { - let initialString = "https://www.webim.ru/%D1%82%D0%B5%D1%81%D1%821/ https://www.webim.ru/%D1%82%D0%B5%D1%81%D1%822/" - let expectedString = "https://www.webim.ru/тест1/ https://www.webim.ru/тест2/" - - XCTAssertEqual(initialString.decodePercentEscapedLinksIfPresent(), - expectedString) - } - - func testMultipleLinksWithPercentEscapingInsideComplexTextString() { - let initialString = "First link: https://www.webim.ru/%D1%82%D0%B5%D1%81%D1%821/ Second link: https://www.webim.ru/%D1%82%D0%B5%D1%81%D1%822/ That's it!" - let expectedString = "First link: https://www.webim.ru/тест1/ Second link: https://www.webim.ru/тест2/ That's it!" - - XCTAssertEqual(initialString.decodePercentEscapedLinksIfPresent(), - expectedString) - } - -} diff --git a/ios/libs/Webim/Example/Tests/ExampleTests/MimeTypeTests.swift b/ios/libs/Webim/Example/Tests/ExampleTests/MimeTypeTests.swift deleted file mode 100755 index 4c7ec76..0000000 --- a/ios/libs/Webim/Example/Tests/ExampleTests/MimeTypeTests.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// MimeTypeTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 12.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -@testable import WebimClientLibrary_Example -import Foundation -import XCTest - -class MimeTypeTests: XCTestCase { - - func testValue() { - // MARK: Test 1 - - var urlString = "/image.jpg" - var url = URL(string: urlString)! - - XCTAssertEqual(MimeType(url: url).value, - "image/jpeg") - XCTAssertTrue(isImage(contentType: MimeType(url: url).value)) - - // MARK: Test 2 - // Unknown extension - - urlString = "/db.db" - url = URL(string: urlString)! - - XCTAssertEqual(MimeType(url: url).value, - "application/octet-stream") - XCTAssertFalse(isImage(contentType: MimeType(url: url).value)) - - // MARK: Test 3 - // No extension - - urlString = "/unknown" - url = URL(string: urlString)! - - XCTAssertEqual(MimeType(url: url).value, - "application/octet-stream") - } - -} diff --git a/ios/libs/Webim/Example/Tests/ExecIfNotDestroyedHandlerExecutorTests.swift b/ios/libs/Webim/Example/Tests/ExecIfNotDestroyedHandlerExecutorTests.swift deleted file mode 100755 index 1fbb98d..0000000 --- a/ios/libs/Webim/Example/Tests/ExecIfNotDestroyedHandlerExecutorTests.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// ExecIfNotDestroyedHandlerExecutorTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 01.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class ExecIfNotDestroyedHandlerExecutorTests: XCTestCase { - - // MARK: - Properties - let execIfNotDestroyedHandlerExecutor = ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: SessionDestroyer(), - queue: DispatchQueue.global()) - - // MARK: - Tests - func testExecuteTask() { - let expectationToBeCalled = XCTestExpectation() - execIfNotDestroyedHandlerExecutor.execute(task: DispatchWorkItem { - expectationToBeCalled.fulfill() - }) - - wait(for: [expectationToBeCalled], - timeout: 1.0) - } - -} diff --git a/ios/libs/Webim/Example/Tests/FileParametersItemTests.swift b/ios/libs/Webim/Example/Tests/FileParametersItemTests.swift deleted file mode 100755 index be6b634..0000000 --- a/ios/libs/Webim/Example/Tests/FileParametersItemTests.swift +++ /dev/null @@ -1,73 +0,0 @@ -// -// FileParametersItemTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 16.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class FileParametersItemTests: XCTestCase { - - // MARK: - Constants - static let FILE_PARAMETERS_JSON_STRING = """ -{ - "client_content_type" : "image/jpeg", - "image" : { - "size" : { - "width" : 700, - "height" : 501 - } - }, - "visitor_id" : "877a920ede7082412656ac1cdec7ecde", - "filename" : "asset.JPG", - "content_type" : "image/png", - "guid" : "010a56da72ee41e2a78d0509155de755", - "size" : 758611 -} -""" - - // MARK: - Properties - private let fileParametersItemDictionary = try! JSONSerialization.jsonObject(with: FileParametersItemTests.FILE_PARAMETERS_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - - // MARK: - Tests - func testInit() { - let fileParametersItem = FileParametersItem(jsonDictionary: fileParametersItemDictionary) - - XCTAssertEqual(fileParametersItem.getSize(), - 758611) - XCTAssertEqual(fileParametersItem.getGUID(), - "010a56da72ee41e2a78d0509155de755") - XCTAssertEqual(fileParametersItem.getContentType(), - "image/png") - XCTAssertEqual(fileParametersItem.getFilename(), - "asset.JPG") - XCTAssertEqual(fileParametersItem.getImageParameters()!.getSize()!.getWidth(), - 700) - XCTAssertEqual(fileParametersItem.getImageParameters()!.getSize()!.getHeight(), - 501) - } - -} diff --git a/ios/libs/Webim/Example/Tests/FullUpdateTests.swift b/ios/libs/Webim/Example/Tests/FullUpdateTests.swift deleted file mode 100755 index f79223c..0000000 --- a/ios/libs/Webim/Example/Tests/FullUpdateTests.swift +++ /dev/null @@ -1,195 +0,0 @@ -// -// FullUpdateTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class FullUpdateTests: XCTestCase { - - // MARK: - Constants - private static let FULL_UPDATE_JSON_STRING = """ -{ - "state" : "chat", - "authToken" : "17778d49ecf342b5aef702479a99bb65", - "visitorNumber" : null, - "visitor" : { - "fields" : { - "name" : "Посетитель" - }, - "channelType" : null, - "channelId" : null, - "id" : "877a920ede7082412656ac1cdec7ecde", - "icon" : { - "color" : "#5fa0ea", - "shape" : "rhombus" - }, - "modificationTs" : 1518790888.5528669, - "creationTs" : 1518790888.5528669, - "hasProvidedFields" : true, - "channelUserName" : null, - "tags" : [ ], - "channelUserId" : null - }, - "pageId" : "fc59d2b80f1742da805e1f93548b3a29", - "onlineStatus" : "offline", - "visitSessionId" : "80a332f6fced40f290a5e8ace4a6d11c", - "pollingPeriod" : 2, - "onlineOperators" : false, - "currentTime" : 1519044952, - "cobrowsingSession" : null, - "normalPollingPeriod" : 10, - "chat" : { - "readByVisitor" : true, - "category" : "Прочее", - "subject" : null, - "operatorTyping" : false, - "clientSideId" : "0134e9d90e0eb95884d880860382c8ab", - "state" : "closed_by_operator", - "needToBeClosed" : false, - "visitorTyping" : null, - "messages" : [ - { - "avatar" : null, - "authorId" : null, - "ts" : 1519040829.056972, - "sessionId" : "80a332f6fced40f290a5e8ace4a6d11c", - "id" : "80a332f6fced40f290a5e8ace4a6d11c_2", - "text" : "Text", - "clientSideId" : "381e483f39e041a68b965da7f767c438", - "kind" : "info", - "name" : "" - } - ], - "offline" : false, - "visitorMessageDraft" : null, - "id" : 2547, - "unreadByVisitorSinceTs" : null, - "operatorIdToRate" : { }, - "creationTs" : 1519040829.056129, - "subcategory" : null, - "requestedForm" : null, - "unreadByOperatorSinceTs" : null, - "operator" : { - "avatar" : "/webim/images/avatar/demo_33201.png", - "fullname" : "Administrator", - "id" : 33201, - "robotType" : null, - "departmentKeys" : [ - "telegram", - "test3", - "test2" - ], - "langToFullname" : { }, - "sip" : "10002715000033201" - } - } -} -""" - - // MARK: - Properties - private let fullUpdateDictionary = try! JSONSerialization.jsonObject(with: FullUpdateTests.FULL_UPDATE_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - - // MARK: - Tests - func testInit() { - let fullUpdateItem = FullUpdate(jsonDictionary: fullUpdateDictionary) - - XCTAssertEqual(fullUpdateItem.getAuthorizationToken(), - "17778d49ecf342b5aef702479a99bb65") - - let chatItemString = """ -{ - "readByVisitor" : true, - "category" : "Прочее", - "subject" : null, - "operatorTyping" : false, - "clientSideId" : "0134e9d90e0eb95884d880860382c8ab", - "state" : "closed_by_operator", - "needToBeClosed" : false, - "visitorTyping" : null, - "messages" : [ - { - "avatar" : null, - "authorId" : null, - "ts" : 1519040829.056972, - "sessionId" : "80a332f6fced40f290a5e8ace4a6d11c", - "id" : "80a332f6fced40f290a5e8ace4a6d11c_2", - "text" : "Text", - "clientSideId" : "381e483f39e041a68b965da7f767c438", - "kind" : "info", - "name" : "" - } - ], - "offline" : false, - "visitorMessageDraft" : null, - "id" : 2547, - "unreadByVisitorSinceTs" : null, - "operatorIdToRate" : { }, - "creationTs" : 1519040829.056129, - "subcategory" : null, - "requestedForm" : null, - "unreadByOperatorSinceTs" : null, - "operator" : { - "avatar" : "/webim/images/avatar/demo_33201.png", - "fullname" : "Administrator", - "id" : 33201, - "robotType" : null, - "departmentKeys" : [ - "telegram", - "test3", - "test2" - ], - "langToFullname" : { }, - "sip" : "10002715000033201" - } -} -""" - let chatItemDictonary = try! JSONSerialization.jsonObject(with: chatItemString.data(using: .utf8)!, - options: []) as! [String : Any?] - XCTAssertEqual(fullUpdateItem.getChat(), - ChatItem(jsonDictionary: chatItemDictonary)) - - XCTAssertNil(fullUpdateItem.getDepartments()) - - XCTAssertFalse(fullUpdateItem.getHintsEnabled()) - - XCTAssertEqual(fullUpdateItem.getOnlineStatus(), - "offline") - - XCTAssertEqual(fullUpdateItem.getPageID(), - "fc59d2b80f1742da805e1f93548b3a29") - - XCTAssertEqual(fullUpdateItem.getSessionID(), - "80a332f6fced40f290a5e8ace4a6d11c") - - XCTAssertEqual(fullUpdateItem.getState(), - "chat") - - XCTAssertNotNil(fullUpdateItem.getVisitorJSONString()) - } - -} diff --git a/ios/libs/Webim/Example/Tests/HMACsha256Tests.swift b/ios/libs/Webim/Example/Tests/HMACsha256Tests.swift deleted file mode 100755 index 893d6ae..0000000 --- a/ios/libs/Webim/Example/Tests/HMACsha256Tests.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// HMACSha256Tests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 17.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class HMACSha256Tests: XCTestCase { - - func testHMACsha256() { - // Setup. - // Example is taken from Wikipedia. - let string = "The quick brown fox jumps over the lazy dog" - let key = "key" - let expectedResult = "f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8" - - let result = string.hmacSHA256(withKey: key) - XCTAssertEqual(result, expectedResult) - } - -} diff --git a/ios/libs/Webim/Example/Tests/HistoryBeforeResponseTests.swift b/ios/libs/Webim/Example/Tests/HistoryBeforeResponseTests.swift deleted file mode 100755 index be744c4..0000000 --- a/ios/libs/Webim/Example/Tests/HistoryBeforeResponseTests.swift +++ /dev/null @@ -1,82 +0,0 @@ -// -// HistoryBeforeResponseTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class HistoryBeforeResponseTests: XCTestCase { - - // MARK: - Constants - private static let HISTORY_BEFORE_RESPONSE_JSON_STRING = """ -{ - "result" : "ok", - "data" : { - "hasMore" : true, - "messages" : [ - { - "avatar" : "/webim/images/avatar/demo_33201.png", - "chatId" : "2470", - "authorId" : 33201, - "data" : null, - "id" : "26066", - "ts_m" : 1518178864048925, - "text" : "5", - "clientSideId" : "2b29154364e14cf8b3823267740ac090", - "kind" : "operator", - "name" : "Administrator" - }, - { - "avatar" : null, - "chatId" : "2470", - "authorId" : null, - "data" : null, - "id" : "26068", - "ts_m" : 1518181740640531, - "text" : "Text", - "clientSideId" : "b91d616953a4d05c3df82f63359ebb58", - "kind" : "file_visitor", - "name" : "Никита" - } - ] - } -} -""" - - // MARK: - Properties - private let historyBeforeResponseDictionary = try! JSONSerialization.jsonObject(with: HistoryBeforeResponseTests.HISTORY_BEFORE_RESPONSE_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - - // MARK: - Tests - func testInit() { - let historyBeforeItem = HistoryBeforeResponse(jsonDictionary: historyBeforeResponseDictionary) - - XCTAssertTrue(historyBeforeItem.getData()!.isHasMore()) - XCTAssertEqual(historyBeforeItem.getData()!.getMessages()!.count, - 2) - } - -} diff --git a/ios/libs/Webim/Example/Tests/HistoryIDTests.swift b/ios/libs/Webim/Example/Tests/HistoryIDTests.swift deleted file mode 100755 index 387f4e0..0000000 --- a/ios/libs/Webim/Example/Tests/HistoryIDTests.swift +++ /dev/null @@ -1,76 +0,0 @@ -// -// HistoryIDTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 01.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class HistoryIDTests: XCTestCase { - - // MARK: - Tests - func testEquals() { - let dbID = "db_id" - let timeInMicrosecond: Int64 = 1 - - // MARK: Test 1 - // Two different normal HistoryID objects. - - var historyID1: HistoryID? = HistoryID(dbID: "db_id1", - timeInMicrosecond: 1) - var historyID2: HistoryID? = HistoryID(dbID: "db_id2", - timeInMicrosecond: 2) - - XCTAssertFalse(historyID1 == historyID2) - - // MARK: Test 2 - // Two same normal HistoryID objects. - - historyID1 = HistoryID(dbID: dbID, - timeInMicrosecond: timeInMicrosecond) - historyID2 = HistoryID(dbID: dbID, - timeInMicrosecond: timeInMicrosecond) - - XCTAssertTrue(historyID1 == historyID2) - - // MARK: Test 3 - // One normal HistoryID object and one nil. - - historyID1 = HistoryID(dbID: dbID, - timeInMicrosecond: timeInMicrosecond) - historyID2 = nil - - XCTAssertFalse(historyID1 == historyID2) - - // MARK: Test 4 - // Two nil objects. - - historyID1 = nil - historyID2 = nil - - XCTAssertTrue(historyID1 == historyID2) - } - -} diff --git a/ios/libs/Webim/Example/Tests/HistorySinceResponseTests.swift b/ios/libs/Webim/Example/Tests/HistorySinceResponseTests.swift deleted file mode 100755 index d9c9e15..0000000 --- a/ios/libs/Webim/Example/Tests/HistorySinceResponseTests.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// HistorySinceResponseTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class HistorySinceResponseTests: XCTestCase { - - // MARK: - Constants - private static let HISTORY_SINCE_RESPONSE_JSON_STRING = """ -{ - "result" : "ok", - "data" : { - "hasMore" : true, - "revision" : "1519046942029554", - "messages" : [ - { - "avatar" : null, - "chatId" : "2489", - "authorId" : null, - "data" : null, - "id" : "26886", - "ts_m" : 1518610821878678, - "text" : "5", - "clientSideId" : "4855e5fb4cf72970fd1ee6d055db165f", - "kind" : "visitor", - "name" : "Никита" - }, - { - "avatar" : null, - "chatId" : "2489", - "authorId" : null, - "data" : null, - "id" : "26887", - "ts_m" : 1518610834493789, - "text" : "Посетитель закрыл диалог", - "clientSideId" : "f90565d2ae724a5f969f72687af7fd49", - "kind" : "info", - "name" : "" - } - ] - } -} -""" - - // MARK: - Properties - private let historySinceResponseDictionary = try! JSONSerialization.jsonObject(with: HistorySinceResponseTests.HISTORY_SINCE_RESPONSE_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - - // MARK: - Methods - func testInit() { - let historySinceResponse = HistorySinceResponse(jsonDictionary: historySinceResponseDictionary) - - XCTAssertEqual(historySinceResponse.getData()!.getMessages()!.count, - 2) - XCTAssertTrue(historySinceResponse.getData()!.isHasMore()!) - XCTAssertEqual(historySinceResponse.getData()!.getRevision(), - "1519046942029554") - } - -} diff --git a/ios/libs/Webim/Example/Tests/Info.plist b/ios/libs/Webim/Example/Tests/Info.plist deleted file mode 100755 index ba72822..0000000 --- a/ios/libs/Webim/Example/Tests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/ios/libs/Webim/Example/Tests/InternalUtilsTests.swift b/ios/libs/Webim/Example/Tests/InternalUtilsTests.swift deleted file mode 100755 index 3474672..0000000 --- a/ios/libs/Webim/Example/Tests/InternalUtilsTests.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// InternalUtilsTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 02.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class InternalUtilsTests: XCTestCase { - - func testCreateServerURLString() { - let expectedServerURLString = "https://demo.webim.ru" - - // MARK: Test 1 - var accountName = "demo" - XCTAssertEqual(InternalUtils.createServerURLStringBy(accountName: accountName), - expectedServerURLString) - - // MARK: Test 2 - accountName = "https://demo.webim.ru" - XCTAssertEqual(InternalUtils.createServerURLStringBy(accountName: accountName), - expectedServerURLString) - - // MARK: Test 3 - accountName = "https://demo.webim.ru/" - XCTAssertEqual(InternalUtils.createServerURLStringBy(accountName: accountName), - expectedServerURLString) - } - -} diff --git a/ios/libs/Webim/Example/Tests/LocationSettingsHolderTests.swift b/ios/libs/Webim/Example/Tests/LocationSettingsHolderTests.swift deleted file mode 100755 index e1d617b..0000000 --- a/ios/libs/Webim/Example/Tests/LocationSettingsHolderTests.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// LocationSettingsHolderTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 21.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class LocationSettingsHolderTests: XCTestCase { - - // MARK: - Constants - private static let USER_DEFAULTS_KEY = "mock" - - // MARK: - Methods - - override func setUp() { - super.setUp() - - UserDefaults.standard.removeObject(forKey: LocationSettingsHolderTests.USER_DEFAULTS_KEY) - } - - override func tearDown() { - UserDefaults.standard.removeObject(forKey: LocationSettingsHolderTests.USER_DEFAULTS_KEY) - - super.tearDown() - } - - // MARK: - Tests - - func testInit() { - let locationSettingsHolder = LocationSettingsHolder(userDefaultsKey: LocationSettingsHolderTests.USER_DEFAULTS_KEY) - - XCTAssertFalse(locationSettingsHolder.getLocationSettings().areHintsEnabled()) - } - - func testReceiving() { - let locationSettingsHolder = LocationSettingsHolder(userDefaultsKey: LocationSettingsHolderTests.USER_DEFAULTS_KEY) - - XCTAssertFalse(locationSettingsHolder.receiving(locationSettings: locationSettingsHolder.getLocationSettings())) - - let newLocationSettings = LocationSettingsImpl(hintsEnabled: true) - XCTAssertTrue(locationSettingsHolder.receiving(locationSettings: newLocationSettings)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/LocationSettingsImplTests.swift b/ios/libs/Webim/Example/Tests/LocationSettingsImplTests.swift deleted file mode 100755 index 916acd9..0000000 --- a/ios/libs/Webim/Example/Tests/LocationSettingsImplTests.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// LocationSettingsImplTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 20.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class LocationSettingsImplTests: XCTestCase { - - // MARK: - Constants - private static let USER_DEFAULTS_KEY = "mock" - - // MARK: - Methods - - override func setUp() { - super.setUp() - - UserDefaults.standard.removeObject(forKey: LocationSettingsImplTests.USER_DEFAULTS_KEY) - } - - override func tearDown() { - UserDefaults.standard.removeObject(forKey: LocationSettingsImplTests.USER_DEFAULTS_KEY) - - super.tearDown() - } - - // MARK: - Tests - - func testInit() { - let locationSettings = LocationSettingsImpl(hintsEnabled: true) - - XCTAssertTrue(locationSettings.areHintsEnabled()) - } - - func testGetSave() { - let USER_DEFAULTS_KEY = "test" - - let locationSettings = LocationSettingsImpl(hintsEnabled: true) - locationSettings.saveTo(userDefaults: USER_DEFAULTS_KEY) - - let restoredLocationSettings = LocationSettingsImpl.getFrom(userDefaults: USER_DEFAULTS_KEY) - - XCTAssertEqual(locationSettings.areHintsEnabled(), - restoredLocationSettings.areHintsEnabled()) - } - -} diff --git a/ios/libs/Webim/Example/Tests/MemoryHistoryMetaInformationStorageTests.swift b/ios/libs/Webim/Example/Tests/MemoryHistoryMetaInformationStorageTests.swift deleted file mode 100755 index 9c61b39..0000000 --- a/ios/libs/Webim/Example/Tests/MemoryHistoryMetaInformationStorageTests.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// MemoryHistoryMetaInformationStorageTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 15.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class MemoryHistoryMetaInformationStorageTests: XCTestCase { - - // MARK: - Tests - func testIsHistoryEnded() { - let memoryHistoryMetaInformationStorage = MemoryHistoryMetaInformationStorage() - - XCTAssertFalse(memoryHistoryMetaInformationStorage.isHistoryEnded()) - - memoryHistoryMetaInformationStorage.set(historyEnded: true) - XCTAssertTrue(memoryHistoryMetaInformationStorage.isHistoryEnded()) - } - -} diff --git a/ios/libs/Webim/Example/Tests/MemoryHistoryStorageTests.swift b/ios/libs/Webim/Example/Tests/MemoryHistoryStorageTests.swift deleted file mode 100755 index 29e5d49..0000000 --- a/ios/libs/Webim/Example/Tests/MemoryHistoryStorageTests.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// MemoryHistoryStorageTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 20.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class MemoryHistoryStorageTests: XCTestCase { - - // MARK: - Constants - private static let SERVER_URL_STRING = "http://demo.webim.ru" - - // MARK: - Methods - // MARK: Private methods - private static func generateMessages(ofCount numberOfMessages: Int) -> [MessageImpl] { - var messages = [MessageImpl]() - - for index in 1 ... numberOfMessages { - messages.append(MessageImpl(serverURLString: MemoryHistoryStorageTests.SERVER_URL_STRING, - id: String(index), - operatorID: "1", - senderAvatarURLString: nil, - senderName: "Name", - type: MessageType.OPERATOR, - data: nil, - text: "Text", - timeInMicrosecond: Int64(index), - attachment: nil, - historyMessage: true, - internalID: String(index), - rawText: nil)) - } - - return messages - } - - // MARK: - Tests - func testGetFullHistory() { - let memoryHistoryStorage = MemoryHistoryStorage() - let messagesCount = 10 - memoryHistoryStorage.receiveHistoryBefore(messages: MemoryHistoryStorageTests.generateMessages(ofCount: messagesCount), - hasMoreMessages: false) - - let expectation = XCTestExpectation() - var gettedMessages = [Message]() - memoryHistoryStorage.getFullHistory() { messages in - gettedMessages = messages - - expectation.fulfill() - } - wait(for: [expectation], - timeout: 1.0) - - XCTAssertEqual(gettedMessages.count, - messagesCount) - } - -} diff --git a/ios/libs/Webim/Example/Tests/MessageFactoriesTests.swift b/ios/libs/Webim/Example/Tests/MessageFactoriesTests.swift deleted file mode 100755 index 713016f..0000000 --- a/ios/libs/Webim/Example/Tests/MessageFactoriesTests.swift +++ /dev/null @@ -1,143 +0,0 @@ -// -// MessageFactoriesTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -// MARK: - Global constants -fileprivate let MESSAGE_ITEM_JSON_STRING = """ -{ - "avatar" : "/webim/images/avatar/demo_33202.png", - "chatId" : "2489", - "authorId" : 33202, - "data" : null, - "id" : "26871", - "ts_m" : 1518609964579372, - "text" : "42", - "clientSideId" : "84e51d5638524ee7833a1fe19a1f2448", - "kind" : "operator", - "name" : "Евгения Техподдержка" -} -""" -fileprivate let MESSAGE_ITEM_DICTIONARY = try! JSONSerialization.jsonObject(with: MESSAGE_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] -fileprivate let MESSAGE_ITEM = MessageItem(jsonDictionary: MESSAGE_ITEM_DICTIONARY) - -class CurrentChatMapperTests: XCTestCase { - - // MARK: - Properties - let currentChatMapper = CurrentChatMessageMapper(withServerURLString: "http://demo.webim.ru") - - // MARK: - Tests - - func testMap() { - let message = currentChatMapper.map(message: MESSAGE_ITEM)! - - XCTAssertEqual(message.getType(), - MessageType.OPERATOR) - XCTAssertNil(message.getAttachment()) - XCTAssertEqual(message.getText(), - "42") - XCTAssertNil(message.getRawText()) - XCTAssertEqual(message.getOperatorID(), - "33202") - XCTAssertEqual(message.getSenderAvatarURLString(), - "/webim/images/avatar/demo_33202.png") - XCTAssertEqual(message.getSenderName(), - "Евгения Техподдержка") - XCTAssertEqual(message.getTimeInMicrosecond(), - 1518609964579372) - XCTAssertFalse(message.hasHistoryComponent()) - } - - func testMapAll() { - XCTAssertEqual(currentChatMapper.mapAll(messages: [MESSAGE_ITEM]).count, - 1) - } - -} - -class HistoryMapperTests: XCTestCase { - - // MARK: - Properties - let historyMapper = HistoryMessageMapper(withServerURLString: "http://demo.webim.ru") - - // MARK: - Tests - func testMap() { - let message = historyMapper.map(message: MESSAGE_ITEM)! - - XCTAssertEqual(message.getType(), - MessageType.OPERATOR) - XCTAssertNil(message.getAttachment()) - XCTAssertEqual(message.getText(), - "42") - XCTAssertNil(message.getRawText()) - XCTAssertEqual(message.getOperatorID(), - "33202") - XCTAssertEqual(message.getSenderAvatarURLString(), - "/webim/images/avatar/demo_33202.png") - XCTAssertEqual(message.getSenderName(), - "Евгения Техподдержка") - XCTAssertEqual(message.getTimeInMicrosecond(), - 1518609964579372) - XCTAssertTrue(message.hasHistoryComponent()) - } - -} - -class SendingFactoryTests: XCTestCase { - - // MARK: - Properties - let sendingFactory = SendingFactory(withServerURLString: "http://demo.webim.ru") - - // MARK: - Tests - - func testCreateTextMessage() { - let message = sendingFactory.createTextMessageToSendWith(id: "1", - text: "Text") - - XCTAssertEqual(message.getID(), - "1") - XCTAssertTrue(message.getSenderName().isEmpty) - XCTAssertEqual(message.getType(), - MessageType.VISITOR) - XCTAssertEqual(message.getText(), - "Text") - } - - func testCreateFileMessage() { - let message = sendingFactory.createFileMessageToSendWith(id: "1") - - XCTAssertEqual(message.getID(), - "1") - XCTAssertTrue(message.getSenderName().isEmpty) - XCTAssertEqual(message.getType(), - MessageType.FILE_FROM_VISITOR) - XCTAssertTrue(message.getText().isEmpty) - } - -} diff --git a/ios/libs/Webim/Example/Tests/MessageHolderTests.swift b/ios/libs/Webim/Example/Tests/MessageHolderTests.swift deleted file mode 100755 index 332c063..0000000 --- a/ios/libs/Webim/Example/Tests/MessageHolderTests.swift +++ /dev/null @@ -1,1713 +0,0 @@ -// -// MessageHolderTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 01.09.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit -import XCTest -@testable import WebimClientLibrary - -class MessageHolderTests: XCTestCase { - - // MARK: - Constants - private enum MessageImplMockData: String { - case serverURLString = "https://demo.webim.ru/" - case operatorID = "operatorID" - case avatarURLString = "image.jpg" - case senderName = "Sender Name" - case text = "Text." - } - - // MARK: - Properties - private var lastAddedMessage: MessageImpl? - private var lastMessageBeforeAdded: MessageImpl? - private var lastRemovedMessage: MessageImpl? - private var lastNewVersionChangedMessage: MessageImpl? - private var lastOldVersionChangedMessage: MessageImpl? - private var messagesCount = 0 - - // MARK: - Methods - // MARK: Private methods - - private func generateHistory(ofCount numberOfMessages: Int) -> [MessageImpl] { - var history = [MessageImpl]() - - for index in messagesCount ..< (messagesCount + numberOfMessages) { - history.append(MessageImpl(serverURLString: MessageImplMockData.serverURLString.rawValue, - id: String(index), - operatorID: MessageImplMockData.operatorID.rawValue, - senderAvatarURLString: MessageImplMockData.avatarURLString.rawValue, - senderName: MessageImplMockData.senderName.rawValue, - type: MessageType.OPERATOR, - data: nil, - text: MessageImplMockData.text.rawValue, - timeInMicrosecond: Int64(index), - attachment: nil, - historyMessage: true, - internalID: String(index), - rawText: nil)) - } - - messagesCount = messagesCount + numberOfMessages - - return history - } - - private func generateCurrentChat(ofCount numberOfMessages: Int) -> [MessageImpl] { - var currentChat = [MessageImpl]() - - for index in messagesCount ..< (messagesCount + numberOfMessages) { - currentChat.append(MessageImpl(serverURLString: MessageImplMockData.serverURLString.rawValue, - id: String(index), - operatorID: MessageImplMockData.operatorID.rawValue, - senderAvatarURLString: MessageImplMockData.avatarURLString.rawValue, - senderName: MessageImplMockData.senderName.rawValue, - type: MessageType.OPERATOR, - data: nil, - text: MessageImplMockData.text.rawValue, - timeInMicrosecond: Int64(index), - attachment: nil, - historyMessage: false, - internalID: String(index), - rawText: nil)) - } - - messagesCount = messagesCount + numberOfMessages - - return currentChat - } - - private func generateHistoryFrom(currentChat: [MessageImpl]) -> [MessageImpl] { - var result = [MessageImpl]() - - for message in currentChat { - let newMessage = MessageImpl(serverURLString: MessageImplMockData.serverURLString.rawValue, - id: message.getID(), - operatorID: message.getOperatorID(), - senderAvatarURLString: message.getSenderAvatarURLString(), - senderName: message.getSenderName(), - type: message.getType(), - data: message.getData(), - text: message.getText(), - timeInMicrosecond: message.getTimeInMicrosecond(), - attachment: message.getAttachment(), - historyMessage: true, - internalID: String(message.getTimeInMicrosecond()), - rawText: message.getRawText()) - result.append(newMessage) - } - - return result - } - - private func newCurrentChat() -> MessageImpl { - messagesCount = messagesCount + messagesCount - - return MessageImpl(serverURLString: MessageImplMockData.serverURLString.rawValue, - id: String(messagesCount), - operatorID: MessageImplMockData.operatorID.rawValue, - senderAvatarURLString: MessageImplMockData.avatarURLString.rawValue, - senderName: MessageImplMockData.senderName.rawValue, - type: MessageType.OPERATOR, - data: nil, - text: MessageImplMockData.text.rawValue, - timeInMicrosecond: Int64(messagesCount), - attachment: nil, - historyMessage: false, - internalID: String(messagesCount), - rawText: nil) - } - - private func newEdited(currentChatMessage: MessageImpl) -> MessageImpl { - return MessageImpl(serverURLString: MessageImplMockData.serverURLString.rawValue, - id: currentChatMessage.getID(), - operatorID: currentChatMessage.getOperatorID(), - senderAvatarURLString: currentChatMessage.getSenderAvatarURLString(), - senderName: currentChatMessage.getSenderName(), - type: currentChatMessage.getType(), - data: nil, - text: (currentChatMessage.getText() + " One more thing."), - timeInMicrosecond: currentChatMessage.getTimeInMicrosecond(), - attachment: nil, - historyMessage: false, - internalID: currentChatMessage.getCurrentChatID(), - rawText: nil) - } - - private func newEdited(historyMessage: MessageImpl) -> MessageImpl { - return MessageImpl(serverURLString: MessageImplMockData.serverURLString.rawValue, - id: historyMessage.getID(), - operatorID: historyMessage.getOperatorID(), - senderAvatarURLString: historyMessage.getSenderAvatarURLString(), - senderName: historyMessage.getSenderName(), - type: historyMessage.getType(), - data: nil, - text: (historyMessage.getText() + " One more thing."), - timeInMicrosecond: historyMessage.getTimeInMicrosecond(), - attachment: nil, - historyMessage: true, - internalID: historyMessage.getHistoryID()?.getDBid(), - rawText: nil) - } - - private func newMessageHolder(withHistory history: [MessageImpl] = [MessageImpl]()) -> MessageHolder { - let sessionDestroyer = SessionDestroyer() - let accessChecker = AccessChecker(thread: Thread.current, - sessionDestroyer: sessionDestroyer) - let execIfNotDestroyedHandlerExecutor = ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: sessionDestroyer, - queue: DispatchQueue.global(qos: .userInteractive)) - let actionRequestLoop = ActionRequestLoop(completionHandlerExecutor: execIfNotDestroyedHandlerExecutor, - internalErrorListener: InternalErrorListenerForTests()) - let webimActions = WebimActions(baseURL: MessageImplMockData.serverURLString.rawValue, - actionRequestLoop: actionRequestLoop) - let remoteHistoryProvider = RemoteHistoryProviderForTests(withWebimActions: webimActions, - historyMessageMapper: HistoryMessageMapper(withServerURLString: MessageImplMockData.serverURLString.rawValue), - historyMetaInformation: MemoryHistoryMetaInformationStorage(), - history: history) - - return MessageHolder(accessChecker: accessChecker, - remoteHistoryProvider: remoteHistoryProvider, - historyStorage: MemoryHistoryStorage(), - reachedEndOfRemoteHistory: false) - } - - private func newMessageHolder(withHistory history: [MessageImpl], - localHistory: [MessageImpl]) -> MessageHolder { - let sessionDestroyer = SessionDestroyer() - let accessChecker = AccessChecker(thread: Thread.current, - sessionDestroyer: sessionDestroyer) - let execIfNotDestroyedHandlerExecutor = ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: sessionDestroyer, - queue: DispatchQueue.global(qos: .userInteractive)) - let actionRequestLoop = ActionRequestLoop(completionHandlerExecutor: execIfNotDestroyedHandlerExecutor, - internalErrorListener: InternalErrorListenerForTests()) - let webimActions = WebimActions(baseURL: MessageImplMockData.serverURLString.rawValue, - actionRequestLoop: actionRequestLoop) - let remoteHistoryProvider = RemoteHistoryProviderForTests(withWebimActions: webimActions, - historyMessageMapper: HistoryMessageMapper(withServerURLString: MessageImplMockData.serverURLString.rawValue), - historyMetaInformation: MemoryHistoryMetaInformationStorage(), - history: history) - let memoryHistoryStorage = MemoryHistoryStorage(messagesToAdd: localHistory) - - return MessageHolder(accessChecker: accessChecker, - remoteHistoryProvider: remoteHistoryProvider, - historyStorage: memoryHistoryStorage, - reachedEndOfRemoteHistory: false) - } - - // MARK: - Tests - - func testGenerateHistory() { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - _ = generateCurrentChat(ofCount: 10) - let history2 = generateHistory(ofCount: 10) - - // MARK: Test 1 - var index = 0 - for message in history1 { - XCTAssertEqual(message.getPrimaryID(), String(index)) - index = index + 1 - } - - // MARK: Test 2 - index = 20 - for message in history2 { - XCTAssertEqual(message.getPrimaryID(), String(index)) - index = index + 1 - } - } - - func testMessageTrackerRespondsImmediatelyOnNewCurrentChatMessages() throws { - // MARK: Model set up - let currentChat = generateCurrentChat(ofCount: 10) - let messageHolder = newMessageHolder() - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - - // MARK: Test - // When: Request next 10 messages (which are of current chat). - messageHolder.set(currentChatMessages: currentChat) - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion should be called on current chat. When requesting messages current chat receives it immediately. - XCTAssertEqual(completionHandlerMessages!, currentChat) - } - - func testMessageTrackerAwaitsForHistoryResponse() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let history2 = generateHistory(ofCount: 10) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - - // MARK: Test 1 - // When: Requesting next 10 messages (which are of history). - let expectationNotToBeCalled = XCTestExpectation() - expectationNotToBeCalled.isInverted = true - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - expectationNotToBeCalled.fulfill() - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion shouldn't be called. It was cached and will be called after history is received. - wait(for: [expectationNotToBeCalled], - timeout: 0.0) - - // MARK: Test 2 - // When: History is received. - messageHolder.receiveHistoryUpdateWith(messages: history2, - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Previously cached completion should be called. - XCTAssertEqual(completionHandlerMessages!, history2) - - // MARK: Test 3 - // When: Requesting next 10 messages. - completionHandlerMessages = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion should be called on history1. - XCTAssertEqual(completionHandlerMessages!, history1) - } - - func testMessageTrackerAwaitsForHistoryResponseWithCurrentChat() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let history2 = generateHistory(ofCount: 10) - let currentChat = generateCurrentChat(ofCount: 10) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - - // MARK: Test 1 - // When: Requesting all messages that are of current chat. - messageHolder.set(currentChatMessages: currentChat) - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion should be called on current chat messages. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Requesting next 10 messages (which are of history). - let expectationNotToBeCalled = XCTestExpectation() - expectationNotToBeCalled.isInverted = true - try messageTracker.getNextMessages(byLimit: 10) { messages in - expectationNotToBeCalled.fulfill() - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion should not be called. It was cached and will be called after history is received. - wait(for: [expectationNotToBeCalled], - timeout: 1.0) - - // MARK: Test 3 - // When: History is received. - messageHolder.receiveHistoryUpdateWith(messages: history2, - deleted: Set(), completion: { - // No need to do anything when testing. - }) - // Then: Cached completion should be called on history2. - XCTAssertEqual(completionHandlerMessages!, history2) - - // MARK: Test 4 - // When: Requesting next 10 messages (which are of received history). - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on history1. - XCTAssertEqual(completionHandlerMessages!, history1) - } - - func testRemoteHistoryProviderStopsRequesting() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let history2 = generateHistory(ofCount: 10) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - - // MARK: Test 1 - // When: Request all messages. - messageHolder.receiveHistoryUpdateWith(messages: history2, - deleted: Set()) { - // No need to do anything when testing. - } - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 100) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: 10 previously received messages should be received and no history requests should be performed. - XCTAssertEqual(completionHandlerMessages!, history2) - XCTAssertEqual((messageHolder.getRemoteHistoryProvider() as! RemoteHistoryProviderForTests).numberOfCalls, 0) - - // MARK: Test 2 - // When: Requesting all messages. - try messageTracker.getNextMessages(byLimit: 100) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Next 10 messages should be received and history request for more should be performed. - XCTAssertEqual(completionHandlerMessages!, history1) - XCTAssertEqual((messageHolder.getRemoteHistoryProvider() as! RemoteHistoryProviderForTests).numberOfCalls, 1) - - // MARK: Test 3 - // When: Requesting more messages. - try messageTracker.getNextMessages(byLimit: 100) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: No messages should be received and no history requests should be performed. - XCTAssertEqual(completionHandlerMessages!, [MessageImpl]()) - XCTAssertEqual((messageHolder.getRemoteHistoryProvider() as! RemoteHistoryProviderForTests).numberOfCalls, 1) - - // MARK: Test 4 - // When: Resetting 15 messages back and requesting for all messages. - try messageTracker.resetTo(message: history2[5]) - try messageTracker.getNextMessages(byLimit: 100) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: 15 messages should be received and no history requests should be preformed. - XCTAssertEqual(completionHandlerMessages!, (history1 + Array(history2[0 ... 4]))) - XCTAssertEqual((messageHolder.getRemoteHistoryProvider() as! RemoteHistoryProviderForTests).numberOfCalls, 1) - } - - func testInsertMessagesBetweenOlderHistoryAndCurrentChat() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let history2 = generateHistory(ofCount: 2) - let currentChat = generateCurrentChat(ofCount: 10) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: history1, - deleted: Set()) { - // No need to do anything when testing. - } - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting 10 messages (which are of current chat). - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on this 10 messages. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Requesting 10 messages (which are history). - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on this 10 messages. - XCTAssertEqual(completionHandlerMessages!, history1) - - // MARK: Test 3 - // When: Receiving history between current chat and receiver older history. - messageHolder.receiveHistoryUpdateWith(messages: history2, - deleted: Set()) { - // No need to do anything when testing. - } - // Then: First history message should be inserted before first current chat message. - XCTAssertEqual(lastAddedMessage, history2[1]) - XCTAssertEqual(lastMessageBeforeAdded, currentChat.last!) - } - - func testReceiveHistoryPartOfCurrentChat() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let currentChat = generateCurrentChat(ofCount: 10) - let history2 = generateHistoryFrom(currentChat: currentChat) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: history1, - deleted: Set()) { - // No need to do anything when testing. - } - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting current chat. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Receiving current chat completion should be called. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Requesting history part. - var numberOfCalls = 0 - try messageTracker.getNextMessages(byLimit: 5) { messages in - numberOfCalls = numberOfCalls + 1 - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Receiving history completion handler should be called. - XCTAssertEqual(numberOfCalls, 1) - XCTAssertEqual(completionHandlerMessages!, Array(history1[5 ... 9])) - - // MARK: Test 3 - // When: Receiving history part of current chat. - messageHolder.receiveHistoryUpdateWith(messages: Array(history2[0 ..< 5]), - deleted: Set()) { - // No need to do anything when testing. - } - // Then: No completion handlers should be called. - XCTAssertEqual(numberOfCalls, 1) - - // MARK: Test 4 - // When: Requesting remaining history. - try messageTracker.getNextMessages(byLimit: 5) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Receiving remaining history completion handler should be called. - XCTAssertEqual(completionHandlerMessages!, Array(history1[0 ... 4])) - } - - func testReceiveFullHistoryOfCurrentChat() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let currentChat = generateCurrentChat(ofCount: 10) - let history2 = generateHistoryFrom(currentChat: currentChat) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: history1, - deleted: Set()) { - // No need to do anything when testing. - } - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting next 10 messages. - var numberOfCalls = 0 - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - numberOfCalls = numberOfCalls + 1 - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Receiving current chat completion handler should be called. - XCTAssertEqual(numberOfCalls, 1) - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Receiving history part of current chat. - messageHolder.receiveHistoryUpdateWith(messages: Array(history2[0 ... 5]), - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Completion handler should not be called and receiving method too. - XCTAssertEqual(numberOfCalls, 1) - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 3 - // When: Requesting for more messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - numberOfCalls = numberOfCalls + 1 - } - // Then: History part before current chat completion handler should be called. - XCTAssertEqual(numberOfCalls, 2) - } - - func testReceiveLastHistoryPartOfCurrentChat() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let currentChat = generateCurrentChat(ofCount: 10) - let history2 = generateHistoryFrom(currentChat: currentChat) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: Array(history2[5 ... 9]), - deleted: Set()) { - // No need to do anything when testing. - } - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting 10 messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Current chat receiving completion handler should be called. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Requesting next 10 messages. - let expectationToBeCalled2 = XCTestExpectation() - try messageTracker.getNextMessages(byLimit: 10) { _ in - expectationToBeCalled2.fulfill() - } - // Then: History part before current chat receiving completion handler should be called. - wait(for: [expectationToBeCalled2], - timeout: 1.0) - - // MARK: Test 3 - // When: Resetting current chat and requesting next messages. - messageTracker.set(messagesLoading: false) - try messageTracker.resetTo(message: currentChat[9]) - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handlers should be called on next 9 current chat messages. - XCTAssertEqual(completionHandlerMessages!, Array(currentChat[0 ... 8])) - - // MARK: Test 4 - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handlers should be called first on received history messages. - XCTAssertEqual(completionHandlerMessages!, history1) - } - - func testRequestAsManyMessagesAsReceivedWithHistoryForCurrentChat() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let currentChat = generateCurrentChat(ofCount: 10) - let history2 = generateHistoryFrom(currentChat: currentChat) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: history1, - deleted: Set()) { - // No need to do anything when testing. - } - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: Array(currentChat[0 ... 5])) - - // MARK: Test 1 - // When: Requesting 10 messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: First 5 messages of current chat receiving completion should be called. - XCTAssertEqual(completionHandlerMessages!, Array(currentChat[0 ... 5])) - - // MARK: Test 2 - // When: Received 5 messaged of history (which is part of current chat). - messageHolder.receiveHistoryUpdateWith(messages: Array(history2[0 ... 5]), - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Receiving method should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 3 - // When: Receiving history which is not a part of current chat. - messageHolder.receiveHistoryUpdateWith(messages: [history2[6]], - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Receiving method should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 4 - // When: Receiving current chat message (which is part of history). - messageHolder.receive(newMessage: currentChat[6]) - // Then: Message should be inserted in the end. - XCTAssertEqual(lastAddedMessage, currentChat[6]) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 5 - // When: Requesting more messages. - let expectationToBeCalled = XCTestExpectation() - try messageTracker.getNextMessages(byLimit: 5) { messages in - expectationToBeCalled.fulfill() - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on history part before current chat. - wait(for: [expectationToBeCalled], - timeout: 1.0) - } - - func testReceiveCurrentChatWhenHistoryFullyTracked() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let currentChat = generateCurrentChat(ofCount: 10) - let history2 = generateHistoryFrom(currentChat: currentChat) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: (history1 + history2), - deleted: Set()) { - // No need to do anything when testing. - } - - // MARK: Test 1 - // When: Requesting 10 messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Receiving completion handler should be called on history part of current chat. - XCTAssertEqual(completionHandlerMessages!, history2) - - // MARK: Test 2 - // When: Receiving chat of 7/10 messages. - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: Array(currentChat[0 ..< 8])) - // Then: Receiving method should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 3 - // When: Receiving next current chat message. - messageHolder.receive(newMessage: currentChat[9]) - // Then: Receiving method should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 4 - // When: Requesting more messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on the older history. - XCTAssertEqual(completionHandlerMessages!, history1) - } - - func testReceiveLocalHistoryRemoteHistoryCurrentChat() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let currentChat = generateCurrentChat(ofCount: 10) - let history2 = generateHistoryFrom(currentChat: currentChat) - let messageHolder = newMessageHolder(withHistory: (history1 + history2), - localHistory: (history1 + Array(history2[0 ... 7]))) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - - // MARK: Test 1 - // When: Requesting next 8 messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 8) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on 8 history messages of current chat. - XCTAssertEqual(completionHandlerMessages!, Array(history2[0 ... 7])) - - // MARK: Test 2 - // When: Receiving history and 1 message of current chat history. - messageHolder.receiveHistoryUpdateWith(messages: (history1 + [history2[8]]), - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Receiving method should be called on that message. - XCTAssertEqual(lastAddedMessage, history2[8]) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 3 - // When: Receiving current chat. - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: currentChat) - // Then: Current chat messages should be added in the end. - XCTAssertEqual(lastAddedMessage, currentChat[9]) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 4 - // When: Requesting more messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion should be called on the older history. - XCTAssertEqual(completionHandlerMessages!, history1) - } - - func testReceiveCurrentChatWhenHistoryLastPartTracked() throws { - // MARK: Model set up - let currentChat = generateCurrentChat(ofCount: 10) - let history = generateHistoryFrom(currentChat: currentChat) - let messageHolder = newMessageHolder(withHistory: history) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: Array(history[1 ... 9]), - deleted: Set()) { - // No need to do anything when testing. - } - - // MARK: Test 1 - // When: Requesting messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion should be called on received history. - XCTAssertEqual(completionHandlerMessages!, Array(history[1 ... 9])) - - // MARK: Test 2 - // When: Receiving chat. - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: currentChat) - // Then: Receiving method should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 3 - // When: Requesting more messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on last history part message. - XCTAssertEqual(completionHandlerMessages!, [currentChat[0]]) - } - - func testMergeChat() throws { - // MARK: Model set up - let messageHolder = newMessageHolder() - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - let chat = ChatItem() - let messages = generateCurrentChat(ofCount: 10) - - // MARK: Test 1 - // When: Requesting some messages - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should not be called because there's no messages received. - XCTAssertNil(completionHandlerMessages) - - // MARK: Test 2 - // When: Receiving chat with 2 messages. - messageHolder.receiving(newChat: nil, - previousChat: chat, - newMessages: Array(messages[0 ... 1])) - // Then: Completion should be called on this messages. Receiving method should not be called. - XCTAssertEqual(completionHandlerMessages!, Array(messages[0 ... 1])) - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 3 - // When: Receiving chat with the same messages. - messageHolder.receiving(newChat: chat, - previousChat: chat, - newMessages: Array(messages[0 ... 1])) - // Then: Receiving method should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 4 - // When: Receiving chat with more messages. - messageHolder.receiving(newChat: chat, - previousChat: chat, - newMessages: Array(messages[0 ... 3])) - // Then: New message should be inserted in the end. Changing or removing messages methods should not be called. - XCTAssertEqual(lastAddedMessage, messages[3]) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - - // MARK: Test 5 - // When: Receiving some non-running messages. - messageHolder.receiving(newChat: chat, - previousChat: chat, - newMessages: (Array(messages[0 ... 1]) + Array(messages[3 ... 4]))) - // Then: Message out of range should be removed, new messages should be added in the end. - XCTAssertEqual(lastRemovedMessage, messages[2]) - XCTAssertEqual(lastAddedMessage, messages[4]) - XCTAssertNil(lastMessageBeforeAdded) - } - - func testReplaceCurrentChat() throws { - // MARK: Model set up - let messageHolder = newMessageHolder() - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - let firstChat = ChatItem(id: "1") - let secondChat = ChatItem(id: "2") - let messages = generateCurrentChat(ofCount: 10) - - // MARK: Test 1 - // When: Requesting some messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion shouldn't be called. It was cached and will be called after messages are received. - XCTAssertNil(completionHandlerMessages) - - // MARK: Test 2 - // When: Receiving first chat with 2 messages. - messageHolder.receiving(newChat: firstChat, - previousChat: nil, - newMessages: Array(messages[0 ... 1])) - // Then: Completion handler should be called. Receiving method should not. - XCTAssertEqual(completionHandlerMessages!, Array(messages[0 ... 1])) - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 3 - // When: Receiving second chat with 3 messages. - messageHolder.receiving(newChat: secondChat, - previousChat: firstChat, - newMessages: Array(messages[2 ... 4])) - // Then: This messages should be added. - XCTAssertEqual(lastAddedMessage, messages[4]) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 4 - // When: Resetting to last message, requesting messages. - try messageTracker.resetTo(message: messages[4]) - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on messages [0 ... 3]. - XCTAssertEqual(completionHandlerMessages!, Array(messages[0 ... 3])) - - // MARK: Test 5 - // When: Receiving second chat with non-running messages. - messageHolder.receiving(newChat: secondChat, - previousChat: secondChat, - newMessages: ([messages[2]] + Array(messages[4 ... 5]))) - // Then: One message should be deleted. One message should be added. - XCTAssertEqual(lastRemovedMessage, messages[3]) - XCTAssertEqual(lastAddedMessage, messages[5]) - - // MARK: Test 6 - // When: Resetting to the last messages and requesting messages. - try messageTracker.resetTo(message: messages[5]) - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on messages except the last one. - XCTAssertEqual(completionHandlerMessages!, (Array(messages[0 ... 2]) + [messages[4]])) - } - - func testReplaceCurrentChatWhenPreviousHistoryReceived() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let messages = generateCurrentChat(ofCount: 10) - let history2 = generateHistoryFrom(currentChat: messages) - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - let firstChat = ChatItem(id: "1") - let secondChat = ChatItem(id: "2") - - // MARK: Test 1 - // When: Requesting messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion shouldn't be called. It was cached and will be called after messages are received. - XCTAssertNil(completionHandlerMessages) - - // MARK: Test 2 - // When: Receiving first chat with 2 messages. - messageHolder.receiving(newChat: firstChat, - previousChat: nil, - newMessages: Array(messages[0 ... 1])) - // Then: Completion handler should be called on this messages. Message listener methods should not be called. - XCTAssertEqual(completionHandlerMessages!, Array(messages[0 ... 1])) - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - - // MARK: Test 3 - // When: Receiving history part of current chat. - messageHolder.receiveHistoryUpdateWith(messages: Array(history2[0 ... 1]), - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Message listener methods should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - - // MARK: Test 4 - // When: Requesting all messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on full history. - XCTAssertEqual(completionHandlerMessages!, history1) - - // MARK: Test 5 - // When: Receiving second chat with next 3 messages. - messageHolder.receiving(newChat: secondChat, - previousChat: firstChat, - newMessages: Array(messages[2 ... 4])) - // Then: Receiving method should be called on all this messages. All current chat messages should be historified. - XCTAssertEqual(lastAddedMessage, messages[4]) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertEqual(messageHolder.getLastChatMessageIndex(), 0) - - // MARK: Test 6 - // When: Resetting to the last message. Requesting latest messages. - try messageTracker.resetTo(message: messages[4]) - try messageTracker.getNextMessages(byLimit: 20) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on previous two messages. - XCTAssertEqual(completionHandlerMessages!, Array(messages[2 ... 3])) - - // MARK: Test 7 - // When: Requesting all messages. - try messageTracker.getNextMessages(byLimit: 20) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion should be called on full history. - XCTAssertEqual(completionHandlerMessages!, (history1 + Array(history2[0 ... 1]))) - - // MARK: Test 8 - // When: Receiving second chat with one message deleted and one added. - messageHolder.receiving(newChat: secondChat, - previousChat: secondChat, - newMessages: ([messages[2]] + Array(messages[4 ... 5]))) - // Then: One message deleted. One message added. - XCTAssertEqual(lastRemovedMessage, messages[3]) - XCTAssertEqual(lastAddedMessage, messages[5]) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 9 - // When: Resetting to last message. Requesting more messages. - try messageTracker.resetTo(message: messages[5]) - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion should be called on missing messages. - XCTAssertEqual(completionHandlerMessages!, ([messages[2], messages[4]])) - } - - func testReplaceCurrentChatWhenPreviousHistoryStoredLocally() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let messages = generateCurrentChat(ofCount: 10) - let history2 = generateHistoryFrom(currentChat: messages) - let messageHolder = newMessageHolder(withHistory: (history1 + history2), - localHistory: Array(history2[0 ... 1])) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - let firstChat = ChatItem(id: "1") - let secondChat = ChatItem(id: "2") - - // MARK: Test 1 - // When: Requesting messages. - var numberOfCalls = 0 - var completionHandlerMessages: [MessageImpl]? - try messageTracker.getNextMessages(byLimit: 10) { messages in - numberOfCalls = numberOfCalls + 1 - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on stored locally history. - XCTAssertEqual(completionHandlerMessages!, Array(history2[0 ... 1])) - - // MARK: Test 2 - // When: Receiving first chat with 2 messages. - messageHolder.receiving(newChat: firstChat, - previousChat: nil, - newMessages: Array(messages[0 ... 1])) - // Then: Completion handler should not be called. Message listener methods should not be called. - XCTAssertEqual(numberOfCalls, 1) - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - - // MARK: Test 3 - // When: Requesting all messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on full history. - XCTAssertEqual(completionHandlerMessages!, history1) - - // MARK: Test 4 - // When: Receiving second chat with next 3 messages. All current chat messages should be historified. - messageHolder.receiving(newChat: secondChat, - previousChat: firstChat, - newMessages: Array(messages[2 ... 4])) - // Then: This messages should be added. - XCTAssertEqual(lastAddedMessage, messages[4]) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertEqual(messageHolder.getLastChatMessageIndex(), 0) - - // MARK: Test 5 - // When: Resetting to the last message. Requesting latest messages. - try messageTracker.resetTo(message: messages[4]) - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on missing messages. - XCTAssertEqual(completionHandlerMessages!, Array(messages[2 ... 3])) - - // MARK: Test 6 - // When: Requesting all messages. - try messageTracker.getNextMessages(byLimit: 20) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on full history. - XCTAssertEqual(completionHandlerMessages!, (history1 + Array(history2[0 ... 1]))) - - // MARK: Test 7 - // When: Receiving second chat again with one message deleted and one added. - messageHolder.receiving(newChat: secondChat, - previousChat: secondChat, - newMessages: ([messages[2]] + Array(messages[4 ... 5]))) - // Then: One message deleted. One message added. - XCTAssertEqual(lastRemovedMessage, messages[3]) - XCTAssertEqual(lastAddedMessage, messages[5]) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 8 - // When: Resetting to the last messages. Requesting missing messages. - try messageTracker.resetTo(message: messages[5]) - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on missing messages. - XCTAssertEqual(completionHandlerMessages!, ([messages[2], messages[4]])) - } - - func testResetMixedCurrentChatAndHistory() throws { - // MARK: Model set up - let history1 = generateHistory(ofCount: 10) - let history2 = generateHistory(ofCount: 10) - let currentChat = generateCurrentChat(ofCount: 10) - let nextCurrentChat = newCurrentChat() - let messageHolder = newMessageHolder(withHistory: (history1 + history2)) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: history2, - deleted: Set()) { - // No need to do anything when testing. - } - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting next 10 messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on current chat. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Requesting next 10 messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on history2. - XCTAssertEqual(completionHandlerMessages!, history2) - - // MARK: Test 3 - // When: Requesting next 10 messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on history1. - XCTAssertEqual(completionHandlerMessages!, history1) - - // MARK: Test 4 - // When: Receiving next current chat message. - messageHolder.receive(newMessage: nextCurrentChat) - // Then: This message should be added in the end. - XCTAssertEqual(lastAddedMessage, nextCurrentChat) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 5 - // When: Resetting to the last message. Requesting next 10 messages - try messageTracker.resetTo(message: nextCurrentChat) - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on current chat. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 6 - // When: Requesting next 10 messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on history2. - XCTAssertEqual(completionHandlerMessages!, history2) - - // MARK: Test 7 - // When: Requesting next 10 messages. - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on history1. - XCTAssertEqual(completionHandlerMessages!, history1) - } - - func testReceiveNewMessageWhenHistoryIsEmpty() throws { - // MARK: Model set up - let nextCurrentChat = newCurrentChat() - let messageHolder = newMessageHolder() - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: [MessageImpl](), - deleted: Set()) { - // No need to do anything when testing. - } - messageHolder.set(endOfHistoryReached: true) - - // MARK: Test 1 - // When: Requesting next messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on empty history. - XCTAssertEqual(completionHandlerMessages!, [MessageImpl]()) - - // MARK: Test 2 - // When: Receiving next current chat message. - messageHolder.receive(newMessage: nextCurrentChat) - // Then: This message should be added in the end. - XCTAssertEqual(lastAddedMessage, nextCurrentChat) - XCTAssertNil(lastMessageBeforeAdded) - } - - func testEditCurrentChatMessage() throws { - // MARK: Model set up - let nextCurrentChat = newCurrentChat() - let editedCurrentChat = newEdited(currentChatMessage: nextCurrentChat) - let messageHolder = newMessageHolder() - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: [MessageImpl](), - deleted: Set()) { - // No need to do anything when testing. - } - messageHolder.set(reachedEndOfLocalHistory: true) - - // MARK: Test 1 - // When: Requesting next messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on empty history. - XCTAssertEqual(completionHandlerMessages!, [MessageImpl]()) - - // MARK: Test 2 - // When: Receiving next current chat message. - messageHolder.receive(newMessage: nextCurrentChat) - // Then: This message should be added in the end. - XCTAssertEqual(lastAddedMessage, nextCurrentChat) - XCTAssertNil(lastMessageBeforeAdded) - - // MARK: Test 3 - // When: Changing message. - messageHolder.changed(message: editedCurrentChat) - // Then: Changing message listener method should be called on this message. - XCTAssertEqual(lastOldVersionChangedMessage, nextCurrentChat) - XCTAssertEqual(lastNewVersionChangedMessage, editedCurrentChat) - } - - func testEditCurrentChatMessageReceivedWithFullUpdate() throws { - // MARK: Model set up - var currentChat = generateCurrentChat(ofCount: 10) - let editedCurrentChat = currentChat - currentChat[9] = newEdited(currentChatMessage: currentChat[9]) - let messageHolder = newMessageHolder() - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - let chat = ChatItem() - messageHolder.receiveHistoryUpdateWith(messages: [MessageImpl](), - deleted: Set()) { - // No need to do anything when testing. - } - messageHolder.set(endOfHistoryReached: true) - messageHolder.receiving(newChat: chat, - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting next messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on current chat. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Receiving new messages (one is different). - messageHolder.receiving(newChat: chat, - previousChat: chat, - newMessages: editedCurrentChat) - // Then: That message should be changed. Other message listener methods should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertEqual(lastOldVersionChangedMessage, currentChat[9]) - XCTAssertEqual(lastNewVersionChangedMessage, editedCurrentChat[9]) - } - - func testEditHistoryMessage() throws { - // MARK: Model set up - let history = generateHistory(ofCount: 10) - let editedHistoryMessage = newEdited(historyMessage: history[9]) - let messageHolder = newMessageHolder(withHistory: history) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: history, - deleted: Set()) { - // No need to do anything when testing. - } - - // MARK: Test 1 - // When: Requesting next messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on history. - XCTAssertEqual(completionHandlerMessages!, history) - - // MARK: Test 2 - // When: Receiving changed history message. - messageHolder.receiveHistoryUpdateWith(messages: [editedHistoryMessage], - deleted: Set()) { - // No need to do anything when testing. - } - // Then: This message should be changed. - XCTAssertEqual(lastOldVersionChangedMessage, history[9]) - XCTAssertEqual(lastNewVersionChangedMessage, editedHistoryMessage) - } - - func testReplaceHistoryMessageWithEditedCurrentChatMessage() throws { - // MARK: Model set up - var currentChat = generateCurrentChat(ofCount: 10) - let history = generateHistoryFrom(currentChat: currentChat) - currentChat[9] = newEdited(currentChatMessage: currentChat[9]) - let messageHolder = newMessageHolder(withHistory: history) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: history, - deleted: Set()) { - // No need to do anything when testing. - } - - // MARK: Test 1 - // When: Requesting next messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on history. - XCTAssertEqual(completionHandlerMessages!, history) - - // MARK: Test 2 - // When: Receiving current chat with one changed message. - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: currentChat) - // Then: This message should be changed. - XCTAssertEqual(lastOldVersionChangedMessage, history[9]) - XCTAssertEqual(lastNewVersionChangedMessage, currentChat[9]) - } - - func testReplaceCurrentChatMessageWithEditedHistoryMessageInClosedChat() throws { - // MARK: Model set up - let currentChat = generateCurrentChat(ofCount: 10) - let history = generateHistoryFrom(currentChat: currentChat) - let editedHistoryMessage = newEdited(historyMessage: history[9]) - let messageHolder = newMessageHolder(withHistory: history) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - let chat = ChatItem() - messageHolder.receiving(newChat: chat, - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting next messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on current chat. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Receiving chat without messages and history messages. - messageHolder.receiving(newChat: nil, - previousChat: chat, - newMessages: [MessageImpl]()) - messageHolder.receiveHistoryUpdateWith(messages: history, - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Message listener methods should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - - // MARK: Test 3 - // When: Receiving changed history message. - messageHolder.receiveHistoryUpdateWith(messages: [editedHistoryMessage], - deleted: Set()) { - // No need to do anything when testing. - } - // Then: This message should be changed. - XCTAssertEqual(lastOldVersionChangedMessage, currentChat[9]) - XCTAssertEqual(lastNewVersionChangedMessage, editedHistoryMessage) - } - - func testReplaceCurrentChatMessageWithEditedHistoryMessageInOpenChat() throws { - // MARK: Model set up - let currentChat = generateCurrentChat(ofCount: 10) - let history = generateHistoryFrom(currentChat: currentChat) - let editedHistoryMessage = newEdited(historyMessage: history[9]) - let messageHolder = newMessageHolder(withHistory: history) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiving(newChat: ChatItem(), - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on current chat. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Receiving history. - messageHolder.receiveHistoryUpdateWith(messages: history, - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Message listener methods should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - - // MARK: Test 3 - // When: Receiving edited history message. - messageHolder.receiveHistoryUpdateWith(messages: [editedHistoryMessage], - deleted: Set()) { - // No need to do anything when testing. - } - // Then: While current chat exists changes in history should not have an effect.. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - } - - func testReceiveEditedHistoryInClosedChat() throws { - // MARK: Model set up - let currentChat = generateCurrentChat(ofCount: 10) - var history = generateHistoryFrom(currentChat: currentChat) - history[9] = newEdited(historyMessage: history[9]) - let messageHolder = newMessageHolder(withHistory: history) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - let chat = ChatItem() - messageHolder.receiving(newChat: chat, - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on current chat. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: Receiving empty chat. - messageHolder.receiving(newChat: nil, - previousChat: chat, - newMessages: [MessageImpl]()) - // Then: Message listener methods should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - - // MARK: Test 3 - // When: Receiving history. - messageHolder.receiveHistoryUpdateWith(messages: history, - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Edited message should be changed. - XCTAssertEqual(lastOldVersionChangedMessage, currentChat[9]) - XCTAssertEqual(lastNewVersionChangedMessage, history[9]) - } - - func testReceiveEditedHistoryAndCloseChat() throws { - // MARK: Set up - let currentChat = generateCurrentChat(ofCount: 10) - var history = generateHistoryFrom(currentChat: currentChat) - history[9] = newEdited(historyMessage: history[9]) - let messageHolder = newMessageHolder(withHistory: history) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - let chat = ChatItem() - messageHolder.receiving(newChat: chat, - previousChat: nil, - newMessages: currentChat) - - // MARK: Test 1 - // When: Requesting messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on current chat. - XCTAssertEqual(completionHandlerMessages!, currentChat) - - // MARK: Test 2 - // When: receiving history. - messageHolder.receiveHistoryUpdateWith(messages: history, - deleted: Set()) { - // No need to do anything when testing. - } - // Then: Message listener methods should not be called. - XCTAssertNil(lastAddedMessage) - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertNil(lastRemovedMessage) - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - - // MARK: Test 3 - // When: Receiving empty chat. - messageHolder.receiving(newChat: nil, - previousChat: chat, - newMessages: [MessageImpl]()) - // Then: Edited message should be changed. - XCTAssertEqual(lastOldVersionChangedMessage, currentChat[9]) - XCTAssertEqual(lastNewVersionChangedMessage, history[9]) - } - - func testReceiveCurrentChatWhenItHoldedAsHistory() throws { - // MARK: Model set up - let currentChat = generateCurrentChat(ofCount: 10) - let history = generateHistoryFrom(currentChat: currentChat) - let messageHolder = newMessageHolder(withHistory: history) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - messageHolder.receiveHistoryUpdateWith(messages: history, - deleted: Set()) { - // No need to do anything when testing. - } - - // MARK: Test 1 - // When: Requesting messages. - var completionHandlerMessages: [MessageImpl]? = nil - var numberOfCalls = 0 - try messageTracker.getNextMessages(byLimit: 10) { messages in - completionHandlerMessages = messages as? [MessageImpl] - numberOfCalls = numberOfCalls + 1 - } - // Then: Completion handler should be called on history. - XCTAssertEqual(completionHandlerMessages!, history) - XCTAssertEqual(numberOfCalls, 1) - - // MARK: Test 2 - // When: Received current chat message twice which is holded as local history. - messageHolder.receive(newMessage: currentChat[9]) - messageHolder.receive(newMessage: currentChat[9]) - // Then: Message shouldn't be received as new. - XCTAssertEqual(numberOfCalls, 1) - } - - func testReplacingHistoryWithCurrentChat() throws { - // MARK: Model set up - let currentChat = generateCurrentChat(ofCount: 1) - let history = generateHistoryFrom(currentChat: currentChat) - let messageHolder = newMessageHolder(withHistory: history) - let messageTracker = try messageHolder.newMessageTracker(withMessageListener: self) - let chat = ChatItem() - messageHolder.receiveHistoryUpdateWith(messages: history, - deleted: Set()) { - // No need to do anything when testing. - } - - // MARK: Test 1 - // When: Requesting messages. - var completionHandlerMessages: [MessageImpl]? = nil - try messageTracker.getNextMessages(byLimit: 1) { messages in - completionHandlerMessages = messages as? [MessageImpl] - } - // Then: Completion handler should be called on history. - XCTAssertEqual(completionHandlerMessages!, history) - - // MARK: Test 2 - // When: Receiving chat with history. - messageHolder.receiving(newChat: nil, - previousChat: chat, - newMessages: currentChat) - // Then: No messages should be changed. - XCTAssertNil(lastOldVersionChangedMessage) - XCTAssertNil(lastNewVersionChangedMessage) - - // MARK: Test 3 - // When: Deleting current chat message. - messageHolder.deletedMessageWith(id: currentChat[0].getCurrentChatID()!) - // Then: Message should be deleted. - XCTAssertEqual(lastRemovedMessage, currentChat[0]) - - // MARK: Test 4 - // When: Receiving chat again. - messageHolder.receiving(newChat: chat, - previousChat: chat, - newMessages: currentChat) - // Then: Message should be added. - XCTAssertNil(lastMessageBeforeAdded) - XCTAssertEqual(lastAddedMessage, currentChat[0]) - } - - func testSetMessagesToSend() { - let messageToSend = MessageToSend(serverURLString: "http://demo.webim.ru", - id: "1", - senderName: "Sender", - type: .OPERATOR, - text: "Text", - timeInMicrosecond: 1) - let messageHolder = newMessageHolder() - messageHolder.set(messagesToSend: [messageToSend]) - - XCTAssertEqual([messageToSend], - messageHolder.getMessagesToSend()) - } - - func testSendingMessage() { - let messageToSend = MessageToSend(serverURLString: "http://demo.webim.ru", - id: "1", - senderName: "Sender", - type: .OPERATOR, - text: "Text", - timeInMicrosecond: 1) - let messageHolder = newMessageHolder() - messageHolder.sending(message: messageToSend) - - XCTAssertEqual([messageToSend], - messageHolder.getMessagesToSend()) - } - - func testSendingCancelled() { - let messageID = "1" - let messageToSend = MessageToSend(serverURLString: "http://demo.webim.ru", - id: messageID, - senderName: "Sender", - type: .OPERATOR, - text: "Text", - timeInMicrosecond: 1) - let messageHolder = newMessageHolder() - messageHolder.sending(message: messageToSend) - messageHolder.sendingCancelledWith(messageID: messageID) - - XCTAssertTrue(messageHolder.getMessagesToSend().isEmpty) - } - - // MARK: - Mocking RemoteHistoryProvider - final class RemoteHistoryProviderForTests: RemoteHistoryProvider { - - // MARK: - Properties - var history: [MessageImpl] - var numberOfCalls = 0 - - // MARK: - Initialization - init(withWebimActions webimActions: WebimActions, - historyMessageMapper: MessageMapper, - historyMetaInformation: HistoryMetaInformationStorage, - history: [MessageImpl] = [MessageImpl]()) { - self.history = history - - super.init(webimActions: webimActions, - historyMessageMapper: historyMessageMapper, - historyMetaInformationStorage: historyMetaInformation) - } - - // MARK: - Methods - override func requestHistory(beforeTimestamp: Int64, - completion: @escaping ([MessageImpl], Bool) -> ()) { - var beforeIndex = 0 - for (messageIndex, message) in history.enumerated() { - if message.getTimeInMicrosecond() <= beforeTimestamp { - beforeIndex = messageIndex - - continue - } else { - break - } - } - - let afterIndex = max(0, (beforeIndex - 100)) - - numberOfCalls = numberOfCalls + 1 - - completion((beforeIndex <= 0) ? [MessageImpl]() : Array(history[afterIndex ..< beforeIndex]), (afterIndex != 0)) - } - - } - -} - -// MARK: - MessageListener -extension MessageHolderTests: MessageListener { - - func added(message newMessage: Message, - after previousMessage: Message?) { - lastAddedMessage = newMessage as? MessageImpl - lastMessageBeforeAdded = previousMessage as? MessageImpl - } - - func removed(message: Message) { - lastRemovedMessage = message as? MessageImpl - } - - func removedAllMessages() { - // No need to do anything when testing. - } - - func changed(message oldVersion: Message, to newVersion: Message) { - lastOldVersionChangedMessage = oldVersion as? MessageImpl - lastNewVersionChangedMessage = newVersion as? MessageImpl - } - -} - - -// MARK: - -extension MessageImpl { - - func getPrimaryID() -> String! { - return (getSource().isHistoryMessage() ? getHistoryID()!.getDBid() : getCurrentChatID()) - } - -} diff --git a/ios/libs/Webim/Example/Tests/MessageImplTests.swift b/ios/libs/Webim/Example/Tests/MessageImplTests.swift deleted file mode 100755 index 457e689..0000000 --- a/ios/libs/Webim/Example/Tests/MessageImplTests.swift +++ /dev/null @@ -1,350 +0,0 @@ -// -// MessageImplTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 20.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class MessageImplTests: XCTestCase { - - // MARK: - Tests - func testToString() { - let message = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - let expectedString = """ -MessageImpl { - serverURLString = http://demo.webim.ru, - ID = id, - operatorID = nil, - senderAvatarURLString = nil, - senderName = Name, - type = VISITOR, - text = Text, - timeInMicrosecond = 0, - attachment = nil, - historyMessage = false, - currentChatID = nil, - historyID = nil, - rawText = nil -} -""" - - XCTAssertEqual(message.toString(), - expectedString) - } - - func testGetSenderAvatarURL() { - let message = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - - XCTAssertNil(message.getSenderAvatarFullURL()) - } - - func testGetSendStatus() { - let message = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - - XCTAssertEqual(message.getSendStatus(), - MessageSendStatus.SENT) - } - - func testIsEqual() { - let message = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - - let message1 = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id1", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - let message2 = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name1", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - let message3 = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text1", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - let message4 = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .OPERATOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - let message5 = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - - XCTAssertFalse(message.isEqual(to: message1)) - XCTAssertFalse(message.isEqual(to: message2)) - XCTAssertFalse(message.isEqual(to: message3)) - XCTAssertFalse(message.isEqual(to: message4)) - XCTAssertTrue(message.isEqual(to: message5)) - } - - // MARK: MessageSource tests - - func testAssertIsCurrentChat() { - let message = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - - XCTAssertNoThrow(try message.getSource().assertIsCurrentChat()) - } - - func testAssertIsHistory() { - let message = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - - XCTAssertThrowsError(try message.getSource().assertIsHistory()) - } - - func testGetHistoryID() { - let message = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - - XCTAssertNil(message.getHistoryID()) - } - - func testGetCurrentChatID() { - let currentChatID = "id" - let message = MessageImpl(serverURLString: "http://demo.webim.ru", - id: "id", - operatorID: nil, - senderAvatarURLString: nil, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: currentChatID, - rawText: nil) - - XCTAssertEqual(currentChatID, - message.getCurrentChatID()) - } - - func testGetSenderAvatarFullURL() { - let baseURLString = "http://demo.webim.ru" - let avatarURLString = "/image.jpg" - let message = MessageImpl(serverURLString: baseURLString, - id: "id", - operatorID: nil, - senderAvatarURLString: avatarURLString, - senderName: "Name", - sendStatus: .SENT, - type: .VISITOR, - data: nil, - text: "Text", - timeInMicrosecond: 0, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil) - - XCTAssertEqual(URL(string: (baseURLString + avatarURLString)), - message.getSenderAvatarFullURL()) - } - -} - -// MARK: - -class MessageAttachmentTests: XCTestCase { - - // MARK: - Tests - func testInit() { - let messageAttachment = MessageAttachmentImpl(urlString: "/image.jpg", - size: 1, - filename: "image", - contentType: "image/jpeg", - imageInfo: nil) - - XCTAssertEqual(messageAttachment.getContentType(), - "image/jpeg") - XCTAssertEqual(messageAttachment.getFileName(), - "image") - XCTAssertNil(messageAttachment.getImageInfo()) - XCTAssertEqual(messageAttachment.getSize(), - 1) - XCTAssertEqual(messageAttachment.getURL(), - URL(string: "/image.jpg")!) - } - -} - -// MARK: - -class ImageInfoImplTests: XCTestCase { - - // MARK: - Tests - func testInit() { - let imageInfo = ImageInfoImpl(withThumbURLString: "https://demo.webim.ru/thumb.jpg", - width: 100, - height: 200) - - - XCTAssertEqual(imageInfo.getThumbURL(), - URL(string: "https://demo.webim.ru/thumb.jpg")) - XCTAssertEqual(imageInfo.getWidth(), - 100) - XCTAssertEqual(imageInfo.getHeight(), - 200) - } - -} diff --git a/ios/libs/Webim/Example/Tests/MessageItemTests.swift b/ios/libs/Webim/Example/Tests/MessageItemTests.swift deleted file mode 100755 index dfd075a..0000000 --- a/ios/libs/Webim/Example/Tests/MessageItemTests.swift +++ /dev/null @@ -1,149 +0,0 @@ -// -// MessageItemTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 16.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class MessageItemTests: XCTestCase { - - // MARK: - Constants - private static let MESSAGE_ITEM_JSON_STRING = """ -{ - "avatar" : "/webim/images/avatar/demo_33202.png", - "chatId" : "2489", - "authorId" : 33202, - "data" : null, - "id" : "26871", - "ts_m" : 1518609964579372, - "text" : "42", - "clientSideId" : "84e51d5638524ee7833a1fe19a1f2448", - "kind" : "operator", - "name" : "Евгения Техподдержка" -} -""" - private static let MESSAGE_ITEM_TO_COMPARE_JSON_STRING_1 = """ -{ - "avatar" : "/webim/images/avatar/demo_33202.png", - "chatId" : "2489", - "authorId" : 33202, - "data" : null, - "id" : "26871", - "ts_m" : 1518609964579372, - "text" : "42", - "clientSideId" : "84e51d5638524ee7833a1fe19a1f2448", - "kind" : "operator", - "name" : "Евгения Техподдержка" -} -""" // Same. - private static let MESSAGE_ITEM_TO_COMPARE_JSON_STRING_2 = """ -{ - "avatar" : "/webim/images/avatar/demo_33202.png", - "chatId" : "2489", - "authorId" : 33202, - "data" : null, - "id" : "26872", - "ts_m" : 1518609964579372, - "text" : "42", - "clientSideId" : "84e51d5638524ee7833a1fe19a1f2448", - "kind" : "operator", - "name" : "Евгения Техподдержка" -} -""" // Different IDs. - private static let MESSAGE_ITEM_TO_COMPARE_JSON_STRING_3 = """ -{ - "avatar" : "/webim/images/avatar/demo_33202.png", - "chatId" : "2489", - "authorId" : 33202, - "data" : null, - "id" : "26871", - "ts_m" : 1518609964579372, - "text" : "42", - "clientSideId" : "84e51d5638524ee7833a1fe19a1f2449", - "kind" : "operator", - "name" : "Евгения Техподдержка" -} -""" // Different client side IDs. - private static let MESSAGE_ITEM_TO_COMPARE_JSON_STRING_4 = """ -{ - "avatar" : "/webim/images/avatar/demo_33202.png", - "chatId" : "2489", - "authorId" : 33202, - "data" : null, - "id" : "26871", - "ts_m" : 1518609964579372, - "text" : "43", - "clientSideId" : "84e51d5638524ee7833a1fe19a1f2448", - "kind" : "operator", - "name" : "Евгения Техподдержка" -} -""" // Different texts. - - // MARK: - Properties - private let messageItemDictionary = try! JSONSerialization.jsonObject(with: MessageItemTests.MESSAGE_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - - // MARK: - Tests - func testInit() { - let messageItem = MessageItem(jsonDictionary: messageItemDictionary) - - XCTAssertEqual(messageItem.getClientSideID(), - "84e51d5638524ee7833a1fe19a1f2448") - XCTAssertEqual(messageItem.getID(), - "26871") - XCTAssertEqual(messageItem.getText(), - "42") - XCTAssertEqual(messageItem.getSenderID(), - "33202") - XCTAssertEqual(messageItem.getSenderAvatarURLString(), - "/webim/images/avatar/demo_33202.png") - XCTAssertNil(messageItem.getData()) - XCTAssertFalse(messageItem.isDeleted()) - XCTAssertEqual(messageItem.getKind(), - MessageItem.MessageKind.operatorMessage) - XCTAssertEqual(messageItem.getSenderName(), - "Евгения Техподдержка") - XCTAssertEqual(messageItem.getTimeInMicrosecond(), - 1518609964579372) - } - - func testEquals() { - let messageItemDictionary1 = try! JSONSerialization.jsonObject(with: MessageItemTests.MESSAGE_ITEM_TO_COMPARE_JSON_STRING_1.data(using: .utf8)!, - options: []) as! [String : Any?] - let messageItemDictionary2 = try! JSONSerialization.jsonObject(with: MessageItemTests.MESSAGE_ITEM_TO_COMPARE_JSON_STRING_2.data(using: .utf8)!, - options: []) as! [String : Any?] - let messageItemDictionary3 = try! JSONSerialization.jsonObject(with: MessageItemTests.MESSAGE_ITEM_TO_COMPARE_JSON_STRING_3.data(using: .utf8)!, - options: []) as! [String : Any?] - let messageItemDictionary4 = try! JSONSerialization.jsonObject(with: MessageItemTests.MESSAGE_ITEM_TO_COMPARE_JSON_STRING_4.data(using: .utf8)!, - options: []) as! [String : Any?] - - XCTAssertTrue(MessageItem(jsonDictionary: messageItemDictionary) == MessageItem(jsonDictionary: messageItemDictionary1)) - XCTAssertTrue(MessageItem(jsonDictionary: messageItemDictionary) != MessageItem(jsonDictionary: messageItemDictionary2)) - XCTAssertTrue(MessageItem(jsonDictionary: messageItemDictionary) != MessageItem(jsonDictionary: messageItemDictionary3)) - XCTAssertTrue(MessageItem(jsonDictionary: messageItemDictionary) != MessageItem(jsonDictionary: messageItemDictionary4)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/MessageStreamImplTests.swift b/ios/libs/Webim/Example/Tests/MessageStreamImplTests.swift deleted file mode 100755 index b8afd40..0000000 --- a/ios/libs/Webim/Example/Tests/MessageStreamImplTests.swift +++ /dev/null @@ -1,202 +0,0 @@ -// -// MessageStreamImplTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 22.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class MessageStreamImplTests: XCTestCase { - - // MARK: - Properties - var messageStream: MessageStreamImpl? - var webimActions: WebimActions? - - // MARK: - Methods - override func setUp() { - super.setUp() - - let serverURLString = "https://demo.webim.ru" - let sessionDestroyer = SessionDestroyer() - let accessChecker = AccessChecker(thread: Thread.current, - sessionDestroyer: sessionDestroyer) - let queue = DispatchQueue.main - webimActions = WebimActions(baseURL: serverURLString, - actionRequestLoop: ActionRequestLoopForTests(completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: sessionDestroyer, - queue: queue), - internalErrorListener: InternalErrorListenerForTests())) - messageStream = MessageStreamImpl(serverURLString: serverURLString, - currentChatMessageFactoriesMapper: CurrentChatMessageMapper(withServerURLString: serverURLString), - sendingMessageFactory: SendingFactory(withServerURLString: serverURLString), - operatorFactory: OperatorFactory(withServerURLString: serverURLString), - accessChecker: accessChecker, - webimActions: webimActions!, - messageHolder: MessageHolder(accessChecker: accessChecker, - remoteHistoryProvider: RemoteHistoryProvider(webimActions: webimActions!, - historyMessageMapper: HistoryMessageMapper(withServerURLString: serverURLString), - historyMetaInformationStorage: MemoryHistoryMetaInformationStorage()), - historyStorage: MemoryHistoryStorage(), - reachedEndOfRemoteHistory: true), - messageComposingHandler: MessageComposingHandler(webimActions: webimActions!, - queue: queue), - locationSettingsHolder: LocationSettingsHolder(userDefaultsKey: "key")) - } - - // MARK: - Tests - - func testSetVisitSessionState() { - messageStream!.set(visitSessionState: .chat) - - XCTAssertEqual(messageStream!.getVisitSessionState(), - VisitSessionState.CHAT) - } - - func testSetUnreadByOperatorTimestamp() { - let date = Date() - messageStream!.set(unreadByOperatorTimestamp: date) - - XCTAssertEqual(messageStream!.getUnreadByOperatorTimestamp(), - date) - } - - func testSetUnreadByVisitorTimestamp() { - let date = Date() - messageStream!.set(unreadByVisitorTimestamp: date) - - XCTAssertEqual(messageStream!.getUnreadByVisitorTimestamp(), - date) - } - - func testOnReceivingDepartmentList() { - let departmentItemDictionary = try! JSONSerialization.jsonObject(with: DEPARTMENT_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - let departmentItem = DepartmentItem(jsonDictionary: departmentItemDictionary)! - messageStream!.onReceiving(departmentItemList: [departmentItem]) - - XCTAssertEqual(messageStream!.getDepartmentList()![0].getKey(), - "mobile_test_1") - XCTAssertEqual(messageStream!.getDepartmentList()![0].getName(), - "Mobile Test 1") - XCTAssertEqual(messageStream!.getDepartmentList()![0].getDepartmentOnlineStatus(), - DepartmentOnlineStatus.OFFLINE) - XCTAssertEqual(messageStream!.getDepartmentList()![0].getOrder(), - 100) - XCTAssertEqual(messageStream!.getDepartmentList()![0].getLocalizedNames()!, - ["ru" : "Mobile Test 1"]) - XCTAssertEqual(messageStream!.getDepartmentList()![0].getLogoURL()!, - URL(string: "https://demo.webim.ru/webim/images/department_logo/wmtest2_1.png")!) - } - - func testGetChatState() { - XCTAssertEqual(messageStream!.getChatState(), - ChatState.UNKNOWN) - } - - func testGetLocationSettings() { - XCTAssertFalse(messageStream!.getLocationSettings().areHintsEnabled()) // Initial value must be false. - } - - func testGetCurrentOperator() { - XCTAssertNil(messageStream!.getCurrentOperator()) // Initially operator does not exist. - } - - func testSetVisitSessionStateListener() { - let visitSessionStateListener = VisitSessionStateListenerForTests() - messageStream!.set(visitSessionStateListener: visitSessionStateListener) - - messageStream!.set(visitSessionState: .chat) - - XCTAssertTrue(visitSessionStateListener.called) - XCTAssertEqual(visitSessionStateListener.state!, - VisitSessionState.CHAT) - } - - func testSetOnlineStatusChangeListener() { - let onlineStatusChangeListener = OnlineStatusChangeListenerForTests() - messageStream!.set(onlineStatusChangeListener: onlineStatusChangeListener) - - messageStream!.set(onlineStatus: .busyOnline) - XCTAssertFalse(onlineStatusChangeListener.called) - - messageStream!.onOnlineStatusChanged(to: .busyOffline) - - XCTAssertTrue(onlineStatusChangeListener.called) - XCTAssertEqual(onlineStatusChangeListener.status!, - OnlineStatus.BUSY_OFFLINE) - } - - func testChangingChatState() { - let chatItemDictionary = try! JSONSerialization.jsonObject(with: ChatItemTests.CHAT_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - let chatItem = ChatItem(jsonDictionary: chatItemDictionary) - messageStream!.changingChatStateOf(chat: chatItem) - - XCTAssertEqual(messageStream!.getChatState(), - ChatState.CHATTING) - XCTAssertNil(messageStream!.getUnreadByOperatorTimestamp()) - XCTAssertNil(messageStream!.getUnreadByVisitorTimestamp()) - XCTAssertEqual(messageStream!.getCurrentOperator()!.getID(), "33201") - } - - func testGetWebimActions() { - XCTAssertTrue(webimActions! === messageStream!.getWebimActions()) - } - -} - -// MARK: - -fileprivate class VisitSessionStateListenerForTests: VisitSessionStateListener { - - // MARK: - Properties - var called = false - var state: VisitSessionState? - - // MARK: - Methods - // MARK: VisitSessionStateListener protocol methods - func changed(state previousState: VisitSessionState, - to newState: VisitSessionState) { - called = true - state = newState - } - -} - -// MARK: - -fileprivate class OnlineStatusChangeListenerForTests: OnlineStatusChangeListener { - - // MARK: - Properties - var called = false - var status: OnlineStatus? - - // MARK: - Methods - // MARK: OnlineStatusChangeListener protocol methods - func changed(onlineStatus previousOnlineStatus: OnlineStatus, - to newOnlineStatus: OnlineStatus) { - called = true - status = newOnlineStatus - } - - -} diff --git a/ios/libs/Webim/Example/Tests/Mocks/ActionRequestLoopMock.swift b/ios/libs/Webim/Example/Tests/Mocks/ActionRequestLoopMock.swift deleted file mode 100755 index 5b9abd4..0000000 --- a/ios/libs/Webim/Example/Tests/Mocks/ActionRequestLoopMock.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// ActionRequestLoop.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 30.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary - -final class ActionRequestLoopForTests: ActionRequestLoop { - - // MARK: - Properties - var webimRequest: WebimRequest? - - // MARK: - Methods - override func enqueue(request: WebimRequest) { - webimRequest = request - } - -} diff --git a/ios/libs/Webim/Example/Tests/Mocks/InternalErrorListenerMock.swift b/ios/libs/Webim/Example/Tests/Mocks/InternalErrorListenerMock.swift deleted file mode 100755 index efffa64..0000000 --- a/ios/libs/Webim/Example/Tests/Mocks/InternalErrorListenerMock.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// InternalErrorListener.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 29.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary - -final class InternalErrorListenerForTests: InternalErrorListener { - - func on(error: String) { - // No need to do anything when testing. - } - -} diff --git a/ios/libs/Webim/Example/Tests/OperatorFactoryTests.swift b/ios/libs/Webim/Example/Tests/OperatorFactoryTests.swift deleted file mode 100755 index edc07e5..0000000 --- a/ios/libs/Webim/Example/Tests/OperatorFactoryTests.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// OperatorFactoryTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class OperatorFactoryTests: XCTestCase { - - // MARK: - Constants - private static let serverURLString = "http://demo.webim.ru" - - // MARK: - Properties - private let operatorFactory = OperatorFactory(withServerURLString: serverURLString) - - // MARK: - Tests - func testCreateOperator() { - let operatorItemDictionary = try! JSONSerialization.jsonObject(with: OPERATOR_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - var operatorItem = OperatorItem(jsonDictionary: operatorItemDictionary) - let `operator` = operatorFactory.createOperatorFrom(operatorItem: operatorItem) - - XCTAssertEqual(`operator`!.getID(), - operatorItem!.getID()) - XCTAssertEqual(`operator`!.getName(), - operatorItem!.getFullName()) - XCTAssertEqual(URL(string: (OperatorFactoryTests.serverURLString + operatorItem!.getAvatarURLString()!)), - `operator`!.getAvatarURL()!) - - operatorItem = nil - XCTAssertNil(operatorFactory.createOperatorFrom(operatorItem: operatorItem)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/OperatorImplTests.swift b/ios/libs/Webim/Example/Tests/OperatorImplTests.swift deleted file mode 100755 index 41ee156..0000000 --- a/ios/libs/Webim/Example/Tests/OperatorImplTests.swift +++ /dev/null @@ -1,87 +0,0 @@ -// -// OperatorImplTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 02.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class OperatorImplTests: XCTestCase { - - // MARK: - Tests - - func testInit() { - let `operator` = OperatorImpl(id: "id", - name: "name", - avatarURLString: nil) - - XCTAssertEqual(`operator`.getID(), - "id") - XCTAssertEqual(`operator`.getName(), - "name") - XCTAssertNil(`operator`.getAvatarURL()) - } - - func testEquals() { - var operator1: OperatorImpl? = OperatorImpl(id: "id1", - name: "name1", - avatarURLString: "avatar1.jpg") - var operator2: OperatorImpl? = OperatorImpl(id: "id1", - name: "name1", - avatarURLString: "avatar1.jpg") - XCTAssertTrue(operator1 == operator2) - - operator1 = OperatorImpl(id: "id1", - name: "name1", - avatarURLString: "avatar1.jpg") - operator2 = OperatorImpl(id: "id2", - name: "name2", - avatarURLString: "avatar2.jpg") - XCTAssertFalse(operator1 == operator2) - - operator1 = OperatorImpl(id: "id1", - name: "name1", - avatarURLString: "avatar1.jpg") - operator2 = OperatorImpl(id: "id2", - name: "name1", - avatarURLString: "avatar1.jpg") - XCTAssertFalse(operator1 == operator2) - - operator1 = OperatorImpl(id: "id1", - name: "name1", - avatarURLString: "avatar1.jpg") - operator2 = OperatorImpl(id: "id1", - name: "name1", - avatarURLString: nil) - XCTAssertFalse(operator1 == operator2) - - operator1 = OperatorImpl(id: "id1", - name: "name1", - avatarURLString: "avatar1.jpg") - operator2 = nil - XCTAssertFalse(operator1 == operator2) - } - -} diff --git a/ios/libs/Webim/Example/Tests/OperatorItemTests.swift b/ios/libs/Webim/Example/Tests/OperatorItemTests.swift deleted file mode 100755 index 9cb064d..0000000 --- a/ios/libs/Webim/Example/Tests/OperatorItemTests.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// OperatorItemTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 16.02.18. -// Copyright © 2018 CocoaPods. All rights reserved. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -// MARK: - Global constants -let OPERATOR_ITEM_JSON_STRING = """ -{ - "avatar" : "/webim/images/avatar/demo_33201.png", - "fullname" : "Administrator", - "id" : 33201, - "robotType" : null, - "departmentKeys" : [ - "telegram", - "test3", - "test2" - ], - "langToFullname" : { }, - "sip" : "10002715000033201" -} -""" - -class OperatorItemTests: XCTestCase { - - // MARK: - Tests - - func testInit() { - let operatorItemDictionary = try! JSONSerialization.jsonObject(with: OPERATOR_ITEM_JSON_STRING.data(using: .utf8)!, - options: []) as! [String : Any?] - let operatorItem = OperatorItem(jsonDictionary: operatorItemDictionary)! - - XCTAssertEqual(operatorItem.getID(), - "33201") - XCTAssertEqual(operatorItem.getFullName(), - "Administrator") - XCTAssertEqual(operatorItem.getAvatarURLString(), - "/webim/images/avatar/demo_33201.png") - } - - func testInitFails() { - let incorrectOperatorJSONString = """ -{ - "avatar" : "/webim/images/avatar/demo_33201.png", - "fullname" : "Administrator", - "robotType" : null, - "departmentKeys" : [ - "telegram", - "test3", - "test2" - ], - "langToFullname" : { }, - "sip" : "10002715000033201" -} -""" - let operatorItemDictionary = try! JSONSerialization.jsonObject(with: incorrectOperatorJSONString.data(using: .utf8)!, - options: []) as! [String : Any?] - - XCTAssertNil(OperatorItem(jsonDictionary: operatorItemDictionary)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/ProvidedVisitorFieldsTests.swift b/ios/libs/Webim/Example/Tests/ProvidedVisitorFieldsTests.swift deleted file mode 100755 index aca9966..0000000 --- a/ios/libs/Webim/Example/Tests/ProvidedVisitorFieldsTests.swift +++ /dev/null @@ -1,73 +0,0 @@ -// -// ProvidedVisitorFieldsTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 20.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class ProvidedVisitorFieldsTests: XCTestCase { - - // MARK: - Constants - private static let PROVIDED_VISITOR_FIELDS_JSON_STRING = """ -{ - "id" : "1234567890987654321", - "display_name" : "Никита", - "crc" : "ffadeb6aa3c788200824e311b9aa44cb" -} -""" - private static let PROVIDED_VISITOR_FIELDS_JSON_DATA = ProvidedVisitorFieldsTests.PROVIDED_VISITOR_FIELDS_JSON_STRING.data(using: .utf8)! - private static let WRONG_PROVIDED_VISITOR_FIELDS_JSON_STRING = """ -{ - "display_name" : "Никита", - "crc" : "ffadeb6aa3c788200824e311b9aa44cb" -} -""" - - // MARK: - Tests - - func testInitWithString() { - let providedVisitorFields = ProvidedVisitorFields(withJSONString: ProvidedVisitorFieldsTests.PROVIDED_VISITOR_FIELDS_JSON_STRING)! - - XCTAssertEqual(ProvidedVisitorFieldsTests.PROVIDED_VISITOR_FIELDS_JSON_STRING, - providedVisitorFields.getJSONString()) - XCTAssertEqual("1234567890987654321", - providedVisitorFields.getID()) - } - - func testInitWithData() { - let providedVisitorFields = ProvidedVisitorFields(withJSONObject: ProvidedVisitorFieldsTests.PROVIDED_VISITOR_FIELDS_JSON_DATA)! - - XCTAssertEqual(ProvidedVisitorFieldsTests.PROVIDED_VISITOR_FIELDS_JSON_STRING, - providedVisitorFields.getJSONString()) - XCTAssertEqual("1234567890987654321", - providedVisitorFields.getID()) - } - - func testInitFailed() { - XCTAssertNil(ProvidedVisitorFields(withJSONString: ProvidedVisitorFieldsTests.WRONG_PROVIDED_VISITOR_FIELDS_JSON_STRING)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/RatingItemTests.swift b/ios/libs/Webim/Example/Tests/RatingItemTests.swift deleted file mode 100755 index 71b021d..0000000 --- a/ios/libs/Webim/Example/Tests/RatingItemTests.swift +++ /dev/null @@ -1,64 +0,0 @@ -// -// RatingItemTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class RatingItemTests: XCTestCase { - - // MARK: - Tests - - func testInit() { - let ratingItemJSONString = """ -{ - "operatorId" : 33201, - "rating" : 2 -} -""" - let ratingItemDictionary = try! JSONSerialization.jsonObject(with: ratingItemJSONString.data(using: .utf8)!, - options: []) as! [String : Any?] - let ratingItem = RatingItem(jsonDictionary: ratingItemDictionary) - - XCTAssertEqual(ratingItem!.getOperatorID(), - "33201") - XCTAssertEqual(ratingItem!.getRating(), - 2) - } - - func testInitFails() { - let ratingItemJSONString = """ -{ - "operatorId" : 33201 -} -""" - let ratingItemDictionary = try! JSONSerialization.jsonObject(with: ratingItemJSONString.data(using: .utf8)!, - options: []) as! [String : Any?] - - XCTAssertNil(RatingItem(jsonDictionary: ratingItemDictionary)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/SQLiteHistoryStorageTests.swift b/ios/libs/Webim/Example/Tests/SQLiteHistoryStorageTests.swift deleted file mode 100755 index 136505a..0000000 --- a/ios/libs/Webim/Example/Tests/SQLiteHistoryStorageTests.swift +++ /dev/null @@ -1,196 +0,0 @@ -// -// SQLiteHistoryStorageTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 20.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class SQLiteHistoryStorageTests: XCTestCase { - - // MARK: - Constants - private static let DB_NAME = "test" - private static let SERVER_URL_STRING = "https://demo.webim.ru" - - // MARK: - Properties - var sqLiteHistoryStorage: SQLiteHistoryStorage? - - // MARK: - Methods - override func setUp() { - super.setUp() - - let queue = DispatchQueue.main - let exeIfNotDestroyedHandlerExecutor = ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: SessionDestroyer(), - queue: queue) - let internalErrorListener = InternalErrorListenerForTests() - let actionRequestLoop = ActionRequestLoopForTests(completionHandlerExecutor: exeIfNotDestroyedHandlerExecutor, - internalErrorListener: internalErrorListener) - sqLiteHistoryStorage = SQLiteHistoryStorage(dbName: SQLiteHistoryStorageTests.DB_NAME, - serverURL: SQLiteHistoryStorageTests.DB_NAME, - webimClient: WebimClient(withActionRequestLoop: actionRequestLoop, - deltaRequestLoop: DeltaRequestLoop(deltaCallback: DeltaCallback(currentChatMessageMapper: CurrentChatMessageMapper(withServerURLString: SQLiteHistoryStorageTests.SERVER_URL_STRING)), - completionHandlerExecutor: exeIfNotDestroyedHandlerExecutor, - sessionParametersListener: nil, - internalErrorListener: internalErrorListener, - baseURL: SQLiteHistoryStorageTests.SERVER_URL_STRING, - title: "Title", - location: "mobile", - appVersion: nil, - visitorFieldsJSONString: nil, - providedAuthenticationTokenStateListener: nil, - providedAuthenticationToken: nil, - deviceID: "ID", - deviceToken: nil, - visitorJSONString: nil, - sessionID: nil, - authorizationData: nil), - webimActions: WebimActions(baseURL: SQLiteHistoryStorageTests.SERVER_URL_STRING, - actionRequestLoop: actionRequestLoop)), - reachedHistoryEnd: true, - queue: queue) - } - - override func tearDown() { - let fileManager = FileManager.default - let documentsPath = try! fileManager.url(for: .documentDirectory, - in: .userDomainMask, - appropriateFor: nil, - create: false) - let dbPath = "\(documentsPath)/\(SQLiteHistoryStorageTests.DB_NAME)" - do { - try fileManager.removeItem(at: URL(string: dbPath)!) - } catch let error { - print("DB file deletion failed with error: " + error.localizedDescription) - } - - super.tearDown() - } - - // MARK: Private methods - private static func generateMessages(ofCount numberOfMessages: Int) -> [MessageImpl] { - var messages = [MessageImpl]() - - for index in 1 ... numberOfMessages { - messages.append(MessageImpl(serverURLString: SQLiteHistoryStorageTests.SERVER_URL_STRING, - id: String(index), - operatorID: "1", - senderAvatarURLString: nil, - senderName: "Name", - type: MessageType.OPERATOR, - data: nil, - text: "Text", - timeInMicrosecond: Int64(index * 1_000_000_000_000), - attachment: nil, - historyMessage: true, - internalID: String(index), - rawText: nil)) - } - - return messages - } - - // MARK: - Tests - - func testGetMajorVersion() { - XCTAssertEqual(sqLiteHistoryStorage!.getMajorVersion(), - 1) - } - - func testGetFullHistory() { - let messagesCount = 10 - sqLiteHistoryStorage!.receiveHistoryBefore(messages: SQLiteHistoryStorageTests.generateMessages(ofCount: messagesCount), - hasMoreMessages: false) - - let expectation = XCTestExpectation() - var gettedMessages = [Message]() - sqLiteHistoryStorage!.getFullHistory() { messages in - gettedMessages = messages - - expectation.fulfill() - } - wait(for: [expectation], - timeout: 1.0) - - XCTAssertEqual(gettedMessages.count, - messagesCount) - } - - func testGetLatestHistory() { - let messagesCount = 10 - sqLiteHistoryStorage!.receiveHistoryBefore(messages: SQLiteHistoryStorageTests.generateMessages(ofCount: messagesCount), - hasMoreMessages: false) - - let messagesLimit = 3 - let expectation = XCTestExpectation() - var gettedMessages = [Message]() - sqLiteHistoryStorage!.getLatestHistory(byLimit: messagesLimit) { messages in - expectation.fulfill() - gettedMessages = messages - } - wait(for: [expectation], - timeout: 1.0) - - XCTAssertEqual(gettedMessages.count, - messagesLimit) - - let timestampArray = gettedMessages.map() { $0.getTime() } - let thresholdTimestamp = Date(timeIntervalSince1970: TimeInterval((messagesCount - messagesLimit) * 1_000_000)) - for timestamp in timestampArray { - XCTAssertTrue(timestamp > thresholdTimestamp) - } - } - - func testGetHistoryBefore() { - let messagesCount = 10 - sqLiteHistoryStorage!.receiveHistoryBefore(messages: SQLiteHistoryStorageTests.generateMessages(ofCount: messagesCount), - hasMoreMessages: false) - - let messagesLimit = 3 - let beforeID = 5 - let expectation = XCTestExpectation() - var gettedMessages = [Message]() - sqLiteHistoryStorage!.getHistoryBefore(id: HistoryID(dbID: String(beforeID), - timeInMicrosecond: Int64(beforeID * 1_000_000_000_000)), - limitOfMessages: messagesLimit) { messages in - gettedMessages = messages - - expectation.fulfill() - } - wait(for: [expectation], - timeout: 1.0) - - XCTAssertEqual(gettedMessages.count, - messagesLimit) - - let timestampArray = gettedMessages.map() { $0.getTime() } - let lowerThresholdTimestamp = Date(timeIntervalSince1970: TimeInterval((beforeID - messagesLimit - 1)) * 1_000_000) - let upperThresholdTimestamp = Date(timeIntervalSince1970: TimeInterval(beforeID * 1_000_000)) - for timestamp in timestampArray { - XCTAssertTrue(timestamp > lowerThresholdTimestamp) - XCTAssertTrue(timestamp < upperThresholdTimestamp) - } - } - -} diff --git a/ios/libs/Webim/Example/Tests/SessionBuilderTests.swift b/ios/libs/Webim/Example/Tests/SessionBuilderTests.swift deleted file mode 100755 index f8fa88f..0000000 --- a/ios/libs/Webim/Example/Tests/SessionBuilderTests.swift +++ /dev/null @@ -1,129 +0,0 @@ -// -// SessionBuilderTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 02.03.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class SessionBuilderTests: XCTestCase { - - // MARK: - Tests - func testBuild() { - let visitorFieldsJSONString = "{\"id\":\"1234567890987654321\",\"display_name\":\"Никита\",\"crc\":\"ffadeb6aa3c788200824e311b9aa44cb\"}" - - XCTAssertThrowsError(try Webim - .newSessionBuilder() - .set(location: "location") - .build()) - XCTAssertThrowsError(try Webim - .newSessionBuilder() - .set(accountName: "account") - .build()) - - XCTAssertThrowsError(try Webim - .newSessionBuilder() - .set(accountName: "account") - .set(location: "location") - .set(deviceToken: "token") - .build()) - XCTAssertNoThrow(try Webim - .newSessionBuilder() - .set(accountName: "account") - .set(location: "location") - .set(deviceToken: "token") - .set(remoteNotificationSystem: .APNS) - .build()) - - XCTAssertThrowsError(try Webim - .newSessionBuilder() - .set(accountName: "account") - .set(location: "location") - .set(visitorFieldsJSONString: visitorFieldsJSONString) - .set(providedAuthorizationTokenStateListener: self) - .build()) - XCTAssertNoThrow(try Webim - .newSessionBuilder() - .set(accountName: "account") - .set(location: "location") - .set(visitorFieldsJSONString: visitorFieldsJSONString) - .build()) - XCTAssertNoThrow(try Webim - .newSessionBuilder() - .set(accountName: "account") - .set(location: "location") - .set(providedAuthorizationTokenStateListener: self) - .build()) - - XCTAssertNoThrow(try Webim - .newSessionBuilder() - .set(accountName: "account") - .set(location: "location") - .set(appVersion: "version") - .set(visitorFieldsJSONData: visitorFieldsJSONString.data(using: .utf8)!) - .set(pageTitle: "title") - .set(fatalErrorHandler: self) - .set(remoteNotificationSystem: .APNS) - .set(deviceToken: "token") - .set(isLocalHistoryStoragingEnabled: true) - .set(isVisitorDataClearingEnabled: false) - .set(webimLogger: self) - .build()) - } - -} - -// MARK: - -extension SessionBuilderTests: ProvidedAuthorizationTokenStateListener { - - // MARK: - Methods - // MARK: ProvidedAuthorizationTokenStateListener protocol methods - func update(providedAuthorizationToken: String) { - // No need to do anything while testing. - } - -} - -// MARK: - -extension SessionBuilderTests: FatalErrorHandler { - - // MARK: - Methods - // MARK: FatalErrorHandler protocol methods - func on(error: WebimError) { - // No need to do anything when testing. - } - -} - -// MARK: - -extension SessionBuilderTests: WebimLogger { - - // MARK: - Methods - // MARK: WebimLogger protocol methods - func log(entry: String) { - // No need to do anything when testing. - } - -} diff --git a/ios/libs/Webim/Example/Tests/SessionDestroyerTests.swift b/ios/libs/Webim/Example/Tests/SessionDestroyerTests.swift deleted file mode 100755 index 2ce03fa..0000000 --- a/ios/libs/Webim/Example/Tests/SessionDestroyerTests.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// SessionDestroyerTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 01.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class SessionDestroyerTests: XCTestCase { - - // MARK: - Tests - func testDestroy() { - // Setup. - - let sessionDestroyer = SessionDestroyer() - - let expectation1 = XCTestExpectation() - let expectation2 = XCTestExpectation() - let expectation3 = XCTestExpectation() - - sessionDestroyer.add { - expectation1.fulfill() - } - sessionDestroyer.add { - expectation2.fulfill() - } - sessionDestroyer.add { - expectation3.fulfill() - } - - // When: Session is destroyed. - sessionDestroyer.destroy() - - // Then: All passed actions should be executed. - XCTAssertTrue(sessionDestroyer.isDestroyed()) - wait(for: [expectation1], - timeout: 1.0) - wait(for: [expectation2], - timeout: 1.0) - wait(for: [expectation3], - timeout: 1.0) - } - -} diff --git a/ios/libs/Webim/Example/Tests/StringFromHTTPParametersTests.swift b/ios/libs/Webim/Example/Tests/StringFromHTTPParametersTests.swift deleted file mode 100755 index 39b29b9..0000000 --- a/ios/libs/Webim/Example/Tests/StringFromHTTPParametersTests.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// StringFromHTTPParametersTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 02.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class StringFromHTTPParametersTests: XCTestCase { - - // MARK: - Tests - func testStringFromHTTPParameters() { - let dictionary = ["parameter1" : "value1", - "parameter2" : "1"] as [String : Any] - let expectedString = "parameter1=value1¶meter2=1" - - XCTAssertEqual(dictionary.stringFromHTTPParameters(), - expectedString) - } - -} diff --git a/ios/libs/Webim/Example/Tests/UIColorHexStringTests.swift b/ios/libs/Webim/Example/Tests/UIColorHexStringTests.swift deleted file mode 100755 index cd46d62..0000000 --- a/ios/libs/Webim/Example/Tests/UIColorHexStringTests.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// UIColorHexStringTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit -@testable import WebimClientLibrary -import XCTest - -class UIColorHexStringTests: XCTestCase { - - // MARK: - Methods - func testUIColorHexString() { - let colorHexString1 = "000000" - let colorHexString2 = "#000000" - let colorHexString3 = "#ffffff" - let colorHexString4 = "0000000" - - XCTAssertEqual(UIColor(hexString: colorHexString1)!, - UIColor(red: (0.0 / 255.0), - green: (0.0 / 255.0), - blue: (0.0 / 255.0), - alpha: 1.0)) - XCTAssertEqual(UIColor(hexString: colorHexString2)!, - UIColor(red: (0.0 / 255.0), - green: (0.0 / 255.0), - blue: (0.0 / 255.0), - alpha: 1.0)) - XCTAssertEqual(UIColor(hexString: colorHexString3)!, - UIColor(red: (255.0 / 255.0), - green: (255.0 / 255.0), - blue: (255.0 / 255.0), - alpha: 1.0)) - XCTAssertNil(UIColor(hexString: colorHexString4)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/VisitorItemTests.swift b/ios/libs/Webim/Example/Tests/VisitorItemTests.swift deleted file mode 100755 index 609609b..0000000 --- a/ios/libs/Webim/Example/Tests/VisitorItemTests.swift +++ /dev/null @@ -1,151 +0,0 @@ -// -// VisitorItemTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit -@testable import WebimClientLibrary -import XCTest - -class VisitorItemTests: XCTestCase { - - // MARK: - Tests - - func testInit() { - let visitorItemJSONString = """ -{ - "fields" : { - "name" : "Посетитель" - }, - "channelType" : null, - "channelId" : null, - "id" : "877a920ede7082412656ac1cdec7ecde", - "icon" : { - "color" : "#5fa0ea", - "shape" : "rhombus" - }, - "modificationTs" : 1518790888.5528669, - "creationTs" : 1518790888.5528669, - "hasProvidedFields" : true, - "channelUserName" : null, - "tags" : [ ], - "channelUserId" : null -} -""" - let visitorItemDictionary = try! JSONSerialization.jsonObject(with: visitorItemJSONString.data(using: .utf8)!, - options: []) as! [String : Any?] - let visitorItem = VisitorItem(jsonDictionary: visitorItemDictionary)! - - XCTAssertEqual(visitorItem.getID(), - "877a920ede7082412656ac1cdec7ecde") - - XCTAssertEqual(visitorItem.getIcon()!.getColor(), - UIColor(hexString: "#5fa0ea")!) - XCTAssertEqual(visitorItem.getIcon()!.getShape(), - "rhombus") - - XCTAssertEqual(visitorItem.getVisitorFields().getName(), - "Посетитель") - XCTAssertNil(visitorItem.getVisitorFields().getEmail()) - XCTAssertNil(visitorItem.getVisitorFields().getPhone()) - } - - func testInitFails() { - let visitorItemJSONString = """ -{ - "fields" : { - "name" : "Посетитель" - }, - "channelType" : null, - "channelId" : null, - "icon" : { - "color" : "#5fa0ea", - "shape" : "rhombus" - }, - "modificationTs" : 1518790888.5528669, - "creationTs" : 1518790888.5528669, - "hasProvidedFields" : true, - "channelUserName" : null, - "tags" : [ ], - "channelUserId" : null -} -""" - let visitorItemDictionary = try! JSONSerialization.jsonObject(with: visitorItemJSONString.data(using: .utf8)!, - options: []) as! [String : Any?] - - XCTAssertNil(VisitorItem(jsonDictionary: visitorItemDictionary)) - } - - func testNilIcon() { - let visitorItemJSONString = """ -{ - "fields" : { - "name" : "Посетитель" - }, - "channelType" : null, - "channelId" : null, - "id" : "877a920ede7082412656ac1cdec7ecde", - "icon" : { - "shape" : "rhombus" - }, - "modificationTs" : 1518790888.5528669, - "creationTs" : 1518790888.5528669, - "hasProvidedFields" : true, - "channelUserName" : null, - "tags" : [ ], - "channelUserId" : null -} -""" - let visitorItemDictionary = try! JSONSerialization.jsonObject(with: visitorItemJSONString.data(using: .utf8)!, - options: []) as! [String : Any?] - let visitorItem = VisitorItem(jsonDictionary: visitorItemDictionary)! - - XCTAssertNil(visitorItem.getIcon()) - } - - func testNilFields() { - let visitorItemJSONString = """ -{ - "fields" : { }, - "channelType" : null, - "channelId" : null, - "id" : "877a920ede7082412656ac1cdec7ecde", - "icon" : { - "shape" : "rhombus" - }, - "modificationTs" : 1518790888.5528669, - "creationTs" : 1518790888.5528669, - "hasProvidedFields" : true, - "channelUserName" : null, - "tags" : [ ], - "channelUserId" : null -} -""" - let visitorItemDictionary = try! JSONSerialization.jsonObject(with: visitorItemJSONString.data(using: .utf8)!, - options: []) as! [String : Any?] - - XCTAssertNil(VisitorItem(jsonDictionary: visitorItemDictionary)) - } - -} diff --git a/ios/libs/Webim/Example/Tests/WebimActionsTests.swift b/ios/libs/Webim/Example/Tests/WebimActionsTests.swift deleted file mode 100755 index 6262178..0000000 --- a/ios/libs/Webim/Example/Tests/WebimActionsTests.swift +++ /dev/null @@ -1,445 +0,0 @@ -// -// WebimActionsTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 29.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class WebimActionsTests: XCTestCase { - - // MARK: - Properties - private let actionRequestLoop = ActionRequestLoopForTests(completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: SessionDestroyer(), - queue: DispatchQueue.global()), - internalErrorListener: InternalErrorListenerForTests() as InternalErrorListener) - private var webimActions: WebimActions? - - // MARK: - Methods - - override func setUp() { - super.setUp() - - webimActions = WebimActions(baseURL: "https://demo.webim.ru", - actionRequestLoop: actionRequestLoop) - } - - override func tearDown() { - actionRequestLoop.webimRequest = nil - - super.tearDown() - } - - // MARK: - Tests - - func testSendMessageRequestFormation() { - // MARK: Test 1 - - // Setup. - var message = "Message" - var clientSideID = "1" - var dataJSONString = "{\"key\":\"value\"}" - var isHintQuestion = true - - // When: Sending message. - webimActions?.send(message: message, - clientSideID: clientSideID, - dataJSONString: dataJSONString, - isHintQuestion: isHintQuestion, - dataMessageCompletionHandler: nil) - - // Then: Request parameters should be like this. - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.post) - - var expectedParametersDictionary = ["message" : message, - "client-side-id" : clientSideID, - "action" : "chat.message", - "hint_question" : "1", - "data" : dataJSONString] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["message"] as! String, - expectedParametersDictionary["message"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["client-side-id"] as! String, - expectedParametersDictionary["client-side-id"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["action"] as! String, - expectedParametersDictionary["action"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["hint_question"] as! String, - expectedParametersDictionary["hint_question"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["data"] as! String, - expectedParametersDictionary["data"] as! String) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getContentType(), - WebimActions.ContentType.urlEncoded.rawValue) - - var expectedBaseURLString = "https://demo.webim.ru/l/v/m/action" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - XCTAssertNil(actionRequestLoop.webimRequest!.getDataMessageCompletionHandler()) - - // MARK: Test 1 - - // Setup. - message = "Message" - clientSideID = "1" - dataJSONString = "{\"key\":\"value\"}" - isHintQuestion = false - - // When: Sending message. - webimActions?.send(message: message, - clientSideID: clientSideID, - dataJSONString: dataJSONString, - isHintQuestion: isHintQuestion, - dataMessageCompletionHandler: nil) - - // Then: Request parameters should be like this. - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.post) - - expectedParametersDictionary = ["message" : message, - "client-side-id" : clientSideID, - "action" : "chat.message", - "hint_question" : "0", - "data" : dataJSONString] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["message"] as! String, - expectedParametersDictionary["message"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["client-side-id"] as! String, - expectedParametersDictionary["client-side-id"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["action"] as! String, - expectedParametersDictionary["action"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["hint_question"] as! String, - expectedParametersDictionary["hint_question"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["data"] as! String, - expectedParametersDictionary["data"] as! String) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getContentType(), - WebimActions.ContentType.urlEncoded.rawValue) - - expectedBaseURLString = "https://demo.webim.ru/l/v/m/action" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - } - - func testSendFileRequestFormation() { - // Setup. - let data = "1010".data(using: .utf8)! - let fileName = "file.jpg" - let mimeType = "image/jpeg" - let clientSideID = "1" - - // When: Sending file. - webimActions?.send(file: data, - filename: fileName, - mimeType: mimeType, - clientSideID: clientSideID, - completionHandler: nil) - - // Then: Request parameters should be like this. - - let boundaryString = actionRequestLoop.webimRequest!.getContentType()!.replacingOccurrences(of: "multipart/form-data; boundary=", - with: "") - let expectedHTTPBody = "--\(boundaryString)\r\n" - + "Content-Disposition: form-data; name=\"webim_upload_file\"; filename=\"\(fileName)\"\r\n" - + "Content-Type: \(mimeType)\r\n\r\n" - + "1010\r\n" - + "--\(boundaryString)--\r\n" - XCTAssertEqual(String(data: actionRequestLoop.webimRequest!.getHTTPBody()!, - encoding: .utf8), - expectedHTTPBody) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.post) - - let expectedParametersDictionary = ["chat-mode" : "online", - "client-side-id" : clientSideID] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["chat-mode"] as! String, - expectedParametersDictionary["chat-mode"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["client-side-id"] as! String, - expectedParametersDictionary["client-side-id"] as! String) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getMessageID(), - clientSideID) - - let expectedBaseURLString = "https://demo.webim.ru/l/v/m/upload" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - - XCTAssertNil(actionRequestLoop.webimRequest!.getSendFileCompletionHandler()) - } - - func testStartChatRequestFormation() { - // Setup. - let message = "Message" - let clientSideID = "1" - let departmentKey = "Department" - - // When: Starting chat. - webimActions?.startChat(withClientSideID: clientSideID, - firstQuestion: message, - departmentKey: departmentKey) - - // Then: Request parameters should be like this. - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.post) - - let expectedParametersDictionary = ["first-question" : message, - "client-side-id" : clientSideID, - "action" : "chat.start", - "force-online" : "1", - "department-key" : departmentKey] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["first-question"] as! String, - expectedParametersDictionary["first-question"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["client-side-id"] as! String, - expectedParametersDictionary["client-side-id"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["action"] as! String, - expectedParametersDictionary["action"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["force-online"] as! String, - expectedParametersDictionary["force-online"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["department-key"] as! String, - expectedParametersDictionary["department-key"] as! String) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getContentType(), - WebimActions.ContentType.urlEncoded.rawValue) - - let expectedBaseURLString = "https://demo.webim.ru/l/v/m/action" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - } - - func testCloseChatRequestFormation() { - // When: Closing chat. - webimActions?.closeChat() - - // Then: Request parameters should be like this. - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.post) - - let expectedParametersDictionary = ["action" : "chat.close"] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["action"] as! String, - expectedParametersDictionary["action"] as! String) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getContentType(), - WebimActions.ContentType.urlEncoded.rawValue) - - let expectedBaseURLString = "https://demo.webim.ru/l/v/m/action" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - } - - func testSetVisitorTypingRequestFormation() { - // Setup. - let message = "Message" - let visitorTyping = true - let deleteDraft = false - - // When: Setting visitor is typing a draft. - webimActions?.set(visitorTyping: visitorTyping, - draft: message, - deleteDraft: deleteDraft) - - // Then: Request parameters should be like this. - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.post) - - let expectedParametersDictionary = ["message-draft" : message, - "action" : "chat.visitor_typing", - "del-message-draft" : "0", - "typing" : "1"] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["message-draft"] as! String, - expectedParametersDictionary["message-draft"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["action"] as! String, - expectedParametersDictionary["action"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["del-message-draft"] as! String, - expectedParametersDictionary["del-message-draft"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["typing"] as! String, - expectedParametersDictionary["typing"] as! String) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getContentType(), - WebimActions.ContentType.urlEncoded.rawValue) - - let expectedBaseURLString = "https://demo.webim.ru/l/v/m/action" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - } - - func testSetVisitorTypingEndRequestFormation() { - // Setup. - let visitorTyping = false - let deleteDraft = true - - // When: Setting visitor is typing a draft. - webimActions?.set(visitorTyping: visitorTyping, - draft: nil, - deleteDraft: deleteDraft) - - // Then: Request parameters should be like this. - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.post) - - let expectedParametersDictionary = ["action" : "chat.visitor_typing", - "del-message-draft" : "1", - "typing" : "0"] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["action"] as! String, - expectedParametersDictionary["action"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["del-message-draft"] as! String, - expectedParametersDictionary["del-message-draft"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["typing"] as! String, - expectedParametersDictionary["typing"] as! String) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getContentType(), - WebimActions.ContentType.urlEncoded.rawValue) - - let expectedBaseURLString = "https://demo.webim.ru/l/v/m/action" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - } - - func testRequestHistorySinceFormation() { - // Setup. - let since = "1" - - // When: Requesting history since. - let expectaion = XCTestExpectation() - webimActions?.requestHistory(since: since) { data in - expectaion.fulfill() - } - - // Then: Request parameters should be like this. - - try! actionRequestLoop.webimRequest!.getCompletionHandler()!(nil) - wait(for: [expectaion], - timeout: 1.0) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.get) - - let expectedParametersDictionary = ["since" : since] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["since"] as! String, - expectedParametersDictionary["since"] as! String) - - XCTAssertNil(actionRequestLoop.webimRequest!.getContentType()) - - let expectedBaseURLString = "https://demo.webim.ru/l/v/m/history" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - } - - func testRequestHistoryBeforeFormation() { - // Setup. - let before = "1" - - // When: Requesting history before. - let expectaion = XCTestExpectation() - webimActions?.requestHistory(beforeMessageTimestamp: Int64(before)!) { data in - expectaion.fulfill() - } - - // Then: Request parameters should be like this. - - try! actionRequestLoop.webimRequest!.getCompletionHandler()!(nil) - wait(for: [expectaion], - timeout: 1.0) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.get) - - let expectedParametersDictionary = ["before-ts" : before] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["before-ts"] as! String, - expectedParametersDictionary["before-ts"] as! String) - - XCTAssertNil(actionRequestLoop.webimRequest!.getContentType()) - - let expectedBaseURLString = "https://demo.webim.ru/l/v/m/history" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - } - - func testRateOperatorRequestFormation() { - // Setup. - let operatorID = "1" - let rating = "2" - - // When: Rating an operator. - webimActions?.rateOperatorWith(id: operatorID, - rating: Int(rating)!, - completionHandler: nil) - - // Then: Request parameters should be like this. - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.post) - - let expectedParametersDictionary = ["action" : "chat.operator_rate_select", - "rate" : rating, - "operator_id" : operatorID] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["action"] as! String, - expectedParametersDictionary["action"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["rate"] as! String, - expectedParametersDictionary["rate"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["operator_id"] as! String, - expectedParametersDictionary["operator_id"] as! String) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getContentType(), - WebimActions.ContentType.urlEncoded.rawValue) - - let expectedBaseURLString = "https://demo.webim.ru/l/v/m/action" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - - XCTAssertNil(actionRequestLoop.webimRequest!.getRateOperatorCompletionHandler()) - } - - func testUpdateDeviceTokenRequestFormation() { - // Setup. - let deviceToken = "1" - - // When: Updating device token. - webimActions?.update(deviceToken: deviceToken) - - // Then: Request parameters should be like this. - - XCTAssertEqual(actionRequestLoop.webimRequest!.getHTTPMethod(), - AbstractRequestLoop.HTTPMethods.post) - - let expectedParametersDictionary = ["action" : "set_push_token", - "push-token" : deviceToken] as [String : Any] - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["action"] as! String, - expectedParametersDictionary["action"] as! String) - XCTAssertEqual(actionRequestLoop.webimRequest!.getPrimaryData()["push-token"] as! String, - expectedParametersDictionary["push-token"] as! String) - - XCTAssertEqual(actionRequestLoop.webimRequest!.getContentType(), - WebimActions.ContentType.urlEncoded.rawValue) - - let expectedBaseURLString = "https://demo.webim.ru/l/v/m/action" - XCTAssertEqual(actionRequestLoop.webimRequest!.getBaseURLString(), - expectedBaseURLString) - } - -} diff --git a/ios/libs/Webim/Example/Tests/WebimClientTests.swift b/ios/libs/Webim/Example/Tests/WebimClientTests.swift deleted file mode 100755 index 342d2ca..0000000 --- a/ios/libs/Webim/Example/Tests/WebimClientTests.swift +++ /dev/null @@ -1,99 +0,0 @@ -// -// WebimClientTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 12.03.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class WebimClientTests: XCTestCase { - - // MARK: - Tests - - func testGetDeltaRequestLoop() { - let execIfNotDestroyedHandlerExecutor = ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: SessionDestroyer(), - queue: DispatchQueue.main) - let internalErrorListener = InternalErrorListenerForTests() - let actionRequestLoop = ActionRequestLoopForTests(completionHandlerExecutor: execIfNotDestroyedHandlerExecutor, - internalErrorListener: internalErrorListener) - let urlString = "http://webim.ru" - let deltaRequestLoop = DeltaRequestLoop(deltaCallback: DeltaCallback(currentChatMessageMapper: CurrentChatMessageMapper(withServerURLString: urlString)), - completionHandlerExecutor: execIfNotDestroyedHandlerExecutor, - sessionParametersListener: nil, - internalErrorListener: internalErrorListener, - baseURL: urlString, - title: "title", - location: "location", - appVersion: nil, - visitorFieldsJSONString: nil, - providedAuthenticationTokenStateListener: nil, - providedAuthenticationToken: nil, - deviceID: "id", - deviceToken: nil, - visitorJSONString: nil, - sessionID: nil, - authorizationData: nil) - - let webimClient = WebimClient(withActionRequestLoop: actionRequestLoop, - deltaRequestLoop: deltaRequestLoop, - webimActions: WebimActions(baseURL: urlString, - actionRequestLoop: actionRequestLoop)) - - XCTAssertTrue(deltaRequestLoop === webimClient.getDeltaRequestLoop()) - } - - func testGetActions() { - let execIfNotDestroyedHandlerExecutor = ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: SessionDestroyer(), - queue: DispatchQueue.main) - let internalErrorListener = InternalErrorListenerForTests() - let actionRequestLoop = ActionRequestLoopForTests(completionHandlerExecutor: execIfNotDestroyedHandlerExecutor, - internalErrorListener: internalErrorListener) - let urlString = "http://webim.ru" - let webimActions = WebimActions(baseURL: urlString, - actionRequestLoop: actionRequestLoop) - - let webimClient = WebimClient(withActionRequestLoop: actionRequestLoop, - deltaRequestLoop: DeltaRequestLoop(deltaCallback: DeltaCallback(currentChatMessageMapper: CurrentChatMessageMapper(withServerURLString: urlString)), - completionHandlerExecutor: execIfNotDestroyedHandlerExecutor, - sessionParametersListener: nil, - internalErrorListener: internalErrorListener, - baseURL: urlString, - title: "title", - location: "location", - appVersion: nil, - visitorFieldsJSONString: nil, - providedAuthenticationTokenStateListener: nil, - providedAuthenticationToken: nil, - deviceID: "id", - deviceToken: nil, - visitorJSONString: nil, - sessionID: nil, - authorizationData: nil), - webimActions: webimActions) - - XCTAssertTrue(webimActions === webimClient.getActions()) - } - -} diff --git a/ios/libs/Webim/Example/Tests/WebimErrorImplTests.swift b/ios/libs/Webim/Example/Tests/WebimErrorImplTests.swift deleted file mode 100755 index 7a93f63..0000000 --- a/ios/libs/Webim/Example/Tests/WebimErrorImplTests.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// WebimErrorImplTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 20.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -@testable import WebimClientLibrary -import XCTest - -class WebimErrorImplTests: XCTestCase { - - // MARK: - Tests - func testInit() { - var webimError = WebimErrorImpl(errorType: .ACCOUNT_BLOCKED, - errorString: nil) - - XCTAssertEqual(webimError.getErrorType(), - FatalErrorType.ACCOUNT_BLOCKED) - XCTAssertEqual(webimError.getErrorString(), - "ACCOUNT_BLOCKED") - - webimError = WebimErrorImpl(errorType: .UNKNOWN, - errorString: "Error") - - XCTAssertEqual(webimError.getErrorType(), - FatalErrorType.UNKNOWN) - XCTAssertEqual(webimError.getErrorString(), - "Error") - } - -} diff --git a/ios/libs/Webim/Example/Tests/WebimInternalLoggerTests.swift b/ios/libs/Webim/Example/Tests/WebimInternalLoggerTests.swift deleted file mode 100755 index a38d9db..0000000 --- a/ios/libs/Webim/Example/Tests/WebimInternalLoggerTests.swift +++ /dev/null @@ -1,112 +0,0 @@ -// -// WebimInternalLoggerTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 16.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class WebimInternalLoggerTests: XCTestCase { - - // MARK: - Properties - let webimInternalLogger = WebimInternalLogger.shared - var logEntry: String? - - // MARK: Methods - override func setUp() { - super.setUp() - - logEntry = nil - } - - // MARK: - Tests - func testSetup() { - // When: Low verbosity level installed and high verbosity level log message is send. - WebimInternalLogger.setup(webimLogger: self, - verbosityLevel: .ERROR) - webimInternalLogger.log(entry: "Test", - verbosityLevel: .VERBOSE) - - // Then: WebimLogger method should not be called. - XCTAssertNil(logEntry) - } - - func testLogWithSameVerbosityLevelIsPassed() { - // Setup. - let verbosityLevel = SessionBuilder.WebimLoggerVerbosityLevel.DEBUG - let logString = "Test" - - // When: Logger installed and log entry passed with the same verbosity level. - WebimInternalLogger.setup(webimLogger: self, - verbosityLevel: verbosityLevel) - webimInternalLogger.log(entry: logString, - verbosityLevel: verbosityLevel) - - // Then: Log entry should be passed to WebimLogger. - XCTAssertNotNil(logEntry) - } - - func testLogWithLowerVerbosityLevelIsPassed() { - // Setup. - let verbosityLevel = SessionBuilder.WebimLoggerVerbosityLevel.DEBUG - let higherVerbosityLevel = SessionBuilder.WebimLoggerVerbosityLevel.VERBOSE - let logString = "Test" - - // When: Logger installed and log entry passed with lower verbosity level. - WebimInternalLogger.setup(webimLogger: self, - verbosityLevel: higherVerbosityLevel) - webimInternalLogger.log(entry: logString, - verbosityLevel: verbosityLevel) - - // Then: Log entry should be passed to WebimLogger. - XCTAssertNotNil(logEntry) - } - - func testLogWithHigherVerbosityLevelIsNotPassed() { - // Setup. - let verbosityLevel = SessionBuilder.WebimLoggerVerbosityLevel.DEBUG - let lowerVerbosityLevel = SessionBuilder.WebimLoggerVerbosityLevel.INFO - let logString = "Test" - - // When: Logger installed and log entry passed with higher verbosity level. - WebimInternalLogger.setup(webimLogger: self, - verbosityLevel: lowerVerbosityLevel) - webimInternalLogger.log(entry: logString, - verbosityLevel: verbosityLevel) - - // Then: Log entry should be passed to WebimLogger. - XCTAssertNil(logEntry) - } - -} - -// MARK: - WebimLogger -extension WebimInternalLoggerTests: WebimLogger { - - func log(entry: String) { - logEntry = entry - } - -} diff --git a/ios/libs/Webim/Example/Tests/WebimRemoteNotificationImplTests.swift b/ios/libs/Webim/Example/Tests/WebimRemoteNotificationImplTests.swift deleted file mode 100755 index 0ee4b50..0000000 --- a/ios/libs/Webim/Example/Tests/WebimRemoteNotificationImplTests.swift +++ /dev/null @@ -1,150 +0,0 @@ -// -// WebimRemoteNotificationImplTests.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 30.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import XCTest -@testable import WebimClientLibrary - -class WebimRemoteNotificationImplTests: XCTestCase { - - // MARK: - Tests - - func testContactRequestNotification() { - // Setup. - let notificationDictionary = ["loc-key" : "P.CR"] as [String : Any] - - // When: Receiving contact request notification. - let webimRemoteNotification = WebimRemoteNotificationImpl(jsonDictionary: notificationDictionary) - - // Then: Parameters should be ruturned like this. - XCTAssertNil(webimRemoteNotification?.getEvent()) - XCTAssertTrue(webimRemoteNotification!.getParameters().isEmpty) - XCTAssertEqual(webimRemoteNotification?.getType(), - NotificationType.CONTACT_INFORMATION_REQUEST) - } - - func testOperatorAcceptedNotification() { - // Setup. - let notificationDictionary = ["loc-key" : "P.OA", - "loc-args" : ["Operator"]] as [String : Any] - - // When: Receiving operator accepted notification. - let webimRemoteNotification = WebimRemoteNotificationImpl(jsonDictionary: notificationDictionary) - - // Then: Parameters should be ruturned like this. - XCTAssertNil(webimRemoteNotification?.getEvent()) - XCTAssertTrue(webimRemoteNotification?.getParameters().count == 1) - XCTAssertEqual(webimRemoteNotification?.getType(), - NotificationType.OPERATOR_ACCEPTED) - } - - func testOperatorFileNotification() { - // Setup. - let notificationDictionary = ["loc-key" : "P.OF", - "loc-args" : ["Operator", - "File"], - "event" : "add"] as [String : Any] - - // When: Receiving operator file adding notification. - let webimRemoteNotification = WebimRemoteNotificationImpl(jsonDictionary: notificationDictionary) - - // Then: Parameters should be ruturned like this. - XCTAssertEqual(webimRemoteNotification?.getEvent(), NotificationEvent.ADD) - XCTAssertTrue(webimRemoteNotification?.getParameters().count == 2) - XCTAssertEqual(webimRemoteNotification?.getType(), - NotificationType.OPERATOR_FILE) - } - - func testOperatorMessageNotification() { - // Setup. - let notificationDictionary = ["loc-key" : "P.OM", - "loc-args" : ["Operator", - "Message"], - "event" : "del"] as [String : Any] - - // When: Receiving operator message deleting notification. - let webimRemoteNotification = WebimRemoteNotificationImpl(jsonDictionary: notificationDictionary) - - // Then: Parameters should be ruturned like this. - XCTAssertEqual(webimRemoteNotification?.getEvent(), NotificationEvent.DELETE) - XCTAssertTrue(webimRemoteNotification?.getParameters().count == 2) - XCTAssertEqual(webimRemoteNotification?.getType(), - NotificationType.OPERATOR_MESSAGE) - } - - func testWidgetNotification() { - // Setup. - let notificationDictionary = ["loc-key" : "P.WM"] as [String : Any] - - // When: Receiving contact request notification. - let webimRemoteNotification = WebimRemoteNotificationImpl(jsonDictionary: notificationDictionary) - - // Then: Parameters should be ruturned like this. - XCTAssertNil(webimRemoteNotification?.getEvent()) - XCTAssertTrue(webimRemoteNotification!.getParameters().isEmpty) - XCTAssertEqual(webimRemoteNotification?.getType(), - NotificationType.WIDGET) - } - - func testUnsupportedType() { - // Setup. - let notificationDictionary = ["loc-key" : "NewType"] as [String : Any] - - // When: Receiving notification of unsupported type. - let webimRemoteNotification = WebimRemoteNotificationImpl(jsonDictionary: notificationDictionary) - - // Then: WebimRemoteNotification object should be nil. - XCTAssertNil(webimRemoteNotification) - } - - func testUnsupportedEvent() { - // Setup. - let notificationDictionary = ["loc-key" : "P.OM", - "loc-args" : ["Operator", - "Message"], - "event" : "NewEvent"] as [String : Any] - - // When: Receiving notification of unsupported type. - let webimRemoteNotification = WebimRemoteNotificationImpl(jsonDictionary: notificationDictionary) - - // Then: Event should be nil. - XCTAssertNil(webimRemoteNotification?.getEvent()) - } - - func testEmptyTypeNotification() { - // Setup. - let notificationDictionary = ["loc-args" : ["Operator", - "Message"], - "event" : "del"] as [String : Any] - - // When: Receiving notification without type. - let webimRemoteNotification = WebimRemoteNotificationImpl(jsonDictionary: notificationDictionary) - - // Then: WebimRemoteNotification object should be nil. - XCTAssertNil(webimRemoteNotification) - } - -} diff --git a/ios/libs/Webim/Example/Tests/WebimTests.swift b/ios/libs/Webim/Example/Tests/WebimTests.swift deleted file mode 100755 index 2f4d459..0000000 --- a/ios/libs/Webim/Example/Tests/WebimTests.swift +++ /dev/null @@ -1,94 +0,0 @@ -// -// WebimTests.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 15.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import WebimClientLibrary -import XCTest - -class WebimTests: XCTestCase { - - // MARK: - Constants - private static let WEBIM_REMOTE_NOTIFICATION_JSON_STRING = """ -{ - "aps" : { - "alert" : { - "loc-key" : "P.OM", - "loc-args" : ["Имя Оператора", "Сообщение"] - }, - "sound" : "default", - }, - "webim": 1 -} -""" - private static let NOT_WEBIM_REMOTE_NOTIFICATION_JSON_STRING = """ -{ - "aps" : { - "alert" : { - "loc-key" : "P.OM", - "loc-args" : ["Имя Оператора", "Сообщение"] - }, - "sound" : "default", - } -} -""" - private static let INCORRECT_REMOTE_NOTIFICATION_JSON_STRING = """ -{ - "alert" : { - "loc-key" : "P.OM", - "loc-args" : ["Имя Оператора", "Сообщение"] - }, - "sound" : "default", -} -""" - - // MARK: - Properties - let webimRemoteNotification = try! JSONSerialization.jsonObject(with: WebimTests.WEBIM_REMOTE_NOTIFICATION_JSON_STRING.data(using: .utf8)!, - options: []) as! [AnyHashable : Any] - let notWebimRemoteNotification = try! JSONSerialization.jsonObject(with: WebimTests.NOT_WEBIM_REMOTE_NOTIFICATION_JSON_STRING.data(using: .utf8)!, - options: []) as! [AnyHashable : Any] - let incorrectRemoteNotification = try! JSONSerialization.jsonObject(with: WebimTests.INCORRECT_REMOTE_NOTIFICATION_JSON_STRING.data(using: .utf8)!, - options: []) as! [AnyHashable : Any] - - // MARK: - Tests - - func testParseRemoteNotification() { - let webimRemoteNotification = Webim.parse(remoteNotification: self.webimRemoteNotification)! - - XCTAssertNil(webimRemoteNotification.getEvent()) - XCTAssertEqual(webimRemoteNotification.getParameters(), ["Имя Оператора", - "Сообщение"]) - XCTAssertEqual(webimRemoteNotification.getType(), - NotificationType.OPERATOR_MESSAGE) - - XCTAssertNil(Webim.parse(remoteNotification: self.incorrectRemoteNotification)) - } - - func testIsWebimRemoteNotificatin() { - XCTAssertTrue(Webim.isWebim(remoteNotification: webimRemoteNotification)) - XCTAssertFalse(Webim.isWebim(remoteNotification: notWebimRemoteNotification)) - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary.xcodeproj/project.pbxproj b/ios/libs/Webim/Example/WebimClientLibrary.xcodeproj/project.pbxproj deleted file mode 100755 index 648bf24..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1054 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 3BD523E036E5E0145C40A893 /* Pods_WebimClientLibrary_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75BFCD5FB1955EE77D987E3C /* Pods_WebimClientLibrary_Tests.framework */; }; - 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; - 607FACD81AFB9204008FA782 /* StartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* StartViewController.swift */; }; - 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; - 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; - 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; - 607FACEC1AFB9204008FA782 /* MessageHolderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* MessageHolderTests.swift */; }; - BDBBA7998D78E4CE2C982C3E /* Pods_WebimClientLibrary_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5A6DD52DA6213CB92530809 /* Pods_WebimClientLibrary_Example.framework */; }; - CE07E9952049794C00E0A0D3 /* SessionBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE07E993204972C600E0A0D3 /* SessionBuilderTests.swift */; }; - CE0CD75A202338FD00719DBE /* HistoryIDTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0CD758202338EE00719DBE /* HistoryIDTests.swift */; }; - CE0CD75D20234BD800719DBE /* SessionDestroyerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0CD75B20234BD500719DBE /* SessionDestroyerTests.swift */; }; - CE0CD7632024561B00719DBE /* InternalUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0CD7622024561B00719DBE /* InternalUtilsTests.swift */; }; - CE0CD765202461FE00719DBE /* StringFromHTTPParametersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0CD764202461FE00719DBE /* StringFromHTTPParametersTests.swift */; }; - CE0CD76720249C3E00719DBE /* OperatorImplTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0CD76620249C3E00719DBE /* OperatorImplTests.swift */; }; - CE18FB9A203DA3890059B9FF /* AccessCheckerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE18FB99203DA3890059B9FF /* AccessCheckerTests.swift */; }; - CE18FB9C203DB32E0059B9FF /* LocationSettingsHolderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE18FB9B203DB32E0059B9FF /* LocationSettingsHolderTests.swift */; }; - CE18FB9E203EBCB00059B9FF /* MessageStreamImplTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE18FB9D203EBCB00059B9FF /* MessageStreamImplTests.swift */; }; - CE1FC99E202333B20090F7E6 /* ExecIfNotDestroyedHandlerExecutorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1FC99D202333B20090F7E6 /* ExecIfNotDestroyedHandlerExecutorTests.swift */; }; - CE24A00E20372239009EE7E7 /* DepartmentItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE24A00D20372239009EE7E7 /* DepartmentItemTests.swift */; }; - CE24A01020372629009EE7E7 /* FileParametersItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE24A00F20372629009EE7E7 /* FileParametersItemTests.swift */; }; - CE24A012203730D5009EE7E7 /* MessageItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE24A011203730D5009EE7E7 /* MessageItemTests.swift */; }; - CE24A014203735C8009EE7E7 /* OperatorItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE24A013203735C8009EE7E7 /* OperatorItemTests.swift */; }; - CE24A019203ADF40009EE7E7 /* RatingItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE24A018203ADF40009EE7E7 /* RatingItemTests.swift */; }; - CE2845B82020A891007B1C25 /* AbstractRequestLoopTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2845B62020A88D007B1C25 /* AbstractRequestLoopTests.swift */; }; - CE2845BB2020B6A3007B1C25 /* ActionRequestLoopTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2845B92020B687007B1C25 /* ActionRequestLoopTests.swift */; }; - CE2845BE2020B718007B1C25 /* ActionRequestLoopMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2845BC2020B70A007B1C25 /* ActionRequestLoopMock.swift */; }; - CE2845C22021B9D4007B1C25 /* DecodePercentEscapedLinksIfPresentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2845C02021B9BC007B1C25 /* DecodePercentEscapedLinksIfPresentTests.swift */; }; - CE2845C42021C2BF007B1C25 /* AuthorizationDataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2845C32021C2BF007B1C25 /* AuthorizationDataTests.swift */; }; - CE2845C62021CF40007B1C25 /* ClientSideIDTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2845C52021CF40007B1C25 /* ClientSideIDTests.swift */; }; - CE2845C82021DBE5007B1C25 /* DeltaRequestLoopTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2845C72021DBE5007B1C25 /* DeltaRequestLoopTests.swift */; }; - CE2CD5952035DF6E00997628 /* MemoryHistoryMetaInformationStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2CD5942035DF6E00997628 /* MemoryHistoryMetaInformationStorageTests.swift */; }; - CE2CD5972035F12600997628 /* ChatItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2CD5962035F12600997628 /* ChatItemTests.swift */; }; - CE324E631FDECBD2004BB116 /* RatingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE324E651FDECBD2004BB116 /* RatingViewController.xib */; }; - CE380424202B0AC2003032D4 /* SettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE380423202B0AC2003032D4 /* SettingsTableViewController.swift */; }; - CE380426202B3526003032D4 /* ColorScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE380425202B3526003032D4 /* ColorScheme.swift */; }; - CE44AE651F87CA8E009787E5 /* MessageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE44AE641F87CA8E009787E5 /* MessageTableViewCell.swift */; }; - CE45EDDD1F9108FA00F56319 /* UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE45EDDC1F9108FA00F56319 /* UIImageView.swift */; }; - CE45EDE01F95F9F700F56319 /* MimeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE45EDDF1F95F95C00F56319 /* MimeType.swift */; }; - CE48362C2031DA5E00E18A20 /* MimeTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE48362B2031DA5E00E18A20 /* MimeTypeTests.swift */; }; - CE48362F2032E3F100E18A20 /* PopupDialogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE48362D2032E0D900E18A20 /* PopupDialogHandler.swift */; }; - CE591A431FC2F31E004C95EE /* WebimService.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE591A421FC2F31E004C95EE /* WebimService.swift */; }; - CE5A03BA1FDEB756009D320A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE5A03BC1FDEB756009D320A /* Localizable.strings */; }; - CE5B7E5C20500A6F00DDA407 /* ProvidedVisitorFieldsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5B7E5B20500A6F00DDA407 /* ProvidedVisitorFieldsTests.swift */; }; - CE5B7E622056B26C00DDA407 /* WebimClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5B7E612056B26C00DDA407 /* WebimClientTests.swift */; }; - CE6741C8200F9A600061EEFD /* HMACSha256Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6741C7200F9A600061EEFD /* HMACSha256Tests.swift */; }; - CE86FA97203AF44700CB9C2D /* VisitorItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FA96203AF44700CB9C2D /* VisitorItemTests.swift */; }; - CE86FA99203AF6AC00CB9C2D /* UIColorHexStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FA98203AF6AC00CB9C2D /* UIColorHexStringTests.swift */; }; - CE86FA9B203AFBFB00CB9C2D /* DeltaItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FA9A203AFBFB00CB9C2D /* DeltaItemTests.swift */; }; - CE86FA9D203B009400CB9C2D /* FullUpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FA9C203B009400CB9C2D /* FullUpdateTests.swift */; }; - CE86FA9F203B07F400CB9C2D /* DeltaResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FA9E203B07F400CB9C2D /* DeltaResponseTests.swift */; }; - CE86FAA1203B0B1600CB9C2D /* HistoryBeforeResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FAA0203B0B1600CB9C2D /* HistoryBeforeResponseTests.swift */; }; - CE86FAA3203B122A00CB9C2D /* HistorySinceResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FAA2203B122A00CB9C2D /* HistorySinceResponseTests.swift */; }; - CE86FAA5203B1B7300CB9C2D /* MessageFactoriesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FAA4203B1B7300CB9C2D /* MessageFactoriesTests.swift */; }; - CE86FAAF203B2D1800CB9C2D /* OperatorFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FAAE203B2D1800CB9C2D /* OperatorFactoryTests.swift */; }; - CE86FAB1203C18D600CB9C2D /* DepartmentFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FAB0203C18D600CB9C2D /* DepartmentFactoryTests.swift */; }; - CE86FAB3203C1E8500CB9C2D /* SQLiteHistoryStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FAB2203C1E8500CB9C2D /* SQLiteHistoryStorageTests.swift */; }; - CE86FAB8203C48DA00CB9C2D /* MemoryHistoryStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FAB7203C48DA00CB9C2D /* MemoryHistoryStorageTests.swift */; }; - CE86FABC203C664F00CB9C2D /* LocationSettingsImplTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FABB203C664F00CB9C2D /* LocationSettingsImplTests.swift */; }; - CE86FABE203C686600CB9C2D /* MessageImplTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FABD203C686600CB9C2D /* MessageImplTests.swift */; }; - CE86FAC0203C6FBC00CB9C2D /* WebimErrorImplTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FABF203C6FBC00CB9C2D /* WebimErrorImplTests.swift */; }; - CE88BCD11FCD7F9A00A4FA2E /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE88BCD01FCD7F9A00A4FA2E /* SettingsViewController.swift */; }; - CE88BCD31FCD88EA00A4FA2E /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE88BCD21FCD88EA00A4FA2E /* Settings.swift */; }; - CE88BCD51FCDA45C00A4FA2E /* ButtonConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE88BCD41FCDA45C00A4FA2E /* ButtonConstants.swift */; }; - CE995DC32020908F00E27A3C /* WebimRemoteNotificationImplTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE995DC12020904300E27A3C /* WebimRemoteNotificationImplTests.swift */; }; - CEA832681F9906C0004845F0 /* ColorConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA832671F9906BF004845F0 /* ColorConstants.swift */; }; - CEA8326A1F99079A004845F0 /* StringConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA832691F99079A004845F0 /* StringConstants.swift */; }; - CEA849051FFCE29A006CC417 /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA849041FFCE29A006CC417 /* UITableView.swift */; }; - CEBFB67F2018CB0F00D9E5F6 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBFB67E2018CB0F00D9E5F6 /* String.swift */; }; - CEBFB6812018E50500D9E5F6 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBFB6802018E50500D9E5F6 /* UIViewController.swift */; }; - CED3BA08201F7E100071EC23 /* WebimActionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED3BA07201F7E100071EC23 /* WebimActionsTests.swift */; }; - CED3BA0B201F87510071EC23 /* InternalErrorListenerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED3BA0A201F87510071EC23 /* InternalErrorListenerMock.swift */; }; - CED72596200E20EF00CD1623 /* ChatViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED72594200E20E500CD1623 /* ChatViewControllerTests.swift */; }; - CED72599200E5B2200CD1623 /* WebimInternalLoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED72597200E5B1C00CD1623 /* WebimInternalLoggerTests.swift */; }; - CEE382C22035D544006C809E /* WebimTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE382C12035D544006C809E /* WebimTests.swift */; }; - CEF61A391F82A4C700BF7071 /* ChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEF61A381F82A4C700BF7071 /* ChatViewController.swift */; }; - DDFC632B1F924D41008E1ACC /* UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFC632A1F924D41008E1ACC /* UIImage.swift */; }; - DDFC63CB1F93F23E008E1ACC /* RatingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFC63CA1F93F23E008E1ACC /* RatingViewController.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 607FACC81AFB9204008FA782 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 607FACCF1AFB9204008FA782; - remoteInfo = WebimClientLibrary; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 188E01CE8A86B2460C60C156 /* Pods-WebimClientLibrary_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WebimClientLibrary_Tests.release.xcconfig"; path = "Target Support Files/Pods-WebimClientLibrary_Tests/Pods-WebimClientLibrary_Tests.release.xcconfig"; sourceTree = ""; }; - 607FACD01AFB9204008FA782 /* WebimClientLibrary_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WebimClientLibrary_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 607FACD71AFB9204008FA782 /* StartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartViewController.swift; sourceTree = ""; }; - 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 607FACE51AFB9204008FA782 /* WebimClientLibrary_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WebimClientLibrary_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 607FACEB1AFB9204008FA782 /* MessageHolderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageHolderTests.swift; sourceTree = ""; }; - 75BFCD5FB1955EE77D987E3C /* Pods_WebimClientLibrary_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WebimClientLibrary_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 998795E306696F247C099BA2 /* Pods-WebimClientLibrary_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WebimClientLibrary_Tests.debug.xcconfig"; path = "Target Support Files/Pods-WebimClientLibrary_Tests/Pods-WebimClientLibrary_Tests.debug.xcconfig"; sourceTree = ""; }; - 9F85297EB410C96E5341BFCC /* Pods-WebimClientLibrary_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WebimClientLibrary_Example.release.xcconfig"; path = "Target Support Files/Pods-WebimClientLibrary_Example/Pods-WebimClientLibrary_Example.release.xcconfig"; sourceTree = ""; }; - AB52E1C1E0F009A386DC1C6C /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; - C4CD65CA48F80B5A4AD826B3 /* WebimClientLibrary.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = WebimClientLibrary.podspec; path = ../WebimClientLibrary.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - CE07E993204972C600E0A0D3 /* SessionBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionBuilderTests.swift; sourceTree = ""; }; - CE0AD26F1F96477500EA9148 /* WebimClientLibrary_Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WebimClientLibrary_Example.entitlements; sourceTree = ""; }; - CE0CD758202338EE00719DBE /* HistoryIDTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryIDTests.swift; sourceTree = ""; }; - CE0CD75B20234BD500719DBE /* SessionDestroyerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDestroyerTests.swift; sourceTree = ""; }; - CE0CD7622024561B00719DBE /* InternalUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalUtilsTests.swift; sourceTree = ""; }; - CE0CD764202461FE00719DBE /* StringFromHTTPParametersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringFromHTTPParametersTests.swift; sourceTree = ""; }; - CE0CD76620249C3E00719DBE /* OperatorImplTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperatorImplTests.swift; sourceTree = ""; }; - CE18FB99203DA3890059B9FF /* AccessCheckerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessCheckerTests.swift; sourceTree = ""; }; - CE18FB9B203DB32E0059B9FF /* LocationSettingsHolderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSettingsHolderTests.swift; sourceTree = ""; }; - CE18FB9D203EBCB00059B9FF /* MessageStreamImplTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageStreamImplTests.swift; sourceTree = ""; }; - CE1FC99D202333B20090F7E6 /* ExecIfNotDestroyedHandlerExecutorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExecIfNotDestroyedHandlerExecutorTests.swift; sourceTree = ""; }; - CE24A00D20372239009EE7E7 /* DepartmentItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DepartmentItemTests.swift; sourceTree = ""; }; - CE24A00F20372629009EE7E7 /* FileParametersItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileParametersItemTests.swift; sourceTree = ""; }; - CE24A011203730D5009EE7E7 /* MessageItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageItemTests.swift; sourceTree = ""; }; - CE24A013203735C8009EE7E7 /* OperatorItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperatorItemTests.swift; sourceTree = ""; }; - CE24A016203ADC88009EE7E7 /* Logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Logo.png; sourceTree = ""; }; - CE24A018203ADF40009EE7E7 /* RatingItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingItemTests.swift; sourceTree = ""; }; - CE2845B62020A88D007B1C25 /* AbstractRequestLoopTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AbstractRequestLoopTests.swift; sourceTree = ""; }; - CE2845B92020B687007B1C25 /* ActionRequestLoopTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionRequestLoopTests.swift; sourceTree = ""; }; - CE2845BC2020B70A007B1C25 /* ActionRequestLoopMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionRequestLoopMock.swift; sourceTree = ""; }; - CE2845C02021B9BC007B1C25 /* DecodePercentEscapedLinksIfPresentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecodePercentEscapedLinksIfPresentTests.swift; sourceTree = ""; }; - CE2845C32021C2BF007B1C25 /* AuthorizationDataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorizationDataTests.swift; sourceTree = ""; }; - CE2845C52021CF40007B1C25 /* ClientSideIDTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientSideIDTests.swift; sourceTree = ""; }; - CE2845C72021DBE5007B1C25 /* DeltaRequestLoopTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeltaRequestLoopTests.swift; sourceTree = ""; }; - CE2CD5942035DF6E00997628 /* MemoryHistoryMetaInformationStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryHistoryMetaInformationStorageTests.swift; sourceTree = ""; }; - CE2CD5962035F12600997628 /* ChatItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemTests.swift; sourceTree = ""; }; - CE324E661FDECBE0004BB116 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/RatingViewController.xib; sourceTree = ""; }; - CE380423202B0AC2003032D4 /* SettingsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTableViewController.swift; sourceTree = ""; }; - CE380425202B3526003032D4 /* ColorScheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorScheme.swift; sourceTree = ""; }; - CE44AE641F87CA8E009787E5 /* MessageTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageTableViewCell.swift; sourceTree = ""; }; - CE45EDDC1F9108FA00F56319 /* UIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageView.swift; sourceTree = ""; }; - CE45EDDF1F95F95C00F56319 /* MimeType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MimeType.swift; sourceTree = ""; }; - CE48362B2031DA5E00E18A20 /* MimeTypeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MimeTypeTests.swift; sourceTree = ""; }; - CE48362D2032E0D900E18A20 /* PopupDialogHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopupDialogHandler.swift; sourceTree = ""; }; - CE54B2511FC452B9009C05BD /* Index.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Index.md; sourceTree = ""; }; - CE591A421FC2F31E004C95EE /* WebimService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebimService.swift; sourceTree = ""; }; - CE5A03BB1FDEB756009D320A /* ru-RU */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ru-RU"; path = "ru-RU.lproj/Localizable.strings"; sourceTree = ""; }; - CE5B7E5B20500A6F00DDA407 /* ProvidedVisitorFieldsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProvidedVisitorFieldsTests.swift; sourceTree = ""; }; - CE5B7E612056B26C00DDA407 /* WebimClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebimClientTests.swift; sourceTree = ""; }; - CE6741C7200F9A600061EEFD /* HMACSha256Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMACSha256Tests.swift; sourceTree = ""; }; - CE86FA96203AF44700CB9C2D /* VisitorItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisitorItemTests.swift; sourceTree = ""; }; - CE86FA98203AF6AC00CB9C2D /* UIColorHexStringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColorHexStringTests.swift; sourceTree = ""; }; - CE86FA9A203AFBFB00CB9C2D /* DeltaItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeltaItemTests.swift; sourceTree = ""; }; - CE86FA9C203B009400CB9C2D /* FullUpdateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FullUpdateTests.swift; sourceTree = ""; }; - CE86FA9E203B07F400CB9C2D /* DeltaResponseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeltaResponseTests.swift; sourceTree = ""; }; - CE86FAA0203B0B1600CB9C2D /* HistoryBeforeResponseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryBeforeResponseTests.swift; sourceTree = ""; }; - CE86FAA2203B122A00CB9C2D /* HistorySinceResponseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistorySinceResponseTests.swift; sourceTree = ""; }; - CE86FAA4203B1B7300CB9C2D /* MessageFactoriesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageFactoriesTests.swift; sourceTree = ""; }; - CE86FAAE203B2D1800CB9C2D /* OperatorFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperatorFactoryTests.swift; sourceTree = ""; }; - CE86FAB0203C18D600CB9C2D /* DepartmentFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DepartmentFactoryTests.swift; sourceTree = ""; }; - CE86FAB2203C1E8500CB9C2D /* SQLiteHistoryStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SQLiteHistoryStorageTests.swift; sourceTree = ""; }; - CE86FAB7203C48DA00CB9C2D /* MemoryHistoryStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryHistoryStorageTests.swift; sourceTree = ""; }; - CE86FABB203C664F00CB9C2D /* LocationSettingsImplTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSettingsImplTests.swift; sourceTree = ""; }; - CE86FABD203C686600CB9C2D /* MessageImplTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageImplTests.swift; sourceTree = ""; }; - CE86FABF203C6FBC00CB9C2D /* WebimErrorImplTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebimErrorImplTests.swift; sourceTree = ""; }; - CE88BCD01FCD7F9A00A4FA2E /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SettingsViewController.swift; path = WebimClientLibrary/SettingsViewController.swift; sourceTree = SOURCE_ROOT; }; - CE88BCD21FCD88EA00A4FA2E /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; }; - CE88BCD41FCDA45C00A4FA2E /* ButtonConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonConstants.swift; sourceTree = ""; }; - CE9379091FEAADC80057E270 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; - CE995DC12020904300E27A3C /* WebimRemoteNotificationImplTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebimRemoteNotificationImplTests.swift; sourceTree = ""; }; - CEA832671F9906BF004845F0 /* ColorConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConstants.swift; sourceTree = ""; }; - CEA832691F99079A004845F0 /* StringConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringConstants.swift; sourceTree = ""; }; - CEA849041FFCE29A006CC417 /* UITableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableView.swift; sourceTree = ""; }; - CEBFB67E2018CB0F00D9E5F6 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; - CEBFB6802018E50500D9E5F6 /* UIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; - CEC27878202DDB760043899C /* ru-RU */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ru-RU"; path = "ru-RU.lproj/Main.strings"; sourceTree = ""; }; - CEC27879202DDD920043899C /* ru-RU */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ru-RU"; path = "ru-RU.lproj/RatingViewController.strings"; sourceTree = ""; }; - CED02E152031C52E000508C9 /* ChatScreenClassic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ChatScreenClassic.png; sourceTree = ""; }; - CED02E182031C52E000508C9 /* ChatScreenDark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ChatScreenDark.png; sourceTree = ""; }; - CED02E242031C5F2000508C9 /* RatingScreenClassic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = RatingScreenClassic.png; sourceTree = ""; }; - CED02E252031C5F2000508C9 /* SettingsScreenDark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SettingsScreenDark.png; sourceTree = ""; }; - CED02E262031C5F2000508C9 /* RatingScreenDark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = RatingScreenDark.png; sourceTree = ""; }; - CED02E272031C5F3000508C9 /* ImageScreenDark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ImageScreenDark.png; sourceTree = ""; }; - CED02E282031C5F3000508C9 /* StartScreenDark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StartScreenDark.png; sourceTree = ""; }; - CED02E292031C5F3000508C9 /* StartScreenClassic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StartScreenClassic.png; sourceTree = ""; }; - CED02E2A2031C5F3000508C9 /* SettingsScreenClassic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SettingsScreenClassic.png; sourceTree = ""; }; - CED02E2B2031C5F3000508C9 /* ImageScreenClassic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ImageScreenClassic.png; sourceTree = ""; }; - CED3BA07201F7E100071EC23 /* WebimActionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebimActionsTests.swift; sourceTree = ""; }; - CED3BA0A201F87510071EC23 /* InternalErrorListenerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalErrorListenerMock.swift; sourceTree = ""; }; - CED72594200E20E500CD1623 /* ChatViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatViewControllerTests.swift; sourceTree = ""; }; - CED72597200E5B1C00CD1623 /* WebimInternalLoggerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebimInternalLoggerTests.swift; sourceTree = ""; }; - CEE382C12035D544006C809E /* WebimTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebimTests.swift; sourceTree = ""; }; - CEF61A381F82A4C700BF7071 /* ChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatViewController.swift; sourceTree = ""; }; - D5A6DD52DA6213CB92530809 /* Pods_WebimClientLibrary_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WebimClientLibrary_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - DDFC632A1F924D41008E1ACC /* UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = ""; }; - DDFC63CA1F93F23E008E1ACC /* RatingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingViewController.swift; sourceTree = ""; }; - EB8C258A78F3730770936414 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; - F0808D307D6955C0CC345203 /* Pods-WebimClientLibrary_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WebimClientLibrary_Example.debug.xcconfig"; path = "Target Support Files/Pods-WebimClientLibrary_Example/Pods-WebimClientLibrary_Example.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 607FACCD1AFB9204008FA782 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - BDBBA7998D78E4CE2C982C3E /* Pods_WebimClientLibrary_Example.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 607FACE21AFB9204008FA782 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3BD523E036E5E0145C40A893 /* Pods_WebimClientLibrary_Tests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 3C3DB6CF3A0FDD8E0CD44FD9 /* Pods */ = { - isa = PBXGroup; - children = ( - F0808D307D6955C0CC345203 /* Pods-WebimClientLibrary_Example.debug.xcconfig */, - 9F85297EB410C96E5341BFCC /* Pods-WebimClientLibrary_Example.release.xcconfig */, - 998795E306696F247C099BA2 /* Pods-WebimClientLibrary_Tests.debug.xcconfig */, - 188E01CE8A86B2460C60C156 /* Pods-WebimClientLibrary_Tests.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - 607FACC71AFB9204008FA782 = { - isa = PBXGroup; - children = ( - CE54B2501FC45274009C05BD /* Documentation */, - 607FACF51AFB993E008FA782 /* Podspec Metadata */, - CE0AD26F1F96477500EA9148 /* WebimClientLibrary_Example.entitlements */, - 607FACD21AFB9204008FA782 /* Example for WebimClientLibrary */, - 607FACE81AFB9204008FA782 /* Tests */, - 607FACD11AFB9204008FA782 /* Products */, - 3C3DB6CF3A0FDD8E0CD44FD9 /* Pods */, - D6405400012B6906279A6D61 /* Frameworks */, - ); - sourceTree = ""; - }; - 607FACD11AFB9204008FA782 /* Products */ = { - isa = PBXGroup; - children = ( - 607FACD01AFB9204008FA782 /* WebimClientLibrary_Example.app */, - 607FACE51AFB9204008FA782 /* WebimClientLibrary_Tests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 607FACD21AFB9204008FA782 /* Example for WebimClientLibrary */ = { - isa = PBXGroup; - children = ( - CEC2787A2031A0110043899C /* Models */, - CEA832661F990689004845F0 /* AppearanceSettings */, - CE45EDDE1F95F94200F56319 /* Utilities */, - 607FACD51AFB9204008FA782 /* AppDelegate.swift */, - CEF61A381F82A4C700BF7071 /* ChatViewController.swift */, - CE44AE641F87CA8E009787E5 /* MessageTableViewCell.swift */, - DDFC63CA1F93F23E008E1ACC /* RatingViewController.swift */, - CE380423202B0AC2003032D4 /* SettingsTableViewController.swift */, - CE88BCD01FCD7F9A00A4FA2E /* SettingsViewController.swift */, - 607FACD71AFB9204008FA782 /* StartViewController.swift */, - 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, - 607FACD91AFB9204008FA782 /* Main.storyboard */, - CE324E651FDECBD2004BB116 /* RatingViewController.xib */, - 607FACDC1AFB9204008FA782 /* Images.xcassets */, - 607FACD31AFB9204008FA782 /* Supporting Files */, - CE5A03BC1FDEB756009D320A /* Localizable.strings */, - ); - name = "Example for WebimClientLibrary"; - path = WebimClientLibrary; - sourceTree = ""; - }; - 607FACD31AFB9204008FA782 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 607FACD41AFB9204008FA782 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 607FACE81AFB9204008FA782 /* Tests */ = { - isa = PBXGroup; - children = ( - CE2845BF2021B993007B1C25 /* ExampleTests */, - CED3BA09201F87390071EC23 /* Mocks */, - CE2845B62020A88D007B1C25 /* AbstractRequestLoopTests.swift */, - CE18FB99203DA3890059B9FF /* AccessCheckerTests.swift */, - CE2845B92020B687007B1C25 /* ActionRequestLoopTests.swift */, - CE2845C32021C2BF007B1C25 /* AuthorizationDataTests.swift */, - CE2CD5962035F12600997628 /* ChatItemTests.swift */, - CE2845C52021CF40007B1C25 /* ClientSideIDTests.swift */, - CE86FA9A203AFBFB00CB9C2D /* DeltaItemTests.swift */, - CE2845C72021DBE5007B1C25 /* DeltaRequestLoopTests.swift */, - CE86FA9E203B07F400CB9C2D /* DeltaResponseTests.swift */, - CE86FAB0203C18D600CB9C2D /* DepartmentFactoryTests.swift */, - CE24A00D20372239009EE7E7 /* DepartmentItemTests.swift */, - CE1FC99D202333B20090F7E6 /* ExecIfNotDestroyedHandlerExecutorTests.swift */, - CE24A00F20372629009EE7E7 /* FileParametersItemTests.swift */, - CE86FA9C203B009400CB9C2D /* FullUpdateTests.swift */, - CE86FAA0203B0B1600CB9C2D /* HistoryBeforeResponseTests.swift */, - CE0CD758202338EE00719DBE /* HistoryIDTests.swift */, - CE86FAA2203B122A00CB9C2D /* HistorySinceResponseTests.swift */, - CE6741C7200F9A600061EEFD /* HMACSha256Tests.swift */, - CE0CD7622024561B00719DBE /* InternalUtilsTests.swift */, - CE18FB9B203DB32E0059B9FF /* LocationSettingsHolderTests.swift */, - CE86FABB203C664F00CB9C2D /* LocationSettingsImplTests.swift */, - CE2CD5942035DF6E00997628 /* MemoryHistoryMetaInformationStorageTests.swift */, - CE86FAB7203C48DA00CB9C2D /* MemoryHistoryStorageTests.swift */, - CE86FAA4203B1B7300CB9C2D /* MessageFactoriesTests.swift */, - 607FACEB1AFB9204008FA782 /* MessageHolderTests.swift */, - CE86FABD203C686600CB9C2D /* MessageImplTests.swift */, - CE24A011203730D5009EE7E7 /* MessageItemTests.swift */, - CE18FB9D203EBCB00059B9FF /* MessageStreamImplTests.swift */, - CE86FAAE203B2D1800CB9C2D /* OperatorFactoryTests.swift */, - CE0CD76620249C3E00719DBE /* OperatorImplTests.swift */, - CE24A013203735C8009EE7E7 /* OperatorItemTests.swift */, - CE5B7E5B20500A6F00DDA407 /* ProvidedVisitorFieldsTests.swift */, - CE24A018203ADF40009EE7E7 /* RatingItemTests.swift */, - CE07E993204972C600E0A0D3 /* SessionBuilderTests.swift */, - CE0CD75B20234BD500719DBE /* SessionDestroyerTests.swift */, - CE86FAB2203C1E8500CB9C2D /* SQLiteHistoryStorageTests.swift */, - CE0CD764202461FE00719DBE /* StringFromHTTPParametersTests.swift */, - CE86FA98203AF6AC00CB9C2D /* UIColorHexStringTests.swift */, - CE86FA96203AF44700CB9C2D /* VisitorItemTests.swift */, - CED3BA07201F7E100071EC23 /* WebimActionsTests.swift */, - CE5B7E612056B26C00DDA407 /* WebimClientTests.swift */, - CE86FABF203C6FBC00CB9C2D /* WebimErrorImplTests.swift */, - CED72597200E5B1C00CD1623 /* WebimInternalLoggerTests.swift */, - CE995DC12020904300E27A3C /* WebimRemoteNotificationImplTests.swift */, - CEE382C12035D544006C809E /* WebimTests.swift */, - 607FACE91AFB9204008FA782 /* Supporting Files */, - ); - path = Tests; - sourceTree = ""; - }; - 607FACE91AFB9204008FA782 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 607FACEA1AFB9204008FA782 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { - isa = PBXGroup; - children = ( - C4CD65CA48F80B5A4AD826B3 /* WebimClientLibrary.podspec */, - EB8C258A78F3730770936414 /* README.md */, - AB52E1C1E0F009A386DC1C6C /* LICENSE */, - ); - name = "Podspec Metadata"; - sourceTree = ""; - }; - CE24A015203ADC2D009EE7E7 /* Images */ = { - isa = PBXGroup; - children = ( - CE24A016203ADC88009EE7E7 /* Logo.png */, - CE88BCD61FCF05CF00A4FA2E /* Screenshots */, - ); - path = Images; - sourceTree = ""; - }; - CE2845BF2021B993007B1C25 /* ExampleTests */ = { - isa = PBXGroup; - children = ( - CED72594200E20E500CD1623 /* ChatViewControllerTests.swift */, - CE2845C02021B9BC007B1C25 /* DecodePercentEscapedLinksIfPresentTests.swift */, - CE48362B2031DA5E00E18A20 /* MimeTypeTests.swift */, - ); - path = ExampleTests; - sourceTree = ""; - }; - CE45EDDB1F9108E200F56319 /* Extensions */ = { - isa = PBXGroup; - children = ( - CEBFB67E2018CB0F00D9E5F6 /* String.swift */, - DDFC632A1F924D41008E1ACC /* UIImage.swift */, - CE45EDDC1F9108FA00F56319 /* UIImageView.swift */, - CEA849041FFCE29A006CC417 /* UITableView.swift */, - CEBFB6802018E50500D9E5F6 /* UIViewController.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - CE45EDDE1F95F94200F56319 /* Utilities */ = { - isa = PBXGroup; - children = ( - CE45EDDB1F9108E200F56319 /* Extensions */, - CE45EDDF1F95F95C00F56319 /* MimeType.swift */, - CE48362D2032E0D900E18A20 /* PopupDialogHandler.swift */, - CE591A421FC2F31E004C95EE /* WebimService.swift */, - ); - path = Utilities; - sourceTree = ""; - }; - CE54B2501FC45274009C05BD /* Documentation */ = { - isa = PBXGroup; - children = ( - CE24A015203ADC2D009EE7E7 /* Images */, - CE54B2511FC452B9009C05BD /* Index.md */, - ); - name = Documentation; - path = ../Documentation; - sourceTree = ""; - }; - CE88BCD61FCF05CF00A4FA2E /* Screenshots */ = { - isa = PBXGroup; - children = ( - CED02E152031C52E000508C9 /* ChatScreenClassic.png */, - CED02E182031C52E000508C9 /* ChatScreenDark.png */, - CED02E2B2031C5F3000508C9 /* ImageScreenClassic.png */, - CED02E272031C5F3000508C9 /* ImageScreenDark.png */, - CED02E242031C5F2000508C9 /* RatingScreenClassic.png */, - CED02E262031C5F2000508C9 /* RatingScreenDark.png */, - CED02E2A2031C5F3000508C9 /* SettingsScreenClassic.png */, - CED02E252031C5F2000508C9 /* SettingsScreenDark.png */, - CED02E292031C5F3000508C9 /* StartScreenClassic.png */, - CED02E282031C5F3000508C9 /* StartScreenDark.png */, - ); - path = Screenshots; - sourceTree = ""; - }; - CEA832661F990689004845F0 /* AppearanceSettings */ = { - isa = PBXGroup; - children = ( - CE88BCD41FCDA45C00A4FA2E /* ButtonConstants.swift */, - CEA832671F9906BF004845F0 /* ColorConstants.swift */, - CEA832691F99079A004845F0 /* StringConstants.swift */, - ); - path = AppearanceSettings; - sourceTree = ""; - }; - CEC2787A2031A0110043899C /* Models */ = { - isa = PBXGroup; - children = ( - CE380425202B3526003032D4 /* ColorScheme.swift */, - CE88BCD21FCD88EA00A4FA2E /* Settings.swift */, - ); - path = Models; - sourceTree = ""; - }; - CED3BA09201F87390071EC23 /* Mocks */ = { - isa = PBXGroup; - children = ( - CE2845BC2020B70A007B1C25 /* ActionRequestLoopMock.swift */, - CED3BA0A201F87510071EC23 /* InternalErrorListenerMock.swift */, - ); - path = Mocks; - sourceTree = ""; - }; - D6405400012B6906279A6D61 /* Frameworks */ = { - isa = PBXGroup; - children = ( - D5A6DD52DA6213CB92530809 /* Pods_WebimClientLibrary_Example.framework */, - 75BFCD5FB1955EE77D987E3C /* Pods_WebimClientLibrary_Tests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 607FACCF1AFB9204008FA782 /* WebimClientLibrary_Example */ = { - isa = PBXNativeTarget; - buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "WebimClientLibrary_Example" */; - buildPhases = ( - 97DA4630C02562D10912CF16 /* [CP] Check Pods Manifest.lock */, - 8CC584B88D331C1B48D729CB /* [Amimono] Create filelist per architecture */, - 607FACCC1AFB9204008FA782 /* Sources */, - 607FACCD1AFB9204008FA782 /* Frameworks */, - 607FACCE1AFB9204008FA782 /* Resources */, - CE86FAB4203C3E6700CB9C2D /* ShellScript */, - BC0CA950BB03125C2F6377C1 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = WebimClientLibrary_Example; - productName = WebimClientLibrary; - productReference = 607FACD01AFB9204008FA782 /* WebimClientLibrary_Example.app */; - productType = "com.apple.product-type.application"; - }; - 607FACE41AFB9204008FA782 /* WebimClientLibrary_Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "WebimClientLibrary_Tests" */; - buildPhases = ( - 8B15E7718621B61E40699296 /* [CP] Check Pods Manifest.lock */, - 607FACE11AFB9204008FA782 /* Sources */, - 607FACE21AFB9204008FA782 /* Frameworks */, - 607FACE31AFB9204008FA782 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 607FACE71AFB9204008FA782 /* PBXTargetDependency */, - ); - name = WebimClientLibrary_Tests; - productName = Tests; - productReference = 607FACE51AFB9204008FA782 /* WebimClientLibrary_Tests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 607FACC81AFB9204008FA782 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 1010; - ORGANIZATIONNAME = CocoaPods; - TargetAttributes = { - 607FACCF1AFB9204008FA782 = { - CreatedOnToolsVersion = 6.3.1; - DevelopmentTeam = 574GE9X9L7; - LastSwiftMigration = 0900; - ProvisioningStyle = Automatic; - SystemCapabilities = { - com.apple.Push = { - enabled = 1; - }; - }; - }; - 607FACE41AFB9204008FA782 = { - CreatedOnToolsVersion = 6.3.1; - LastSwiftMigration = 0900; - TestTargetID = 607FACCF1AFB9204008FA782; - }; - }; - }; - buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "WebimClientLibrary" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - "ru-RU", - ); - mainGroup = 607FACC71AFB9204008FA782; - productRefGroup = 607FACD11AFB9204008FA782 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 607FACCF1AFB9204008FA782 /* WebimClientLibrary_Example */, - 607FACE41AFB9204008FA782 /* WebimClientLibrary_Tests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 607FACCE1AFB9204008FA782 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, - CE5A03BA1FDEB756009D320A /* Localizable.strings in Resources */, - CE324E631FDECBD2004BB116 /* RatingViewController.xib in Resources */, - 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, - 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 607FACE31AFB9204008FA782 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 8B15E7718621B61E40699296 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-WebimClientLibrary_Tests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 8CC584B88D331C1B48D729CB /* [Amimono] Create filelist per architecture */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[Amimono] Create filelist per architecture"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/bash; - shellScript = "declare -a DEPENDENCIES=('Cosmos' 'PopupDialog' 'SQLite.swift' 'SlackTextViewController' 'SnapKit' 'WebimClientLibrary');\nIFS=\" \" read -r -a SPLIT <<< \"$ARCHS\"\nfor ARCH in \"${SPLIT[@]}\"; do\n cd \"$OBJROOT/Pods.build\"\n filelist=\"\"\n for dependency in \"${DEPENDENCIES[@]}\"; do\n path=\"${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}/${dependency}.build/Objects-normal/${ARCH}\"\n if [ -d \"$path\" ]; then\n search_path=\"$path/*.o\"\n for obj_file in $search_path; do\n filelist+=\"${OBJROOT}/Pods.build/${obj_file}\"\n filelist+=$'\\n'\n done\n fi\n done\n filelist=${filelist%$'\\n'}\n echo \"$filelist\" > \"${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}-${TARGET_NAME}-${ARCH}.objects.filelist\"\ndone\n"; - }; - 97DA4630C02562D10912CF16 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-WebimClientLibrary_Example-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - BC0CA950BB03125C2F6377C1 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-WebimClientLibrary_Example/Pods-WebimClientLibrary_Example-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/Cosmos/Cosmos.framework", - "${BUILT_PRODUCTS_DIR}/PopupDialog/PopupDialog.framework", - "${BUILT_PRODUCTS_DIR}/SQLite.swift/SQLite.framework", - "${BUILT_PRODUCTS_DIR}/SlackTextViewController/SlackTextViewController.framework", - "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework", - "${BUILT_PRODUCTS_DIR}/WebimClientLibrary/WebimClientLibrary.framework", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - ); - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Cosmos.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PopupDialog.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SQLite.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SlackTextViewController.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebimClientLibrary.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-WebimClientLibrary_Example/Pods-WebimClientLibrary_Example-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - CE86FAB4203C3E6700CB9C2D /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Fabric/run\" 80055b71f053ff36cce8743fbac5eecae7df7f28 7b5c5723b733cc6cd3e884c6babc2c58039b5f0100489ed510513c1f04df4945"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 607FACCC1AFB9204008FA782 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CE591A431FC2F31E004C95EE /* WebimService.swift in Sources */, - CE48362F2032E3F100E18A20 /* PopupDialogHandler.swift in Sources */, - CEBFB67F2018CB0F00D9E5F6 /* String.swift in Sources */, - 607FACD81AFB9204008FA782 /* StartViewController.swift in Sources */, - CEA849051FFCE29A006CC417 /* UITableView.swift in Sources */, - CE88BCD31FCD88EA00A4FA2E /* Settings.swift in Sources */, - CE380426202B3526003032D4 /* ColorScheme.swift in Sources */, - CE45EDDD1F9108FA00F56319 /* UIImageView.swift in Sources */, - CE44AE651F87CA8E009787E5 /* MessageTableViewCell.swift in Sources */, - CE45EDE01F95F9F700F56319 /* MimeType.swift in Sources */, - CE380424202B0AC2003032D4 /* SettingsTableViewController.swift in Sources */, - CEBFB6812018E50500D9E5F6 /* UIViewController.swift in Sources */, - DDFC632B1F924D41008E1ACC /* UIImage.swift in Sources */, - CEF61A391F82A4C700BF7071 /* ChatViewController.swift in Sources */, - 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, - CE88BCD51FCDA45C00A4FA2E /* ButtonConstants.swift in Sources */, - CEA832681F9906C0004845F0 /* ColorConstants.swift in Sources */, - CEA8326A1F99079A004845F0 /* StringConstants.swift in Sources */, - DDFC63CB1F93F23E008E1ACC /* RatingViewController.swift in Sources */, - CE88BCD11FCD7F9A00A4FA2E /* SettingsViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 607FACE11AFB9204008FA782 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CE24A012203730D5009EE7E7 /* MessageItemTests.swift in Sources */, - CE2CD5972035F12600997628 /* ChatItemTests.swift in Sources */, - CED3BA08201F7E100071EC23 /* WebimActionsTests.swift in Sources */, - CE0CD765202461FE00719DBE /* StringFromHTTPParametersTests.swift in Sources */, - CE0CD75A202338FD00719DBE /* HistoryIDTests.swift in Sources */, - CE995DC32020908F00E27A3C /* WebimRemoteNotificationImplTests.swift in Sources */, - CED72596200E20EF00CD1623 /* ChatViewControllerTests.swift in Sources */, - CE86FA97203AF44700CB9C2D /* VisitorItemTests.swift in Sources */, - CE86FAB8203C48DA00CB9C2D /* MemoryHistoryStorageTests.swift in Sources */, - CE18FB9C203DB32E0059B9FF /* LocationSettingsHolderTests.swift in Sources */, - CE0CD7632024561B00719DBE /* InternalUtilsTests.swift in Sources */, - CEE382C22035D544006C809E /* WebimTests.swift in Sources */, - CE2845C62021CF40007B1C25 /* ClientSideIDTests.swift in Sources */, - CE2845B82020A891007B1C25 /* AbstractRequestLoopTests.swift in Sources */, - CE86FAA3203B122A00CB9C2D /* HistorySinceResponseTests.swift in Sources */, - CE5B7E622056B26C00DDA407 /* WebimClientTests.swift in Sources */, - CE2845C22021B9D4007B1C25 /* DecodePercentEscapedLinksIfPresentTests.swift in Sources */, - CE2CD5952035DF6E00997628 /* MemoryHistoryMetaInformationStorageTests.swift in Sources */, - CE6741C8200F9A600061EEFD /* HMACSha256Tests.swift in Sources */, - CE86FA9F203B07F400CB9C2D /* DeltaResponseTests.swift in Sources */, - CE2845BB2020B6A3007B1C25 /* ActionRequestLoopTests.swift in Sources */, - CE86FAA5203B1B7300CB9C2D /* MessageFactoriesTests.swift in Sources */, - CE86FAC0203C6FBC00CB9C2D /* WebimErrorImplTests.swift in Sources */, - CE07E9952049794C00E0A0D3 /* SessionBuilderTests.swift in Sources */, - CE5B7E5C20500A6F00DDA407 /* ProvidedVisitorFieldsTests.swift in Sources */, - CE0CD75D20234BD800719DBE /* SessionDestroyerTests.swift in Sources */, - CE86FAB1203C18D600CB9C2D /* DepartmentFactoryTests.swift in Sources */, - CE86FAAF203B2D1800CB9C2D /* OperatorFactoryTests.swift in Sources */, - 607FACEC1AFB9204008FA782 /* MessageHolderTests.swift in Sources */, - CE24A019203ADF40009EE7E7 /* RatingItemTests.swift in Sources */, - CE2845BE2020B718007B1C25 /* ActionRequestLoopMock.swift in Sources */, - CE18FB9E203EBCB00059B9FF /* MessageStreamImplTests.swift in Sources */, - CE2845C42021C2BF007B1C25 /* AuthorizationDataTests.swift in Sources */, - CE24A01020372629009EE7E7 /* FileParametersItemTests.swift in Sources */, - CE24A014203735C8009EE7E7 /* OperatorItemTests.swift in Sources */, - CE86FAA1203B0B1600CB9C2D /* HistoryBeforeResponseTests.swift in Sources */, - CE24A00E20372239009EE7E7 /* DepartmentItemTests.swift in Sources */, - CE0CD76720249C3E00719DBE /* OperatorImplTests.swift in Sources */, - CE48362C2031DA5E00E18A20 /* MimeTypeTests.swift in Sources */, - CE86FA99203AF6AC00CB9C2D /* UIColorHexStringTests.swift in Sources */, - CE86FA9B203AFBFB00CB9C2D /* DeltaItemTests.swift in Sources */, - CED72599200E5B2200CD1623 /* WebimInternalLoggerTests.swift in Sources */, - CE1FC99E202333B20090F7E6 /* ExecIfNotDestroyedHandlerExecutorTests.swift in Sources */, - CE86FA9D203B009400CB9C2D /* FullUpdateTests.swift in Sources */, - CE2845C82021DBE5007B1C25 /* DeltaRequestLoopTests.swift in Sources */, - CE86FAB3203C1E8500CB9C2D /* SQLiteHistoryStorageTests.swift in Sources */, - CE86FABC203C664F00CB9C2D /* LocationSettingsImplTests.swift in Sources */, - CED3BA0B201F87510071EC23 /* InternalErrorListenerMock.swift in Sources */, - CE86FABE203C686600CB9C2D /* MessageImplTests.swift in Sources */, - CE18FB9A203DA3890059B9FF /* AccessCheckerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 607FACCF1AFB9204008FA782 /* WebimClientLibrary_Example */; - targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 607FACD91AFB9204008FA782 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 607FACDA1AFB9204008FA782 /* Base */, - CEC27878202DDB760043899C /* ru-RU */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 607FACDF1AFB9204008FA782 /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; - CE324E651FDECBD2004BB116 /* RatingViewController.xib */ = { - isa = PBXVariantGroup; - children = ( - CE324E661FDECBE0004BB116 /* Base */, - CEC27879202DDD920043899C /* ru-RU */, - ); - name = RatingViewController.xib; - sourceTree = ""; - }; - CE5A03BC1FDEB756009D320A /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - CE5A03BB1FDEB756009D320A /* ru-RU */, - CE9379091FEAADC80057E270 /* Base */, - ); - name = Localizable.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 607FACED1AFB9204008FA782 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: hummingbirddj@gmail.com (5AWBA79F9B)"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 607FACEE1AFB9204008FA782 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 607FACF01AFB9204008FA782 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F0808D307D6955C0CC345203 /* Pods-WebimClientLibrary_Example.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = WebimClientLibrary_Example.entitlements; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 574GE9X9L7; - FRAMEWORK_SEARCH_PATHS = " $(inherited)"; - INFOPLIST_FILE = WebimClientLibrary/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MODULE_NAME = ExampleApp; - OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" -Xfrontend -warn-long-expression-type-checking=100 -Xfrontend -warn-long-function-bodies=200 -Onone"; - PRODUCT_BUNDLE_IDENTIFIER = "ru.webim.Webim-Client"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 607FACF11AFB9204008FA782 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9F85297EB410C96E5341BFCC /* Pods-WebimClientLibrary_Example.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = WebimClientLibrary_Example.entitlements; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 574GE9X9L7; - FRAMEWORK_SEARCH_PATHS = " $(inherited)"; - INFOPLIST_FILE = WebimClientLibrary/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MODULE_NAME = ExampleApp; - PRODUCT_BUNDLE_IDENTIFIER = "ru.webim.Webim-Client"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 607FACF31AFB9204008FA782 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 998795E306696F247C099BA2 /* Pods-WebimClientLibrary_Tests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WebimClientLibrary_Example.app/WebimClientLibrary_Example"; - }; - name = Debug; - }; - 607FACF41AFB9204008FA782 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 188E01CE8A86B2460C60C156 /* Pods-WebimClientLibrary_Tests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = ""; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.2; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WebimClientLibrary_Example.app/WebimClientLibrary_Example"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "WebimClientLibrary" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 607FACED1AFB9204008FA782 /* Debug */, - 607FACEE1AFB9204008FA782 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "WebimClientLibrary_Example" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 607FACF01AFB9204008FA782 /* Debug */, - 607FACF11AFB9204008FA782 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "WebimClientLibrary_Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 607FACF31AFB9204008FA782 /* Debug */, - 607FACF41AFB9204008FA782 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 607FACC81AFB9204008FA782 /* Project object */; -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary.xcworkspace/contents.xcworkspacedata b/ios/libs/Webim/Example/WebimClientLibrary.xcworkspace/contents.xcworkspacedata deleted file mode 100755 index cf39992..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/ios/libs/Webim/Example/WebimClientLibrary.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/libs/Webim/Example/WebimClientLibrary.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100755 index 3ddf867..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - BuildSystemType - Latest - - diff --git a/ios/libs/Webim/Example/WebimClientLibrary/AppDelegate.swift b/ios/libs/Webim/Example/WebimClientLibrary/AppDelegate.swift deleted file mode 100755 index 461c5bb..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/AppDelegate.swift +++ /dev/null @@ -1,104 +0,0 @@ -// -// AppDelegate.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 01.00.2017. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Crashlytics -import Fabric -import UIKit -import WebimClientLibrary - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - // MARK: - Constants - enum UserDefaultsKey: String { - case deviceToken = "device-token" - } - - // MARK: - Properties - var window: UIWindow? - - // MARK: - Methods - - func application(_ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - Fabric.with([Crashlytics.self]) - - // Remote notifications configuration - let notificationTypes: UIUserNotificationType = [.alert, - .badge, - .sound] - let remoteNotificationSettings = UIUserNotificationSettings(types: notificationTypes, - categories: nil) - application.registerUserNotificationSettings(remoteNotificationSettings) - application.registerForRemoteNotifications() - application.applicationIconBadgeNumber = 0 - - - - return true - } - - func application(_ application: UIApplication, - didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { - let deviceToken = deviceToken.map { String(format: "%02.2hhx", $0) }.joined() - UserDefaults.standard.set(deviceToken, - forKey: UserDefaultsKey.deviceToken.rawValue) - - print("Device token: \(deviceToken)") - } - - func application(_ application: UIApplication, - didFailToRegisterForRemoteNotificationsWithError error: Error) { - print("Remote notification support is unavailable due to error: \(error.localizedDescription)") - } - - func application(_ application: UIApplication, - didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { - print(userInfo) - - // WEBIM: Remote notification handling. - if Webim.isWebim(remoteNotification: userInfo) == true { - _ = Webim.parse(remoteNotification: userInfo) - // Handle Webim remote notification. - } else { - // Handle another type of remote notification. - } - } - - func setStatusBarColor() { - switch ColorScheme.shared.schemeType { - case .light: - UIApplication.shared.statusBarStyle = .default - - break - case .dark: - UIApplication.shared.statusBarStyle = .lightContent - - break - } - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/AppearanceSettings/ButtonConstants.swift b/ios/libs/Webim/Example/WebimClientLibrary/AppearanceSettings/ButtonConstants.swift deleted file mode 100755 index f4b945f..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/AppearanceSettings/ButtonConstants.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// ButtonConstants.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 28.11.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -//startChatButton -enum Button: CGFloat { - case borderWidth = 0 - case cornerRadius = 8.0 -} - -enum TransparentButton: CGFloat { - case borderWidth = 1.0 - case cornerRadius = 8.0 -} - -// Scroll to bottom button. -enum ScrollToBottomButton: CGFloat { - case margin = 8.0 - case size = 48.0 - case visibilityThreshold = 60.0 -} -enum ScrollToBottomButtonAnimation: Double { - case duration = 0.2 -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/AppearanceSettings/ColorConstants.swift b/ios/libs/Webim/Example/WebimClientLibrary/AppearanceSettings/ColorConstants.swift deleted file mode 100755 index 741e950..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/AppearanceSettings/ColorConstants.swift +++ /dev/null @@ -1,153 +0,0 @@ -// -// File.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 19.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -// MARK: - Colors - -fileprivate let RED_COLOR = UIColor(red: (192.0 / 255.0), - green: (0.0 / 255.0), - blue: (64.0 / 255.0), - alpha: 1.0) - -// MARK: Classic scheme -fileprivate let BACKGROUND_CELL_LIGHT_COLOR_CLASSIC = UIColor.white -//Background main color light(StartVC) -fileprivate let BACKGROUND_MAIN_COLOR_CLASSIC = UIColor.white -fileprivate let BACKGROUND_SECONDARY_COLOR_CLASSIC = BACKGROUND_MAIN_COLOR_CLASSIC -fileprivate let BACKGROUND_TABLE_VIEW_COLOR_CLASSIC = UIColor.white -//cell field(SettingsVC) -fileprivate let BACKGROUND_TEXT_FIELD_COLOR_CLASSIC = UIColor(red: (239.0 / 255.0), - green: (239.0 / 255.0), - blue: (244.0 / 255.0), - alpha: 1.0) -fileprivate let BUTTON_BORDER_COLOR_CLASSIC = UIColor(red: (67.0 / 255.0), - green: (67.0 / 255.0), - blue: (67.0 / 255.0), - alpha: 1.0) -//startChatButton light(StartVC) -fileprivate let BUTTON_COLOR_CLASSIC = UIColor(red: (11 / 255.0), - green: (180.0 / 255.0), - blue: (168.0 / 255.0), - alpha: 1.0) -//separation_light between light and dark(SettingsVC) -fileprivate let DELIMITER_COLOR_CLASSIC = BACKGROUND_MAIN_COLOR_CLASSIC -//startChatButton_light text(StartVC) -fileprivate let TEXT_BUTTON_COLOR_CLASSIC = BACKGROUND_MAIN_COLOR_CLASSIC -//settingsButton_light text and border(StartVC) -fileprivate let TEXT_BUTTON_TRANSPARENT_COLOR_CLASSIC = BACKGROUND_MAIN_COLOR_DARK -fileprivate let TEXT_BUTTON_TRANSPARENT_HIGHLIGHTED_COLOR_CLASSIC = UIColor.lightGray -//text in separation light(SettingsVC) -fileprivate let TEXT_CELL_LIGHT_COLOR_CLASSIC = BACKGROUND_MAIN_COLOR_DARK -//start_text_main_light color(StartVC) -fileprivate let TEXT_MAIN_COLOR_CLASSIC = BACKGROUND_MAIN_COLOR_DARK -fileprivate let TEXT_NAME_OPERATOR_COLOR_CLASSIC = RED_COLOR -fileprivate let TEXT_NAME_VISITOR_COLOR_CLASSIC = UIColor(red: (0.0 / 255.0), - green: (152.0 / 255.0), - blue: (79.0 / 255.0), - alpha: 1.0) -fileprivate let TEXT_SECONDARY_COLOR_CLASSIC = UIColor.darkGray -//cell text light(SettingsVC) -fileprivate let TEXT_TEXT_FIELD_COLOR_CLASSIC = BACKGROUND_MAIN_COLOR_DARK -fileprivate let TEXT_TEXT_FIELD_ERROR_COLOR_CLASSIC = RED_COLOR -//start_text_tint_main_light color(StartVC) -fileprivate let TEXT_TINT_COLOR_CLASSIC = BUTTON_COLOR_CLASSIC - -// MARK: Dark theme -//(SettingsVC) -fileprivate let BACKGROUND_CELL_LIGHT_COLOR_DARK = BACKGROUND_MAIN_COLOR_DARK -//Background main color dark(StartVC) -fileprivate let BACKGROUND_MAIN_COLOR_DARK = UIColor(red: (47.0 / 255.0), - green: (49.0 / 255.0), - blue: (95.0 / 255.0), - alpha: 1.0) -//top of the screen dark(StartVC) -fileprivate let BACKGROUND_SECONDARY_COLOR_DARK = BACKGROUND_MAIN_COLOR_DARK -//(ChatVC) -fileprivate let BACKGROUND_TABLE_VIEW_COLOR_DARK = BACKGROUND_MAIN_COLOR_DARK -//cell field(SettingsVC) -fileprivate let BACKGROUND_TEXT_FIELD_COLOR_DARK = BACKGROUND_TEXT_FIELD_COLOR_CLASSIC -fileprivate let BUTTON_BORDER_COLOR_DARK = BUTTON_BORDER_COLOR_CLASSIC -//startChatButton light(StartVC) -fileprivate let BUTTON_COLOR_DARK = BUTTON_COLOR_CLASSIC -//separation_dark between light and dark(SettingsVC) -fileprivate let DELIMITER_COLOR_DARK = BACKGROUND_MAIN_COLOR_DARK -//startChatButton_light text(StartVC) -fileprivate let TEXT_BUTTON_COLOR_DARK = UIColor.white -//settingsButton_dark text and border(StartVC) -fileprivate let TEXT_BUTTON_TRANSPARENT_COLOR_DARK = UIColor.white -fileprivate let TEXT_BUTTON_TRANSPARENT_HIGHLIGHTED_COLOR_DARK = UIColor.white -//text in separation light(SettingsVC) -fileprivate let TEXT_CELL_LIGHT_COLOR_DARK = UIColor.white -fileprivate let TEXT_MAIN_COLOR_DARK = UIColor.white -fileprivate let TEXT_NAME_OPERATOR_COLOR_DARK = TEXT_NAME_OPERATOR_COLOR_CLASSIC -fileprivate let TEXT_NAME_VISITOR_COLOR_DARK = TEXT_NAME_VISITOR_COLOR_CLASSIC -fileprivate let TEXT_SECONDARY_COLOR_DARK = UIColor.lightGray -//cell text dark(SettingsVC) -fileprivate let TEXT_TEXT_FIELD_COLOR_DARK = BACKGROUND_MAIN_COLOR_DARK -fileprivate let TEXT_TEXT_FIELD_ERROR_COLOR_DARK = TEXT_TEXT_FIELD_ERROR_COLOR_CLASSIC -//start_text_tint_main_dark color(StartVC) -fileprivate let TEXT_TINT_COLOR_DARK = BUTTON_COLOR_CLASSIC - -// MARK: - Model -let backgroundCellLightColor = SchemeColor(classic: BACKGROUND_CELL_LIGHT_COLOR_CLASSIC, - dark: BACKGROUND_CELL_LIGHT_COLOR_DARK) -let backgroundMainColor = SchemeColor(classic: BACKGROUND_MAIN_COLOR_CLASSIC, - dark: BACKGROUND_MAIN_COLOR_DARK) -let backgroundSecondaryColor = SchemeColor(classic: BACKGROUND_SECONDARY_COLOR_CLASSIC, - dark: BACKGROUND_SECONDARY_COLOR_DARK) -let backgroundTableViewColor = SchemeColor(classic: BACKGROUND_TABLE_VIEW_COLOR_CLASSIC, - dark: BACKGROUND_TABLE_VIEW_COLOR_DARK) -let backgroundTextFieldColor = SchemeColor(classic: BACKGROUND_TEXT_FIELD_COLOR_CLASSIC, - dark: BACKGROUND_TEXT_FIELD_COLOR_DARK) -let buttonBorderColor = SchemeColor(classic: BUTTON_BORDER_COLOR_CLASSIC, - dark: BUTTON_BORDER_COLOR_DARK) -let buttonColor = SchemeColor(classic: BUTTON_COLOR_CLASSIC, - dark: BUTTON_COLOR_DARK) -let delimiterColor = SchemeColor(classic: DELIMITER_COLOR_CLASSIC, - dark: DELIMITER_COLOR_DARK) -let textButtonColor = SchemeColor(classic: TEXT_BUTTON_COLOR_CLASSIC, - dark: TEXT_BUTTON_COLOR_DARK) -let textButtonTransparentColor = SchemeColor(classic: TEXT_BUTTON_TRANSPARENT_COLOR_CLASSIC, - dark: TEXT_BUTTON_TRANSPARENT_COLOR_DARK) -let textButtonTransparentHighlightedColor = SchemeColor(classic: TEXT_BUTTON_TRANSPARENT_HIGHLIGHTED_COLOR_CLASSIC, - dark: TEXT_BUTTON_TRANSPARENT_HIGHLIGHTED_COLOR_DARK) -let textCellLightColor = SchemeColor(classic: TEXT_CELL_LIGHT_COLOR_CLASSIC, - dark: TEXT_CELL_LIGHT_COLOR_DARK) -let textMainColor = SchemeColor(classic: TEXT_MAIN_COLOR_CLASSIC, - dark: TEXT_MAIN_COLOR_DARK) -let textNameOperatorColor = SchemeColor(classic: TEXT_NAME_OPERATOR_COLOR_CLASSIC, - dark: TEXT_NAME_OPERATOR_COLOR_DARK) -let textNameVisitorColor = SchemeColor(classic: TEXT_NAME_VISITOR_COLOR_CLASSIC, - dark: TEXT_NAME_VISITOR_COLOR_DARK) -let textSecondaryColor = SchemeColor(classic: TEXT_SECONDARY_COLOR_CLASSIC, - dark: TEXT_SECONDARY_COLOR_DARK) -let textTextFieldColor = SchemeColor(classic: TEXT_TEXT_FIELD_COLOR_CLASSIC, - dark: TEXT_TEXT_FIELD_COLOR_DARK) -let textTextFieldErrorColor = SchemeColor(classic: TEXT_TEXT_FIELD_ERROR_COLOR_CLASSIC, - dark: TEXT_TEXT_FIELD_ERROR_COLOR_CLASSIC) -let textTintColor = SchemeColor(classic: TEXT_TINT_COLOR_CLASSIC, - dark: TEXT_TINT_COLOR_DARK) diff --git a/ios/libs/Webim/Example/WebimClientLibrary/AppearanceSettings/StringConstants.swift b/ios/libs/Webim/Example/WebimClientLibrary/AppearanceSettings/StringConstants.swift deleted file mode 100755 index 65e0cb7..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/AppearanceSettings/StringConstants.swift +++ /dev/null @@ -1,139 +0,0 @@ -// -// StringConstants.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 19.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -enum Avatar: String { - case accessibilityLabel = "SenderAvatarImage" - case accessibilityHintOperator = "ShowsRatingDialog" -} - -enum BackButton: String { - case accessibilityLabel = "Back" - case accessibilityHint = "ClosesScreen" -} - -enum ChatClosedDialog: String { - case message = "ChatClosed" - - case buttonTitle = "OK" - case buttonAccessibilityHint = "ClosesDialog" -} - -enum CloseChatButton: String { - case accessibilityLabel = "CloseChat" - case accessibilityHint = "ClosesChat" -} - -enum DepartmentListDialog: String { - case title = "ContactTopic" - - case buttonAccessibilityHint = "ChoosesTopic" - - case cancelButtonTitle = "Cancel" - case cancelButtonAccessibilityHint = "ClosesDialog" -} - -enum FileMessage: String { - case fileUnavailable = "FileUnavailable" -} - -enum LeftButton: String { - case accessibilityLabel = "ChooseFile" - case accessibilityHint = "ShowsImagePicker" -} - -enum RateOperatorErrorMessage: String { - case title = "OperatorRatingFailed" - - case buttonTitle = "OK" - case buttonAccessibilityHint = "ClosesRateOperatorError" - - case message = "RateOperatorErrorMessage" -} - -enum RatingDialog: String { - case actionButtonAccessibilityHint = "RatesOperator" - case actionButtonTitle = "Rate" - - case cancelButtonAccessibilityHint = "ClosesRatingDialog" - case cancelButtonTitle = "Cancel" -} - -enum SendFileErrorMessage: String { - case title = "FileSendingFailed" - - case buttonTitle = "OK" - case buttonAccessibilityHint = "ClosesSendFileError" - - // Error messages - case fileSizeExceeded = "FileTooLarge" - case fileTypeNotAllowed = "FileTypeNotSupported" - case fileNotFound = "FileNotFound" - case unknownError = "FileSendingUnknownError" -} - -enum SessionCreationErrorDialog: String { - case buttonTitle = "OK" - case buttonAccessibilityHint = "ClosesSessionError" - - case title = "SessionCreationFailed" - - // Error messages - case accountBlocked = "AccountBlocked" - case visitorBanned = "VisitorBanned" -} - -enum SettingsErrorDialog: String { - case buttonTitle = "OK" - case buttonAccessibilityHint = "ClosesSettingsError" - - case title = "InvalidSettings" - - // Error messages - case wrongAccountName = "AccountNameEmpty" - case wrongLocation = "LocationEmpty" -} - -enum ShowFileDialog: String { - case buttonTitle = "OK" - - // Error messages - case imageFormatInvalid = "ImageFormatInvalid" - case imageLinkInvalid = "ImageLinkInvalid" - case notImage = "PreviewUnavailable" - - case accessibilityHint = "ClosesFilePreview" -} - -enum StartView: String { - case welcomeText = "Welcome to the WebimClientLibrary demo app!\n\nTo start a chat tap on the button below.\n\nOperator can answer to your chat at:\nhttps://demo.webim.ru/\nLogin: o@webim.ru\nPassword: password\n\nThis app source code can be found at:\nhttps://github.com/webim/webim-client-sdk-ios" -} - -enum TableView: String { - case refreshControlText = "LoadingMessages" - case emptyTableViewText = "EmptyChat" -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/LaunchScreen.xib b/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/LaunchScreen.xib deleted file mode 100755 index e0de33c..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/Localizable.strings b/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/Localizable.strings deleted file mode 100755 index 031fed8..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/Localizable.strings +++ /dev/null @@ -1,109 +0,0 @@ -/* - Localizable.strings - WebimClientLibrary - - Created by Nikita Lazarev-Zubov on 11.12.17. - Copyright © 2017 Webim. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - - -// MARK: - Remote notifications - -"P.OA" = "Operator assigned to your appeal: %@."; -"P.OF" = "%@ has sent file: %@."; -"P.OM" = "%@ has sent message: %@."; - - -// MARK: - StringConstants.swift - -// EMPTY_TABLE_VIEW_TEXT -"EmptyChat" = "Send first message to start chat."; - -// REFRESH_CONTROL_TEXT -"LoadingMessages" = "Loading messages..."; - -// Avatar -"SenderAvatarImage" = "Sender avatar image"; -"ShowsRatingDialog" = "Shows rating dialog."; - -// BackButton -"Back" = "Close screen"; -"ClosesScreen" = "Closes screen for returning to previous screen."; - -// ChatClosedDialog -"ChatClosed" = "Chat finished."; -"OK" = "OK"; -"ClosesRateOperatorError" = "Closes dialog."; - -// CloseChatButton -"CloseChat" = "Close chat"; -"ClosesChat" = "Closes chat without closing this screen."; - -// DepartmentListDialog -"ContactTopic" = "Contact topic"; -"ChoosesTopic" = "Chooses this topic for contacting."; -"Cancel" = "Cancel"; -"ClosesDialog" = "Closes dialog."; - -// FileMessage -"FileUnavailable" = "File is unavailable."; - -// LeftButton -"ChooseFile" = "Choose file"; -"ShowsImagePicker" = "Shows image picker to choose an image to send."; - -// RateOperatorErrorMessage -"OperatorRatingFailed" = "Operator rating failed"; -"OK" = "OK"; -"ClosesRateOperatorError" = "Closes dialog."; -"RateOperatorErrorMessage" = "Unknown error occured."; - -// RatingDialog -"Rate" = "Rate"; -"Cancel" = "Cancel"; -"RatesOperator" = "Rates operator with chosen rating."; -"ClosesRatingDialog" = "Closes rating dialog."; - -// SendFileErrorMessage -"FileSendingFailed" = "File sending failed"; -"ClosesSendFileError" = "Closes dialog."; -"FileTooLarge" = "File is too large."; -"FileTypeNotSupported" = "File type is not supported."; -"FileNotFound" = "Sending files in body is not supported."; -"FileSendingUnknownError" = "Find sending unknown error."; - -// SessionCreationErrorDialog -"ClosesSessionError" = "Closes dialog."; -"SessionCreationFailed" = "Session creation failed"; -"AccountBlocked" = "Account that is used to create session is blocked. Please contact Webim support or use another one."; -"VisitorBanned" = "Your visitor account is in the black list."; - -// SettingsErrorDialog -"ClosesSettingsError" = "Closes dialog."; -"InvalidSettings" = "Invalid account settings"; -"AccountNameEmpty" = "Account name can't be empty."; -"LocationEmpty" = "Location can't be empty."; - -// ShowFileDialog -"ImageFormatInvalid" = "Image format is not valid."; -"ImageLinkInvalid" = "Image link is not valid."; -"PreviewUnavailable" = "Preview is not available."; -"ClosesFilePreview" = "Closes file preview."; diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/Main.storyboard b/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/Main.storyboard deleted file mode 100755 index 3252b8a..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/Main.storyboard +++ /dev/null @@ -1,422 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Welcome to the WebimClientLibrary demo app! - -To start a chat tap on the button below. - -Operator can answer to your chat at: -https://demo.webim.ru/ -Login: o@webim.ru -Password: password - -This app source code can be found at: -https://github.com/webim/webim-client-sdk-ios - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/RatingViewController.xib b/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/RatingViewController.xib deleted file mode 100755 index 34e260e..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Base.lproj/RatingViewController.xib +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/libs/Webim/Example/WebimClientLibrary/ChatViewController.swift b/ios/libs/Webim/Example/WebimClientLibrary/ChatViewController.swift deleted file mode 100755 index 2ac89b5..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/ChatViewController.swift +++ /dev/null @@ -1,637 +0,0 @@ -// -// ChatViewController.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 02.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import SlackTextViewController -import UIKit -import WebimClientLibrary - -final class ChatViewController: SLKTextViewController { - - // MARK: - Properties - private let imagePicker = UIImagePickerController() - private let refreshControl = UIRefreshControl() - private lazy var alreadyRated = [String: Bool]() - private var lastOperatorID: String? - private lazy var messages = [Message]() - private var popupDialogHandler: PopupDialogHandler? - private var scrollToBottomButton: UIButton? - private var webimService: WebimService? - - - // MARK: - Methods - - override func viewDidLoad() { - super.viewDidLoad() - - webimService = WebimService(fatalErrorHandlerDelegate: self, - departmentListHandlerDelegate: self) - popupDialogHandler = PopupDialogHandler(delegate: self) - - imagePicker.delegate = self - - setupNavigationItem() - setupRefreshControl() - setupSlackTextViewController() - setupWebimSession() - } - - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - setupTableView() - - scrollToBottomButton?.removeFromSuperview() // Need for redrawing after device is rotated. - setupScrollToBottomButton() - } - - // For testing purposes. - func set(messages: [Message]) { - self.messages = messages - } - - // MARK: SlackTextViewController methods - - override func textViewDidChange(_ textView: UITextView) { - webimService!.setVisitorTyping(draft: textView.text) - } - - override func didPressRightButton(_ sender: Any?) { // Send message button - textView.refreshFirstResponder() - - if let text = textView.text, - !text.isEmpty { - webimService!.send(message: text) { [weak self] in - self?.textView.text = "" - self?.webimService!.setVisitorTyping(draft: nil) // Delete visitor typing draft after message is sent. - } - } - } - - override func didPressLeftButton(_ sender: Any?) { // Send file buton - dismissKeyboard(true) - - imagePicker.allowsEditing = false - imagePicker.sourceType = .photoLibrary - present(imagePicker, - animated: true, - completion: nil) - } - - // MARK: UICollectionViewDataSource methods - override func numberOfSections(in tableView: UITableView) -> Int { - if messages.count > 0 { - tableView.backgroundView = nil - - return 1 - } else { - tableView.emptyTableView(message: TableView.emptyTableViewText.rawValue.localized) - - return 0 - } - } - - - // MARK: UITableViewDelegate methods - - override func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - return messages.count - } - - override func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", - for: indexPath) as? MessageTableViewCell else { - fatalError("The dequeued cell is not an instance of MessageTableViewCell.") - } - - let message = messages[indexPath.row] - cell.setContent(withMessage: message) - - if let operatorID = message.getOperatorID() { - lastOperatorID = operatorID // For using on chat closing. - let gestureRecognizer = UITapGestureRecognizer(target: self, - action: #selector(ChatViewController.rateOperator(_:))) - cell.avatarImageView.addGestureRecognizer(gestureRecognizer) - } - - if (message.getType() == .FILE_FROM_OPERATOR) - || (message.getType() == .FILE_FROM_VISITOR) { - let gestureRecognizer = UITapGestureRecognizer(target: self, - action: #selector(ChatViewController.showFile(_:))) - cell.bodyLabel.addGestureRecognizer(gestureRecognizer) - } - - return cell - } - - // MARK: UIScrollViewDelegate protocol methods - override func scrollViewDidScroll(_ scrollView: UIScrollView) { - if tableView!.contentOffset.y >= (tableView!.contentSize.height - tableView!.frame.size.height - ScrollToBottomButton.visibilityThreshold.rawValue) { - UIView.animate(withDuration: ScrollToBottomButtonAnimation.duration.rawValue, - delay: 0.1, - options: [], - animations: { [weak self] in - self?.scrollToBottomButton?.alpha = 0.0 - } - , completion: nil) - } else { - UIView.animate(withDuration: ScrollToBottomButtonAnimation.duration.rawValue, - delay: 0.1, - options: [], - animations: { [weak self] in - self?.scrollToBottomButton?.alpha = 1.0 - } - , completion: nil) - } - } - - // MARK: Private methods - - private func setupTableView() { - tableView?.backgroundColor = backgroundTableViewColor.color() - - tableView?.estimatedRowHeight = 64.0 - tableView?.rowHeight = UITableView.automaticDimension - tableView?.separatorStyle = .none - tableView?.register(MessageTableViewCell.self, - forCellReuseIdentifier: "MessageCell") - } - - private func setupRefreshControl() { - if #available(iOS 10.0, *) { - tableView?.refreshControl = refreshControl - } else { - tableView?.addSubview(refreshControl) - } - refreshControl.addTarget(self, - action: #selector(requestMessages), - for: .valueChanged) - refreshControl.tintColor = textMainColor.color() - refreshControl.attributedTitle = NSAttributedString(string: TableView.refreshControlText.rawValue.localized, - attributes: [.foregroundColor : textMainColor.color()]) - } - - private func setupSlackTextViewController() { - isInverted = false - - leftButton.setImage(#imageLiteral(resourceName: "Clip"), - for: .normal) - leftButton.accessibilityLabel = LeftButton.accessibilityLabel.rawValue.localized - leftButton.accessibilityHint = LeftButton.accessibilityHint.rawValue.localized - - rightButton.setImage(#imageLiteral(resourceName: "SendMessage"), - for: .normal) - rightButton.setTitle(nil, - for: .normal) - - textInputbar.tintColor = textTintColor.color() - textInputbar.backgroundColor = backgroundSecondaryColor.color() - textInputbar.textView.textInputView.layer.backgroundColor = backgroundTextFieldColor.color().cgColor - textInputbar.textView.textColor = textTextFieldColor.color() - textInputbar.textView.tintColor = textTextFieldColor.color() - textInputbar.textView.keyboardAppearance = ColorScheme.shared.keyboardAppearance() - textInputbar.textView.layer.cornerRadius = 15.0 - } - - private func setupNavigationItem() { - setupLeftBarButtonItem() - setupRightBarButtonItem() - setupTitleView() - } - - private func setupLeftBarButtonItem() { - let backButton = UIButton(type: .custom) - backButton.setImage(ColorScheme.shared.backButtonImage(), - for: .normal) - backButton.imageView?.contentMode = .scaleAspectFit - backButton.accessibilityLabel = BackButton.accessibilityLabel.rawValue.localized - backButton.accessibilityHint = BackButton.accessibilityHint.rawValue.localized - backButton.addTarget(self, - action: #selector(onBackButtonClick(sender:)), - for: .touchUpInside) - let leftBarButtonItem = UIBarButtonItem(customView: backButton) - navigationItem.leftBarButtonItem = leftBarButtonItem - } - - @objc - private func onBackButtonClick(sender: UIButton) { - webimService!.stopSession() - - navigationController?.popViewController(animated: true) - } - - private func setupRightBarButtonItem() { - let closeChatButton = UIButton(type: .custom) - closeChatButton.setImage(ColorScheme.shared.closeChatButtonImage(), - for: .normal) - closeChatButton.imageView?.contentMode = .scaleAspectFit - closeChatButton.accessibilityLabel = CloseChatButton.accessibilityLabel.rawValue.localized - closeChatButton.accessibilityHint = CloseChatButton.accessibilityHint.rawValue.localized - closeChatButton.addTarget(self, - action: #selector(endChat), - for: .touchUpInside) - navigationItem.rightBarButtonItem = UIBarButtonItem(customView: closeChatButton) - } - - @objc - private func endChat() { - webimService!.closeChat() - - if let operatorID = lastOperatorID { - if alreadyRated[operatorID] != true { // Don't offer to rate an operator if a visitor already did it independently. - if showRatingDialog(forOperator: operatorID) { - return - } - } - } - - popupDialogHandler?.showChatClosedDialog() - } - - private func setupTitleView() { - let navigationItemImageView = UIImageView(image: ColorScheme.shared.navigationItemImage()) - navigationItemImageView.contentMode = .scaleAspectFit - navigationItem.titleView = navigationItemImageView - } - - private func setupScrollToBottomButton() { - let xPosition = view.frame.size.width - ScrollToBottomButton.size.rawValue - ScrollToBottomButton.margin.rawValue - let yPosition = UIApplication.shared.statusBarFrame.height + navigationController!.navigationBar.frame.size.height + ScrollToBottomButton.margin.rawValue - scrollToBottomButton = UIButton(frame: CGRect(x: xPosition, - y: yPosition, - width: ScrollToBottomButton.size.rawValue, - height: ScrollToBottomButton.size.rawValue)) - scrollToBottomButton!.setImage(ColorScheme.shared.scrollToBottomButtonImage(), - for: .normal) - scrollToBottomButton!.addTarget(self, - action: #selector(scrollToBottom), - for: .touchUpInside) - scrollToBottomButton!.alpha = 0.0 - view.addSubview(scrollToBottomButton!) - } - - private func setupWebimSession() { - webimService!.createSession() - webimService!.startSession() - - webimService!.setMessageStream() - webimService!.setMessageTracker(withMessageListener: self) - webimService!.getLastMessages() { [weak self] messages in - self?.messages.insert(contentsOf: messages, - at: 0) - DispatchQueue.main.async() { - self?.tableView?.reloadData() - self?.scrollToBottom() - self?.webimService?.setChatRead() - } - } - } - - @objc - private func requestMessages() { - webimService!.getNextMessages() { [weak self] messages in - self?.messages.insert(contentsOf: messages, - at: 0) - DispatchQueue.main.async() { - self?.tableView?.reloadData() - self?.refreshControl.endRefreshing() - self?.webimService?.setChatRead() - } - } - } - - @objc - private func rateOperator(_ recognizer: UITapGestureRecognizer) { - guard recognizer.state == .ended else { - return - } - - let tapLocation = recognizer.location(in: tableView) - if let tapIndexPath = tableView?.indexPathForRow(at: tapLocation) { - let message = messages[tapIndexPath.row] - if let operatorID = message.getOperatorID() { - _ = showRatingDialog(forOperator: operatorID) - } - } - } - - private func showRatingDialog(forOperator operatorID: String) -> Bool { - guard webimService!.isChatExist() else { - return false - } - - popupDialogHandler?.showRatingDialog(forOperator: operatorID) { [weak self] rating in - self?.alreadyRated[operatorID] = true - - self?.webimService!.rateOperator(withID: operatorID, - byRating: rating, - completionHandler: self) - } - - return true - } - - @objc - private func showFile(_ recognizer: UITapGestureRecognizer) { - guard recognizer.state == .ended else { - return - } - - let tapLocation = recognizer.location(in: tableView) - guard let tapIndexPath = tableView?.indexPathForRow(at: tapLocation) else { - return - } - - let message = messages[tapIndexPath.row] - guard let attachment = message.getAttachment() else { - return - } - - let attachmentURL = attachment.getURL() - - var popupMessage: String? - var image: UIImage? - - if isImage(contentType: attachment.getContentType()) { - let semaphore = DispatchSemaphore(value: 0) - let request = URLRequest(url: attachmentURL) - - print("Requesting file: \(attachmentURL.absoluteString)") - - URLSession.shared.dataTask(with: request, - completionHandler: { data, _, _ in - if let data = data { - if let downloadedImage = UIImage(data: data) { - image = downloadedImage - } else { - popupMessage = ShowFileDialog.imageFormatInvalid.rawValue.localized - } - } else { - popupMessage = ShowFileDialog.imageLinkInvalid.rawValue.localized - } - - semaphore.signal() - }).resume() - - _ = semaphore.wait(timeout: .distantFuture) - } else { - popupMessage = ShowFileDialog.notImage.rawValue - } - - popupDialogHandler?.showFileDialog(withMessage: popupMessage, - title: attachment.getFileName(), - image: image) - } - - @objc - private func scrollToBottom() { - if messages.isEmpty { - return - } - - let bottomMessageIndex = IndexPath(row: (tableView?.numberOfRows(inSection: 0))! - 1, - section: 0) - tableView?.scrollToRow(at: bottomMessageIndex, - at: .bottom, - animated: true) - } - -} - -// MARK: - UIImagePickerControllerDelegate -extension ChatViewController: UIImagePickerControllerDelegate { - - // MARK: - Methods - - func imagePickerController(_ picker: UIImagePickerController, - didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { - if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { - if let imageURL = info[UIImagePickerController.InfoKey.referenceURL] as? URL { - let imageData: Data - let imageExtension = imageURL.pathExtension.lowercased() - if imageExtension == "jpg" || imageExtension == "jpeg" { - imageData = image.jpegData(compressionQuality: 1.0)! - } else { - imageData = image.pngData()! - } - let imageName = imageURL.lastPathComponent - let mimeType = MimeType(url: imageURL as URL) - - webimService!.send(file: imageData, - fileName: imageName, - mimeType: mimeType.value, - completionHandler: self) - } - } - - dismiss(animated: true, - completion: nil) - } - - func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { - dismiss(animated: true, - completion: nil) - } - -} - -// MARK: - UINavigationControllerDelegate -extension ChatViewController: UINavigationControllerDelegate { - // For image picker. -} - -// MARK: - WEBIM: MessageListener -extension ChatViewController: MessageListener { - - // MARK: - Methods - - func added(message newMessage: Message, - after previousMessage: Message?) { - var inserted = false - - if let previousMessage = previousMessage { - for (index, message) in messages.enumerated() { - if previousMessage.isEqual(to: message) { - messages.insert(newMessage, - at: (index == 0) ? index : (index - 1)) - inserted = true - - break - } - } - } - - if !inserted { - messages.append(newMessage) - } - - DispatchQueue.main.async() { - self.tableView?.reloadData() - self.scrollToBottom() - } - } - - func removed(message: Message) { - var toUpdate = false - - for (messageIndex, iteratedMessage) in messages.enumerated() { - if iteratedMessage.getID() == message.getID() { - messages.remove(at: messageIndex) - toUpdate = true - - break - } - } - - if toUpdate { - DispatchQueue.main.async() { - self.tableView?.reloadData() - self.scrollToBottom() - } - } - } - - func removedAllMessages() { - messages.removeAll() - - DispatchQueue.main.async() { - self.tableView?.reloadData() - } - } - - func changed(message oldVersion: Message, - to newVersion: Message) { - var toUpdate = false - - for (messageIndex, iteratedMessage) in messages.enumerated() { - if iteratedMessage.getID() == oldVersion.getID() { - messages[messageIndex] = newVersion - toUpdate = true - - break - } - } - - if toUpdate { - DispatchQueue.main.async() { - self.tableView?.reloadData() - self.scrollToBottom() - } - } - } - -} - -// MARK: - SendFileCompletionHandler -extension ChatViewController: SendFileCompletionHandler { - - // MARK: - Methods - - func onSuccess(messageID: String) { - // Ignored. - } - - func onFailure(messageID: String, - error: SendFileError) { - DispatchQueue.main.sync { - var message: String? - switch error { - case .FILE_SIZE_EXCEEDED: - message = SendFileErrorMessage.fileSizeExceeded.rawValue.localized - - break - case .FILE_TYPE_NOT_ALLOWED: - message = SendFileErrorMessage.fileTypeNotAllowed.rawValue.localized - - break - case .UNKNOWN: - message = SendFileErrorMessage.unknownError.rawValue.localized - - break - case .UPLOADED_FILE_NOT_FOUND: - message = SendFileErrorMessage.fileNotFound.rawValue.localized - - break - } - - popupDialogHandler?.showFileSendFailureDialog(withMessage: message!) { [weak self] in - guard let `self` = self else { - return - } - - for (index, message) in self.messages.enumerated() { - if message.getID() == messageID { - self.messages.remove(at: index) - DispatchQueue.main.async() { - self.tableView?.reloadData() - } - - return - } - } - } - } - } - -} - -// MARK: - RateOperatorCompletionHandler -extension ChatViewController: RateOperatorCompletionHandler { - - // MARK: - Methods - - func onSuccess() { - // Ignored. - } - - func onFailure(error: RateOperatorError) { - popupDialogHandler?.showRatingFailureDialog() - } - -} - -// MARK: - FatalErrorHandler -extension ChatViewController: FatalErrorHandlerDelegate { - - // MARK: - Methods - func showErrorDialog(withMessage message: String) { - popupDialogHandler?.showCreatingSessionFailureDialog(withMessage: message) - } - -} - -// MARK: - DepartmentListHandlerDelegate -extension ChatViewController: DepartmentListHandlerDelegate { - - // MARK: - Methods - func show(departmentList: [Department], - action: @escaping (String) -> ()) { - popupDialogHandler?.showDepartmentListDialog(withDepartmentList: departmentList, - action: action) - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-1.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-1.png deleted file mode 100755 index 2c3f9c1..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-1.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-2.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-2.png deleted file mode 100755 index 86b33ad..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-2.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-3.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-3.png deleted file mode 100755 index 86b33ad..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-3.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-4.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-4.png deleted file mode 100755 index d401162..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-4.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-5.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-5.png deleted file mode 100755 index 0e15e06..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-5.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-6.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-6.png deleted file mode 100755 index cada44e..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-6.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-7.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-7.png deleted file mode 100755 index 28b7b96..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-7.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-8.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-8.png deleted file mode 100755 index ac76fd9..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon-8.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon.png deleted file mode 100755 index 6dec760..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/AppIcon.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100755 index 5cd7cef..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "AppIcon-8.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "AppIcon-7.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "AppIcon-6.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "AppIcon-4.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "AppIcon-5.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "AppIcon-3.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "AppIcon-2.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "AppIcon-1.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-20.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-41.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-29.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-58.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-40.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-80.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-76.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-152.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-167.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "AppIcon.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-152.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-152.png deleted file mode 100755 index 253af33..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-152.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-167.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-167.png deleted file mode 100755 index 5dda991..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-167.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-20.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-20.png deleted file mode 100755 index ef7135d..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-20.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-29.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-29.png deleted file mode 100755 index 34e2f02..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-29.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-40.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-40.png deleted file mode 100755 index 7697ffe..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-40.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-41.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-41.png deleted file mode 100755 index 7697ffe..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-41.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-58.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-58.png deleted file mode 100755 index f785523..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-58.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-76.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-76.png deleted file mode 100755 index f748437..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-76.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-80.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-80.png deleted file mode 100755 index deccf5c..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/AppIcon.appiconset/Icon-80.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Check.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Check.imageset/Contents.json deleted file mode 100755 index 10fc5ba..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Check.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "check_Icon-32.png" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Check.imageset/check_Icon-32.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Check.imageset/check_Icon-32.png deleted file mode 100755 index 917ce63..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Check.imageset/check_Icon-32.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Contents.json deleted file mode 100755 index da4a164..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/DefaultAvatar.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/DefaultAvatar.imageset/Contents.json deleted file mode 100755 index 11e336d..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/DefaultAvatar.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "DefaultAvatar.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/DefaultAvatar.imageset/DefaultAvatar.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/DefaultAvatar.imageset/DefaultAvatar.pdf deleted file mode 100755 index fe14231..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/DefaultAvatar.imageset/DefaultAvatar.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/HardcodedVisitorAvatar.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/HardcodedVisitorAvatar.imageset/Contents.json deleted file mode 100755 index 1b483fd..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/HardcodedVisitorAvatar.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "VisitorAvatar.png" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/HardcodedVisitorAvatar.imageset/VisitorAvatar.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/HardcodedVisitorAvatar.imageset/VisitorAvatar.png deleted file mode 100755 index 8d35f35..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/HardcodedVisitorAvatar.imageset/VisitorAvatar.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back.imageset/Contents.json deleted file mode 100755 index f24c5fd..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "back_Icon-32.png" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back.imageset/back_Icon-32.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back.imageset/back_Icon-32.png deleted file mode 100755 index 7ffe69b..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back.imageset/back_Icon-32.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back_dark.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back_dark.imageset/Contents.json deleted file mode 100755 index f24c5fd..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back_dark.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "back_Icon-32.png" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back_dark.imageset/back_Icon-32.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back_dark.imageset/back_Icon-32.png deleted file mode 100755 index 7ffe69b..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Back_dark.imageset/back_Icon-32.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Contents.json deleted file mode 100755 index da4a164..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Back/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip.imageset/ClipIcon.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip.imageset/ClipIcon.pdf deleted file mode 100755 index 6fafcae..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip.imageset/ClipIcon.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip.imageset/Contents.json deleted file mode 100755 index e6d42a7..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "ClipIcon.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip_dark.imageset/Clip_dark.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip_dark.imageset/Clip_dark.pdf deleted file mode 100755 index b742ded..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip_dark.imageset/Clip_dark.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip_dark.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip_dark.imageset/Contents.json deleted file mode 100755 index f7203dd..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Clip_dark.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "Clip_dark.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Contents.json deleted file mode 100755 index da4a164..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Clip/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close.imageset/Contents.json deleted file mode 100755 index a05197e..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "close_Icon-32.png" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close.imageset/close_Icon-32.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close.imageset/close_Icon-32.png deleted file mode 100755 index a4f95b2..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close.imageset/close_Icon-32.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close_dark.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close_dark.imageset/Contents.json deleted file mode 100755 index a05197e..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close_dark.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "close_Icon-32.png" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close_dark.imageset/close_Icon-32.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close_dark.imageset/close_Icon-32.png deleted file mode 100755 index a4f95b2..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Close_dark.imageset/close_Icon-32.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Contents.json deleted file mode 100755 index da4a164..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Close/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Contents.json deleted file mode 100755 index da4a164..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Empty.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Empty.imageset/Contents.json deleted file mode 100755 index 00234c1..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Empty.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "Empty.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Empty.imageset/Empty.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Empty.imageset/Empty.pdf deleted file mode 100755 index f171604..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/Empty.imageset/Empty.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/Contents.json deleted file mode 100755 index da4a164..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage.imageset/Contents.json deleted file mode 100755 index ac44b5a..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "SendMessageIcon.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage.imageset/SendMessageIcon.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage.imageset/SendMessageIcon.pdf deleted file mode 100755 index 5b8b0bb..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage.imageset/SendMessageIcon.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage_dark.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage_dark.imageset/Contents.json deleted file mode 100755 index 68ae080..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage_dark.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "SendMessage_dark.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage_dark.imageset/SendMessage_dark.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage_dark.imageset/SendMessage_dark.pdf deleted file mode 100755 index 4e8ba63..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Icons/SendMessage/SendMessage_dark.imageset/SendMessage_dark.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/Contents.json deleted file mode 100755 index da4a164..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/LogoWebim.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/LogoWebim.imageset/Contents.json deleted file mode 100755 index f4d61f5..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/LogoWebim.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LogoWebim.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/LogoWebim.imageset/LogoWebim.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/LogoWebim.imageset/LogoWebim.pdf deleted file mode 100755 index 86f27e2..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/LogoWebim.imageset/LogoWebim.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/Contents.json deleted file mode 100755 index da4a164..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar.imageset/Contents.json deleted file mode 100755 index f562f7e..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LogoWebimNavigationBar.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar.imageset/LogoWebimNavigationBar.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar.imageset/LogoWebimNavigationBar.pdf deleted file mode 100755 index 0fc82eb..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar.imageset/LogoWebimNavigationBar.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar_dark.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar_dark.imageset/Contents.json deleted file mode 100755 index 69f2fc6..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar_dark.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "logo_white.png" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar_dark.imageset/logo_white.png b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar_dark.imageset/logo_white.png deleted file mode 100755 index 52b90c0..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/Logo/NavigationBar/LogoWebimNavigationBar_dark.imageset/logo_white.png and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/Contents.json deleted file mode 100755 index da4a164..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom.imageset/Contents.json deleted file mode 100755 index 694526f..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "ScrollToBottom.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom.imageset/ScrollToBottom.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom.imageset/ScrollToBottom.pdf deleted file mode 100755 index 357d8d1..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom.imageset/ScrollToBottom.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom_dark.imageset/Contents.json b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom_dark.imageset/Contents.json deleted file mode 100755 index 8fc17ea..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom_dark.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "ScrollToBottom_dark.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom_dark.imageset/ScrollToBottom_dark.pdf b/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom_dark.imageset/ScrollToBottom_dark.pdf deleted file mode 100755 index d13c4f8..0000000 Binary files a/ios/libs/Webim/Example/WebimClientLibrary/Images.xcassets/ScrollToBottom/ScrollToBottom_dark.imageset/ScrollToBottom_dark.pdf and /dev/null differ diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Info.plist b/ios/libs/Webim/Example/WebimClientLibrary/Info.plist deleted file mode 100755 index 66be41d..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Info.plist +++ /dev/null @@ -1,70 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleDisplayName - Webim - чат с компанией - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 3.24.7 - CFBundleSignature - ???? - CFBundleVersion - 3.24.7.1 - Fabric - - APIKey - 80055b71f053ff36cce8743fbac5eecae7df7f28 - Kits - - - KitInfo - - KitName - Crashlytics - - - - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIRequiresFullScreen - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeRight - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - UIInterfaceOrientationPortraitUpsideDown - - UIViewControllerBasedStatusBarAppearance - - NSPhotoLibraryUsageDescription - This app requires access to the photo library. - - diff --git a/ios/libs/Webim/Example/WebimClientLibrary/MessageTableViewCell.swift b/ios/libs/Webim/Example/WebimClientLibrary/MessageTableViewCell.swift deleted file mode 100755 index 4d88cd8..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/MessageTableViewCell.swift +++ /dev/null @@ -1,315 +0,0 @@ -// -// MessageTableViewCell.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 06.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import SnapKit -import UIKit -import WebimClientLibrary - -// MARK: - -final class MessageTableViewCell: UITableViewCell { - - // MARK: - Constants - private enum Size: CGFloat { - case avatar = 40.0 - } - - // MARK: - Properties - private static var imageCache = [URL: UIImage]() - private let dateFormatter: DateFormatter = { - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "dd MMM yyyy hh:mm:ss" - - return dateFormatter - }() - - // MARK: Subviews - lazy var avatarImageView = UIImageView() - lazy var bodyLabel: UILabel = { - let label = UILabel() - label.font = UIFont.preferredFont(forTextStyle: .body) - label.numberOfLines = 0 - - return label - }() - lazy var nameLabel: UILabel = { - let label = UILabel() - label.font = UIFont.preferredFont(forTextStyle: .subheadline) - - return label - }() - lazy var timeLabel: UILabel = { - let label = UILabel() - label.font = UIFont.preferredFont(forTextStyle: .footnote) - label.textColor = .lightGray - label.textAlignment = .right - - return label - }() - - - // MARK: - Initialization - - override init(style: UITableViewCell.CellStyle, - reuseIdentifier: String?) { - super.init(style: style, - reuseIdentifier: reuseIdentifier) - - configureSubviews() - } - - required init?(coder aDecoder: NSCoder) { - // UITableViewCell requirement. - - super.init(coder: aDecoder) - } - - - // MARK: - Methods - - override func prepareForReuse() { - super.prepareForReuse() - - avatarImageView.image = nil - } - - func setContent(withMessage message: Message) { - switch message.getType() { - case .ACTION_REQUEST: - layoutActionRequest(message: message) - - break - case .CONTACTS_REQUEST: - layoutOperator(message: message) - - break - case .FILE_FROM_OPERATOR: - layoutFileFromOperator(message: message) - - break - case .FILE_FROM_VISITOR: - layoutFileFromVisitor(message: message) - - break - case .INFO: - layoutInfo(message: message) - - break - case .OPERATOR: - layoutOperator(message: message) - - break - case .OPERATOR_BUSY: - layoutOperatorBusy(message: message) - - break - case .VISITOR: - layoutVisitor(message: message) - - break - } - - backgroundColor = backgroundTableViewColor.color() - } - - // MARK: Private methods - - private func configureSubviews() { - self.addSubview(avatarImageView) - self.addSubview(nameLabel) - self.addSubview(bodyLabel) - self.addSubview(timeLabel) - - avatarImageView.snp.makeConstraints { [weak self] constraintsMaker in - guard let `self` = self else { - return - } - - constraintsMaker.height.equalTo(Size.avatar.rawValue) - constraintsMaker.width.equalTo(avatarImageView.snp.height) - constraintsMaker.top.equalTo(self).offset(10) - constraintsMaker.left.equalTo(self).offset(20) - } - - nameLabel.snp.makeConstraints { [weak self] constraintsMaker in - guard let `self` = self else { - return - } - - constraintsMaker.top.equalTo(self).offset(10) - constraintsMaker.left.equalTo(avatarImageView.snp.right).offset(10) - constraintsMaker.right.equalTo(self).offset(-20) - } - - bodyLabel.snp.makeConstraints { [weak self] constraintsMaker in - guard let `self` = self else { - return - } - - constraintsMaker.top.equalTo(nameLabel.snp.bottom).offset(1) - constraintsMaker.left.equalTo(avatarImageView.snp.right).offset(10) - constraintsMaker.right.equalTo(self).offset(-20) - } - - timeLabel.snp.makeConstraints { [weak self] constraintsMaker in - guard let `self` = self else { - return - } - - constraintsMaker.top.equalTo(bodyLabel.snp.bottom).offset(1) - constraintsMaker.left.equalTo(avatarImageView.snp.right).offset(10) - constraintsMaker.right.equalTo(self).offset(-20) - constraintsMaker.bottom.equalTo(self).offset(-10) - } - } - - private func layoutActionRequest(message: Message) { - // Action request messages are kind of customization. There's no such messages at demo account. - } - - private func layoutFileFromOperator(message: Message) { - if let fileName = message.getAttachment()?.getFileName() { - bodyLabel.text = fileName - } else { - bodyLabel.text = FileMessage.fileUnavailable.rawValue.localized - } - bodyLabel.textColor = textTintColor.color() - bodyLabel.isUserInteractionEnabled = true - selectionStyle = .none - - nameLabel.text = message.getSenderName() - - timeLabel.text = dateFormatter.string(from: message.getTime()) - - getOperatorAvatar(forImageView: avatarImageView, - message: message) - avatarImageView.accessibilityLabel = Avatar.accessibilityLabel.rawValue.localized - avatarImageView.accessibilityHint = Avatar.accessibilityHintOperator.rawValue.localized - } - - private func layoutFileFromVisitor(message: Message) { - if let fileName = message.getAttachment()?.getFileName() { - bodyLabel.text = fileName - } else { - bodyLabel.text = FileMessage.fileUnavailable.rawValue.localized - } - bodyLabel.textColor = textTintColor.color() - bodyLabel.isUserInteractionEnabled = true - selectionStyle = .none - - nameLabel.text = message.getSenderName() - - timeLabel.text = dateFormatter.string(from: message.getTime()) - - avatarImageView.image = #imageLiteral(resourceName: "HardcodedVisitorAvatar") - avatarImageView.isHidden = false - avatarImageView.isUserInteractionEnabled = false - avatarImageView.accessibilityLabel = Avatar.accessibilityLabel.rawValue.localized - } - - private func layoutInfo(message: Message) { - bodyLabel.text = message.getText().decodePercentEscapedLinksIfPresent() - bodyLabel.textColor = textSecondaryColor.color() - bodyLabel.isUserInteractionEnabled = false - selectionStyle = .none - - nameLabel.text = "" - - timeLabel.text = "" - - avatarImageView.isHidden = true - } - - private func layoutOperator(message: Message) { - bodyLabel.text = message.getText().decodePercentEscapedLinksIfPresent() - bodyLabel.textColor = textMainColor.color() - bodyLabel.isUserInteractionEnabled = false - selectionStyle = .none - - nameLabel.text = message.getSenderName() - nameLabel.textColor = textNameOperatorColor.color() - - timeLabel.text = dateFormatter.string(from: message.getTime()) - - getOperatorAvatar(forImageView: avatarImageView, - message: message) - avatarImageView.accessibilityLabel = Avatar.accessibilityLabel.rawValue.localized - avatarImageView.accessibilityHint = Avatar.accessibilityHintOperator.rawValue.localized - } - - private func layoutOperatorBusy(message: Message) { - bodyLabel.text = message.getText().decodePercentEscapedLinksIfPresent() - bodyLabel.textColor = textSecondaryColor.color() - bodyLabel.isUserInteractionEnabled = false - selectionStyle = .none - - nameLabel.text = "" - - timeLabel.text = "" - - avatarImageView.isHidden = true - } - - private func layoutVisitor(message: Message) { - bodyLabel.text = message.getText().decodePercentEscapedLinksIfPresent() - bodyLabel.textColor = textMainColor.color() - bodyLabel.isUserInteractionEnabled = false - selectionStyle = .none - - nameLabel.text = message.getSenderName() - nameLabel.textColor = textNameVisitorColor.color() - - timeLabel.text = dateFormatter.string(from: message.getTime()) - - avatarImageView.image = #imageLiteral(resourceName: "HardcodedVisitorAvatar") - avatarImageView.isHidden = false - avatarImageView.isUserInteractionEnabled = false - avatarImageView.accessibilityLabel = Avatar.accessibilityLabel.rawValue.localized - } - - private func getOperatorAvatar(forImageView imageView: UIImageView, - message: Message) { - // FIXME: Could load wrong image to cell due to cell reuse mechanism. - - imageView.image = #imageLiteral(resourceName: "DefaultAvatar") - imageView.isHidden = false - imageView.isUserInteractionEnabled = true - - guard let avatarURL = message.getSenderAvatarFullURL() else { - return - } - - if let image = MessageTableViewCell.imageCache[avatarURL] { - imageView.image = image - } else { - imageView.loadImageAsynchronouslyFrom(url: avatarURL, - rounded: true) { image in - MessageTableViewCell.imageCache[avatarURL] = image - } - } - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Models/ColorScheme.swift b/ios/libs/Webim/Example/WebimClientLibrary/Models/ColorScheme.swift deleted file mode 100755 index ef54808..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Models/ColorScheme.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// ColorScheme.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 07.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -final class ColorScheme { - - // MARK: - Properties - static let shared = ColorScheme() - var schemeType: SchemeType - - // MARK: - Initialization - private init() { - if let settings = UserDefaults.standard.object(forKey: USER_DEFAULTS_NAME) as? [String : String] { - if let rawValue = settings[UserDefaultsKey.colorScheme.rawValue], - let option = SchemeType(rawValue: rawValue) { - self.schemeType = option - } else { - self.schemeType = .light - } - } else { - self.schemeType = .light - } - } - - // MARK: - Methods - - func navigationItemImage() -> UIImage { - switch schemeType { - case .light: - return #imageLiteral(resourceName: "LogoWebimNavigationBar") - case .dark: - return #imageLiteral(resourceName: "LogoWebimNavigationBar_dark") - } - } - - func backButtonImage() -> UIImage { - switch schemeType { - case .light: - return #imageLiteral(resourceName: "Back") - case .dark: - return #imageLiteral(resourceName: "Back_dark") - } - } - - func closeChatButtonImage() -> UIImage { - switch schemeType { - case .light: - return #imageLiteral(resourceName: "Close") - case .dark: - return #imageLiteral(resourceName: "Close_dark") - } - } - - func scrollToBottomButtonImage() -> UIImage { - switch schemeType { - case .light: - return #imageLiteral(resourceName: "ScrollToBottom") - case .dark: - return #imageLiteral(resourceName: "ScrollToBottom_dark") - } - } - - func keyboardAppearance() -> UIKeyboardAppearance { - switch schemeType { - case .light: - return .light - case .dark: - return .dark - } - } - - // MARK: - - enum SchemeType: String { - case light = "classic" - case dark = "dark" - } - -} - -// MARK: - -struct SchemeColor { - - // MARK: - Properties - private let classic: UIColor - private let dark: UIColor - - // MARK: - Initialization - init(classic: UIColor, - dark: UIColor) { - self.classic = classic - self.dark = dark - } - - // MARK: - Methods - - func color() -> UIColor { - return colorWith(scheme: ColorScheme.shared.schemeType) - } - - // MARK: Private methods - private func colorWith(scheme: ColorScheme.SchemeType) -> UIColor { - switch scheme { - case .light: - return classic - case .dark: - return dark - } - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Models/Settings.swift b/ios/libs/Webim/Example/WebimClientLibrary/Models/Settings.swift deleted file mode 100755 index 4886aa0..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Models/Settings.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// Settings.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 28.11.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -// MARK: - Global constants -let USER_DEFAULTS_NAME = "settings" -enum UserDefaultsKey: String { - case accountName = "account_name" - case colorScheme = "color_scheme" - case location = "location" - case pageTitle = "page_title" -} - -// MARK: - -final class Settings { - - // MARK: - Constants - enum DefaultSettings: String { - case accountName = "demo" - case location = "mobile" - case pageTitle = "iOS demo app" - } - - // MARK: - Properties - static let shared = Settings() - var accountName: String - var location: String - var pageTitle: String - - // MARK: - Initialization - private init() { - if let settings = UserDefaults.standard.object(forKey: USER_DEFAULTS_NAME) as? [String : String] { - self.accountName = settings[UserDefaultsKey.accountName.rawValue] ?? DefaultSettings.accountName.rawValue - self.location = settings[UserDefaultsKey.location.rawValue] ?? DefaultSettings.location.rawValue - self.pageTitle = settings[UserDefaultsKey.pageTitle.rawValue] ?? DefaultSettings.pageTitle.rawValue - } else { - self.accountName = DefaultSettings.accountName.rawValue - self.location = DefaultSettings.location.rawValue - self.pageTitle = DefaultSettings.pageTitle.rawValue - } - } - - // MARK: - Methods - func save() { - let settings = [UserDefaultsKey.accountName.rawValue : accountName, - UserDefaultsKey.location.rawValue : location, - UserDefaultsKey.pageTitle.rawValue : pageTitle, - UserDefaultsKey.colorScheme.rawValue : ColorScheme.shared.schemeType.rawValue] - UserDefaults.standard.set(settings, - forKey: USER_DEFAULTS_NAME) - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/RatingViewController.swift b/ios/libs/Webim/Example/WebimClientLibrary/RatingViewController.swift deleted file mode 100755 index b6e0d1b..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/RatingViewController.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// RatingViewController.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 15.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Cosmos -import UIKit - -final class RatingViewController: UIViewController { - - // MARK: - Properties - // MARK: Outlets - @IBOutlet weak var backgroundView: UIView! - @IBOutlet weak var ratingView: CosmosView! - @IBOutlet weak var textLabel: UILabel! - - // MARK: - Methods - override func viewDidLoad() { - super.viewDidLoad() - - textLabel.textColor = textMainColor.color() - backgroundView.backgroundColor = backgroundSecondaryColor.color() - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/SettingsTableViewController.swift b/ios/libs/Webim/Example/WebimClientLibrary/SettingsTableViewController.swift deleted file mode 100755 index 5aeeec4..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/SettingsTableViewController.swift +++ /dev/null @@ -1,199 +0,0 @@ -// -// SettingsTableViewController.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 07.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -final class SettingsTableViewController: UITableViewController { - - // MARK: - Properties - - var delegate: SettingsViewController? - - // MARK: Outlets - - // Text fields - @IBOutlet weak var accountNameTextField: UITextField! - @IBOutlet weak var locationTextField: UITextField! - @IBOutlet weak var pageTitleTextField: UITextField! - - // Text fields error hints - @IBOutlet weak var accountNameHintLabel: UILabel! - @IBOutlet weak var locationHintLabel: UILabel! - - // Text - @IBOutlet var textFieldLabels: [UILabel]! - - // Color scheme - @IBOutlet weak var classicCheckboxImageView: UIImageView! // Row 0 - @IBOutlet weak var darkCheckboxImageView: UIImageView! // Row 2 - @IBOutlet var colorSchemeNames: [UILabel]! - - // Table cells - @IBOutlet weak var accountSettingsCell: UITableViewCell! - @IBOutlet var colorThemeCells: [UITableViewCell]! - @IBOutlet weak var delimiter: UIView! - - // MARK: - Methods - - override func viewDidLoad() { - super.viewDidLoad() - - accountNameTextField.text = Settings.shared.accountName - locationTextField.text = Settings.shared.location - pageTitleTextField.text = Settings.shared.pageTitle - - setupColorSchemeCheckboxes() - setupColorScheme() - - for hintLabel in [accountNameHintLabel, locationHintLabel] { - hintLabel!.alpha = 0.0 - hintLabel!.textColor = textTextFieldErrorColor.color() - } - for textField in [accountNameTextField, - locationTextField] { - textField!.addTarget(self, - action: #selector(textDidChange), - for: .editingChanged) - textField!.layer.cornerRadius = 5.0 - textField!.layer.borderColor = textTextFieldErrorColor.color().cgColor - textField!.delegate = self - } - pageTitleTextField.delegate = self - } - - // MARK: UITableViewDelegate protocol methods - - override func tableView(_ tableView: UITableView, - willDisplayHeaderView view: UIView, - forSection section: Int) { - view.tintColor = backgroundMainColor.color() - } - - override func tableView(_ tableView: UITableView, - didSelectRowAt indexPath: IndexPath) { - guard indexPath.section == 1 else { // Color theme section - return - } - - var selectedColorScheme: ColorScheme.SchemeType? - switch indexPath.row { - case 0: - selectedColorScheme = .light - - break - case 2: - selectedColorScheme = .dark - - break - default: - return - } - - if ColorScheme.shared.schemeType != selectedColorScheme { - ColorScheme.shared.schemeType = selectedColorScheme! - UIView.animate(withDuration: 0.2) { - self.setupColorSchemeCheckboxes() - self.setupColorScheme() - } - } - } - - // MARK: Private mwethods - - private func setupColorSchemeCheckboxes() { - switch ColorScheme.shared.schemeType { - case .light: - classicCheckboxImageView.alpha = 1.0 - darkCheckboxImageView.alpha = 0.0 - case .dark: - classicCheckboxImageView.alpha = 0.0 - darkCheckboxImageView.alpha = 1.0 - } - } - - private func setupColorScheme() { - delegate?.setupColorScheme() - - tableView.backgroundColor = backgroundMainColor.color() - accountSettingsCell.backgroundColor = backgroundMainColor.color() - for cell in colorThemeCells { - cell.backgroundColor = backgroundCellLightColor.color() - } - - for label in textFieldLabels { - label.textColor = textMainColor.color() - } - for label in colorSchemeNames { - label.textColor = textCellLightColor.color() - } - - for textField in [accountNameTextField, - locationTextField, - pageTitleTextField] { - textField!.backgroundColor = backgroundTextFieldColor.color() - textField!.textColor = textTextFieldColor.color() - textField!.tintColor = textTextFieldColor.color() - textField!.keyboardAppearance = ColorScheme.shared.keyboardAppearance() - } - - delimiter.backgroundColor = delimiterColor.color() - - let appDelegate = UIApplication.shared.delegate as! AppDelegate - appDelegate.setStatusBarColor() - } - - @objc - private func textDidChange(textField: UITextField) { - var hintLabel: UILabel? - if textField == accountNameTextField { - hintLabel = accountNameHintLabel - } else { - hintLabel = locationHintLabel - } - - UIView.animate(withDuration: 0.2) { - if (textField.text == nil) - || textField.text!.isEmpty { - textField.layer.borderWidth = 1.0 - hintLabel!.alpha = 1.0 - } else { - textField.layer.borderWidth = 0.0 - hintLabel!.alpha = 0.0 - } - } - } - -} - -extension SettingsTableViewController: UITextFieldDelegate { - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - textField.resignFirstResponder() - - return true - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/SettingsViewController.swift b/ios/libs/Webim/Example/WebimClientLibrary/SettingsViewController.swift deleted file mode 100755 index 129cd41..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/SettingsViewController.swift +++ /dev/null @@ -1,170 +0,0 @@ -// -// SettingsViewController.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 28.11.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import PopupDialog -import UIKit - -final class SettingsViewController: UIViewController { - - // MARK: - Properties - private var popupDialogHandler: PopupDialogHandler? - private var settingsTableViewController: SettingsTableViewController? - - // MARK: Outlets - @IBOutlet weak var saveButton: UIButton! - - - // MARK: - Methods - - override func viewDidLoad() { - super.viewDidLoad() - - popupDialogHandler = PopupDialogHandler(delegate: self) - - setupNavigationItem() - setupSaveButton() - - hideKeyboardOnTap() - } - - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - setupColorScheme() - } - - func setupColorScheme() { - view.backgroundColor = backgroundMainColor.color() - - navigationController?.navigationBar.barTintColor = backgroundSecondaryColor.color() - setupVisibleNavigationItemsElements() - - saveButton.backgroundColor = buttonColor.color() - saveButton.setTitleColor(textButtonColor.color(), - for: .normal) - } - - // MARK: Navigation - - override func prepare(for segue: UIStoryboardSegue, - sender: Any?) { - if let viewController = segue.destination as? SettingsTableViewController, - segue.identifier == "EmbedSettingsTable" { - settingsTableViewController = viewController - - viewController.delegate = self - } - } - - override func shouldPerformSegue(withIdentifier identifier: String, - sender: Any?) -> Bool { - if identifier != "EmbedSettingsTable", - !settingsValidated() { - return false - } - - return true - } - - // MARK: Private methods - - private func setupNavigationItem() { - setupVisibleNavigationItemsElements() - - // Need for title view to be centered. - let emptyBarButton = UIButton(type: .custom) - emptyBarButton.setImage(#imageLiteral(resourceName: "Empty"), - for: .normal) - emptyBarButton.isUserInteractionEnabled = false - navigationItem.rightBarButtonItem = UIBarButtonItem(customView: emptyBarButton) - } - - private func setupVisibleNavigationItemsElements() { - let backButton = UIButton(type: .custom) - backButton.setImage(ColorScheme.shared.backButtonImage(), - for: .normal) - backButton.imageView?.contentMode = .scaleAspectFit - backButton.accessibilityLabel = BackButton.accessibilityLabel.rawValue.localized - backButton.accessibilityHint = BackButton.accessibilityHint.rawValue.localized - backButton.addTarget(self, - action: #selector(onBackButtonClick(sender:)), - for: .touchUpInside) - let leftBarButtonItem = UIBarButtonItem(customView: backButton) - self.navigationItem.leftBarButtonItem = leftBarButtonItem - - let navigationItemImageView = UIImageView(image: ColorScheme.shared.navigationItemImage()) - navigationItemImageView.contentMode = .scaleAspectFit - navigationItem.titleView = navigationItemImageView - } - - @objc - private func onBackButtonClick(sender: UIButton) { - if settingsValidated() { - navigationController?.popViewController(animated: true) - } - } - - private func settingsValidated() -> Bool { - guard let accountName = settingsTableViewController?.accountNameTextField.text, - !accountName.isEmpty else { - popupDialogHandler?.showSettingsAlertDialog(withMessage: SettingsErrorDialog.wrongAccountName.rawValue.localized) - - return false - } - guard let location = settingsTableViewController?.locationTextField.text, - !location.isEmpty else { - popupDialogHandler?.showSettingsAlertDialog(withMessage: SettingsErrorDialog.wrongLocation.rawValue.localized) - - return false - } - - set(accountName: accountName, - location: location, - pageTitle: settingsTableViewController?.pageTitleTextField.text) - - return true - } - - private func set(accountName: String, - location: String, - pageTitle: String?) { - Settings.shared.accountName = accountName - Settings.shared.location = location - if let pageTitle = pageTitle, - !pageTitle.isEmpty { - Settings.shared.pageTitle = pageTitle - } - - Settings.shared.save() - } - - private func setupSaveButton() { - saveButton.layer.borderWidth = Button.borderWidth.rawValue - saveButton.layer.borderColor = buttonBorderColor.color().cgColor - saveButton.layer.cornerRadius = Button.cornerRadius.rawValue - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/StartViewController.swift b/ios/libs/Webim/Example/WebimClientLibrary/StartViewController.swift deleted file mode 100755 index e0b97aa..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/StartViewController.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// StartViewController.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 01.00.2017. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -final class StartViewController: UIViewController { - - // MARK: - Properties - // MARK: Outlets - @IBOutlet weak var startChatButton: UIButton! - @IBOutlet weak var settingsButton: UIButton! - @IBOutlet weak var welcomeTextView: UITextView! - - // MARK: - Methods - - override func viewDidLoad() { - super.viewDidLoad() - - setupStartChatButton() - setupSettingsButton() - - // Xcode does not localize UITextView text automatically. - welcomeTextView.text = NSLocalizedString(StartView.welcomeText.rawValue, - tableName: "Main", - bundle: .main, - value: "", - comment: "") - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - setupColorScheme() - setupNavigationItem() - } - - @IBAction func unwindFromSettings(_: UIStoryboardSegue) { - // No need to do anything. - } - - // MARK: Private methods - - private func setupStartChatButton() { - startChatButton.layer.cornerRadius = Button.cornerRadius.rawValue - startChatButton.layer.borderWidth = Button.borderWidth.rawValue - startChatButton.layer.borderColor = buttonBorderColor.color().cgColor - } - - private func setupSettingsButton() { - settingsButton.layer.cornerRadius = TransparentButton.cornerRadius.rawValue - settingsButton.layer.borderWidth = TransparentButton.borderWidth.rawValue - } - - private func setupColorScheme() { - view.backgroundColor = backgroundMainColor.color() - navigationController?.navigationBar.barTintColor = backgroundSecondaryColor.color() - - welcomeTextView.backgroundColor = backgroundMainColor.color() - welcomeTextView.textColor = textMainColor.color() - welcomeTextView.tintColor = textTintColor.color() - - startChatButton.backgroundColor = buttonColor.color() - startChatButton.setTitleColor(textButtonColor.color(), - for: .normal) - - settingsButton.setTitleColor(textButtonTransparentColor.color(), - for: .normal) - settingsButton.setTitleColor(textButtonTransparentHighlightedColor.color(), - for: .highlighted) - settingsButton.layer.borderColor = textButtonTransparentColor.color().cgColor - } - - private func setupNavigationItem() { - let navigationItemImageView = UIImageView(image: ColorScheme.shared.navigationItemImage()) - navigationItemImageView.contentMode = .scaleAspectFit - navigationItem.titleView = navigationItemImageView - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/String.swift b/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/String.swift deleted file mode 100755 index 98e3890..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/String.swift +++ /dev/null @@ -1,93 +0,0 @@ -// -// String.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 24.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -extension String { - - // MARK: - Properties - var localized: String { - return NSLocalizedString(self, - comment: "") - } - -} - -// MARK: - -extension String { - - // MARK: - Methods - public func decodePercentEscapedLinksIfPresent() -> String { - var convertedString = String() - - let checkingTypes: NSTextCheckingResult.CheckingType = [.link] - if let linksDetector = try? NSDataDetector(types: checkingTypes.rawValue) { - let linkMatches = linksDetector.matches(in: self, - range: NSMakeRange(0, - self.count)) - if !linkMatches.isEmpty { - var position = 0 - - for linkMatch in linkMatches { - let linkMatchRange = linkMatch.range - if let url = linkMatch.url { - let beforeLinkStringSliceRangeStart = self.index(self.startIndex, - offsetBy: position) - let beforeLinkStringSliceRangeEnd = self.index(self.startIndex, - offsetBy: linkMatchRange.location) - let beforeLinkStringSlice = String(self[beforeLinkStringSliceRangeStart ..< beforeLinkStringSliceRangeEnd]) - convertedString += beforeLinkStringSlice - - position = linkMatchRange.location + linkMatchRange.length - - let urlString = url.absoluteString.removingPercentEncoding - if urlString != nil { - convertedString += urlString! - } else { - let linkStringSliceRangeStart = self.index(self.startIndex, - offsetBy: linkMatchRange.location) - let linkStringSliceRangeEnd = self.index(self.startIndex, - offsetBy: linkMatchRange.length) - convertedString += String(self[linkStringSliceRangeStart ..< linkStringSliceRangeEnd]) - } - } - } - - let closingStringSliceRangeStart = self.index(self.startIndex, - offsetBy: position) - let closingStringSliceRangeEnd = self.index(self.startIndex, - offsetBy: self.count) - let closingStringSlice = String(self[closingStringSliceRangeStart ..< closingStringSliceRangeEnd]) - convertedString += closingStringSlice - } else { - return self - } - } - - return convertedString - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UIImage.swift b/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UIImage.swift deleted file mode 100755 index abe2ca3..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UIImage.swift +++ /dev/null @@ -1,65 +0,0 @@ -// -// UIImage.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 14.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -extension UIImage { - - // MARK: - Methods - func roundImage() -> UIImage { - let minEdge = min(self.size.height, - self.size.width) - let size = CGSize(width: minEdge, - height: minEdge) - - UIGraphicsBeginImageContextWithOptions(size, - false, - 0.0) - let context = UIGraphicsGetCurrentContext()! - - self.draw(in: CGRect(origin: CGPoint.zero, - size: size), - blendMode: .copy, - alpha: 1.0) - - context.setBlendMode(.copy) - context.setFillColor(UIColor.clear.cgColor) - - let rectPath = UIBezierPath(rect: CGRect(origin: CGPoint.zero, - size: size)) - let circlePath = UIBezierPath(ovalIn: CGRect(origin: CGPoint.zero, - size: size)) - rectPath.append(circlePath) - rectPath.usesEvenOddFillRule = true - rectPath.fill() - - let result = UIGraphicsGetImageFromCurrentImageContext()! - UIGraphicsEndImageContext() - - return result - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UIImageView.swift b/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UIImageView.swift deleted file mode 100755 index 2bc6905..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UIImageView.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// UIImageView.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 13.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -extension UIImageView { - - // MARK: - Methods - public func loadImageAsynchronouslyFrom(url: URL, - rounded: Bool = false, - completion: ((_ image: UIImage) -> ())? = nil) { - let request = URLRequest(url: url) - - print("Requesting image: \(url.absoluteString)") - - URLSession.shared.dataTask(with: request, - completionHandler: { [weak self] (data, _, _) in - if let data = data { - DispatchQueue.main.async { - if let image = UIImage(data: data) { - var imageToSave = image - - if rounded { - imageToSave = imageToSave.roundImage() - } - - self?.image = imageToSave - - if let completion = completion { - completion(imageToSave) - } - } - } - } else { - return - } - }).resume() - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UITableView.swift b/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UITableView.swift deleted file mode 100755 index 3e3655e..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UITableView.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// UITableView.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 03.01.18. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -extension UITableView { - - // MARK: - Methods - func emptyTableView(message: String) { - let messageLabel = UILabel(frame: CGRect(x: 0.0, - y: 0.0, - width: self.bounds.size.width, - height: self.bounds.size.height)) - messageLabel.attributedText = NSAttributedString(string: message) - messageLabel.textColor = textMainColor.color() - messageLabel.numberOfLines = 0 - messageLabel.textAlignment = .center - messageLabel.sizeToFit() - - self.backgroundView = messageLabel - self.separatorStyle = .none - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UIViewController.swift b/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UIViewController.swift deleted file mode 100755 index 0096a83..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/Extensions/UIViewController.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// UIViewController.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 24.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -// MARK: - -extension UIViewController { - - // MARK: - Methods - - func hideKeyboardOnTap() { - let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, - action: #selector(dismissKeyboard)) - tap.cancelsTouchesInView = false - view.addGestureRecognizer(tap) - } - - // MARK: Private methods - @objc - private func dismissKeyboard() { - view.endEditing(true) - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/MimeType.swift b/ios/libs/Webim/Example/WebimClientLibrary/Utilities/MimeType.swift deleted file mode 100755 index b7b0697..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/MimeType.swift +++ /dev/null @@ -1,159 +0,0 @@ -// -// MimeType.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 14.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -// MARK: - Global constants -fileprivate let DEFAULT_MIME_TYPE = "application/octet-stream" -fileprivate let mimeTypes = [ - "html" : "text/html", - "htm" : "text/html", - "shtml" : "text/html", - "css" : "text/css", - "xml" : "text/xml", - "gif" : "image/gif", - "jpeg" : "image/jpeg", - "jpg" : "image/jpeg", - "js" : "application/javascript", - "atom" : "application/atom+xml", - "rss" : "application/rss+xml", - "mml" : "text/mathml", - "txt" : "text/plain", - "jad" : "text/vnd.sun.j2me.app-descriptor", - "wml" : "text/vnd.wap.wml", - "htc" : "text/x-component", - "png" : "image/png", - "tif" : "image/tiff", - "tiff" : "image/tiff", - "wbmp" : "image/vnd.wap.wbmp", - "ico" : "image/x-icon", - "jng" : "image/x-jng", - "bmp" : "image/x-ms-bmp", - "svg" : "image/svg+xml", - "svgz" : "image/svg+xml", - "webp" : "image/webp", - "woff" : "application/font-woff", - "jar" : "application/java-archive", - "war" : "application/java-archive", - "ear" : "application/java-archive", - "json" : "application/json", - "hqx" : "application/mac-binhex40", - "doc" : "application/msword", - "pdf" : "application/pdf", - "ps" : "application/postscript", - "eps" : "application/postscript", - "ai" : "application/postscript", - "rtf" : "application/rtf", - "m3u8" : "application/vnd.apple.mpegurl", - "xls" : "application/vnd.ms-excel", - "eot" : "application/vnd.ms-fontobject", - "ppt" : "application/vnd.ms-powerpoint", - "wmlc" : "application/vnd.wap.wmlc", - "kml" : "application/vnd.google-earth.kml+xml", - "kmz" : "application/vnd.google-earth.kmz", - "7z" : "application/x-7z-compressed", - "cco" : "application/x-cocoa", - "jardiff" : "application/x-java-archive-diff", - "jnlp" : "application/x-java-jnlp-file", - "run" : "application/x-makeself", - "pl" : "application/x-perl", - "pm" : "application/x-perl", - "prc" : "application/x-pilot", - "pdb" : "application/x-pilot", - "rar" : "application/x-rar-compressed", - "rpm" : "application/x-redhat-package-manager", - "sea" : "application/x-sea", - "swf" : "application/x-shockwave-flash", - "sit" : "application/x-stuffit", - "tcl" : "application/x-tcl", - "tk" : "application/x-tcl", - "der" : "application/x-x509-ca-cert", - "pem" : "application/x-x509-ca-cert", - "crt" : "application/x-x509-ca-cert", - "xpi" : "application/x-xpinstall", - "xhtml" : "application/xhtml+xml", - "xspf" : "application/xspf+xml", - "zip" : "application/zip", - "bin" : "application/octet-stream", - "exe" : "application/octet-stream", - "dll" : "application/octet-stream", - "deb" : "application/octet-stream", - "dmg" : "application/octet-stream", - "iso" : "application/octet-stream", - "img" : "application/octet-stream", - "msi" : "application/octet-stream", - "msp" : "application/octet-stream", - "msm" : "application/octet-stream", - "docx" : "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "xlsx" : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - "pptx" : "application/vnd.openxmlformats-officedocument.presentationml.presentation", - "mid" : "audio/midi", - "midi" : "audio/midi", - "kar" : "audio/midi", - "mp3" : "audio/mpeg", - "ogg" : "audio/ogg", - "m4a" : "audio/x-m4a", - "ra" : "audio/x-realaudio", - "3gpp" : "video/3gpp", - "3gp" : "video/3gpp", - "ts" : "video/mp2t", - "mp4" : "video/mp4", - "mpeg" : "video/mpeg", - "mpg" : "video/mpeg", - "mov" : "video/quicktime", - "webm" : "video/webm", - "flv" : "video/x-flv", - "m4v" : "video/x-m4v", - "mng" : "video/x-mng", - "asx" : "video/x-ms-asf", - "asf" : "video/x-ms-asf", - "wmv" : "video/x-ms-wmv", - "avi" : "video/x-msvideo" -] - -// MARK: - -struct MimeType { - - // MARK: - Properties - private let `extension`: String - var value: String { - return (mimeTypes[`extension`.lowercased()] ?? DEFAULT_MIME_TYPE) - } - - // MARK: - Initialization - public init(url: URL) { - `extension` = url.pathExtension - } - -} - -// MARK: - -func isImage(contentType: String) -> Bool { - return ((contentType == "image/gif") - || (contentType == "image/jpeg") - || (contentType == "image/png") - || (contentType == "image/tiff")) -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/PopupDialogHandler.swift b/ios/libs/Webim/Example/WebimClientLibrary/Utilities/PopupDialogHandler.swift deleted file mode 100755 index 055f417..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/PopupDialogHandler.swift +++ /dev/null @@ -1,230 +0,0 @@ -// -// PopupDialogHandler.swift -// WebimClientLibrary_Tests -// -// Created by Nikita Lazarev-Zubov on 13.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import PopupDialog -import UIKit -import WebimClientLibrary - -final class PopupDialogHandler { - - // MARK: - Constants - static let BUTTON_HEIGHT = 60 - - // MARK: - Properties - private let delegate: UIViewController - - // MARK - Initializer - init(delegate: UIViewController) { - self.delegate = delegate - } - - // MARK: - Methods - - func showSettingsAlertDialog(withMessage message: String) { - let popup = PopupDialog(title: SettingsErrorDialog.title.rawValue.localized, - message: message) - popup.view.backgroundColor = backgroundSecondaryColor.color() - (popup.viewController as! PopupDialogDefaultViewController).titleColor = textMainColor.color() - - let okButton = CancelButton(title: SettingsErrorDialog.buttonTitle.rawValue.localized, - action: nil) - okButton.accessibilityHint = SettingsErrorDialog.buttonAccessibilityHint.rawValue.localized - okButton.titleColor = textMainColor.color() - okButton.backgroundColor = backgroundSecondaryColor.color() - popup.addButton(okButton) - - delegate.present(popup, - animated: true, - completion: nil) - } - - func showCreatingSessionFailureDialog(withMessage message: String) { - let popup = PopupDialog(title: SessionCreationErrorDialog.title.rawValue.localized, - message: message.localized) - popup.view.backgroundColor = backgroundSecondaryColor.color() - (popup.viewController as! PopupDialogDefaultViewController).titleColor = textMainColor.color() - - let okButton = CancelButton(title: SessionCreationErrorDialog.buttonTitle.rawValue.localized, - action: nil) - okButton.accessibilityHint = SessionCreationErrorDialog.buttonAccessibilityHint.rawValue.localized - okButton.titleColor = textMainColor.color() - okButton.backgroundColor = backgroundSecondaryColor.color() - popup.addButton(okButton) - - delegate.present(popup, - animated: true, - completion: nil) - } - - func showDepartmentListDialog(withDepartmentList departmentList: [Department], - action: @escaping (String) -> ()) { - let popup = PopupDialog(title: DepartmentListDialog.title.rawValue.localized, - message: nil, - image: nil, - buttonAlignment: .vertical, - transitionStyle: .bounceDown, - completion: nil) - popup.view.backgroundColor = backgroundSecondaryColor.color() - (popup.viewController as! PopupDialogDefaultViewController).titleColor = textMainColor.color() - - for department in departmentList { - let button = DefaultButton(title: department.getName()) { - action(department.getKey()) - } - button.accessibilityHint = DepartmentListDialog.buttonAccessibilityHint.rawValue.localized - button.titleColor = textMainColor.color() - button.backgroundColor = backgroundSecondaryColor.color() - popup.addButton(button) - } - - let cancelButton = CancelButton(title: DepartmentListDialog.cancelButtonTitle.rawValue.localized, - height: PopupDialogHandler.BUTTON_HEIGHT, - dismissOnTap: true, - action: nil) - cancelButton.accessibilityHint = DepartmentListDialog.cancelButtonAccessibilityHint.rawValue.localized - cancelButton.backgroundColor = backgroundSecondaryColor.color() - popup.addButton(cancelButton) - - delegate.present(popup, - animated: true, - completion: nil) - } - - func showFileSendFailureDialog(withMessage message: String, - action: (() -> ())? = nil) { - let popupDialog = PopupDialog(title: SendFileErrorMessage.title.rawValue.localized, - message: message) - popupDialog.view.backgroundColor = backgroundSecondaryColor.color() - (popupDialog.viewController as! PopupDialogDefaultViewController).titleColor = textMainColor.color() - - let okButton = CancelButton(title: SendFileErrorMessage.buttonTitle.rawValue.localized) { - action?() - } - okButton.accessibilityHint = SendFileErrorMessage.buttonAccessibilityHint.rawValue.localized - okButton.backgroundColor = backgroundSecondaryColor.color() - okButton.titleColor = textMainColor.color() - popupDialog.addButton(okButton) - - delegate.present(popupDialog, - animated: true, - completion: nil) - } - - func showFileDialog(withMessage message: String?, - title: String, - image: UIImage?) { - let button = CancelButton(title: ShowFileDialog.buttonTitle.rawValue.localized, - action: nil) - button.accessibilityHint = ShowFileDialog.accessibilityHint.rawValue.localized - button.backgroundColor = backgroundSecondaryColor.color() - button.titleColor = textMainColor.color() - - let popup = PopupDialog(title: title, - message: message, - image: image, - buttonAlignment: .horizontal, - transitionStyle: .bounceUp, - gestureDismissal: true, - completion: nil) - popup.view.backgroundColor = backgroundSecondaryColor.color() - (popup.viewController as! PopupDialogDefaultViewController).titleColor = textMainColor.color() - popup.addButton(button) - - delegate.present(popup, - animated: true, - completion: nil) - } - - func showRatingDialog(forOperator operatorID: String, - action: @escaping (_ rating: Int) -> ()) { - let ratingViewController = RatingViewController(nibName: "RatingViewController", - bundle: nil) - let popup = PopupDialog(viewController: ratingViewController, - buttonAlignment: .horizontal, - transitionStyle: .bounceUp, - gestureDismissal: true) - - let cancelButton = CancelButton(title: RatingDialog.cancelButtonTitle.rawValue.localized, - height: PopupDialogHandler.BUTTON_HEIGHT, - dismissOnTap: true, - action: nil) - cancelButton.accessibilityHint = RatingDialog.cancelButtonAccessibilityHint.rawValue.localized - cancelButton.backgroundColor = backgroundSecondaryColor.color() - - let rateButton = DefaultButton(title: RatingDialog.actionButtonTitle.rawValue.localized, - height: PopupDialogHandler.BUTTON_HEIGHT, - dismissOnTap: true) { - action(Int(ratingViewController.ratingView.rating)) - } - rateButton.accessibilityHint = RatingDialog.actionButtonAccessibilityHint.rawValue.localized - rateButton.backgroundColor = backgroundSecondaryColor.color() - rateButton.titleColor = textMainColor.color() - - popup.addButtons([cancelButton, - rateButton]) - - delegate.present(popup, - animated: true, - completion: nil) - } - - func showRatingFailureDialog() { - let popupDialog = PopupDialog(title: RateOperatorErrorMessage.title.rawValue.localized, - message: RateOperatorErrorMessage.message.rawValue.localized) - popupDialog.view.backgroundColor = backgroundSecondaryColor.color() - (popupDialog.viewController as! PopupDialogDefaultViewController).titleColor = textMainColor.color() - - let okButton = CancelButton(title: RateOperatorErrorMessage.buttonTitle.rawValue.localized, - action: nil) - okButton.accessibilityHint = RateOperatorErrorMessage.buttonAccessibilityHint.rawValue.localized - okButton.titleColor = textMainColor.color() - okButton.backgroundColor = backgroundSecondaryColor.color() - popupDialog.addButton(okButton) - - delegate.present(popupDialog, - animated: true, - completion: nil) - } - - func showChatClosedDialog() { - let popupDialog = PopupDialog(title: nil, - message: ChatClosedDialog.message.rawValue.localized) - popupDialog.view.backgroundColor = backgroundSecondaryColor.color() - (popupDialog.viewController as! PopupDialogDefaultViewController).messageColor = textMainColor.color() - - let okButton = CancelButton(title: ChatClosedDialog.buttonTitle.rawValue.localized, - action: nil) - okButton.accessibilityHint = ChatClosedDialog.buttonAccessibilityHint.rawValue.localized - okButton.titleColor = textMainColor.color() - okButton.backgroundColor = backgroundSecondaryColor.color() - popupDialog.addButton(okButton) - - delegate.present(popupDialog, - animated: true, - completion: nil) - } - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/WebimService.swift b/ios/libs/Webim/Example/WebimClientLibrary/Utilities/WebimService.swift deleted file mode 100755 index d8fb4ce..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/Utilities/WebimService.swift +++ /dev/null @@ -1,510 +0,0 @@ -// -// WebimService.swift -// WebimClientLibrary_Example -// -// Created by Nikita Lazarev-Zubov on 20.11.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import WebimClientLibrary - -final class WebimService { - - // MARK: - Constants - private enum ChatSettings: Int { - case messagesPerRequest = 5 - } - private enum VisitorFields: String { - case id = "id" - case name = "display_name" - case crc = "crc" - } - private enum VisitorFieldsValue: String { - // Hardcoded. See more at https://webim.ru/help/identification/ - case id = "1234567890987654321" - case name = "Никита" - case crc = "ffadeb6aa3c788200824e311b9aa44cb" - } - - // MARK: - Properties - private let fatalErrorHandlerDelegate: FatalErrorHandlerDelegate - private let departmentListHandlerDelegate: DepartmentListHandlerDelegate - private var messageStream: MessageStream? - private var messageTracker: MessageTracker? - private var webimSession: WebimSession? - - // MARK: - Initialization - init(fatalErrorHandlerDelegate: FatalErrorHandlerDelegate, - departmentListHandlerDelegate: DepartmentListHandlerDelegate) { - self.fatalErrorHandlerDelegate = fatalErrorHandlerDelegate - self.departmentListHandlerDelegate = departmentListHandlerDelegate - } - - // MARK: - Methods - - func createSession() { - let deviceToken: String? = UserDefaults.standard.object(forKey: AppDelegate.UserDefaultsKey.deviceToken.rawValue) as? String - - var sessionBuilder = Webim.newSessionBuilder() - .set(accountName: Settings.shared.accountName) - .set(location: Settings.shared.location) - .set(pageTitle: Settings.shared.pageTitle) - .set(fatalErrorHandler: self) - .set(remoteNotificationSystem: ((deviceToken != nil) ? .APNS : .NONE)) - .set(deviceToken: deviceToken) - .set(isVisitorDataClearingEnabled: false) - .set(webimLogger: self, - verbosityLevel: .VERBOSE) - - if (Settings.shared.accountName == Settings.DefaultSettings.accountName.rawValue) { - sessionBuilder = sessionBuilder.set(visitorFieldsJSONString: "{\"\(VisitorFields.id.rawValue)\":\"\(VisitorFieldsValue.id.rawValue)\",\"\(VisitorFields.name.rawValue)\":\"\(VisitorFieldsValue.name.rawValue)\",\"\(VisitorFields.crc.rawValue)\":\"\(VisitorFieldsValue.crc.rawValue)\"}") // Hardcoded values that work with "demo" account only! - } - - do { - webimSession = try sessionBuilder.build() - } catch let error as SessionBuilder.SessionBuilderError { - // Assuming to check parameters values in Webim session builder methods. - switch error { - case .NIL_ACCOUNT_NAME: - print("Webim session object creating failed because of passing nil account name.") - - break - case .NIL_LOCATION: - print("Webim session object creating failed because of passing nil location name.") - - break - case .INVALID_REMOTE_NOTIFICATION_CONFIGURATION: - print("Webim session object creating failed because of invalid remote notifications configuration.") - - break - case .INVALID_AUTHENTICATION_PARAMETERS: - print("Webim session object creating failed because of invalid visitor authentication system configuration.") - - break - case .INVALIDE_HEX: - print("Webim can't parsed prechat fields") - } - } catch { - print("Webim session object creating failed with unknown error: \(error.localizedDescription)") - } - } - - func startSession() { - do { - try webimSession?.resume() - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle or re-creating Webim session object. - print("Webim session starting/resuming failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Webim session starting/resuming failed because it was called from a wrong thread.") - - break - } - } catch { - print("Webim session starting/resuming failed with unknown error: \(error.localizedDescription)") - } - - startChat() - } - - func stopSession() { - do { - try messageTracker?.destroy() - try webimSession?.destroy() - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Ignored because if session is already destroyed, we don't care (it's the same thing that we try to achieve). - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Webim session or message tracker destroing failed because it was called from a wrong thread.") - - break - } - } catch { - print("Webim session or message tracker destroing failed with unknown error: \(error.localizedDescription)") - } - } - - func setMessageStream() { - messageStream = webimSession?.getStream() - } - - func setVisitorTyping(draft: String?) { - do { - if messageStream == nil { - setMessageStream() - } - try messageStream?.setVisitorTyping(draftMessage: draft) - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle. - print("Visitor status sending failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Visitor status sending failed because it was called from a wrong thread.") - - break - } - } catch { - print("Visitor typing status sending failed with unknown error: \(error.localizedDescription)") - } - } - - func send(message: String, - completion: (() -> ())? = nil) { - do { - if messageStream == nil { - setMessageStream() - } - - if messageStream?.getVisitSessionState() == .DEPARTMENT_SELECTION, - let departments = messageStream?.getDepartmentList() { - departmentListHandlerDelegate.show(departmentList: departments) { [weak self] departmentKey in - self?.startChat(departmentKey: departmentKey, - message: message) - completion?() - } - } else { - _ = try messageStream?.send(message: message) // Returned message ID ignored. - completion?() - } - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle or re-creating Webim session object. - print("Message sending failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Message sending failed because it was called from a wrong thread.") - - break - } - } catch { - print("Message sending failed with unknown error: \(error.localizedDescription)") - } - } - - func send(file data: Data, - fileName: String, - mimeType: String, - completionHandler: SendFileCompletionHandler) { - if messageStream == nil { - setMessageStream() - } - - if messageStream?.getVisitSessionState() == .DEPARTMENT_SELECTION, - let departments = messageStream?.getDepartmentList() { - departmentListHandlerDelegate.show(departmentList: departments) { [weak self] departmentKey in - self?.startChat(departmentKey: departmentKey, - message: nil) - self?.sendFile(data: data, - fileName: fileName, - mimeType: mimeType, - completionHandler: completionHandler) - } - } else { - sendFile(data: data, - fileName: fileName, - mimeType: mimeType, - completionHandler: completionHandler) - } - } - - func isChatExist() -> Bool { - guard let chatState = messageStream?.getChatState() else { - return false - } - - return ((chatState == .CHATTING) - || (chatState == .CLOSED_BY_OPERATOR)) - } - - func closeChat() { - do { - if messageStream == nil { - setMessageStream() - } - - try messageStream?.closeChat() - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle or re-creating Webim session object. - print("Webim session starting/resuming failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Webim session starting/resuming failed because it was called from a wrong thread.") - - break - } - } catch { - print("Webim session starting/resuming failed with unknown error: \(error.localizedDescription)") - } - } - - func rateOperator(withID operatorID: String, - byRating rating: Int, - completionHandler: RateOperatorCompletionHandler?) { - do { - if messageStream == nil { - setMessageStream() - } - - try messageStream?.rateOperatorWith(id: operatorID, - byRating: rating, - completionHandler: completionHandler) - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle or re-creating Webim session object. - print("Webim session starting/resuming failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Webim session starting/resuming failed because it was called from a wrong thread.") - - break - } - } catch { - print("Webim session starting/resuming failed with unknown error: \(error.localizedDescription)") - } - } - - func setMessageTracker(withMessageListener messageListener: MessageListener) { - do { - if messageStream == nil { - setMessageStream() - } - - try messageTracker = messageStream?.newMessageTracker(messageListener: messageListener) - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle or re-creating Webim session object. - print("Webim session starting/resuming failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Webim session starting/resuming failed because it was called from a wrong thread.") - - break - } - } catch { - print("Webim session starting/resuming failed with unknown error: \(error.localizedDescription)") - } - } - - func getLastMessages(completion: @escaping (_ result: [Message]) -> ()) { - do { - try messageTracker?.getLastMessages(byLimit: ChatSettings.messagesPerRequest.rawValue, - completion: completion) - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle or re-creating Webim session object. - print("Webim session starting/resuming failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Webim session starting/resuming failed because it was called from a wrong thread.") - - break - } - } catch { - print("Webim session starting/resuming failed with unknown error: \(error.localizedDescription)") - } - } - - func getNextMessages(completion: @escaping (_ result: [Message]) -> ()) { - do { - try messageTracker?.getNextMessages(byLimit: ChatSettings.messagesPerRequest.rawValue, - completion: completion) - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle or re-creating Webim session object. - print("Webim session starting/resuming failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Webim session starting/resuming failed because it was called from a wrong thread.") - - break - } - } catch { - print("Webim session starting/resuming failed with unknown error: \(error.localizedDescription)") - } - } - - // MARK: Private methods - - private func startChat(departmentKey: String? = nil, - message: String? = nil) { - do { - if messageStream == nil { - setMessageStream() - } - - try messageStream?.startChat(departmentKey: departmentKey, - firstQuestion: message) - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle or re-creating Webim session object. - print("Chat starting failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Chat starting failed because it was called from a wrong thread.") - - break - - } - } catch { - print("Chat starting failed with unknown error: \(error.localizedDescription)") - } - } - - func setChatRead() { - do { - if messageStream == nil { - setMessageStream() - } - - try messageStream?.setChatRead() - } catch { - print("Read chat failed with unknown error: \(error.localizedDescription)") - } - } - - private func sendFile(data: Data, - fileName: String, - mimeType: String, - completionHandler: SendFileCompletionHandler) { - do { - _ = try messageStream?.send(file: data, - filename: fileName, - mimeType: mimeType, - completionHandler: completionHandler) // Returned message ID ignored. - } catch let error as AccessError { - switch error { - case .INVALID_SESSION: - // Assuming to check Webim session object lifecycle or re-creating Webim session object. - print("Message sending failed because it was called when session object is invalid.") - - break - case .INVALID_THREAD: - // Assuming to check concurrent calls of WebimClientLibrary methods. - print("Message sending failed because it was called from a wrong thread.") - - break - } - } catch { - print("Message status sending failed with unknown error: \(error.localizedDescription)") - } - } - -} - -// MARK: - WEBIM: FatalErrorHandler -extension WebimService: FatalErrorHandler { - - // MARK: - Methods - func on(error: WebimError) { - let errorType = error.getErrorType() - switch errorType { - case .ACCOUNT_BLOCKED: - // Assuming to contact with Webim support. - print("Account with used account name is blocked by Webim service.") - fatalErrorHandlerDelegate.showErrorDialog(withMessage: SessionCreationErrorDialog.accountBlocked.rawValue) - - break - case .PROVIDED_VISITOR_FIELDS_EXPIRED: - // Assuming to re-authorize it and re-create session object. - print("Provided visitor fields expired. See \"expires\" key of this fields.") - - break - case .UNKNOWN: - print("An unknown error occured: \(error.getErrorString()).") - - break - case .VISITOR_BANNED: - print("Visitor with provided visitor fields is banned by an operator.") - fatalErrorHandlerDelegate.showErrorDialog(withMessage: SessionCreationErrorDialog.visitorBanned.rawValue) - - break - case .WRONG_PROVIDED_VISITOR_HASH: - // Assuming to check visitor field generating. - print("Wrong CRC passed with visitor fields.") - - break - } - } - -} - -// MARK: - WebimLogger -extension WebimService: WebimLogger { - - // MARK: - Methods - func log(entry: String) { - print(entry) - } - -} - -// MARK: - -protocol FatalErrorHandlerDelegate: AnyObject { - - // MARK: - Methods - func showErrorDialog(withMessage message: String) - -} - -// MARK: - -protocol DepartmentListHandlerDelegate: AnyObject { - - // MARK: - Methods - func show(departmentList: [Department], - action: @escaping (String) -> ()) - -} diff --git a/ios/libs/Webim/Example/WebimClientLibrary/ru-RU.lproj/Localizable.strings b/ios/libs/Webim/Example/WebimClientLibrary/ru-RU.lproj/Localizable.strings deleted file mode 100755 index d79ce97..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/ru-RU.lproj/Localizable.strings +++ /dev/null @@ -1,109 +0,0 @@ -/* - Localizable.strings - WebimClientLibrary - - Created by Nikita Lazarev-Zubov on 11.12.17. - Copyright © 2017 Webim. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - - -// MARK: - Remote notifications - -"P.OA" = "Обращению назначен оператор: %@."; -"P.OF" = "%@ прислал файл: %@."; -"P.OM" = "%@ написал сообщение: %@."; - - -// MARK: - StringConstants.swift - -// EMPTY_TABLE_VIEW_TEXT -"EmptyChat" = "Отправьте первое сообщение, чтобы начать чат."; - -// REFRESH_CONTROL_TEXT -"LoadingMessages" = "Сообщения загружаются..."; - -// Avatar -"SenderAvatarImage" = "Изображение аватара отправителя сообщения"; -"ShowsRatingDialog" = "Показывает окно оценки оператора."; - -// BackButton -"Back" = "Закрыть экран"; -"ClosesScreen" = "Закрывает экран и возвращает на предыдущий."; - -// ChatClosedDialog -"ChatClosed" = "Чат закончен."; -"OK" = "OK"; -"ClosesRateOperatorError" = "Закрывает окно."; - -// CloseChatButton -"CloseChat" = "Закрыть чат"; -"ClosesChat" = "Закрывает чат не закрывая данный экран."; - -// DepartmentListDialog -"ContactTopic" = "Тема обращения"; -"ChoosesTopic" = "Выбирает данную тему для обращения"; -"Cancel" = "Отмена"; -"ClosesDialog" = "Закрывает окно."; - -// FileMessage -"FileUnavailable" = "Файл недоступен."; - -// LeftButton -"ChooseFile" = "Выбрать файл для отправки"; -"ShowsImagePicker" = "Показывает окно выбора изображения для отправки."; - -// RateOperatorErrorMessage -"OperatorRatingFailed" = "Неудачная попытка оценить оператора"; -"OK" = "OK"; -"ClosesRateOperatorError" = "Закрывает окно."; -"RateOperatorErrorMessage" = "Произошла неизвестная ошибка."; - -// RatingDialog -"Rate" = "Оценить"; -"Cancel" = "Отмена"; -"RatesOperator" = "Оценивает оператора."; -"ClosesRatingDialog" = "Закрывает диалог."; - -// SendFileErrorMessage -"FileSendingFailed" = "Неудачная попытка отправки файла"; -"ClosesSendFileError" = "Закрывает окно."; -"FileTooLarge" = "Размер файла превышен."; -"FileTypeNotSupported" = "Данный тип файла не поддерживается."; -"FileNotFound" = "Отправляемый файл не был получен."; -"FileSendingUnknownError" = "Неизвестная ошибка при отправке файла"; - -// SessionCreationErrorDialog -"ClosesSessionError" = "Закрывает окно."; -"SessionCreationFailed" = "Неудачная попытка создания сессии"; -"AccountBlocked" = "Учетная запись, с помощью которой была произведена попытка начать сессию, заблокирован. Пожалуйста, обратитесь в службу поддержки \"Webim\" или используйте другую учетную запись."; -"VisitorBanned" = "Ваша учетная запись посетителя находится в черном списке."; - -// SettingsErrorDialog -"ClosesSettingsError" = "Закрывает окно."; -"InvalidSettings" = "Неверные данные учетной записи"; -"AccountNameEmpty" = "Название учетной записи не может быть пустым."; -"LocationEmpty" = "Значение размещения не может быть пустым."; - -// ShowFileDialog -"ImageFormatInvalid" = "Неверный формат изображения."; -"ImageLinkInvalid" = "Ссылка недействительна."; -"PreviewUnavailable" = "Просмотр недоступен."; -"ClosesFilePreview" = "Закрывает окно."; diff --git a/ios/libs/Webim/Example/WebimClientLibrary/ru-RU.lproj/Main.strings b/ios/libs/Webim/Example/WebimClientLibrary/ru-RU.lproj/Main.strings deleted file mode 100755 index 6bfda1d..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/ru-RU.lproj/Main.strings +++ /dev/null @@ -1,88 +0,0 @@ - -/* Class = "UILabel"; text = "Account name *"; ObjectID = "7Wr-eX-iv8"; */ -"7Wr-eX-iv8.text" = "Название аккаунта *"; - -/* Class = "UITableViewSection"; footerTitle = "If you are registered in Webim service you can use your own account name and location."; ObjectID = "FX1-M6-A8v"; */ -"FX1-M6-A8v.footerTitle" = "Если вы зарегистрированы в сервисе \"Webim\", вы можете использовать свою учетную запись."; - -/* Class = "UITableViewSection"; headerTitle = "ACCOUNT"; ObjectID = "FX1-M6-A8v"; */ -"FX1-M6-A8v.headerTitle" = "УЧЕТНАЯ ЗАПИСЬ"; - -/* Class = "UIButton"; accessibilityHint = "Saves current settings and shows start screen."; ObjectID = "QrB-ab-D1k"; */ -"QrB-ab-D1k.accessibilityHint" = "Сохраняет текущие настройки и возвращается к начальной странице."; - -/* Class = "UIButton"; accessibilityLabel = "Save"; ObjectID = "QrB-ab-D1k"; */ -"QrB-ab-D1k.accessibilityLabel" = "Сохранить"; - -/* Class = "UIButton"; normalTitle = "Save"; ObjectID = "QrB-ab-D1k"; */ -"QrB-ab-D1k.normalTitle" = "Сохранить"; - -/* Class = "UILabel"; accessibilityLabel = "Classic color theme"; ObjectID = "Xp5-8q-gOf"; */ -"Xp5-8q-gOf.accessibilityLabel" = "Стандартная цветовая схема"; - -/* Class = "UILabel"; text = "Classic"; ObjectID = "Xp5-8q-gOf"; */ -"Xp5-8q-gOf.text" = "Стандартная"; - -/* Class = "UITextField"; accessibilityLabel = "Page title field"; ObjectID = "YbA-Bc-Fio"; */ -"YbA-Bc-Fio.accessibilityLabel" = "Поле названия страницы чата"; - -/* Class = "UITextField"; text = "iOS Demo App"; ObjectID = "YbA-Bc-Fio"; */ -"YbA-Bc-Fio.text" = "iOS Demo App"; - -/* Class = "UITextField"; accessibilityLabel = "Location name field"; ObjectID = "ZbE-AG-UMG"; */ -"ZbE-AG-UMG.accessibilityLabel" = "Поле названия размещения (локации)"; - -/* Class = "UITextField"; text = "mobile"; ObjectID = "ZbE-AG-UMG"; */ -"ZbE-AG-UMG.text" = "mobile"; - -/* Class = "UITextView"; accessibilityLabel = "Greeting words"; ObjectID = "bPt-yP-yHN"; */ -"bPt-yP-yHN.accessibilityLabel" = "Приветственные слова"; - -// Xcode does not localize UITextView text automatically. -/* Class = "UITextView"; text = "Welcome to the WebimClientLibrary demo app!\n\nTo start a chat tap on the button below.\n\nOperator can answer to your chat at:\nhttps://demo.webim.ru/\nLogin: o@webim.ru\nPassword: password\n\nThis app source code can be found at:\nhttps://github.com/webim/webim-client-sdk-ios"; ObjectID = "bPt-yP-yHN"; */ -"Welcome to the WebimClientLibrary demo app!\n\nTo start a chat tap on the button below.\n\nOperator can answer to your chat at:\nhttps://demo.webim.ru/\nLogin: o@webim.ru\nPassword: password\n\nThis app source code can be found at:\nhttps://github.com/webim/webim-client-sdk-ios" = "Добро пожаловать в демо-приложение WebimClientLibrary!\n\nЧтобы начать чат, нажмите кнопку внизу.\n\nОператор может ответить на обращение здесь:\nhttps://demo.webim.ru/\nЛогин: o@webim.ru\nПароль: password\n\nИсходный код данного приложения может быть найден здесь:\nhttps://github.com/webim/webim-client-sdk-ios"; - -/* Class = "UIButton"; accessibilityHint = "Starts chat."; ObjectID = "edo-SU-HN8"; */ -"edo-SU-HN8.accessibilityHint" = "Начинает чат."; - -/* Class = "UIButton"; accessibilityLabel = "Start chat"; ObjectID = "edo-SU-HN8"; */ -"edo-SU-HN8.accessibilityLabel" = "Начать чат"; - -/* Class = "UIButton"; normalTitle = "Start chat"; ObjectID = "edo-SU-HN8"; */ -"edo-SU-HN8.normalTitle" = "Начать чат"; - -/* Class = "UITableViewSection"; headerTitle = "COLOR THEME"; ObjectID = "fJX-AG-mdU"; */ -"fJX-AG-mdU.headerTitle" = "ЦВЕТОВАЯ СХЕМА"; - -/* Class = "UILabel"; text = "Page title"; ObjectID = "kTz-jD-ziQ"; */ -"kTz-jD-ziQ.text" = "Название экрана чата"; - -/* Class = "UITextField"; accessibilityLabel = "Account name field"; ObjectID = "qLZ-bH-B74"; */ -"qLZ-bH-B74.accessibilityLabel" = "Поле названия учетной записи"; - -/* Class = "UITextField"; text = "demo"; ObjectID = "qLZ-bH-B74"; */ -"qLZ-bH-B74.text" = "demo"; - -/* Class = "UILabel"; text = "Location *"; ObjectID = "qQH-qh-OFD"; */ -"qQH-qh-OFD.text" = "Размещение *"; - -/* Class = "UIButton"; accessibilityHint = "Shows settings."; ObjectID = "rMR-x2-dzu"; */ -"rMR-x2-dzu.accessibilityHint" = "Показывает настройки."; - -/* Class = "UIButton"; accessibilityLabel = "Settings"; ObjectID = "rMR-x2-dzu"; */ -"rMR-x2-dzu.accessibilityLabel" = "Настройки"; - -/* Class = "UIButton"; normalTitle = "Settings"; ObjectID = "rMR-x2-dzu"; */ -"rMR-x2-dzu.normalTitle" = "Настройки"; - -/* Class = "UILabel"; accessibilityLabel = "Dark color theme"; ObjectID = "slT-Ti-eBV"; */ -"slT-Ti-eBV.accessibilityLabel" = "Темная цветовая СХЕМА"; - -/* Class = "UILabel"; text = "Dark"; ObjectID = "slT-Ti-eBV"; */ -"slT-Ti-eBV.text" = "Темная"; - -/* Class = "UILabel"; text = "* Account name can't be empty."; ObjectID = "5Lf-Fb-XN7"; */ -"5Lf-Fb-XN7.text" = "* Название учетной записи не может быть пустым."; - -/* Class = "UILabel"; text = "* Location can't be empty."; ObjectID = "6r5-5x-xIB"; */ -"6r5-5x-xIB.text" = "* Размещение (локация) не может быть пустым."; diff --git a/ios/libs/Webim/Example/WebimClientLibrary/ru-RU.lproj/RatingViewController.strings b/ios/libs/Webim/Example/WebimClientLibrary/ru-RU.lproj/RatingViewController.strings deleted file mode 100755 index 6f91939..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary/ru-RU.lproj/RatingViewController.strings +++ /dev/null @@ -1,9 +0,0 @@ - -/* Class = "UIView"; accessibilityHint = "Устанавливает оценку оператора числом от одного до пяти."; ObjectID = "TCC-HX-zVh"; */ -"TCC-HX-zVh.accessibilityHint" = "Устанавливает оценку оператора числом от одного до пяти."; - -/* Class = "UIView"; accessibilityLabel = "Оценка"; ObjectID = "TCC-HX-zVh"; */ -"TCC-HX-zVh.accessibilityLabel" = "Оценка"; - -/* Class = "UILabel"; text = "Оценить оператора"; ObjectID = "XLW-Lu-VBj"; */ -"XLW-Lu-VBj.text" = "Оценить оператора"; diff --git a/ios/libs/Webim/Example/WebimClientLibrary_Example.entitlements b/ios/libs/Webim/Example/WebimClientLibrary_Example.entitlements deleted file mode 100755 index 903def2..0000000 --- a/ios/libs/Webim/Example/WebimClientLibrary_Example.entitlements +++ /dev/null @@ -1,8 +0,0 @@ - - - - - aps-environment - development - - diff --git a/ios/libs/Webim/Info.plist b/ios/libs/Webim/Info.plist deleted file mode 100755 index cad21c5..0000000 --- a/ios/libs/Webim/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 3.24.7 - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/ios/libs/Webim/LICENSE b/ios/libs/Webim/LICENSE deleted file mode 100755 index b116da0..0000000 --- a/ios/libs/Webim/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2017-2019 Webim - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/ios/libs/Webim/README.md b/ios/libs/Webim/README.md deleted file mode 100755 index 89f1549..0000000 --- a/ios/libs/Webim/README.md +++ /dev/null @@ -1,181 +0,0 @@ -
- -![Webim logo](Documentation/Images/Logo.png) - -
- -# WebimClientLibrary - -This library provides [_Webim SDK_ for _iOS_](https://webim.ru/integration/mobile-sdk/ios-sdk-howto/) – a way to integrate _Webim_ service into your _iOS_ app. - -## Installation - -> Minimum iOS version supported – 8.0. - -### CocoaPods - -Add following line for your target in your **Podfile**: -``` -pod 'WebimClientLibrary', :git => 'https://github.com/webim/webim-client-sdk-ios.git', :branch => 'master', :tag => '3.24.6' -``` -`use_frameworks!` must be specified. - -### Carthage - -Add following line to your **Cartfile**: -``` -github "webim/webim-client-sdk-ios" ~> 3.24.7 -``` - -### Additional notes - -#### Objective-C - -Trying to integrate _WebimClientLibrary_ into your _Objective-C_ code? Try out our [_WebimClientLibraryWrapper_](https://github.com/webim/webim-client-sdk-ios-wrapper). - -#### Previous version - -Previous _Objective-C_ version (version numbers 2.x.x) can be reached from **version2** branch. - -## Release notes -* SQLiteHistoryStorage methods bugs fixed. -* Uptime in HistoryPoller bag fixed. -* New parameters in User-Agent: Bundle ID and version. - -## Example - -![Start screen screenshot Classic theme](Documentation/Images/Screenshots/StartScreenClassic.png) ![Settings screen screenshot Classic theme](Documentation/Images/Screenshots/SettingsScreenClassic.png) ![Chat screen screenshot Classic theme](Documentation/Images/Screenshots/ChatScreenClassic.png) ![Image preview screenshot Classic theme](Documentation/Images/Screenshots/ImageScreenClassic.png) ![Rating window screenshot Classic theme](Documentation/Images/Screenshots/RatingScreenClassic.png) - -![Start screen screenshot Dark theme](Documentation/Images/Screenshots/StartScreenDark.png) ![Settings screen screenshot Dark theme](Documentation/Images/Screenshots/SettingsScreenDark.png) ![Chat screen screenshot Dark theme](Documentation/Images/Screenshots/ChatScreenDark.png) ![Image preview screenshot Dark theme](Documentation/Images/Screenshots/ImageScreenDark.png) ![Rating window screenshot Dark theme](Documentation/Images/Screenshots/RatingScreenDark.png) - -If you don't have _CocoaPods_ installed you should firstly run `sudo gem install cocoapods`. - -To run the example project, clone the repo and run `pod install` from the **Example** directory first. - -## Usage - -### Session - -SDK functionality usage starts with session object creating. - -`Webim` class method `newSessionBuilder()` returns session builder object (class `SessionBuilder`) (both of this classes and their methods are described inside **Webim.swift** file). Then setting session parameters methods are to be called on the created `SessionBuilder` object. After all necessary parameters are set, method `build()` is to be called. This method returns `WebimSession` object. - -Typical usage example: -``` -let webimSession = try Webim.newSessionBuilder().set(accountName: "ACCOUNT_NAME").set(location: "LOCATION_NAME").build() -``` - -All parameters that can be set while creating a session and all errors that can be thrown are also described in **Webim.swift** file. Account name and locations are the only required of them. - -After the session is created it must be started by `resume()` method (since a session object is initially paused). - -Session can be paused (`pause()` method) and resumed (`resume()` method) as well as destroyed (`destroy()` method) if necessary. All of this methods are described in **WebimSession.swift** file. - -### MessageStream - -All message stream methods are described in **MessageStream.swift** file. - -For this methods usage ability the `MessageStream` object is have to be getted through `getStream()` method by `WebimSession` class object. - -Methods examples: -`send(message:)` – send message, -`rateOperatorWith(id:byRating:)` – rate operator, -`closeChat()` – close chat. - -### MessageTracker - -`newMessageTracker(messageListener:)` method by `MessageStream` object creates `MessageTracker` object, which can be used to control a message stream inside an app. - -E.g. `getNextMessages(byLimit:completion:)` method requests a certain amount of messages from the history. - -Methods descriptions can be found inside **MessageTracker.swift** file. - -### MessageListener - -`MessageListener` protocol describes methods which can help to track changes in the message stream. An app must have a class which implements this protocol methods: `added(message:after:)`, `removed(message:)`, `removedAllMessages()`, `changed(message:to:)`. This methods are called automatically when new message is added, a message is deleted, all messages are deleted and a message is changed respectively. - -Full methods descriptions can be found inside **MessageListener.swift** file. - -### Message - -`MessageListener` protocol methods operate on `Message` objects which is described inside **Message.swift** file. - -All necessary information about specific message can be getted through `Message` objects methods: unique message number (`getID()` method), message text (`getText()` method), attached file info (`getAttachment()` method) etc. - -All related tools (methods for working with attachments, message types etc.) are also described in **Message.swift** file. - -### Additional features - -Methods for getting information about specific operator are described inside **Operator.swift** file. Operator object can be getted through `MessageStream` object `getCurrentOperator()` method. - -Methods for working with remote notifications by _Webim_ service are described inside **WebimRemoteNotification.swift** file. - -Specific remote notification object can be getted through `Webim` class `parse(remoteNotification:)` method. This class also has method `isWebim(remoteNotification:)` which can be used to easily discover whether the notification is send by _Webim_ service or not. - -**FatalErrorHandler.swift** contains `FatalErrorHandler` protocol description. Its methods can be implemented by an app for tracking errors which can arise in progress. All kinds of specific errors are described inside the same file. - -**MessageStream.swift** also contains additional protocols descriptions which can be implemented by an app classes for tracking different particular changes. E.g. `ChatStateListener` protocol methods are called when chat state is changed (all the specific chat states are described in the same file). - -## Remote notifications - -**For remote notifications to be enabled you should send your app certificates/private key to us. For more information please contact to our support!** - -For iOS to be able to handle remote notifications automatically your app must be aware of possible remote notification types and arguments. - -Possible `loc-key` values: -* `P.CR` means that operator sent contact information request. -* `P.OA` means that operator accepted chat. -* `P.OF` means that operator sent a flie. -* `P.OM` means that operator sent a text message. -* `P.WM` means that operator sent a widget message (for this functionality support one should contact _Webim_ support). - -`loc-args` values for this types: -* `P.CR`: empty. -* `P.OA`: operator's name. -* `P.OF`: operator's name, file name. -* `P.OM`: operator's name, message text. -* `P.WM`: empty. - -Remote notification handling with Strings.localizable file example: -``` -"P.OM" = "Message from %@ is received: %@." -``` - -### Conclusion - -Entities and methods described above are all that it necessary for working in an app with _Webim_ service and even more. - -Abilities described In this manual are not all of the existing ones, so after necessary minimum is implemented it is recommended to get acquainted with full list of protocols and methods listed in SDK public files. - -All public interfaces, classes and methods are described inside this files (in alphabetical order): -* **Department.swift**, -* **FatalErrorHandler.swift**, -* **Message.swift**, -* **MessageListener.swift**, -* **MessageStream.swift**, -* **MessageTracker.swit**, -* **Operator.swift**, -* **ProvidedAuthorizationTokenStateListener.swift** -* **Webim.swift**, -* **WebimError.swift**, -* **WebimLogger.swift**, -* **WebimRemoteNotification.swift**, -* **WebimSession.swift**. - -Every single class, protocol, method etc. description provided inside [documentation](Documentation/Index.md). - -## Additional information - -_WebimClientLibrary_ uses [_SQLite.swift_](https://github.com/stephencelis/SQLite.swift). (There's no need to add this depencies into Podfile.) - -In the sake of ease of several functionalities implementation Example app uses (in alphabetical order): -* [_Cosmos_](https://github.com/evgenyneu/Cosmos) – for visual implementation of operator rating mechanism. -* [_Crashlytics_](https://try.crashlytics.com) – for detecting crashes and investigating their causes. -* [_PopupDialog_](https://github.com/Orderella/PopupDialog) – for implemetation of pop-up dialogs. -* [_SnapKit_](https://github.com/SnapKit/SnapKit) – for AutoLayout mechanism implementation inside the code. -* [_SlackTextViewController_](https://github.com/slackhq/SlackTextViewController) – for chat stream displaying inside Table View. - - -## License - -_WebimClientLibrary_ is available under the MIT license. See the LICENSE file for more info. diff --git a/ios/libs/Webim/WebimClientLibrary.podspec b/ios/libs/Webim/WebimClientLibrary.podspec deleted file mode 100755 index 0fa9652..0000000 --- a/ios/libs/Webim/WebimClientLibrary.podspec +++ /dev/null @@ -1,19 +0,0 @@ -Pod::Spec.new do |s| - - s.name = 'WebimClientLibrary' - s.version = '3.24.7' - - s.author = { 'Webim.ru Ltd.' => 'n.lazarev-zubov@webim.ru' } - s.homepage = 'https://webim.ru/integration/mobile-sdk/ios-sdk-howto/' - s.license = { :type => 'MIT', :file => 'LICENSE' } - s.summary = 'Webim.ru client SDK for iOS.' - - s.ios.deployment_target = '8.0' - s.swift_version = '4.2' - s.source = { :git => 'https://github.com/webim/webim-client-sdk-ios.git', :tag => s.version.to_s } - - s.dependency 'SQLite.swift', '0.11.5' - s.frameworks = 'Foundation' - s.source_files = 'WebimClientLibrary/**/*' - -end diff --git a/ios/libs/Webim/WebimClientLibrary.xcodeproj/project.pbxproj b/ios/libs/Webim/WebimClientLibrary.xcodeproj/project.pbxproj deleted file mode 100755 index fb13e71..0000000 --- a/ios/libs/Webim/WebimClientLibrary.xcodeproj/project.pbxproj +++ /dev/null @@ -1,778 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - 8FD2428B200CDB18007EB9CB /* WebimClientLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FD2427D200CDB18007EB9CB /* WebimClientLibrary.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8FD244A8200CE25C007EB9CB /* WebimLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2445C200CE258007EB9CB /* WebimLogger.swift */; }; - 8FD244A9200CE25C007EB9CB /* MessageListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2445D200CE258007EB9CB /* MessageListener.swift */; }; - 8FD244AA200CE25C007EB9CB /* WebimRemoteNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2445E200CE259007EB9CB /* WebimRemoteNotification.swift */; }; - 8FD244AB200CE25C007EB9CB /* WebimSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2445F200CE259007EB9CB /* WebimSession.swift */; }; - 8FD244AC200CE25C007EB9CB /* Operator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24460200CE259007EB9CB /* Operator.swift */; }; - 8FD244AD200CE25C007EB9CB /* Department.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24461200CE259007EB9CB /* Department.swift */; }; - 8FD244AE200CE25C007EB9CB /* ProvidedAuthorizationTokenStateListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24462200CE259007EB9CB /* ProvidedAuthorizationTokenStateListener.swift */; }; - 8FD244AF200CE25C007EB9CB /* MessageTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24463200CE25A007EB9CB /* MessageTracker.swift */; }; - 8FD244B0200CE25C007EB9CB /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24464200CE25A007EB9CB /* Message.swift */; }; - 8FD244B1200CE25C007EB9CB /* HistoryMetaInformationStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24466200CE25A007EB9CB /* HistoryMetaInformationStorage.swift */; }; - 8FD244B2200CE25C007EB9CB /* MemoryHistoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24467200CE25A007EB9CB /* MemoryHistoryStorage.swift */; }; - 8FD244B3200CE25C007EB9CB /* InternalErrorListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24468200CE25A007EB9CB /* InternalErrorListener.swift */; }; - 8FD244B4200CE25C007EB9CB /* MemoryHistoryMetaInformationStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24469200CE25A007EB9CB /* MemoryHistoryMetaInformationStorage.swift */; }; - 8FD244B5200CE25C007EB9CB /* ClientSideID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2446A200CE25A007EB9CB /* ClientSideID.swift */; }; - 8FD244B6200CE25C007EB9CB /* WebimActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2446B200CE25A007EB9CB /* WebimActions.swift */; }; - 8FD244B7200CE25C007EB9CB /* MessageComposingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2446C200CE25A007EB9CB /* MessageComposingHandler.swift */; }; - 8FD244B8200CE25C007EB9CB /* WebimInternalError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2446D200CE25A007EB9CB /* WebimInternalError.swift */; }; - 8FD244B9200CE25C007EB9CB /* LocationSettingsHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2446E200CE25A007EB9CB /* LocationSettingsHolder.swift */; }; - 8FD244BB200CE25C007EB9CB /* WebimRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24470200CE25A007EB9CB /* WebimRequest.swift */; }; - 8FD244BC200CE25C007EB9CB /* WebimClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24471200CE25A007EB9CB /* WebimClient.swift */; }; - 8FD244BD200CE25C007EB9CB /* RemoteHistoryProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24472200CE25A007EB9CB /* RemoteHistoryProvider.swift */; }; - 8FD244BE200CE25C007EB9CB /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24475200CE25A007EB9CB /* Dictionary.swift */; }; - 8FD244BF200CE25C007EB9CB /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24476200CE25A007EB9CB /* String.swift */; }; - 8FD244C0200CE25C007EB9CB /* MessageFactories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24477200CE25A007EB9CB /* MessageFactories.swift */; }; - 8FD244C1200CE25C007EB9CB /* InternalUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24478200CE25A007EB9CB /* InternalUtils.swift */; }; - 8FD244C2200CE25C007EB9CB /* CompletionHandlerWrappers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24479200CE25A007EB9CB /* CompletionHandlerWrappers.swift */; }; - 8FD244C3200CE25C007EB9CB /* AbstractRequestLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2447A200CE25A007EB9CB /* AbstractRequestLoop.swift */; }; - 8FD244C4200CE25C007EB9CB /* DeltaCallback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2447B200CE25A007EB9CB /* DeltaCallback.swift */; }; - 8FD244C5200CE25C007EB9CB /* ActionRequestLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2447C200CE25A007EB9CB /* ActionRequestLoop.swift */; }; - 8FD244C6200CE25C007EB9CB /* SessionDestroyer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2447D200CE25A007EB9CB /* SessionDestroyer.swift */; }; - 8FD244C7200CE25C007EB9CB /* ProvidedVisitorFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2447E200CE25A007EB9CB /* ProvidedVisitorFields.swift */; }; - 8FD244C8200CE25C007EB9CB /* ExecIfNotDestroyedHandlerExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2447F200CE25A007EB9CB /* ExecIfNotDestroyedHandlerExecutor.swift */; }; - 8FD244C9200CE25C007EB9CB /* AuthorizationData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24480200CE25A007EB9CB /* AuthorizationData.swift */; }; - 8FD244CA200CE25C007EB9CB /* DeltaRequestLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24481200CE25A007EB9CB /* DeltaRequestLoop.swift */; }; - 8FD244CB200CE25C007EB9CB /* OperatorItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24483200CE25A007EB9CB /* OperatorItem.swift */; }; - 8FD244CC200CE25C007EB9CB /* DepartmentItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24484200CE25A007EB9CB /* DepartmentItem.swift */; }; - 8FD244CD200CE25C007EB9CB /* RatingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24485200CE25A007EB9CB /* RatingItem.swift */; }; - 8FD244CE200CE25C007EB9CB /* VisitSessionStateItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24486200CE25A007EB9CB /* VisitSessionStateItem.swift */; }; - 8FD244CF200CE25C007EB9CB /* HistoryBeforeResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24488200CE25A007EB9CB /* HistoryBeforeResponse.swift */; }; - 8FD244D0200CE25C007EB9CB /* HistorySinceResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24489200CE25A007EB9CB /* HistorySinceResponse.swift */; }; - 8FD244D1200CE25C007EB9CB /* DeltaResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2448A200CE25A007EB9CB /* DeltaResponse.swift */; }; - 8FD244D2200CE25C007EB9CB /* FileParametersItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2448B200CE25A007EB9CB /* FileParametersItem.swift */; }; - 8FD244D3200CE25C007EB9CB /* OnlineStatusItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2448C200CE25A007EB9CB /* OnlineStatusItem.swift */; }; - 8FD244D4200CE25C007EB9CB /* DeltaItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2448E200CE25A007EB9CB /* DeltaItem.swift */; }; - 8FD244D5200CE25C007EB9CB /* FullUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2448F200CE25A007EB9CB /* FullUpdate.swift */; }; - 8FD244D6200CE25C007EB9CB /* ChatItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24490200CE25A007EB9CB /* ChatItem.swift */; }; - 8FD244D7200CE25C007EB9CB /* VisitorItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24491200CE25A007EB9CB /* VisitorItem.swift */; }; - 8FD244D8200CE25C007EB9CB /* MessageItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24492200CE25A007EB9CB /* MessageItem.swift */; }; - 8FD244D9200CE25C007EB9CB /* MessageToSend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24493200CE25A007EB9CB /* MessageToSend.swift */; }; - 8FD244DA200CE25C007EB9CB /* SessionParametersListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24494200CE25A007EB9CB /* SessionParametersListener.swift */; }; - 8FD244DB200CE25C007EB9CB /* AccessChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24495200CE25A007EB9CB /* AccessChecker.swift */; }; - 8FD244DC200CE25C007EB9CB /* SQLiteHistoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24496200CE25A007EB9CB /* SQLiteHistoryStorage.swift */; }; - 8FD244DD200CE25C007EB9CB /* HistoryID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24497200CE25A007EB9CB /* HistoryID.swift */; }; - 8FD244DE200CE25C007EB9CB /* HistoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24498200CE25A007EB9CB /* HistoryStorage.swift */; }; - 8FD244DF200CE25C007EB9CB /* MessageHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD24499200CE25A007EB9CB /* MessageHolder.swift */; }; - 8FD244E0200CE25C007EB9CB /* DepartmentImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2449B200CE25B007EB9CB /* DepartmentImpl.swift */; }; - 8FD244E1200CE25C007EB9CB /* OperatorImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2449C200CE25B007EB9CB /* OperatorImpl.swift */; }; - 8FD244E2200CE25C007EB9CB /* MessageStreamImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2449D200CE25B007EB9CB /* MessageStreamImpl.swift */; }; - 8FD244E3200CE25C007EB9CB /* WebimRemoteNotificationImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2449E200CE25B007EB9CB /* WebimRemoteNotificationImpl.swift */; }; - 8FD244E4200CE25C007EB9CB /* MessageImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD2449F200CE25B007EB9CB /* MessageImpl.swift */; }; - 8FD244E5200CE25C007EB9CB /* WebimErrorImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD244A0200CE25B007EB9CB /* WebimErrorImpl.swift */; }; - 8FD244E6200CE25C007EB9CB /* MessageTrackerImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD244A1200CE25B007EB9CB /* MessageTrackerImpl.swift */; }; - 8FD244E7200CE25C007EB9CB /* WebimSessionImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD244A2200CE25B007EB9CB /* WebimSessionImpl.swift */; }; - 8FD244E8200CE25C007EB9CB /* LocationSettingsImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD244A3200CE25B007EB9CB /* LocationSettingsImpl.swift */; }; - 8FD244E9200CE25C007EB9CB /* FatalErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD244A4200CE25B007EB9CB /* FatalErrorHandler.swift */; }; - 8FD244EA200CE25C007EB9CB /* WebimError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD244A5200CE25B007EB9CB /* WebimError.swift */; }; - 8FD244EB200CE25C007EB9CB /* MessageStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD244A6200CE25B007EB9CB /* MessageStream.swift */; }; - 8FD244EC200CE25C007EB9CB /* Webim.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD244A7200CE25B007EB9CB /* Webim.swift */; }; - CE2E681120123DB7004E99EA /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2E681020123DB6004E99EA /* Array.swift */; }; - CE2E681320123DC9004E99EA /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2E681220123DC9004E99EA /* Collection.swift */; }; - CE2E681520123DD0004E99EA /* Int.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2E681420123DD0004E99EA /* Int.swift */; }; - CE2E681720123DD4004E99EA /* UInt32.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2E681620123DD4004E99EA /* UInt32.swift */; }; - CE529807222EA38C00033278 /* HistoryRevisionItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE529806222EA38C00033278 /* HistoryRevisionItem.swift */; }; - CE6A6978220C730F00B11E29 /* FAQItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6A6977220C730F00B11E29 /* FAQItem.swift */; }; - CE6A697A220C731600B11E29 /* FAQ.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6A6979220C731600B11E29 /* FAQ.swift */; }; - CE6A697C220C799300B11E29 /* FAQActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6A697B220C799300B11E29 /* FAQActions.swift */; }; - CE6A697E220C7F3000B11E29 /* FAQClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6A697D220C7F3000B11E29 /* FAQClient.swift */; }; - CE6A6980220C83F900B11E29 /* FAQRequestLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6A697F220C83F900B11E29 /* FAQRequestLoop.swift */; }; - CE6A6982220C968D00B11E29 /* FAQImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6A6981220C968D00B11E29 /* FAQImpl.swift */; }; - CE6A6984220C9BBB00B11E29 /* FAQDestroyer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6A6983220C9BBB00B11E29 /* FAQDestroyer.swift */; }; - CE6A6986220C9DE200B11E29 /* FAQAccessChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6A6985220C9DE200B11E29 /* FAQAccessChecker.swift */; }; - CE6A6988220CA70A00B11E29 /* FAQItemItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6A6987220CA70A00B11E29 /* FAQItemItem.swift */; }; - CE76D61F22108835006A5BF0 /* ExecIfNotDestroyedFAQHandlerExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE76D61E22108834006A5BF0 /* ExecIfNotDestroyedFAQHandlerExecutor.swift */; }; - CE76D6212210A6DC006A5BF0 /* FAQStructure.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE76D6202210A6DC006A5BF0 /* FAQStructure.swift */; }; - CE76D6232210A6F3006A5BF0 /* FAQCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE76D6222210A6F3006A5BF0 /* FAQCategory.swift */; }; - CE86FA95203AF37F00CB9C2D /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FA94203AF37F00CB9C2D /* UIColor.swift */; }; - CE86FAAB203B2A2600CB9C2D /* OperatorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FAAA203B2A2600CB9C2D /* OperatorFactory.swift */; }; - CE86FAAD203B2A4500CB9C2D /* DepartmentFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE86FAAC203B2A4500CB9C2D /* DepartmentFactory.swift */; }; - CEBF03962211D5EE001658D8 /* FAQStructureItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBF03952211D5EE001658D8 /* FAQStructureItem.swift */; }; - CEBF03982211D837001658D8 /* FAQCategoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBF03972211D837001658D8 /* FAQCategoryItem.swift */; }; - CEBF039A2211F070001658D8 /* FAQCategoryInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBF03992211F070001658D8 /* FAQCategoryInfo.swift */; }; - CED72593200E11D900CD1623 /* WebimInternalLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED72592200E11D900CD1623 /* WebimInternalLogger.swift */; }; - CEF33876221C74C700A7EA27 /* FAQCategoryInfoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEF33875221C74C700A7EA27 /* FAQCategoryInfoItem.swift */; }; - D6A45F8B22A13A2400B5BB27 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6A45F8A22A13A2400B5BB27 /* SQLite.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 8FD2427A200CDB18007EB9CB /* WebimClientLibrary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WebimClientLibrary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 8FD2427D200CDB18007EB9CB /* WebimClientLibrary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebimClientLibrary.h; sourceTree = ""; }; - 8FD2445C200CE258007EB9CB /* WebimLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimLogger.swift; sourceTree = ""; }; - 8FD2445D200CE258007EB9CB /* MessageListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageListener.swift; sourceTree = ""; }; - 8FD2445E200CE259007EB9CB /* WebimRemoteNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimRemoteNotification.swift; sourceTree = ""; }; - 8FD2445F200CE259007EB9CB /* WebimSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimSession.swift; sourceTree = ""; }; - 8FD24460200CE259007EB9CB /* Operator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operator.swift; sourceTree = ""; }; - 8FD24461200CE259007EB9CB /* Department.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Department.swift; sourceTree = ""; }; - 8FD24462200CE259007EB9CB /* ProvidedAuthorizationTokenStateListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProvidedAuthorizationTokenStateListener.swift; sourceTree = ""; }; - 8FD24463200CE25A007EB9CB /* MessageTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageTracker.swift; sourceTree = ""; }; - 8FD24464200CE25A007EB9CB /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; }; - 8FD24466200CE25A007EB9CB /* HistoryMetaInformationStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryMetaInformationStorage.swift; sourceTree = ""; }; - 8FD24467200CE25A007EB9CB /* MemoryHistoryStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MemoryHistoryStorage.swift; sourceTree = ""; }; - 8FD24468200CE25A007EB9CB /* InternalErrorListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InternalErrorListener.swift; sourceTree = ""; }; - 8FD24469200CE25A007EB9CB /* MemoryHistoryMetaInformationStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MemoryHistoryMetaInformationStorage.swift; sourceTree = ""; }; - 8FD2446A200CE25A007EB9CB /* ClientSideID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClientSideID.swift; sourceTree = ""; }; - 8FD2446B200CE25A007EB9CB /* WebimActions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimActions.swift; sourceTree = ""; }; - 8FD2446C200CE25A007EB9CB /* MessageComposingHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageComposingHandler.swift; sourceTree = ""; }; - 8FD2446D200CE25A007EB9CB /* WebimInternalError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimInternalError.swift; sourceTree = ""; }; - 8FD2446E200CE25A007EB9CB /* LocationSettingsHolder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationSettingsHolder.swift; sourceTree = ""; }; - 8FD24470200CE25A007EB9CB /* WebimRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimRequest.swift; sourceTree = ""; }; - 8FD24471200CE25A007EB9CB /* WebimClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimClient.swift; sourceTree = ""; }; - 8FD24472200CE25A007EB9CB /* RemoteHistoryProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteHistoryProvider.swift; sourceTree = ""; }; - 8FD24475200CE25A007EB9CB /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; - 8FD24476200CE25A007EB9CB /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; - 8FD24477200CE25A007EB9CB /* MessageFactories.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageFactories.swift; sourceTree = ""; }; - 8FD24478200CE25A007EB9CB /* InternalUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InternalUtils.swift; sourceTree = ""; }; - 8FD24479200CE25A007EB9CB /* CompletionHandlerWrappers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompletionHandlerWrappers.swift; sourceTree = ""; }; - 8FD2447A200CE25A007EB9CB /* AbstractRequestLoop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AbstractRequestLoop.swift; sourceTree = ""; }; - 8FD2447B200CE25A007EB9CB /* DeltaCallback.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeltaCallback.swift; sourceTree = ""; }; - 8FD2447C200CE25A007EB9CB /* ActionRequestLoop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionRequestLoop.swift; sourceTree = ""; }; - 8FD2447D200CE25A007EB9CB /* SessionDestroyer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionDestroyer.swift; sourceTree = ""; }; - 8FD2447E200CE25A007EB9CB /* ProvidedVisitorFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProvidedVisitorFields.swift; sourceTree = ""; }; - 8FD2447F200CE25A007EB9CB /* ExecIfNotDestroyedHandlerExecutor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExecIfNotDestroyedHandlerExecutor.swift; sourceTree = ""; }; - 8FD24480200CE25A007EB9CB /* AuthorizationData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthorizationData.swift; sourceTree = ""; }; - 8FD24481200CE25A007EB9CB /* DeltaRequestLoop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeltaRequestLoop.swift; sourceTree = ""; }; - 8FD24483200CE25A007EB9CB /* OperatorItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorItem.swift; sourceTree = ""; }; - 8FD24484200CE25A007EB9CB /* DepartmentItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DepartmentItem.swift; sourceTree = ""; }; - 8FD24485200CE25A007EB9CB /* RatingItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RatingItem.swift; sourceTree = ""; }; - 8FD24486200CE25A007EB9CB /* VisitSessionStateItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VisitSessionStateItem.swift; sourceTree = ""; }; - 8FD24488200CE25A007EB9CB /* HistoryBeforeResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryBeforeResponse.swift; sourceTree = ""; }; - 8FD24489200CE25A007EB9CB /* HistorySinceResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistorySinceResponse.swift; sourceTree = ""; }; - 8FD2448A200CE25A007EB9CB /* DeltaResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeltaResponse.swift; sourceTree = ""; }; - 8FD2448B200CE25A007EB9CB /* FileParametersItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileParametersItem.swift; sourceTree = ""; }; - 8FD2448C200CE25A007EB9CB /* OnlineStatusItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnlineStatusItem.swift; sourceTree = ""; }; - 8FD2448E200CE25A007EB9CB /* DeltaItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeltaItem.swift; sourceTree = ""; }; - 8FD2448F200CE25A007EB9CB /* FullUpdate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullUpdate.swift; sourceTree = ""; }; - 8FD24490200CE25A007EB9CB /* ChatItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatItem.swift; sourceTree = ""; }; - 8FD24491200CE25A007EB9CB /* VisitorItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VisitorItem.swift; sourceTree = ""; }; - 8FD24492200CE25A007EB9CB /* MessageItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageItem.swift; sourceTree = ""; }; - 8FD24493200CE25A007EB9CB /* MessageToSend.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageToSend.swift; sourceTree = ""; }; - 8FD24494200CE25A007EB9CB /* SessionParametersListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionParametersListener.swift; sourceTree = ""; }; - 8FD24495200CE25A007EB9CB /* AccessChecker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessChecker.swift; sourceTree = ""; }; - 8FD24496200CE25A007EB9CB /* SQLiteHistoryStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteHistoryStorage.swift; sourceTree = ""; }; - 8FD24497200CE25A007EB9CB /* HistoryID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryID.swift; sourceTree = ""; }; - 8FD24498200CE25A007EB9CB /* HistoryStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryStorage.swift; sourceTree = ""; }; - 8FD24499200CE25A007EB9CB /* MessageHolder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHolder.swift; sourceTree = ""; }; - 8FD2449B200CE25B007EB9CB /* DepartmentImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DepartmentImpl.swift; sourceTree = ""; }; - 8FD2449C200CE25B007EB9CB /* OperatorImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorImpl.swift; sourceTree = ""; }; - 8FD2449D200CE25B007EB9CB /* MessageStreamImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageStreamImpl.swift; sourceTree = ""; }; - 8FD2449E200CE25B007EB9CB /* WebimRemoteNotificationImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimRemoteNotificationImpl.swift; sourceTree = ""; }; - 8FD2449F200CE25B007EB9CB /* MessageImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageImpl.swift; sourceTree = ""; }; - 8FD244A0200CE25B007EB9CB /* WebimErrorImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimErrorImpl.swift; sourceTree = ""; }; - 8FD244A1200CE25B007EB9CB /* MessageTrackerImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageTrackerImpl.swift; sourceTree = ""; }; - 8FD244A2200CE25B007EB9CB /* WebimSessionImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimSessionImpl.swift; sourceTree = ""; }; - 8FD244A3200CE25B007EB9CB /* LocationSettingsImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationSettingsImpl.swift; sourceTree = ""; }; - 8FD244A4200CE25B007EB9CB /* FatalErrorHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FatalErrorHandler.swift; sourceTree = ""; }; - 8FD244A5200CE25B007EB9CB /* WebimError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebimError.swift; sourceTree = ""; }; - 8FD244A6200CE25B007EB9CB /* MessageStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageStream.swift; sourceTree = ""; }; - 8FD244A7200CE25B007EB9CB /* Webim.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Webim.swift; sourceTree = ""; }; - 8FD244ED200CE3E4007EB9CB /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; - CE2E681020123DB6004E99EA /* Array.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = ""; }; - CE2E681220123DC9004E99EA /* Collection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Collection.swift; sourceTree = ""; }; - CE2E681420123DD0004E99EA /* Int.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Int.swift; sourceTree = ""; }; - CE2E681620123DD4004E99EA /* UInt32.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UInt32.swift; sourceTree = ""; }; - CE529806222EA38C00033278 /* HistoryRevisionItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryRevisionItem.swift; sourceTree = ""; }; - CE6A6977220C730F00B11E29 /* FAQItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FAQItem.swift; sourceTree = ""; }; - CE6A6979220C731600B11E29 /* FAQ.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FAQ.swift; sourceTree = ""; }; - CE6A697B220C799300B11E29 /* FAQActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQActions.swift; sourceTree = ""; }; - CE6A697D220C7F3000B11E29 /* FAQClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQClient.swift; sourceTree = ""; }; - CE6A697F220C83F900B11E29 /* FAQRequestLoop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQRequestLoop.swift; sourceTree = ""; }; - CE6A6981220C968D00B11E29 /* FAQImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQImpl.swift; sourceTree = ""; }; - CE6A6983220C9BBB00B11E29 /* FAQDestroyer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQDestroyer.swift; sourceTree = ""; }; - CE6A6985220C9DE200B11E29 /* FAQAccessChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQAccessChecker.swift; sourceTree = ""; }; - CE6A6987220CA70A00B11E29 /* FAQItemItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQItemItem.swift; sourceTree = ""; }; - CE76D61E22108834006A5BF0 /* ExecIfNotDestroyedFAQHandlerExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExecIfNotDestroyedFAQHandlerExecutor.swift; sourceTree = ""; }; - CE76D6202210A6DC006A5BF0 /* FAQStructure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQStructure.swift; sourceTree = ""; }; - CE76D6222210A6F3006A5BF0 /* FAQCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQCategory.swift; sourceTree = ""; }; - CE86FA94203AF37F00CB9C2D /* UIColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; - CE86FAAA203B2A2600CB9C2D /* OperatorFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorFactory.swift; sourceTree = ""; }; - CE86FAAC203B2A4500CB9C2D /* DepartmentFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DepartmentFactory.swift; sourceTree = ""; }; - CEBF03952211D5EE001658D8 /* FAQStructureItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQStructureItem.swift; sourceTree = ""; }; - CEBF03972211D837001658D8 /* FAQCategoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQCategoryItem.swift; sourceTree = ""; }; - CEBF03992211F070001658D8 /* FAQCategoryInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQCategoryInfo.swift; sourceTree = ""; }; - CED72592200E11D900CD1623 /* WebimInternalLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebimInternalLogger.swift; path = Backend/WebimInternalLogger.swift; sourceTree = ""; }; - CEF33875221C74C700A7EA27 /* FAQCategoryInfoItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQCategoryInfoItem.swift; sourceTree = ""; }; - D6A45F8A22A13A2400B5BB27 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 8FD24276200CDB18007EB9CB /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D6A45F8B22A13A2400B5BB27 /* SQLite.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 8FD24270200CDB18007EB9CB = { - isa = PBXGroup; - children = ( - 8FD2427C200CDB18007EB9CB /* WebimClientLibrary */, - 8FD2427B200CDB18007EB9CB /* Products */, - 8FD24457200CE029007EB9CB /* Frameworks */, - ); - sourceTree = ""; - }; - 8FD2427B200CDB18007EB9CB /* Products */ = { - isa = PBXGroup; - children = ( - 8FD2427A200CDB18007EB9CB /* WebimClientLibrary.framework */, - ); - name = Products; - sourceTree = ""; - }; - 8FD2427C200CDB18007EB9CB /* WebimClientLibrary */ = { - isa = PBXGroup; - children = ( - 8FD2427D200CDB18007EB9CB /* WebimClientLibrary.h */, - 8FD24465200CE25A007EB9CB /* Backend */, - 8FD2449A200CE25B007EB9CB /* Implementation */, - 8FD24461200CE259007EB9CB /* Department.swift */, - 8FD244A4200CE25B007EB9CB /* FatalErrorHandler.swift */, - CE6A6979220C731600B11E29 /* FAQ.swift */, - CE6A6977220C730F00B11E29 /* FAQItem.swift */, - 8FD24464200CE25A007EB9CB /* Message.swift */, - 8FD2445D200CE258007EB9CB /* MessageListener.swift */, - 8FD244A6200CE25B007EB9CB /* MessageStream.swift */, - CED72592200E11D900CD1623 /* WebimInternalLogger.swift */, - 8FD24463200CE25A007EB9CB /* MessageTracker.swift */, - 8FD24460200CE259007EB9CB /* Operator.swift */, - 8FD24462200CE259007EB9CB /* ProvidedAuthorizationTokenStateListener.swift */, - 8FD244A7200CE25B007EB9CB /* Webim.swift */, - 8FD244A5200CE25B007EB9CB /* WebimError.swift */, - 8FD2445C200CE258007EB9CB /* WebimLogger.swift */, - 8FD2445E200CE259007EB9CB /* WebimRemoteNotification.swift */, - 8FD2445F200CE259007EB9CB /* WebimSession.swift */, - 8FD244ED200CE3E4007EB9CB /* Info.plist */, - CE76D6202210A6DC006A5BF0 /* FAQStructure.swift */, - CE76D6222210A6F3006A5BF0 /* FAQCategory.swift */, - CEBF03992211F070001658D8 /* FAQCategoryInfo.swift */, - ); - path = WebimClientLibrary; - sourceTree = ""; - }; - 8FD24457200CE029007EB9CB /* Frameworks */ = { - isa = PBXGroup; - children = ( - D6A45F8A22A13A2400B5BB27 /* SQLite.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 8FD24465200CE25A007EB9CB /* Backend */ = { - isa = PBXGroup; - children = ( - 8FD24482200CE25A007EB9CB /* Items */, - 8FD24473200CE25A007EB9CB /* Utilities */, - 8FD24466200CE25A007EB9CB /* HistoryMetaInformationStorage.swift */, - 8FD24467200CE25A007EB9CB /* MemoryHistoryStorage.swift */, - 8FD24468200CE25A007EB9CB /* InternalErrorListener.swift */, - 8FD24469200CE25A007EB9CB /* MemoryHistoryMetaInformationStorage.swift */, - 8FD2446A200CE25A007EB9CB /* ClientSideID.swift */, - 8FD2446B200CE25A007EB9CB /* WebimActions.swift */, - 8FD2446C200CE25A007EB9CB /* MessageComposingHandler.swift */, - 8FD2446D200CE25A007EB9CB /* WebimInternalError.swift */, - 8FD2446E200CE25A007EB9CB /* LocationSettingsHolder.swift */, - 8FD24470200CE25A007EB9CB /* WebimRequest.swift */, - 8FD24471200CE25A007EB9CB /* WebimClient.swift */, - 8FD24472200CE25A007EB9CB /* RemoteHistoryProvider.swift */, - 8FD2447A200CE25A007EB9CB /* AbstractRequestLoop.swift */, - 8FD2447B200CE25A007EB9CB /* DeltaCallback.swift */, - 8FD2447C200CE25A007EB9CB /* ActionRequestLoop.swift */, - 8FD2447D200CE25A007EB9CB /* SessionDestroyer.swift */, - 8FD2447E200CE25A007EB9CB /* ProvidedVisitorFields.swift */, - 8FD2447F200CE25A007EB9CB /* ExecIfNotDestroyedHandlerExecutor.swift */, - 8FD24480200CE25A007EB9CB /* AuthorizationData.swift */, - 8FD24481200CE25A007EB9CB /* DeltaRequestLoop.swift */, - 8FD24493200CE25A007EB9CB /* MessageToSend.swift */, - 8FD24494200CE25A007EB9CB /* SessionParametersListener.swift */, - 8FD24495200CE25A007EB9CB /* AccessChecker.swift */, - 8FD24496200CE25A007EB9CB /* SQLiteHistoryStorage.swift */, - 8FD24497200CE25A007EB9CB /* HistoryID.swift */, - 8FD24498200CE25A007EB9CB /* HistoryStorage.swift */, - 8FD24499200CE25A007EB9CB /* MessageHolder.swift */, - CE6A697B220C799300B11E29 /* FAQActions.swift */, - CE6A697D220C7F3000B11E29 /* FAQClient.swift */, - CE6A697F220C83F900B11E29 /* FAQRequestLoop.swift */, - CE6A6983220C9BBB00B11E29 /* FAQDestroyer.swift */, - CE6A6985220C9DE200B11E29 /* FAQAccessChecker.swift */, - CE76D61E22108834006A5BF0 /* ExecIfNotDestroyedFAQHandlerExecutor.swift */, - ); - path = Backend; - sourceTree = ""; - }; - 8FD24473200CE25A007EB9CB /* Utilities */ = { - isa = PBXGroup; - children = ( - 8FD24474200CE25A007EB9CB /* Extensions */, - 8FD24479200CE25A007EB9CB /* CompletionHandlerWrappers.swift */, - CE86FAAC203B2A4500CB9C2D /* DepartmentFactory.swift */, - 8FD24478200CE25A007EB9CB /* InternalUtils.swift */, - 8FD24477200CE25A007EB9CB /* MessageFactories.swift */, - CE86FAAA203B2A2600CB9C2D /* OperatorFactory.swift */, - ); - path = Utilities; - sourceTree = ""; - }; - 8FD24474200CE25A007EB9CB /* Extensions */ = { - isa = PBXGroup; - children = ( - CE2E681020123DB6004E99EA /* Array.swift */, - CE2E681220123DC9004E99EA /* Collection.swift */, - 8FD24475200CE25A007EB9CB /* Dictionary.swift */, - CE2E681420123DD0004E99EA /* Int.swift */, - 8FD24476200CE25A007EB9CB /* String.swift */, - CE86FA94203AF37F00CB9C2D /* UIColor.swift */, - CE2E681620123DD4004E99EA /* UInt32.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - 8FD24482200CE25A007EB9CB /* Items */ = { - isa = PBXGroup; - children = ( - 8FD24483200CE25A007EB9CB /* OperatorItem.swift */, - 8FD24484200CE25A007EB9CB /* DepartmentItem.swift */, - 8FD24485200CE25A007EB9CB /* RatingItem.swift */, - 8FD24486200CE25A007EB9CB /* VisitSessionStateItem.swift */, - 8FD24487200CE25A007EB9CB /* Responses */, - 8FD2448B200CE25A007EB9CB /* FileParametersItem.swift */, - 8FD2448C200CE25A007EB9CB /* OnlineStatusItem.swift */, - 8FD2448D200CE25A007EB9CB /* Deltas */, - 8FD24490200CE25A007EB9CB /* ChatItem.swift */, - 8FD24491200CE25A007EB9CB /* VisitorItem.swift */, - 8FD24492200CE25A007EB9CB /* MessageItem.swift */, - CE6A6987220CA70A00B11E29 /* FAQItemItem.swift */, - CEBF03952211D5EE001658D8 /* FAQStructureItem.swift */, - CEBF03972211D837001658D8 /* FAQCategoryItem.swift */, - CEF33875221C74C700A7EA27 /* FAQCategoryInfoItem.swift */, - CE529806222EA38C00033278 /* HistoryRevisionItem.swift */, - ); - path = Items; - sourceTree = ""; - }; - 8FD24487200CE25A007EB9CB /* Responses */ = { - isa = PBXGroup; - children = ( - 8FD24488200CE25A007EB9CB /* HistoryBeforeResponse.swift */, - 8FD24489200CE25A007EB9CB /* HistorySinceResponse.swift */, - 8FD2448A200CE25A007EB9CB /* DeltaResponse.swift */, - ); - path = Responses; - sourceTree = ""; - }; - 8FD2448D200CE25A007EB9CB /* Deltas */ = { - isa = PBXGroup; - children = ( - 8FD2448E200CE25A007EB9CB /* DeltaItem.swift */, - 8FD2448F200CE25A007EB9CB /* FullUpdate.swift */, - ); - path = Deltas; - sourceTree = ""; - }; - 8FD2449A200CE25B007EB9CB /* Implementation */ = { - isa = PBXGroup; - children = ( - 8FD2449B200CE25B007EB9CB /* DepartmentImpl.swift */, - 8FD244A3200CE25B007EB9CB /* LocationSettingsImpl.swift */, - 8FD2449F200CE25B007EB9CB /* MessageImpl.swift */, - 8FD2449D200CE25B007EB9CB /* MessageStreamImpl.swift */, - 8FD244A1200CE25B007EB9CB /* MessageTrackerImpl.swift */, - 8FD2449C200CE25B007EB9CB /* OperatorImpl.swift */, - 8FD244A0200CE25B007EB9CB /* WebimErrorImpl.swift */, - 8FD2449E200CE25B007EB9CB /* WebimRemoteNotificationImpl.swift */, - 8FD244A2200CE25B007EB9CB /* WebimSessionImpl.swift */, - CE6A6981220C968D00B11E29 /* FAQImpl.swift */, - ); - path = Implementation; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 8FD24277200CDB18007EB9CB /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 8FD2428B200CDB18007EB9CB /* WebimClientLibrary.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 8FD24279200CDB18007EB9CB /* WebimClientLibrary */ = { - isa = PBXNativeTarget; - buildConfigurationList = 8FD2428E200CDB18007EB9CB /* Build configuration list for PBXNativeTarget "WebimClientLibrary" */; - buildPhases = ( - 8FD24275200CDB18007EB9CB /* Sources */, - 8FD24276200CDB18007EB9CB /* Frameworks */, - 8FD24277200CDB18007EB9CB /* Headers */, - 8FD24278200CDB18007EB9CB /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = WebimClientLibrary; - productName = WebimClientLibrary; - productReference = 8FD2427A200CDB18007EB9CB /* WebimClientLibrary.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 8FD24271200CDB18007EB9CB /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0920; - ORGANIZATIONNAME = "Sergey Maslov"; - TargetAttributes = { - 8FD24279200CDB18007EB9CB = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 0920; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = 8FD24274200CDB18007EB9CB /* Build configuration list for PBXProject "WebimClientLibrary" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 8FD24270200CDB18007EB9CB; - productRefGroup = 8FD2427B200CDB18007EB9CB /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 8FD24279200CDB18007EB9CB /* WebimClientLibrary */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 8FD24278200CDB18007EB9CB /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 8FD24275200CDB18007EB9CB /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CE86FAAB203B2A2600CB9C2D /* OperatorFactory.swift in Sources */, - CE6A6988220CA70A00B11E29 /* FAQItemItem.swift in Sources */, - 8FD244B5200CE25C007EB9CB /* ClientSideID.swift in Sources */, - 8FD244B6200CE25C007EB9CB /* WebimActions.swift in Sources */, - CE86FAAD203B2A4500CB9C2D /* DepartmentFactory.swift in Sources */, - 8FD244D2200CE25C007EB9CB /* FileParametersItem.swift in Sources */, - 8FD244BC200CE25C007EB9CB /* WebimClient.swift in Sources */, - CE529807222EA38C00033278 /* HistoryRevisionItem.swift in Sources */, - 8FD244BD200CE25C007EB9CB /* RemoteHistoryProvider.swift in Sources */, - 8FD244AF200CE25C007EB9CB /* MessageTracker.swift in Sources */, - CEF33876221C74C700A7EA27 /* FAQCategoryInfoItem.swift in Sources */, - 8FD244E9200CE25C007EB9CB /* FatalErrorHandler.swift in Sources */, - 8FD244C6200CE25C007EB9CB /* SessionDestroyer.swift in Sources */, - 8FD244E2200CE25C007EB9CB /* MessageStreamImpl.swift in Sources */, - 8FD244AE200CE25C007EB9CB /* ProvidedAuthorizationTokenStateListener.swift in Sources */, - 8FD244CD200CE25C007EB9CB /* RatingItem.swift in Sources */, - 8FD244C1200CE25C007EB9CB /* InternalUtils.swift in Sources */, - 8FD244C3200CE25C007EB9CB /* AbstractRequestLoop.swift in Sources */, - CE6A697C220C799300B11E29 /* FAQActions.swift in Sources */, - CE6A6978220C730F00B11E29 /* FAQItem.swift in Sources */, - 8FD244C0200CE25C007EB9CB /* MessageFactories.swift in Sources */, - CE2E681720123DD4004E99EA /* UInt32.swift in Sources */, - 8FD244C4200CE25C007EB9CB /* DeltaCallback.swift in Sources */, - 8FD244DB200CE25C007EB9CB /* AccessChecker.swift in Sources */, - 8FD244E6200CE25C007EB9CB /* MessageTrackerImpl.swift in Sources */, - 8FD244DC200CE25C007EB9CB /* SQLiteHistoryStorage.swift in Sources */, - CE86FA95203AF37F00CB9C2D /* UIColor.swift in Sources */, - 8FD244D4200CE25C007EB9CB /* DeltaItem.swift in Sources */, - CE76D6232210A6F3006A5BF0 /* FAQCategory.swift in Sources */, - 8FD244D3200CE25C007EB9CB /* OnlineStatusItem.swift in Sources */, - 8FD244BF200CE25C007EB9CB /* String.swift in Sources */, - 8FD244CB200CE25C007EB9CB /* OperatorItem.swift in Sources */, - CE6A6986220C9DE200B11E29 /* FAQAccessChecker.swift in Sources */, - 8FD244A8200CE25C007EB9CB /* WebimLogger.swift in Sources */, - 8FD244B0200CE25C007EB9CB /* Message.swift in Sources */, - 8FD244D6200CE25C007EB9CB /* ChatItem.swift in Sources */, - 8FD244E3200CE25C007EB9CB /* WebimRemoteNotificationImpl.swift in Sources */, - 8FD244CA200CE25C007EB9CB /* DeltaRequestLoop.swift in Sources */, - CE6A6984220C9BBB00B11E29 /* FAQDestroyer.swift in Sources */, - CE6A697E220C7F3000B11E29 /* FAQClient.swift in Sources */, - 8FD244EB200CE25C007EB9CB /* MessageStream.swift in Sources */, - 8FD244AB200CE25C007EB9CB /* WebimSession.swift in Sources */, - 8FD244E7200CE25C007EB9CB /* WebimSessionImpl.swift in Sources */, - 8FD244B2200CE25C007EB9CB /* MemoryHistoryStorage.swift in Sources */, - 8FD244DF200CE25C007EB9CB /* MessageHolder.swift in Sources */, - 8FD244AC200CE25C007EB9CB /* Operator.swift in Sources */, - 8FD244E1200CE25C007EB9CB /* OperatorImpl.swift in Sources */, - CEBF03962211D5EE001658D8 /* FAQStructureItem.swift in Sources */, - 8FD244B8200CE25C007EB9CB /* WebimInternalError.swift in Sources */, - 8FD244DA200CE25C007EB9CB /* SessionParametersListener.swift in Sources */, - 8FD244D0200CE25C007EB9CB /* HistorySinceResponse.swift in Sources */, - 8FD244C5200CE25C007EB9CB /* ActionRequestLoop.swift in Sources */, - 8FD244C9200CE25C007EB9CB /* AuthorizationData.swift in Sources */, - CE6A6982220C968D00B11E29 /* FAQImpl.swift in Sources */, - CE6A6980220C83F900B11E29 /* FAQRequestLoop.swift in Sources */, - 8FD244BE200CE25C007EB9CB /* Dictionary.swift in Sources */, - 8FD244C8200CE25C007EB9CB /* ExecIfNotDestroyedHandlerExecutor.swift in Sources */, - CEBF03982211D837001658D8 /* FAQCategoryItem.swift in Sources */, - CEBF039A2211F070001658D8 /* FAQCategoryInfo.swift in Sources */, - CE2E681120123DB7004E99EA /* Array.swift in Sources */, - 8FD244D8200CE25C007EB9CB /* MessageItem.swift in Sources */, - 8FD244AA200CE25C007EB9CB /* WebimRemoteNotification.swift in Sources */, - 8FD244B9200CE25C007EB9CB /* LocationSettingsHolder.swift in Sources */, - 8FD244B7200CE25C007EB9CB /* MessageComposingHandler.swift in Sources */, - 8FD244A9200CE25C007EB9CB /* MessageListener.swift in Sources */, - 8FD244E0200CE25C007EB9CB /* DepartmentImpl.swift in Sources */, - 8FD244EC200CE25C007EB9CB /* Webim.swift in Sources */, - 8FD244BB200CE25C007EB9CB /* WebimRequest.swift in Sources */, - 8FD244DE200CE25C007EB9CB /* HistoryStorage.swift in Sources */, - 8FD244E4200CE25C007EB9CB /* MessageImpl.swift in Sources */, - CED72593200E11D900CD1623 /* WebimInternalLogger.swift in Sources */, - 8FD244CC200CE25C007EB9CB /* DepartmentItem.swift in Sources */, - CE76D61F22108835006A5BF0 /* ExecIfNotDestroyedFAQHandlerExecutor.swift in Sources */, - 8FD244D5200CE25C007EB9CB /* FullUpdate.swift in Sources */, - 8FD244B4200CE25C007EB9CB /* MemoryHistoryMetaInformationStorage.swift in Sources */, - 8FD244CE200CE25C007EB9CB /* VisitSessionStateItem.swift in Sources */, - 8FD244C7200CE25C007EB9CB /* ProvidedVisitorFields.swift in Sources */, - 8FD244CF200CE25C007EB9CB /* HistoryBeforeResponse.swift in Sources */, - 8FD244DD200CE25C007EB9CB /* HistoryID.swift in Sources */, - 8FD244C2200CE25C007EB9CB /* CompletionHandlerWrappers.swift in Sources */, - CE76D6212210A6DC006A5BF0 /* FAQStructure.swift in Sources */, - 8FD244B1200CE25C007EB9CB /* HistoryMetaInformationStorage.swift in Sources */, - 8FD244D7200CE25C007EB9CB /* VisitorItem.swift in Sources */, - CE2E681320123DC9004E99EA /* Collection.swift in Sources */, - 8FD244EA200CE25C007EB9CB /* WebimError.swift in Sources */, - 8FD244E8200CE25C007EB9CB /* LocationSettingsImpl.swift in Sources */, - 8FD244AD200CE25C007EB9CB /* Department.swift in Sources */, - 8FD244E5200CE25C007EB9CB /* WebimErrorImpl.swift in Sources */, - 8FD244B3200CE25C007EB9CB /* InternalErrorListener.swift in Sources */, - CE6A697A220C731600B11E29 /* FAQ.swift in Sources */, - 8FD244D9200CE25C007EB9CB /* MessageToSend.swift in Sources */, - 8FD244D1200CE25C007EB9CB /* DeltaResponse.swift in Sources */, - CE2E681520123DD0004E99EA /* Int.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 8FD2428C200CDB18007EB9CB /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 8FD2428D200CDB18007EB9CB /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 8FD2428F200CDB18007EB9CB /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = ru.webim.WebimClientLibrary; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 8FD24290200CDB18007EB9CB /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = ru.webim.WebimClientLibrary; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 8FD24274200CDB18007EB9CB /* Build configuration list for PBXProject "WebimClientLibrary" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 8FD2428C200CDB18007EB9CB /* Debug */, - 8FD2428D200CDB18007EB9CB /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 8FD2428E200CDB18007EB9CB /* Build configuration list for PBXNativeTarget "WebimClientLibrary" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 8FD2428F200CDB18007EB9CB /* Debug */, - 8FD24290200CDB18007EB9CB /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 8FD24271200CDB18007EB9CB /* Project object */; -} diff --git a/ios/libs/Webim/WebimClientLibrary.xcodeproj/xcshareddata/xcschemes/WebimClientLibrary.xcscheme b/ios/libs/Webim/WebimClientLibrary.xcodeproj/xcshareddata/xcschemes/WebimClientLibrary.xcscheme deleted file mode 100755 index d8d23a3..0000000 --- a/ios/libs/Webim/WebimClientLibrary.xcodeproj/xcshareddata/xcschemes/WebimClientLibrary.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/AbstractRequestLoop.swift b/ios/libs/Webim/WebimClientLibrary/Backend/AbstractRequestLoop.swift deleted file mode 100755 index 740ee99..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/AbstractRequestLoop.swift +++ /dev/null @@ -1,278 +0,0 @@ -// -// AbstractRequestLoop.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that handles HTTP-request sending by SDK. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -class AbstractRequestLoop { - - // MARK: - Constants - enum HTTPMethods: String { - case get = "GET" - case post = "POST" - } - enum ResponseFields: String { - case data = "data" - case error = "error" - } - enum DataFields: String { - case error = "error" - } - enum UnknownError: Error { - case interrupted - case serverError - } - - // MARK: - Properties - private let pauseCondition = NSCondition() - private let pauseLock = NSRecursiveLock() - var paused = true - var running = true - private var currentDataTask: URLSessionDataTask? - - // MARK: - Methods - - func start() { - preconditionFailure("This method must be overridden!") - } - - func pause() { - pauseLock.lock() - paused = true - pauseLock.unlock() - } - - func resume() { - pauseLock.lock() - paused = false - pauseCondition.broadcast() - pauseLock.unlock() - } - - func stop() { - running = false - resume() - - if let currentDataTask = currentDataTask { - currentDataTask.cancel() - } - } - - func isRunning() -> Bool { - return running - } - - func perform(request: URLRequest) throws -> Data { - var requestWithUesrAngent = request - requestWithUesrAngent.setValue("iOS: Webim-Client (\(UIDevice.current.model); \(UIDevice.current.systemVersion)); Bundle ID and version: \(Bundle.main.bundleIdentifier ?? "none") \(Bundle.main.infoDictionary?["CFBundleVersion"] ?? "none")", forHTTPHeaderField: "User-Agent") - - var errorCounter = 0 - var lastHTTPCode = -1 - - while isRunning() { - let startTime = Date() - var httpCode = 0 - - let semaphore = DispatchSemaphore(value: 0) - var receivedData: Data? = nil - - log(request: requestWithUesrAngent) - - let dataTask = URLSession.shared.dataTask(with: requestWithUesrAngent) { [weak self] data, response, error in - guard let `self` = `self` else { - return - } - - if let response = response { - httpCode = (response as! HTTPURLResponse).statusCode - } - - if error != nil { - semaphore.signal() - - // Error log. - var webimLoggerEntry = "Webim response:\n" - + "URL – " + requestWithUesrAngent.url!.absoluteString - if let httpBody = requestWithUesrAngent.httpBody { - if let dataString = String(data: httpBody, - encoding: .utf8) { - webimLoggerEntry += ("\nParameters – " + dataString) - } - } - webimLoggerEntry += "\nHTTP code – " + String(httpCode) - webimLoggerEntry += "\nError – " + error!.localizedDescription - WebimInternalLogger.shared.log(entry: webimLoggerEntry) - - if let error = error as NSError?, !(error.domain == NSURLErrorDomain && error.code == NSURLErrorNotConnectedToInternet) { - return - } - } - - if let data = data { - receivedData = data - - var webimLoggerEntry = "Webim response:\n" - + "URL – " + requestWithUesrAngent.url!.absoluteString - if let httpBody = requestWithUesrAngent.httpBody { - if let dataString = String(data: httpBody, - encoding: .utf8) { - webimLoggerEntry += ("\nParameters – " + dataString) - } - } - webimLoggerEntry += "\nHTTP code – " + String(httpCode) - webimLoggerEntry += self.encode(responseData: data) - WebimInternalLogger.shared.log(entry: webimLoggerEntry, verbosityLevel: .DEBUG) - } - - semaphore.signal() - } - currentDataTask = dataTask - dataTask.resume() - - _ = semaphore.wait(timeout: .distantFuture) - currentDataTask = nil - blockUntilPaused() - - if !isRunning() { - break - } - - if httpCode == 0 { - usleep(useconds_t(10_000_000.0)) - continue - } - - if let receivedData = receivedData, - httpCode == 200 { - return receivedData - } - - if httpCode == 413 { // Request Entity Too Large - throw SendFileError.FILE_SIZE_EXCEEDED - } - if httpCode == 415 { // Unsupported Media Type - throw SendFileError.FILE_TYPE_NOT_ALLOWED - } - - if httpCode == lastHTTPCode { - var parametersString: String? - if let httpBody = requestWithUesrAngent.httpBody { - parametersString = String(data: httpBody, - encoding: .utf8) - } - WebimInternalLogger.shared.log(entry: "Request \(requestWithUesrAngent.url!.absoluteString)" - + "\(parametersString ?? "") " - + "failed with HTTP code: \(httpCode).", - verbosityLevel: .WARNING) - } - - errorCounter += 1 - - lastHTTPCode = httpCode - - // If request wasn't successful and error isn't fatal, wait some time and try again. - if (errorCounter >= 5) { - // If there was more that five tries stop trying. - throw UnknownError.serverError - } - let sleepTime = Double(errorCounter) as TimeInterval - let timeElapsed = Date().timeIntervalSince(startTime) - if Double(timeElapsed) < Double(sleepTime) { - let remainingTime = Double(sleepTime) - Double(timeElapsed) - usleep(useconds_t(remainingTime * 1_000_000.0)) - } - } - - throw UnknownError.interrupted - } - - func handleRequestLoop(error: UnknownError) { - switch error { - case .interrupted: - WebimInternalLogger.shared.log(entry: "Request interrupted (it's OK if WebimSession object was destroyed).", - verbosityLevel: .DEBUG) - - break - case .serverError: - WebimInternalLogger.shared.log(entry: "Request failed with server error.") - - break - } - } - - // MARK: Private methods - - private func blockUntilPaused() { - pauseCondition.lock() - while paused { - pauseCondition.wait() - } - pauseCondition.unlock() - } - - private func log(request: URLRequest) { - var webimLoggerEntry = "Webim request:\n" - webimLoggerEntry += ("HTTP method - " + request.httpMethod! + "\n") - webimLoggerEntry += ("URL – " + request.url!.absoluteString) - if let httpBody = request.httpBody { - if let dataString = String(data: httpBody, - encoding: .utf8) { - webimLoggerEntry += ("\nParameters – " + dataString) - } - } - - WebimInternalLogger.shared.log(entry: webimLoggerEntry, - verbosityLevel: .INFO) - } - - private func encode(responseData: Data) -> String { - do { - let jsonResponse = try JSONSerialization.jsonObject(with: responseData, - options: .mutableContainers) - let prettyPrintedJSONResponse = try JSONSerialization.data(withJSONObject: jsonResponse, - options: .prettyPrinted) - - if let dataResponseString = String(data: prettyPrintedJSONResponse, - encoding: .utf8) { - return "\nJSON:\n" + dataResponseString - } - } catch { - if let dataResponseString = String(data: responseData, - encoding: .utf8) { - return "\nData:\n" + dataResponseString - } - } - - return "" - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/AccessChecker.swift b/ios/libs/Webim/WebimClientLibrary/Backend/AccessChecker.swift deleted file mode 100755 index 7e9cd42..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/AccessChecker.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// AccessChecker.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.09.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that checks if session methods are called in appropriate conditions. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -class AccessChecker { - - // MARK: - Properties - let thread: Thread - let sessionDestroyer: SessionDestroyer - - // MARK: - Initialization - init(thread: Thread, - sessionDestroyer: SessionDestroyer) { - self.thread = thread - self.sessionDestroyer = sessionDestroyer - } - - // MARK: - Methods - func checkAccess() throws { - guard thread == Thread.current else { - throw AccessError.INVALID_THREAD - } - - guard !sessionDestroyer.isDestroyed() else { - throw AccessError.INVALID_SESSION - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/ActionRequestLoop.swift b/ios/libs/Webim/WebimClientLibrary/Backend/ActionRequestLoop.swift deleted file mode 100755 index 87c33c5..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/ActionRequestLoop.swift +++ /dev/null @@ -1,407 +0,0 @@ -// -// ActionRequestLoop.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 14.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that handles HTTP-requests sended by WebimClientLibrary with visitor requested actions (e.g. sending messages, operator rating, chat closing etc.). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -class ActionRequestLoop: AbstractRequestLoop { - - // MARK: - Properties - private let completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor - private let internalErrorListener: InternalErrorListener - var operationQueue: OperationQueue? - private var authorizationData: AuthorizationData? - - - // MARK: - Initialization - init(completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor, - internalErrorListener: InternalErrorListener) { - self.completionHandlerExecutor = completionHandlerExecutor - self.internalErrorListener = internalErrorListener - } - - // MARK: - Methods - - override func start() { - guard operationQueue == nil else { - return - } - - operationQueue = OperationQueue() - operationQueue?.maxConcurrentOperationCount = 1 - operationQueue?.qualityOfService = .userInitiated - } - - override func stop() { - super.stop() - - operationQueue?.cancelAllOperations() - operationQueue = nil - } - - func set(authorizationData: AuthorizationData?) { - self.authorizationData = authorizationData - } - - func enqueue(request: WebimRequest) { - operationQueue?.addOperation { [weak self] in - guard let `self` = self else { - return - } - - if self.authorizationData == nil { - do { - try self.authorizationData = self.awaitForNewAuthorizationData(withLastAuthorizationData: nil) - } catch { - return - } - } - let usedAuthorizationData = self.authorizationData! - - if !self.isRunning() { - return - } - - var parameterDictionary = request.getPrimaryData() - parameterDictionary[WebimActions.Parameter.pageID.rawValue] = usedAuthorizationData.getPageID() - parameterDictionary[WebimActions.Parameter.authorizationToken.rawValue] = usedAuthorizationData.getAuthorizationToken() - let parametersString = parameterDictionary.stringFromHTTPParameters() - - var url: URL? - var urlRequest: URLRequest? - let httpMethod = request.getHTTPMethod() - if httpMethod == .get { - url = URL(string: (request.getBaseURLString() + "?" + parametersString)) - urlRequest = URLRequest(url: url!) - } else { // POST - if let fileName = request.getFileName(), - let mimeType = request.getMimeType(), - let fileData = request.getFileData(), - let boundaryString = request.getBoundaryString() { - // Assuming that ready HTTP body is passed only for multipart requests. - url = URL(string: (request.getBaseURLString())) - urlRequest = URLRequest(url: url!) - urlRequest!.httpBody = self.createHTTPBody(filename: fileName, - mimeType: mimeType, - fileData: fileData, - boundaryString: boundaryString, - primaryData: parameterDictionary) - } else { - // For URL encoded requests. - url = URL(string: request.getBaseURLString()) - urlRequest = URLRequest(url: url!) - urlRequest!.httpBody = parametersString.data(using: .utf8) - } - - // Assuming that content type field is always exists when it is POST request, and does not when request is of GET type. - urlRequest!.setValue(request.getContentType(), - forHTTPHeaderField: "Content-Type") - } - - urlRequest!.httpMethod = httpMethod.rawValue - - do { - let data = try self.perform(request: urlRequest!) - if let dataJSON = try? JSONSerialization.jsonObject(with: data) as? [String: Any] { - if let error = dataJSON?[AbstractRequestLoop.ResponseFields.error.rawValue] as? String { - switch error { - case WebimInternalError.reinitializationRequired.rawValue: - do { - try self.authorizationData = self.awaitForNewAuthorizationData(withLastAuthorizationData: nil) - } catch { - return - } - self.enqueue(request: request) - - break - case WebimInternalError.fileSizeExceeded.rawValue, - WebimInternalError.fileTypeNotAllowed.rawValue, - WebimInternalError.uploadedFileNotFound.rawValue, - WebimInternalError.notAllowedMimeType.rawValue, - WebimInternalError.notMatchingMagicNumbers.rawValue: - self.handleSendFile(error: error, - ofRequest: request) - - break - case WebimInternalError.wrongArgumentValue.rawValue: - self.handleWrongArgumentValueError(ofRequest: request) - - break - case WebimInternalError.noChat.rawValue, - WebimInternalError.operatorNotInChat.rawValue: - self.handleRateOperator(error: error, - ofRequest: request) - - break - case WebimInternalError.messageNotFound.rawValue, - WebimInternalError.notAllowed.rawValue, - WebimInternalError.messageNotOwned.rawValue: - self.handleDeleteMessage(error: error, - ofRequest: request) - break - default: - self.running = false - - self.completionHandlerExecutor.execute(task: DispatchWorkItem { - self.internalErrorListener.on(error: error) - }) - - break - } - - return - } - - // Some internal errors can be received inside "error" field inside "data" field. - if let dataDictionary = dataJSON?[AbstractRequestLoop.ResponseFields.data.rawValue] as? [String: Any], - let errorString = dataDictionary[AbstractRequestLoop.DataFields.error.rawValue] as? String { - self.handleDataMessage(error: errorString, - ofRequest: request) - } - - if let completionHandler = request.getCompletionHandler() { - self.completionHandlerExecutor.execute(task: DispatchWorkItem { - do { - try completionHandler(data) - } catch { - WebimInternalLogger.shared.log(entry: "Error executing callback on receiver data: \(String(data: data, encoding: .utf8) ?? "unreadable data").", - verbosityLevel: .WARNING) - } - - }) - } - - self.handleClientCompletionHandlerOf(request: request) - } else { - WebimInternalLogger.shared.log(entry: "Error de-serializing server response: \(String(data: data, encoding: .utf8) ?? "unreadable data")", - verbosityLevel: .WARNING) - } - } catch let sendFileError as SendFileError { - // SendFileErrors are generated from HTTP code. - if let sendFileCompletionHandler = request.getSendFileCompletionHandler() { - sendFileCompletionHandler.onFailure(messageID: request.getMessageID()!, - error: sendFileError) - } - } catch let unknownError as UnknownError { - self.handleRequestLoop(error: unknownError) - } catch { - WebimInternalLogger.shared.log(entry: "Request failed with unknown error: \(request.getBaseURLString()).", - verbosityLevel: .WARNING) - } - } - } - - // MARK: Private methods - - private func createHTTPBody(filename: String, - mimeType: String, - fileData: Data, - boundaryString: String, - primaryData: [String: Any]) -> Data { - - let boundaryStart = "--\(boundaryString)\r\n" - let contentDispositionString = "Content-Disposition: form-data; name=\"webim_upload_file\"; filename=\"\(filename)\"\r\n" - let contentTypeString = "Content-Type: \(mimeType)\r\n\r\n" - let boundaryEnd = "--\(boundaryString)--\r\n" - - var requestBodyData = Data() - for (key, value) in primaryData { - requestBodyData.append("--\(boundaryString)\r\n".data(using: .utf8)!) - requestBodyData.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!) - requestBodyData.append("\(value)\r\n".data(using: .utf8)!) - } - requestBodyData.append(boundaryStart.data(using: .utf8)!) - requestBodyData.append(contentDispositionString.data(using: .utf8)!) - requestBodyData.append(contentTypeString.data(using: .utf8)!) - requestBodyData.append(fileData) - requestBodyData.append("\r\n".data(using: .utf8)!) - requestBodyData.append(boundaryEnd.data(using: .utf8)!) - - return requestBodyData - } - - private func awaitForNewAuthorizationData(withLastAuthorizationData lastAuthorizationData: AuthorizationData?) throws -> AuthorizationData { - while isRunning() - && (lastAuthorizationData == authorizationData) { - usleep(100_000) // 0.1 s. - } - - if authorizationData == nil { - // Interrupted request. - throw AbstractRequestLoop.UnknownError.interrupted - } - - return authorizationData! - } - - private func handleDataMessage(error errorString: String, - ofRequest webimRequest: WebimRequest) { - if let dataMessageCompletionHandler = webimRequest.getDataMessageCompletionHandler() { - completionHandlerExecutor.execute(task: DispatchWorkItem { - dataMessageCompletionHandler.onFailure(messageID: webimRequest.getMessageID()!, - error: ActionRequestLoop.convertToPublic(dataMessageErrorString: errorString)) - }) - } - } - - private func handleRateOperator(error errorString: String, - ofRequest webimRequest: WebimRequest) { - if let rateOperatorCompletionhandler = webimRequest.getRateOperatorCompletionHandler() { - completionHandlerExecutor.execute(task: DispatchWorkItem { - let rateOperatorError: RateOperatorError - if errorString == WebimInternalError.noChat.rawValue { - rateOperatorError = .NO_CHAT - } else { - rateOperatorError = .WRONG_OPERATOR_ID - } - - rateOperatorCompletionhandler.onFailure(error: rateOperatorError) - }) - } - } - - private func handleEditMessage(error errorString: String, - ofRequest webimRequest: WebimRequest) { - if let editMessageCompletionHandler = webimRequest.getEditMessageCompletionHandler() { - completionHandlerExecutor.execute(task: DispatchWorkItem { - let editMessageError: EditMessageError - switch errorString { - case WebimInternalError.messageEmpty.rawValue: - editMessageError = .MESSAGE_EMPTY - break - case WebimInternalError.maxMessageLengthExceeded.rawValue: - editMessageError = .MAX_LENGTH_EXCEEDED - break - case WebimInternalError.notAllowed.rawValue: - editMessageError = .NOT_ALLOWED - break - case WebimInternalError.messageNotOwned.rawValue: - editMessageError = .MESSAGE_NOT_OWNED - break - case WebimInternalError.wrongMessageKind.rawValue: - editMessageError = .WRONG_MESSAGE_KIND - break - default: - editMessageError = .UNKNOWN - } - - editMessageCompletionHandler.onFailure(messageID: webimRequest.getMessageID()!, - error: editMessageError) - }) - } - } - - private func handleDeleteMessage(error errorString: String, - ofRequest webimRequest: WebimRequest) { - if let deleteMessageCompletionHandler = webimRequest.getDeleteMessageCompletionHandler() { - completionHandlerExecutor.execute(task: DispatchWorkItem { - let deleteMessageError: DeleteMessageError - switch errorString { - case WebimInternalError.messageNotFound.rawValue: - deleteMessageError = .MESSAGE_NOT_FOUND - break - case WebimInternalError.notAllowed.rawValue: - deleteMessageError = .NOT_ALLOWED - break - case WebimInternalError.messageNotOwned.rawValue: - deleteMessageError = .MESSAGE_NOT_OWNED - break - default: - deleteMessageError = .UNKNOWN - } - - deleteMessageCompletionHandler.onFailure(messageID: webimRequest.getMessageID()!, - error: deleteMessageError) - }) - } - } - - private func handleSendFile(error errorString: String, - ofRequest webimRequest: WebimRequest) { - if let sendFileCompletionHandler = webimRequest.getSendFileCompletionHandler() { - completionHandlerExecutor.execute(task: DispatchWorkItem { - let sendFileError: SendFileError - switch errorString { - case WebimInternalError.fileSizeExceeded.rawValue: - sendFileError = .FILE_SIZE_EXCEEDED - break - case WebimInternalError.fileTypeNotAllowed.rawValue: - sendFileError = .FILE_TYPE_NOT_ALLOWED - break - case WebimInternalError.uploadedFileNotFound.rawValue: - sendFileError = .UPLOADED_FILE_NOT_FOUND - break - default: - sendFileError = .UNKNOWN - } - - sendFileCompletionHandler.onFailure(messageID: webimRequest.getMessageID()!, - error: sendFileError) - }) - } - } - - private func handleWrongArgumentValueError(ofRequest webimRequest: WebimRequest) { - WebimInternalLogger.shared.log(entry: "Request \(webimRequest.getBaseURLString()) with parameters \(webimRequest.getPrimaryData().stringFromHTTPParameters()) failed with error \(WebimInternalError.wrongArgumentValue.rawValue)", - verbosityLevel: .WARNING) - } - - private func handleClientCompletionHandlerOf(request: WebimRequest) { - completionHandlerExecutor.execute(task: DispatchWorkItem { - request.getDataMessageCompletionHandler()?.onSuccess(messageID: request.getMessageID()!) - request.getSendFileCompletionHandler()?.onSuccess(messageID: request.getMessageID()!) - request.getRateOperatorCompletionHandler()?.onSuccess() - request.getDeleteMessageCompletionHandler()?.onSuccess(messageID: request.getMessageID()!) - request.getEditMessageCompletionHandler()?.onSuccess(messageID: request.getMessageID()!) - }) - } - - private static func convertToPublic(dataMessageErrorString: String) -> DataMessageError { - switch dataMessageErrorString { - case WebimInternalError.quotedMessageCannotBeReplied.rawValue: - return .QUOTED_MESSAGE_CANNOT_BE_REPLIED - case WebimInternalError.quotedMessageCorruptedID.rawValue: - return .QUOTED_MESSAGE_WRONG_ID - case WebimInternalError.quotedMessageFromAnotherVisitor.rawValue: - return .QUOTED_MESSAGE_FROM_ANOTHER_VISITOR - case WebimInternalError.quotedMessageMultipleID.rawValue: - return .QUOTED_MESSAGE_MULTIPLE_IDS - case WebimInternalError.quotedMessageNotFound.rawValue: - return .QUOTED_MESSAGE_WRONG_ID - case WebimInternalError.quotedMessageRequiredArgumentsMissing.rawValue: - return .QUOTED_MESSAGE_REQUIRED_ARGUMENTS_MISSING - default: - return .UNKNOWN - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/AuthorizationData.swift b/ios/libs/Webim/WebimClientLibrary/Backend/AuthorizationData.swift deleted file mode 100755 index 2edb709..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/AuthorizationData.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// AuthorizationData.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Struct that encapsulates session authorization data. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct AuthorizationData { - - // MARK: - Properties - private var pageID: String - private var authorizationToken: String - - - // MARK: - Initialization - init?(pageID: String?, - authorizationToken: String?) { - guard let pageID = pageID, - let authorizationToken = authorizationToken else { - return nil - } - - self.pageID = pageID - self.authorizationToken = authorizationToken - } - - - // MARK: - Methods - - func getPageID() -> String { - return pageID - } - - func getAuthorizationToken() -> String? { - return authorizationToken - } - -} - -// MARK: - Equatable -extension AuthorizationData: Equatable { - - static func == (lhs: AuthorizationData, - rhs: AuthorizationData) -> Bool { - return (lhs.pageID == rhs.pageID) - && (lhs.authorizationToken == rhs.authorizationToken) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/ClientSideID.swift b/ios/libs/Webim/WebimClientLibrary/Backend/ClientSideID.swift deleted file mode 100755 index 98ce576..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/ClientSideID.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// StringID.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class which is responsible for generating random IDs (e.g. for sending messages). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct ClientSideID { - - // MARK: - Constants - enum StringSize: Int { - case clientSideID = 32 - } - enum StringSymbols: NSString { - case uid = "abcdef0123456789" - } - - // MARK: - Methods - - static func generateClientSideID() -> String { - return generateRandomString(ofCharactersNumber: StringSize.clientSideID.rawValue) - } - - static func generateRandomString(ofCharactersNumber numberOfCharacters: Int) -> String { - let letters: NSString = StringSymbols.uid.rawValue - let length = UInt32(letters.length) - - var randomString = "" - - for _ in 0 ..< numberOfCharacters { - let random = arc4random_uniform(length) - var nextChar = letters.character(at: Int(random)) - randomString = randomString + (NSString(characters: &nextChar, - length: 1) as String) - } - - return randomString - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/DeltaCallback.swift b/ios/libs/Webim/WebimClientLibrary/Backend/DeltaCallback.swift deleted file mode 100755 index c873d80..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/DeltaCallback.swift +++ /dev/null @@ -1,395 +0,0 @@ -// -// DeltaCallback.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 12.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that handles server response when SDK requests chat updates. - - seealso: - `DeltaResponse` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class DeltaCallback { - - // MARK: - Properties - private let currentChatMessageMapper: MessageMapper - private var currentChat: ChatItem? - private let readBeforeTimestampString = "read_before_timestamp" - private weak var messageHolder: MessageHolder? - private weak var messageStream: MessageStreamImpl? - private weak var historyPoller: HistoryPoller? - - // MARK: - Initialization - init(currentChatMessageMapper: MessageMapper) { - self.currentChatMessageMapper = currentChatMessageMapper - } - - // MARK: - Methods - - func set(messageStream: MessageStreamImpl, - messageHolder: MessageHolder, - historyPoller: HistoryPoller) { - self.messageStream = messageStream - self.messageHolder = messageHolder - self.historyPoller = historyPoller - } - - func process(deltaList: [DeltaItem]) { - for delta in deltaList { - guard let deltaType = delta.getDeltaType() else { - continue - } - - switch deltaType { - case .chat: - handleChatUpdateBy(delta: delta) - - break - case .chatMessage: - handleChatMessageUpdateBy(delta: delta) - - break - case .chatOperator: - handleChatOperatorUpdateBy(delta: delta) - - break - case .chatOperatorTyping: - handleChatOperatorTypingUpdateBy(delta: delta) - - break - case .chatReadByVisitor: - handleChatReadByVisitorUpdateBy(delta: delta) - - break - case .chatState: - handleChatStateUpdateBy(delta: delta) - - break - case .chatUnreadByOperatorTimestamp: - handleUnreadByOperatorTimestampUpdateBy(delta: delta) - - break - case .departmentList: - handleDepartmentListUpdateBy(delta: delta) - - break - case .historyRevision: - handleHistoryRevisionUpdateBy(delta: delta) - - break - case .operatorRate: - handleOperatorRateUpdateBy(delta: delta) - - break - case .unreadByVisitor: - handleUnreadByVisitorUpdateBy(delta: delta) - - break - case .visitSessionState: - handleVisitSessionStateUpdateBy(delta: delta) - - break - case .chatMessageRead: - handleMessageRead(delta: delta) - break - default: - // Not supported delta type. - - break - } - } - } - - func process(fullUpdate: FullUpdate) { - if let visitSessionState = fullUpdate.getState() { - messageStream?.set(visitSessionState: (VisitSessionStateItem(rawValue: visitSessionState) ?? .unknown)) - } - - if let departments = fullUpdate.getDepartments() { - messageStream?.onReceiving(departmentItemList: departments) - } - - currentChat = fullUpdate.getChat() - - messageStream?.changingChatStateOf(chat: currentChat) - messageStream?.saveLocationSettingsOn(fullUpdate: fullUpdate) - - if let revision = fullUpdate.getHistoryRevision() { - historyPoller?.set(hasHistoryRevision: true) - historyPoller?.requestHistory(since: revision) - } - - if let onlineStatusString = fullUpdate.getOnlineStatus() { - if let onlineStatus = OnlineStatusItem(rawValue: onlineStatusString) { - messageStream?.onOnlineStatusChanged(to: onlineStatus) - } - } - - if currentChat != nil { - for messageItem in (currentChat?.getMessages())! { - if let message = currentChatMessageMapper.map(message: messageItem) { - if (message.getType() == MessageType.FILE_FROM_VISITOR || message.getType() != MessageType.VISITOR) && message.isReadByOperator() { - let time = message.getTimeInMicrosecond() - if time > Int64(UserDefaults.standard.integer(forKey: readBeforeTimestampString)) { - UserDefaults.standard.set(time, forKey: readBeforeTimestampString) - historyPoller?.updateReadBeforeTimestamp(timestamp: time) - } - } - } - } - } else { - UserDefaults.standard.set(-1, forKey: readBeforeTimestampString) - } - } - - // MARK: Private methods - - private func handleChatUpdateBy(delta: DeltaItem) { - guard delta.getEvent() == .update, - let deltaData = delta.getData() as? [String : Any?] else { - return - } - - currentChat = ChatItem(jsonDictionary: deltaData) - messageStream?.changingChatStateOf(chat: currentChat) - } - - private func handleChatMessageUpdateBy(delta: DeltaItem) { - let deltaEvent = delta.getEvent() - let deltaID = delta.getID() - - if deltaEvent == .delete { - if currentChat != nil { - var currentChatMessages = currentChat!.getMessages() - for (currentChatMessageIndex, currentChatMessage) in currentChatMessages.enumerated() { - if currentChatMessage.getID() == deltaID { // Deleted message ID is passed as delta ID. - currentChatMessages.remove(at: currentChatMessageIndex) - currentChat!.set(messages: currentChatMessages) - - break - } - } - } - - messageHolder?.deletedMessageWith(id: deltaID) - } else { - guard let deltaData = delta.getData() as? [String : Any] else { - return - } - - let messageItem = MessageItem(jsonDictionary: deltaData) - let message = currentChatMessageMapper.map(message: messageItem) - if deltaEvent == .add { - var isNewMessage = false - if currentChat != nil && !currentChat!.getMessages().contains(messageItem) { - currentChat?.add(message: messageItem) - isNewMessage = true - } - - if isNewMessage && message != nil { - messageHolder?.receive(newMessage: message!) - } - - } else if deltaEvent == .update { - if currentChat != nil { - var currentChatMessages = currentChat!.getMessages() - for (currentChatMessageIndex, currentChatMessage) in currentChatMessages.enumerated() { - if currentChatMessage.getID() == messageItem.getID() { - currentChatMessages[currentChatMessageIndex] = messageItem - - break - } - } - } - - if message != nil { - messageHolder?.changed(message: message!) - } - } - } - } - - - private func handleMessageRead(delta: DeltaItem) { - let deltaEvent = delta.getEvent() - let deltaId = delta.getID() - - if let isRead = delta.getData() as? Bool, deltaEvent == .update { - if currentChat != nil { - var currentChatMessages = currentChat!.getMessages() - for (currentChatMessageIndex, currentChatMessage) in currentChatMessages.enumerated() { - if currentChatMessage.getID() == deltaId { - currentChatMessage.setRead(read: isRead) - guard let message = currentChatMessageMapper.map(message: currentChatMessage) else { - return - } - currentChatMessages[currentChatMessageIndex] = currentChatMessage - messageHolder?.changed(message: message) - let time = message.getTimeInMicrosecond() - if time > UserDefaults.standard.integer(forKey: "readBeforeTimestampString") { - UserDefaults.standard.set(time, forKey: "readBeforeTimestampString") - historyPoller?.updateReadBeforeTimestamp(timestamp: time) - } - break - } - } - } - } - } - - private func handleChatOperatorUpdateBy(delta: DeltaItem) { - guard delta.getEvent() == .update, - let deltaData = delta.getData() as? [String : Any] else { - return - } - - if let operatorItem = OperatorItem(jsonDictionary: deltaData) { - currentChat?.set(operator: operatorItem) - - messageStream?.changingChatStateOf(chat: currentChat) - } - } - - private func handleChatOperatorTypingUpdateBy(delta: DeltaItem) { - guard delta.getEvent() == .update, - let operatorTyping = delta.getData() as? Bool else { - return - } - - currentChat?.set(operatorTyping: operatorTyping) - messageStream?.changingChatStateOf(chat: currentChat) - } - - private func handleChatReadByVisitorUpdateBy(delta: DeltaItem) { - guard let readByVisitor = delta.getData() as? Bool, - delta.getEvent() == .update else { - return - } - - currentChat?.set(readByVisitor: readByVisitor) - - if readByVisitor { - currentChat?.set(unreadByVisitorTimestamp: nil) - currentChat?.set(unreadByVisitorMessageCount: 0) - messageStream?.set(unreadByVisitorTimestamp: nil) - messageStream?.set(unreadByVisitorMessageCount: 0) - } - } - - private func handleChatStateUpdateBy(delta: DeltaItem) { - guard delta.getEvent() == .update, - let chatState = delta.getData() as? String else { - return - } - - currentChat?.set(state: ChatItem.ChatItemState(withType: chatState)) - - messageStream?.changingChatStateOf(chat: currentChat) - } - - private func handleUnreadByOperatorTimestampUpdateBy(delta: DeltaItem) { - guard delta.getEvent() == .update else { - return - } - - var unreadByOperatorTimestamp: Double? - if delta.getData() != nil { - unreadByOperatorTimestamp = delta.getData() as? Double - } - currentChat?.set(unreadByOperatorTimestamp: unreadByOperatorTimestamp) - messageStream?.set(unreadByOperatorTimestamp: (unreadByOperatorTimestamp != nil ? Date(timeIntervalSince1970: unreadByOperatorTimestamp!) : nil)) - } - - private func handleDepartmentListUpdateBy(delta: DeltaItem) { - guard let deltaData = delta.getData() as? [Any] else { - return - } - - var departmentItems = [DepartmentItem]() - for departmentData in deltaData { - if let departmentDictionary = departmentData as? [String: Any] { - if let deparmentItem = DepartmentItem(jsonDictionary: departmentDictionary) { - departmentItems.append(deparmentItem) - } - } - } - - messageStream?.onReceiving(departmentItemList: departmentItems) - } - - private func handleHistoryRevisionUpdateBy(delta: DeltaItem) { - guard let deltaData = delta.getData() as? [String: Any] else { - return - } - - let revisionItem = HistoryRevisionItem(jsonDictionary: deltaData) - historyPoller?.requestHistory(since: revisionItem.getRevision()) - } - - private func handleOperatorRateUpdateBy(delta: DeltaItem) { - guard let deltaData = delta.getData() as? [String: Any] else { - return - } - - if let rating = RatingItem(jsonDictionary: deltaData) { - if delta.getEvent() == .update { - currentChat?.set(rating: rating, - toOperatorWithId: rating.getOperatorID()) - } - } - } - - private func handleUnreadByVisitorUpdateBy(delta: DeltaItem) { - guard delta.getEvent() == .update, - let unreadByVisitorUpdate = delta.getData() as? [String: Any], - let unreadByVisitorMessageConut = unreadByVisitorUpdate[DeltaItem.UnreadByVisitorField.messageCount.rawValue] as? Int, - let unreadByVisitorTimestamp = unreadByVisitorUpdate[DeltaItem.UnreadByVisitorField.timestamp.rawValue] as? Double else { - return - } - currentChat?.set(unreadByVisitorMessageCount: unreadByVisitorMessageConut) - messageStream?.set(unreadByVisitorTimestamp: Date(timeIntervalSince1970: unreadByVisitorTimestamp)) - messageStream?.set(unreadByVisitorMessageCount: unreadByVisitorMessageConut) - } - - private func handleVisitSessionStateUpdateBy(delta: DeltaItem) { - guard let sessionState = delta.getData() as? String else { - return - } - - if sessionState == VisitSessionStateItem.offlineMessage.rawValue { - messageStream?.set(onlineStatus: .offline) - messageStream?.getWebimActions().closeChat() - } - - if delta.getEvent() == .update { - messageStream?.set(visitSessionState: (VisitSessionStateItem(rawValue: sessionState) ?? .unknown)) - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/DeltaRequestLoop.swift b/ios/libs/Webim/WebimClientLibrary/Backend/DeltaRequestLoop.swift deleted file mode 100755 index 2f8b84d..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/DeltaRequestLoop.swift +++ /dev/null @@ -1,388 +0,0 @@ -// -// DeltaRequestLoop.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 16.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that handles HTTP-requests sending by SDK with internal requested actions (initialization and chat updates). - - seealso: - `DeltaCallback` - `DeltaResponse` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -class DeltaRequestLoop: AbstractRequestLoop { - - // MARK: - Properties - private static var providedAuthenticationTokenErrorCount = 0 - private let appVersion: String? - private let baseURL: String - private let completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor - private let deltaCallback: DeltaCallback - private let deviceID: String - private let internalErrorListener: InternalErrorListener - private let sessionParametersListener: SessionParametersListener? - private let title: String - var authorizationData: AuthorizationData? - var queue: DispatchQueue? - var since: Int64 = 0 - private var deviceToken: String? - private var location: String - private var providedAuthenticationToken: String? - private weak var providedAuthenticationTokenStateListener: ProvidedAuthorizationTokenStateListener? - private var sessionID: String? - private var visitorFieldsJSONString: String? - private var visitorJSONString: String? - private var prechat: String? - - // MARK: - Initialization - init(deltaCallback: DeltaCallback, - completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor, - sessionParametersListener: SessionParametersListener?, - internalErrorListener: InternalErrorListener, - baseURL: String, - title: String, - location: String, - appVersion: String?, - visitorFieldsJSONString: String?, - providedAuthenticationTokenStateListener: ProvidedAuthorizationTokenStateListener?, - providedAuthenticationToken: String?, - deviceID: String, - deviceToken: String?, - visitorJSONString: String?, - sessionID: String?, - prechat:String?, - authorizationData: AuthorizationData?) { - self.deltaCallback = deltaCallback - self.completionHandlerExecutor = completionHandlerExecutor - self.sessionParametersListener = sessionParametersListener - self.internalErrorListener = internalErrorListener - self.baseURL = baseURL - self.title = title - self.location = location - self.appVersion = appVersion - self.visitorFieldsJSONString = visitorFieldsJSONString - self.deviceID = deviceID - self.deviceToken = deviceToken - self.visitorJSONString = visitorJSONString - self.sessionID = sessionID - self.authorizationData = authorizationData - self.providedAuthenticationTokenStateListener = providedAuthenticationTokenStateListener - self.providedAuthenticationToken = providedAuthenticationToken - self.prechat = prechat - } - - // MARK: - Methods - - override func start() { - guard queue == nil else { - return - } - - queue = DispatchQueue(label: "ru.webim.DeltaDispatchQueue") - queue!.async { - self.run() - } - } - - override func stop() { - super.stop() - - queue = nil - } - - func set(deviceToken: String) { - self.deviceToken = deviceToken - } - - func change(location: String) throws { - self.location = location - - authorizationData = nil - since = 0 - - requestInitialization() - } - - func getAuthorizationData() -> AuthorizationData? { - return authorizationData - } - - func run() { - while isRunning() { - if authorizationData != nil && since != 0 { - requestDelta() - } else { - requestInitialization() - } - } - } - - func requestInitialization() { - let url = URL(string: getDeltaServerURLString() + "?" + getInitializationParameterString()) - var request = URLRequest(url: url!) - request.httpMethod = AbstractRequestLoop.HTTPMethods.get.rawValue - - do { - let data = try perform(request: request) - if let dataJSON = try? JSONSerialization.jsonObject(with: data) as! [String: Any] { - if let error = dataJSON[AbstractRequestLoop.ResponseFields.error.rawValue] as? String { - handleInitialization(error: error) - } else { - DeltaRequestLoop.providedAuthenticationTokenErrorCount = 0 - - let deltaResponse = DeltaResponse(jsonDictionary: dataJSON) - - if let deltaList = deltaResponse.getDeltaList() { - if deltaList.count > 0 { - handleIncorrectServerAnswer() - - return - } - } - - guard let fullUpdate = deltaResponse.getFullUpdate() else { - handleIncorrectServerAnswer() - - return - } - - if let since = deltaResponse.getRevision() { - self.since = since - } - - process(fullUpdate: fullUpdate) - } - } else { - WebimInternalLogger.shared.log(entry: "Error de-serializing server response: \(String(data: data, encoding: .utf8) ?? "unreadable data").", - verbosityLevel: .WARNING) - } - } catch let unknownError as UnknownError { - handleRequestLoop(error: unknownError) - } catch { - WebimInternalLogger.shared.log(entry: "Request failed with unknown error: \(error.localizedDescription)", - verbosityLevel: .WARNING) - } - } - - func requestDelta() { - let url = URL(string: getDeltaServerURLString() + "?" + getDeltaParameterString()) - var request = URLRequest(url: url!) - request.httpMethod = AbstractRequestLoop.HTTPMethods.get.rawValue - - do { - let data = try perform(request: request) - if let dataJSON = try? JSONSerialization.jsonObject(with: data) as! [String: Any] { - if let error = dataJSON[AbstractRequestLoop.ResponseFields.error.rawValue] as? String { - handleDeltaRequest(error: error) - } else { - let deltaResponse = DeltaResponse(jsonDictionary: dataJSON) - - guard let revision = deltaResponse.getRevision() else { - // Delta timeout. - return - } - since = revision - - if let fullUpdate = deltaResponse.getFullUpdate() { - completionHandlerExecutor.execute(task: DispatchWorkItem { - self.process(fullUpdate: fullUpdate) - }) - } else if let deltaList = deltaResponse.getDeltaList() { - if deltaList.count > 0 { - completionHandlerExecutor.execute(task: DispatchWorkItem { - self.deltaCallback.process(deltaList: deltaList) - }) - } - } - } - } else { - WebimInternalLogger.shared.log(entry: "Error de-serializing server response: \(String(data: data, encoding: .utf8) ?? "unreadable data").", - verbosityLevel: .WARNING) - } - } catch let unknownError as UnknownError { - handleRequestLoop(error: unknownError) - } catch { - WebimInternalLogger.shared.log(entry: "Request failed with unknown error: \(error.localizedDescription).", - verbosityLevel: .WARNING) - } - } - - // MARK: Private methods - - private func getDeltaServerURLString() -> String { - return (baseURL + WebimActions.ServerPathSuffix.getDelta.rawValue) - } - - private func getInitializationParameterString() -> String { - var parameterDictionary = [WebimActions.Parameter.deviceID.rawValue: deviceID, - WebimActions.Parameter.event.rawValue: WebimActions.Event.initialization.rawValue, - WebimActions.Parameter.location.rawValue: location, - WebimActions.Parameter.platform.rawValue: WebimActions.Platform.ios.rawValue, - WebimActions.Parameter.respondImmediately.rawValue: String(1), // true - WebimActions.Parameter.since.rawValue: String(0), - WebimActions.Parameter.title.rawValue: title] as [String: Any] - if let appVersion = appVersion { - parameterDictionary[WebimActions.Parameter.applicationVersion.rawValue] = appVersion - } - if let deviceToken = deviceToken { - parameterDictionary[WebimActions.Parameter.deviceToken.rawValue] = deviceToken - } - if let sessionID = sessionID { - parameterDictionary[WebimActions.Parameter.visitSessionID.rawValue] = sessionID - } - if let visitorJSONString = visitorJSONString { - parameterDictionary[WebimActions.Parameter.visitor.rawValue] = visitorJSONString - } - if let visitorFieldsJSONString = visitorFieldsJSONString { - parameterDictionary[WebimActions.Parameter.visitorExt.rawValue] = visitorFieldsJSONString - } - if let providedAuthenticationToken = providedAuthenticationToken { - parameterDictionary[WebimActions.Parameter.providedAuthenticationToken.rawValue] = providedAuthenticationToken - } - if let prechat = prechat { - parameterDictionary[WebimActions.Parameter.prechat.rawValue] = prechat - } - - return parameterDictionary.stringFromHTTPParameters() - } - - private func getDeltaParameterString() -> String { - let currentTimestamp = Int64(CFAbsoluteTimeGetCurrent() * 1000) - var parameterDictionary = [WebimActions.Parameter.since.rawValue: String(since), - WebimActions.Parameter.timestamp.rawValue: String(currentTimestamp)] as [String: Any] - if let authorizationData = authorizationData { - parameterDictionary[WebimActions.Parameter.pageID.rawValue] = authorizationData.getPageID() - parameterDictionary[WebimActions.Parameter.authorizationToken.rawValue] = authorizationData.getAuthorizationToken() - } - - return parameterDictionary.stringFromHTTPParameters() - } - - private func sleepBetweenInitializationAttempts() { - authorizationData = nil - since = 0 - - usleep(1_000_000) // 1s - } - - private func handleIncorrectServerAnswer() { - WebimInternalLogger.shared.log(entry: "Incorrect server answer while requesting initialization.", - verbosityLevel: .DEBUG) - - usleep(1_000_000) // 1s - } - - private func handleInitialization(error: String) { - switch error { - case WebimInternalError.reinitializationRequired.rawValue: - handleReinitializationRequiredError() - - break - case WebimInternalError.providedAuthenticationTokenNotFound.rawValue: - handleProvidedAuthenticationTokenNotFoundError() - - break - default: - running = false - - completionHandlerExecutor.execute(task: DispatchWorkItem { - self.internalErrorListener.on(error: error) - }) - - break - } - } - - private func handleDeltaRequest(error: String) { - if error == WebimInternalError.reinitializationRequired.rawValue { - handleReinitializationRequiredError() - } else { - completionHandlerExecutor.execute(task: DispatchWorkItem { - self.internalErrorListener.on(error: error) - }) - } - } - - private func handleReinitializationRequiredError() { - authorizationData = nil - since = 0 - } - - private func handleProvidedAuthenticationTokenNotFoundError() { - DeltaRequestLoop.providedAuthenticationTokenErrorCount += 1 - - if DeltaRequestLoop.providedAuthenticationTokenErrorCount < 5 { - sleepBetweenInitializationAttempts() - } else { - providedAuthenticationTokenStateListener?.update(providedAuthorizationToken: providedAuthenticationToken!) - - DeltaRequestLoop.providedAuthenticationTokenErrorCount = 0 - - sleepBetweenInitializationAttempts() - } - } - - private func process(fullUpdate: FullUpdate) { - let visitorJSONString = fullUpdate.getVisitorJSONString() - let sessionID = fullUpdate.getSessionID() - let authorizationData = AuthorizationData(pageID: fullUpdate.getPageID(), - authorizationToken: fullUpdate.getAuthorizationToken()) - - let isNecessaryToUpdateVisitorFieldJSONString = (self.visitorFieldsJSONString == nil) - || (self.visitorFieldsJSONString != visitorFieldsJSONString) - let isNecessaryToUpdateSessionID = (self.sessionID == nil) - || (self.sessionID != sessionID) - let isNecessaryToUpdateAuthorizationData = (self.authorizationData == nil) - || ((self.authorizationData?.getPageID() != fullUpdate.getPageID()) - || (self.authorizationData?.getAuthorizationToken() != fullUpdate.getAuthorizationToken())) - - if (isNecessaryToUpdateVisitorFieldJSONString - || isNecessaryToUpdateSessionID) - || isNecessaryToUpdateAuthorizationData { - self.visitorJSONString = visitorJSONString - self.sessionID = sessionID - self.authorizationData = authorizationData - - DispatchQueue.global(qos: .background).async { [weak self] in - guard let `self` = self else { - return - } - - self.sessionParametersListener?.onSessionParametersChanged(visitorFieldsJSONString: self.visitorJSONString!, - sessionID: self.sessionID!, - authorizationData: self.authorizationData!) - } - } - - completionHandlerExecutor.execute(task: DispatchWorkItem { - self.deltaCallback.process(fullUpdate: fullUpdate) - }) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/ExecIfNotDestroyedFAQHandlerExecutor.swift b/ios/libs/Webim/WebimClientLibrary/Backend/ExecIfNotDestroyedFAQHandlerExecutor.swift deleted file mode 100755 index 8eb4480..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/ExecIfNotDestroyedFAQHandlerExecutor.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// ExecIfNotDestroyedFAQHandlerExecutor.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates asynchronous callbacks calling. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class ExecIfNotDestroyedFAQHandlerExecutor { - - // MARK: - Properties - private let faqDestroyer: FAQDestroyer - private let queue: DispatchQueue - - // MARK: - Initialization - init(faqDestroyer: FAQDestroyer, - queue: DispatchQueue) { - self.faqDestroyer = faqDestroyer - self.queue = queue - } - - // MARK: - Methods - func execute(task: DispatchWorkItem) { - if !faqDestroyer.isDestroyed() { - queue.async { - if !self.faqDestroyer.isDestroyed() { - task.perform() - } - } - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/ExecIfNotDestroyedHandlerExecutor.swift b/ios/libs/Webim/WebimClientLibrary/Backend/ExecIfNotDestroyedHandlerExecutor.swift deleted file mode 100755 index b716fe7..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/ExecIfNotDestroyedHandlerExecutor.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// ExecIfNotDestroyedHandlerExecutor.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.09.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates asynchronous callbacks calling. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class ExecIfNotDestroyedHandlerExecutor { - - // MARK: - Properties - private let sessionDestroyer: SessionDestroyer - private let queue: DispatchQueue - - // MARK: - Initialization - init(sessionDestroyer: SessionDestroyer, - queue: DispatchQueue) { - self.sessionDestroyer = sessionDestroyer - self.queue = queue - } - - // MARK: - Methods - func execute(task: DispatchWorkItem) { - if !sessionDestroyer.isDestroyed() { - queue.async { - if !self.sessionDestroyer.isDestroyed() { - task.perform() - } - } - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/FAQAccessChecker.swift b/ios/libs/Webim/WebimClientLibrary/Backend/FAQAccessChecker.swift deleted file mode 100755 index 93ab9ac..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/FAQAccessChecker.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// AccessChecker.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.09.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that checks if FAQ methods are called in appropriate conditions. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -class FAQAccessChecker { - - // MARK: - Properties - let thread: Thread - let faqDestroyer: FAQDestroyer - - // MARK: - Initialization - init(thread: Thread, - faqDestroyer: FAQDestroyer) { - self.thread = thread - self.faqDestroyer = faqDestroyer - } - - // MARK: - Methods - func checkAccess() throws { - guard thread == Thread.current else { - throw FAQAccessError.INVALID_THREAD - } - - guard !faqDestroyer.isDestroyed() else { - throw FAQAccessError.INVALID_FAQ - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/FAQActions.swift b/ios/libs/Webim/WebimClientLibrary/Backend/FAQActions.swift deleted file mode 100755 index 103ec96..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/FAQActions.swift +++ /dev/null @@ -1,96 +0,0 @@ -// -// FAQActions.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -class FAQActions { - - // MARK: - Constants - enum Parameter: String { - case itemId = "itemid" - case categoryId = "categoryid" - } - enum ServerPathSuffix: String { - case item = "/services/faq/v1/item" - case category = "/services/faq/v1/category" - case structure = "/services/faq/v1/structure" - } - - // MARK: - Properties - private let baseURL: String - private let faqRequestLoop: FAQRequestLoop - - // MARK: - Initialization - init(baseURL: String, - faqRequestLoop: FAQRequestLoop) { - self.baseURL = baseURL - self.faqRequestLoop = faqRequestLoop - } - - // MARK: - Methods - - func getItem(itemId: String, - completion: @escaping (_ faqItem: Data?) throws -> ()) { - let dataToPost = [Parameter.itemId.rawValue: itemId] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.item.rawValue - - faqRequestLoop.enqueue(request: WebimRequest(httpMethod: .get, - primaryData: dataToPost, - baseURLString: urlString, - faqItemRequestCompletionHandler: completion)) - } - - func getCategory(categoryId: Int, - completion: @escaping (_ faqCategory: Data?) throws -> ()) { - let dataToPost = [Parameter.categoryId.rawValue: String(categoryId)] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.category.rawValue - - faqRequestLoop.enqueue(request: WebimRequest(httpMethod: .get, - primaryData: dataToPost, - baseURLString: urlString, - faqCategoryRequestCompletionHandler: completion)) - } - - func getStructure(categoryId: Int, - completion: @escaping (_ faqStructure: Data?) throws -> ()) { - let dataToPost = [Parameter.categoryId.rawValue: String(categoryId)] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.structure.rawValue - - faqRequestLoop.enqueue(request: WebimRequest(httpMethod: .get, - primaryData: dataToPost, - baseURLString: urlString, - faqStructureRequestCompletionHandler: completion)) - } -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/FAQClient.swift b/ios/libs/Webim/WebimClientLibrary/Backend/FAQClient.swift deleted file mode 100755 index b795356..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/FAQClient.swift +++ /dev/null @@ -1,106 +0,0 @@ -// -// FAQClient.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class FAQClientBuilder { - - // MARK: - Properties - private var baseURL: String? - private var completionHandlerExecutor: ExecIfNotDestroyedFAQHandlerExecutor? - - // MARK: - Builder methods - - func set(baseURL: String) -> FAQClientBuilder { - self.baseURL = baseURL - - return self - } - - func set(completionHandlerExecutor: ExecIfNotDestroyedFAQHandlerExecutor?) -> FAQClientBuilder { - self.completionHandlerExecutor = completionHandlerExecutor - - return self - } - - func build() -> FAQClient { - let faqRequestLoop = FAQRequestLoop(completionHandlerExecutor: completionHandlerExecutor!) - - return FAQClient(withFAQRequestLoop: faqRequestLoop, - faqActions: FAQActions(baseURL: baseURL!, faqRequestLoop: faqRequestLoop)) - } - -} - -// MARK: - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class FAQClient { - - // MARK: - Properties - private let faqRequestLoop: FAQRequestLoop - private let faqActions: FAQActions - - // MARK: - Initialization - init(withFAQRequestLoop faqRequestLoop: FAQRequestLoop, - faqActions: FAQActions) { - self.faqRequestLoop = faqRequestLoop - self.faqActions = faqActions - } - - // MARK: - Methods - - func start() { - faqRequestLoop.start() - } - - func pause() { - faqRequestLoop.pause() - } - - func resume() { - faqRequestLoop.resume() - } - - func stop() { - faqRequestLoop.stop() - } - - func getActions() -> FAQActions { - return faqActions - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/FAQDestroyer.swift b/ios/libs/Webim/WebimClientLibrary/Backend/FAQDestroyer.swift deleted file mode 100755 index a2f6651..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/FAQDestroyer.swift +++ /dev/null @@ -1,62 +0,0 @@ -// -// FAQDestroyer.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class FAQDestroyer { - - // MARK: - Properties - private lazy var actions = [() -> ()]() - private var destroyed = false - - // MARK: - Methods - - func add(action: @escaping () -> ()) { - actions.append(action) - } - - func destroy() { - if !destroyed { - destroyed = true - - for action in actions { - action() - } - actions.removeAll(keepingCapacity: false) - } - } - - func isDestroyed() -> Bool { - return destroyed - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/FAQRequestLoop.swift b/ios/libs/Webim/WebimClientLibrary/Backend/FAQRequestLoop.swift deleted file mode 100755 index ab04ab5..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/FAQRequestLoop.swift +++ /dev/null @@ -1,148 +0,0 @@ -// -// FAQRequestLoop.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.17. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that handles HTTP-requests sended by WebimClientLibrary with visitor FAQ actions. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -class FAQRequestLoop: AbstractRequestLoop { - - // MARK: - Properties - private let completionHandlerExecutor: ExecIfNotDestroyedFAQHandlerExecutor - var operationQueue: OperationQueue? - - - // MARK: - Initialization - init(completionHandlerExecutor: ExecIfNotDestroyedFAQHandlerExecutor) { - self.completionHandlerExecutor = completionHandlerExecutor - } - - // MARK: - Methods - - override func start() { - guard operationQueue == nil else { - return - } - - operationQueue = OperationQueue() - operationQueue?.maxConcurrentOperationCount = 1 - operationQueue?.qualityOfService = .userInitiated - } - - override func stop() { - super.stop() - - operationQueue?.cancelAllOperations() - operationQueue = nil - } - - func enqueue(request: WebimRequest) { - operationQueue?.addOperation { [weak self] in - guard let `self` = self else { - return - } - - if !self.isRunning() { - return - } - - let parameterDictionary = request.getPrimaryData() - let parametersString = parameterDictionary.stringFromHTTPParameters() - - var url: URL? - var urlRequest: URLRequest? - let httpMethod = request.getHTTPMethod() - url = URL(string: (request.getBaseURLString() + "?" + parametersString)) - urlRequest = URLRequest(url: url!) - - urlRequest!.httpMethod = httpMethod.rawValue - - do { - let data = try self.perform(request: urlRequest!) - if let dataJSON = try? JSONSerialization.jsonObject(with: data) as? [String: Any] { - if let error = dataJSON?[AbstractRequestLoop.ResponseFields.error.rawValue] as? String { - self.running = false - - return - } - - if let completionHandler = request.getFAQItemRequestCompletionHandler() { - self.completionHandlerExecutor.execute(task: DispatchWorkItem { - do { - try completionHandler(data) - } catch { - } - - }) - } - - if let completionHandler = request.getFAQCategoryRequestCompletionHandler() { - self.completionHandlerExecutor.execute(task: DispatchWorkItem { - do { - try completionHandler(data) - } catch { - } - - }) - } - - if let completionHandler = request.getFAQStructureRequestCompletionHandler() { - self.completionHandlerExecutor.execute(task: DispatchWorkItem { - do { - try completionHandler(data) - } catch { - } - - }) - } - - self.handleClientCompletionHandlerOf(request: request) - } - } catch let unknownError as UnknownError { - self.handleRequestLoop(error: unknownError) - } catch { - } - } - } - - // MARK: Private methode - - private func handleClientCompletionHandlerOf(request: WebimRequest) { - completionHandlerExecutor.execute(task: DispatchWorkItem { - request.getDataMessageCompletionHandler()?.onSuccess(messageID: request.getMessageID()!) - request.getSendFileCompletionHandler()?.onSuccess(messageID: request.getMessageID()!) - request.getRateOperatorCompletionHandler()?.onSuccess() - request.getDeleteMessageCompletionHandler()?.onSuccess(messageID: request.getMessageID()!) - request.getEditMessageCompletionHandler()?.onSuccess(messageID: request.getMessageID()!) - }) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/HistoryID.swift b/ios/libs/Webim/WebimClientLibrary/Backend/HistoryID.swift deleted file mode 100755 index 4e6d901..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/HistoryID.swift +++ /dev/null @@ -1,71 +0,0 @@ -// -// HistoryID.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates message ID in history context. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class HistoryID { - - // MARK: - Properties - private let dbID: String - private let timeInMicrosecond: Int64 - - // MARK: - Initialization - init(dbID: String, - timeInMicrosecond: Int64) { - self.dbID = dbID - self.timeInMicrosecond = timeInMicrosecond - } - - // MARK: - Methods - - func getDBid() -> String { - return dbID - } - - func getTimeInMicrosecond() -> Int64 { - return timeInMicrosecond - } - -} - -// MARK: - Equatable -extension HistoryID: Equatable { - - // MARK: - Methods - static func == (lhs: HistoryID, - rhs: HistoryID) -> Bool { - return ((lhs.dbID == rhs.dbID) - && (lhs.timeInMicrosecond == rhs.timeInMicrosecond)) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/HistoryMetaInformationStorage.swift b/ios/libs/Webim/WebimClientLibrary/Backend/HistoryMetaInformationStorage.swift deleted file mode 100755 index 182dd32..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/HistoryMetaInformationStorage.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// HistoryMetaInformationStorage.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.09.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -protocol HistoryMetaInformationStorage { - - func isHistoryEnded() -> Bool - - func set(historyEnded: Bool) - - func set(revision: String?) - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/HistoryStorage.swift b/ios/libs/Webim/WebimClientLibrary/Backend/HistoryStorage.swift deleted file mode 100755 index c661811..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/HistoryStorage.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// HistoryStorage.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -protocol HistoryStorage { - - /** - When this values is changed history will be re-requested. - */ - func getMajorVersion() -> Int - - func set(reachedHistoryEnd: Bool) - - func getFullHistory(completion: @escaping ([Message]) -> ()) - - func getLatestHistory(byLimit limitOfMessages: Int, - completion: @escaping ([Message]) -> ()) - - func getHistoryBefore(id: HistoryID, - limitOfMessages: Int, - completion: @escaping ([Message]) -> ()) - - func receiveHistoryBefore(messages: [MessageImpl], - hasMoreMessages: Bool) - - func receiveHistoryUpdate(withMessages messages: [MessageImpl], - idsToDelete: Set, - completion: @escaping (_ endOfBatch: Bool, _ messageDeleted: Bool, _ deletedMesageID: String?, _ messageChanged: Bool, _ changedMessage: MessageImpl?, _ messageAdded: Bool, _ addedMessage: MessageImpl?, _ idBeforeAddedMessage: HistoryID?) -> ()) - - func updateReadBeforeTimestamp(timestamp: Int64) -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/InternalErrorListener.swift b/ios/libs/Webim/WebimClientLibrary/Backend/InternalErrorListener.swift deleted file mode 100755 index 9cdae79..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/InternalErrorListener.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// InternalErrorListener.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -protocol InternalErrorListener { - - func on(error: String) - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/ChatItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/ChatItem.swift deleted file mode 100755 index 520b83c..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/ChatItem.swift +++ /dev/null @@ -1,318 +0,0 @@ -// -// ChatItem.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates chat data. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class ChatItem { - - // MARK: - Constants - - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case category = "category" - case clientSideID = "clientSideId" - case creationTimestamp = "creationTs" - case id = "id" - case messages = "messages" - case modificationTimestamp = "modificationTs" - case offline = "offline" - case `operator` = "operator" - case operatorIDToRate = "operatorIdToRate" - case operatorTyping = "operatorTyping" - case readByVisitor = "readByVisitor" - case state = "state" - case subcategory = "subcategory" - case subject = "subject" - case unreadByOperatorTimestamp = "unreadByOperatorSinceTs" - case unreadByVisitorMessageCount = "unreadByVisitorMsgCnt" - case unreadByVisitorTimestamp = "unreadByVisitorSinceTs" - case visitorTyping = "visitorTyping" - } - - // MARK: - Properties - private var category: String? - private var clientSideID: String? - private var creationTimestamp: Double - private var id: String - private lazy var messages = [MessageItem]() - private var modificationTimestamp: Double? - private var offline: Bool? - private var `operator`: OperatorItem? - private lazy var operatorIDToRate = [String: RatingItem]() - private var operatorTyping: Bool? - private var readByVisitor: Bool? - private var state: String? - private var subcategory: String? - private var subject: String? - private var unreadByOperatorTimestamp: Double? - private var unreadByVisitorMessageCount: Int - private var unreadByVisitorTimestamp: Double? - private var visitorTyping: Bool? - - // MARK: - Initialization - - init(jsonDictionary: [String: Any?]) { - if let creationTimestampValue = jsonDictionary[JSONField.creationTimestamp.rawValue] as? Double { - creationTimestamp = creationTimestampValue - } else { - creationTimestamp = ChatItem.createCreationTimestamp() - } - - if let idValue = jsonDictionary[JSONField.id.rawValue] as? String { - id = idValue - } else { - id = String(Int(-creationTimestamp)) - } - - if let unreadByVisitorMessageCount = jsonDictionary[JSONField.unreadByVisitorMessageCount.rawValue] as? Int { - self.unreadByVisitorMessageCount = unreadByVisitorMessageCount - } else { - self.unreadByVisitorMessageCount = 0 - } - - if let messagesValue = jsonDictionary[JSONField.messages.rawValue] as? [Any] { - for message in messagesValue { - if let messageValue = message as? [String: Any?] { - let messageItem = MessageItem(jsonDictionary: messageValue) - messages.append(messageItem) - } - } - } - - if let operatorValue = jsonDictionary[JSONField.`operator`.rawValue] as? [String: Any?] { - `operator` = OperatorItem(jsonDictionary: operatorValue) - } - - if let operatorIDToRateValue = jsonDictionary[JSONField.operatorIDToRate.rawValue] as? [String: Any?] { - for (operatorIDValue, ratingValue) in operatorIDToRateValue { - if let ratingItemValue = ratingValue as? [String: Any?] { - let rating = RatingItem(jsonDictionary: ratingItemValue) - operatorIDToRate[operatorIDValue] = rating - } - } - } - - if let category = jsonDictionary[JSONField.category.rawValue] as? String { - self.category = category - } - - if let clientSideID = jsonDictionary[JSONField.clientSideID.rawValue] as? String { - self.clientSideID = clientSideID - } - - if let modificationTimestamp = jsonDictionary[JSONField.modificationTimestamp.rawValue] as? Double { - self.modificationTimestamp = modificationTimestamp - } - - if let offline = jsonDictionary[JSONField.offline.rawValue] as? Bool { - self.offline = offline - } - - if let operatorTyping = jsonDictionary[JSONField.operatorTyping.rawValue] as? Bool { - self.operatorTyping = operatorTyping - } - - if let readByVisitor = jsonDictionary[JSONField.readByVisitor.rawValue] as? Bool { - self.readByVisitor = readByVisitor - } - - if let state = jsonDictionary[JSONField.state.rawValue] as? String { - self.state = state - } - - if let subcategory = jsonDictionary[JSONField.subcategory.rawValue] as? String { - self.subcategory = subcategory - } - - if let subject = jsonDictionary[JSONField.subject.rawValue] as? String { - self.subject = subject - } - - if let unreadByOperatorTimestamp = jsonDictionary[JSONField.unreadByOperatorTimestamp.rawValue] as? Double { - self.unreadByOperatorTimestamp = unreadByOperatorTimestamp - } - - if let unreadByVisitorTimestamp = jsonDictionary[JSONField.unreadByVisitorTimestamp.rawValue] as? Double { - self.unreadByVisitorTimestamp = unreadByVisitorTimestamp - } - - if let visitorTyping = jsonDictionary[JSONField.visitorTyping.rawValue] as? Bool { - self.visitorTyping = visitorTyping - } - } - - // For testing purpoeses. - init(id: String? = nil) { - creationTimestamp = ChatItem.createCreationTimestamp() - - if id == nil { - self.id = String(Int(-creationTimestamp)) - } else { - self.id = id! - } - - unreadByVisitorMessageCount = 0 - } - - // MARK: - Methods - - func getMessages() -> [MessageItem] { - return messages - } - - func set(messages: [MessageItem]) { - self.messages = messages - } - - func add(message: MessageItem, - atPosition position: Int? = nil) { - if position == nil { - messages.append(message) - } else { - messages.insert(message, - at: position!) - } - } - - func isOperatorTyping() -> Bool { - return (operatorTyping == true) - } - - func set(operatorTyping: Bool?) { - self.operatorTyping = operatorTyping - } - - func getState() -> ChatItemState? { - return ChatItemState(withType: state!) - } - - func set(state: ChatItemState) { - self.state = state.rawValue - } - - func getOperator() -> OperatorItem? { - return `operator` - } - - func set(operator: OperatorItem) { - self.`operator` = `operator` - } - - func getReadByVisitor() -> Bool? { - return readByVisitor - } - - func set(readByVisitor: Bool?) { - self.readByVisitor = readByVisitor - } - - func getOperatorIDToRate() -> [String: RatingItem]? { - return operatorIDToRate - } - - func set(rating: RatingItem, - toOperatorWithId operatorID: String) { - operatorIDToRate[operatorID] = rating - } - - func getUnreadByVisitorMessageCount() -> Int { - return unreadByVisitorMessageCount - } - - func set(unreadByVisitorMessageCount: Int) { - self.unreadByVisitorMessageCount = unreadByVisitorMessageCount - } - - func getUnreadByVisitorTimestamp() -> Double? { - return unreadByVisitorTimestamp - } - - func getUnreadByOperatorTimestamp() -> Double? { - return unreadByOperatorTimestamp - } - - func set(unreadByOperatorTimestamp: Double?) { - self.unreadByOperatorTimestamp = unreadByOperatorTimestamp - } - - func set(unreadByVisitorTimestamp: Double?) { - self.unreadByVisitorTimestamp = unreadByVisitorTimestamp - } - - - // MARK: Private methods - private static func createCreationTimestamp() -> Double { - return Double(InternalUtils.getCurrentTimeInMicrosecond()) - } - - // MARK: - - enum ChatItemState: String { - case chatting = "chatting" - case chattingWithRobot = "chatting_with_robot" - case closed = "closed" - case closedByOperator = "closed_by_operator" - case closedByVisitor = "closed_by_visitor" - case invitation = "invitation" - case queue = "queue" - case unknown = "unknown" - - // MARK: - Initialization - init(withType typeValue: String) { - self = ChatItemState(rawValue: typeValue) ?? .unknown - } - - - // MARK: - Methods - func isClosed() -> Bool { - return (((self == .closed) - || (self == .closedByVisitor)) - || (self == .closedByOperator)) - || (self == .unknown) - } - - } - -} - -// MARK: - Equatable -extension ChatItem: Equatable { - - // MARK: - Methods - // Used inside MessageHolderImpl.receiving(newChat:previousChat:newMessages:) only. - static func == (lhs: ChatItem, - rhs: ChatItem) -> Bool { - return (lhs.id == rhs.id) - && (lhs.clientSideID == rhs.clientSideID) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Deltas/DeltaItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/Deltas/DeltaItem.swift deleted file mode 100755 index 1e36854..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Deltas/DeltaItem.swift +++ /dev/null @@ -1,117 +0,0 @@ -// -// DeltaItem.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates chat update data, received from a server. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class DeltaItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - enum DeltaType: String { - case chat = "CHAT" - case chatMessage = "CHAT_MESSAGE" - case chatOperator = "CHAT_OPERATOR" - case chatOperatorTyping = "CHAT_OPERATOR_TYPING" - case chatReadByVisitor = "CHAT_READ_BY_VISITOR" - case chatState = "CHAT_STATE" - case chatUnreadByOperatorTimestamp = "CHAT_UNREAD_BY_OPERATOR_SINCE_TS" - case departmentList = "DEPARTMENT_LIST" - case historyRevision = "HISTORY_REVISION" - case offlineChatMessage = "OFFLINE_CHAT_MESSAGE" - case operatorRate = "OPERATOR_RATE" - case unreadByVisitor = "UNREAD_BY_VISITOR" - case visitSession = "VISIT_SESSION" - case visitSessionState = "VISIT_SESSION_STATE" - case chatMessageRead = "MESSAGE_READ" - } - enum Event: String { - case add = "add" - case delete = "del" - case update = "upd" - } - enum UnreadByVisitorField: String { - case timestamp = "sinceTs" - case messageCount = "msgCnt" - } - private enum JSONField: String { - case data = "data" - case event = "event" - case objectType = "objectType" - case id = "id" - } - - // MARK: - Properties - private var data: Any? - private var event: Event - private var deltaType: DeltaType? - private var id: String - - // MARK: - Initialization - init?(jsonDictionary: [String: Any?]) { - guard let eventString = jsonDictionary[JSONField.event.rawValue] as? String, - let event = Event(rawValue: eventString) else { - return nil - } - self.event = event - - guard let id = jsonDictionary[JSONField.id.rawValue] as? String else { - return nil - } - self.id = id - - self.data = jsonDictionary[JSONField.data.rawValue] ?? nil - - if let objectTypeString = jsonDictionary[JSONField.objectType.rawValue] as? String { - deltaType = DeltaType(rawValue: objectTypeString) - } - } - - // MARK: - Methods - - func getDeltaType() -> DeltaType? { - return deltaType - } - - func getID() -> String { - return id - } - - func getEvent() -> Event { - return event - } - - func getData() -> Any? { - return data - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Deltas/FullUpdate.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/Deltas/FullUpdate.swift deleted file mode 100755 index e4663c7..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Deltas/FullUpdate.swift +++ /dev/null @@ -1,162 +0,0 @@ -// -// FullUpdate.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates full data update, received from a server. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct FullUpdate { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case authorizationToken = "authToken" - case chat = "chat" - case departments = "departments" - case hintsEnabled = "hintsEnabled" - case historyRevision = "historyRevision" - case onlineStatus = "onlineStatus" - case pageID = "pageId" - case sessionID = "visitSessionId" - case state = "state" - case visitor = "visitor" - } - - // MARK: - Properties - private var authorizationToken: String? - private var chat: ChatItem? - private var departments: [DepartmentItem]? - private var hintsEnabled: Bool - private var historyRevision: Int? - private var onlineStatus: String? - private var pageID: String? - private var sessionID: String? - private var state: String? - private var visitorJSONString: String? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let authorizationToken = jsonDictionary[JSONField.authorizationToken.rawValue] as? String { - self.authorizationToken = authorizationToken - } - - if let chatValue = jsonDictionary[JSONField.chat.rawValue] as? [String: Any?] { - chat = ChatItem(jsonDictionary: chatValue) - } - - if let pageID = jsonDictionary[JSONField.pageID.rawValue] as? String { - self.pageID = pageID - } - - if let onlineStatus = jsonDictionary[JSONField.onlineStatus.rawValue] as? String { - self.onlineStatus = onlineStatus - } - - if let sessionID = jsonDictionary[JSONField.sessionID.rawValue] as? String { - self.sessionID = sessionID - } - - if let state = jsonDictionary[JSONField.state.rawValue] as? String { - self.state = state - } - - if let visitorJSON = jsonDictionary[JSONField.visitor.rawValue] { - if let visitorJSONData = try? JSONSerialization.data(withJSONObject: visitorJSON!) { - visitorJSONString = String(data: visitorJSONData, - encoding: .utf8) - } - } - - if let departmantsData = jsonDictionary[JSONField.departments.rawValue] as? [Any] { - var departmentItems = [DepartmentItem]() - for departmentData in departmantsData { - if let departmentDictionary = departmentData as? [String: Any] { - if let deparmentItem = DepartmentItem(jsonDictionary: departmentDictionary) { - departmentItems.append(deparmentItem) - } - } - } - self.departments = departmentItems - } - - hintsEnabled = (jsonDictionary[JSONField.hintsEnabled.rawValue] as? Bool) ?? false - - if let historyRevision = jsonDictionary[JSONField.historyRevision.rawValue] as? Int { - self.historyRevision = historyRevision - } - } - - // MARK: - Methods - - func getAuthorizationToken() -> String? { - return authorizationToken - } - - func getDepartments() -> [DepartmentItem]? { - return departments - } - - func getChat() -> ChatItem? { - return chat - } - - func getHintsEnabled() -> Bool { - return hintsEnabled - } - - func getHistoryRevision() -> String? { - guard historyRevision != nil else { - return nil - } - return String(historyRevision!) - } - - func getOnlineStatus() -> String? { - return onlineStatus - } - - func getPageID() -> String? { - return pageID - } - - func getSessionID() -> String? { - return sessionID - } - - func getState() -> String? { - return state - } - - func getVisitorJSONString() -> String? { - return visitorJSONString - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/DepartmentItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/DepartmentItem.swift deleted file mode 100755 index 5758cfd..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/DepartmentItem.swift +++ /dev/null @@ -1,115 +0,0 @@ -// -// DepartmentItem.swift -// Cosmos -// -// Created by Nikita Lazarev-Zubov on 11.12.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Encapsulates internal representation of single department. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class DepartmentItem { - - // MARK: - Constants - - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case key = "key" - case localizedNames = "localeToName" - case name = "name" - case onlineStatus = "online" - case order = "order" - case logo = "logo" - } - - enum InternalDepartmentOnlineStatus: String { - case busyOffline = "busy_offline" - case busyOnline = "busy_online" - case offline = "offline" - case online = "online" - case unknown - } - - // MARK: - Properties - private let key: String - private let name: String - private let onlineStatus: InternalDepartmentOnlineStatus - private let order: Int - private var localizedNames: [String: String]? - private var logo: String? - - // MARK: - Initialization - init?(jsonDictionary: [String: Any?]) { - guard let key = jsonDictionary[JSONField.key.rawValue] as? String, - let name = jsonDictionary[JSONField.name.rawValue] as? String, - let onlineStatusString = jsonDictionary[JSONField.onlineStatus.rawValue] as? String, - let order = jsonDictionary[JSONField.order.rawValue] as? Int else { - return nil - } - - self.key = key - self.name = name - self.onlineStatus = InternalDepartmentOnlineStatus(rawValue: onlineStatusString) ?? .unknown - self.order = order - - if let logoURLString = jsonDictionary[JSONField.logo.rawValue] as? String { - self.logo = logoURLString - } - - if let localizedNames = jsonDictionary[JSONField.localizedNames.rawValue] as? [String: String] { - self.localizedNames = localizedNames - } - } - - // MARK: - Methods - - func getKey() -> String { - return key - } - - func getName() -> String { - return name - } - - func getOnlineStatus() -> InternalDepartmentOnlineStatus { - return onlineStatus - } - - func getOrder() -> Int { - return order - } - - func getLocalizedNames() -> [String: String]? { - return localizedNames - } - - func getLogoURLString() -> String? { - return logo - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQCategoryInfoItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQCategoryInfoItem.swift deleted file mode 100755 index df84463..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQCategoryInfoItem.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// FAQCategoryInfoItem.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class FAQCategoryInfoItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case id = "id" - case title = "title" - } - - // MARK: - Properties - private var id: Int? - private var title: String? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let id = jsonDictionary[JSONField.id.rawValue] as? Int { - self.id = id - } - - if let title = jsonDictionary[JSONField.title.rawValue] as? String { - self.title = title - } - } - -} - -extension FAQCategoryInfoItem: FAQCategoryInfo { - func getID() -> Int { - return id! - } - - func getTitle() -> String { - return title! - } - -} - -// MARK: - Equatable -extension FAQCategoryInfoItem: Equatable { - - // MARK: - Methods - static func == (lhs: FAQCategoryInfoItem, - rhs: FAQCategoryInfoItem) -> Bool { - if lhs.id == rhs.id { - return true - } - - return false - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQCategoryItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQCategoryItem.swift deleted file mode 100755 index c5c97ff..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQCategoryItem.swift +++ /dev/null @@ -1,152 +0,0 @@ -// -// FAQCategoryItem.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class FAQCategoryItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case id = "categoryid" - case title = "title" - case childs = "childs" - } - - // MARK: - Properties - private var id: Int? - private var title: String? - private var children = [Child]() - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let id = jsonDictionary[JSONField.id.rawValue] as? Int { - self.id = id - } - - if let title = jsonDictionary[JSONField.title.rawValue] as? String { - self.title = title - } - - if let childs = jsonDictionary[JSONField.childs.rawValue] as? [Any] { - for child in childs { - if let childValue = child as? [String: Any?] { - let childItem = Child(jsonDictionary: childValue) - children.append(childItem) - } - } - } - } - -} - -extension FAQCategoryItem: FAQCategory { - func getID() -> Int { - return id! - } - - func getTitle() -> String { - return title! - } - - func getItems() -> [FAQItem] { - var items = [FAQItem]() - for child in children { - if child.type == .ITEM { - items.append(child.data as! FAQItemItem) - } - } - return items - } - - func getSubcategories() -> [FAQCategoryInfo] { - var subCategories = [FAQCategoryInfo]() - for child in children { - if child.type == .CATEGORY { - subCategories.append(child.data as! FAQCategoryInfoItem) - } - } - return subCategories - } - - -} - -// MARK: - Equatable -extension FAQCategoryItem: Equatable { - - // MARK: - Methods - static func == (lhs: FAQCategoryItem, - rhs: FAQCategoryItem) -> Bool { - if lhs.id == rhs.id { - return true - } - - return false - } - -} - -final class Child { - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case type = "type" - case data = "data" - } - - // MARK: - Properties - public var type: RootType? - public var data: Any? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let type = jsonDictionary[JSONField.type.rawValue] as? String { - switch type { - case "item": - self.type = .ITEM - if let data = jsonDictionary[JSONField.data.rawValue] as? [String: Any?] { - self.data = FAQItemItem(jsonDictionary: data) - } - break - case "category": - self.type = .CATEGORY - if let data = jsonDictionary[JSONField.data.rawValue] as? [String: Any?] { - self.data = FAQCategoryInfoItem(jsonDictionary: data) - } - break - default: - self.type = .UNKNOWN - } - } - } -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQItemItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQItemItem.swift deleted file mode 100755 index 1bd7440..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQItemItem.swift +++ /dev/null @@ -1,137 +0,0 @@ -// -// FAQItemItem.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class FAQItemItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case id = "id" - case categories = "categories" - case title = "title" - case tags = "tags" - case content = "content" - case likes = "likes" - case dislikes = "dislikes" - } - - // MARK: - Properties - private var id: String? - private var categories: [Int]? - private var title: String? - private var tags: [String]? - private var content: String? - private var likes: Int? - private var dislikes: Int? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let id = jsonDictionary[JSONField.id.rawValue] as? String { - self.id = id - } - - if let categories = jsonDictionary[JSONField.categories.rawValue] as? [Int] { - self.categories = categories - } - - if let title = jsonDictionary[JSONField.title.rawValue] as? String { - self.title = title - } - - if let tags = jsonDictionary[JSONField.tags.rawValue] as? [String] { - self.tags = tags - } - - if let content = jsonDictionary[JSONField.content.rawValue] as? String { - self.content = content - } - - if let likes = jsonDictionary[JSONField.likes.rawValue] as? Int { - self.likes = likes - } - - if let dislikes = jsonDictionary[JSONField.dislikes.rawValue] as? Int { - self.dislikes = dislikes - } - } - -} - -extension FAQItemItem: FAQItem { - - func getID() -> String { - return id! - } - - func getCategories() -> [Int] { - return categories! - } - - func getTitle() -> String { - return title! - } - - func getTags() -> [String] { - return tags! - } - - func getContent() -> String { - return content! - } - - func getLikeCount() -> Int { - return likes! - } - - func getDislikeCount() -> Int { - return dislikes! - } - - -} - -// MARK: - Equatable -extension FAQItemItem: Equatable { - - // MARK: - Methods - static func == (lhs: FAQItemItem, - rhs: FAQItemItem) -> Bool { - if lhs.id == rhs.id { - return true - } - - return false - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQStructureItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQStructureItem.swift deleted file mode 100755 index a8b4810..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FAQStructureItem.swift +++ /dev/null @@ -1,133 +0,0 @@ -// -// FAQStructureItem.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class FAQStructureItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case id = "id" - case type = "type" - case childs = "childs" - case title = "title" - } - - // MARK: - Properties - private var id: String? - private var title: String? - private var type: RootType? - private var children = [FAQStructureItem]() - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let id = jsonDictionary[JSONField.id.rawValue] as? String { - self.id = id - } - - if let title = jsonDictionary[JSONField.title.rawValue] as? String { - self.title = title - } - - if let type = jsonDictionary[JSONField.type.rawValue] as? String { - self.type = toRootType(type: type) - } - - if type == .ITEM { - if let id = jsonDictionary[JSONField.id.rawValue] as? String { - self.id = id - } - } else { - if let id = jsonDictionary[JSONField.id.rawValue] as? Int { - self.id = String(id) - } - } - - if let childs = jsonDictionary[JSONField.childs.rawValue] as? [Any] { - for child in childs { - if let childValue = child as? [String: Any?] { - let childItem = FAQStructureItem(jsonDictionary: childValue) - children.append(childItem) - } - } - } - } - - private func toRootType(type: String) -> RootType? { - switch type { - case "item": - return .ITEM - case "category": - return .CATEGORY - default: - return nil - } - } - -} - -extension FAQStructureItem: FAQStructure { - func getID() -> String { - return id! - } - - func getType() -> RootType { - return type! - } - - func getChildren() -> [FAQStructure] { - return children - } - - func getTitle() -> String { - return title! - } - - - -} - -// MARK: - Equatable -extension FAQStructureItem: Equatable { - - // MARK: - Methods - static func == (lhs: FAQStructureItem, - rhs: FAQStructureItem) -> Bool { - if lhs.id == rhs.id { - return true - } - - return false - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FileParametersItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/FileParametersItem.swift deleted file mode 100755 index 04d2d9d..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/FileParametersItem.swift +++ /dev/null @@ -1,162 +0,0 @@ -// -// FileParametersItem.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class FileParametersItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case contentType = "content_type" - case fileName = "filename" - case guid = "guid" - case imageParameters = "image" - case size = "size" - } - - // MARK: - Properties - private var contentType: String? - private var filename: String? - private var guid: String? - private var imageParameters: ImageParameters? - private var size: Int64? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let imageParametersDictionary = jsonDictionary[JSONField.imageParameters.rawValue] as? [String: Any?] { - imageParameters = ImageParameters(jsonDictionary: imageParametersDictionary) - } - - if let contentType = jsonDictionary[JSONField.contentType.rawValue] as? String { - self.contentType = contentType - } - - if let filename = jsonDictionary[JSONField.fileName.rawValue] as? String { - self.filename = filename - } - - if let guid = jsonDictionary[JSONField.guid.rawValue] as? String { - self.guid = guid - } - - if let size = jsonDictionary[JSONField.size.rawValue] as? Int64 { - self.size = size - } - } - - // MARK: - Methods - - func getSize() -> Int64? { - return size - } - - func getGUID() -> String? { - return guid - } - - func getContentType() -> String? { - return contentType - } - - func getFilename() -> String? { - return filename - } - - func getImageParameters() -> ImageParameters? { - return imageParameters - } - -} - -// MARK: - -final class ImageParameters { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case size = "size" - } - - // MARK: - Properties - private var size: ImageSize? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let sizeDictionary = jsonDictionary[JSONField.size.rawValue] as? [String: Any?] { - self.size = ImageSize(jsonDictionary: sizeDictionary) - } - } - - // MARK: - Methods - func getSize() -> ImageSize? { - return size - } - -} - -// MARK: - -struct ImageSize { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case height = "height" - case width = "width" - } - - // MARK: - Properties - private var width: Int? - private var height: Int? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let height = jsonDictionary[JSONField.height.rawValue] as? Int { - self.height = height - } - - if let width = jsonDictionary[JSONField.width.rawValue] as? Int { - self.width = width - } - } - - // MARK: - Methods - - func getWidth() -> Int? { - return width - } - - func getHeight() -> Int? { - return height - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/HistoryRevisionItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/HistoryRevisionItem.swift deleted file mode 100755 index c4c9897..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/HistoryRevisionItem.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// HistoryRevisionItem.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 05.03.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class HistoryRevisionItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case revision = "revision" - } - - // MARK: - Properties - private var revision: Int64 - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let revision = jsonDictionary[JSONField.revision.rawValue] as? Int64 { - self.revision = revision - } else { - self.revision = 0 - } - } - - // MARK: - Methods - func getRevision() -> String { - return String(revision) - } -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/MessageItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/MessageItem.swift deleted file mode 100755 index 758f410..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/MessageItem.swift +++ /dev/null @@ -1,262 +0,0 @@ -// -// MessageItem.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 14.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates message data, received from a server. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MessageItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case authorID = "authorId" - case avatarURLString = "avatar" - case canBeEdited = "canBeEdited" - case chatID = "chatId" - case clientSideID = "clientSideId" - case data = "data" - case deleted = "deleted" - case id = "id" - case kind = "kind" - case read = "read" - case senderName = "name" - case text = "text" - case timestampInMicrosecond = "ts_m" - case timestampInSecond = "ts" - } - - // MARK: - Properties - private var authorID: String? - private var avatarURLString: String? - private var canBeEdited: Bool? - private var chatID: String? - private var clientSideID: String? - private var data: [String: Any?]? - private var deleted: Bool? - private var id: String? - private var kind: MessageKind? - private var senderName: String? - private var text: String? - private var timestampInMicrosecond: Int64 = -1 - private var timestampInSecond: Double? - private var read: Bool? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let messageKind = jsonDictionary[JSONField.kind.rawValue] as? String { - kind = MessageKind(rawValue: messageKind) - } - - if let authorID = jsonDictionary[JSONField.authorID.rawValue] as? Int { - self.authorID = String(authorID) - } - - if let avatarURLString = jsonDictionary[JSONField.avatarURLString.rawValue] as? String { - self.avatarURLString = avatarURLString - } - - if let canBeEdited = jsonDictionary[JSONField.canBeEdited.rawValue] as? Bool { - self.canBeEdited = canBeEdited - } - - if let chatID = jsonDictionary[JSONField.chatID.rawValue] as? String { - self.chatID = chatID - } - - if let clientSideID = jsonDictionary[JSONField.clientSideID.rawValue] as? String { - self.clientSideID = clientSideID - } - - if let data = jsonDictionary[JSONField.data.rawValue] as? [String: Any?] { - self.data = data - } - - if let deleted = jsonDictionary[JSONField.deleted.rawValue] as? Bool { - self.deleted = deleted - } - - if let id = jsonDictionary[JSONField.id.rawValue] as? String { - self.id = id - } - - if let read = jsonDictionary[JSONField.read.rawValue] as? Bool { - self.read = read - } - - if let senderName = jsonDictionary[JSONField.senderName.rawValue] as? String { - self.senderName = senderName - } - - if let text = jsonDictionary[JSONField.text.rawValue] as? String { - self.text = text - } - - if let timestampInMicrosecond = jsonDictionary[JSONField.timestampInMicrosecond.rawValue] as? Int64 { - self.timestampInMicrosecond = timestampInMicrosecond - } - - if let timestampInSecond = jsonDictionary[JSONField.timestampInSecond.rawValue] as? Double { - self.timestampInSecond = timestampInSecond - } - } - - // MARK: - Methods - - func getClientSideID() -> String? { - if clientSideID == nil { - clientSideID = id - } - - return clientSideID - } - - func getID() -> String? { - return id - } - - func getText() -> String? { - return text - } - - func getSenderID() -> String? { - return authorID - } - - func getSenderAvatarURLString() -> String? { - return avatarURLString - } - - func getData() -> [String: Any?]? { - return data - } - - func isDeleted() -> Bool { - return (deleted == true) - } - - func getKind() -> MessageKind? { - return kind - } - - func getSenderName() -> String? { - return senderName - } - - func getTimeInMicrosecond() -> Int64? { - return ((timestampInMicrosecond != -1) ? timestampInMicrosecond : Int64(timestampInSecond! * 1_000_000)) - } - - func getRead() -> Bool? { - return read - } - - func setRead(read:Bool) { - self.read = read - } - - func getCanBeEdited() -> Bool { - return canBeEdited ?? false - } - - // MARK: - - enum MessageKind: String { - // Raw values equal to field names received in responses from server. - case actionRequest = "action_request" - case contactInformationRequest = "cont_req" - case contactInformation = "contacts" - case fileFromOperator = "file_operator" - case fileFromVisitor = "file_visitor" - case forOperator = "for_operator" - case info = "info" - case operatorMessage = "operator" - case operatorBusy = "operator_busy" - case visitorMessage = "visitor" - - // MARK: - Initialization - init(messageType: MessageType) { - switch messageType { - case .ACTION_REQUEST: - self = .actionRequest - - break - case .CONTACTS_REQUEST: - self = .contactInformationRequest - - break - case .FILE_FROM_OPERATOR: - self = .fileFromOperator - - break - case .FILE_FROM_VISITOR: - self = .fileFromVisitor - - break - case .INFO: - self = .info - - break - case .OPERATOR: - self = .operatorMessage - - break - case .OPERATOR_BUSY: - self = .operatorBusy - - break - case .VISITOR: - self = .visitorMessage - - break - } - } - - } - -} - -// MARK: - Equatable -extension MessageItem: Equatable { - - // MARK: - Methods - static func == (lhs: MessageItem, - rhs: MessageItem) -> Bool { - if (((lhs.id == rhs.id) - && (lhs.clientSideID == rhs.clientSideID)) - && (lhs.timestampInSecond == rhs.timestampInSecond)) - && (lhs.text == rhs.text) { - return true - } - - return false - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/OnlineStatusItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/OnlineStatusItem.swift deleted file mode 100755 index 85c23a7..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/OnlineStatusItem.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// OnlineStatusItem.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Raw values equal to field names received in responses from server (except `unknown` case which is custom). - * `BUSY_OFFLINE` - user can't send messages at all; - * `BUSY_ONLINE` - user send offline messages, but server can return an error; - * `OFFLINE` - user can send offline messages; - * `ONLINE` - user can send online and offline messages; - * `UNKNOWN` - session has not received data from server. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -enum OnlineStatusItem: String { - case busyOffline = "busy_offline" - case busyOnline = "busy_online" - case offline = "offline" - case online = "online" - case unknown = "unknown" -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/OperatorItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/OperatorItem.swift deleted file mode 100755 index 8701d21..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/OperatorItem.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// OperatorItem.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 14.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates chat operator data, received from server. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct OperatorItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case avatarURLString = "avatar" - case departmentKeys = "departmentKeys" - case id = "id" - case fullName = "fullname" - } - - // MARK: - Properties - private var avatarURLString: String? - private var id: String - private var fullName: String - - // MARK: - Initialization - init?(jsonDictionary: [String: Any?]) { - if let id = jsonDictionary[JSONField.id.rawValue] as? Int { - self.id = String(id) - } else { - return nil - } - - if let fullName = jsonDictionary[JSONField.fullName.rawValue] as? String { - self.fullName = fullName - } else { - return nil - } - - if let avatarURLString = jsonDictionary[JSONField.avatarURLString.rawValue] as? String { - self.avatarURLString = avatarURLString - } - } - - // MARK: - Methods - - func getID() -> String { - return id - } - - func getFullName() -> String { - return fullName - } - - func getAvatarURLString() -> String? { - return avatarURLString - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/RatingItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/RatingItem.swift deleted file mode 100755 index 7056618..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/RatingItem.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// RatingItem.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 14.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates operator rating data. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct RatingItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case operatorID = "operatorId" - case rating = "rating" - } - - // MARK: - Properties - private var operatorID: String - private var rating: Int - - // MARK: - Initialization - init?(jsonDictionary: [String : Any?]) { - guard let operatorID = jsonDictionary[JSONField.operatorID.rawValue] as? Int, - let rating = jsonDictionary[JSONField.rating.rawValue] as? Int else { - return nil - } - - self.operatorID = String(operatorID) - self.rating = rating - } - - // MARK: - Methods - - func getOperatorID() -> String { - return operatorID - } - - func getRating() -> Int { - return rating - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Responses/DeltaResponse.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/Responses/DeltaResponse.swift deleted file mode 100755 index ecccee9..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Responses/DeltaResponse.swift +++ /dev/null @@ -1,86 +0,0 @@ -// -// DeltaResponse.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates chat update respnonce, requested from a server. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class DeltaResponse { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case deltaList = "deltaList" - case fullUpdate = "fullUpdate" - case revision = "revision" - } - - // MARK: - Properties - private lazy var deltaList = [DeltaItem]() - private var fullUpdate: FullUpdate? - private var revision: Int64? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let revision = jsonDictionary[JSONField.revision.rawValue] as? Int64 { - self.revision = revision - } - - if let fullUpdateValue = jsonDictionary[JSONField.fullUpdate.rawValue] as? [String: Any?] { - fullUpdate = FullUpdate(jsonDictionary: fullUpdateValue) - } - - if let deltaItemArray = jsonDictionary[JSONField.deltaList.rawValue] as? [Any] { - for arrayItem in deltaItemArray { - if let arrayItem = arrayItem as? [String: Any?] { - if let deltaItem = DeltaItem(jsonDictionary: arrayItem) { - deltaList.append(deltaItem) - } - } - } - } - } - - // MARK: - Methods - - func getRevision() -> Int64? { - return revision - } - - func getFullUpdate() -> FullUpdate? { - return fullUpdate - } - - func getDeltaList() -> [DeltaItem]? { - return deltaList - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Responses/HistoryBeforeResponse.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/Responses/HistoryBeforeResponse.swift deleted file mode 100755 index 41e051d..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Responses/HistoryBeforeResponse.swift +++ /dev/null @@ -1,100 +0,0 @@ -// -// HistoryBeforeResponse.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 14.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct HistoryBeforeResponse { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - enum JSONField: String { - case data = "data" - } - - // MARK: - Properties - private var historyResponseData: HistoryResponseData? - private var result: String? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let dataDictionary = jsonDictionary[JSONField.data.rawValue] as? [String: Any?] { - historyResponseData = HistoryResponseData(jsonDictionary: dataDictionary) - } - } - - // MARK: - Methods - func getData() -> HistoryResponseData? { - return historyResponseData - } - - // MARK: - - struct HistoryResponseData { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - enum JSONField: String { - case hasMore = "hasMore" - case messages = "messages" - } - - // MARK: - Properties - private var hasMore: Bool - private var messages: [MessageItem]? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - messages = [MessageItem]() - if let messagesArray = jsonDictionary[JSONField.messages.rawValue] as? [Any?] { - for item in messagesArray { - if let messageDictionary = item as? [String: Any?] { - let messageItem = MessageItem(jsonDictionary: messageDictionary) - messages?.append(messageItem) - } - } - } - - hasMore = ((jsonDictionary[JSONField.hasMore.rawValue] as? Bool) ?? false) - } - - // MARK: - Methods - - func isHasMore() -> Bool { - return hasMore - } - - func getMessages() -> [MessageItem]? { - return messages - } - - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Responses/HistorySinceResponse.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/Responses/HistorySinceResponse.swift deleted file mode 100755 index b33b47e..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/Responses/HistorySinceResponse.swift +++ /dev/null @@ -1,107 +0,0 @@ -// -// HistorySinceResponse.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct HistorySinceResponse { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - enum JSONField: String { - case data = "data" - } - - // MARK: - Properties - private var historyResponseData: HistoryResponseData? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - if let dataDictionary = jsonDictionary[JSONField.data.rawValue] as? [String: Any?] { - historyResponseData = HistoryResponseData(jsonDictionary: dataDictionary) - } - } - - // MARK: - Methods - func getData() -> HistoryResponseData? { - return historyResponseData - } - - // MARK: - - struct HistoryResponseData { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - enum JSONField: String { - case hasMore = "hasMore" - case messages = "messages" - case revision = "revision" - } - - // MARK: - Properties - private var hasMore: Bool? - private var messages: [MessageItem]? - private var revision: String? - - // MARK: - Initialization - init(jsonDictionary: [String: Any?]) { - var messages = [MessageItem]() - if let messagesArray = jsonDictionary[JSONField.messages.rawValue] as? [Any?] { - for item in messagesArray { - if let messageDictionary = item as? [String: Any?] { - let messageItem = MessageItem(jsonDictionary: messageDictionary) - messages.append(messageItem) - } - } - } - self.messages = messages - - hasMore = ((jsonDictionary[JSONField.hasMore.rawValue] as? Bool) ?? false) - revision = jsonDictionary[JSONField.revision.rawValue] as! String? - } - - // MARK: - Methods - - func getMessages() -> [MessageItem]? { - return messages - } - - func isHasMore() -> Bool? { - return hasMore - } - - func getRevision() -> String? { - return revision - } - - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/VisitSessionStateItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/VisitSessionStateItem.swift deleted file mode 100755 index b2d15b7..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/VisitSessionStateItem.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// VisitSessionStateItem.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -enum VisitSessionStateItem: String { - // Raw values equal to field names received in responses from server. - case callbackHunter = "callback-hunter" - case chat = "chat" - case chatShowing = "chat-showing" - case departmentSelection = "department-selection" - case end = "end" - case firstQuestion = "first-question" - case idle = "idle" - case idleAfterChat = "idle-after-chat" - case offlineMessage = "offline-message" - case showing = "showing" - case showingAuto = "showing-auto" - case showingByURLParameter = "showing-by-url-param" - case unknown -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Items/VisitorItem.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Items/VisitorItem.swift deleted file mode 100755 index 52833df..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Items/VisitorItem.swift +++ /dev/null @@ -1,181 +0,0 @@ -// -// VisitorItem.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -// This class is not used anywhere yet. Implemented for the future tasks. -/** - Internal representation of visitor information. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct VisitorItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case icon = "icon" - case id = "id" - case fields = "fields" - } - - // MARK: - Properties - private var icon: IconItem? - private var id: String - private var visitorFields: VisitorFieldsItem - - // MARK: - Initialization - init?(jsonDictionary: [String: Any?]) { - guard let id = jsonDictionary[JSONField.id.rawValue] as? String, - let visitorFieldsValue = jsonDictionary[JSONField.fields.rawValue] as? [String: Any?], - let visitorFields = VisitorFieldsItem(jsonDictionary: visitorFieldsValue) else { - return nil - } - - self.id = id - self.visitorFields = visitorFields - - if let iconValue = jsonDictionary[JSONField.icon.rawValue] as? [String : Any?] { - icon = IconItem(jsonDictionary: iconValue) - } - } - - // MARK: - Methods - - func getIcon() -> IconItem? { - return icon - } - - func getID() -> String { - return id - } - - func getVisitorFields() -> VisitorFieldsItem { - return visitorFields - } - -} - -/** - Representation of generated by server visitor avatar image of standard ones. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct IconItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case color = "color" - case shape = "shape" - } - - // MARK: - Properties - private var color: UIColor - private var shape: String - - // MARK: - Initialization - init?(jsonDictionary: [String: Any?]) { - guard let colorString = jsonDictionary[JSONField.color.rawValue] as? String, - let color = UIColor(hexString: colorString), - let shape = jsonDictionary[JSONField.shape.rawValue] as? String else { - return nil - } - - self.color = color - self.shape = shape - } - - // MARK: - Methods - - func getColor() -> UIColor { - return color - } - - func getShape() -> String { - return shape - } - -} - -// MARK: - -/** - Internal representation of visitor fields. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct VisitorFieldsItem { - - // MARK: - Constants - // Raw values equal to field names received in responses from server. - private enum JSONField: String { - case email = "email" - case name = "name" - case phone = "phone" - } - - // MARK: - Properties - private var email: String? - private var name: String - private var phone: String? - - // MARK: - Initialization - init?(jsonDictionary: [String : Any?]) { - guard let name = jsonDictionary[JSONField.name.rawValue] as? String else { - return nil - } - self.name = name - - if let email = jsonDictionary[JSONField.email.rawValue] as? String { - self.email = email - } - - if let phone = jsonDictionary[JSONField.phone.rawValue] as? String { - self.phone = phone - } - } - - // MARK: - Methods - - func getName() -> String { - return name - } - - func getEmail() -> String? { - return email - } - - func getPhone() -> String? { - return phone - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/LocationSettingsHolder.swift b/ios/libs/Webim/WebimClientLibrary/Backend/LocationSettingsHolder.swift deleted file mode 100755 index 042511d..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/LocationSettingsHolder.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// LocationSettingsHolder.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class LocationSettingsHolder { - - // MARK: - Properties - private let locationSettings: LocationSettingsImpl - private let userDefaultsKey: String - - // MARK: - Initialization - init(userDefaultsKey: String) { - self.userDefaultsKey = userDefaultsKey - locationSettings = LocationSettingsImpl.getFrom(userDefaults: userDefaultsKey) - } - - // MARK: - Methods - - func getLocationSettings() -> LocationSettingsImpl { - return locationSettings - } - - func receiving(locationSettings: LocationSettingsImpl) -> Bool { - if locationSettings != self.locationSettings { - locationSettings.saveTo(userDefaults: userDefaultsKey) - - return true - } - - return false - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/MemoryHistoryMetaInformationStorage.swift b/ios/libs/Webim/WebimClientLibrary/Backend/MemoryHistoryMetaInformationStorage.swift deleted file mode 100755 index 819f386..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/MemoryHistoryMetaInformationStorage.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// MemoryHistoryMetaInformationStorage.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.09.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MemoryHistoryMetaInformationStorage: HistoryMetaInformationStorage { - - // MARK: - Properties - private var historyEnded = false - - // MARK: - Methods - // MARK: HistoryMetaInformationStorage protocol methods - - func isHistoryEnded() -> Bool { - return historyEnded - } - - func set(historyEnded: Bool) { - self.historyEnded = historyEnded - } - - func set(revision: String?) { - // No need to do anything in this implementation. - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/MemoryHistoryStorage.swift b/ios/libs/Webim/WebimClientLibrary/Backend/MemoryHistoryStorage.swift deleted file mode 100755 index ba63482..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/MemoryHistoryStorage.swift +++ /dev/null @@ -1,226 +0,0 @@ -// -// MemoryHistoryStorage.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that is responsible for history storage when it is set to memory mode. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MemoryHistoryStorage: HistoryStorage { - - // MARK: - Properties - private let majorVersion = Int(InternalUtils.getCurrentTimeInMicrosecond() % Int64(Int.max)) - private lazy var historyMessages = [MessageImpl]() - private var reachedHistoryEnd = false - private var readBeforeTimestamp: Int64 - - // MARK: - Initialization - - init() { - // Empty initializer introduced because of init(with:) existence. - self.readBeforeTimestamp = -1 - } - - init(readBeforeTimestamp: Int64) { - self.readBeforeTimestamp = readBeforeTimestamp - } - - // For testing purposes only. - init(messagesToAdd: [MessageImpl]) { - self.readBeforeTimestamp = -1 - for message in messagesToAdd { - historyMessages.append(message) - } - } - - // MARK: - Methods - // MARK: HistoryStorage protocol methods - - func getMajorVersion() -> Int { - return majorVersion - } - - func set(reachedHistoryEnd: Bool) { - // No need in this implementation. - } - - func getFullHistory(completion: @escaping ([Message]) -> ()) { - completion(historyMessages as [Message]) - } - - func getLatestHistory(byLimit limitOfMessages: Int, - completion: @escaping ([Message]) -> ()) { - respondTo(messages: historyMessages, - limitOfMessages: limitOfMessages, - completion: completion) - } - - func getHistoryBefore(id: HistoryID, - limitOfMessages: Int, - completion: @escaping ([Message]) -> ()) { - let sortedMessages = historyMessages.sorted { $0.getHistoryID()!.getTimeInMicrosecond() < $1.getHistoryID()!.getTimeInMicrosecond() } - - if sortedMessages[0].getHistoryID()!.getTimeInMicrosecond() > id.getTimeInMicrosecond() { - completion([MessageImpl]()) - - return - } - - for (index, message) in sortedMessages.enumerated() { - if message.getHistoryID() == id { - respondTo(messages: sortedMessages, - limitOfMessages: limitOfMessages, - offset: index, - completion: completion) - - break - } - } - } - - func receiveHistoryBefore(messages: [MessageImpl], - hasMoreMessages: Bool) { - if !hasMoreMessages { - reachedHistoryEnd = true - } - - historyMessages = messages + historyMessages - } - - func receiveHistoryUpdate(withMessages messages: [MessageImpl], - idsToDelete: Set, - completion: @escaping (_ endOfBatch: Bool, _ messageDeleted: Bool, _ deletedMesageID: String?, _ messageChanged: Bool, _ changedMessage: MessageImpl?, _ messageAdded: Bool, _ addedMessage: MessageImpl?, _ idBeforeAddedMessage: HistoryID?) -> ()) { - deleteFromHistory(idsToDelete: idsToDelete, - completion: completion) - mergeHistoryChanges(messages: messages, - completion: completion) - - completion(true, false, nil, false, nil, false, nil, nil) - } - - func updateReadBeforeTimestamp(timestamp: Int64) { - self.readBeforeTimestamp = timestamp - } - - // MARK: Private methods - - private func respondTo(messages: [MessageImpl], - limitOfMessages: Int, - completion: ([Message]) -> ()) { - completion((messages.count == 0) ? messages : ((messages.count <= limitOfMessages) ? messages : Array(messages[(messages.count - limitOfMessages) ..< messages.count]))) - } - - private func respondTo(messages: [MessageImpl], - limitOfMessages: Int, - offset: Int, - completion: ([Message]) -> ()) { - let supposedQuantity = offset - limitOfMessages - completion(Array(messages[((supposedQuantity > 0) ? supposedQuantity : 0) ..< offset])) - } - - private func deleteFromHistory(idsToDelete: Set, - completion: (_ endOfBatch: Bool, _ messageDeleted: Bool, _ deletedMesageID: String?, _ messageChanged: Bool, _ changedMessage: MessageImpl?, _ messageAdded: Bool, _ addedMessage: MessageImpl?, _ idBeforeAddedMessage: HistoryID?) -> ()) { - for idToDelete in idsToDelete { - for (index, message) in historyMessages.enumerated() { - if message.getHistoryID()?.getDBid() == idToDelete { - historyMessages.remove(at: index) - completion(false, true, message.getHistoryID()?.getDBid(), false, nil, false, nil, nil) - - break - } - } - } - } - - private func mergeHistoryChanges(messages: [MessageImpl], - completion: (_ endOfBatch: Bool, _ messageDeleted: Bool, _ deletedMesageID: String?, _ messageChanged: Bool, _ changedMessage: MessageImpl?, _ messageAdded: Bool, _ addedMessage: MessageImpl?, _ idBeforeAddedMessage: HistoryID?) -> ()) { - /* - Algorithm merges messages with history messages. - Messages before first history message are ignored. - Messages with the same time in Microseconds with corresponding history messages are replacing them. - Messages after last history message are added in the end. - The rest of the messages are merged in the middle of history messages. - */ - - var receivedMessages = messages - var result = [MessageImpl]() - - outerLoop: for historyMessage in historyMessages { - while receivedMessages.count > 0 { - for message in receivedMessages { - if (message.getTimeInMicrosecond() <= readBeforeTimestamp || readBeforeTimestamp == -1) { - message.setRead(isRead: true) - } - if message.getTimeInMicrosecond() < historyMessage.getTimeInMicrosecond() { - if !result.isEmpty { - result.append(message) - completion(false, false, nil, false, nil, true, message, historyMessage.getHistoryID()) - - receivedMessages.remove(at: 0) - - continue - } else { - receivedMessages.remove(at: 0) - - break - } - } - - if message.getTimeInMicrosecond() > historyMessage.getTimeInMicrosecond() { - result.append(historyMessage) - - continue outerLoop - } - - if message.getTimeInMicrosecond() == historyMessage.getTimeInMicrosecond() { - result.append(message) - completion(false, false, nil, true, message, false, nil, nil) - - receivedMessages.remove(at: 0) - - continue outerLoop - } - } - } - - result.append(historyMessage) - } - - if receivedMessages.count > 0 { - for message in receivedMessages { - result.append(message) - completion(false, false, nil, false, nil, true, message, nil) - } - } - - historyMessages = result - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/MessageComposingHandler.swift b/ios/libs/Webim/WebimClientLibrary/Backend/MessageComposingHandler.swift deleted file mode 100755 index 6866787..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/MessageComposingHandler.swift +++ /dev/null @@ -1,115 +0,0 @@ -// -// MessageComposingHandlerImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 14.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that is responsible for sending drafts of visitor typed messages to an operator side chat. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MessageComposingHandler { - - // MARK: - Constants - private enum Deadline: Int { - case draftSendingInterval = 1 // Second - case resetStatusDelay = 5 // Second - } - - // MARK: - Properties - private let queue: DispatchQueue - private let webimActions: WebimActions - private var latestDraft: String? - private var resetTimer: Timer? - private var updateDraftScheduled = false - - // MARK: - Initialization - init(webimActions: WebimActions, - queue: DispatchQueue) { - self.webimActions = webimActions - self.queue = queue - } - - // MARK: - Methods - - func setComposing(draft: String?) { - latestDraft = draft - - if !updateDraftScheduled { - send(draft: draft) - updateDraftScheduled = true - - queue.asyncAfter(deadline: (DispatchTime.now() + .seconds(Deadline.draftSendingInterval.rawValue)), - execute: { [weak self] in - guard let `self` = self else { - return - } - - self.updateDraftScheduled = false - - if self.latestDraft != draft { - self.send(draft: self.latestDraft) - } - }) - } - - resetTimer?.invalidate() - - if draft != nil { - let resetTime = Date().addingTimeInterval(Double(Deadline.resetStatusDelay.rawValue)) - resetTimer = Timer(fireAt: resetTime, - interval: 0.0, - target: self, - selector: #selector(resetTypingStatus), - userInfo: nil, - repeats: false) - RunLoop.main.add(resetTimer!, - forMode: RunLoop.Mode.common) - } - } - - // MARK: Private methods - - @objc - private func resetTypingStatus() { - queue.async { - self.webimActions.set(visitorTyping: false, - draft: nil, - deleteDraft: false) - } - } - - private func send(draft: String?) { - let visitorTyping = ((draft == nil) ? false : (draft!.isEmpty ? false : true)) - let deleteDraft = ((draft == nil) ? true : (draft!.isEmpty ? true : false)) - webimActions.set(visitorTyping: visitorTyping, - draft: draft, - deleteDraft: deleteDraft) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/MessageHolder.swift b/ios/libs/Webim/WebimClientLibrary/Backend/MessageHolder.swift deleted file mode 100755 index fca4754..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/MessageHolder.swift +++ /dev/null @@ -1,564 +0,0 @@ -// -// MessageHolder.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 20.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MessageHolder { - - // MARK: - Properties - private let accessChecker: AccessChecker - private let historyStorage: HistoryStorage - private let remoteHistoryProvider: RemoteHistoryProvider - private lazy var currentChatMessages = [MessageImpl]() - private var lastChatMessageIndex = 0 - private lazy var messagesToSend = [MessageToSend]() - private var messageTracker: MessageTrackerImpl? - private var reachedEndOfLocalHistory = false - private var reachedEndOfRemoteHistory: Bool - - // MARK: - Initialization - init(accessChecker: AccessChecker, - remoteHistoryProvider: RemoteHistoryProvider, - historyStorage: HistoryStorage, - reachedEndOfRemoteHistory: Bool) { - self.accessChecker = accessChecker - self.remoteHistoryProvider = remoteHistoryProvider - self.historyStorage = historyStorage - self.reachedEndOfRemoteHistory = reachedEndOfRemoteHistory - } - - // MARK: - Methods - - func checkAccess() throws { - try accessChecker.checkAccess() - } - - func getCurrentChatMessages() -> [MessageImpl] { - return currentChatMessages - } - - func set(currentChatMessages: [MessageImpl]) { - self.currentChatMessages = currentChatMessages - } - - func getMessagesToSend() -> [MessageToSend] { - return messagesToSend - } - - func removeFromMessagesToSendAt(index: Int) { - messagesToSend.remove(at: index) - } - - func set(messagesToSend: [MessageToSend]) { - self.messagesToSend = messagesToSend - } - - func getLatestMessages(byLimit limitOfMessages: Int, - completion: @escaping ([Message]) -> ()) { - if !currentChatMessages.isEmpty { - respondTo(messages: currentChatMessages, - limitOfMessages: limitOfMessages, - completion: completion) - } else { - historyStorage.getLatestHistory(byLimit: limitOfMessages, - completion: completion) - } - } - - func getMessagesBy(limit: Int, - before message: MessageImpl, - completion: @escaping ([Message]) -> ()) { - if message.getSource().isCurrentChatMessage() { - if currentChatMessages.isEmpty { - WebimInternalLogger.shared.log(entry: "Current chat is empty. Requesting history rejected.", - verbosityLevel: .VERBOSE) - - completion([Message]()) - - return - } - - let firstMessage = currentChatMessages.first! - if message == firstMessage { - if !firstMessage.hasHistoryComponent() { - historyStorage.getLatestHistory(byLimit: limit, - completion: completion) - } else { - getMessagesFromHistoryBefore(id: firstMessage.getHistoryID()!, - limit: limit, - completion: completion) - } - } else { - getMessagesFromCurrentChatBefore(message: message, - limit: limit, - completion: completion) - } - } else { - getMessagesFromHistoryBefore(id: message.getHistoryID()!, - limit: limit, - completion: completion) - } - } - - func set(messageTracker: MessageTrackerImpl?) { - self.messageTracker = messageTracker - } - - func getHistoryStorage() -> HistoryStorage { - return historyStorage - } - - func set(reachedEndOfLocalHistory: Bool) { - self.reachedEndOfLocalHistory = reachedEndOfLocalHistory - } - - func newMessageTracker(withMessageListener messageListener: MessageListener) throws -> MessageTrackerImpl { - try messageTracker?.destroy() - - set(messageTracker: MessageTrackerImpl(messageListener: messageListener, - messageHolder: self)) - - return messageTracker! - } - - func receiveHistoryUpdateWith(messages: [MessageImpl], - deleted: Set, - completion: @escaping () -> ()) { - historyStorage.receiveHistoryUpdate(withMessages: messages, - idsToDelete: deleted) { [weak self] (endOfBatch: Bool, messageDeleted: Bool, deletedMessageID: String?, messageChanged: Bool, changedMessage: MessageImpl?, messageAdded: Bool, addedMessage: MessageImpl?, idBeforeAddedMessage: HistoryID?) -> () in - if endOfBatch { - self?.messageTracker?.endedHistoryBatch() - - completion() - } - - if messageDeleted { - // Assuming that when messageDeleted == true deletedMessageID cannot be nil. - self?.messageTracker?.deletedHistoryMessage(withID: deletedMessageID!) - } - - if messageChanged { - // Assuming that when messageChanged == true changedMessage cannot be nil. - self?.messageTracker?.changedHistory(message: changedMessage!) - } - - if messageAdded { - // Assuming that when messageAdded == true addedMessage cannot be nil. - if (self?.tryMergeWithLastChat(message: addedMessage!) != true) { - self?.messageTracker?.addedHistory(message: addedMessage!, - before: idBeforeAddedMessage) - } - } - } - } - - func receiving(newChat: ChatItem?, - previousChat: ChatItem?, - newMessages: [MessageImpl]) { - if currentChatMessages.isEmpty { - receive(newMessages: newMessages) - } else { - if newChat == nil { - historifyCurrentChat() - } else if (previousChat == nil) || - (newChat != previousChat) { - historifyCurrentChat() - - receive(newMessages: newMessages) - } else { - mergeCurrentChatWith(newMessages: newMessages) - } - } - } - - func receive(newMessage: MessageImpl) { - if messageTracker != nil { - messageTracker!.addedNew(message: newMessage, - of: self) - } else { - currentChatMessages.append(newMessage) - } - } - - func changed(message: MessageImpl) { - for messageIndex in lastChatMessageIndex ..< currentChatMessages.count { - let previousVersion = currentChatMessages[messageIndex] - if previousVersion.getCurrentChatID() == message.getCurrentChatID() { - currentChatMessages[messageIndex] = message - - messageTracker?.changedCurrentChatMessage(from: previousVersion, - to: message, - at: messageIndex, - of: self) - - return - } - } - } - - func deletedMessageWith(id: String) { - for messageIndex in lastChatMessageIndex ..< currentChatMessages.count { - let message = currentChatMessages[messageIndex] - if message.getCurrentChatID() == id { - currentChatMessages.remove(at: messageIndex) - - messageTracker?.deletedCurrentChat(message: message, - at: messageIndex, - messageHolder: self) - - return - } - } - } - - func sending(message: MessageToSend) { - messagesToSend.append(message) - - messageTracker?.messageListener?.added(message: message, - after: nil) - } - - func sendingCancelledWith(messageID: String) { - for messageIndex in 0 ..< messagesToSend.count { - if messagesToSend[messageIndex].getID() == messageID { - let message = messagesToSend[messageIndex] - - messagesToSend.remove(at: messageIndex) - - messageTracker?.messageListener?.removed(message: message) - - return - } - } - } - - func changing(messageID: String, message: String?) -> String? { - if messageTracker == nil { - return nil - } - var messageImpl: MessageImpl? = nil - - for curr in currentChatMessages { - if curr.getID() == messageID { - messageImpl = curr - break - } - } - - if messageImpl == nil { - return nil - } - - let newMessage = MessageImpl(serverURLString: (messageImpl?.getServerUrlString())!, - id: messageID, - operatorID: messageImpl?.getOperatorID(), - senderAvatarURLString: messageImpl?.getSenderAvatarURLString(), - senderName: (messageImpl?.getSenderName())!, - sendStatus: .SENDING, - type: (messageImpl?.getType())!, - data: messageImpl?.getData(), - text: (message == nil ? messageImpl?.getText() : message)!, - timeInMicrosecond: (messageImpl?.getTimeInMicrosecond())!, - attachment: messageImpl?.getAttachment(), - historyMessage: (messageImpl?.getSource().isHistoryMessage())!, - internalID: messageImpl?.getCurrentChatID(), - rawText: messageImpl?.getRawText(), - read: (messageImpl?.isReadByOperator())!, - messageCanBeEdited: (messageImpl?.canBeEdited())!) - messageTracker?.messageListener?.changed(message: messageImpl!, to: newMessage) - return messageImpl?.getText() - } - - func changingCancelledWith(messageID: String, message: String) { - if messageTracker == nil { - return - } - var messageImpl: MessageImpl? = nil - - for curr in currentChatMessages { - if curr.getID() == messageID { - messageImpl = curr - break - } - } - - if messageImpl == nil { - return - } - - let newMessage = MessageImpl(serverURLString: (messageImpl?.getServerUrlString())!, - id: messageID, - operatorID: messageImpl?.getOperatorID(), - senderAvatarURLString: messageImpl?.getSenderAvatarURLString(), - senderName: (messageImpl?.getSenderName())!, - sendStatus: .SENT, - type: (messageImpl?.getType())!, - data: messageImpl?.getData(), - text: message, - timeInMicrosecond: (messageImpl?.getTimeInMicrosecond())!, - attachment: messageImpl?.getAttachment(), - historyMessage: (messageImpl?.getSource().isHistoryMessage())!, - internalID: messageImpl?.getCurrentChatID(), - rawText: messageImpl?.getRawText(), - read: (messageImpl?.isReadByOperator())!, - messageCanBeEdited: (messageImpl?.canBeEdited())!) - messageTracker?.messageListener?.changed(message: messageImpl!, to: newMessage) - } - - // MARK: For testing purposes. - - func getLastChatMessageIndex() -> Int { - return lastChatMessageIndex - } - - func getRemoteHistoryProvider() -> RemoteHistoryProvider { - return remoteHistoryProvider - } - - func set(endOfHistoryReached: Bool) { - reachedEndOfRemoteHistory = endOfHistoryReached - historyStorage.set(reachedHistoryEnd: endOfHistoryReached) - } - - // MARK: Private methods - - private func receive(newMessages: [MessageImpl]) { - if messageTracker != nil { - messageTracker!.addedNew(messages: newMessages, - of: self) - } else { - for message in newMessages { - currentChatMessages.append(message) - } - } - } - - private func respondTo(messages: [MessageImpl], - limitOfMessages: Int, - completion: ([Message]) -> ()) { - completion(messages.isEmpty - ? [MessageImpl]() - : (messages.count <= limitOfMessages) ? messages : Array(messages[(messages.count - limitOfMessages) ..< messages.count])) - } - - private func respondTo(messages: [MessageImpl], - limitOfMessages: Int, - offset: Int, - completion: ([Message]) -> ()) { - let messageList = Array(messages[max(0, (offset - limitOfMessages)) ..< offset]) - completion(messageList) - } - - private func historifyCurrentChat() { - var newCurrentChatMessages = [MessageImpl]() - - for currentChatMessage in currentChatMessages { - if currentChatMessage.hasHistoryComponent() { - currentChatMessage.invertHistoryStatus() - - if let id = currentChatMessage.getHistoryID()?.getDBid() { - if let historyMessage = messageTracker?.idToHistoryMessageMap[id] { - historyMessage.setMessageCanBeEdited(messageCanBeEdited: false) - if currentChatMessage != historyMessage { - messageTracker?.messageListener?.changed(message: currentChatMessage, - to: historyMessage) - } else { - messageTracker?.idToHistoryMessageMap[id] = currentChatMessage - } - } - } - } else { - newCurrentChatMessages.append(currentChatMessage) - if currentChatMessage.canBeEdited() { - currentChatMessage.setMessageCanBeEdited(messageCanBeEdited: false) - messageTracker?.messageListener?.changed(message: currentChatMessage, to: currentChatMessage) - } - } - } - - self.set(currentChatMessages: newCurrentChatMessages) - - lastChatMessageIndex = currentChatMessages.count - } - - private func requestHistory(beforeID id: HistoryID, - limit: Int, - completion: @escaping ([Message]) -> ()) { - remoteHistoryProvider.requestHistory(beforeTimestamp: id.getTimeInMicrosecond(), - completion: { [weak self] (messages: [MessageImpl], hasMoreMessages: Bool) in - if messages.isEmpty { - self?.reachedEndOfRemoteHistory = true - } else { - self?.historyStorage.receiveHistoryBefore(messages: messages, - hasMoreMessages: hasMoreMessages) - } - - self?.respondTo(messages: messages, - limitOfMessages: limit, - completion: completion) - }) - } - - private func getMessagesFromHistoryBefore(id: HistoryID, - limit: Int, - completion: @escaping ([Message]) -> ()) { - if reachedEndOfLocalHistory != true { - historyStorage.getHistoryBefore(id: id, - limitOfMessages: limit, - completion: { [weak self] messages in - if !messages.isEmpty { - completion(messages) - } else { - self?.reachedEndOfLocalHistory = true - self?.getMessagesFromHistoryBefore(id: id, - limit: limit, - completion: completion) - } - }) - } else if reachedEndOfRemoteHistory == true { - completion([MessageImpl]()) - } else { - requestHistory(beforeID: id, - limit: limit, - completion: completion) - } - } - - private func getMessagesFromCurrentChatBefore(message: MessageImpl, - limit: Int, - completion: ([Message]) -> ()) { - do { - try message.getSource().assertIsCurrentChat() - } catch { - WebimInternalLogger.shared.log(entry: "Message before which messages are requested is not a part of current chat: \(message.toString()).", - verbosityLevel: .DEBUG) - - return - } - - let messageIndex = currentChatMessages.index(of: message)! - - guard messageIndex >= 1 else { - WebimInternalLogger.shared.log(entry: "Message \(message.toString()) before which messages of current chat are requested can't have index less than 1. Current index: \(messageIndex).", - verbosityLevel: .DEBUG) - - return - } - - respondTo(messages: currentChatMessages, - limitOfMessages: limit, - offset: messageIndex, - completion: completion) - } - - private func mergeCurrentChatWith(newMessages: [MessageImpl]) { - var previousMessageIndex = lastChatMessageIndex - var areOldMessagesEnded = false - - for messageIndex in 0 ..< newMessages.count { - let newMessage = newMessages[messageIndex] - - if !areOldMessagesEnded { - var isMerged = false - - while previousMessageIndex < currentChatMessages.count { - let previousMessage = currentChatMessages[previousMessageIndex] - if previousMessage.getID() == newMessage.getID() { - if previousMessage != newMessage { - currentChatMessages[previousMessageIndex] = newMessage - - messageTracker?.changedCurrentChatMessage(from: previousMessage, - to: newMessage, - at: previousMessageIndex, - of: self) - } - - isMerged = true - - previousMessageIndex = previousMessageIndex + 1 - - break - } else { - currentChatMessages.remove(at: previousMessageIndex) - - messageTracker?.deletedCurrentChat(message: previousMessage, - at: previousMessageIndex, - messageHolder: self) - } - } // End of "while previousMessageIndex < currentChatMessages.count". - - if !isMerged && - (previousMessageIndex >= currentChatMessages.count) { - areOldMessagesEnded = true - } - } // End of "if !areOldMessagesEnded". - - if areOldMessagesEnded { - receive(newMessage: newMessage) - } - } - } - - private func tryMergeWithLastChat(message: MessageImpl) -> Bool { - for (currentChatMessageIndex, currentChatMessage) in currentChatMessages.enumerated() { - guard currentChatMessage.getID() == message.getID() else { - continue - } - - if currentChatMessageIndex < lastChatMessageIndex { - let replacementMessage = currentChatMessage.transferToHistory(message: message) - messageTracker?.idToHistoryMessageMap[message.getHistoryID()!.getDBid()] = replacementMessage - - if replacementMessage != currentChatMessage { - messageTracker?.messageListener?.changed(message: currentChatMessage, - to: replacementMessage) - } - - currentChatMessages.remove(at: currentChatMessageIndex) - lastChatMessageIndex -= 1 - } else { - currentChatMessage.setSecondaryHistory(historyEquivalentMessage: message) - - messageTracker?.idToHistoryMessageMap[message.getHistoryID()!.getDBid()] = message - } - - return true - } - - return false - } - - func updateReadBeforeTimestamp(timestamp: Int64) { - historyStorage.updateReadBeforeTimestamp(timestamp: timestamp) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/MessageToSend.swift b/ios/libs/Webim/WebimClientLibrary/Backend/MessageToSend.swift deleted file mode 100755 index e69061d..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/MessageToSend.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// MessageToSend.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 17.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Message subtype which is used when message is sending by visitor at the moment. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MessageToSend: MessageImpl { - - // MARK: - Initialization - init(serverURLString: String, - id: String, - senderName: String, - type: MessageType, - text: String, - timeInMicrosecond: Int64) { - super.init(serverURLString: serverURLString, - id: id, - operatorID: nil, - senderAvatarURLString: nil, - senderName: senderName, - sendStatus: .SENDING, - type: type, - data: nil, - text: text, - timeInMicrosecond: timeInMicrosecond, - attachment: nil, - historyMessage: false, - internalID: nil, - rawText: nil, - read: false, - messageCanBeEdited: false) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/ProvidedVisitorFields.swift b/ios/libs/Webim/WebimClientLibrary/Backend/ProvidedVisitorFields.swift deleted file mode 100755 index 504d9a2..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/ProvidedVisitorFields.swift +++ /dev/null @@ -1,106 +0,0 @@ -// -// ProvidedVisitorFields.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 08.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates unique visitor data. - - Author: - Nikita Lazarev-Zubov - - Copyright: - 2017 Webim - */ -final class ProvidedVisitorFields { - - // MARK: - Properties - private let id: String - private let jsonString: String - - // MARK: - Initialization - - convenience init?(withJSONString jsonString: String) { - if let jsonData = jsonString.data(using: .utf8) { - self.init(jsonString: jsonString, - JSONObject: jsonData) - } else { - return nil - } - } - - convenience init?(withJSONObject jsonData: Data) { - let jsonString = String(data: jsonData, - encoding: .utf8) - - self.init(jsonString: jsonString!, - JSONObject: jsonData) - - } - - private init?(jsonString: String, - JSONObject: Data) { - do { - if let jsonData = try JSONSerialization.jsonObject(with: JSONObject) as? [String: Any] { - if let fields = jsonData["fields"] as? [String: String] { - if let id = fields["id"] { - self.id = id - } else { - throw VisitorFieldsError.invalidVisitorFields("Visitor fields JSON object must contain ID field") - } - } else if let id = jsonData["id"] as? String { - self.id = id - } else { - throw VisitorFieldsError.invalidVisitorFields("Visitor fields JSON object must contain ID field") - } - } else { - throw VisitorFieldsError.serializingFail("Error serializing visitor JSON data.") - } - - self.jsonString = jsonString - } catch { - WebimInternalLogger.shared.log(entry: "Error serializing provided visitor fields: \(String(data: JSONObject, encoding: .utf8) ?? "unreadable data").", - verbosityLevel: .DEBUG) - - return nil - } - } - - // MARK: - Methods - - func getID() -> String { - return id - } - - func getJSONString() -> String { - return jsonString - } - - // MARK: - - enum VisitorFieldsError: Error { - case serializingFail(String) - case invalidVisitorFields(String) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/RemoteHistoryProvider.swift b/ios/libs/Webim/WebimClientLibrary/Backend/RemoteHistoryProvider.swift deleted file mode 100755 index f5e3d9c..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/RemoteHistoryProvider.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// RemoteHistoryProvider.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.09.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -class RemoteHistoryProvider { - - // MARK: - Properties - private var webimActions: WebimActions - private var historyMessageMapper: MessageMapper - private var historyMetaInformationStorage: HistoryMetaInformationStorage - - // MARK: - Initialization - init(webimActions: WebimActions, - historyMessageMapper: MessageMapper, - historyMetaInformationStorage: HistoryMetaInformationStorage) { - self.webimActions = webimActions - self.historyMessageMapper = historyMessageMapper - self.historyMetaInformationStorage = historyMetaInformationStorage - } - - // MARK: - Methods - func requestHistory(beforeTimestamp: Int64, - completion: @escaping ([MessageImpl], Bool) -> ()) { - webimActions.requestHistory(beforeMessageTimestamp: beforeTimestamp) { [weak self] data in - guard data != nil, - let `self` = self else { - completion([MessageImpl](), false) - - return - } - - let json = try? JSONSerialization.jsonObject(with: data!, - options: []) - if let historyBeforeResponseDictionary = json as? [String: Any?] { - let historyBeforeResponse = HistoryBeforeResponse(jsonDictionary: historyBeforeResponseDictionary) - - if let messages = historyBeforeResponse.getData()?.getMessages() { - completion(self.historyMessageMapper.mapAll(messages: messages), (historyBeforeResponse.getData()?.isHasMore() == true)) - - if historyBeforeResponse.getData()?.isHasMore() != true { - self.historyMetaInformationStorage.set(historyEnded: true) - } - } else { - completion([MessageImpl](), false) - self.historyMetaInformationStorage.set(historyEnded: true) - } - } - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/SQLiteHistoryStorage.swift b/ios/libs/Webim/WebimClientLibrary/Backend/SQLiteHistoryStorage.swift deleted file mode 100755 index 83c715d..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/SQLiteHistoryStorage.swift +++ /dev/null @@ -1,677 +0,0 @@ -// -// SQLiteHistoryStorage.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.08.17. -// Copyright В© 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import SQLite - -/** - Class that is responsible for history storage inside SQLite DB. Uses SQLite.swift library. - - seealso: - https://github.com/stephencelis/SQLite.swift - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class SQLiteHistoryStorage: HistoryStorage { - - // MARK: - Constants - - // MARK: SQLite tables and columns names - private enum TableName: String { - case history = "history" - } - private enum ColumnName: String { - // In DB columns order. - case id = "id" - case clientSideID = "client_side_id" - case timestamp = "timestamp" - case senderID = "sender_id" - case senderName = "sender_name" - case avatarURLString = "avatar_url_string" - case type = "type" - case text = "text" - case data = "data" - } - - // MARK: SQLite.swift abstractions - - private static let history = Table(TableName.history.rawValue) - - // In DB columns order. - private static let id = Expression(ColumnName.id.rawValue) - private static let clientSideID = Expression(ColumnName.clientSideID.rawValue) - private static let timestamp = Expression(ColumnName.timestamp.rawValue) - private static let senderID = Expression(ColumnName.senderID.rawValue) - private static let senderName = Expression(ColumnName.senderName.rawValue) - private static let avatarURLString = Expression(ColumnName.avatarURLString.rawValue) - private static let type = Expression(ColumnName.type.rawValue) - private static let text = Expression(ColumnName.text.rawValue) - private static let data = Expression(ColumnName.data.rawValue) - - - // MARK: - Properties - private static let queryQueue = DispatchQueue(label: "SQLiteHistoryStorageQueryQueue", qos: .background) - private let completionHandlerQueue: DispatchQueue - private let serverURLString: String - private let webimClient: WebimClient - private var db: Connection? - private var firstKnownTimestamp: Int64 = -1 - private var readBeforeTimestamp: Int64 - private var prepared = false - private var reachedHistoryEnd: Bool - - - // MARK: - Initialization - init(dbName: String, - serverURL serverURLString: String, - webimClient: WebimClient, - reachedHistoryEnd: Bool, - queue: DispatchQueue, - readBeforeTimestamp: Int64) { - self.serverURLString = serverURLString - self.webimClient = webimClient - self.reachedHistoryEnd = reachedHistoryEnd - self.completionHandlerQueue = queue - self.readBeforeTimestamp = readBeforeTimestamp - - createTableWith(name: dbName) - } - - // MARK: - Methods - - // MARK: HistoryStorage protocol methods - - func getMajorVersion() -> Int { - // No need in this implementation. - return 1 - } - - func getVersionDB() -> Int { - return 1 - } - - func set(reachedHistoryEnd: Bool) { - self.reachedHistoryEnd = reachedHistoryEnd - } - - func updateDB() { - dropTables() - createTables() - } - - func getFullHistory(completion: @escaping ([Message]) -> ()) { - SQLiteHistoryStorage.queryQueue.async { [weak self] in - guard let `self` = self else { - return - } - - /* - SELECT * FROM history - ORDER BY timestamp_in_microsecond ASC - */ - let query = SQLiteHistoryStorage - .history - .order(SQLiteHistoryStorage.timestamp.asc) - - var messages = [MessageImpl]() - - do { - for row in try self.db!.prepare(query) { - let message = self.createMessageBy(row: row) - messages.append(message) - - self.db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - } - - self.completionHandlerQueue.async { - completion(messages as [Message]) - } - } catch { - WebimInternalLogger.shared.log(entry: error.localizedDescription, - verbosityLevel: .WARNING) - } - } - } - - func getLatestHistory(byLimit limitOfMessages: Int, - completion: @escaping ([Message]) -> ()) { - SQLiteHistoryStorage.queryQueue.async { [weak self] in - guard let `self` = self else { - return - } - - /* - SELECT * FROM history - ORDER BY timestamp_in_microsecond DESC - LIMIT limitOfMessages - */ - let query = SQLiteHistoryStorage - .history - .order(SQLiteHistoryStorage.timestamp.desc) - .limit(limitOfMessages) - - var messages = [MessageImpl]() - - do { - for row in try self.db!.prepare(query) { - let message = self.createMessageBy(row: row) - messages.append(message) - } - - self.db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - - messages = messages.reversed() - self.completionHandlerQueue.async { - completion(messages as [Message]) - } - } catch { - WebimInternalLogger.shared.log(entry: error.localizedDescription, - verbosityLevel: .WARNING) - } - } - } - - func getHistoryBefore(id: HistoryID, - limitOfMessages: Int, - completion: @escaping ([Message]) -> ()) { - SQLiteHistoryStorage.queryQueue.async { [weak self] in - guard let `self` = self else { - return - } - - let beforeTimeInMicrosecond = id.getTimeInMicrosecond() - - /* - SELECT * FROM history - WHERE timestamp_in_microsecond < beforeTimeInMicrosecond - ORDER BY timestamp_in_microsecond DESC - LIMIT limitOfMessages - */ - let query = SQLiteHistoryStorage - .history - .filter(SQLiteHistoryStorage.timestamp < beforeTimeInMicrosecond) - .order(SQLiteHistoryStorage.timestamp.desc) - .limit(limitOfMessages) - - var messages = [MessageImpl]() - - do { - for row in try self.db!.prepare(query) { - let message = self.createMessageBy(row: row) - messages.append(message) - - self.db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - } - - messages = messages.reversed() - self.completionHandlerQueue.async { - completion(messages as [Message]) - } - } catch { - WebimInternalLogger.shared.log(entry: error.localizedDescription, - verbosityLevel: .WARNING) - } - } - } - - func receiveHistoryBefore(messages: [MessageImpl], - hasMoreMessages: Bool) { - SQLiteHistoryStorage.queryQueue.async { [weak self] in - guard let `self` = self else { - return - } - - var newFirstKnownTimeInMicrosecond = Int64.max - - for message in messages { - newFirstKnownTimeInMicrosecond = min(newFirstKnownTimeInMicrosecond, - message.getHistoryID()!.getTimeInMicrosecond()) - do { - /* - INSERT OR FAIL - INTO history - (id, timestamp_in_microsecond, sender_id, sender_name, avatar_url_string, type, text, data) - VALUES - (message.getID(), message.getHistoryID()!.getTimeInMicrosecond(), message.getOperatorID(), message.getSenderName(), message.getSenderAvatarURLString(), MessageItem.MessageKind(messageType: message.getType()).rawValue, message.getRawText() ?? message.getText(), SQLiteHistoryStorage.convertToBlob(dictionary: message.getData())) - */ - let statement = try self.db!.prepare("INSERT OR FAIL INTO history (" - + "\(SQLiteHistoryStorage.ColumnName.id.rawValue), " - + "\(SQLiteHistoryStorage.ColumnName.timestamp.rawValue), " - + "\(SQLiteHistoryStorage.ColumnName.senderID.rawValue), " - + "\(SQLiteHistoryStorage.ColumnName.senderName.rawValue), " - + "\(SQLiteHistoryStorage.ColumnName.avatarURLString.rawValue), " - + "\(SQLiteHistoryStorage.ColumnName.type.rawValue), " - + "\(SQLiteHistoryStorage.ColumnName.text.rawValue), " - + "\(SQLiteHistoryStorage.ColumnName.data.rawValue)) VALUES (?, ?, ?, ?, ?, ?, ?, ?)") - try statement.run(message.getID(), - message.getHistoryID()!.getTimeInMicrosecond(), - message.getOperatorID(), - message.getSenderName(), - message.getSenderAvatarURLString(), - MessageItem.MessageKind(messageType: message.getType()).rawValue, - message.getRawText() ?? message.getText(), - SQLiteHistoryStorage.convertToBlob(dictionary: message.getData())) - // Raw SQLite statement constructed because there's no way to implement INSERT OR FAIL query with SQLite.swift methods. Appropriate INSERT query can look like this: - /*try self.db!.run(SQLiteHistoryStorage - .history - .insert(SQLiteHistoryStorage.id <- message.getID(), - SQLiteHistoryStorage.timestampInMicrosecond <- message.getTimeInMicrosecond(), - SQLiteHistoryStorage.senderID <- message.getOperatorID(), - SQLiteHistoryStorage.senderName <- message.getSenderName(), - SQLiteHistoryStorage.avatarURLString <- message.getSenderAvatarURLString(), - SQLiteHistoryStorage.type <- MessageItem.MessageKind(messageType: message.getType()).rawValue, - SQLiteHistoryStorage.text <- message.getText(), - SQLiteHistoryStorage.data <- SQLiteHistoryStorage.convertToBlob(dictionary: message.getData())))*/ - - self.db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - } catch { - WebimInternalLogger.shared.log(entry: error.localizedDescription, - verbosityLevel: .WARNING) - } - } - - if newFirstKnownTimeInMicrosecond != Int64.max { - self.firstKnownTimestamp = newFirstKnownTimeInMicrosecond - } - } - } - - func receiveHistoryUpdate(withMessages messages: [MessageImpl], - idsToDelete: Set, - completion: @escaping (_ endOfBatch: Bool, _ messageDeleted: Bool, _ deletedMesageID: String?, _ messageChanged: Bool, _ changedMessage: MessageImpl?, _ messageAdded: Bool, _ addedMessage: MessageImpl?, _ idBeforeAddedMessage: HistoryID?) -> ()) { - SQLiteHistoryStorage.queryQueue.sync { [weak self] in - guard let `self` = self else { - return - } - - self.prepare() - - var newFirstKnownTimestamp = Int64.max - - for message in messages { - guard message.getHistoryID() != nil else { - continue - } - - if ((self.firstKnownTimestamp != -1) - && (message.getHistoryID()!.getTimeInMicrosecond() < self.firstKnownTimestamp)) - && !self.reachedHistoryEnd { - continue - } - - newFirstKnownTimestamp = min(newFirstKnownTimestamp, - message.getHistoryID()!.getTimeInMicrosecond()) - - do { - try self.insert(message: message) - - /* - SELECT * - FROM history - WHERE timestamp > message.getTimeInMicrosecond() - ORDER BY timestamp ASC - LIMIT 1 - */ - let postQuery = SQLiteHistoryStorage - .history - .filter(SQLiteHistoryStorage.timestamp > message.getTimeInMicrosecond()) - .order(SQLiteHistoryStorage.timestamp.asc) - .limit(1) - do { - if let row = try self.db!.pluck(postQuery) { - self.db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - - let nextMessage = self.createMessageBy(row: row) - completionHandlerQueue.async { - completion(false, - false, - nil, - false, - nil, - true, - message, - nextMessage.getHistoryID()!) - } - } else { - completionHandlerQueue.async { - completion(false, - false, - nil, - false, - nil, - true, - message, - nil) - } - } - } catch let error { - WebimInternalLogger.shared.log(entry: error.localizedDescription, - verbosityLevel: .WARNING) - } - } catch let Result.error(_, code, _) where code == SQLITE_CONSTRAINT { - do { - try update(message: message) - - completionHandlerQueue.async { - completion(false, false, nil, true, message, false, nil, nil) - } - } catch { - WebimInternalLogger.shared.log(entry: "Update received message: \(message.toString()) failed: \(error.localizedDescription)", - verbosityLevel: .ERROR) - } - } catch { - WebimInternalLogger.shared.log(entry: "Insert / update received message: \(message.toString()) failed: \(error.localizedDescription)", - verbosityLevel: .ERROR) - } - } // End of `for message in messages` - - if (firstKnownTimestamp == -1) - && (newFirstKnownTimestamp != Int64.max) { - firstKnownTimestamp = newFirstKnownTimestamp - } - - self.completionHandlerQueue.async { - completion(true, false, nil, false, nil, false, nil, nil) - } - } - } - - func updateReadBeforeTimestamp(timestamp: Int64) { - self.readBeforeTimestamp = timestamp - } - - // MARK: Private methods - - private static func convertToBlob(dictionary: [String: Any?]?) -> Blob? { - if let dictionary = dictionary { - let data = NSKeyedArchiver.archivedData(withRootObject: dictionary) - - return data.datatypeValue - } - - return nil - } - - private func dropTables() { - try! self.db?.run(SQLiteHistoryStorage.history.drop(ifExists: true)) - } - - private func createTableWith(name: String) { - SQLiteHistoryStorage.queryQueue.sync { [weak self] in - guard let `self` = self else { - return - } - - let fileManager = FileManager.default - let documentsPath = try! fileManager.url(for: .documentDirectory, - in: .userDomainMask, - appropriateFor: nil, - create: false) - let dbPath = "\(documentsPath)/\(name)" - self.db = try! Connection(dbPath) - self.db?.userVersion = 1 - self.db?.busyTimeout = 1.0 - self.db?.busyHandler() { tries in - if tries >= 3 { - return false - } - - return true - } - - createTables() - } - } - - private func createTables() { - /* - CREATE TABLE history - id TEXT PRIMARY KEY NOT NULL, - client_side_id TEXT, - timestamp_in_microsecond INTEGER NOT NULL, - sender_id TEXT, - sender_name TEXT NOT NULL, - avatar_url_string TEXT, - type TEXT NOT NULL, - text TEXT NOT NULL, - data TEXT - */ - try! self.db?.run(SQLiteHistoryStorage.history.create(ifNotExists: true) { t in - t.column(SQLiteHistoryStorage.id, - primaryKey: true) - t.column(SQLiteHistoryStorage.clientSideID) - t.column(SQLiteHistoryStorage.timestamp) - t.column(SQLiteHistoryStorage.senderID) - t.column(SQLiteHistoryStorage.senderName) - t.column(SQLiteHistoryStorage.avatarURLString) - t.column(SQLiteHistoryStorage.type) - t.column(SQLiteHistoryStorage.text) - t.column(SQLiteHistoryStorage.data) - }) - self.db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - } - - private func createIndex() { - do { - /* - CREATE UNIQUE INDEX index_history_on_timestamp_in_microsecond - ON history (time_since_in_microsecond) - */ - _ = try db?.run(SQLiteHistoryStorage - .history - .createIndex(SQLiteHistoryStorage.timestamp, - unique: true)) - } catch { - WebimInternalLogger.shared.log(entry: error.localizedDescription, - verbosityLevel: .VERBOSE) - } - - db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - - createIndex() - } - - private func prepare() { - if !prepared { - prepared = true - - /* - SELECT timestamp_in_microsecond - FROM history - ORDER BY timestamp_in_microsecond ASC - LIMIT 1 - */ - let query = SQLiteHistoryStorage - .history - .select(SQLiteHistoryStorage.timestamp) - .order(SQLiteHistoryStorage.timestamp.asc) - .limit(1) - - do { - if let row = try self.db!.pluck(query) { - db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - - firstKnownTimestamp = row[SQLiteHistoryStorage.timestamp] - } - } catch { - WebimInternalLogger.shared.log(entry: error.localizedDescription, - verbosityLevel: .WARNING) - } - } - } - - private func createMessageBy(row: Row) -> MessageImpl { - let id = row[SQLiteHistoryStorage.id] - let clientSideID = row[SQLiteHistoryStorage.clientSideID] - - var rawText: String? = nil - var text = row[SQLiteHistoryStorage.text] - let type = MessageMapper.convert(messageKind: MessageItem.MessageKind(rawValue: row[SQLiteHistoryStorage.type])!) - if (type == .FILE_FROM_OPERATOR) - || (type == .FILE_FROM_VISITOR) { - rawText = text - text = "" - } - - var data: [String: Any?]? - if let dataValue = row[SQLiteHistoryStorage.data] { - data = NSKeyedUnarchiver.unarchiveObject(with: Data.fromDatatypeValue(dataValue)) as? [String: Any?] - } - - - var attachment: MessageAttachment? = nil - if let rawText = rawText { - attachment = MessageAttachmentImpl.getAttachment(byServerURL: serverURLString, - webimClient: webimClient, - text: rawText) - } - - return MessageImpl(serverURLString: serverURLString, - id: (clientSideID ?? id), - operatorID: row[SQLiteHistoryStorage.senderID], - senderAvatarURLString: row[SQLiteHistoryStorage.avatarURLString], - senderName: row[SQLiteHistoryStorage.senderName], - type: type!, - data: data, - text: text, - timeInMicrosecond: row[SQLiteHistoryStorage.timestamp], - attachment: attachment, - historyMessage: true, - internalID: id, - rawText: rawText, - read: row[SQLiteHistoryStorage.timestamp] <= readBeforeTimestamp || readBeforeTimestamp == -1, - messageCanBeEdited: false) - } - - private func insert(message: MessageImpl) throws { - /* - INSERT INTO history (id, - client_side_id, - timestamp, - sender_id, - sender_name, - avatar_url_string, - type, - text, - data - ) VALUES ( - historyID.getDBid(), - message.getID(), - timeInMicorsecond, - message.getOperatorID(), - message.getSenderName(), - message.getSenderAvatarURLString(), - MessageItem.MessageKind(messageType: message.getType()).rawValue, - (message.getRawText() ?? message.getText()), - SQLiteHistoryStorage.convertToBlob(dictionary: message.getData()))) - */ - try db?.run(SQLiteHistoryStorage - .history - .insert(SQLiteHistoryStorage.id <- message.getHistoryID()!.getDBid(), - SQLiteHistoryStorage.clientSideID <- message.getID(), - SQLiteHistoryStorage.timestamp <- message.getHistoryID()!.getTimeInMicrosecond(), - SQLiteHistoryStorage.senderID <- message.getOperatorID(), - SQLiteHistoryStorage.senderName <- message.getSenderName(), - SQLiteHistoryStorage.avatarURLString <- message.getSenderAvatarURLString(), - SQLiteHistoryStorage.type <- MessageItem.MessageKind(messageType: message.getType()).rawValue, - SQLiteHistoryStorage.text <- (message.getRawText() ?? message.getText()), - SQLiteHistoryStorage.data <- SQLiteHistoryStorage.convertToBlob(dictionary: message.getData()))) - - db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - } - - private func update(message: MessageImpl) throws { - /* - UPDATE history - SET ( - client_side_id = message.getID(), - timestamp = message.getHistoryID()!.getTimeInMicrosecond(), - sender_id = message.getOperatorID(), - sender_name = message.getSenderName(), - avatar_url_string = message.getSenderAvatarURLString(), - type = MessageItem.MessageKind(messageType: message.getType()).rawValue, - text = (message.getRawText() ?? message.getText()), - data = SQLiteHistoryStorage.convertToBlob(dictionary: message.getData())) - WHERE id = message.getHistoryID()!.getDBid() - */ - try db!.run(SQLiteHistoryStorage - .history - .where(SQLiteHistoryStorage.id == message.getHistoryID()!.getDBid()) - .update(SQLiteHistoryStorage.clientSideID <- message.getID(), - SQLiteHistoryStorage.timestamp <- message.getHistoryID()!.getTimeInMicrosecond(), - SQLiteHistoryStorage.senderID <- message.getOperatorID(), - SQLiteHistoryStorage.senderName <- message.getSenderName(), - SQLiteHistoryStorage.avatarURLString <- message.getSenderAvatarURLString(), - SQLiteHistoryStorage.type <- MessageItem.MessageKind(messageType: message.getType()).rawValue, - SQLiteHistoryStorage.text <- (message.getRawText() ?? message.getText()), - SQLiteHistoryStorage.data <- SQLiteHistoryStorage.convertToBlob(dictionary: message.getData()))) - - db?.trace { - WebimInternalLogger.shared.log(entry: "\($0)", - verbosityLevel: .DEBUG) - } - } - -} - -// MARK: - -extension Connection { - - // MARK: - Properties - public var userVersion: Int32 { - get { return Int32(try! scalar("PRAGMA user_version") as! Int64) } - set { try! run("PRAGMA user_version = \(newValue)") } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/SessionDestroyer.swift b/ios/libs/Webim/WebimClientLibrary/Backend/SessionDestroyer.swift deleted file mode 100755 index a1a93a1..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/SessionDestroyer.swift +++ /dev/null @@ -1,71 +0,0 @@ -// -// SessionDestroyer.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.09.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class SessionDestroyer { - - // MARK: - Properties - private lazy var actions = [() -> ()]() - private var destroyed = false - private var userDefaultsKey: String - - init(userDefaultsKey: String) { - self.userDefaultsKey = userDefaultsKey - } - - // MARK: - Methods - - func add(action: @escaping () -> ()) { - actions.append(action) - } - - func getUserDefaulstKey() -> String { - return userDefaultsKey - } - - func destroy() { - if !destroyed { - destroyed = true - - for action in actions { - action() - } - actions.removeAll(keepingCapacity: false) - } - } - - func isDestroyed() -> Bool { - return destroyed - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/SessionParametersListener.swift b/ios/libs/Webim/WebimClientLibrary/Backend/SessionParametersListener.swift deleted file mode 100755 index 0168bae..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/SessionParametersListener.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// SessionParametersListener.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that is responsible for history storage when it is set to memory mode. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -protocol SessionParametersListener { - - func onSessionParametersChanged(visitorFieldsJSONString: String, - sessionID: String, - authorizationData: AuthorizationData) - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/CompletionHandlerWrappers.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/CompletionHandlerWrappers.swift deleted file mode 100755 index 7cb795b..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/CompletionHandlerWrappers.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// CompletionHandlerWrappers.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 20.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class used for handling storing cached completion handler in `MessageTrackerImpl` class. - - seealso: - `MessageTrackerImpl.cachedCompletionHandler` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MessageHolderCompletionHandlerWrapper { - - // MARK: - Properties - private var messageHolderCompletionHandler: ([Message]) -> () - - // MARK: - Initialization - init(completionHandler: @escaping ([Message]) -> ()) { - messageHolderCompletionHandler = completionHandler - } - - // MARK: - Methods - func getCompletionHandler() -> ([Message]) -> () { - return messageHolderCompletionHandler - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/DepartmentFactory.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/DepartmentFactory.swift deleted file mode 100755 index d1ef309..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/DepartmentFactory.swift +++ /dev/null @@ -1,78 +0,0 @@ -// -// DepartmentFactory.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Mapper class that is responsible for converting internal department model objects to public ones. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -final class DepartmentFactory { - - // MARK: - Properties - let serverURLString: String - - // MARK - Initialization - init(serverURLString: String) { - self.serverURLString = serverURLString - } - - // MARK: - Methods - - func convert(departmentItem: DepartmentItem) -> DepartmentImpl { - var fullLogoURL: URL? = nil - if let logoURLString = departmentItem.getLogoURLString() { - fullLogoURL = URL(string: serverURLString + logoURLString) - } - - return DepartmentImpl(key: departmentItem.getKey(), - name: departmentItem.getName(), - departmentOnlineStatus: publicState(ofDepartmentOnlineStatus: departmentItem.getOnlineStatus()), - order: departmentItem.getOrder(), - localizedNames: departmentItem.getLocalizedNames(), - logo: fullLogoURL) - } - - // MARK: Private methods - private func publicState(ofDepartmentOnlineStatus departmentOnlineStatus: DepartmentItem.InternalDepartmentOnlineStatus) -> DepartmentOnlineStatus { - switch departmentOnlineStatus { - case .busyOffline: - return .BUSY_OFFLINE - case .busyOnline: - return .BUSY_ONLINE - case .offline: - return .OFFLINE - case .online: - return .ONLINE - case .unknown: - return .UNKNOWN - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Array.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Array.swift deleted file mode 100755 index afc2694..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Array.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// Array.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 17.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -extension Array where Element == UInt8 { - - // MARK: - Methods - /** - Part or HMAC SHA256 generation system. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - public func toHexString() -> String { - return `lazy`.reduce("") { - var s = String($1, - radix: 16) - if s.count == 1 { - s = "0" + s - } - - return $0 + s - } - } -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Collection.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Collection.swift deleted file mode 100755 index 57de148..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Collection.swift +++ /dev/null @@ -1,112 +0,0 @@ -// -// Collection.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 17.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -extension Collection { - - /** - Part or HMAC SHA256 generation system. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - func batched(by size: IndexDistance) -> BatchedCollection { - return BatchedCollection(base: self, - size: size) - } - -} - -// MARK: - -/** - Part or HMAC SHA256 generation system. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -struct BatchedCollection: Collection { - - typealias Index = BatchedCollectionIndex - - // MARK: - Properties - let base: Base - let size: Base.IndexDistance - - // MARK: - Methods - private func nextBreak(after idx: Base.Index) -> Base.Index { - return (base.index(idx, - offsetBy: size, - limitedBy: base.endIndex) ?? base.endIndex) - } - - var startIndex: Index { - return Index(range: base.startIndex ..< nextBreak(after: base.startIndex)) - } - - var endIndex: Index { - return Index(range: base.endIndex ..< base.endIndex) - } - - func index(after idx: Index) -> Index { - return Index(range: idx.range.upperBound ..< nextBreak(after: idx.range.upperBound)) - } - - subscript(idx: Index) -> Base.SubSequence { - return base[idx.range] - } -} - -// MARK: - Comparable -extension BatchedCollectionIndex: Comparable { - - // MARK: - Methods - - static func ==(lhs: BatchedCollectionIndex, - rhs: BatchedCollectionIndex) -> Bool { - return (lhs.range.lowerBound == rhs.range.lowerBound) - } - - static func <(lhs: BatchedCollectionIndex, - rhs: BatchedCollectionIndex) -> Bool { - return (lhs.range.lowerBound < rhs.range.lowerBound) - } - -} - -// MARK: - -/** - Part or HMAC SHA256 generation system. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -struct BatchedCollectionIndex { - let range: Range -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Dictionary.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Dictionary.swift deleted file mode 100755 index d312cc6..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Dictionary.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// Dictionary.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -extension Dictionary { - - // MARK: - Methods - /** - Build string representation of HTTP parameter dictionary of keys and objects. - This percent escapes in compliance with RFC 3986. - - important: - Supports only non-optional String keys and values. - - seealso: - http://www.ietf.org/rfc/rfc3986.txt - - returns: - String representation in the form of key1=value1&key2=value2 where the keys and values are percent escaped. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func stringFromHTTPParameters() -> String { - let parameterArray = map { (key, value) -> String in - let percentEscapedKey = (key as! String).addingPercentEncodingForURLQueryValue()! - let percentEscapedValue = (value as! String).addingPercentEncodingForURLQueryValue()! - return "\(percentEscapedKey)=\(percentEscapedValue)" - } - - return parameterArray.joined(separator: "&") - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Int.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Int.swift deleted file mode 100755 index 112dee3..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/Int.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// Int.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 17.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -extension Int { - - // MARK: - Methods - /** - Part or HMAC SHA256 generation system. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - @_transparent - func bytes(totalBytes: Int) -> Array { - let valuePointer = UnsafeMutablePointer.allocate(capacity: 1) - valuePointer.pointee = self - - let bytesPointer = UnsafeMutablePointer(OpaquePointer(valuePointer)) - var bytes = Array(repeating: 0, - count: totalBytes) - let memoryLayoutSize = MemoryLayout.size - let constraint = ((memoryLayoutSize < totalBytes) ? memoryLayoutSize : totalBytes) - for j in 0 ..< constraint { - bytes[(totalBytes - 1 - j)] = (bytesPointer + j).pointee - } - - valuePointer.deinitialize() - valuePointer.deallocate(capacity: 1) - - return bytes - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/String.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/String.swift deleted file mode 100755 index b8b01c8..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/String.swift +++ /dev/null @@ -1,407 +0,0 @@ -// -// String.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.10.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -extension String { - - // MARK: - Methods - - /** - Percent escapes values to be added to a URL query as specified in RFC 3986. - This percent-escapes all characters besides the alphanumeric character set and "-", ".", "_", and "~". - - seealso: - http://ietf.org/rfc/rfc3986.txt - - returns: - Percent-escaped string. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func addingPercentEncodingForURLQueryValue() -> String? { - let generalDelimitersToEncode = ":#[]@" // Does not include "?" or "/" due to RFC 3986 - Section 3.4. - let subDelimitersToEncode = "!$&'()*+,;=" - - var allowed = CharacterSet.urlQueryAllowed - allowed.remove(charactersIn: (generalDelimitersToEncode + subDelimitersToEncode)) - - return addingPercentEncoding(withAllowedCharacters: allowed) - } - - /** - Generates HMAC SHA256 code taken on passed key value for self. - - parameter key: - Key to generate hash code. - - returns: - Hash code of string taken with passed key. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func hmacSHA256(withKey key: String) -> String? { - let stringBytes: [UInt8] = Array(self.utf8) - let keyBytes: [UInt8] = Array(key.utf8) - let hmac = try! HMACsha256(key: keyBytes).authenticate(stringBytes).toHexString() - - return hmac - } - -} - -// MARK: - -/** - Part or HMAC SHA256 generation system. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -public final class HMACsha256 { - - // MARK: - Constants - private enum Error: Swift.Error { - case authenticateError - } - private static let blockSize = 64 - - - // MARK: - Properties - var key: Array - - - // MARK: - Initialization - public init(key: Array) { - self.key = key - - if key.count > HMACsha256.blockSize { - if let hash = calculateHash(key) { - self.key = hash - } - } - - if key.count < HMACsha256.blockSize { - self.key = add(to: key) - } - } - - - // MARK: - Methods - - func authenticate(_ bytes: Array) throws -> Array { - var opad = Array(repeating: 0x5c, - count: HMACsha256.blockSize) - for idx in key.indices { - opad[idx] = key[idx] ^ opad[idx] - } - var ipad = Array(repeating: 0x36, - count: HMACsha256.blockSize) - for idx in key.indices { - ipad[idx] = key[idx] ^ ipad[idx] - } - - guard let ipadAndMessageHash = calculateHash(ipad + bytes), - let result = calculateHash(opad + ipadAndMessageHash) else { - throw Error.authenticateError - } - - return result - } - - // MARK: Private methods - - private func calculateHash(_ bytes: Array) -> Array? { - return SHA256().calculate(for: bytes) - } - - private func add(to bytes: Array) -> Array { - let paddingCount = HMACsha256.blockSize - (bytes.count % HMACsha256.blockSize) - if paddingCount > 0 { - return (bytes + Array(repeating: 0, - count: paddingCount)) - } - - return bytes - } - -} - -// MARK: - -/** - Part or HMAC SHA256 generation system. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -public final class SHA256 { - - // MARK: - Constants - private static let blockSize = 64 - private static let digestLength = 32 - private static let h: Array = [0x6a09e667, - 0xbb67ae85, - 0x3c6ef372, - 0xa54ff53a, - 0x510e527f, - 0x9b05688c, - 0x1f83d9ab, - 0x5be0cd19] - private static let k: Array = [0x428a2f98, - 0x71374491, - 0xb5c0fbcf, - 0xe9b5dba5, - 0x3956c25b, - 0x59f111f1, - 0x923f82a4, - 0xab1c5ed5, - 0xd807aa98, - 0x12835b01, - 0x243185be, - 0x550c7dc3, - 0x72be5d74, - 0x80deb1fe, - 0x9bdc06a7, - 0xc19bf174, - 0xe49b69c1, - 0xefbe4786, - 0x0fc19dc6, - 0x240ca1cc, - 0x2de92c6f, - 0x4a7484aa, - 0x5cb0a9dc, - 0x76f988da, - 0x983e5152, - 0xa831c66d, - 0xb00327c8, - 0xbf597fc7, - 0xc6e00bf3, - 0xd5a79147, - 0x06ca6351, - 0x14292967, - 0x27b70a85, - 0x2e1b2138, - 0x4d2c6dfc, - 0x53380d13, - 0x650a7354, - 0x766a0abb, - 0x81c2c92e, - 0x92722c85, - 0xa2bfe8a1, - 0xa81a664b, - 0xc24b8b70, - 0xc76c51a3, - 0xd192e819, - 0xd6990624, - 0xf40e3585, - 0x106aa070, - 0x19a4c116, - 0x1e376c08, - 0x2748774c, - 0x34b0bcb5, - 0x391c0cb3, - 0x4ed8aa4a, - 0x5b9cca4f, - 0x682e6ff3, - 0x748f82ee, - 0x78a5636f, - 0x84c87814, - 0x8cc70208, - 0x90befffa, - 0xa4506ceb, - 0xbef9a3f7, - 0xc67178f2] - - // MARK: - Properties - private var accumulatedHash32 = SHA256.h.map { UInt32($0) } - private var processedBytesTotalCount: Int = 0 - - // MARK: - Methods - - func calculate(for bytes: Array) -> Array { - do { - return try update(withBytes: bytes[bytes.startIndex ..< bytes.endIndex]) - } catch { - return [] - } - } - - // MARK: Private methods - - private func update(withBytes bytes: ArraySlice) throws -> Array { - var accumulated = Array() - accumulated += bytes - - let lengthInBits = (processedBytesTotalCount + accumulated.count) * 8 - let lengthBytes = lengthInBits.bytes(totalBytes: (SHA256.blockSize / 8)) // A 64-bit/128-bit representation of b. blockSize fit by accident. - - // Step 1. Append padding. - SHA256.bitPadding(to: &accumulated, - blockSize: SHA256.blockSize, - allowance: (SHA256.blockSize / 8)) - - // Step 2. Append Length a 64-bit representation of lengthInBits. - accumulated += lengthBytes - - var processedBytes = 0 - for chunk in accumulated.batched(by: SHA256.blockSize) { - process32(block: chunk, - currentHash: &accumulatedHash32) - processedBytes += chunk.count - } - accumulated.removeFirst(processedBytes) - processedBytesTotalCount += processedBytes - - // Current hash output. - var result = Array(repeating: 0, - count: SHA256.digestLength) - var pos = 0 - for idx in 0 ..< accumulatedHash32.count where idx < Int.max { - let h = accumulatedHash32[idx].bigEndian - result[pos] = UInt8(h & 0xff) - result[pos + 1] = UInt8((h >> 8) & 0xff) - result[pos + 2] = UInt8((h >> 16) & 0xff) - result[pos + 3] = UInt8((h >> 24) & 0xff) - pos += 4 - } - - return result - } - - // Mutating currentHash in place is way faster than returning new result. - private func process32(block chunk: ArraySlice, - currentHash hh: inout Array) { - // Break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15, big-endian. - // Extend the sixteen 32-bit words into sixty-four 32-bit words: - let M = UnsafeMutablePointer.allocate(capacity: SHA256.k.count) - M.initialize(to: 0, count: - SHA256.k.count) - defer { - M.deinitialize(count: SHA256.k.count) - M.deallocate(capacity: SHA256.k.count) - } - - for x in 0 ..< SHA256.k.count { - switch x { - case 0 ... 15: - let start = chunk.startIndex.advanced(by: (x * 4)) - M[x] = UInt32(bytes: chunk, - fromIndex: start) - - break - default: - let s0 = SHA256.rotateRight(M[x - 15], - by: 7) ^ SHA256.rotateRight(M[x - 15], - by: 18) ^ (M[x - 15] >> 3) - let s1 = SHA256.rotateRight(M[x - 2], - by: 17) ^ SHA256.rotateRight(M[x - 2], - by: 19) ^ (M[x - 2] >> 10) - M[x] = M[x - 16] &+ s0 &+ M[x - 7] &+ s1 - - break - } - } - - var A = hh[0] - var B = hh[1] - var C = hh[2] - var D = hh[3] - var E = hh[4] - var F = hh[5] - var G = hh[6] - var H = hh[7] - - // Main loop - for j in 0.., - blockSize: Int, - allowance: Int) { - let msgLength = data.count - // Step 1. Append Padding Bits. - // Append one bit (UInt8 with one bit) to message. - data.append(0x80) - - // Step 2. Append "0" bit until message length in bits ≡ 448 (mod 512). - let max = blockSize - allowance // 448, 986. - if msgLength % blockSize < max { // 448. - data += Array(repeating: 0, - count: (max - 1 - (msgLength % blockSize))) - } else { - data += Array(repeating: 0, - count: (blockSize + max - 1 - (msgLength % blockSize))) - } - } - - private static func rotateRight(_ value: UInt32, - by: UInt32) -> UInt32 { - return ((value >> by) | (value << (32 - by))) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/UIColor.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/UIColor.swift deleted file mode 100755 index 68a30be..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/UIColor.swift +++ /dev/null @@ -1,62 +0,0 @@ -// -// UIColor.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import UIKit - -extension UIColor { - - /** - Initializes and returns a color object using hex string. - - parameter hexString: - Hex string representing color with or whithout "#" prefix. - - returns: - The color object or `nil` if passed string can't represent a color. The color information represented by this object is in an RGB colorspace. On applications linked for iOS 10 or later, the color is specified in an extended range sRGB color space. On earlier versions of iOS, the color is specified in a device RGB colorspace. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - convenience init?(hexString: String) { - var colorString: String = hexString.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() - - if (colorString.hasPrefix("#")) { - colorString.remove(at: colorString.startIndex) - } - - if colorString.count != 6 { - return nil - } - - var rgbValue: UInt32 = 0 - Scanner(string: colorString).scanHexInt32(&rgbValue) - - self.init(red: (CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0), - green:(CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0), - blue: (CGFloat(rgbValue & 0x0000FF) / 255.0), - alpha: 1.0) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/UInt32.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/UInt32.swift deleted file mode 100755 index 26b641d..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/Extensions/UInt32.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// UInt32.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 17.01.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -extension UInt32 { - - // MARK: - Initialization - /** - Part or HMAC SHA256 generation system. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - @_specialize(exported: true, where T == ArraySlice) - init(bytes: T, - fromIndex index: T.Index) where T.Element == UInt8, T.Index == Int { - if bytes.isEmpty { - self = 0 - - return - } - - let count = bytes.count - - let val0 = ((count > 0) ? (UInt32(bytes[index.advanced(by: 0)]) << 24) : 0) - let val1 = ((count > 1) ? (UInt32(bytes[index.advanced(by: 1)]) << 16) : 0) - let val2 = ((count > 2) ? (UInt32(bytes[index.advanced(by: 2)]) << 8) : 0) - let val3 = ((count > 3) ? UInt32(bytes[index.advanced(by: 3)]) : 0) - - self = val0 | val1 | val2 | val3 - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/InternalUtils.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/InternalUtils.swift deleted file mode 100755 index ab111b1..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/InternalUtils.swift +++ /dev/null @@ -1,103 +0,0 @@ -// -// InternalUtils.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 08.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Various SDK utilities. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class InternalUtils { - - // MARK: - Methods - - static func createServerURLStringBy(accountName: String) -> String { - var serverURLstring = accountName - - if serverURLstring.range(of: "://") != nil { - if serverURLstring.last! == "/" { - serverURLstring.removeLast() - } - - return serverURLstring - } - - return "https://\(serverURLstring).webim.ru" - } - - static func getCurrentTimeInMicrosecond() -> Int64 { - return Int64(Date().timeIntervalSince1970 * 1_000_000) - } - - static func parse(remoteNotification: [AnyHashable : Any], visitorId: String?) -> WebimRemoteNotification? { - if let apsFields = remoteNotification[WebimRemoteNotificationImpl.APNSField.aps.rawValue] as? [String: Any] { - if let alertFields = apsFields[WebimRemoteNotificationImpl.APSField.alert.rawValue] as? [String: Any] { - if visitorId != nil { - return WebimRemoteNotificationImpl(jsonDictionary: alertFields) as WebimRemoteNotification? - } else { - let notification = WebimRemoteNotificationImpl(jsonDictionary: alertFields) as WebimRemoteNotification? - let params = notification?.getParameters() - var indexOfId: Int - switch notification?.getType() { - case .OPERATOR_ACCEPTED?: - indexOfId = 1 - break - case .OPERATOR_FILE?, - .OPERATOR_MESSAGE?: - indexOfId = 2 - break - default: - indexOfId = 0 - } - - if params?.count ?? 0 <= indexOfId { - return notification - } - return params?[indexOfId] == visitorId ? notification : nil - } - } else { - return nil - } - } else { - WebimInternalLogger.shared.log(entry: "Unknown remote notification format: \(remoteNotification).", - verbosityLevel: .DEBUG) - - return nil - } - } - - static func isWebim(remoteNotification: [AnyHashable: Any]) -> Bool { - if let webimField = remoteNotification[WebimRemoteNotificationImpl.APNSField.webim.rawValue] as? Bool { - return webimField - } - - return false - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/MessageFactories.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/MessageFactories.swift deleted file mode 100755 index 344db10..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/MessageFactories.swift +++ /dev/null @@ -1,222 +0,0 @@ -// -// MessageFactories.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 10.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -// MARK: - -/** - Abstract class that supposed to be parent of mapper classes that are responsible for converting internal message model objects to public one. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -class MessageMapper { - - // MARK: - Constants - private enum MapError: Error { - case invalidMessageType(String) - } - - // MARK: - Properties - private let serverURLString: String - private weak var webimClient: WebimClient? - - // MARK: - Initialization - init(withServerURLString serverURLString: String) { - self.serverURLString = serverURLString - } - - // MARK: - Methods - - static func convert(messageKind: MessageItem.MessageKind) -> MessageType? { - switch messageKind { - case .actionRequest: - return .ACTION_REQUEST - case .contactInformationRequest: - return .CONTACTS_REQUEST - case .fileFromOperator: - return .FILE_FROM_OPERATOR - case .fileFromVisitor: - return .FILE_FROM_VISITOR - case .info: - return .INFO - case .operatorMessage: - return .OPERATOR - case .operatorBusy: - return .OPERATOR_BUSY - case .visitorMessage: - return .VISITOR - default: - WebimInternalLogger.shared.log(entry: "Invalid message type received: \(messageKind.rawValue)", - verbosityLevel: .WARNING) - - return nil - } - } - - func convert(messageItem: MessageItem, - historyMessage: Bool) -> MessageImpl? { - let kind = messageItem.getKind() - if (kind == nil) - || (kind == .contactInformation) - || (kind == .forOperator) { - return nil - } - let type = MessageMapper.convert(messageKind: kind!) - if type == nil { - return nil - } - - var attachment: MessageAttachment? = nil - var text: String? = nil - var rawText: String? = nil - - let messageItemText = messageItem.getText() - if (kind == .fileFromVisitor) - || (kind == .fileFromOperator) { - attachment = MessageAttachmentImpl.getAttachment(byServerURL: serverURLString, - webimClient: webimClient!, - text: messageItemText!) - if attachment == nil { - return nil - } - - text = attachment?.getFileName() - rawText = messageItemText! - } else { - text = messageItemText ?? "" - } - - return MessageImpl(serverURLString: serverURLString, - id: messageItem.getClientSideID()!, - operatorID: messageItem.getSenderID(), - senderAvatarURLString: messageItem.getSenderAvatarURLString(), - senderName: messageItem.getSenderName()!, - type: type!, - data: messageItem.getData(), - text: text!, - timeInMicrosecond: messageItem.getTimeInMicrosecond()!, - attachment: attachment, - historyMessage: historyMessage, - internalID: messageItem.getID(), - rawText: rawText, - read: messageItem.getRead() ?? true, - messageCanBeEdited: messageItem.getCanBeEdited()) - } - - func set(webimClient: WebimClient) { - self.webimClient = webimClient - } - - func mapAll(messages: [MessageItem]) -> [MessageImpl] { - return messages.map { map(message: $0) }.compactMap { $0 } - } - - func map(message: MessageItem) -> MessageImpl? { - preconditionFailure("This method must be overridden!") - } - -} - -// MARK: - -/** - Concrete mapper class that is responsible for converting internal message model objects to public message model objects of current chat. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class CurrentChatMessageMapper: MessageMapper { - - // MARK: - Methods - override func map(message: MessageItem) -> MessageImpl? { - return convert(messageItem: message, - historyMessage: false) - } - -} - -// MARK: - -/** - Concrete mapper class that is responsible for converting internal message model objects to public message model objects of previous chats. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class HistoryMessageMapper: MessageMapper { - - // MARK: - Methods - override func map(message: MessageItem) -> MessageImpl? { - return convert(messageItem: message, - historyMessage: true) - } - -} - -// MARK: - -/** - Class that responsible for creating child class objects for public message model objects of messages that are to be sent by visitor. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class SendingFactory { - - // MARK: - Properties - var serverURLString: String - - - // MARK: - Initialization - init(withServerURLString serverURLString: String) { - self.serverURLString = serverURLString - } - - - // MARK: - Methods - - func createTextMessageToSendWith(id: String, - text: String) -> MessageToSend { - return MessageToSend(serverURLString: serverURLString, - id: id, - senderName: "", - type: .VISITOR, - text: text, - timeInMicrosecond: InternalUtils.getCurrentTimeInMicrosecond()) - } - - func createFileMessageToSendWith(id: String) -> MessageToSend { - return MessageToSend(serverURLString: serverURLString, - id: id, - senderName: "", - type: .FILE_FROM_VISITOR, - text: "", - timeInMicrosecond: InternalUtils.getCurrentTimeInMicrosecond()) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/OperatorFactory.swift b/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/OperatorFactory.swift deleted file mode 100755 index ac1db66..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/Utilities/OperatorFactory.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// OperatorFactory.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 19.02.18. -// Copyright © 2018 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Mapper class that is responsible for converting internal operator model objects to public ones. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class OperatorFactory { - - // MARK: - Properties - var serverURLString: String - - // MARK: - Initialization - init(withServerURLString serverURLString: String) { - self.serverURLString = serverURLString - } - - // MARK: - Methods - func createOperatorFrom(operatorItem: OperatorItem?) -> OperatorImpl? { - return ((operatorItem == nil) ? nil : OperatorImpl(id: operatorItem!.getID(), - name: operatorItem!.getFullName(), - avatarURLString: ((operatorItem!.getAvatarURLString() == nil) ? nil : (serverURLString + operatorItem!.getAvatarURLString()!)))) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/WebimActions.swift b/ios/libs/Webim/WebimClientLibrary/Backend/WebimActions.swift deleted file mode 100755 index a9895e8..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/WebimActions.swift +++ /dev/null @@ -1,348 +0,0 @@ -// -// WebimActions.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that is responsible for history storage when it is set to memory mode. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -class WebimActions { - - // MARK: - Constants - enum ContentType: String { - case multipartBody = "multipart/form-data; boundary=" // + boundary string - case urlEncoded = "application/x-www-form-urlencoded" - } - enum Event: String { - case initialization = "init" - } - enum Parameter: String { - case actionn = "action" - case applicationVersion = "app-version" - case authorizationToken = "auth-token" - case beforeTimestamp = "before-ts" - case chatMode = "chat-mode" - case clientSideID = "client-side-id" - case data = "data" - case deleteDraft = "del-message-draft" - case departmentKey = "department-key" - case deviceID = "device-id" - case deviceToken = "push-token" - case draft = "message-draft" - case event = "event" - case firstQuestion = "first-question" - case forceOnline = "force-online" - case hintQuestion = "hint_question" - case location = "location" - case message = "message" - case operatorID = "operator_id" - case pageID = "page-id" - case platform = "platform" - case providedAuthenticationToken = "provided_auth_token" - case rating = "rate" - case respondImmediately = "respond-immediately" - case visitSessionID = "visit-session-id" - case since = "since" - case timestamp = "ts" - case title = "title" - case visitor = "visitor" - case visitorExt = "visitor-ext" - case visitorTyping = "typing" - case prechat = "prechat-key-independent-fields" - case customFields = "custom_fields" - } - enum Platform: String { - case ios = "ios" - } - enum ServerPathSuffix: String { - case doAction = "/l/v/m/action" - case getDelta = "/l/v/m/delta" - case downloadFile = "/l/v/m/download" - case getHistory = "/l/v/m/history" - case uploadFile = "/l/v/m/upload" - } - enum MultipartBody: String { - case name = "webim_upload_file" - } - private enum ChatMode: String { - case online = "online" - } - private enum Action: String { - case closeChat = "chat.close" - case rateOperator = "chat.operator_rate_select" - case respondSentryCall = "chat.action_request.call_sentry_action_request" - case sendMessage = "chat.message" - case deleteMessage = "chat.delete_message" - case setDeviceToken = "set_push_token" - case setPrechat = "chat.set_prechat_fields" - case setVisitorTyping = "chat.visitor_typing" - case startChat = "chat.start" - case chatRead = "chat.read_by_visitor" - case widgetUpdate = "widget.update" - } - - // MARK: - Properties - private let baseURL: String - private let actionRequestLoop: ActionRequestLoop - - // MARK: - Initialization - init(baseURL: String, - actionRequestLoop: ActionRequestLoop) { - self.baseURL = baseURL - self.actionRequestLoop = actionRequestLoop - } - - // MARK: - Methods - - func send(message: String, - clientSideID: String, - dataJSONString: String?, - isHintQuestion: Bool?, - dataMessageCompletionHandler: DataMessageCompletionHandler? = nil, - editMessageCompletionHandler: EditMessageCompletionHandler? = nil) { - var dataToPost = [Parameter.actionn.rawValue: Action.sendMessage.rawValue, - Parameter.clientSideID.rawValue: clientSideID, - Parameter.message.rawValue: message] as [String: Any] - if let isHintQuestion = isHintQuestion { - dataToPost[Parameter.hintQuestion.rawValue] = isHintQuestion ? "1" : "0" // True / false. - } - if let dataJSONString = dataJSONString { - dataToPost[Parameter.data.rawValue] = dataJSONString - } - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - messageID: clientSideID, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString, - dataMessageCompletionHandler: dataMessageCompletionHandler, - editMessageCompletionHandler: editMessageCompletionHandler)) - } - - func send(file: Data, - filename: String, - mimeType: String, - clientSideID: String, - completionHandler: SendFileCompletionHandler?) { - let dataToPost = [Parameter.chatMode.rawValue: ChatMode.online.rawValue, - Parameter.clientSideID.rawValue: clientSideID] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.uploadFile.rawValue - - let boundaryString = NSUUID().uuidString - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - messageID: clientSideID, - filename: filename, - mimeType: mimeType, - fileData: file, - boundaryString: boundaryString, - contentType: (ContentType.multipartBody.rawValue + boundaryString), - baseURLString: urlString, - sendFileCompletionHandler: completionHandler)) - } - - func delete(clientSideID: String, - completionHandler: DeleteMessageCompletionHandler?) { - let dataToPost = [Parameter.actionn.rawValue: Action.deleteMessage.rawValue, - Parameter.clientSideID.rawValue: clientSideID] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - messageID: clientSideID, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString, - deleteMessageCompletionHandler: completionHandler)) - } - - func startChat(withClientSideID clientSideID: String, - firstQuestion: String? = nil, - departmentKey: String? = nil, - customFields: String? = nil) { - var dataToPost = [Parameter.actionn.rawValue: Action.startChat.rawValue, - Parameter.forceOnline.rawValue: "1", // true - Parameter.clientSideID.rawValue: clientSideID] as [String: Any] - if let firstQuestion = firstQuestion { - dataToPost[Parameter.firstQuestion.rawValue] = firstQuestion - } - if let departmentKey = departmentKey { - dataToPost[Parameter.departmentKey.rawValue] = departmentKey - } - if let custom_fields = customFields { - dataToPost[Parameter.customFields.rawValue] = custom_fields - } - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString)) - } - - func closeChat() { - let dataToPost = [Parameter.actionn.rawValue: Action.closeChat.rawValue] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString)) - } - - func set(visitorTyping: Bool, - draft: String?, - deleteDraft: Bool) { - var dataToPost = [Parameter.actionn.rawValue: Action.setVisitorTyping.rawValue, - Parameter.deleteDraft.rawValue: deleteDraft ? "1" : "0", // true / false - Parameter.visitorTyping.rawValue: visitorTyping ? "1" : "0"] as [String: Any] // true / false - if let draft = draft { - dataToPost[Parameter.draft.rawValue] = draft - } - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString)) - } - - func set(prechatFields: String) { - let dataToPost = [Parameter.actionn.rawValue: Action.setPrechat.rawValue, - Parameter.prechat.rawValue: prechatFields] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString)) - } - - func requestHistory(since: String?, - completion: @escaping (_ data: Data?) throws -> ()) { - var dataToPost = [String: Any]() - if let since = since { - dataToPost[Parameter.since.rawValue] = since - } - - let urlString = baseURL + ServerPathSuffix.getHistory.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .get, - primaryData: dataToPost, - baseURLString: urlString, - historyRequestCompletionHandler: completion)) - } - - func requestHistory(beforeMessageTimestamp: Int64, - completion: @escaping (_ data: Data?) throws -> ()) { - let dataToPost = [Parameter.beforeTimestamp.rawValue: String(beforeMessageTimestamp)] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.getHistory.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .get, - primaryData: dataToPost, - baseURLString: urlString, - historyRequestCompletionHandler: completion)) - } - - func rateOperatorWith(id: String?, - rating: Int, - completionHandler: RateOperatorCompletionHandler?) { - var dataToPost = [Parameter.actionn.rawValue: Action.rateOperator.rawValue, - Parameter.rating.rawValue: String(rating)] as [String: Any] - if let id = id { - dataToPost[Parameter.operatorID.rawValue] = id - } - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString, - rateOperatorCompletionHandler: completionHandler)) - } - - func respondSentryCall(id: String) { - let dataToPost = [Parameter.actionn.rawValue: Action.respondSentryCall.rawValue, - Parameter.clientSideID.rawValue: id] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString)) - } - - func update(deviceToken: String) { - let dataToPost = [Parameter.actionn.rawValue: Action.setDeviceToken.rawValue, - Parameter.deviceToken.rawValue: deviceToken] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString)) - } - - func setChatRead() { - let dataToPost = [Parameter.actionn.rawValue: Action.chatRead.rawValue] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString)) - } - - func updateWidgetStatusWith(data: String) { - let dataToPost = [Parameter.actionn.rawValue: Action.widgetUpdate.rawValue, - Parameter.data.rawValue: data] as [String: Any] - - let urlString = baseURL + ServerPathSuffix.doAction.rawValue - - actionRequestLoop.enqueue(request: WebimRequest(httpMethod: .post, - primaryData: dataToPost, - contentType: ContentType.urlEncoded.rawValue, - baseURLString: urlString)) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/WebimClient.swift b/ios/libs/Webim/WebimClientLibrary/Backend/WebimClient.swift deleted file mode 100755 index 7a7db1e..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/WebimClient.swift +++ /dev/null @@ -1,283 +0,0 @@ -// -// WebimClient.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 10.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class WebimClientBuilder { - - // MARK: - Properties - private var appVersion: String? - private var prechat: String? - private var authorizationData: AuthorizationData? - private var baseURL: String? - private var completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor? - private var deltaCallback: DeltaCallback? - private var deviceID: String? - private var deviceToken: String? - private var internalErrorListener: InternalErrorListener? - private var location: String? - private var providedAuthenticationToken: String? - private weak var providedAuthenticationTokenStateListener: ProvidedAuthorizationTokenStateListener? - private var sessionID: String? - private var sessionParametersListener: SessionParametersListener? - private var title: String? - private var visitorFieldsJSONString: String? - private var visitorJSONString: String? - - // MARK: - Builder methods - - func set(appVersion: String?) -> WebimClientBuilder { - self.appVersion = appVersion - - return self - } - - func set(baseURL: String) -> WebimClientBuilder { - self.baseURL = baseURL - - return self - } - - func set(location: String) -> WebimClientBuilder { - self.location = location - - return self - } - - func set(deltaCallback: DeltaCallback) -> WebimClientBuilder { - self.deltaCallback = deltaCallback - - return self - } - - func set(sessionParametersListener: SessionParametersListener) -> WebimClientBuilder { - self.sessionParametersListener = sessionParametersListener - - return self - } - - func set(internalErrorListener: InternalErrorListener) -> WebimClientBuilder { - self.internalErrorListener = internalErrorListener - - return self - } - - func set(visitorJSONString: String?) -> WebimClientBuilder { - self.visitorJSONString = visitorJSONString - - return self - } - - func set(visitorFieldsJSONString: String?) -> WebimClientBuilder { - self.visitorFieldsJSONString = visitorFieldsJSONString - - return self - } - - func set(providedAuthenticationTokenStateListener: ProvidedAuthorizationTokenStateListener?, - providedAuthenticationToken: String? = nil) -> WebimClientBuilder { - self.providedAuthenticationTokenStateListener = providedAuthenticationTokenStateListener - self.providedAuthenticationToken = providedAuthenticationToken - - return self - } - - func set(sessionID: String?) -> WebimClientBuilder { - self.sessionID = sessionID - - return self - } - - func set(authorizationData: AuthorizationData?) -> WebimClientBuilder { - self.authorizationData = authorizationData - - return self - } - - func set(completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor?) -> WebimClientBuilder { - self.completionHandlerExecutor = completionHandlerExecutor - - return self - } - - func set(title: String) -> WebimClientBuilder { - self.title = title - - return self - } - - func set(deviceToken: String?) -> WebimClientBuilder { - self.deviceToken = deviceToken - - return self - } - - func set(deviceID: String) -> WebimClientBuilder { - self.deviceID = deviceID - - return self - } - - func set(prechat:String?) -> WebimClientBuilder { - self.prechat = prechat - return self - } - - func build() -> WebimClient { - let actionRequestLoop = ActionRequestLoop(completionHandlerExecutor: completionHandlerExecutor!, - internalErrorListener: internalErrorListener!) - - actionRequestLoop.set(authorizationData: authorizationData) - - let deltaRequestLoop = DeltaRequestLoop(deltaCallback: deltaCallback!, - completionHandlerExecutor: completionHandlerExecutor!, - sessionParametersListener: SessionParametersListenerWrapper(withSessionParametersListenerToWrap: sessionParametersListener, - actionRequestLoop: actionRequestLoop), - internalErrorListener: internalErrorListener!, - baseURL: baseURL!, - title: title!, - location: location!, - appVersion: appVersion, - visitorFieldsJSONString: visitorFieldsJSONString, - providedAuthenticationTokenStateListener: providedAuthenticationTokenStateListener, - providedAuthenticationToken: providedAuthenticationToken, - deviceID: deviceID!, - deviceToken: deviceToken, - visitorJSONString: visitorJSONString, - sessionID: sessionID, - prechat: prechat, - authorizationData: authorizationData - ) - - return WebimClient(withActionRequestLoop: actionRequestLoop, - deltaRequestLoop: deltaRequestLoop, - webimActions: WebimActions(baseURL: baseURL!, - actionRequestLoop: actionRequestLoop)) - } - -} - -// MARK: - -// Need to update deviceToken in DeltaRequestLoop on update in WebimActions. -/** - Class that is responsible for history storage when it is set to memory mode. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class WebimClient { - - // MARK: - Properties - private let actionRequestLoop: ActionRequestLoop - private let deltaRequestLoop: DeltaRequestLoop - private let webimActions: WebimActions - - // MARK: - Initialization - init(withActionRequestLoop actionRequestLoop: ActionRequestLoop, - deltaRequestLoop: DeltaRequestLoop, - webimActions: WebimActions) { - self.actionRequestLoop = actionRequestLoop - self.deltaRequestLoop = deltaRequestLoop - self.webimActions = webimActions - } - - // MARK: - Methods - - func start() { - deltaRequestLoop.start() - actionRequestLoop.start() - } - - func pause() { - deltaRequestLoop.pause() - actionRequestLoop.pause() - } - - func resume() { - deltaRequestLoop.resume() - actionRequestLoop.resume() - } - - func stop() { - deltaRequestLoop.stop() - actionRequestLoop.stop() - } - - func set(deviceToken: String) { - deltaRequestLoop.set(deviceToken: deviceToken) - webimActions.update(deviceToken: deviceToken) - } - - func getDeltaRequestLoop() -> DeltaRequestLoop { - return deltaRequestLoop - } - - func getActions() -> WebimActions { - return webimActions - } - -} - -// MARK: - -// Need to update AuthorizationData in ActionRequestLoop on update in DeltaRequestLoop. -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final private class SessionParametersListenerWrapper: SessionParametersListener { - - // MARK: - Properties - private let wrappedSessionParametersListener: SessionParametersListener? - private let actionRequestLoop: ActionRequestLoop - - // MARK: - Initializers - init(withSessionParametersListenerToWrap wrappingSessionParametersListener: SessionParametersListener?, - actionRequestLoop: ActionRequestLoop) { - wrappedSessionParametersListener = wrappingSessionParametersListener - self.actionRequestLoop = actionRequestLoop - } - - // MARK: - SessionParametersListener protocol methods - func onSessionParametersChanged(visitorFieldsJSONString visitorJSONString: String, - sessionID: String, - authorizationData: AuthorizationData) { - actionRequestLoop.set(authorizationData: authorizationData) - - wrappedSessionParametersListener?.onSessionParametersChanged(visitorFieldsJSONString: visitorJSONString, - sessionID: sessionID, - authorizationData: authorizationData) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/WebimInternalError.swift b/ios/libs/Webim/WebimClientLibrary/Backend/WebimInternalError.swift deleted file mode 100755 index e62ed34..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/WebimInternalError.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// WebimInternalError.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 17.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Errors that can be received from a server after a HTTP-request. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -enum WebimInternalError: String, Error { - case accountBlocked = "account-blocked" - case chatRequired = "chat-required" - case contentTypeNotRecognized = "content_type_not_recognized"; - case domainNotFromWhitelist = "domain-not-from-whitelist"; - case fileSizeExceeded = "max_file_size_exceeded" - case fileTypeNotAllowed = "not_allowed_file_type" - case notAllowedMimeType = "not_allowed_mime_type"; - case noPreviousChats = "no_previous_chats"; - case notMatchingMagicNumbers = "not_matching_magic_numbers"; - case providedVisitorFieldsExpired = "provided-visitor-expired" - case reinitializationRequired = "reinit-required" - case settingDisabled = "setting_disabled"; - case serverNotReady = "server-not-ready" - case sessionNotFound = "session_not_found"; - case uploadedFileNotFound = "uploaded-file-not-found"; - case visitorBanned = "visitor_banned" - case wrongArgumentValue = "wrong-argument-value" - case wrongProvidedVisitorFieldsHashValue = "wrong-provided-visitor-hash-value" - - // Data errors - // Quoting message errors - case quotedMessageCannotBeReplied = "quoting-message-that-cannot-be-replied" - case quotedMessageFromAnotherVisitor = "quoting-message-from-another-visitor" - case quotedMessageCorruptedID = "corrupted-quoted-message-id" - case quotedMessageMultipleID = "multiple-quoted-messages-found" - case quotedMessageNotFound = "quoted-message-not-found" - case quotedMessageRequiredArgumentsMissing = "required-quote-args-missing" - - // Provided authonication token errors - case providedAuthenticationTokenNotFound = "provided-auth-token-not-found" - - // Send, edit and delete message errors. - // send or edit: - case messageEmpty = "message_empty"; - case maxMessageLengthExceeded = "max-message-length-exceeded"; - // delete: - case messageNotFound = "message_not_found"; - // edit or delete - case notAllowed = "not_allowed"; - case messageNotOwned = "message_not_owned"; - // edit - case wrongMessageKind = "wrong_message_kind"; - - - // Rate operator errors - case noChat = "no-chat" - case operatorNotInChat = "operator-not-in-chat" -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/WebimInternalLogger.swift b/ios/libs/Webim/WebimClientLibrary/Backend/WebimInternalLogger.swift deleted file mode 100755 index 52b1848..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/WebimInternalLogger.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// WebimInternalLogger.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.01.18. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that wraps `WebimLogger` into singleton pattern and encapsulates its verbose level. - First, one should call `setup(webimLogger:verbosityLevel:)` method with particular parameters, then it will be possible to use `WebimInternalLogger.shared`. - - seealso: - `WebimLogger`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -final class WebimInternalLogger { - - // MARK: - Properties - static let shared = WebimInternalLogger() - private static let setup = WebimInternalLoggerParametersHelper() - - // MARK: - Initialization - private init() { - // Needed for singleton pattern. - } - - // MARK: - Methods - - class func setup(webimLogger: WebimLogger?, - verbosityLevel: SessionBuilder.WebimLoggerVerbosityLevel?) { - WebimInternalLogger.setup.webimLogger = webimLogger - WebimInternalLogger.setup.verbosityLevel = verbosityLevel - } - - func log(entry: String, - verbosityLevel: SessionBuilder.WebimLoggerVerbosityLevel = .ERROR) { - let logEntry = "WEBIM LOG. " + Date().debugDescription + " " + entry - switch verbosityLevel { - case .VERBOSE: - if isVerbose() { - WebimInternalLogger.setup.webimLogger?.log(entry: logEntry) - } - - break - case .DEBUG: - if isDebug() { - WebimInternalLogger.setup.webimLogger?.log(entry: logEntry) - } - - break - case .INFO: - if isInfo() { - WebimInternalLogger.setup.webimLogger?.log(entry: logEntry) - } - - break - case .WARNING: - if isWarning() { - WebimInternalLogger.setup.webimLogger?.log(entry: logEntry) - } - - break - case .ERROR: - WebimInternalLogger.setup.webimLogger?.log(entry: logEntry) - - break - } - } - - // MARK: Private methods - - private func isVerbose() -> Bool { - return (WebimInternalLogger.setup.verbosityLevel == .VERBOSE) - } - - private func isDebug() -> Bool { - return ((WebimInternalLogger.setup.verbosityLevel == .DEBUG) - || (WebimInternalLogger.setup.verbosityLevel == .VERBOSE)) - } - - private func isInfo() -> Bool { - return ((WebimInternalLogger.setup.verbosityLevel == .VERBOSE) - || (WebimInternalLogger.setup.verbosityLevel == .DEBUG) - || (WebimInternalLogger.setup.verbosityLevel == .INFO)) - } - - private func isWarning() -> Bool { - return ((WebimInternalLogger.setup.verbosityLevel == .VERBOSE) - || (WebimInternalLogger.setup.verbosityLevel == .DEBUG) - || (WebimInternalLogger.setup.verbosityLevel == .INFO) - || (WebimInternalLogger.setup.verbosityLevel == .WARNING)) - } - -} - -/** - Helper class for `WebimInternalLogger` singleton instance setup. - - seealso: - `WebimInternalLogger`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -final class WebimInternalLoggerParametersHelper { - - // MARK: - Properties - var verbosityLevel: SessionBuilder.WebimLoggerVerbosityLevel? - var webimLogger: WebimLogger? - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Backend/WebimRequest.swift b/ios/libs/Webim/WebimClientLibrary/Backend/WebimRequest.swift deleted file mode 100755 index 5c3e799..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Backend/WebimRequest.swift +++ /dev/null @@ -1,172 +0,0 @@ -// -// WebimRequest.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 11.09.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates paramters or HTTP-requests sending by WebimClientLibrary. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class WebimRequest { - - // MARK: - Properties - private let baseURLString: String - private let httpMethod: AbstractRequestLoop.HTTPMethods - private let primaryData: [String: Any] - private var contentType: String? - private weak var dataMessageCompletionHandler: DataMessageCompletionHandler? - private var historyRequestCompletionHandler: ((_ data: Data?) throws -> ())? - private var faqItemRequestCompletionHandler: ((_ item: Data?) throws -> ())? - private var faqCategoryRequestCompletionHandler: ((_ item: Data?) throws -> ())? - private var faqStructureRequestCompletionHandler: ((_ item: Data?) throws -> ())? - private var httpBody: Data? - private var messageID: String? - private var filename: String? - private var mimeType: String? - private var fileData: Data? - private var boundaryString: String? - private weak var rateOperatorCompletionHandler: RateOperatorCompletionHandler? - private var sendFileCompletionHandler: SendFileCompletionHandler? - private var deleteMessageCompletionHandler: DeleteMessageCompletionHandler? - private var editMessageCompletionHandler: EditMessageCompletionHandler? - - // MARK: - Initialization - init(httpMethod: AbstractRequestLoop.HTTPMethods, - primaryData: [String: Any], - messageID: String? = nil, - filename: String? = nil, - mimeType: String? = nil, - fileData: Data? = nil, - boundaryString: String? = nil, - contentType: String? = nil, - baseURLString: String, - historyRequestCompletionHandler: ((_ data: Data?) throws -> ())? = nil, - faqItemRequestCompletionHandler: ((_ item: Data?) throws -> ())? = nil, - faqCategoryRequestCompletionHandler: ((_ item: Data?) throws -> ())? = nil, - faqStructureRequestCompletionHandler: ((_ item: Data?) throws -> ())? = nil, - dataMessageCompletionHandler: DataMessageCompletionHandler? = nil, - rateOperatorCompletionHandler: RateOperatorCompletionHandler? = nil, - sendFileCompletionHandler: SendFileCompletionHandler? = nil, - deleteMessageCompletionHandler: DeleteMessageCompletionHandler? = nil, - editMessageCompletionHandler: EditMessageCompletionHandler? = nil) { - self.httpMethod = httpMethod - self.primaryData = primaryData - self.messageID = messageID - self.filename = filename - self.mimeType = mimeType - self.fileData = fileData - self.boundaryString = boundaryString - self.contentType = contentType - self.baseURLString = baseURLString - self.historyRequestCompletionHandler = historyRequestCompletionHandler - self.dataMessageCompletionHandler = dataMessageCompletionHandler - self.rateOperatorCompletionHandler = rateOperatorCompletionHandler - self.sendFileCompletionHandler = sendFileCompletionHandler - self.deleteMessageCompletionHandler = deleteMessageCompletionHandler - self.editMessageCompletionHandler = editMessageCompletionHandler - self.faqItemRequestCompletionHandler = faqItemRequestCompletionHandler - self.faqCategoryRequestCompletionHandler = faqCategoryRequestCompletionHandler - self.faqStructureRequestCompletionHandler = faqStructureRequestCompletionHandler - } - - - // MARK: - Methods - - func getHTTPMethod() -> AbstractRequestLoop.HTTPMethods { - return httpMethod - } - - func getBaseURLString() -> String { - return baseURLString - } - - func getContentType() -> String? { - return contentType - } - - func getCompletionHandler() -> ((_ data: Data?) throws -> ())? { - return historyRequestCompletionHandler - } - - func getFAQItemRequestCompletionHandler() -> ((_ data: Data?) throws -> ())? { - return faqItemRequestCompletionHandler - } - - func getFAQCategoryRequestCompletionHandler() -> ((_ data: Data?) throws -> ())? { - return faqCategoryRequestCompletionHandler - } - - func getFAQStructureRequestCompletionHandler() -> ((_ data: Data?) throws -> ())? { - return faqStructureRequestCompletionHandler - } - - func getFileName() -> String? { - return filename - } - - func getMimeType() -> String? { - return mimeType - } - - func getFileData() -> Data? { - return fileData - } - - func getBoundaryString() -> String? { - return boundaryString - } - - func getMessageID() -> String? { - return messageID - } - - func getPrimaryData() -> [String: Any] { - return primaryData - } - - func getDataMessageCompletionHandler() -> DataMessageCompletionHandler? { - return dataMessageCompletionHandler - } - - func getRateOperatorCompletionHandler() -> RateOperatorCompletionHandler? { - return rateOperatorCompletionHandler - } - - func getSendFileCompletionHandler() -> SendFileCompletionHandler? { - return sendFileCompletionHandler - } - - func getDeleteMessageCompletionHandler() -> DeleteMessageCompletionHandler? { - return deleteMessageCompletionHandler - } - - func getEditMessageCompletionHandler() -> EditMessageCompletionHandler? { - return editMessageCompletionHandler - } -} diff --git a/ios/libs/Webim/WebimClientLibrary/Department.swift b/ios/libs/Webim/WebimClientLibrary/Department.swift deleted file mode 100755 index 5ba3720..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Department.swift +++ /dev/null @@ -1,162 +0,0 @@ -// -// Department.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 12.12.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Single department entity. Provides methods to get department information. - Department objects can be received through `DepartmentListChangeListener` protocol methods and `getDepartmentList()` method of `MessageStream` protocol. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol Department { - - /** - Department key is used to start chat with some department. - - seealso: - `startChat(departmentKey:)` method of `MessageStream` protocol. - - returns: - Department key value that uniquely identifies this department. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getKey() -> String - - /** - - returns: - Department public name. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getName() -> String - - /** - - seealso: - `DepartmentOnlineStatus`. - - returns: - Department online status. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getDepartmentOnlineStatus() -> DepartmentOnlineStatus - - /** - - returns: - Order number. Higher numbers match higher priority. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getOrder() -> Int - - /** - - returns: - Dictionary of department localized names (if exists). Key is custom locale descriptor, value is matching name. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getLocalizedNames() -> [String: String]? - - /** - - returns: - Department logo URL (if exists). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getLogoURL() -> URL? - -} - -/** - Possible department online statuses. - - seealso: - `getDepartmentOnlineStatus()` of `Department` protocol. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum DepartmentOnlineStatus { - - /** - Offline state with chats' count limit exceeded. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case BUSY_OFFLINE - - /** - Online state with chats' count limit exceeded. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case BUSY_ONLINE - - /** - Visitor is able to send offline messages. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case OFFLINE - - /** - Visitor is able to send both online and offline messages. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case ONLINE - - /** - Any status that is not supported by this version of the library. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case UNKNOWN - -} diff --git a/ios/libs/Webim/WebimClientLibrary/FAQ.swift b/ios/libs/Webim/WebimClientLibrary/FAQ.swift deleted file mode 100755 index 2c1a87e..0000000 --- a/ios/libs/Webim/WebimClientLibrary/FAQ.swift +++ /dev/null @@ -1,169 +0,0 @@ -// -// FAQ.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - - -import Foundation - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -public protocol FAQ { - - /** - Resumes FAQ networking. - - important: - FAQ is created as paused. To start using it firstly you should call this method. - - throws: - `FAQAccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `FAQAccessError.INVALID_FAQ` if FAQ was destroyed. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func resume() throws - - /** - Pauses FAQ networking. - - throws: - `FAQAccessError.INVALID_THREAD` if the method was called not from the thread the FAQ was created in. - `FAQAccessError.INVALID_FAQ` if FAQ was destroyed. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func pause() throws - - /** - Destroys FAQ. After that any FAQ methods are not available. - - throws: - `FAQAccessError.INVALID_THREAD` if the method was called not from the thread the FAQ was created in. - `FAQAccessError.INVALID_FAQ` if FAQ was destroyed. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func destroy() throws - - /** - Requests category. If nil is passed inside completion, there no category with this id. - - seealso: - `destroy()` method. - `FAQCategory` protocol. - - parameter id: - Category ID. - - parameter completion: - Completion to be called on category if method call succeeded. - - parameter result: - Resulting category if method call succeeded. - - throws: - `FAQAccessError.INVALID_THREAD` if the method was called not from the thread the FAQ was created in. - `FAQAccessError.INVALID_FAQ` if the method was called after FAQ object was destroyed. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getCategory(id: Int, completion: @escaping (_ result: FAQCategory?) -> ()) throws - - /** - Requests item. If nil is passed inside completion, there no item with this id. - - seealso: - `destroy()` method. - `FAQItem` protocol. - - parameter id: - Item ID. - - parameter completion: - Completion to be called on item if method call succeeded. - - parameter result: - Resulting item if method call succeeded. - - throws: - `FAQAccessError.INVALID_THREAD` if the method was called not from the thread the FAQ was created in. - `FAQAccessError.INVALID_FAQ` if the method was called after FAQ object was destroyed. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getItem(id: String, completion: @escaping (_ result: FAQItem?) -> ()) throws - - /** - Requests structure. If nil is passed inside completion, there no structure with this id. - - seealso: - `destroy()` method. - `FAQStructure` protocol. - - parameter id: - Structure ID. - - parameter completion: - Completion to be called on structure if method call succeeded. - - parameter result: - Resulting structure if method call succeeded. - - throws: - `FAQAccessError.INVALID_THREAD` if the method was called not from the thread the FAQ was created in. - `FAQAccessError.INVALID_FAQ` if the method was called after FAQ object was destroyed. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getStructure(id: Int, completion: @escaping (_ result: FAQStructure?) -> ()) throws -} - -// MARK: - -/** - Error types that can be throwed by FAQ methods. - - seealso: - `FAQ` methods. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -public enum FAQAccessError: Error { - - /** - Error that is thrown if the method was called not from the thread the FAQ was created in. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - case INVALID_THREAD - - /** - Error that is thrown if FAQ was destroyed. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - case INVALID_FAQ -} diff --git a/ios/libs/Webim/WebimClientLibrary/FAQCategory.swift b/ios/libs/Webim/WebimClientLibrary/FAQCategory.swift deleted file mode 100755 index 13275cb..0000000 --- a/ios/libs/Webim/WebimClientLibrary/FAQCategory.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// FAQCategory.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - - -import Foundation - -/** - FAQ category contains pages with some information and subcategories. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -public protocol FAQCategory { - - /** - Every category can be uniquefied by its ID. - - returns: - Unique ID of the category. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getID() -> Int - - /** - - returns: - Title of the category. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getTitle() -> String - - /** - Every category contains items. - - returns: - List of category items. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getItems() -> [FAQItem] - - /** - Every category can be contains subcategories. - - returns: - List of categories that contains the item. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getSubcategories() -> [FAQCategoryInfo] -} diff --git a/ios/libs/Webim/WebimClientLibrary/FAQCategoryInfo.swift b/ios/libs/Webim/WebimClientLibrary/FAQCategoryInfo.swift deleted file mode 100755 index 8f79a79..0000000 --- a/ios/libs/Webim/WebimClientLibrary/FAQCategoryInfo.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// FAQCategoryInfo.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - - -import Foundation - -/** - FAQCategory without children. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -public protocol FAQCategoryInfo { - - /** - Every category can be uniquefied by its ID. - - returns: - Unique ID of the category. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getID() -> Int - - /** - - returns: - Title of the category. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getTitle() -> String -} diff --git a/ios/libs/Webim/WebimClientLibrary/FAQItem.swift b/ios/libs/Webim/WebimClientLibrary/FAQItem.swift deleted file mode 100755 index 530796d..0000000 --- a/ios/libs/Webim/WebimClientLibrary/FAQItem.swift +++ /dev/null @@ -1,111 +0,0 @@ -// -// FAQItem.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - - -import Foundation - -/** - FAQ page with some information. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -public protocol FAQItem { - - /** - Every item can be uniquefied by its ID. - - returns: - Unique ID of the item. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getID() -> String - - /** - Every item can be contained in different categories. - - returns: - List of categories that contains the item. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getCategories() -> [Int] - - /** - - returns: - Title of the item. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getTitle() -> String - - /** - - returns: - List of item tags. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getTags() -> [String] - - /** - - returns: - Item content. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getContent() -> String - - /** - - returns: - Like count of the item. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getLikeCount() -> Int - - - /** - - returns: - Dislike count of the item. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getDislikeCount() -> Int -} diff --git a/ios/libs/Webim/WebimClientLibrary/FAQStructure.swift b/ios/libs/Webim/WebimClientLibrary/FAQStructure.swift deleted file mode 100755 index 8edf9e3..0000000 --- a/ios/libs/Webim/WebimClientLibrary/FAQStructure.swift +++ /dev/null @@ -1,118 +0,0 @@ -// -// FAQStructure.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - - -import Foundation - -/** - Category subtree. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -public protocol FAQStructure { - /** - Every structure has root. - - returns: - Unique ID of the tree root. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getID() -> String - - /** - - returns: - Root type. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getType() -> RootType - - /** - - returns: - Root's children. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getChildren() -> [FAQStructure] - - /** - - returns: - Root title. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func getTitle() -> String -} - -// MARK: - -/** - Supported structure root types. - - seealso: - `FAQStructure.getType()` - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -public enum RootType { - /** - Root is category. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - case CATEGORY - - /** - Root is item. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - case ITEM - - /** - Unknown root type. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - case UNKNOWN - -} diff --git a/ios/libs/Webim/WebimClientLibrary/FatalErrorHandler.swift b/ios/libs/Webim/WebimClientLibrary/FatalErrorHandler.swift deleted file mode 100755 index 2866d40..0000000 --- a/ios/libs/Webim/WebimClientLibrary/FatalErrorHandler.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// FatalErrorHandler.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 08.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - - -import Foundation - - -/** - Protocol that provides methods to handle errors are sent by Webim service. - - seealso: - `set(fatalErrorHandler:)` method of `SessionBuilder` class. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol FatalErrorHandler: class { - - /** - This method is to be called when Webim service error is received. - - important: - Method called NOT FROM THE MAIN THREAD! - - parameter error: - Error type. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func on(error: WebimError) - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/DepartmentImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/DepartmentImpl.swift deleted file mode 100755 index f04f437..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/DepartmentImpl.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// DepartmentImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 12.12.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -final class DepartmentImpl: Department { - - // MARK: - Properties - private let departmentOnlineStatus: DepartmentOnlineStatus - private let key: String - private let name: String - private let order: Int - private var localizedNames: [String: String]? - private var logoURL: URL? - - // MARK: - Initialization - init(key: String, - name: String, - departmentOnlineStatus: DepartmentOnlineStatus, - order: Int, - localizedNames: [String: String]? = nil, - logo: URL? = nil) { - self.key = key - self.name = name - self.departmentOnlineStatus = departmentOnlineStatus - self.order = order - self.localizedNames = localizedNames - self.logoURL = logo - } - - // MARK: - Methods - // MARK: Department protocol methods - - func getKey() -> String { - return key - } - - func getName() -> String { - return name - } - - func getDepartmentOnlineStatus() -> DepartmentOnlineStatus { - return departmentOnlineStatus - } - - func getOrder() -> Int { - return order - } - - func getLocalizedNames() -> [String: String]? { - return localizedNames - } - - func getLogoURL() -> URL? { - return logoURL - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/FAQImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/FAQImpl.swift deleted file mode 100755 index ca88519..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/FAQImpl.swift +++ /dev/null @@ -1,175 +0,0 @@ -// -// FAQImpl.swift -// WebimClientLibrary -// -// Created by Nikita Kaberov on 07.02.19. -// Copyright © 2019 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -// MARK: - -/** - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ -final class FAQImpl { - - // MARK: - Properties - private var accessChecker: FAQAccessChecker - private var clientStarted = false - private var faqDestroyer: FAQDestroyer - private var faqClient: FAQClient - - // MARK: - Initialization - private init(accessChecker: FAQAccessChecker, - faqDestroyer: FAQDestroyer, - faqClient: FAQClient) { - self.accessChecker = accessChecker - self.faqDestroyer = faqDestroyer - self.faqClient = faqClient - } - - // MARK: - Methods - - static func newInstanceWith(accountName: String) -> FAQImpl { - - let faqDestroyer = FAQDestroyer() - - let serverURLString = InternalUtils.createServerURLStringBy(accountName: accountName) - - let queue = DispatchQueue.global(qos: .userInteractive) - - let faqClient = FAQClientBuilder() - .set(baseURL: serverURLString) - .set(completionHandlerExecutor: ExecIfNotDestroyedFAQHandlerExecutor(faqDestroyer: faqDestroyer, - queue: queue)) - .build() as FAQClient - - let accessChecker = FAQAccessChecker(thread: Thread.current, - faqDestroyer: faqDestroyer) - - faqDestroyer.add() { - faqClient.stop() - } - - return FAQImpl(accessChecker: accessChecker, - faqDestroyer: faqDestroyer, - faqClient: faqClient) - } -} - -// MARK: - FAQ -extension FAQImpl: FAQ { - func getCategory(id: Int, completion: @escaping (FAQCategory?) -> ()) throws { - try accessChecker.checkAccess() - - faqClient.getActions().getCategory(categoryId: id) { data in - if data != nil { - let json = try? JSONSerialization.jsonObject(with: data!, - options: []) - if let faqCategoryDictionary = json as? [String: Any?] { - let faqCategory = FAQCategoryItem(jsonDictionary: faqCategoryDictionary) - - completion(faqCategory) - } - } else { - completion(nil) - } - } - } - - func getStructure(id: Int, completion: @escaping (FAQStructure?) -> ()) throws { - try accessChecker.checkAccess() - faqClient.getActions().getStructure(categoryId: id) { data in - if data != nil { - let json = try? JSONSerialization.jsonObject(with: data!, - options: []) - if let faqStructureDictionary = json as? [String: Any?] { - let faqStructure = FAQStructureItem(jsonDictionary: faqStructureDictionary) - - completion(faqStructure) - } - } else { - completion(nil) - } - } - - } - - func getItem(id: String, completion: @escaping (FAQItem?) -> ()) throws { - try accessChecker.checkAccess() - - faqClient.getActions().getItem(itemId: id) { data in - if data != nil { - let json = try? JSONSerialization.jsonObject(with: data!, - options: []) - if let faqItemDictionary = json as? [String: Any?] { - let faqItem = FAQItemItem(jsonDictionary: faqItemDictionary) - - completion(faqItem) - } - } else { - completion(nil) - } - } - } - - - func resume() throws { - try checkAccess() - - if !clientStarted { - faqClient.start() - clientStarted = true - } - - faqClient.resume() - } - - func pause() throws { - if faqDestroyer.isDestroyed() { - return - } - - try checkAccess() - - faqClient.pause() - } - - func destroy() throws { - if faqDestroyer.isDestroyed() { - return - } - - try checkAccess() - - faqDestroyer.destroy() - } - - // MARK: Private methods - private func checkAccess() throws { - try accessChecker.checkAccess() - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/LocationSettingsImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/LocationSettingsImpl.swift deleted file mode 100755 index 4ae91f1..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/LocationSettingsImpl.swift +++ /dev/null @@ -1,96 +0,0 @@ -// -// LocationSettingsImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that encapsulates various location settings received form server when initializing session. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class LocationSettingsImpl { - - // MARK: - Constants - enum UserDefaultsKey: String { - case hintsEnabled = "hints_enabled" - } - - - // MARK: - Properties - private var hintsEnabled: Bool - - - // MARK: - Initialization - init(hintsEnabled: Bool) { - self.hintsEnabled = hintsEnabled - } - - - // MARK: - Methods - - static func getFrom(userDefaults userDefaultsKey: String) -> LocationSettingsImpl { - if let userDefaults = UserDefaults.standard.dictionary(forKey: userDefaultsKey) { - if let hintsEnabled = userDefaults[UserDefaultsKey.hintsEnabled.rawValue] as? Bool { - return LocationSettingsImpl(hintsEnabled: hintsEnabled) - } - } - - return LocationSettingsImpl(hintsEnabled: false) - } - - func saveTo(userDefaults userDefaultsKey: String) { - if var userDefaults = UserDefaults.standard.dictionary(forKey: userDefaultsKey) { - userDefaults[UserDefaultsKey.hintsEnabled.rawValue] = hintsEnabled - UserDefaults.standard.set(userDefaults, - forKey: userDefaultsKey) - } - - UserDefaults.standard.setValue([UserDefaultsKey.hintsEnabled.rawValue: hintsEnabled], - forKey: userDefaultsKey) - } - -} - -// MARK: - Equatable -extension LocationSettingsImpl: Equatable { - - static func == (lhs: LocationSettingsImpl, - rhs: LocationSettingsImpl) -> Bool { - return lhs.hintsEnabled == rhs.hintsEnabled - } - -} - -// MARK: - LocationSettings -extension LocationSettingsImpl: LocationSettings { - - func areHintsEnabled() -> Bool { - return hintsEnabled - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/MessageImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/MessageImpl.swift deleted file mode 100755 index cdd2ad6..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/MessageImpl.swift +++ /dev/null @@ -1,537 +0,0 @@ -// -// MessageImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 15.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Internal messages representasion. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -class MessageImpl { - - // MARK: - Properties - private let attachment: MessageAttachment? - private let id: String - private let operatorID: String? - private let rawText: String? - private let senderAvatarURLString: String? - private let senderName: String - private let sendStatus: MessageSendStatus - private let serverURLString: String - private let text: String - private let timeInMicrosecond: Int64 - private let type: MessageType - private var currentChatID: String? - private var data: [String: Any?]? - private var historyID: HistoryID? - private var historyMessage: Bool - private var read: Bool - private var messageCanBeEdited: Bool - - // MARK: - Initialization - init(serverURLString: String, - id: String, - operatorID: String?, - senderAvatarURLString: String?, - senderName: String, - sendStatus: MessageSendStatus = .SENT, - type: MessageType, - data: [String: Any?]?, - text: String, - timeInMicrosecond: Int64, - attachment: MessageAttachment?, - historyMessage: Bool, - internalID: String?, - rawText: String?, - read: Bool, - messageCanBeEdited: Bool) { - self.attachment = attachment - self.data = data - self.id = id - self.operatorID = operatorID - self.rawText = rawText - self.senderAvatarURLString = senderAvatarURLString - self.senderName = senderName - self.sendStatus = sendStatus - self.serverURLString = serverURLString - self.text = text - self.timeInMicrosecond = timeInMicrosecond - self.type = type - self.read = read - self.messageCanBeEdited = messageCanBeEdited - - self.historyMessage = historyMessage - if historyMessage { - historyID = HistoryID(dbID: internalID!, - timeInMicrosecond: timeInMicrosecond) - } else { - currentChatID = internalID - } - } - - // MARK: - Methods - - func getRawText() -> String? { - return rawText - } - - func getSenderAvatarURLString() -> String? { - return senderAvatarURLString - } - - func getTimeInMicrosecond() -> Int64 { - return timeInMicrosecond - } - - func hasHistoryComponent() -> Bool { - return (historyID != nil) - } - - func getHistoryID() -> HistoryID? { - guard historyID != nil else { - WebimInternalLogger.shared.log(entry: "Message \(self.toString()) do not have history component.", - verbosityLevel: .DEBUG) - - return nil - } - - return historyID - } - - func getCurrentChatID() -> String? { - guard currentChatID != nil else { - WebimInternalLogger.shared.log(entry: "Message \(self.toString()) do not have an ID in current chat or do not exist in current chat or chat exists itself not.", - verbosityLevel: .DEBUG) - - return nil - } - - return currentChatID - } - - func getServerUrlString() -> String { - return serverURLString - } - - func getSource() -> MessageSource { - return (historyMessage ? MessageSource.history : MessageSource.currentChat) - } - - func transferToCurrentChat(message: MessageImpl) -> MessageImpl { - if self != message { - message.setSecondaryHistory(historyEquivalentMessage: self) - - return message - } - - setSecondaryCurrentChat(currentChatEquivalentMessage: message) - - invertHistoryStatus() - - return self - } - - func transferToHistory(message: MessageImpl) -> MessageImpl { - if self != message { - message.setSecondaryCurrentChat(currentChatEquivalentMessage: self) - - return message - } - - setSecondaryHistory(historyEquivalentMessage: message) - - invertHistoryStatus() - - return self - } - - func invertHistoryStatus() { - guard historyID != nil, - currentChatID != nil else { - WebimInternalLogger.shared.log(entry: "Message \(self.toString()) has not history component or does not belong to current chat.", - verbosityLevel: .DEBUG) - - return - } - - historyMessage = !historyMessage - } - - func setSecondaryHistory(historyEquivalentMessage: MessageImpl) { - guard !getSource().isHistoryMessage(), - historyEquivalentMessage.getSource().isHistoryMessage() else { - WebimInternalLogger.shared.log(entry: "Message \(self.toString()) is already has history component.", - verbosityLevel: .DEBUG) - - return - } - - historyID = historyEquivalentMessage.getHistoryID() - } - - func setSecondaryCurrentChat(currentChatEquivalentMessage: MessageImpl) { - guard getSource().isHistoryMessage(), - !currentChatEquivalentMessage.getSource().isHistoryMessage() else { - WebimInternalLogger.shared.log(entry: "Current chat equivalent of the message \(self.toString()) is already has history component.", - verbosityLevel: .DEBUG) - - return - } - - currentChatID = currentChatEquivalentMessage.getCurrentChatID() - } - - func setRead(isRead: Bool) { - read = isRead - } - - func getRead() -> Bool { - return read - } - - func setMessageCanBeEdited(messageCanBeEdited: Bool) { - self.messageCanBeEdited = messageCanBeEdited - } - - func toString() -> String { - return """ -MessageImpl { - serverURLString = \(serverURLString), - ID = \(id), - operatorID = \(operatorID ?? "nil"), - senderAvatarURLString = \(senderAvatarURLString ?? "nil"), - senderName = \(senderName), - type = \(type), - text = \(text), - timeInMicrosecond = \(timeInMicrosecond), - attachment = \(attachment?.getURL().absoluteString ?? "nil"), - historyMessage = \(historyMessage), - currentChatID = \(currentChatID ?? "nil"), - historyID = \(historyID?.getDBid() ?? "nil"), - rawText = \(rawText ?? "nil"), - read = \(read) -} -""" - } - - // MARK: - - enum MessageSource { - case history - case currentChat - - // MARK: - Methods - - func assertIsCurrentChat() throws { - guard isCurrentChatMessage() else { - throw MessageError.invalidState("Current message is not a part of current chat.") - } - } - - func assertIsHistory() throws { - guard isHistoryMessage() else { - throw MessageError.invalidState("Current message is not a part of the history.") - } - } - - func isHistoryMessage() -> Bool { - return (self == .history) - } - - func isCurrentChatMessage() -> Bool { - return (self == .currentChat) - } - - } - - // MARK: - - enum MessageError: Error { - case invalidState(String) - } - -} - -// MARK: - Message -extension MessageImpl: Message { - - func getAttachment() -> MessageAttachment? { - return attachment - } - - func getData() -> [String: Any?]? { - return data - } - - func getID() -> String { - return id - } - - func getOperatorID() -> String? { - return operatorID - } - - func getSenderAvatarFullURL() -> URL? { - guard let senderAvatarURLString = senderAvatarURLString else { - return nil - } - - return URL(string: (serverURLString + senderAvatarURLString)) - } - - func getSendStatus() -> MessageSendStatus { - return sendStatus - } - - func getSenderName() -> String { - return senderName - } - - func getText() -> String { - return text - } - - func getTime() -> Date { - return Date(timeIntervalSince1970: TimeInterval(timeInMicrosecond / 1_000_000)) - } - - func getType() -> MessageType { - return type - } - - func isEqual(to message: Message) -> Bool { - return (self == message as! MessageImpl) - } - - func isReadByOperator() -> Bool { - return getRead() //todo: maybe returns old value - } - - func canBeEdited() -> Bool { - return messageCanBeEdited - } - -} - -// MARK: - Equatable -extension MessageImpl: Equatable { - - static func == (lhs: MessageImpl, - rhs: MessageImpl) -> Bool { - return ((((((((lhs.id == rhs.id) - && (lhs.operatorID == rhs.operatorID)) - && (lhs.rawText == rhs.rawText)) - && (lhs.senderAvatarURLString == rhs.senderAvatarURLString)) - && (lhs.senderName == rhs.senderName)) - && (lhs.text == rhs.text)) - && (lhs.timeInMicrosecond == rhs.timeInMicrosecond)) - && (lhs.type == rhs.type)) - && (lhs.isReadByOperator() == rhs.isReadByOperator() - && (lhs.canBeEdited() == rhs.canBeEdited())) - } - -} - -// MARK: - -/** - Internal messages' attachments representation. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MessageAttachmentImpl { - - // MARK: - Constants - private enum Period: Int64 { - case attachmentURLExpires = 300 // (seconds) = 5 (minutes). - } - - - // MARK: - Properties - private let urlString: String - private let size: Int64? - private let filename: String - private let contentType: String - private let imageInfo: ImageInfo? - - - // MARK: - Initialization - init(urlString: String, - size: Int64?, - filename: String, - contentType: String, - imageInfo: ImageInfo? = nil) { - self.urlString = urlString - self.size = size - self.filename = filename - self.contentType = contentType - self.imageInfo = imageInfo - } - - // MARK: - Methods - static func getAttachment(byServerURL serverURLString: String, - webimClient: WebimClient, - text: String) -> MessageAttachment? { - let textData = text.data(using: .utf8)! - guard let textDictionary = try? JSONSerialization.jsonObject(with: textData, - options: []) as? [String: Any?] else { - WebimInternalLogger.shared.log(entry: "Message attachment parameters parsing failed: \(text).", - verbosityLevel: .WARNING) - - return nil - } - - let fileParameters = FileParametersItem(jsonDictionary: textDictionary!) - guard let filename = fileParameters.getFilename(), - let guid = fileParameters.getGUID(), - let contentType = fileParameters.getContentType() else { - return nil - } - - guard let pageID = webimClient.getDeltaRequestLoop().getAuthorizationData()?.getPageID(), - let authorizationToken = webimClient.getDeltaRequestLoop().getAuthorizationData()?.getAuthorizationToken() else { - WebimInternalLogger.shared.log(entry: "Tried to access to message attachment without authorization data.") - - return nil - } - - let expires = Int64(Date().timeIntervalSince1970) + Period.attachmentURLExpires.rawValue - let data: String = guid + String(expires) - if let hash = data.hmacSHA256(withKey: authorizationToken) { - let fileURLString = serverURLString + WebimActions.ServerPathSuffix.downloadFile.rawValue + "/" - + guid + "/" - + filename.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)! + "?" - + "page-id" + "=" + pageID + "&" - + "expires" + "=" + String(expires) + "&" - + "hash" + "=" + hash - - return MessageAttachmentImpl(urlString: fileURLString, - size: fileParameters.getSize(), - filename: filename, - contentType: contentType, - imageInfo: extractImageInfoOf(fileParameters: fileParameters, - with: fileURLString)) - } else { - WebimInternalLogger.shared.log(entry: "Error creating message attachment link due to HMAC SHA256 encoding error.") - - return nil - } - } - - // MARK: Private methods - private static func extractImageInfoOf(fileParameters: FileParametersItem?, - with fileURLString: String?) -> ImageInfo? { - guard fileParameters != nil, - fileURLString != nil else { - return nil - } - - let imageSize = fileParameters?.getImageParameters()?.getSize() - guard imageSize != nil else { - return nil - } - - let thumbURLString = (fileURLString == nil) ? nil : (fileURLString! + "&thumb=ios") - guard thumbURLString != nil else { - return nil - } - - return ImageInfoImpl(withThumbURLString: thumbURLString!, - width: imageSize!.getWidth(), - height: imageSize!.getHeight()) - } - -} - -// MARK: - MessageAttachment -extension MessageAttachmentImpl: MessageAttachment { - - func getContentType() -> String { - return contentType - } - - func getFileName() -> String { - return filename - } - - func getImageInfo() -> ImageInfo? { - return imageInfo - } - - func getSize() -> Int64? { - return size - } - - func getURL() -> URL { - return URL(string: urlString)! - } - -} - -// MARK: - -/** - Internal image information representation. - - seealso: - `MessageAttachment` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class ImageInfoImpl: ImageInfo { - - // MARK: - Properties - private let thumbURLString: String - private let width: Int? - private let height: Int? - - // MARK: - Initialization - init(withThumbURLString thumbURLString: String, - width: Int?, - height: Int?) { - self.thumbURLString = thumbURLString - self.width = width - self.height = height - } - - // MARK: - Methods - // MARK: ImageInfo protocol methods - - func getThumbURL() -> URL { - return URL(string: thumbURLString)! - } - - func getHeight() -> Int? { - return height - } - - func getWidth() -> Int? { - return width - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/MessageStreamImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/MessageStreamImpl.swift deleted file mode 100755 index 8a299e2..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/MessageStreamImpl.swift +++ /dev/null @@ -1,700 +0,0 @@ -// -// MessageStreamImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 08.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that responsible for handling full set of events inside message stream. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MessageStreamImpl { - - // MARK: - Properties - private let accessChecker: AccessChecker - private let currentChatMessageFactoriesMapper: MessageMapper - private let locationSettingsHolder: LocationSettingsHolder - private let messageComposingHandler: MessageComposingHandler - private let messageHolder: MessageHolder - private let sendingMessageFactory: SendingFactory - private let serverURLString: String - private let webimActions: WebimActions - private var chat: ChatItem? - private weak var chatStateListener: ChatStateListener? - private var currentOperator: OperatorImpl? - private var departmentList: [Department]? - private weak var departmentListChangeListener: DepartmentListChangeListener? - private weak var currentOperatorChangeListener: CurrentOperatorChangeListener? - private var isChatIsOpening = false - private var lastChatState: ChatItem.ChatItemState = .unknown - private var lastOperatorTypingStatus: Bool? - private weak var locationSettingsChangeListener: LocationSettingsChangeListener? - private var operatorFactory: OperatorFactory - private weak var operatorTypingListener: OperatorTypingListener? - private var onlineStatus: OnlineStatusItem = .unknown - private weak var onlineStatusChangeListener: OnlineStatusChangeListener? - private var unreadByOperatorTimestamp: Date? - private weak var unreadByOperatorTimestampChangeListener: UnreadByOperatorTimestampChangeListener? - private var unreadByVisitorMessageCount: Int - private weak var unreadByVisitorMessageCountChangeListener: UnreadByVisitorMessageCountChangeListener? - private var unreadByVisitorTimestamp: Date? - private weak var unreadByVisitorTimestampChangeListener: UnreadByVisitorTimestampChangeListener? - private var visitSessionState: VisitSessionStateItem = .unknown - private weak var visitSessionStateListener: VisitSessionStateListener? - - // MARK: - Initialization - init(serverURLString: String, - currentChatMessageFactoriesMapper: MessageMapper, - sendingMessageFactory: SendingFactory, - operatorFactory: OperatorFactory, - accessChecker: AccessChecker, - webimActions: WebimActions, - messageHolder: MessageHolder, - messageComposingHandler: MessageComposingHandler, - locationSettingsHolder: LocationSettingsHolder) { - self.serverURLString = serverURLString - self.currentChatMessageFactoriesMapper = currentChatMessageFactoriesMapper - self.sendingMessageFactory = sendingMessageFactory - self.operatorFactory = operatorFactory - self.accessChecker = accessChecker - self.webimActions = webimActions - self.messageHolder = messageHolder - self.messageComposingHandler = messageComposingHandler - self.locationSettingsHolder = locationSettingsHolder - self.unreadByVisitorMessageCount = -1 - } - - // MARK: - Methods - - func getWebimActions() -> WebimActions { - return webimActions - } - - func set(visitSessionState: VisitSessionStateItem) { - let previousVisitSessionState = self.visitSessionState - self.visitSessionState = visitSessionState - - isChatIsOpening = false - - visitSessionStateListener?.changed(state: publicState(ofVisitSessionState: previousVisitSessionState), - to: publicState(ofVisitSessionState: visitSessionState)) - } - - func set(onlineStatus: OnlineStatusItem) { - self.onlineStatus = onlineStatus - } - - func set(unreadByOperatorTimestamp: Date?) { - let previousValue = self.unreadByOperatorTimestamp - - self.unreadByOperatorTimestamp = unreadByOperatorTimestamp - - if previousValue != unreadByOperatorTimestamp { - unreadByOperatorTimestampChangeListener?.changedUnreadByOperatorTimestampTo(newValue: self.unreadByOperatorTimestamp) - } - } - - func set(unreadByVisitorTimestamp: Date?) { - let previousValue = self.unreadByVisitorTimestamp - - self.unreadByVisitorTimestamp = unreadByVisitorTimestamp - - if previousValue != unreadByVisitorTimestamp { - unreadByVisitorTimestampChangeListener?.changedUnreadByVisitorTimestampTo(newValue: self.unreadByVisitorTimestamp) - } - } - - func set(unreadByVisitorMessageCount: Int) { - let previousValue = self.unreadByVisitorMessageCount - - self.unreadByVisitorMessageCount = unreadByVisitorMessageCount - - if previousValue != unreadByVisitorMessageCount { - unreadByVisitorMessageCountChangeListener?.changedUnreadByVisitorMessageCountTo(newValue: self.unreadByVisitorMessageCount) - } - } - - func changingChatStateOf(chat: ChatItem?) { - let previousChat = self.chat - self.chat = chat - - messageHolder.receiving(newChat: self.chat, - previousChat: previousChat, - newMessages: (self.chat == nil) ? [MessageImpl]() : currentChatMessageFactoriesMapper.mapAll(messages: self.chat!.getMessages())) - - let newChatState = (self.chat == nil) ? .closed : self.chat!.getState() - if let newChatState = newChatState { - // Recieved chat state can be unsupported by the library. - if lastChatState != newChatState { - chatStateListener?.changed(state: publicState(ofChatState: lastChatState), - to: publicState(ofChatState: newChatState)) - } - lastChatState = newChatState - } - - let newOperator = operatorFactory.createOperatorFrom(operatorItem: self.chat?.getOperator()) - if newOperator != currentOperator { - let previousOperator = currentOperator - currentOperator = newOperator - - currentOperatorChangeListener?.changed(operator: previousOperator, - to: newOperator) - } - - let operatorTypingStatus = ((chat != nil) - && chat!.isOperatorTyping()) - if lastOperatorTypingStatus != operatorTypingStatus { - operatorTypingListener?.onOperatorTypingStateChanged(isTyping: operatorTypingStatus) - } - lastOperatorTypingStatus = operatorTypingStatus - - if let unreadByOperatorTimestamp = chat?.getUnreadByOperatorTimestamp() { - set(unreadByOperatorTimestamp: Date(timeIntervalSince1970: unreadByOperatorTimestamp)) - } - - if let unreadByVisitorMessageCount = chat?.getUnreadByVisitorMessageCount() { - set(unreadByVisitorMessageCount: unreadByVisitorMessageCount) - } - - if let unreadByVisitorTimestamp = chat?.getUnreadByVisitorTimestamp() { - set(unreadByVisitorTimestamp: Date(timeIntervalSince1970: unreadByVisitorTimestamp)) - } - if chat?.getReadByVisitor() == true { - set(unreadByVisitorTimestamp: nil) - } - } - - func saveLocationSettingsOn(fullUpdate: FullUpdate) { - let hintsEnabled = (fullUpdate.getHintsEnabled() == true) - - let previousLocationSettings = locationSettingsHolder.getLocationSettings() - let newLocationSettings = LocationSettingsImpl(hintsEnabled: hintsEnabled) - - let newLocationSettingsReceived = locationSettingsHolder.receiving(locationSettings: newLocationSettings) - - if newLocationSettingsReceived { - locationSettingsChangeListener?.changed(locationSettings: previousLocationSettings, - to: newLocationSettings) - } - } - - func onOnlineStatusChanged(to newOnlineStatus: OnlineStatusItem) { - let previousPublicOnlineStatus = publicState(ofOnlineStatus: onlineStatus) - let newPublicOnlineStatus = publicState(ofOnlineStatus: newOnlineStatus) - - if onlineStatus != newOnlineStatus { - onlineStatusChangeListener?.changed(onlineStatus: previousPublicOnlineStatus, - to: newPublicOnlineStatus) - } - - onlineStatus = newOnlineStatus - } - - func onReceiving(departmentItemList: [DepartmentItem]) { - var departmentList = [Department]() - let departmentFactory = DepartmentFactory(serverURLString: serverURLString) - for departmentItem in departmentItemList { - let department = departmentFactory.convert(departmentItem: departmentItem) - departmentList.append(department) - } - self.departmentList = departmentList - - departmentListChangeListener?.received(departmentList: departmentList) - } - - // MARK: Private methods - - private func publicState(ofChatState chatState: ChatItem.ChatItemState) -> ChatState { - switch chatState { - case .queue: - return .QUEUE - case .chatting: - return .CHATTING - case .chattingWithRobot: - return .CHATTING_WITH_ROBOT - case .closed: - return .NONE - case .closedByVisitor: - return .CLOSED_BY_VISITOR - case .closedByOperator: - return .CLOSED_BY_OPERATOR - case .invitation: - return .INVITATION - default: - return .UNKNOWN - } - } - - private func publicState(ofOnlineStatus onlineStatus: OnlineStatusItem) -> OnlineStatus { - switch onlineStatus { - case .busyOffline: - return .BUSY_OFFLINE - case .busyOnline: - return .BUSY_ONLINE - case .offline: - return .OFFLINE - case .online: - return .ONLINE - default: - return .UNKNOWN - } - } - - private func publicState(ofVisitSessionState visitSessionState: VisitSessionStateItem) -> VisitSessionState { - switch visitSessionState { - case .chat: - return .CHAT - case .departmentSelection: - return .DEPARTMENT_SELECTION - case .idle: - return .IDLE - case .idleAfterChat: - return .IDLE_AFTER_CHAT - case .offlineMessage: - return .OFFLINE_MESSAGE - default: - return .UNKNOWN - } - } - -} - -// MARK: - MessageStream -extension MessageStreamImpl: MessageStream { - - // MARK: - Methods - - func getVisitSessionState() -> VisitSessionState { - return publicState(ofVisitSessionState: visitSessionState) - } - - func getChatState() -> ChatState { - return publicState(ofChatState: lastChatState) - } - - func getUnreadByOperatorTimestamp() -> Date? { - return unreadByOperatorTimestamp - } - - func getUnreadByVisitorMessageCount() -> Int { - return (unreadByVisitorMessageCount > 0) ? unreadByVisitorMessageCount : 0 - } - - func getUnreadByVisitorTimestamp() -> Date? { - return unreadByVisitorTimestamp - } - - func getDepartmentList() -> [Department]? { - return departmentList - } - - func getLocationSettings() -> LocationSettings { - return locationSettingsHolder.getLocationSettings() - } - - func getCurrentOperator() -> Operator? { - return currentOperator - } - - func getLastRatingOfOperatorWith(id: String) -> Int { - let rating = chat?.getOperatorIDToRate()?[id] - - return ((rating == nil) ? 0 : rating!.getRating()) - } - - - func rateOperatorWith(id: String?, - byRating rating: Int, - completionHandler: RateOperatorCompletionHandler?) throws { - guard rating >= 1, - rating <= 5 else { - WebimInternalLogger.shared.log(entry: "Rating must be within from 1 to 5 range. Passed value: \(rating)", - verbosityLevel: .WARNING) - - return - } - - try accessChecker.checkAccess() - - webimActions.rateOperatorWith(id: id, - rating: (rating - 3), // Accepted range: (-2, -1, 0, 1, 2). - completionHandler: completionHandler) - } - - func respondSentryCall(id: String) throws { - try accessChecker.checkAccess() - - webimActions.respondSentryCall(id: id) - } - - func startChat() throws { - try startChat(departmentKey: nil, - firstQuestion: nil) - } - - func startChat(firstQuestion: String?) throws { - try startChat(departmentKey: nil, - firstQuestion: firstQuestion) - } - - func startChat(departmentKey: String?) throws { - try startChat(departmentKey: departmentKey, - firstQuestion: nil) - } - - func startChat(customFields:String?) throws { - try startChat(departmentKey: nil, firstQuestion: nil, customFields: customFields) - } - - func startChat(firstQuestion:String?, customFields: String?) throws { - try startChat(departmentKey: nil, firstQuestion: firstQuestion, customFields: customFields) - } - - func startChat(departmentKey: String?, customFields: String?) throws { - try startChat(departmentKey: departmentKey, firstQuestion: nil, customFields: customFields) - } - - func startChat(departmentKey: String?, firstQuestion: String?) throws { - try startChat(departmentKey: departmentKey, firstQuestion: firstQuestion, customFields: nil) - } - - func startChat(departmentKey: String?, - firstQuestion: String?, - customFields: String?) throws { - try accessChecker.checkAccess() - - if (lastChatState.isClosed() - || (visitSessionState == .offlineMessage)) - && !isChatIsOpening { - webimActions.startChat(withClientSideID: ClientSideID.generateClientSideID(), - firstQuestion: firstQuestion, - departmentKey: departmentKey, - customFields: customFields) - } - } - - func closeChat() throws { - try accessChecker.checkAccess() - - let chatIsOpen = ((lastChatState != .closedByVisitor) - && (lastChatState != .closed)) - && (lastChatState != .unknown) - if chatIsOpen { - webimActions.closeChat() - } - } - - func setVisitorTyping(draftMessage: String?) throws { - try accessChecker.checkAccess() - - messageComposingHandler.setComposing(draft: draftMessage) - } - - func send(message: String) throws -> String { - return try sendMessageInternally(messageText: message) - } - - func send(message: String, - data: [String: Any]?, - completionHandler: DataMessageCompletionHandler?) throws -> String { - if data != nil, let jsonData = try? JSONSerialization.data(withJSONObject: data as Any, - options: []) { - let jsonString = String(data: jsonData, - encoding: .utf8) - - return try sendMessageInternally(messageText: message, - dataJSONString: jsonString, - dataMessageCompletionHandler: completionHandler) - } else { - return try sendMessageInternally(messageText: message) - } - } - - func send(message: String, - isHintQuestion: Bool?) throws -> String { - return try sendMessageInternally(messageText: message, - isHintQuestion: isHintQuestion) - } - - func send(file: Data, - filename: String, - mimeType: String, - completionHandler: SendFileCompletionHandler?) throws -> String { - try startChat() - - let messageID = ClientSideID.generateClientSideID() - messageHolder.sending(message: sendingMessageFactory.createFileMessageToSendWith(id: messageID)) - - webimActions.send(file: file, - filename: filename, - mimeType: mimeType, - clientSideID: messageID, - completionHandler: SendFileCompletionHandlerWrapper(sendFileCompletionHandler: completionHandler, - messageHolder: messageHolder)) - - return messageID - } - - func updateWidgetStatus(data: String) throws { - try accessChecker.checkAccess() - - webimActions.updateWidgetStatusWith(data: data) - } - - func edit(message: Message, text: String, completionHandler: EditMessageCompletionHandler?) throws -> Bool { - try accessChecker.checkAccess() - - if !message.canBeEdited() { - return false - } - let id = message.getID() - let oldMessage = messageHolder.changing(messageID: id, message: text) - if oldMessage != nil { - webimActions.send(message: text, - clientSideID: id, - dataJSONString: nil, - isHintQuestion: false, - editMessageCompletionHandler: EditMessageCompletionHandlerWrapper(editMessageCompletionHandler: completionHandler, - messageHolder: messageHolder, - message: oldMessage!)) - return true - } - return false - } - - func delete(message: Message, completionHandler: DeleteMessageCompletionHandler?) throws -> Bool { - try accessChecker.checkAccess() - - if !message.canBeEdited() { - return false - } - let id = message.getID() - let oldMessage = messageHolder.changing(messageID: id, message: nil) - - if oldMessage != nil { - webimActions.delete(clientSideID: id, - completionHandler: DeleteMessageCompletionHandlerWrapper(deleteMessageCompletionHandler: completionHandler, - messageHolder: messageHolder, - message: oldMessage!)) - return true - } - return false - } - - func setChatRead() throws { - try accessChecker.checkAccess() - - webimActions.setChatRead() - } - - func set(prechatFields: String) throws { - try accessChecker.checkAccess() - - webimActions.set(prechatFields: prechatFields) - } - - func newMessageTracker(messageListener: MessageListener) throws -> MessageTracker { - try accessChecker.checkAccess() - - return try messageHolder.newMessageTracker(withMessageListener: messageListener) as MessageTracker - } - - func set(visitSessionStateListener: VisitSessionStateListener) { - self.visitSessionStateListener = visitSessionStateListener - } - - func set(chatStateListener: ChatStateListener) { - self.chatStateListener = chatStateListener - } - - func set(currentOperatorChangeListener: CurrentOperatorChangeListener) { - self.currentOperatorChangeListener = currentOperatorChangeListener - } - - func set(operatorTypingListener: OperatorTypingListener) { - self.operatorTypingListener = operatorTypingListener - } - - func set(departmentListChangeListener: DepartmentListChangeListener) { - self.departmentListChangeListener = departmentListChangeListener - } - - func set(locationSettingsChangeListener: LocationSettingsChangeListener) { - self.locationSettingsChangeListener = locationSettingsChangeListener - } - - func set(onlineStatusChangeListener: OnlineStatusChangeListener) { - self.onlineStatusChangeListener = onlineStatusChangeListener - } - - func set(unreadByOperatorTimestampChangeListener: UnreadByOperatorTimestampChangeListener) { - self.unreadByOperatorTimestampChangeListener = unreadByOperatorTimestampChangeListener - } - - func set(unreadByVisitorMessageCountChangeListener: UnreadByVisitorMessageCountChangeListener) { - self.unreadByVisitorMessageCountChangeListener = unreadByVisitorMessageCountChangeListener - } - - func set(unreadByVisitorTimestampChangeListener: UnreadByVisitorTimestampChangeListener) { - self.unreadByVisitorTimestampChangeListener = unreadByVisitorTimestampChangeListener - } - - // MARK: Private methods - private func sendMessageInternally(messageText: String, - dataJSONString: String? = nil, - isHintQuestion: Bool? = nil, - dataMessageCompletionHandler: DataMessageCompletionHandler? = nil) throws -> String { - try startChat() - - let messageID = ClientSideID.generateClientSideID() - messageHolder.sending(message: sendingMessageFactory.createTextMessageToSendWith(id: messageID, - text: messageText)) - webimActions.send(message: messageText, - clientSideID: messageID, - dataJSONString: dataJSONString, - isHintQuestion: isHintQuestion, - dataMessageCompletionHandler: DataMessageCompletionHandlerWrapper(dataMessageCompletionHandler: dataMessageCompletionHandler, - messageHolder: messageHolder)) - - return messageID - } - -} - -// MARK: - -fileprivate final class SendFileCompletionHandlerWrapper: SendFileCompletionHandler { - - // MARK: - Properties - private let messageHolder: MessageHolder - private var sendFileCompletionHandler: SendFileCompletionHandler? - - // MARK: - Initialization - init(sendFileCompletionHandler: SendFileCompletionHandler?, - messageHolder: MessageHolder) { - self.sendFileCompletionHandler = sendFileCompletionHandler - self.messageHolder = messageHolder - } - - // MARK: - Methods - - func onSuccess(messageID: String) { - sendFileCompletionHandler?.onSuccess(messageID: messageID) - } - - func onFailure(messageID: String, - error: SendFileError) { - messageHolder.sendingCancelledWith(messageID: messageID) - sendFileCompletionHandler?.onFailure(messageID: messageID, - error: error) - } - -} - -fileprivate final class DataMessageCompletionHandlerWrapper: DataMessageCompletionHandler { - - // MARK: - Properties - private let messageHolder: MessageHolder - private weak var dataMessageCompletionHandler: DataMessageCompletionHandler? - - // MARK: - Initialization - init(dataMessageCompletionHandler: DataMessageCompletionHandler?, - messageHolder: MessageHolder) { - self.dataMessageCompletionHandler = dataMessageCompletionHandler - self.messageHolder = messageHolder - } - - // MARK: - Methods - - func onSuccess(messageID: String) { - dataMessageCompletionHandler?.onSuccess(messageID : messageID) - } - - func onFailure(messageID: String, error: DataMessageError) { - messageHolder.sendingCancelledWith(messageID: messageID) - dataMessageCompletionHandler?.onFailure(messageID: messageID, error: error) - } - -} - -fileprivate final class EditMessageCompletionHandlerWrapper: EditMessageCompletionHandler { - - // MARK: - Properties - private let messageHolder: MessageHolder - private weak var editMessageCompletionHandler: EditMessageCompletionHandler? - private let message: String - - // MARK: - Initialization - init(editMessageCompletionHandler: EditMessageCompletionHandler?, - messageHolder: MessageHolder, - message: String) { - self.editMessageCompletionHandler = editMessageCompletionHandler - self.messageHolder = messageHolder - self.message = message - } - - // MARK: - Methods - - func onSuccess(messageID: String) { - editMessageCompletionHandler?.onSuccess(messageID : messageID) - } - - func onFailure(messageID: String, error: EditMessageError) { - messageHolder.changingCancelledWith(messageID: messageID, message: message) - editMessageCompletionHandler?.onFailure(messageID: messageID, error: error) - } - -} - -fileprivate final class DeleteMessageCompletionHandlerWrapper: DeleteMessageCompletionHandler { - - // MARK: - Properties - private let messageHolder: MessageHolder - private weak var deleteMessageCompletionHandler: DeleteMessageCompletionHandler? - private let message: String - - // MARK: - Initialization - init(deleteMessageCompletionHandler: DeleteMessageCompletionHandler?, - messageHolder: MessageHolder, - message: String) { - self.deleteMessageCompletionHandler = deleteMessageCompletionHandler - self.messageHolder = messageHolder - self.message = message - } - - // MARK: - Methods - - func onSuccess(messageID: String) { - deleteMessageCompletionHandler?.onSuccess(messageID : messageID) - } - - func onFailure(messageID: String, error: DeleteMessageError) { - messageHolder.changingCancelledWith(messageID: messageID, message: message) - deleteMessageCompletionHandler?.onFailure(messageID: messageID, error: error) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/MessageTrackerImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/MessageTrackerImpl.swift deleted file mode 100755 index 5a80fa6..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/MessageTrackerImpl.swift +++ /dev/null @@ -1,644 +0,0 @@ -// -// MessageTrackerImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Class that is responsible for tracking changes of message stream. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class MessageTrackerImpl { - - // MARK: - Properties - private let messageHolder: MessageHolder - var idToHistoryMessageMap = [String: MessageImpl]() - weak var messageListener: MessageListener? - private var allMessageSourcesEnded = false - private var cachedCompletionHandler: MessageHolderCompletionHandlerWrapper? - private var cachedLimit: Int? - private var destroyed: Bool? - private var headMessage: MessageImpl? - private var firstHistoryUpdateReceived: Bool? - private var messagesLoading: Bool? - - // MARK: - Initialization - init(messageListener: MessageListener, - messageHolder: MessageHolder) { - self.messageListener = messageListener - self.messageHolder = messageHolder - } - - // MARK: - Methods - - func addedNew(message: MessageImpl, - of messageHolder: MessageHolder) { - do { - try message.getSource().assertIsCurrentChat() - } catch { - WebimInternalLogger.shared.log(entry: "Message which is being added is not a part of current chat: \(message.toString()).", - verbosityLevel: .DEBUG) - - return - } - - addNewOrMerge(message: message, - of: messageHolder) - - if (headMessage == nil) - || allMessageSourcesEnded { - // FIXME: Do it on endOfBatch only. - if let completionHandler = cachedCompletionHandler { - getNextUncheckedMessagesBy(limit: (cachedLimit ?? 0), - completion: completionHandler.getCompletionHandler()) - - cachedCompletionHandler = nil - } - } - } - - func addedNew(messages: [MessageImpl], - of messageHolder: MessageHolder) { - if !messages.isEmpty { - if (headMessage != nil) - || allMessageSourcesEnded { - for message in messages { - addNewOrMerge(message: message, - of: messageHolder) - } - } else { - var currentChatMessages = messageHolder.getCurrentChatMessages() - currentChatMessages.append(contentsOf: messages) - messageHolder.set(currentChatMessages: currentChatMessages) - - if let completionHandler = cachedCompletionHandler { - getNextUncheckedMessagesBy(limit: (cachedLimit ?? 0), - completion: completionHandler.getCompletionHandler()) - - cachedCompletionHandler = nil - } - } - } - } - - func changedCurrentChatMessage(from previousVersion: MessageImpl, - to newVersion: MessageImpl, - at index: Int, - of messageHolder: MessageHolder) { - do { - try previousVersion.getSource().assertIsCurrentChat() - } catch { - WebimInternalLogger.shared.log(entry: "Message which is being changed is not a part of current chat: \(previousVersion.toString()).", - verbosityLevel: .DEBUG) - - return - } - do { - try newVersion.getSource().assertIsCurrentChat() - } catch { - WebimInternalLogger.shared.log(entry: "Replacement message for a current chat message is not a part of current chat: \(newVersion.toString()).", - verbosityLevel: .DEBUG) - - return - } - - guard let headMessage = headMessage else { - return - } - - if headMessage.getSource().isHistoryMessage() { - if previousVersion == headMessage { - self.headMessage = newVersion - } - - messageListener?.changed(message: previousVersion, - to: newVersion) - } else { - let currentChatMessages = messageHolder.getCurrentChatMessages() - for (currentChatMessageIndex, currentChatMessage) in currentChatMessages.enumerated() { - if currentChatMessage.getID() == headMessage.getID() { - if index >= currentChatMessageIndex { - if previousVersion == headMessage { - self.headMessage = newVersion - } - - messageListener?.changed(message: previousVersion, - to: newVersion) - } - - return - } - } - } - } - - func deletedCurrentChat(message: MessageImpl, - at index: Int, - messageHolder: MessageHolder) { - do { - try message.getSource().assertIsCurrentChat() - } catch { - WebimInternalLogger.shared.log(entry: "Message which is being deleted is not a part of current chat: \(message.toString())", - verbosityLevel: .DEBUG) - } - - let currentChatMessages = messageHolder.getCurrentChatMessages() - - guard let headMessage = headMessage else { - return - } - - let headIndex = currentChatMessages.index(of: headMessage) ?? -1 - - if headMessage.getSource().isHistoryMessage() - || (index > headIndex) { - if headIndex == (index + 1) { - self.headMessage = (currentChatMessages.count < headIndex) ? nil : currentChatMessages[headIndex] - } - - messageListener?.removed(message: message) - } - } - - func endedHistoryBatch() { - guard firstHistoryUpdateReceived != true else { - return - } - - firstHistoryUpdateReceived = true - - if let completionHandler = cachedCompletionHandler { - getNextUncheckedMessagesBy(limit: (cachedLimit ?? 0), - completion: completionHandler.getCompletionHandler()) - - cachedCompletionHandler = nil - } - } - - func deletedHistoryMessage(withID messageID: String) { - guard let message = idToHistoryMessageMap[messageID] else { - return - } - idToHistoryMessageMap[messageID] = nil - - guard let headMessage = headMessage else { - return - } - if headMessage.getSource().isHistoryMessage() - && (message.getTimeInMicrosecond() >= headMessage.getTimeInMicrosecond()) { - messageListener?.removed(message: message) - } - } - - func changedHistory(message: MessageImpl) { - do { - try message.getSource().assertIsHistory() - } catch { - WebimInternalLogger.shared.log(entry: "Message which is being changed is not a part of history: \(message.toString()).", - verbosityLevel: .DEBUG) - } - - guard let headMessage = headMessage, - headMessage.getSource().isHistoryMessage(), - (message.getTimeInMicrosecond() >= headMessage.getTimeInMicrosecond()) else { - return - } - - let previousMessage: MessageImpl? = idToHistoryMessageMap[message.getHistoryID()!.getDBid()] - idToHistoryMessageMap[message.getHistoryID()!.getDBid()] = message - if previousMessage != nil { - messageListener?.changed(message: previousMessage!, - to: message) - } else { - WebimInternalLogger.shared.log(entry: "Unknown message was changed: \(message.toString())", - verbosityLevel: .DEBUG) - } - } - - func addedHistory(message: MessageImpl, - before id: HistoryID?) { - do { - try message.getSource().assertIsHistory() - } catch { - WebimInternalLogger.shared.log(entry: "Message which is being added is not a part of history: \(message.toString()).", - verbosityLevel: .DEBUG) - - return - } - - guard let headMessage = headMessage, - headMessage.getSource().isHistoryMessage() else { - return - } - - if let beforeID = id { - if let beforeMessage = idToHistoryMessageMap[beforeID.getDBid()] { - messageListener?.added(message: message, - after: beforeMessage) - } - } else { - let currentChatMessages = messageHolder.getCurrentChatMessages() - messageListener?.added(message: message, - after: (currentChatMessages.isEmpty ? nil : currentChatMessages.last!)) - } - - idToHistoryMessageMap[message.getHistoryID()!.getDBid()] = message - } - - // For testing purposes. - func set(messagesLoading: Bool) { - self.messagesLoading = messagesLoading - } - - // MARK: Private methods - - private func addNewOrMerge(message: MessageImpl, - of messageHolder: MessageHolder) { - do { - try message.getSource().assertIsCurrentChat() - } catch { - WebimInternalLogger.shared.log(entry: "Message which is being added is not a part of current chat: \(message.toString()).", - verbosityLevel: .DEBUG) - - return - } - - var toCallMessageAdded = true - - var currentChatMessages = messageHolder.getCurrentChatMessages() - - if headMessage == nil { - headMessage = message - } else if (headMessage!.getTimeInMicrosecond()) > message.getTimeInMicrosecond() { - toCallMessageAdded = false - - currentChatMessages.append(message) - } else { - for (historyID, historyMessage) in idToHistoryMessageMap { - if message.getID() == historyMessage.getID() { - toCallMessageAdded = false - - let replacingMessage = historyMessage.transferToCurrentChat(message: message) - currentChatMessages.append(replacingMessage) - if (replacingMessage != historyMessage) { - messageListener?.changed(message: historyMessage, - to: replacingMessage) - } - - idToHistoryMessageMap[historyID] = nil - - break - } - } - } - - if toCallMessageAdded { - for (currentChatMessageIndex, currentChatMessage) in currentChatMessages.enumerated() { - if currentChatMessage.getID() == message.getID() { - currentChatMessages[currentChatMessageIndex] = message - messageListener?.changed(message: currentChatMessage, - to: message) - messageHolder.set(currentChatMessages: currentChatMessages) - - break - } - } - - currentChatMessages.append(message) - - if let messageToSend = getToSendMirrorAndRemove(message: message, - of: messageHolder) { - messageListener?.changed(message: messageToSend, - to: message) - } else { - let messagesToSend = messageHolder.getMessagesToSend() - messageListener?.added(message: message, - after: (messageHolder.getMessagesToSend().isEmpty ? nil : messagesToSend.first!)) - } - } - - messageHolder.set(currentChatMessages: currentChatMessages) - } - - private func getToSendMirrorAndRemove(message: MessageImpl, - of messageHolder: MessageHolder) -> MessageToSend? { - var messagesToSend = messageHolder.getMessagesToSend() - - for i in 0.. ()) { - let completionHandler = { [weak self] (messages: [Message]) -> () in - self?.receive(messages: messages as! [MessageImpl], - limit: limit, - completion: completion) - - self?.messagesLoading = false - } - - if headMessage != nil { - messageHolder.getMessagesBy(limit: limit, - before: headMessage!, - completion: completionHandler) - } else { - messageHolder.getLatestMessages(byLimit: limit, - completion: completionHandler) - } - } - - private func receive(messages: [MessageImpl], - limit: Int, - completion: @escaping ([Message]) -> ()) { - var result: [MessageImpl]? - - if !messages.isEmpty { - let currentChatMessages = messageHolder.getCurrentChatMessages() - if !currentChatMessages.isEmpty { - if (messages.last!.getTime() >= currentChatMessages.first!.getTime()) { - // We received history that overlap current chat messages. Merging. - - var filteredMessages = [MessageImpl]() - - let firstMessage = messages.first! - - for message in messages { - var addToFilteredMessages = true - - if message.getSource().isHistoryMessage() { - let messageTime = message.getTime() - if (messageTime >= currentChatMessages.first!.getTime()) - && (messageTime <= currentChatMessages.last!.getTime()) { - for currentChatMessage in currentChatMessages { - if currentChatMessage.getID() == message.getID() { - addToFilteredMessages = false - - currentChatMessage.setSecondaryHistory(historyEquivalentMessage: message) - - break - } - } - } - } - - if addToFilteredMessages { - filteredMessages.append(message) - } - } - - if filteredMessages.isEmpty { - let completionHandler = { [weak self] (messages: [Message]) -> () in - self?.receive(messages: messages as! [MessageImpl], - limit: limit, - completion: completion) - - self?.messagesLoading = false - } - messageHolder.getMessagesBy(limit: limit, - before: firstMessage, - completion: completionHandler) - - return - } - - result = filteredMessages - } else { - result = messages - } - } else { - result = messages - } - - for message in messages { - if message.getSource().isHistoryMessage() { - idToHistoryMessageMap[message.getHistoryID()!.getDBid()] = message - } - } - - let firstMessage = result!.first! - - if headMessage == nil { - headMessage = firstMessage - } else if firstMessage.getTimeInMicrosecond() < headMessage!.getTimeInMicrosecond() { - headMessage = firstMessage - } - } else { // End `if !messages.isEmpty` - result = messages - - allMessageSourcesEnded = true - } - - completion(result!) - } - -} - -// MARK: - MessageTracker -extension MessageTrackerImpl: MessageTracker { - - func getLastMessages(byLimit limitOfMessages: Int, - completion: @escaping ([Message]) -> ()) throws { - try messageHolder.checkAccess() - guard destroyed != true else { - WebimInternalLogger.shared.log(entry: "MessageTracker object is destroyed. Unable to perform request to get new messages.") - completion([Message]()) - - return - } - guard messagesLoading != true else { - WebimInternalLogger.shared.log(entry: "Messages are already loading. Unable to perform a second request to get new messages.") - completion([Message]()) - - return - } - guard limitOfMessages > 0 else { - WebimInternalLogger.shared.log(entry: "Limit of messages to perform request to get new messages must be greater that zero. Passed value – \(limitOfMessages).") - completion([Message]()) - - return - } - - let wrappedCompletion: ([Message]) -> () = { [weak self] messages in - (self?.destroyed != false) ? completion(messages) : completion([Message]()) - } - - let currentChatMessages = messageHolder.getCurrentChatMessages() - if currentChatMessages.isEmpty { - messagesLoading = true - - cachedCompletionHandler = MessageHolderCompletionHandlerWrapper(completionHandler: wrappedCompletion) - cachedLimit = limitOfMessages - - messageHolder.getHistoryStorage().getLatestHistory(byLimit: limitOfMessages) { [weak self] messages in - if let cachedCompletionHandler = self?.cachedCompletionHandler, - !messages.isEmpty || self?.firstHistoryUpdateReceived == true { - self?.firstHistoryUpdateReceived = true - - let completionHandlerToPass = cachedCompletionHandler.getCompletionHandler() - self?.receive(messages: messages as! [MessageImpl], - limit: limitOfMessages, - completion: completionHandlerToPass) - - self?.cachedCompletionHandler = nil - - self?.messagesLoading = false - } - } - } else { - let result = Array(currentChatMessages.suffix(limitOfMessages)) - headMessage = result.first - - wrappedCompletion(result) - } - } - - func getNextMessages(byLimit limitOfMessages: Int, - completion: @escaping ([Message]) -> ()) throws { - try messageHolder.checkAccess() - guard destroyed != true else { - WebimInternalLogger.shared.log(entry: "MessageTracker object is destroyed. Unable to perform request to get new messages.") - completion([Message]()) - - return - } - guard messagesLoading != true else { - WebimInternalLogger.shared.log(entry: "Messages are already loading. Unable to perform a second request to get new messages.") - completion([Message]()) - - return - } - guard limitOfMessages > 0 else { - WebimInternalLogger.shared.log(entry: "Limit of messages to perform request to get new messages must be greater that zero. Passed value – \(limitOfMessages).") - completion([Message]()) - - return - } - - let wrappedCompletion: ([Message]) -> () = { [weak self] messages in - (self?.destroyed != false) ? completion(messages) : completion([Message]()) - } - - messagesLoading = true - - let currentChatMessages = messageHolder.getCurrentChatMessages() - if (firstHistoryUpdateReceived == true) - || (!currentChatMessages.isEmpty - && (currentChatMessages.first != headMessage)) { - getNextUncheckedMessagesBy(limit: limitOfMessages, - completion: wrappedCompletion) - } else { - cachedCompletionHandler = MessageHolderCompletionHandlerWrapper(completionHandler: wrappedCompletion) - cachedLimit = limitOfMessages - - messageHolder.getHistoryStorage().getLatestHistory(byLimit: limitOfMessages) { [weak self] messages in - if let cachedCompletionHandler = self?.cachedCompletionHandler, - !messages.isEmpty || self?.firstHistoryUpdateReceived == true { - self?.firstHistoryUpdateReceived = true - - let completionHandlerToPass = cachedCompletionHandler.getCompletionHandler() - self?.receive(messages: messages as! [MessageImpl], - limit: limitOfMessages, - completion: completionHandlerToPass) - - self?.cachedCompletionHandler = nil - - self?.messagesLoading = false - } - } - } - } - - func getAllMessages(completion: @escaping ([Message]) -> ()) throws { - try messageHolder.checkAccess() - guard destroyed != true else { - WebimInternalLogger.shared.log(entry: "MessageTracker object is destroyed. Unable to perform request to get new messages.") - completion([Message]()) - - return - } - - let wrappedCompletion: ([Message]) -> () = { [weak self] messages in - (self?.destroyed != false) ? completion(messages) : completion([Message]()) - } - - messageHolder.getHistoryStorage().getFullHistory(completion: wrappedCompletion) - } - - func resetTo(message: Message) throws { - try messageHolder.checkAccess() - guard destroyed != true else { - WebimInternalLogger.shared.log(entry: "MessageTracker object was destroyed. Unable to perform a request to reset to a message.") - - return - } - guard messagesLoading != true else { - WebimInternalLogger.shared.log(entry: "Messages is loading. Unable to perform a simultaneous request to reset to a message.") - - return - } - - let unwrappedMessage = message as! MessageImpl - if unwrappedMessage != headMessage { - messageHolder.set(reachedEndOfLocalHistory: false) - } - if unwrappedMessage.getSource().isHistoryMessage() { - var newIDToHistoryMessageMap = [String: MessageImpl]() - for (id, iteratedMessage) in idToHistoryMessageMap { - if iteratedMessage.getTimeInMicrosecond() >= unwrappedMessage.getTimeInMicrosecond() { - newIDToHistoryMessageMap[id] = iteratedMessage - } - } - idToHistoryMessageMap = newIDToHistoryMessageMap - } else { - idToHistoryMessageMap.removeAll() - } - - headMessage = unwrappedMessage - } - - func destroy() throws { - try messageHolder.checkAccess() - - if destroyed != true { - destroyed = true - - messageHolder.set(messagesToSend: [MessageToSend]()) - - messageHolder.set(messageTracker: nil) - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/OperatorImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/OperatorImpl.swift deleted file mode 100755 index d5f34bb..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/OperatorImpl.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// OperatorImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 17.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Internal representation of a chat operator data. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -struct OperatorImpl: Operator { - - // MARK: - Properties - private let id: String - private let name: String - private let avatarURLString: String? - - // MARK: - Initialization - init(id: String, - name: String, - avatarURLString: String? = nil) { - self.id = id - self.name = name - self.avatarURLString = avatarURLString - } - - // MARK: - Methods - // MARK: Operator protocol methods - - func getID() -> String { - return id - } - - func getName() -> String { - return name - } - - func getAvatarURL() -> URL? { - guard let avatarURLString = avatarURLString else { - return nil - } - - return URL(string: avatarURLString) - } - -} - -// MARK: - Equatable -extension OperatorImpl: Equatable { - - // MARK: - Methods - static func == (lhs: OperatorImpl, - rhs: OperatorImpl) -> Bool { - return ((lhs.id == rhs.id) - && (lhs.name == rhs.name)) - && (lhs.avatarURLString == rhs.avatarURLString) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/WebimErrorImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/WebimErrorImpl.swift deleted file mode 100755 index 4da19fb..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/WebimErrorImpl.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// WebimErrorImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Public Webim service error representation. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class WebimErrorImpl: WebimError { - - // MARK: - Properties - private var errorType: FatalErrorType - private var errorString: String? - - // MARK: - Initialization - init(errorType: FatalErrorType, - errorString: String?) { - self.errorType = errorType - self.errorString = errorString - } - - // MARK: - Methods - // MARK: WebimError protocol methods - - func getErrorType() -> FatalErrorType { - return errorType - } - - func getErrorString() -> String { - return (errorString ?? String(describing: errorType)) - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/WebimRemoteNotificationImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/WebimRemoteNotificationImpl.swift deleted file mode 100755 index 8ea4dcc..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/WebimRemoteNotificationImpl.swift +++ /dev/null @@ -1,125 +0,0 @@ -// -// WebimRemoteNotificationImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class WebimRemoteNotificationImpl { - - // MARK: - Constants - enum APNSField: String { - case aps = "aps" - case webim = "webim" - } - enum APSField: String { - case alert = "alert" - } - private enum AlertField: String { - case event = "event" - case parameters = "loc-args" - case type = "loc-key" - } - private enum InternalNotificationEvent: String { - case add = "add" - case delete = "del" - } - private enum InternalNotificationType: String { - case contactInformationRequest = "P.CR" - case operatorAccepted = "P.OA" - case operatorFile = "P.OF" - case operatorMessage = "P.OM" - case widget = "P.WM" - } - - // MARK: - Properties - private var event: InternalNotificationEvent? = nil - private lazy var parameters = [String]() - private var type: InternalNotificationType - - // MARK: - Initialization - init?(jsonDictionary: [String: Any?]) { - guard let typeString = jsonDictionary[AlertField.type.rawValue] as? String, - let type = InternalNotificationType(rawValue: typeString) else { - return nil - } - self.type = type - - if let eventString = jsonDictionary[AlertField.event.rawValue] as? String, - let event = InternalNotificationEvent(rawValue: eventString) { - self.event = event - } - - if let parameters = jsonDictionary[AlertField.parameters.rawValue] as? [String] { - self.parameters = parameters - } - } - -} - -// MARK: - WebimRemoteNotification -extension WebimRemoteNotificationImpl: WebimRemoteNotification { - - // MARK: - Methods - // MARK: WebimRemoteNotification protocol methods - - func getType() -> NotificationType { - switch type { - case .contactInformationRequest: - return .CONTACT_INFORMATION_REQUEST - case .operatorAccepted: - return .OPERATOR_ACCEPTED - case .operatorFile: - return .OPERATOR_FILE - case .operatorMessage: - return .OPERATOR_MESSAGE - case .widget: - return .WIDGET - } - } - - func getEvent() -> NotificationEvent? { - if let event = event { - switch event { - case .add: - return .ADD - case .delete: - return .DELETE - } - } - - return nil - } - - func getParameters() -> [String] { - return parameters - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Implementation/WebimSessionImpl.swift b/ios/libs/Webim/WebimClientLibrary/Implementation/WebimSessionImpl.swift deleted file mode 100755 index ae2ac75..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Implementation/WebimSessionImpl.swift +++ /dev/null @@ -1,765 +0,0 @@ -// -// WebimSessionImpl.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 02.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation -import UIKit - -// MARK: - Constants -fileprivate enum UserDefaultsName: String { - case guid = "ru.webim.WebimClientSDKiOS.guid" - case main = "ru.webim.WebimClientSDKiOS.visitor." -} -fileprivate enum UserDefaultsMainPrefix: String { - case authorizationToken = "auth_token" - case dbVersion = "db_version" - case deviceToken = "push_token" - case historyEnded = "history_ended" - case historyDBname = "history_db_name" - case historyMajorVersion = "history_major_version" - case historyRevision = "history_revision" - case pageID = "page_id" - case readBeforeTimestamp = "read_before_timestamp" - case sessionID = "session_id" - case visitor = "visitor" - case visitorExt = "visitor_ext" -} -fileprivate enum UserDefaultsGUIDPrefix: String { - case uuid = "guid" -} - -// MARK: - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class WebimSessionImpl { - - // MARK: - Constants - private enum DefaultSettings: String { - case pageTitle = "iOS Client" - } - - // MARK: - Properties - private var accessChecker: AccessChecker - private var clientStarted = false - private var historyPoller: HistoryPoller - private var messageStream: MessageStreamImpl - private var sessionDestroyer: SessionDestroyer - private var webimClient: WebimClient - - // MARK: - Initialization - private init(accessChecker: AccessChecker, - sessionDestroyer: SessionDestroyer, - webimClient: WebimClient, - historyPoller: HistoryPoller, - messageStream: MessageStreamImpl) { - self.accessChecker = accessChecker - self.sessionDestroyer = sessionDestroyer - self.webimClient = webimClient - self.historyPoller = historyPoller - self.messageStream = messageStream - } - - // MARK: - Methods - - static func newInstanceWith(accountName: String, - location: String, - appVersion: String?, - visitorFields: ProvidedVisitorFields?, - providedAuthorizationTokenStateListener: ProvidedAuthorizationTokenStateListener?, - providedAuthorizationToken: String?, - pageTitle: String?, - fatalErrorHandler: FatalErrorHandler?, - deviceToken: String?, - isLocalHistoryStoragingEnabled: Bool, - isVisitorDataClearingEnabled: Bool, - webimLogger: WebimLogger?, - verbosityLevel: SessionBuilder.WebimLoggerVerbosityLevel?, - prechat: String?) -> WebimSessionImpl { - WebimInternalLogger.setup(webimLogger: webimLogger, - verbosityLevel: verbosityLevel) - - let queue = DispatchQueue.global(qos: .userInteractive) - - let userDefaultsKey = UserDefaultsName.main.rawValue + (visitorFields?.getID() ?? "anonymous") - let userDefaults = UserDefaults.standard.dictionary(forKey: userDefaultsKey) - - if isVisitorDataClearingEnabled { - clearVisitorDataFor(userDefaultsKey: userDefaultsKey) - } - - checkSavedSessionFor(userDefaultsKey: userDefaultsKey, - newProvidedVisitorFields: visitorFields) - - let sessionDestroyer = SessionDestroyer(userDefaultsKey: userDefaultsKey) - - let visitorJSON = (userDefaults?[UserDefaultsMainPrefix.visitor.rawValue] ?? nil) - - let visitorFieldsJSONString = visitorFields?.getJSONString() - - let serverURLString = InternalUtils.createServerURLStringBy(accountName: accountName) - WebimInternalLogger.shared.log(entry: "Specified Webim server – \(serverURLString).", - verbosityLevel: .DEBUG) - - let currentChatMessageMapper: MessageMapper = CurrentChatMessageMapper(withServerURLString: serverURLString) - - let sessionID = userDefaults?[UserDefaultsMainPrefix.sessionID.rawValue] ?? nil - - let pageID = userDefaults?[UserDefaultsMainPrefix.pageID.rawValue] as! String? - let authorizationToken = userDefaults?[UserDefaultsMainPrefix.authorizationToken.rawValue] as! String? - let authorizationData = AuthorizationData(pageID: pageID, - authorizationToken: authorizationToken) - - let deltaCallback = DeltaCallback(currentChatMessageMapper: currentChatMessageMapper) - - let webimClient = WebimClientBuilder() - .set(baseURL: serverURLString) - .set(location: location) - .set(appVersion: appVersion) - .set(visitorFieldsJSONString: visitorFieldsJSONString) - .set(deltaCallback: deltaCallback) - .set(sessionParametersListener: SessionParametersListenerImpl(withUserDefaultsKey: userDefaultsKey)) - .set(internalErrorListener: DestroyOnFatalErrorListener(sessionDestroyer: sessionDestroyer, - internalErrorListener: ErrorHandlerToInternalAdapter(fatalErrorHandler: fatalErrorHandler))) - .set(visitorJSONString: visitorJSON as! String?) - .set(providedAuthenticationTokenStateListener: providedAuthorizationTokenStateListener, - providedAuthenticationToken: providedAuthorizationToken) - .set(sessionID: sessionID as! String?) - .set(authorizationData: authorizationData) - .set(completionHandlerExecutor: ExecIfNotDestroyedHandlerExecutor(sessionDestroyer: sessionDestroyer, - queue: queue)) - .set(title: (pageTitle ?? DefaultSettings.pageTitle.rawValue)) - .set(deviceToken: deviceToken) - .set(deviceID: getDeviceID()) - .set(prechat: prechat) - .build() as WebimClient - - var historyStorage: HistoryStorage - var historyMetaInformationStoragePreferences: HistoryMetaInformationStorage - if isLocalHistoryStoragingEnabled { - var dbName = userDefaults?[UserDefaultsMainPrefix.historyDBname.rawValue] as? String - - if dbName == nil { - dbName = "webim_" + ClientSideID.generateClientSideID() + ".db" - if let userDefaults = userDefaults { - var renewedUserDefaults = userDefaults - renewedUserDefaults[UserDefaultsMainPrefix.historyDBname.rawValue] = dbName - UserDefaults.standard.set(renewedUserDefaults, - forKey: userDefaultsKey) - } else { - UserDefaults.standard.setValue([UserDefaultsMainPrefix.historyDBname.rawValue: dbName], - forKey: userDefaultsKey) - } - } - - historyMetaInformationStoragePreferences = HistoryMetaInformationStoragePreferences(userDefaultsKey: userDefaultsKey) - - let sqlhistoryStorage = SQLiteHistoryStorage(dbName: dbName!, - serverURL: serverURLString, - webimClient: webimClient, - reachedHistoryEnd: historyMetaInformationStoragePreferences.isHistoryEnded(), - queue: queue, - readBeforeTimestamp: Int64(UserDefaults.standard.integer(forKey: UserDefaultsMainPrefix.readBeforeTimestamp.rawValue))) - historyStorage = sqlhistoryStorage - - let historyMajorVersion = historyStorage.getMajorVersion() - if (userDefaults?[UserDefaultsMainPrefix.historyMajorVersion.rawValue] as? Int) != historyMajorVersion { - if var userDefaults = UserDefaults.standard.dictionary(forKey: userDefaultsKey) { - userDefaults.removeValue(forKey: UserDefaultsMainPrefix.historyRevision.rawValue) - userDefaults.removeValue(forKey: UserDefaultsMainPrefix.historyEnded.rawValue) - userDefaults.removeValue(forKey: UserDefaultsMainPrefix.historyMajorVersion.rawValue) - UserDefaults.standard.setValue(userDefaults, - forKey: userDefaultsKey) - } - } - - if (userDefaults?[UserDefaultsMainPrefix.dbVersion.rawValue] as? Int) != sqlhistoryStorage.getVersionDB() { - sqlhistoryStorage.updateDB() - UserDefaults.standard.set(sqlhistoryStorage.getVersionDB(), forKey: UserDefaultsMainPrefix.dbVersion.rawValue) - } - } else { - historyStorage = MemoryHistoryStorage(readBeforeTimestamp: Int64(UserDefaults.standard.integer(forKey: UserDefaultsMainPrefix.readBeforeTimestamp.rawValue))) - historyMetaInformationStoragePreferences = MemoryHistoryMetaInformationStorage() - } - - let accessChecker = AccessChecker(thread: Thread.current, - sessionDestroyer: sessionDestroyer) - - let webimActions = webimClient.getActions() - let historyMessageMapper: MessageMapper = HistoryMessageMapper(withServerURLString: serverURLString) - let messageHolder = MessageHolder(accessChecker: accessChecker, - remoteHistoryProvider: RemoteHistoryProvider(webimActions: webimActions, - historyMessageMapper: historyMessageMapper, - historyMetaInformationStorage: historyMetaInformationStoragePreferences), - historyStorage: historyStorage, - reachedEndOfRemoteHistory: historyMetaInformationStoragePreferences.isHistoryEnded()) - let messageStream = MessageStreamImpl(serverURLString: serverURLString, - currentChatMessageFactoriesMapper: currentChatMessageMapper, - sendingMessageFactory: SendingFactory(withServerURLString: serverURLString), - operatorFactory: OperatorFactory(withServerURLString: serverURLString), - accessChecker: accessChecker, - webimActions: webimActions, - messageHolder: messageHolder, - messageComposingHandler: MessageComposingHandler(webimActions: webimActions, - queue: queue), - locationSettingsHolder: LocationSettingsHolder(userDefaultsKey: userDefaultsKey)) - - let historyPoller = HistoryPoller(withSessionDestroyer: sessionDestroyer, - queue: queue, - historyMessageMapper: historyMessageMapper, - webimActions: webimActions, - messageHolder: messageHolder, - historyMetaInformationStorage: historyMetaInformationStoragePreferences) - - deltaCallback.set(messageStream: messageStream, - messageHolder: messageHolder, - historyPoller: historyPoller) - - sessionDestroyer.add() { - webimClient.stop() - } - sessionDestroyer.add() { - historyPoller.pause() - } - - // Needed for message attachment secure download link generation. - currentChatMessageMapper.set(webimClient: webimClient) - historyMessageMapper.set(webimClient: webimClient) - - return WebimSessionImpl(accessChecker: accessChecker, - sessionDestroyer: sessionDestroyer, - webimClient: webimClient, - historyPoller: historyPoller, - messageStream: messageStream) - } - - // MARK: Private methods - - private static func clearVisitorDataFor(userDefaultsKey: String) { - deleteDBFileFor(userDefaultsKey: userDefaultsKey) - UserDefaults.standard.removeObject(forKey: userDefaultsKey) - } - - private static func deleteDBFileFor(userDefaultsKey: String) { - if let dbName = UserDefaults.standard.dictionary(forKey: userDefaultsKey)?[UserDefaultsMainPrefix.historyDBname.rawValue] as? String { - let fileManager = FileManager.default - let documentsDirectory = try! fileManager.url(for: .documentDirectory, - in: .userDomainMask, - appropriateFor: nil, - create: false) - let dbURL = documentsDirectory.appendingPathComponent(dbName) - - do { - try fileManager.removeItem(at: dbURL) - } catch { - WebimInternalLogger.shared.log(entry: "Error deleting DB file at \(dbURL) or file doesn't exist.", - verbosityLevel: .VERBOSE) - } - } - } - - private static func checkSavedSessionFor(userDefaultsKey: String, - newProvidedVisitorFields: ProvidedVisitorFields?) { - let newVisitorFieldsJSONString = newProvidedVisitorFields?.getJSONString() - let previousVisitorFieldsJSONString = UserDefaults.standard.dictionary(forKey: userDefaultsKey)?[UserDefaultsMainPrefix.visitorExt.rawValue] as? String - - var previousProvidedVisitorFields: ProvidedVisitorFields? = nil - if previousVisitorFieldsJSONString != nil { - previousProvidedVisitorFields = ProvidedVisitorFields(withJSONString: previousVisitorFieldsJSONString!) - - if (newProvidedVisitorFields == nil) - || (previousProvidedVisitorFields?.getID() != newProvidedVisitorFields?.getID()) { - clearVisitorDataFor(userDefaultsKey: userDefaultsKey) - } - } - - if newVisitorFieldsJSONString != previousVisitorFieldsJSONString { - UserDefaults.standard.removeObject(forKey: userDefaultsKey) - - let newVisitorFieldsDictionary = [UserDefaultsMainPrefix.visitorExt.rawValue: newVisitorFieldsJSONString] - UserDefaults.standard.set(newVisitorFieldsDictionary, - forKey: userDefaultsKey) - } - } - - private static func getDeviceID() -> String { - let userDefaults = UserDefaults.standard.dictionary(forKey: UserDefaultsName.guid.rawValue) - var uuidString = (userDefaults?[UserDefaultsGUIDPrefix.uuid.rawValue] ?? nil) - - if uuidString == nil { - uuidString = UIDevice.current.identifierForVendor!.uuidString - if var userDefaults = UserDefaults.standard.dictionary(forKey: UserDefaultsName.guid.rawValue) { - userDefaults[UserDefaultsGUIDPrefix.uuid.rawValue] = uuidString - UserDefaults.standard.set(userDefaults, - forKey: UserDefaultsName.guid.rawValue) - } else { - UserDefaults.standard.setValue([UserDefaultsGUIDPrefix.uuid.rawValue: uuidString], - forKey: UserDefaultsName.guid.rawValue) - } - } - - return uuidString as! String - } - -} - -// MARK: - WebimSession -extension WebimSessionImpl: WebimSession { - - func resume() throws { - try checkAccess() - - if !clientStarted { - webimClient.start() - clientStarted = true - } - - webimClient.resume() - historyPoller.resume() - } - - func pause() throws { - if sessionDestroyer.isDestroyed() { - return - } - - try checkAccess() - - webimClient.pause() - historyPoller.pause() - } - - func destroy() throws { - if sessionDestroyer.isDestroyed() { - return - } - - try checkAccess() - - sessionDestroyer.destroy() - } - - func destroyWithClearVisitorData() throws { - if sessionDestroyer.isDestroyed() { - return - } - - try checkAccess() - - sessionDestroyer.destroy() - WebimSessionImpl.clearVisitorDataFor(userDefaultsKey: sessionDestroyer.getUserDefaulstKey()) - } - - func getStream() -> MessageStream { - return messageStream - } - - func change(location: String) throws { - try checkAccess() - - try webimClient.getDeltaRequestLoop().change(location: location) - } - - func set(deviceToken: String) throws { - try checkAccess() - - webimClient.set(deviceToken: deviceToken) - } - - - // MARK: Private methods - private func checkAccess() throws { - try accessChecker.checkAccess() - } - -} - -// MARK: - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class HistoryPoller { - - // MARK: - Constants - private enum TimeInterval: Int64 { - case historyPolling = 60_000 // ms - } - - // MARK: - Properties - private let historyMessageMapper: MessageMapper - private let historyMetaInformationStorage: HistoryMetaInformationStorage - private let queue: DispatchQueue - private let messageHolder: MessageHolder - private let sessionDestroyer: SessionDestroyer - private let webimActions: WebimActions - private var dispatchWorkItem: DispatchWorkItem? - private var historySinceCompletionHandler: ((_ messageList: [MessageImpl], _ deleted: Set, _ hasMore: Bool, _ isInitial: Bool, _ revision: String?) -> ())? - private var lastPollingTime = -TimeInterval.historyPolling.rawValue - private var lastRevision: String? - private var running: Bool? - private var hasHistoryRevision = false - - // MARK: - Initialization - init(withSessionDestroyer sessionDestroyer: SessionDestroyer, - queue: DispatchQueue, - historyMessageMapper: MessageMapper, - webimActions: WebimActions, - messageHolder: MessageHolder, - historyMetaInformationStorage: HistoryMetaInformationStorage) { - self.sessionDestroyer = sessionDestroyer - self.queue = queue - self.historyMessageMapper = historyMessageMapper - self.webimActions = webimActions - self.messageHolder = messageHolder - self.historyMetaInformationStorage = historyMetaInformationStorage - } - - // MARK: - Methods - - func pause() { - dispatchWorkItem?.cancel() - dispatchWorkItem = nil - - running = false - } - - func resume() { - pause() - - running = true - - historySinceCompletionHandler = createHistorySinceCompletionHandler() - - let uptime = Int64(ProcessInfo.processInfo.systemUptime) * 1000 - if (uptime - lastPollingTime) > TimeInterval.historyPolling.rawValue { - requestHistory(since: lastRevision, - completion: historySinceCompletionHandler!) - } else { - if !self.hasHistoryRevision { - // Setting next history polling in TimeInterval.HISTORY_POLL after lastPollingTime. - - let dispatchTime = DispatchTime(uptimeNanoseconds: (UInt64((lastPollingTime + TimeInterval.historyPolling.rawValue) * 1_000_000) - UInt64((uptime) * 1_000_000))) - - dispatchWorkItem = DispatchWorkItem() { [weak self] in - guard let `self` = self else { - return - } - - self.requestHistory(since: self.lastRevision, - completion: self.historySinceCompletionHandler!) - } - - queue.asyncAfter(deadline: dispatchTime, - execute: dispatchWorkItem!) - } - } - } - - func set(hasHistoryRevision: Bool) { - self.hasHistoryRevision = hasHistoryRevision - } - - func updateReadBeforeTimestamp(timestamp: Int64) { - self.messageHolder.updateReadBeforeTimestamp(timestamp: timestamp) - } - - // MARK: Private methods - - private func createHistorySinceCompletionHandler() -> (_ messageList: [MessageImpl], _ deleted: Set, _ hasMore: Bool, _ isInitial: Bool, _ revision: String?) -> () { - return { [weak self] (messageList: [MessageImpl], deleted: Set, hasMore: Bool, isInitial: Bool, revision: String?) in - guard let `self` = self, - !self.sessionDestroyer.isDestroyed() else { - return - } - - self.lastPollingTime = Int64(ProcessInfo.processInfo.systemUptime) * 1000 - self.lastRevision = revision - - if isInitial - && !hasMore { - self.messageHolder.set(reachedEndOfLocalHistory: true) - self.historyMetaInformationStorage.set(historyEnded: true) - } - - self.messageHolder.receiveHistoryUpdateWith(messages: messageList, - deleted: deleted, - completion: { [weak self] in - // Revision is saved after history is saved only. - // I.e. if history will not be saved, then revision will not be overwritten. History will be re-requested. - self?.historyMetaInformationStorage.set(revision: revision) - }) - - if self.running != true { - if !isInitial - && hasMore { - self.lastPollingTime = -TimeInterval.historyPolling.rawValue - } - - return - } - - if !isInitial && hasMore { - self.requestHistory(since: revision, - completion: self.createHistorySinceCompletionHandler()) - } else { - if !self.hasHistoryRevision { - self.dispatchWorkItem = DispatchWorkItem() { [weak self] in - guard let `self` = self, self.hasHistoryRevision == false else { - return - } - self.requestHistory(since: revision, - completion: self.createHistorySinceCompletionHandler()) - - - } - let interval = Int(TimeInterval.historyPolling.rawValue) - self.queue.asyncAfter(deadline: (.now() + .milliseconds(interval)), - execute: self.dispatchWorkItem!) - } - } - } - } - - public func requestHistory(since: String) { - if self.lastRevision == nil || self.lastRevision != since { - requestHistory(since: lastRevision, completion: historySinceCompletionHandler!) - } - } - - private func requestHistory(since: String?, - completion: @escaping (_ messageList: [MessageImpl], _ deleted: Set, _ hasMore: Bool, _ isInitial: Bool, _ revision: String?) -> ()) { - webimActions.requestHistory(since: since) { data in - if data != nil { - let json = try? JSONSerialization.jsonObject(with: data!, - options: []) - if let historySinceResponseDictionary = json as? [String: Any?] { - let historySinceResponse = HistorySinceResponse(jsonDictionary: historySinceResponseDictionary) - - var deletes = Set() - var messageChanges = [MessageItem]() - - if let messages = historySinceResponse.getData()?.getMessages() { - for message in messages { - if message.isDeleted() { - if let id = message.getID() { - deletes.insert(id) - } - } else { - messageChanges.append(message) - } - } - } - - completion(self.historyMessageMapper.mapAll(messages: messageChanges), deletes, (historySinceResponse.getData()?.isHasMore() == true), (since == nil), historySinceResponse.getData()?.getRevision()) - } - } else { - completion([MessageImpl](), Set(), false, (since == nil), since) - } - } - } - -} - -// MARK: - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final class SessionParametersListenerImpl: SessionParametersListener { - - // MARL: - Constants - private enum VisitorFieldsJSONField: String { - case id = "id" - } - - // MARK: - Properties - private let userDefaultsKey: String - - // MARK: - Initialization - init(withUserDefaultsKey userDefaultsKey: String) { - self.userDefaultsKey = userDefaultsKey - } - - // MARK: - Methods - // MARK: SessionParametersListener methods - func onSessionParametersChanged(visitorFieldsJSONString: String, - sessionID: String, - authorizationData: AuthorizationData) { - if var userDefaults = UserDefaults.standard.dictionary(forKey: userDefaultsKey) { - userDefaults[UserDefaultsMainPrefix.visitor.rawValue] = visitorFieldsJSONString - userDefaults[UserDefaultsMainPrefix.sessionID.rawValue] = sessionID - userDefaults[UserDefaultsMainPrefix.pageID.rawValue] = authorizationData.getPageID() - userDefaults[UserDefaultsMainPrefix.authorizationToken.rawValue] = authorizationData.getAuthorizationToken() - UserDefaults.standard.set(userDefaults, - forKey: userDefaultsKey) - } else { - UserDefaults.standard.setValue([UserDefaultsMainPrefix.visitor.rawValue: visitorFieldsJSONString, - UserDefaultsMainPrefix.sessionID.rawValue: sessionID, - UserDefaultsMainPrefix.pageID.rawValue: authorizationData.getPageID(), - UserDefaultsMainPrefix.authorizationToken.rawValue: authorizationData.getAuthorizationToken()], - forKey: userDefaultsKey) - } - } - -} - -// MARK: - -/** - Class that responsible on destroying session on service fatal error occured. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final private class DestroyOnFatalErrorListener: InternalErrorListener { - - // MARK: - Properties - private let internalErrorListener: InternalErrorListener? - private var sessionDestroyer: SessionDestroyer - - // MARK: - Initialization - init(sessionDestroyer: SessionDestroyer, - internalErrorListener: InternalErrorListener?) { - self.sessionDestroyer = sessionDestroyer - self.internalErrorListener = internalErrorListener - } - - // MARK: - Methods - // MARK: InternalErrorListener protocol methods - func on(error: String) { - if !sessionDestroyer.isDestroyed() { - sessionDestroyer.destroy() - - internalErrorListener?.on(error: error) - } - } - -} - -// MARK: - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final private class ErrorHandlerToInternalAdapter: InternalErrorListener { - - // MARK: - Parameters - private var fatalErrorHandler: FatalErrorHandler? - - // MARK: - Initialization - init(fatalErrorHandler: FatalErrorHandler?) { - self.fatalErrorHandler = fatalErrorHandler - } - - // MARK: - Methods - - // MARK: InternalErrorListener protocol methods - func on(error: String) { - let webimError = WebimErrorImpl(errorType: toPublicErrorType(string: error), - errorString: error) - fatalErrorHandler?.on(error: webimError) - } - - // MARK: Private methods - private func toPublicErrorType(string: String) -> FatalErrorType { - switch string { - case WebimInternalError.accountBlocked.rawValue: - return .ACCOUNT_BLOCKED - case WebimInternalError.visitorBanned.rawValue: - return .VISITOR_BANNED - case WebimInternalError.wrongProvidedVisitorFieldsHashValue.rawValue: - return .WRONG_PROVIDED_VISITOR_HASH - case WebimInternalError.providedVisitorFieldsExpired.rawValue: - return .PROVIDED_VISITOR_FIELDS_EXPIRED - default: - return .UNKNOWN - } - } - -} - -// MARK: - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -final private class HistoryMetaInformationStoragePreferences: HistoryMetaInformationStorage { - - // MARK: - Properties - var userDefaultsKey: String - - // MARK: - Initialization - init(userDefaultsKey: String) { - self.userDefaultsKey = userDefaultsKey - } - - // MARK: - Methods - // MARK: HistoryMetaInformationStorage protocol methods - - func isHistoryEnded() -> Bool { - if let historyEnded = UserDefaults.standard.dictionary(forKey: userDefaultsKey)?[UserDefaultsMainPrefix.historyEnded.rawValue] as? Bool { - return historyEnded - } - - return false - } - - func set(historyEnded: Bool) { - if var userDefaults = UserDefaults.standard.dictionary(forKey: userDefaultsKey) { - userDefaults[UserDefaultsMainPrefix.historyEnded.rawValue] = historyEnded - UserDefaults.standard.set(userDefaults, - forKey: userDefaultsKey) - } else { - UserDefaults.standard.setValue([UserDefaultsMainPrefix.historyEnded.rawValue: historyEnded], - forKey: userDefaultsKey) - } - } - - func set(revision: String?) { - if let revision = revision { - if var userDefaults = UserDefaults.standard.dictionary(forKey: userDefaultsKey) { - userDefaults[UserDefaultsMainPrefix.historyRevision.rawValue] = revision - UserDefaults.standard.set(userDefaults, - forKey: userDefaultsKey) - } else { - UserDefaults.standard.setValue([UserDefaultsMainPrefix.historyRevision.rawValue: revision], - forKey: userDefaultsKey) - } - } - } - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Message.swift b/ios/libs/Webim/WebimClientLibrary/Message.swift deleted file mode 100755 index f3b8023..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Message.swift +++ /dev/null @@ -1,446 +0,0 @@ -// -// Message.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - - -import Foundation - - -/** - Abstracts a single message in the message history. - A message is an immutable object. It means that changing some of the message fields creates a new object. Messages can be compared by using `isEqual(to:)` method for searching messages with the same set of fields or by ID (`message1.getID() == message2.getID()`) for searching logically identical messages. ID is formed on the client side when sending a message (`MessageStream.send(message:isHintQuestion:)` or `MessageStream.sendFile(atPath:mimeType:completion:)). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol Message { - - /** - Messages of the types `MessageType.FILE_FROM_OPERATOR` and `MessageType.FILE_FROM_VISITOR` can contain attachments. - - important: - Notice that this method may return nil even in the case of previously listed types of messages. E.g. if a file is being sent. - - seealso: - `MessageAttachment` protocol. - - returns: - The attachment of the message. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getAttachment() -> MessageAttachment? - - /** - Messages of type `MessageType.ACTION_REQUEST` contain custom dictionary. - - returns: - Dictionary which contains custom fields or `nil` if there's no such custom fields. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getData() -> [String: Any?]? - - /** - Every message can be uniquefied by its ID. Messages also can be lined up by its IDs. - - important: - ID doesn’t change while changing the content of a message. - - returns: - Unique ID of the message. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getID() -> String - - /** - - returns: - ID of a message sender, if the sender is an operator. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getOperatorID() -> String? - - /** - - returns: - URL of a sender's avatar or `nil` if one does not exist. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getSenderAvatarFullURL() -> URL? - - /** - - returns: - Name of a message sender. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getSenderName() -> String - - /** - - returns: - `MessageSendStatus.SENT` if a message had been sent to the server, was received by the server and was delivered to all the clients; `MessageSendStatus.SENDING` if not. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getSendStatus() -> MessageSendStatus - - /** - - returns: - Text of the message. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getText() -> String - - /** - - returns: - Timestamp of the moment the message was processed by the server. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getTime() -> Date - - /** - - seealso: - `MessageType` enum. - - returns: - Type of a message. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getType() -> MessageType - - /** - Method which can be used to compare if two Message objects have identical contents. - - parameter message: - Second `Message` object. - - returns: - True if two `Message` objects are identical and false otherwise. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func isEqual(to message: Message) -> Bool - - /** - - returns: - True if visitor message read by operator or this message is not by visitor and false otherwise. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func isReadByOperator() -> Bool - - /** - - returns: - True if this message can be edited or deleted. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func canBeEdited() -> Bool - -} - -/** - Contains information about an attachment file. - - seealso: - `Message.getAttachment()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol MessageAttachment { - - /** - - returns: - MIME-type of an attachment file. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getContentType() -> String - - /** - - returns: - Name of an attachment file. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getFileName() -> String - - /** - - seealso: - `ImageInfo` protocol. - - returns: - If a file is an image, returns information about an image; in other cases returns nil. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getImageInfo() -> ImageInfo? - - /** - - returns: - Attachment file size in bytes. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getSize() -> Int64? - - /** - - important: - Notice that this URL is short-living and is tied to a session. - - returns: - URL of attached file. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getURL() -> URL - -} - -/** - Provides information about an image. - - seealso: - `MessageAttachment.getImageInfo()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol ImageInfo { - - /** - Returns a URL String of an image thumbnail. - The maximum width and height is usually 300 px but it can be adjusted at server settings. - To get an actual preview size before file uploading is completed, use the following code: - ```` - let THUMB_SIZE = 300 - var width = imageInfo.getWidth() - var height = imageInfo.getHeight() - if (height > width) { - width = (THUMB_SIZE * width) / height - height = THUMB_SIZE - } else { - height = (THUMB_SIZE * height) / width - width = THUMB_SIZE - } - ```` - - important: - Notice that this URL is short-living and is tied to a session. - - returns: - URL of reduced image. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getThumbURL() -> URL - - /** - - returns: - Height of an image in pixels. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getHeight() -> Int? - - /** - - returns: - Width of an image in pixels. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getWidth() -> Int? -} - -// MARK: - -/** - Supported message types. - - seealso: - `Message.getType()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum MessageType { - - /** - A message from operator which requests some actions from a visitor. - E.g. choose an operator group by clicking on a button in this message. - - seealso: - `Message.getData()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case ACTION_REQUEST - - /** - Message type that is received after operator clicked contacts request button. - - important: - There's no this functionality automatic support yet. All payload is transfered inside standard text field. - - seealso: - `Message.getText()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case CONTACTS_REQUEST - - /** - A message sent by an operator which contains an attachment. - - important: - Notice that the method `Message.getAttachment()` may return nil even for messages of this type. E.g. if a file is being sent. - - seealso: - `Message.getAttachment()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case FILE_FROM_OPERATOR - - /** - A message sent by a visitor which contains an attachment. - - important: - Notice that the method `Message.getAttachment()` may return nil even for messages of this type. E.g. if a file is being sent. - - seealso: - `Message.getAttachment()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case FILE_FROM_VISITOR - - /** - A system information message. - Messages of this type are automatically sent at specific events. E.g. when starting a chat, closing a chat or when an operator joins a chat. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case INFO - - /** - A text message sent by an operator. - - seealso: - `Message.getText()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case OPERATOR - - /** - A system information message which indicates that an operator is busy and can't reply to a visitor at the moment. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case OPERATOR_BUSY - - /** - A text message sent by a visitor. - - seealso: - `Message.getText()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case VISITOR - -} - -/** - Until a message is sent to the server, is received by the server and is spreaded among clients, message can be seen as "being send"; at the same time `Message.getSendStatus()` will return `SENDING`. In other cases - `SENT`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum MessageSendStatus { - - /** - A message is being sent. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case SENDING - - /** - A message had been sent to the server, received by the server and was spreaded among clients. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case SENT - -} diff --git a/ios/libs/Webim/WebimClientLibrary/MessageListener.swift b/ios/libs/Webim/WebimClientLibrary/MessageListener.swift deleted file mode 100755 index a6270a0..0000000 --- a/ios/libs/Webim/WebimClientLibrary/MessageListener.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// MessageListener.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Delegate protocol that provide methods to handle changes in message stream. - - seealso: - `MessageStream.newMessageTracker(messageListener:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol MessageListener: class { - - /** - Called when added a new message. - If `previousMessage == nil` then it should be added to the end of message history (the lowest message is added), in other cases the message should be inserted before the message (i.e. above in history) which was given as a parameter `previousMessage`. - - important: - Notice that this is a logical insertion of a message. I.e. calling this method does not necessarily mean receiving a new (unread) message. Moreover, at the first call `MessageTracker.getNextMessages(byLimit:completion:)` most often the last messages of a local history (i.e. which is stored on a user's device) are returned, and this method will be called for each message received from a server after a successful connection. - - seealso: - `Message` protocol. - - parameter newMessage: - Added message. - - parameter previousMessage: - A message after which it is needed to make a message insert. If `nil` then an insert is performed at the end of the list. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func added(message newMessage: Message, - after previousMessage: Message?) - - /** - Called when removing a message. - - seealso: - `Message` protocol. - - parameter message: - A message to be removed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func removed(message: Message) - - /** - Called when removed all the messages. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func removedAllMessages() - - /** - Called when changing a message. - `Message` is an immutable type and field values can not be changed. That is why message changing occurs as replacing one object with another. Thereby you can find out, for example, which certain message fields have changed by comparing an old and a new object values. - - seealso: - `Message` protocol. - - parameter oldVersion: - Message changed from. - - parameter newVersion: - Message changed to. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func changed(message oldVersion: Message, - to newVersion: Message) - -} diff --git a/ios/libs/Webim/WebimClientLibrary/MessageStream.swift b/ios/libs/Webim/WebimClientLibrary/MessageStream.swift deleted file mode 100755 index d28ecc2..0000000 --- a/ios/libs/Webim/WebimClientLibrary/MessageStream.swift +++ /dev/null @@ -1,1633 +0,0 @@ -// -// MessageStream.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 07.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - seealso: - `WebimSession.getStream()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol MessageStream: class { - - /** - - seealso: - `VisitSessionState` type. - - returns: - Current session state. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getVisitSessionState() -> VisitSessionState - - /** - - returns: - Current chat state. - - seealso: - `ChatState` type. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getChatState() -> ChatState - - /** - - returns: - Timestamp after which all chat messages are unread by operator (at the moment of last server update recieved). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getUnreadByOperatorTimestamp() -> Date? - - /** - - returns: - Timestamp after which all chat messages are unread by visitor (at the moment of last server update recieved) or `nil` if there's no unread by visitor messages. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getUnreadByVisitorTimestamp() -> Date? - - /** - - returns: - Count of unread by visitor messages (at the moment of last server update recieved). - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func getUnreadByVisitorMessageCount() -> Int - - /** - - seealso: - `Department` protocol. - `DepartmentListChangeListener` protocol. - - returns: - List of departments or `nil` if there're any or department list is not received yet. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getDepartmentList() -> [Department]? - - /** - - returns: - Current LocationSettings of the MessageStream. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getLocationSettings() -> LocationSettings - - /** - - returns: - Operator of the current chat. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getCurrentOperator() -> Operator? - - /** - - parameter id: - ID of the operator. - - returns: - Previous rating of the operator or 0 if it was not rated before. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getLastRatingOfOperatorWith(id: String) -> Int - - /** - Rates an operator. - To get an ID of the current operator call `getCurrentOperator()`. - - important: - Requires existing chat. - - seealso: - `RateOperatorCompletionHandler` protocol. - - parameter id: - ID of the operator to be rated. If passed `nil` current chat operator will be rated. - - parameter rate: - A number in range (1...5) that represents an operator rating. If the number is out of range, rating will not be sent to a server. - - parameter comletionHandler: - `RateOperatorCompletionHandler` object. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func rateOperatorWith(id: String?, - byRating rating: Int, - completionHandler: RateOperatorCompletionHandler?) throws - - /** - Respond sentry call - - important: - Id of redirect to sentry message - - parameter id: - ID of the operator to be rated. If passed `nil` current chat operator will be rated. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func respondSentryCall(id: String) throws - - /** - Changes `ChatState` to `ChatState.QUEUE`. - Can cause `VisitSessionState.DEPARTMENT_SELECTION` session state. It means that chat must be started by `startChat(departmentKey:)` method. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func startChat() throws - - /** - Starts chat and sends first message simultaneously. - Changes `ChatState` to `ChatState.QUEUE`. - - parameter firstQuestion: - First message to send. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func startChat(firstQuestion: String?) throws - - /** - Starts chat with particular department. - Changes `ChatState` to `ChatState.QUEUE`. - - seealso: - `Department` protocol. - - parameter departmentKey: - Department key (see `getKey()` of `Department` protocol). Calling this method without this parameter passed is the same as `startChat()` method is called. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func startChat(departmentKey: String?) throws - - - /** - Starts chat with custom fields. - Changes `ChatState` to `ChatState.QUEUE`. - - parameter customFields: - Custom fields in JSON format. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func startChat(customFields:String?) throws - - /** - Starts chat with particular department and sends first message simultaneously. - Changes `ChatState` to `ChatState.QUEUE`. - - seealso: - `Department` protocol. - - parameter departmentKey: - Department key (see `getKey()` of `Department` protocol). Calling this method without this parameter passed is the same as `startChat()` method is called. - - parameter firstQuestion: - First message to send. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev - - copyright: - 2017 Webim - */ - func startChat(departmentKey: String?, - firstQuestion: String?) throws - - /** - Starts chat with custom fields and sends first message simultaneously. - Changes `ChatState` to `ChatState.QUEUE`. - - parameter firstQuestion: - First message to send. - - parameter customFields: - Custom fields in JSON format. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func startChat(firstQuestion:String?, - customFields: String?) throws - - /** - Starts chat with particular department and custom fields. - Changes `ChatState` to `ChatState.QUEUE`. - - seealso: - `Department` protocol. - - parameter departmentKey: - Department key (see `getKey()` of `Department` protocol). Calling this method without this parameter passed is the same as `startChat()` method is called. - - parameter customFields: - Custom fields in JSON format. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func startChat(departmentKey: String?, - customFields: String?) throws - - /** - Starts chat with particular department and custom fields and sends first message simultaneously. - Changes `ChatState` to `ChatState.QUEUE`. - - seealso: - `Department` protocol. - - parameter departmentKey: - Department key (see `getKey()` of `Department` protocol). Calling this method without this parameter passed is the same as `startChat()` method is called. - - parameter firstQuestion: - First message to send. - - parameter customFields: - Custom fields in JSON format. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func startChat(departmentKey: String?, - firstQuestion: String?, - customFields: String?) throws - - - /** - Changes `ChatState` to `ChatState.CLOSED_BY_VISITOR`. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func closeChat() throws - - /** - This method must be called whenever there is a change of the input field of a message transferring current content of a message as a parameter. - - parameter draftMessage: - Current message content. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func setVisitorTyping(draftMessage: String?) throws - - /** - Sends prechat fields to server. - - parameter prechatFields: - Custom fields. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func set(prechatFields: String) throws - - /** - Sends a text message. - When calling this method, if there is an active `MessageTracker` (see newMessageTracker(messageListener:)). `MessageListener.added(message:after:)`) with a message `MessageSendStatus.SENDING` in the status is also called. - - important: - Maximum length of message is 32000 characters. Longer messages will be clipped. - - parameter message: - Text of the message. - - returns: - ID of the message. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func send(message: String) throws -> String - - /** - Sends a text message. - When calling this method, if there is an active `MessageTracker` object (see `newMessageTracker(messageListener:)` method). `MessageListener.added(message:after:)`) with a message `MessageSendStatus.SENDING` in the status is also called. - - important: - Maximum length of message is 32000 characters. Longer messages will be clipped. - - parameter message: - Text of the message. - - parameter data: - Optional. Custom message parameters dictionary. Note that this functionality does not work as is – server version must support it. - - parameter completionHandler: - Completion handler that executes when operation is done. - - returns: - ID of the message. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func send(message: String, - data: [String: Any]?, - completionHandler: DataMessageCompletionHandler?) throws -> String - - /** - Sends a text message. - When calling this method, if there is an active `MessageTracker` object (see `newMessageTracker(messageListener:)` method). `MessageListener.added(message:after:)`) with a message `MessageSendStatus.SENDING` in the status is also called. - - important: - Maximum length of message is 32000 characters. Longer messages will be clipped. - - parameter message: - Text of the message. - - parameter isHintQuestion: - Optional. Shows to server if a visitor chose a hint (true) or wrote his own text (false). - - returns: - ID of the message. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func send(message: String, - isHintQuestion: Bool?) throws -> String - - /** - Sends a file message. - When calling this method, if there is an active `MessageTracker` object (see `newMessageTracker(messageListener:)` method), `MessageListener.added(message:after:)` with a message `MessageSendStatus.SENDING` in the status is also called. - - seealso: - Method could fail. See `SendFileError`. - - parameter file: - File data to send - - parameter filename: - File name with file extension. - - parameter mimeType: - MIME type of the file to send. - - parameter completionHandler: - Completion handler that executes when operation is done. - - returns: - ID of the message. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func send(file: Data, - filename: String, - mimeType: String, - completionHandler: SendFileCompletionHandler?) throws -> String - - /** - Update widget status. The change is displayed by the operator. - - parameter data: - JSON string with new widget status. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - func updateWidgetStatus(data: String) throws - - /** - Edits a text message. - When calling this method, if there is an active `MessageTracker` object (see `newMessageTracker(messageListener:)` method). `MessageListener.changed(oldVersion:newVersion:)`) with a message `MessageSendStatus.SENDING` in the status is also called. - - important: - Maximum length of message is 32000 characters. Longer messages will be clipped. - - parameter message: - ID of the message to edit. - - parameter text: - Text of the message. - - parameter completionHandler: - Completion handler that executes when operation is done. - - returns: - True if the message can be edited. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func edit(message: Message, - text: String, - completionHandler: EditMessageCompletionHandler?) throws -> Bool - - /** - Deletes a message. - When calling this method, if there is an active `MessageTracker` object (see `newMessageTracker(messageListener:)` method). `MessageListener.removed(message:)`) with a message `MessageSendStatus.SENT` in the status is also called. - - parameter message: - The message to delete. - - parameter completionHandler: - Completion handler that executes when operation is done. - - returns: - True if the message can be deleted. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func delete(message: Message, - completionHandler: DeleteMessageCompletionHandler?) throws -> Bool - - /** - Set chat has been read by visitor. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Aleksej Lapenok - - copyright: - 2018 Webim - */ - func setChatRead() throws - - /** - `MessageTracker` (via `MessageTracker.getNextMessages(byLimit:completion:)`) allows to request the messages which are above in the history. Each next call `MessageTracker.getNextMessages(byLimit:completion:)` returns earlier messages in relation to the already requested ones. - Changes of user-visible messages (e.g. ever requested from `MessageTracker`) are transmitted to `MessageListener`. That is why `MessageListener` is needed when creating `MessageTracker`. - - important: - For each `MessageStream` at every single moment can exist the only one active `MessageTracker`. When creating a new one at the previous there will be automatically called `MessageTracker.destroy()`. - - parameter messageListener: - A listener of message changes in the tracking range. - - returns: - A new `MessageTracker` for this stream. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func newMessageTracker(messageListener: MessageListener) throws -> MessageTracker - - /** - Sets `VisitSessionStateListener` object. - - seealso: - `VisitSessionStateListener` protocol. - `VisitSessionState` type. - - parameter visitSessionStateListener: - `VisitSessionStateListener` object. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func set(visitSessionStateListener: VisitSessionStateListener) - - /** - Sets the `ChatState` change listener. - - parameter chatStateListener: - The `ChatState` change listener. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func set(chatStateListener: ChatStateListener) - - /** - Sets the current `Operator` change listener. - - parameter currentOperatorChangeListener: - Current `Operator` change listener. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func set(currentOperatorChangeListener: CurrentOperatorChangeListener) - - /** - Sets `DepartmentListChangeListener` object. - - seealso: - `DepartmentListChangeListener` protocol. - `Department` protocol. - - parameter departmentListChangeListener: - `DepartmentListChangeListener` object. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func set(departmentListChangeListener: DepartmentListChangeListener) - - /** - Sets the listener of the MessageStream LocationSettings changes. - - parameter locationSettingsChangeListener: - The listener of MessageStream LocationSettings changes. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func set(locationSettingsChangeListener: LocationSettingsChangeListener) - - /** - Sets the listener of the "operator typing" status changes. - - parameter operatorTypingListener: - The listener of the "operator typing" status changes. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func set(operatorTypingListener: OperatorTypingListener) - - /** - Sets the listener of session status changes. - - parameter onlineStatusChangeListener: - `OnlineStatusChangeListener` object. - - seealso: - `OnlineStatusChangeListener` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func set(onlineStatusChangeListener: OnlineStatusChangeListener) - - /** - Sets listener for parameter that is to be returned by `MessageStream.getUnreadByOperatorTimestamp()` method. - - parameter unreadByOperatorTimestampChangeListener: - `UnreadByOperatorTimestampChangeListener` object. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - func set(unreadByOperatorTimestampChangeListener: UnreadByOperatorTimestampChangeListener) - - /** - Sets listener for parameter that is to be returned by `MessageStream.getUnreadByVisitorMessageCount()` method. - - parameter unreadByVisitorMessageCountChangeListener: - `UnreadByVisitorMessageCountChangeListener` object. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func set(unreadByVisitorMessageCountChangeListener: UnreadByVisitorMessageCountChangeListener) - - /** - Sets listener for parameter that is to be returned by `MessageStream.getUnreadByVisitorTimestamp()` method. - - parameter unreadByVisitorTimestampChangeListener: - `UnreadByVisitorTimestampChangeListener` object. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - func set(unreadByVisitorTimestampChangeListener: UnreadByVisitorTimestampChangeListener) - -} - -/** - Interface that provides methods for handling MessageStream LocationSettings which are received from server. - - seealso: - `LocationSettingsChangeListener` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol LocationSettings { - - /** - This method shows to an app if it should show hint questions to visitor. - - returns: - True if an app should show hint questions to visitor, false otherwise. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func areHintsEnabled() -> Bool - -} - -// MARK: - -/** - - seealso: - `MessageStream.send(message:data:completionHandler:)`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -public protocol DataMessageCompletionHandler: class { - - /** - Executed when operation is done successfully. - - parameter messageID: - ID of the message. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - func onSuccess(messageID: String) - - /** - Executed when operation is failed. - - parameter messageID: - ID of the message. - - parameter error: - Error. - - seealso: - `DataMessageError`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - func onFailure(messageID: String, - error: DataMessageError) - -} - -/** - - seealso: - `MessageStream.edit(message:messageID:completionHandler:)`. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ -public protocol EditMessageCompletionHandler: class { - /** - Executed when operation is done successfully. - - parameter messageID: - ID of the message. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func onSuccess(messageID: String) - - /** - Executed when operation is failed. - - parameter messageID: - ID of the message. - - parameter error: - Error. - - seealso: - `EditMessageError`. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func onFailure(messageID: String, - error: EditMessageError) -} - -/** - - seealso: - `MessageStream.delete(messageID:completionHandler:)`. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ -public protocol DeleteMessageCompletionHandler: class { - /** - Executed when operation is done successfully. - - parameter messageID: - ID of the message. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func onSuccess(messageID: String) - - /** - Executed when operation is failed. - - parameter messageID: - ID of the message. - - parameter error: - Error. - - seealso: - `DeleteMessageError`. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func onFailure(messageID: String, - error: DeleteMessageError) -} - -/** - - seealso: - `MessageStream.send(file:filename:mimeType:completionHandler:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol SendFileCompletionHandler: class { - - /** - Executed when operation is done successfully. - - parameter messageID: - ID of the message. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func onSuccess(messageID: String) - - /** - Executed when operation is failed. - - parameter messageID: - ID of the message. - - parameter error: - Error. - - seealso: - `SendFileError`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func onFailure(messageID: String, - error: SendFileError) - -} - -/** - - seealso: - `MessageStream.rateOperatorWith(id:byRating:completionHandler:)`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol RateOperatorCompletionHandler: class { - - /** - Executed when operation is done successfully. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func onSuccess() - - /** - Executed when operation is failed. - - parameter error: - Error. - - seealso: - `RateOperatorError`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func onFailure(error: RateOperatorError) - -} - -/** - Provides methods to track changes of `VisitSessionState` status. - - seealso: - `VisitSessionState` protocol. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol VisitSessionStateListener: class { - - /** - Called when `VisitSessionState` status is changed. - - parameter previousState: - Previous value of `VisitSessionState` status. - - parameter newState: - New value of `VisitSessionState` status. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func changed(state previousState: VisitSessionState, - to newState: VisitSessionState) - -} - -/** - Delegate protocol that provides methods to handle changes of chat state. - - seealso: - `MessageStream.set(chatStateListener:)` - `MessageStream.getChatState()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol ChatStateListener: class { - - /** - Called during `ChatState` transition. - - parameter previousState: - Previous state. - - parameter newState: - New state. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func changed(state previousState: ChatState, - to newState: ChatState) - -} - -/** - - seealso: - `MessageStream.set(currentOperatorChangeListener:)` - `MessageStream.getCurrentOperator()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol CurrentOperatorChangeListener: class { - - /** - Called when `Operator` of the current chat changed. - - parameter previousOperator: - Previous operator. - - parameter newOperator: - New operator or nil if doesn't exist. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func changed(operator previousOperator: Operator?, - to newOperator: Operator?) - -} - -/** - Provides methods to track changes in departments list. - - seealso: - `Department` protocol. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol DepartmentListChangeListener: class { - - /** - Called when department list is received. - - seealso: - `Department` protocol. - - parameter departmentList: - Current department list. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func received(departmentList: [Department]) - -} - -/** - Interface that provides methods for handling changes in LocationSettings. - - seealso: - `LocationSettings` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol LocationSettingsChangeListener: class { - - /** - Method called by an app when new LocationSettings object is received. - - parameter previousLocationSettings: - Previous LocationSettings state. - - parameter newLocationSettings: - New LocationSettings state. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func changed(locationSettings previousLocationSettings: LocationSettings, - to newLocationSettings: LocationSettings) - -} - -/** - - seealso: - `MessageStream.set(operatorTypingListener:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol OperatorTypingListener: class { - - /** - Called when operator typing state changed. - - parameter isTyping: - True if operator is typing, false otherwise. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func onOperatorTypingStateChanged(isTyping: Bool) - -} - -/** - Interface that provides methods for handling changes of session status. - - seealso: - `MessageStream.set(onlineStatusChangeListener:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol OnlineStatusChangeListener: class { - - /** - Called when new session status is received. - - parameter previousOnlineStatus: - Previous value. - - parameter newOnlineStatus: - New value. - - seealso: - `OnlineStatus` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func changed(onlineStatus previousOnlineStatus: OnlineStatus, - to newOnlineStatus: OnlineStatus) - -} - -/** - Interface that provides methods for handling changes of parameter that is to be returned by `MessageStream.getUnreadByOperatorTimestamp()` method. - - seealso: - `MessageStream.set(unreadByOperatorTimestampChangeListener:)`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -public protocol UnreadByOperatorTimestampChangeListener: class { - - /** - Method to be called when parameter that is to be returned by `MessageStream.getUnreadByOperatorTimestamp()` method is changed. - - parameter newValue: - New unread by operator timestamp value. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - func changedUnreadByOperatorTimestampTo(newValue: Date?) - -} - -/** - Interface that provides methods for handling changes of parameter that is to be returned by `MessageStream.getUnreadByVisitorMessageCount()` method. - - seealso: - `MessageStream.set(unreadByVisitorMessageCountChangeListener:)`. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ -public protocol UnreadByVisitorMessageCountChangeListener: class { - - /** - Interface that provides methods for handling changes of parameter that is to be returned by `MessageStream.getUnreadByVisitorMessageCount()` method. - - parameter newValue: - New unread by visitor message count value. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func changedUnreadByVisitorMessageCountTo(newValue: Int) - -} - -/** - Interface that provides methods for handling changes of parameter that is to be returned by `MessageStream.getUnreadByVisitorTimestamp()` method. - - seealso: - `MessageStream.set(unreadByVisitorTimestampChangeListener:)`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -public protocol UnreadByVisitorTimestampChangeListener: class { - - /** - Interface that provides methods for handling changes of parameter that is to be returned by `MessageStream.getUnreadByVisitorTimestamp()` method. - - parameter newValue: - New unread by visitor timestamp value. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - func changedUnreadByVisitorTimestampTo(newValue: Date?) - -} - -// MARK: - - -/** - A chat is seen in different ways by an operator depending on ChatState. - The initial state is `NONE`. - Then if a visitor sends a message (`MessageStream.send(message:isHintQuestion:)`), the chat changes it's state to `QUEUE`. The chat can be turned into this state by calling `MessageStream.startChat()`. - After that, if an operator takes the chat to process, the state changes to `CHATTING`. The chat is being in this state until the visitor or the operator closes it. - When closing a chat by the visitor `MessageStream.closeChat()`, it turns into the state `CLOSED_BY_VISITOR`, by the operator - `CLOSED_BY_OPERATOR`. - When both the visitor and the operator close the chat, it's state changes to the initial – `NONE`. A chat can also automatically turn into the initial state during long-term absence of activity in it. - Furthermore, the first message can be sent not only by a visitor but also by an operator. In this case the state will change from the initial to `INVITATION`, and then, after the first message of the visitor, it changes to `CHATTING`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum ChatState { - - /** - Means that an operator has taken a chat for processing. - From this state a chat can be turned into: - * `CLOSED_BY_OPERATOR`, if an operator closes the chat; - * `CLOSED_BY_VISITOR`, if a visitor closes the chat (`MessageStream.closeChat()`); - * `NONE`, automatically during long-term absence of activity. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case CHATTING - - /** - Means that chat is picked up by a bot. - From this state a chat can be turned into: - * `CHATTING`, if an operator intercepted the chat; - * `CLOSED_BY_VISITOR`, if a visitor closes the chat (`MessageStream.closeChat()`); - * `NONE`, automatically during long-term absence of activity. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - case CHATTING_WITH_ROBOT - - /** - Means that an operator has closed the chat. - From this state a chat can be turned into: - * `NONE`, if the chat is also closed by a visitor (`MessageStream.closeChat()`), or automatically during long-term absence of activity; - * `QUEUE`, if a visitor sends a new message (`MessageStream.send(message:isHintQuestion:)`). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case CLOSED_BY_OPERATOR - - /** - Means that a visitor has closed the chat. - From this state a chat can be turned into: - * `NONE`, if the chat is also closed by an operator or automatically during long-term absence of activity; - * `QUEUE`, if a visitor sends a new message (`MessageStream.send(message:isHintQuestion:)`). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case CLOSED_BY_VISITOR - - /** - Means that a chat has been started by an operator and at this moment is waiting for a visitor's response. - From this state a chat can be turned into: - * `CHATTING`, if a visitor sends a message (`MessageStream.send(message:isHintQuestion:)`); - * `NONE`, if an operator or a visitor closes the chat (`MessageStream.closeChat()`). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case INVITATION - - /** - Means the absence of a chat as such, e.g. a chat has not been started by a visitor nor by an operator. - From this state a chat can be turned into: - * `QUEUE`, if the chat is started by a visitor (by the first message or by calling `MessageStream.startChat()`; - * `INVITATION`, if the chat is started by an operator. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case NONE - - /** - Means that a chat has been started by a visitor and at this moment is being in the queue for processing by an operator. - From this state a chat can be turned into: - * `CHATTING`, if an operator takes the chat for processing; - * `NONE`, if a visitor closes the chat (by calling (`MessageStream.closeChat()`) before it is taken for processing; - * `CLOSED_BY_OPERATOR`, if an operator closes the chat without taking it for processing. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case QUEUE - - /** - The state is undefined. - This state is set as the initial when creating a new session, until the first response of the server containing the actual state is got. This state is also used as a fallback if WebimClientLibrary can not identify the server state (e.g. if the server has been updated to a version that contains new states). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case UNKNOWN - -} - -/** - Online state possible cases. - - seealso: - `OnlineStatusChangeListener` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum OnlineStatus { - - /** - Offline state with chats' count limit exceeded. - Means that visitor is not able to send messages at all. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case BUSY_OFFLINE - - /** - Online state with chats' count limit exceeded. - Visitor is able send offline messages, but the server can reject it. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case BUSY_ONLINE - - /** - Visitor is able to send offline messages. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case OFFLINE - - /** - Visitor is able to send both online and offline messages. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case ONLINE - - /** - First status is not recieved yet or status is not supported by this version of the library. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case UNKNOWN - -} - -/** - Session possible states. - - seealso: - `getVisitSessionState()` method of `MessageStream` protocol. - `VisitSessionStateListener` protocol. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum VisitSessionState { - - /** - Chat in progress. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case CHAT - - /** - Chat must be started with department selected (there was a try to start chat without department selected). - - seealso: - `startChat(departmentKey:)` of `MessageStream` protocol. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case DEPARTMENT_SELECTION - - /** - Session is active but no chat is occuring (chat was not started yet). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case IDLE - - /** - Session is active but no chat is occuring (chat was closed recently). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case IDLE_AFTER_CHAT - - /** - Offline state. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case OFFLINE_MESSAGE - - /** - First status is not received yet or status is not supported by this version of the library. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case UNKNOWN - -} - -/** - - seealso: - `DataMessageCompletionHandler.onFailure(messageID:error:)`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ -public enum DataMessageError: Error { - - /** - Received error is not supported by current WebimClientLibrary version. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - case UNKNOWN - - // MARK: Quoted message errors - // Note that quoted message mechanism is not a standard feature – it must be implemented by a server. For more information please contact with Webim support service. - - /** - To be raised when quoted message ID belongs to a message without `canBeReplied` flag set to `true` (this flag is to be set on the server-side). - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - case QUOTED_MESSAGE_CANNOT_BE_REPLIED - - /** - To be raised when quoted message ID belongs to another visitor's chat. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - case QUOTED_MESSAGE_FROM_ANOTHER_VISITOR - - /** - To be raised when quoted message ID belongs to multiple messages (server DB error). - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - case QUOTED_MESSAGE_MULTIPLE_IDS - - /** - To be raised when one or more required arguments of quoting mechanism are missing. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - case QUOTED_MESSAGE_REQUIRED_ARGUMENTS_MISSING - - /** - To be raised when wrong quoted message ID is sent. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - case QUOTED_MESSAGE_WRONG_ID - -} - -/** - - seealso: - `EditMessageCompletionHandler.onFailure(messageID:error:)` - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ -public enum EditMessageError: Error { - /** - Received error is not supported by current WebimClientLibrary version. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case UNKNOWN - /** - Editing messages by visitor is turned off on the server. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case NOT_ALLOWED - /** - Editing message is empty. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case MESSAGE_EMPTY - /** - Visitor can edit only his messages. - The specified id belongs to someone else's message. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case MESSAGE_NOT_OWNED - /** - The server may deny a request if the message size exceeds a limit. - The maximum size of a message is configured on the server. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case MAX_LENGTH_EXCEEDED - /** - Visitor can edit only text messages. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case WRONG_MESSAGE_KIND -} - -/** - - seealso: - `DeleteMessageCompletionHandler.onFailure(messageID:error:)` - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ -public enum DeleteMessageError: Error { - /** - Received error is not supported by current WebimClientLibrary version. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case UNKNOWN - /** - Deleting messages by visitor is turned off on the server. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case NOT_ALLOWED - /** - Visitor can delete only his messages. - The specified id belongs to someone else's message. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case MESSAGE_NOT_OWNED - /** - Message with the specified id is not found in history. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case MESSAGE_NOT_FOUND -} - -/** - - seealso: - `SendFileCompletionHandler.onFailure(messageID:error:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum SendFileError: Error { - - /** - The server may deny a request if the file size exceeds a limit. - The maximum size of a file is configured on the server. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case FILE_SIZE_EXCEEDED - - /** - The server may deny a request if the file type is not allowed. - The list of allowed file types is configured on the server. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case FILE_TYPE_NOT_ALLOWED - - /** - Sending files in body is not supported. Use multipart form only. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case UPLOADED_FILE_NOT_FOUND - /** - Received error is not supported by current WebimClientLibrary version. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - case UNKNOWN - -} - -/** - - seealso: - `RateOperatorCompletionHandler.onFailure(error:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum RateOperatorError: Error { - - /** - Arised when trying to send operator rating request if no chat is exists. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case NO_CHAT - - /** - Arised when trying to send operator rating request if passed operator ID doesn't belong to existing chat operator (or, in the same place, chat doesn't have an operator at all). - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case WRONG_OPERATOR_ID - -} diff --git a/ios/libs/Webim/WebimClientLibrary/MessageTracker.swift b/ios/libs/Webim/WebimClientLibrary/MessageTracker.swift deleted file mode 100755 index 0bb48c1..0000000 --- a/ios/libs/Webim/WebimClientLibrary/MessageTracker.swift +++ /dev/null @@ -1,151 +0,0 @@ -// -// MessageTracker.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - MessageTracker allows to request the messages which are above in the history. - - seealso: - `MessageStream.newMessageTracker(messageListener:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol MessageTracker: class { - - /** - Requests last messages from history. Returns not more than `limitOfMessages` of messages. If an empty list is passed inside completion, there no messages in history yet. - If there is any previous `MessageTracker` request that is not completed, or limit of messages is less than 1, or current `MessageTracker` has been destroyed, this method will do nothing. - Following history request can be fulfilled by `getLastMessages(byLimit:completion:)` method. - - important: - Notice that this method can not be called again until the callback for the previous call will be invoked. - When an error occurs (e.g. there's one request is still running) an empty list will be returned inside completion block. - - seealso: - `getLastMessages(byLimit:completion:)` method. - `destroy()` method. - `Message` protocol. - - parameter limitOfMessages: - A number of messages will be returned (not more than this specified number). - - parameter completion: - Completion to be called on resulting array of messages if method call succeeded. It is guaranteed that completion will be called with empty or not result if call didn't throw an error. If current `MessageTracker` is destroyed completion will be called on empty result. - - parameter result: - Resulting array of messages if method call succeeded. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the `WebimSession` was created in. - `AccessError.INVALID_SESSION` if the method was called after `WebimSession` object was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getLastMessages(byLimit limitOfMessages: Int, - completion: @escaping (_ result: [Message]) -> ()) throws - - /** - Requests the messages above in history. Returns not more than `limitOfMessages` of messages. If an empty list is passed inside completion, the end of the message history is reached. - If there is any previous `MessageTracker` request that is not completed, or limit of messages is less than 1, or current `MessageTracker` has been destroyed, this method will do nothing. - - seealso: - `destroy()` method. - `Message` protocol. - - important: - Notice that this method can not be called again until the callback for the previous call will be invoked. - When an error occurs (e.g. there's one request is still running) an empty list will be returned inside completion block. - - parameter limitOfMessages: - A number of messages will be returned (not more than this specified number). - - parameter completion: - Completion to be called on resulting array of messages if method call succeeded. It is guaranteed that completion will be called with empty or not result if call didn't throw an error. If current `MessageTracker` is destroyed completion will be called on empty result. - - parameter result: - Resulting array of messages if method call succeeded. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the `WebimSession` was created in. - `AccessError.INVALID_SESSION` if the method was called after `WebimSession` object was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getNextMessages(byLimit limitOfMessages: Int, - completion: @escaping (_ result: [Message]) -> ()) throws - - /** - Requests all messages from history. If an empty list is passed inside completion, there no messages in history yet. - If there is any previous `MessageTracker` request that is not completed, or current `MessageTracker` has been destroyed, this method will do nothing. - - important: - This method is totally independent on `getNextMessages(byLimit:completion:)` and `getLastMessages(byLimit:completion:)` methods' calls. - When an error occurs (e.g. `MessageTracker` object is destroyed) an empty list will be returned inside completion block. - - seealso: - `destroy()` method. - `Message` protocol. - - parameter completion: - Completion to be called on resulting array of messages if method call succeeded. It is guaranteed that completion will be called with empty or not result if call didn't throw an error. If current `MessageTracker` is destroyed completion will be called on empty result. - - parameter result: - Resulting array of messages if method call succeeded. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the `WebimSession` was created in. - `AccessError.INVALID_SESSION` if the method was called after `WebimSession` object was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getAllMessages(completion: @escaping (_ result: [Message]) -> ()) throws - - /** - `MessageTracker` retains some range of messages. By using this method one can move the upper limit of this range to another message. - If there is any previous `MessageTracker` request that is not completed, this method will do nothing. - - important: - Notice that this method can not be used unless the previous call `getNextMessages(byLimit:completion:)` was finished (completion handler was invoked). - - seealso: - `Message` protocol. - - parameter message: - A message reset to. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the `WebimSession` was created in. - `AccessError.INVALID_SESSION` if the method was called after `WebimSession` object was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func resetTo(message: Message) throws - - /** - Destroys the `MessageTracker`. - It is impossible to use any `MessageTracker` methods after it was destroyed. - - seealso: - `Message` protocol. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the `WebimSession` was created in. - `AccessError.INVALID_SESSION` if the method was called after `WebimSession` object was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func destroy() throws - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Operator.swift b/ios/libs/Webim/WebimClientLibrary/Operator.swift deleted file mode 100755 index c0cba02..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Operator.swift +++ /dev/null @@ -1,73 +0,0 @@ -// -// Operator.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Abstracts a chat operator. - - seealso: - `MessageStream.getCurrentOperator()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol Operator { - - /** - - returns: - Unique ID of the operator. - - seealso: - `MessageStream.rateOperatorWith(id:byRate:completionHandler:)` - `MessageStream.getLastRatingOfOperatorWith(id:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getID() -> String - - /** - - returns: - Display name of the operator. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getName() -> String - - /** - - returns: - URL of the operator’s avatar or `nil` if does not exist. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getAvatarURL() -> URL? - -} diff --git a/ios/libs/Webim/WebimClientLibrary/ProvidedAuthorizationTokenStateListener.swift b/ios/libs/Webim/WebimClientLibrary/ProvidedAuthorizationTokenStateListener.swift deleted file mode 100755 index b2ead88..0000000 --- a/ios/libs/Webim/WebimClientLibrary/ProvidedAuthorizationTokenStateListener.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// ProvidedAuthorizationTokenStateListener.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 06.12.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - When client provides custom visitor authorization mechanism, it can be realised by providing custom authorization token which is used instead of visitor fields. - When provided authorization token is generated (or passed to session by client app), `update(providedAuthorizationToken:)` method is called. This method call indicates that client app must send provided authorisation token to its server which is responsible to send it to Webim service. - - important: - This mechanism can't be used as is. It requires that client server to support this mecahnism. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol ProvidedAuthorizationTokenStateListener: class { - - /** - Method is called in two cases: - 1. Provided authorization token is genrated (or set by client app) and must be sent to client server which is responsible to send it to Webim service. - 2. Passed provided authorization token is not valid. Provided authorization token can be invalid if Webim service did not receive it from client server yet. - When this method is called, client server must send provided authorization token to Webim service. - - parameter providedAuthorizationToken: - Provided authorization token which corresponds to session. - - seealso: - `set(providedAuthorizationTokenStateListener:providedAuthorizationToken:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func update(providedAuthorizationToken: String) - -} diff --git a/ios/libs/Webim/WebimClientLibrary/Webim.swift b/ios/libs/Webim/WebimClientLibrary/Webim.swift deleted file mode 100755 index 7fdf6d6..0000000 --- a/ios/libs/Webim/WebimClientLibrary/Webim.swift +++ /dev/null @@ -1,759 +0,0 @@ -// -// Webim.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 02.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Main point of WebimClientLibrary. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public final class Webim { - - /** - Returns new SessionBuilder object for creating WebimSession object. - - returns: - The instance of WebimSession builder. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - static public func newSessionBuilder() -> SessionBuilder { - return SessionBuilder() - } - - /** - Returns new FAQBuilder object for creating FAQ object. - - returns: - The instance of FAQ builder. - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - static public func newFAQBuilder() -> FAQBuilder { - return FAQBuilder() - } - - /** - Deserializes received remote notification. - This method can be called with `userInfo` parameter of your UIApplicationDelegate method `application(_:didReceiveRemoteNotification:)`. - Remote notification dictionary must be stored inside standard APNs key "aps". - - parameter remoteNotification: - User info of received remote notification. - - returns: - Remote notification object or nil if there's no useful payload or this notification is sent not by Webim service. - - seealso: - `SessionBuilder.set(remoteNotificationsSystem:)` - `isWebim(remoteNotification:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - static public func parse(remoteNotification: [AnyHashable : Any], visitorId: String? = nil) -> WebimRemoteNotification? { - return InternalUtils.parse(remoteNotification: remoteNotification, visitorId: visitorId) - } - - /** - If remote notifications (SessionBuilder.setRemoteNotificationSystem) are enabled for the session, then you can receive remote notifications belonging to this session. - This method can be called with `userInfo` parameter of your UIApplicationDelegate method `application(_:didReceiveRemoteNotification:)`. - Remote notification dictionary must be stored inside standard APNs key "aps". - - parameter remoteNotification: - User info of received remote notification. - - returns: - Boolean value that indicates is received remote notification is sent by Webim service. - - seealso: - `SessionBuilder.set(remoteNotificationSystem:)` - `parseRemoteNotification()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - static public func isWebim(remoteNotification: [AnyHashable: Any]) -> Bool { - return InternalUtils.isWebim(remoteNotification: remoteNotification) - } - - - // MARK: - - /** - - seealso: - `SessionBuilder.setRemoteNotificationSystem()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public enum RemoteNotificationSystem { - case APNS - case NONE - } - -} - -// MARK: - -/** - `WebimSession` builder. - - seealso: - `Webim.newSessionBuilder()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public final class SessionBuilder { - - // MARK: - Properties - private var accountName: String? - private var appVersion: String? - private var deviceToken: String? - private var fatalErrorHandler: FatalErrorHandler? - private var localHistoryStoragingEnabled = true - private var location: String? - private var pageTitle: String? - private var providedAuthorizationToken: String? - private weak var providedAuthorizationTokenStateListener: ProvidedAuthorizationTokenStateListener? - private var remoteNotificationSystem: Webim.RemoteNotificationSystem = .NONE - private var visitorDataClearingEnabled = false - private var visitorFields: ProvidedVisitorFields? - private weak var webimLogger: WebimLogger? - private var webimLoggerVerbosityLevel: WebimLoggerVerbosityLevel? - private var prechat: String? - - // MARK: - Methods - - /** - Sets company account name in Webim system. - Usually presented by full domain URL of the server (e.g "https://demo.webim.ru"). - For testing purposes it is possible to use account name "demo". - - parameter accountName: - Webim account name. - - returns: - `SessionBuilder` object with account name set. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(accountName: String) -> SessionBuilder { - self.accountName = accountName - - return self - } - - /** - Location on server. - You can use "mobile" or contact support for creating new one. - - parameter location: - Location name. - - returns: - `SessionBuilder` object with location set. - - seealso: - https://webim.ru/help/help-terms/#location - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(location: String) -> SessionBuilder { - self.location = location - - return self - } - - /** - Set prechat fields with extra information. - - parameter prechat: - Prechat fields in JSON format. - - returns: - `SessionBuilder` object with location set. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - public func set(prechat: String) -> SessionBuilder { - self.prechat = prechat - return self - } - - /** - You can differentiate your app versions on server by setting this parameter. E.g. "2.9.11". - This is optional. - - parameter appVersion: - Client app version name. - - returns: - `SessionBuilder` object with app version set. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(appVersion: String?) -> SessionBuilder { - self.appVersion = appVersion - - return self - } - - /** - A visitor can be anonymous or authorized. Without calling this method when creating a session visitor is anonymous. - In this case visitor receives a random ID, which is written in `UserDefaults`. If the data is lost (for example when application was reinstalled), the user ID is also lost, as well as the message history. - Authorizing of a visitor can be useful when there are internal mechanisms of authorization in your application and you want the message history to exist regardless of a device communication occurs from. - This method takes as a parameter a string containing the signed fields of a user in JSON format. Since the fields are necessary to be signed with a private key that can never be included into the code of a client's application, this string must be created and signed somewhere on your backend side. Read more about forming a string and a signature here: https://webim.ru/help/identification/ - - important: - Can't be used simultanously with `set(providedAuthorizationTokenStateListener:providedAuthorizationToken:)`. - - parameter jsonString: - JSON-string containing the signed fields of a visitor. - - returns: - `SessionBuilder` object with visitor fields set. - - SeeAlso: - https://webim.ru/help/identification/ - set(visitorFieldsJSONdata:) - - Author: - Nikita Lazarev-Zubov - - Copyright: - 2017 Webim - */ - public func set(visitorFieldsJSONString: String) -> SessionBuilder { - self.visitorFields = ProvidedVisitorFields(withJSONString: visitorFieldsJSONString) - - return self - } - - /** - A visitor can be anonymous or authorized. Without calling this method when creating a session visitor is anonymous. - In this case visitor receives a random ID, which is written in `UserDefaults`. If the data is lost (for example when application was reinstalled), the user ID is also lost, as well as the message history. - Authorizing of a visitor can be useful when there are internal mechanisms of authorization in your application and you want the message history to exist regardless of a device communication occurs from. - This method takes as a parameter a string containing the signed fields of a user in JSON format. Since the fields are necessary to be signed with a private key that can never be included into the code of a client's application, this string must be created and signed somewhere on your backend side. Read more about forming a string and a signature here: https://webim.ru/help/identification/ - - important: - Can't be used simultanously with `set(providedAuthorizationTokenStateListener:providedAuthorizationToken:)`. - - parameter jsonData: - JSON-data containing the signed fields of a visitor. - - returns: - `SessionBuilder` object with visitor fields set. - - SeeAlso: - `set(visitorFieldsJSONstring:)` - - Author: - Nikita Lazarev-Zubov - - Copyright: - 2017 Webim - */ - public func set(visitorFieldsJSONData: Data) -> SessionBuilder { - self.visitorFields = ProvidedVisitorFields(withJSONObject: visitorFieldsJSONData) - - return self - } - - /** - When client provides custom visitor authorization mechanism, it can be realised by providing custom authorization token which is used instead of visitor fields. - - important: - Can't be used simultaneously with `set(visitorFields:)`. - - parameter providedAuthorizationTokenStateListener: - `ProvidedAuthorizationTokenStateListener` object. - - parameter providedAuthorizationToken: - Optional. Client generated provided authorization token. If it is not passed, library generates its own. - - seealso: - `ProvidedAuthorizationTokenStateListener` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(providedAuthorizationTokenStateListener: ProvidedAuthorizationTokenStateListener?, - providedAuthorizationToken: String? = nil) -> SessionBuilder { - self.providedAuthorizationTokenStateListener = providedAuthorizationTokenStateListener - self.providedAuthorizationToken = providedAuthorizationToken - - return self - } - - /** - Sets the page title visible to an operator. In the web version of a chat it is a title of a web page a user opens a chat from. - By default "iOS Client". - - parameter pageTitle: - Page title that visible to an operator. - - returns: - `SessionBuilder` object with page title set. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(pageTitle: String?) -> SessionBuilder { - self.pageTitle = pageTitle - - return self - } - - /** - Sets a fatal error handler. An error is considered fatal if after processing it the session can not be continued anymore. - - parameter fatalErrorHandler: - Fatal error handler. - - returns: - `SessionBuilder` object with fatal error handler set. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(fatalErrorHandler: FatalErrorHandler?) -> SessionBuilder { - self.fatalErrorHandler = fatalErrorHandler - - return self - } - - /** - Webim service can send remote notifications when new messages are received in chat. - By default it does not. You have to handle receiving by yourself. - To differentiate notifications from your app and from Webim service check the field "from" (see `Webim.isWebim(remoteNotification:)`). - - important: - If remote notification system is set you must set device token. - - parameter remoteNotificationSystem: - Enum that indicates which system of remote notification is used. By default – `NONE` (remote notifications are not to be sent). - - returns: - `SessionBuilder` object with remote notification system set. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(remoteNotificationSystem: Webim.RemoteNotificationSystem) -> SessionBuilder { - self.remoteNotificationSystem = remoteNotificationSystem - - return self - } - - /** - Sets device token. - Example that shows how to change device token for the proper formatted one: - `let deviceToken = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()` - - parameter deviceToken: - Device token in hexadecimal format and without any spaces and service symbols. - - returns: - `SessionBuilder` object with device token set. - - seealso: - `setRemoteNotificationsSystem` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(deviceToken: String?) -> SessionBuilder { - self.deviceToken = deviceToken - - return self - } - - /** - By default a session stores a message history locally. This method allows to disable history storage. - - important: - Use only for debugging! - - parameter isLocalHistoryStoragingEnabled: - Boolean parameter that indicated if an app should enable or disable local history storing. - - returns: - `SessionBuilder` object with isLocalHistoryStoragingEnabled parameter set. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(isLocalHistoryStoragingEnabled: Bool) -> SessionBuilder { - self.localHistoryStoragingEnabled = isLocalHistoryStoragingEnabled - - return self - } - - /** - If set to true, all the visitor data is cleared before the session starts. - - important: - Use only for debugging! - - parameter isVisitorDataClearingEnabled: - Boolean parameter that indicated if an app should clear visitor data before session starts. - - returns: - `SessionBuilder` object with isVisitorDataClearingEnabled parameter set. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(isVisitorDataClearingEnabled: Bool) -> SessionBuilder { - self.visitorDataClearingEnabled = isVisitorDataClearingEnabled - - return self - } - - /** - Method to pass WebimLogger object. - - parameter webimLogger: - `WebimLogger` object. - - returns: - `SessionBuilder` object with `WebimLogger` object set. - - seealso: - `WebimLogger` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func set(webimLogger: WebimLogger?, - verbosityLevel: WebimLoggerVerbosityLevel = .WARNING) -> SessionBuilder { - self.webimLogger = webimLogger - webimLoggerVerbosityLevel = verbosityLevel - - return self - } - - /** - Builds new `WebimSession` object. - - important: - All the follow-up work with the session must be implemented from the same thread this method was called in. - Notice that a session is created as a paused. To start using it the first thing to do is to call `WebimSession.resume()`. - - returns: - New `WebimSession` object. - - throws: - `SessionBuilder.SessionBuilderError.NIL_ACCOUNT_NAME` if account name wasn't set to a non-nil value. - `SessionBuilder.SessionBuilderError.NIL_LOCATION` if location wasn't set to a non-nil value. - `SessionBuilder.SessionBuilderError.INVALID_REMOTE_NOTIFICATION_CONFIGURATION` if there is a try to pass device token with `RemoteNotificationSystem` not set (or set to `.NONE`). - `SessionBuilder.SessionBuilderError.INVALID_AUTHENTICATION_PARAMETERS` if methods `set(visitorFieldsJSONString:)` or `set(visitorFieldsJSONData:)` are called with `set(providedAuthorizationTokenStateListener:,providedAuthorizationToken:)` simultaneously. - - seealso: - `SessionBuilder.SessionBuilderError` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - public func build() throws -> WebimSession { - guard let accountName = accountName else { - throw SessionBuilderError.NIL_ACCOUNT_NAME - } - guard let location = location else { - throw SessionBuilderError.NIL_LOCATION - } - - let remoteNotificationsEnabled = (self.remoteNotificationSystem != Webim.RemoteNotificationSystem.NONE) - if (deviceToken != nil) - && !remoteNotificationsEnabled { - throw SessionBuilderError.INVALID_REMOTE_NOTIFICATION_CONFIGURATION - } - - if (visitorFields != nil) - && (providedAuthorizationTokenStateListener != nil) { - throw SessionBuilderError.INVALID_AUTHENTICATION_PARAMETERS - } - - var providedAuthorizationToken = self.providedAuthorizationToken - - if let listener = providedAuthorizationTokenStateListener { - providedAuthorizationToken = providedAuthorizationToken ?? ClientSideID.generateClientSideID() - listener.update(providedAuthorizationToken: providedAuthorizationToken!) - } - - if var prechat = self.prechat { - if !prechat.contains(":") { - //not json or string data - if prechat.count % 2 != 0 { - throw SessionBuilderError.INVALIDE_HEX - } - var byteArray = [UInt8]() - var index = prechat.startIndex - byteArray.reserveCapacity(prechat.count/2) - for _ in 0.. FAQBuilder { - self.accountName = accountName - - return self - } - - /** - Builds new `FAQ` object. - - important: - All the follow-up work with the FAQ must be implemented from the same thread this method was called in. - Notice that a FAQ is created as a paused. To start using it the first thing to do is to call `FAQ.resume()`. - - returns: - New `FAQ` object. - - throws: - `SessionBuilder.SessionBuilderError.NIL_ACCOUNT_NAME` if account name wasn't set to a non-nil value. - - seealso: - `FAQBuilder.FAQBuilderError` - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - public func build() throws -> FAQ { - guard let accountName = accountName else { - throw FAQBuilderError.NIL_ACCOUNT_NAME - } - - return FAQImpl.newInstanceWith(accountName: accountName) as FAQ - } - - /** - Error types that can be thrown by `FAQBuilder` `build()` method. - - seealso: - `FAQBuilder.build()` - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - public enum FAQBuilderError: Error { - - /** - Error that is thrown when trying to create faq object with `nil` account name. - - seealso: - `set(accountName:)` - - author: - Nikita Kaberov - - copyright: - 2019 Webim - */ - case NIL_ACCOUNT_NAME - - } - -} - diff --git a/ios/libs/Webim/WebimClientLibrary/WebimClientLibrary.h b/ios/libs/Webim/WebimClientLibrary/WebimClientLibrary.h deleted file mode 100755 index ea6bc77..0000000 --- a/ios/libs/Webim/WebimClientLibrary/WebimClientLibrary.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// WebimClientLibrary.h -// WebimClientLibrary -// -// Created by Sergey Maslov on 15.01.2018. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -#import - -//! Project version number for WebimClientLibrary. -FOUNDATION_EXPORT double WebimClientLibraryVersionNumber; - -//! Project version string for WebimClientLibrary. -FOUNDATION_EXPORT const unsigned char WebimClientLibraryVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - - diff --git a/ios/libs/Webim/WebimClientLibrary/WebimError.swift b/ios/libs/Webim/WebimClientLibrary/WebimError.swift deleted file mode 100755 index 13a4fe0..0000000 --- a/ios/libs/Webim/WebimClientLibrary/WebimError.swift +++ /dev/null @@ -1,144 +0,0 @@ -// -// WebimError.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 09.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Abstracts Webim service possible error responses. - - seealso: - `FatalErrorHandler` protocol. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol WebimError { - - /** - - returns: - Parsed type of the error. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getErrorType() -> FatalErrorType - - /** - - returns: - String representation of an error. Mostly useful if the error type is unknown. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getErrorString() -> String - -} - -// MARK: - -/** - Webim service error types. - - important: - Mind that most of this errors causes session to destroy. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum FatalErrorType { - - /** - Indicates that the account in Webim service has been disabled (e.g. for non-payment). The error is unrelated to the user’s actions. - Recommended response is to show the user an error message with a recommendation to try using the chat later. - - important: - Notice that the session will be destroyed if this error occured. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case ACCOUNT_BLOCKED - - /** - Indicates an expired authorization of a visitor. - The recommended response is to re-authorize it and to re-create session object. - - important: - Notice that the session will be destroyed if this error occured. - - seealso: - `Webim.SessionBuilder.set(visitorFieldsJSONstring:)` - `Webim.SessionBuilder.set(visitorFieldsJSONdata:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case PROVIDED_VISITOR_FIELDS_EXPIRED - - /** - Indicates the occurrence of an unknown error. - Recommended response is to send an automatic bug report and show to a user an error message with the recommendation to try using the chat later. - - important: - Notice that the session will be destroyed if this error occured. - - seealso: - `WebimError.getErrorString()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case UNKNOWN - - /** - Indicates that a visitor was banned by an operator and can't send messages to a chat anymore. - Occurs when a user tries to open the chat or write a message after that. - Recommended response is to show the user an error message with the recommendation to try using the chat later or explain to the user that it was blocked for some reason. - - important: - Notice that the session will be destroyed if this error occured. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case VISITOR_BANNED - - /** - Indicates a problem of your application authorization mechanism and is unrelated to the user’s actions. - Occurs when trying to authorize a visitor with a non-valid signature. - Recommended response is to send an automatic bug report and show the user an error message with the recommendation to try using the chat later. - - important: - Notice that the session will be destroyed if this error occured. - - seealso: - `Webim.SessionBuilder.set(visitorFieldsJSONstring:)` - `Webim.SessionBuilder.set(visitorFieldsJSONdata:)` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case WRONG_PROVIDED_VISITOR_HASH - -} diff --git a/ios/libs/Webim/WebimClientLibrary/WebimLogger.swift b/ios/libs/Webim/WebimClientLibrary/WebimLogger.swift deleted file mode 100755 index 1c2f570..0000000 --- a/ios/libs/Webim/WebimClientLibrary/WebimLogger.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// WebimLogger.swift -// Cosmos -// -// Created by Nikita Lazarev-Zubov on 08.12.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Protocol that provides methods for implementing custom WebimClientLibrary network requests logging. - It can be useful for debugging production releases if debug logs are not available. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol WebimLogger: class { - - /** - Method which is called after new WebimClientLibrary network request log entry came out. - - parameter entry: - New WebimClientLibrary network request log entry. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func log(entry: String) - -} diff --git a/ios/libs/Webim/WebimClientLibrary/WebimRemoteNotification.swift b/ios/libs/Webim/WebimClientLibrary/WebimRemoteNotification.swift deleted file mode 100755 index 68928f2..0000000 --- a/ios/libs/Webim/WebimClientLibrary/WebimRemoteNotification.swift +++ /dev/null @@ -1,176 +0,0 @@ -// -// WebimRemoteNotification.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 08.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - Abstracts a remote notifications from Webim service. - - seealso: - `Webim.parseRemoteNotification()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol WebimRemoteNotification { - - /** - - seealso: - `NotificationType` enum. - - returns: - Type of this remote notification. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getType() -> NotificationType - - /** - - seealso: - `NotificationEvent` enum. - - returns: - Event of this remote notification. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getEvent() -> NotificationEvent? - - /** - - returns: - Parameters of this remote notification. Each `NotificationType` has specific list of parameters. - - seealso: - `NotificationType` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getParameters() -> [String] - -} - -// MARK: - -/** - - seealso: - `WebimRemoteNotification.getType()` - `WebimRemoteNotification.getParameters()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum NotificationType { - - /** - This notification type indicated that contact information request is sent to a visitor. - Parameters: empty. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - case CONTACT_INFORMATION_REQUEST - - /** - This notification type indicated that an operator has connected to a dialogue. - Parameters: - * Operator's name. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case OPERATOR_ACCEPTED - - /** - This notification type indicated that an operator has sent a file. - Parameters: - * Operator's name; - * File name. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case OPERATOR_FILE - - /** - This notification type indicated that an operator has sent a text message. - Parameters: - * Operator's name; - * Message text. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case OPERATOR_MESSAGE - - /** - This notification type indicated that an operator has sent a widget message. - Parameters: empty. - - important: - This type can be received only if server supports this functionality. - - author: - Nikita Lazarev-Zubov - - copyright: - 2018 Webim - */ - case WIDGET -} - -/** - - seealso: - `WebimRemoteNotification.getEvent()` - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum NotificationEvent { - - /** - Means that a notification should be added by current remote notification. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case ADD - - /** - Means that a notification should be deleted by current remote notification. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case DELETE - -} diff --git a/ios/libs/Webim/WebimClientLibrary/WebimSession.swift b/ios/libs/Webim/WebimClientLibrary/WebimSession.swift deleted file mode 100755 index 1099274..0000000 --- a/ios/libs/Webim/WebimClientLibrary/WebimSession.swift +++ /dev/null @@ -1,160 +0,0 @@ -// -// WebimSession.swift -// WebimClientLibrary -// -// Created by Nikita Lazarev-Zubov on 02.08.17. -// Copyright © 2017 Webim. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -/** - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public protocol WebimSession: class { - - /** - Resumes session networking. - - important: - Session is created as paused. To start using it firstly you should call this method. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func resume() throws - - /** - Pauses session networking. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func pause() throws - - /** - Destroys session. After that any session methods are not available. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func destroy() throws - - /** - Destroys session, performing a cleanup.. After that any session methods are not available. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Kaberov - - copyright: - 2018 Webim - */ - func destroyWithClearVisitorData() throws - - /** - - returns: - A `MessageStream` object attached to this session. Each invocation of this method returns the same object. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func getStream() -> MessageStream - - /** - Changes location without creating a new session. - - parameter location: - New location name. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - seealso: - `FatalErrorHandler`. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func change(location: String) throws - - /** - This method allows to manually set device token after the session is created. - Example that shows how to change device token for the proper formatted one: - `let deviceToken = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()` - - parameter deviceToken: - Device token in hexadecimal format and without any spaces and service symbols. - - throws: - `AccessError.INVALID_THREAD` if the method was called not from the thread the WebimSession was created in. - `AccessError.INVALID_SESSION` if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - func set(deviceToken: String) throws - -} - -// MARK: - -/** - Error types that can be throwed by MessageStream methods. - - seealso: - `WebimSession` and `MessageStream` methods. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ -public enum AccessError: Error { - - /** - Error that is thrown if the method was called not from the thread the WebimSession was created in. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case INVALID_THREAD - - /** - Error that is thrown if WebimSession was destroyed. - - author: - Nikita Lazarev-Zubov - - copyright: - 2017 Webim - */ - case INVALID_SESSION -} diff --git a/node_modules/.bin/react-native b/node_modules/.bin/react-native new file mode 120000 index 0000000..7ec0ed3 --- /dev/null +++ b/node_modules/.bin/react-native @@ -0,0 +1 @@ +../../../node_modules/react-native/cli.js \ No newline at end of file diff --git a/package.json b/package.json index 6af4953..189962e 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,24 @@ { "name": "webim-react-native", - "version": "0.0.3", - "author": "ownikss", - "description": "webim implementation", - "rnpm": { - "android": { - "sourceDir": "./android" - }, - "ios": { - "sourceDir": "./ios" - } + "version": "0.1.0", + "author": "Nikita Sirotkin", + "license": "MIT", + "description": "RN Webim implementation", + "main": "js/index.ts", + "scripts": { + "prepare": "rm -rf js && tsc" + }, + "repository": { + "type": "git", + "url": "https://github.com/volga-volga/react-native-webim" + }, + "devDependencies": { + "@types/react": "*", + "@types/react-native": "*", + "typescript": "^3.8.3" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" } } diff --git a/react-native.config.js b/react-native.config.js new file mode 100644 index 0000000..2bbaec1 --- /dev/null +++ b/react-native.config.js @@ -0,0 +1,15 @@ +module.exports = { + dependencies: { + 'react-native-webim': { + platforms: { + ios: { + podspecPath: `${__dirname}/node_modules/react-native-webim/RNWebim.podspec`, + }, + android: { + packageImportPath: 'import ru.vvdev.webim.WebimPackage;', + packageInstance: 'new WebimPackage()' + }, + }, + }, + }, +}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..64f9ede --- /dev/null +++ b/src/index.ts @@ -0,0 +1,7 @@ +import RNWebim from './webim'; + +export * from './types'; +export * from './utils'; +export * from './webim'; + +export default RNWebim; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..11783cb --- /dev/null +++ b/src/types.ts @@ -0,0 +1,54 @@ +export type SessionBuilderParams = { + accountName: string; + location: string; + accountJSON?: string; + providedAuthorizationToken?: string; + appVersion?: string; + clearVisitorData?: boolean; + storeHistoryLocally?: boolean; + title?: string; + pushToken?: string; +}; + +export enum WebimEvents { + NEW_MESSAGE = 'newMessage', + REMOVE_MESSAGE = 'removeMessage', + EDIT_MESSAGE = 'changedMessage', + CLEAR_DIALOG = 'allMessagesRemoved', + TOKEN_UPDATED = 'tokenUpdated', + ERROR = 'error', +} + +export interface WebimAttachment { + contentType: string; + info: string; + name: string; + size: number; + url: string; +} + +export interface WebimMessage { + id: string; + avatar?: string; + time: number; + type: 'OPERATOR' | 'VISITOR' | 'INFO'; + text: string; + name: string; + status: 'SENT'; + read: boolean; + canEdit: boolean; + attachment?: WebimAttachment; +} + +export type NativeError = { + message: string; +}; + +export type NewMessageListener = (data: { msg: WebimMessage }) => void; +export type UpdateMessageListener = (data: { from: WebimMessage, to: WebimMessage }) => void; +export type RemoveMessageListener = (data: { msg: WebimMessage }) => void; +export type DialogClearedListener = () => void; +export type TokenUpdatedListener = (token: string) => void; +export type ErrorListener = (error: NativeError) => void; + +export type WebimEventListener = NewMessageListener | UpdateMessageListener | RemoveMessageListener | DialogClearedListener | TokenUpdatedListener | ErrorListener; diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..9ca6a04 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,17 @@ +import {NativeError} from './types'; + +export function parseNativeResponse(response?: T): T | null { + return response || null; +} + +export function processError(error: NativeError) { + return new Error(error.message); +} + +export class WebimSubscription { + readonly remove: () => void; + + constructor(remove: () => void) { + this.remove = remove; + } +} diff --git a/src/webim.ts b/src/webim.ts new file mode 100644 index 0000000..473d97f --- /dev/null +++ b/src/webim.ts @@ -0,0 +1,163 @@ +import {NativeModules, NativeEventEmitter} from 'react-native'; +import { + DialogClearedListener, ErrorListener, + NativeError, NewMessageListener, RemoveMessageListener, + SessionBuilderParams, TokenUpdatedListener, UpdateMessageListener, WebimEventListener, + WebimEvents, + WebimMessage, +} from './types'; +import {WebimSubscription, processError} from './utils'; + +const {RNWebim: WebimNative} = NativeModules; +const emitter = new NativeEventEmitter(NativeModules.RNWebim); + +const DEFAULT_MESSAGES_LIMIT = 100; + +export class RNWebim { + static resumeSession(params: SessionBuilderParams): Promise { + return new Promise((resolve, reject) => { + WebimNative.resumeSession( + params, + (error: NativeError) => reject(processError(error)), + () => resolve(), + ); + }); + } + + static destroySession(clearData: boolean = false) { + return new Promise((resolve, reject) => { + WebimNative.destroySession( + clearData, + (error: NativeError) => reject(processError(error)), + () => resolve(), + ); + }); + } + + static getLastMessages( + limit: number = DEFAULT_MESSAGES_LIMIT, + ): Promise<{ messages: WebimMessage[] }> { + return new Promise((resolve, reject) => { + WebimNative.getLastMessages( + limit, + (error: NativeError) => reject(processError(error)), + (messages: { messages: WebimMessage[] }) => resolve(messages), + ); + }); + } + + static getNextMessages( + limit: number = DEFAULT_MESSAGES_LIMIT, + ): Promise<{ messages: WebimMessage[] }> { + return new Promise((resolve, reject) => { + WebimNative.getNextMessages( + limit, + (error: NativeError) => reject(processError(error)), + (messages: { messages: WebimMessage[] }) => resolve(messages), + ); + }); + } + + static getAllMessages(): Promise<{ messages: WebimMessage[] }> { + return new Promise((resolve, reject) => { + WebimNative.getAllMessages( + (error: NativeError) => reject(processError(error)), + (messages: { messages: WebimMessage[] }) => resolve(messages), + ); + }); + } + + static send(message: string) { + return new Promise((resolve, reject) => + WebimNative.send( + message, + (error: NativeError) => reject(processError(error)), + (id: string) => resolve(id), + ), + ); + } + + static rateOperator(rate: number) { + return new Promise((resolve, reject) => { + WebimNative.rateOperator( + rate, + (error: NativeError) => reject(processError(error)), + () => resolve(), + ); + }); + } + + static tryAttachFile() { + return new Promise((resolve, reject) => { + WebimNative.tryAttachFile( + (error: NativeError) => reject(processError(error)), + async (file: { + uri: string; + name: string; + mime: string; + extension: string; + }) => { + const {uri, name, mime, extension} = file; + try { + await RNWebim.sendFile(uri, name, mime, extension); + resolve(); + } catch (e) { + reject(processError(e)); + } + }, + ); + }); + } + + static sendFile(uri: string, name: string, mime: string, extension: string) { + return new Promise((resolve, reject) => + WebimNative.sendFile(uri, name, mime, extension, reject, resolve), + ); + } + + public static addNewMessageListener(listener: NewMessageListener): WebimSubscription { + emitter.addListener(WebimEvents.NEW_MESSAGE, listener); + return new WebimSubscription(() => RNWebim.removeListener(WebimEvents.NEW_MESSAGE, listener)); + } + + public static addRemoveMessageListener(listener: RemoveMessageListener): WebimSubscription { + emitter.addListener(WebimEvents.REMOVE_MESSAGE, listener); + return new WebimSubscription(() => RNWebim.removeListener(WebimEvents.REMOVE_MESSAGE, listener)); + } + + public static addEditMessageListener(listener: UpdateMessageListener): WebimSubscription { + emitter.addListener(WebimEvents.EDIT_MESSAGE, listener); + return new WebimSubscription(() => RNWebim.removeListener(WebimEvents.EDIT_MESSAGE, listener)); + } + + public static addDialogClearedListener(listener: DialogClearedListener): WebimSubscription { + emitter.addListener(WebimEvents.CLEAR_DIALOG, listener); + return new WebimSubscription(() => RNWebim.removeListener(WebimEvents.CLEAR_DIALOG, listener)); + } + + public static addTokenUpdatedListener(listener: TokenUpdatedListener): WebimSubscription { + emitter.addListener(WebimEvents.TOKEN_UPDATED, listener); + return new WebimSubscription(() => RNWebim.removeListener(WebimEvents.TOKEN_UPDATED, listener)); + } + + public static addErrorListener(listener: ErrorListener): WebimSubscription { + emitter.addListener(WebimEvents.ERROR, listener); + return new WebimSubscription(() => RNWebim.removeListener(WebimEvents.ERROR, listener)); + } + + public static addListener(event: WebimEvents, listener: WebimEventListener): WebimSubscription { + emitter.addListener(event, listener); + return new WebimSubscription(() => RNWebim.removeListener(event, listener)); + } + + public static removeListener(event: WebimEvents, listener: WebimEventListener): void { + emitter.removeListener(event, listener); + } + + static removeAllListeners(event: WebimEvents) { + emitter.removeAllListeners(event); + } +} + +export default RNWebim; + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f49a4a7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "declaration": true, + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "jsx": "react", + "lib": ["dom", "es5", "es6", "scripthost"], + "target": "es5", + "rootDir": "./src", + "outDir": "js", + "sourceMap": true, + "skipLibCheck": true + }, + "exclude": ["node_modules"] +}