import Message from './message'
import Visitor from './visitor'
import Connection from "./connection";
import axios from "axios";
// const API_URL = process.env.API_URL + ':' + process.env.API_PORT + '/' + process.env.API_PATH;
const API_URL = 'https://beta.chatix.io:5022/v1';
/**
* Chat class represents conversation between visitor and managers. This is main private class for all actions inside
* library.
* @property {Manager[]} managers people who are connected to current conversation in dashboard
* @property {Visitor} visitor user who visits current page
* @property {Connection} connection class provides protocol implementation
*/
class Chat {
/**
* Chat constructor
* @param {string} websiteId Website ID from Chatix dashboard
* @param {string} visitrorId Visitor ID can be passed from backend. If null, SDK will try to find it in
* local storage and request new if it wasn't found in storage.
*/
constructor(websiteId, visitrorId = null) {
this.websiteId = websiteId;
this.messages = [];
this.managers = [];
this.onConnected = function(){};
this.onDisconnected = function(){};
this.onManagerConnectedToConversation = function(){};
this.onManagerDisconnectedFromConversation = function(){};
this.onConversationMessageReceived = function(){};
this.onConversationMessageUpdated = function(){};
this.onConversationMessageDeleted = function(){};
this.onChatroomCreated = function(){};
this.onChatroomUpdated = function(){};
this.onChatroomDeleted = function(){};
this.onChatroomRestored = function(){};
this.onChatroomMessageReceived = function(){};
this.onChatroomMessageUpdated = function(){};
this.onChatroomMessageDeleted = function(){};
this.onMemberConnectedToChatroom = function(){};
this.onManagerConnectedToChatroom = function(){};
this.onVisitorDisconnectedFromChatroom = function(){};
this.onManagerDisconnectedFromChatroom = function(){};
this.onScreencastPermissionRequested = function(){};
this.onManagerConnectedToScreencast = function(){};
this.onManagerDisconnectedFromScreencast = function(){};
this.connection = new Connection();
this.connection.onConnected = this.onConnected;
this.connection.onDisconnected = this.onDisconnected;
this.connection.onApplyErrorMessage = (message, method) => {
console.error("Chatix error occured in method " + method + ", desciption: " + message);
};
this.connection.onApplyDialogMessage = this._onConversationMessageReceivedCallback;
this.connection.onConnectManagerToConversation = this.onManagerConnectedCallback;
this.connection.onDisconnectManagerFromConversation = this.onManagerDisconnectedFromConversationCallback;
this.connection.onScreencastRequested = this.onScreencastPermissionRequestedCallback;
this.connection.onDisconnectManagerFromScreencast = this.onManagerDisconnectedFromScreencastCallback;
this.connection.onApplyChatroomMessage = this.onChatroomMessageReceivedCallback;
this.connection.onConnectManagerToChatroom = this.onManagerConnectedToChatroomCallback;
this.connection.onDisonnectManagerFromChatroom = this.onManagerDisconnectedFromChatroomCallback;
this.connection.onConnectVisitorToChatroom = this.onMemberConnectedToChatroomCallback;
this.connection.onDisconnectVisitorFromChatroom = this.onMemberDisconnectedFromChatroomCallback;
this.connection.onCreateChatroom = this.onChatroomCreatedCallback;
this.connection.onUpdateChatroom = this.onChatroomUpdatedCallback;
this.connection.onDeleteChatroom = this.onChatroomDeletedCallback;
this.connection.onRestoreChatroom = this.onChatroomRestoredCallback;
this.connection.onUpdateConversationMessage = this.onConversationMesssageUpdatedCallback;
this.connection.onDeleteConversationMessage = this.onConversationMessageDeletedCallback;
this.connection.onScreenDataRequested = this.onScreenDataRequestedCallback;
this.connection.onManagerSentScreenEvent = this.onManagerSentScreenEventCallback;
this.connection.onInvalidVisitorIdConnected = () => {console.error("Invalid Visitor Id Connection")};
this.visitor = new Visitor();
this.visitor.setUuid(visitrorId);
}
/**
* Starts SignalR connection to server
*/
async startConnection() {
if (this.visitor.getUuid === null) {
this.visitor.setUuid(await this.connection.getNewVisitorId(this.websiteId));
}
try {
await this.connection.start(this.websiteId, this.visitor.getUuid());
let visitor = await this.connection.getVisitorInfo();
this.visitor = visitor;
this.onConnected();
return true;
} catch(e) {
console.error(e);
return false;
}
}
// applyVisitor() {
// if (localStorage.getItem('chatix__visitorId') != null) {
// localStorage.removeItem('chatix__visitorId')
// }
// if (!this.visitor) {
// let storageValue = localStorage.getItem('chatix__visitorId_v1');
// if (storageValue) {
// this.visitor = new Visitor(this);
// this.visitor.uuid = storageValue;
// return Promise.resolve();
// } else {
// return axios.get(API_URL + '/visitor/get-id?websiteId=' + this.websiteId)
// .then((res) => {
// if (localStorage.getItem('chatix__visitorId_v0')) {
// localStorage.removeItem('chatix__visitorId_v0')
// }
// localStorage.setItem('chatix__visitorId_v1', res.data);
// this.visitor = new Visitor();
// this.visitor.uuid = res.data;
// }).catch(function(data){
// console.log(data.response);
// });
// }
// } else {
// return Promise.resolve();
// }
// }
/**
* Stops network connection
*/
async stopConnection() {
try {
await this.connection.stop();
return true;
} catch (e) {
return false;
}
}
async getWebchat() {
return this.connection.getWebChatInfo();
}
/**
* Getter for current conversation visitor
*
* @return {Visitor|null}
*/
getVisitor() {
return this.visitor;
}
/**
* Setter for current conversation visitor
* @param {Visitor} visitor
*/
async setVisitor(visitor) {
let responseVisitor = await this.connection.sendVisitorInfo(visitor);
this.visitor = responseVisitor;
}
/**
* Getter for all website managers
*
* @return {Manager[]|*}
*/
async getManagers() {
return await this.connection.getWebChatManagers();
}
/**
* Getter for current conversation managers
*
* @return {Manager[]|*}
*/
async getConnectedManagers() {
return await this.connection.getConnectedToConversationManagers();
}
async sendBroadcastData(innerHTML, broadcastData) {
await this.connection.sendBroadcastData(innerHTML, broadcastData);
}
async sendBroadcastEvent(broadcastEvent) {
await this.connection.sendBroadcastEvent(broadcastEvent);
}
/**
* Sends data to server about user navigation
* @param {string} url Current page URL
* @param {string} title Current page title
*/
async sendPage(url, title) {
await this.connection.sendPage(url, title);
}
/**
* Sends current visitor typing
* @param {string} text current visitor input
*/
async visitorTypes(text) {
await this.connection.sendVisitorTypedText(text);
}
/**
* Sends request for current conversation messages. Messages returns ordered by sent time ascending.
*
* @param {string|null} lastKnownMessageId ID of the last message in dialog you have rendered.
* @param {number} count Number of messages to return.
* @return {Promise.<Message[]>}
*/
async getConversationHistory(lastKnownMessageId = null, count = 50) {
return this.connection.getConversationHistory(lastKnownMessageId, count);
}
/**
* Gets information about manager from API
* @param {string} managerId ID of manager you are interested in
*/
async getManagerInfo(managerId) {
return await this.connection.getManagerInfo(managerId);
}
/**
* Sends text message to current conversation
*
* @param {text} text new message text
*/
async sendTextMessage(text) {
let message = Message.buildText(text);
return await this.connection.sendMessage(message);
}
/**
* @private
* Uploads conversation file to Chatix storage
* @param {File} file File to send.
* @see https://developer.mozilla.org/en-US/docs/Web/API/File to get more details
*/
async _uploadConversationFile(file) {
const data = new FormData();
data.append('formFile', file);
let response = await axios.post(API_URL + '/file/save?visitorId=' + this.visitor.getUuid() + '&websiteId=' + this.websiteId, data);
if (file.type == 'image/jpeg' || file.type == 'image/png') {
let message = Message.buildImg(response.data);
return await this.connection.sendMessage(message);
}
else {
let message = Message.buildFile(response.data);
return await this.connection.sendMessage(message);
}
}
/**
* Sends file or image message to Chatix
* @param {File|File[]} files File to send or array of files
* @see https://developer.mozilla.org/en-US/docs/Web/API/File to get more details
*/
async sendFileMessage(files) {
let response = [];
if (files.length) {
for (let file of files) {
response.push(await this._uploadConversationFile(file));
}
}
else {
response.push(await this._uploadConversationFile(files));
}
return response;
}
/**
* @private
* Uploads chatroom file to Chatix storage
* @param {File} file File to send.
* @see https://developer.mozilla.org/en-US/docs/Web/API/File to get more details
*/
async _uploadChatroomFile(file, chatroomId) {
const data = new FormData();
data.append('formFile', file);
let response = await axios.post(API_URL + '/file/save?visitorId=' + this.visitor.getUuid() + '&websiteId=' + this.websiteId + '&chatroomId=' + chatroomId, data);
if (file.type == 'image/jpeg' || file.type == 'image/png') {
let message = Message.buildImg(response.data);
return await this.connection.sendChatroomMessage(message);
}
else {
let message = Message.buildFile(response.data);
return await this.connection.sendChatroomMessage(message);
}
}
async sendChatroomTextMessage(messageText, chatroomId) {
return await this.connection.sendChatroomTextMessage(messageText, chatroomId);
}
/**
* Sends files or images to chatroom
* @param {File|File[]} files File or files to send
* @param {string} chatroomId Chatroom ID where to send messages
*/
async sendChatroomFileMessage(files, chatroomId) {
let response = [];
if (files.length) {
for (let file of files) {
response.push(await this._uploadChatroomFile(file, chatroomId));
}
}
else {
response.push(await this._uploadChatroomFile(files, chatroomId));
}
return response;
}
/**
* Sorts messages by sent_at ascending
* @param {Message[]} messages Messages array to sort
*/
sortMessages(messages) {
return messages.sort(function (a, b) {
if (a.sent_at < b.sent_at) {
return -1;
}
else if (a.sent_at > b.sent_at) {
return 1;
}
else {
return 0;
}
});
}
async getChatroom(chatroomId) {
return await this.connection.getChatroom(chatroomId);
}
async getAllChatrooms(page, perPage) {
return await this.connection.getAllChatrooms(page, perPage);
}
async getMyChatrooms(page, perPage) {
return await this.connection.getMyChatrooms(page, perPage);
}
async connectToChatroom(chatroomId) {
return await this.connection.connectToChatroom(chatroomId);
}
async disconnectFromChatroom(chatroomId) {
return await this.connection.disconnectFromChatroom(chatroomId);
}
async getChatroomMembers(chatroomId, page = 1, perPage = 100) {
return await this.connection.getChatroomMembers(chatroomId, perPage, page);
}
async getChatroomHistory(chatroomId, lastKnownMessageId = null, count = 50) {
return await this.connection.getChatroomHistory(chatroomId, lastKnownMessageId, count);
}
async sendScreencastPermission(flag) {
return await this.connection.allowScreenCast(flag);
}
async interruptScreencast() {
return await this.connection.interruptScreenCast();
}
/**
* Receiving new message in conversation
*
* @param {Message} message new message
* @todo обновить на получение одного сообщения
*/
_onConversationMessageReceivedCallback(message) {
var allData = [];
allData = allData.concat(this.messages, message);
var sortMess = this.sortMessages(allData);
this.messages = sortMess;
this.onConversationMessageReceived(message)
}
/**
* @todo Зачем?
* @param {} chatInfo
*/
receivedChatInfo(chatInfo) {
this.chatInfo = chatInfo;
this.onChatInfo(chatInfo);
}
onConnectedCallback(visitor) {
this.onConnected(visitor);
}
/**
*
* @param {Manager} manager new connected manager
*/
_onManagerConnectedCallback(manager) {
this.managers.push(manager);
this.onManagerConnectedToConversation(manager);
}
_onScreencastPermissionRequestedCallback() {
this.onScreencastPermissionRequested();
}
_onManagerDisconnectedFromScreencastCallback(manager) {
this.onManagerDisconnectedFromScreencast(manager);
}
_onManagerDisconnectedFromConversationCallback(manager) {
this.onManagerDisconnectedFromConversation(manager);
}
_onChatroomMessageReceivedCallback(message, chatroomId) {
this.onChatroomMessageReceived(message, chatroomId)
}
_onManagerConnectedToChatroomCallback(manager, chatroomId) {
this.onManagerConnectedToChatroom(manager, chatroomId);
}
_onMemberConnectedToChatroomCallback(visitor, chatroomId) {
this.onMemberConnectedToChatroom(visitor, chatroomId);
}
_onManagerDisconnectedFromChatroomCallback(manager, chatroomId) {
this.onManagerDisconnectedFromChatroom(manager, chatroomId);
}
_onMemberDisconnectedFromChatroomCallback(visitor, chatroomId) {
this.onMemberDisconnectedFromChatroom(visitor, chatroomId)
}
_onChatroomCreatedCallback(chatroom) {
this.onChatroomCreated(chatroom);
}
_onChatroomUpdatedCallback(chatroom) {
this.onChatroomUpdated(chatroom);
}
_onChatroomDeletedCallback(chatroomId) {
this.onChatroomDeleted(chatroomId)
}
_onChatroomRestoredCallback(chatroom) {
this.onChatroomRestored(chatroom);
}
_onConversationMesssageUpdatedCallback(message) {
let messageIndex = this.messages.find(mess => mess.uuid === message.uuid);
messageIndex = this.messages.indexOf(messageIndex);
if (this.messages[messageIndex] !== undefined) {
this.messages[messageIndex] = message;
}
this.onConversationMessageUpdated(message);
}
_onConversationMessageDeletedCallback(messageId) {
let messageIndex = this.messages.find(mess => mess.uuid === messageId);
messageIndex = this.messages.indexOf(messageIndex);
if (this.messages[messageIndex] !== undefined) {
delete this.messages[messageIndex];
}
this.onConversationMessageDeleted(messageId)
}
/**
* @todo перенести логику отправки данных экрана в отдельный компонент
*/
_onScreenDataRequestedCallback(){
}
/**
* @todo перенести логику отрисовки ивентов в отдельный компонент
*/
_onManagerSentScreenEventCallback(){
}
}
export default Chat;