ComunicWeb/assets/js/components/conversations/chatWindows.js

1179 lines
30 KiB
JavaScript
Raw Normal View History

/**
* Conversation chat window functions
*
* @author Pierre HUBERT
*/
2020-04-02 17:13:10 +00:00
const ConvChatWindow = {
2017-06-18 07:15:50 +00:00
2017-06-18 09:32:31 +00:00
/**
* @var {Object} __conversationsCache Chat windows cache
*/
__conversationsCache: {},
2017-06-18 07:15:50 +00:00
/**
* Open a new conversation window
*
2017-06-18 09:14:26 +00:00
* @param {Integer} conversationID The ID of the window to open
2017-06-18 07:15:50 +00:00
* @return {Boolean} True for a success
*/
openConversation: function(conversationID){
//Log action
ComunicWeb.debug.logMessage("Opening conversation " + conversationID);
//Create a conversation window
var conversationWindow = this.create({
2018-03-25 07:43:39 +00:00
target: byId(ComunicWeb.components.conversations.manager.__conversationsContainerID),
2017-06-18 09:14:26 +00:00
conversationID: conversationID,
2017-06-18 07:15:50 +00:00
});
2017-06-18 09:14:26 +00:00
//Load the conversation
this.load(conversationID, conversationWindow);
//Success
return true;
},
/**
* Create a new chat window
*
* @param {Object} infos Informations required for the new chat window
* @info {HTMLElement} target The target of the new chat window
* @info {Integer} conversationID The ID of the target conversation
* @return {Object} Informations about the new chat window
*/
create: function(infos){
//Log action
ComunicWeb.debug.logMessage("Create a new chat window");
//First, create the generic conversation window
var infosBox = ComunicWeb.components.conversations.windows.create(infos.target.children[0]);
//Save conversation ID
infosBox.conversationID = infos.conversationID;
//Change box root class name
infosBox.rootElem.className += " chat-window direct-chat direct-chat-primary";
//Adapt close button behaviour
infosBox.closeFunction = function(){
//Remove root element
infosBox.rootElem.remove();
//Remove the conversation from opened ones
ComunicWeb.components.conversations.cachingOpened.remove(infosBox.conversationID);
//Unload conversation
ComunicWeb.components.conversations.chatWindows.unload(infosBox.conversationID);
}
infosBox.closeButton.onclick = infosBox.closeFunction;
//Debug
2018-03-25 07:43:39 +00:00
//Create messages container
infosBox.messagesArea = createElem2({
appendTo: infosBox.boxBody,
type: "div",
class: "direct-chat-messages",
2017-06-25 17:10:26 +00:00
innerHTML: "",
});
//Add button to get conversation members
infosBox.membersButton = createElem2({
type: "button",
insertBefore: infosBox.closeButton,
elemType: "button",
class: "btn btn-box-tool",
title: "Conversation members"
});
infosBox.membersButton.setAttribute("data-toggle", "tooltip");
infosBox.membersButton.setAttribute("data-widget", "chat-pane-toggle");
//Add button icon
var buttonIcon = createElem("i", infosBox.membersButton);
buttonIcon.className = "fa fa-users";
//Add conversation members pane
var membersPane = createElem("div", infosBox.boxBody);
membersPane.className = "direct-chat-contacts";
//Add conversation members list
infosBox.membersList = createElem("ul", membersPane);
infosBox.membersList.className = "contacts-list";
//Add send a message form
this.addMessageform(infosBox);
//Return informations about the chat window
return infosBox;
},
/**
* Add a message form to the chat windows
*
* @param {Object} infosBox Informations about the chat box
* @return {Boolean} True for a success
*/
addMessageform: function(infosBox){
2018-03-25 07:43:39 +00:00
//Create form container
var conversationFormContainer = createElem2({
appendTo: infosBox.boxFooter,
2017-06-21 16:29:14 +00:00
type: "form",
class: "create-message-form"
});
2017-06-21 16:29:14 +00:00
//Create input group
var inputGroup = createElem2({
2018-03-25 07:43:39 +00:00
appendTo: conversationFormContainer,
type: "div",
class: "input-group"
});
//Create text input (for message)
var inputText = createElem2({
appendTo: inputGroup,
2017-06-21 16:29:14 +00:00
type: "textarea",
class: "form-control",
placeholder: "New message...",
});
inputText.maxLength = 200;
2017-06-21 16:29:14 +00:00
//Enable textarea 2.0 on the message
var textarea2 = new ComunicWeb.components.textarea();
textarea2.init({
element: inputText,
minHeight: "34px",
autosize: true,
});
//Create image input (for optionnal image)
var inputImage = createElem2({
type: "input",
elemType: "file",
});
//Create button group
var buttonGroup = createElem2({
appendTo: inputGroup,
type: "span",
class: "input-group-btn",
});
//Add emojie button
var emojiButton = createElem2({
appendTo: buttonGroup,
type: "button",
elemType: "button",
class: "btn btn-flat btn-add-emoji",
});
//Add image icon
createElem2({
type: "i",
appendTo: emojiButton,
class: "fa fa-smile-o"
});
//Make emojie button lives
ComunicWeb.components.emoji.picker.addPicker(inputText, emojiButton, function(){
//Make the emojie picker visible
wdtEmojiBundle.popup.style.top = (abs_height_bottom_screen()-357)+"px";
//Make the smile button visible
var currLeft = Number(wdtEmojiBundle.popup.style.left.replace("px", ""));
var potentialLeft = currLeft - 20;
if(potentialLeft > 0)
wdtEmojiBundle.popup.style.left = potentialLeft + "px";
});
2017-06-21 16:29:14 +00:00
//Add image button
var imageButton = createElem2({
appendTo: buttonGroup,
type: "button",
elemType: "button",
class: "btn btn-flat btn-add-image",
});
imageButton.onclick = function(){
//Call file selector
inputImage.click();
};
//Add image icon
createElem2({
type: "i",
appendTo: imageButton,
class: "fa fa-image"
});
//Add send button
var sendButton = createElem2({
appendTo: buttonGroup,
2017-06-23 15:25:29 +00:00
type: "button",
class: "btn btn-primary btn-flat",
elemType: "submit",
2017-06-21 16:29:14 +00:00
});
2017-06-23 15:25:29 +00:00
//Add send icon
createElem2({
appendTo: sendButton,
type: "i",
class: "fa fa-send-o",
});
2017-06-21 16:29:14 +00:00
//Prevent textarea from adding a new line when pressing enter
$(inputText).keypress(function(event){
if(event.keyCode == 13){
event.preventDefault();
sendButton.click();
}
});
2017-06-21 16:29:14 +00:00
//Add required elements to infosBox
infosBox.sendMessageForm = {
2018-03-25 07:43:39 +00:00
formRoot: conversationFormContainer,
2017-06-21 16:29:14 +00:00
sendButton: sendButton,
inputText: inputText,
textarea2: textarea2,
inputImage: inputImage,
};
//Success
return true;
},
2017-06-18 09:14:26 +00:00
/**
* Load (or reload) a conversation
*
* @param {Integer} conversationID The ID of the conversation to load
* @param {Object} conversationWindow Informations about the conversation window
* @return {Boolean} True for a success
*/
2021-03-06 11:04:01 +00:00
load: async function(conversationID, conversationWindow) {
2021-03-06 11:04:01 +00:00
try {
2021-03-06 11:04:01 +00:00
//Change conversation window name (loading state)
this.changeName("Loading", conversationWindow);
2017-06-18 07:15:50 +00:00
2021-03-06 11:04:01 +00:00
/** @type {Conversation} */
const conv = await new Promise((res, rej) => {
ConversationsInterface.getInfosOne(conversationID, (info) => {
if (info.error)
rej(info)
else
res(info)
});
})
2017-06-18 07:15:50 +00:00
2021-03-06 11:04:01 +00:00
const users = await getUsers(conv.members.map(m => m.user_id));
2017-06-18 07:15:50 +00:00
2021-03-06 11:04:01 +00:00
// Create conversation informations root object
var conversationInfos = {
box: conversationWindow,
membersInfos: users,
infos: conv
};
2017-06-18 07:15:50 +00:00
2021-03-06 11:04:01 +00:00
// Save conversation informations in the cache
this.__conversationsCache["conversation-"+conversationID] = conversationInfos;
2017-06-18 07:15:50 +00:00
2021-03-06 11:04:01 +00:00
//Change the name of the conversation
this.changeName(await getConvName(conv), conversationWindow);
2017-06-18 07:15:50 +00:00
2021-03-06 11:04:01 +00:00
// Update conversation members informations
this.updateMembersList(conversationInfos);
2017-06-18 07:15:50 +00:00
2021-03-06 11:04:01 +00:00
// Display conversation settings pane
this.showConversationSettings(conversationInfos);
2021-03-06 11:04:01 +00:00
// Register the conversation in the service
ConvService.registerConversation(conversationID);
2017-06-21 16:29:14 +00:00
2021-03-06 11:04:01 +00:00
// Make send a message button lives
conversationInfos.box.sendMessageForm.formRoot.onsubmit = (e) => {
e.preventDefault();
//Submit new message
this.submitMessageForm(conversationInfos);
2017-06-21 16:29:14 +00:00
2021-03-06 11:04:01 +00:00
};
2021-03-06 11:04:01 +00:00
//Add call button (if possible)
this.showCallButton(conversationInfos);
2017-06-18 07:15:50 +00:00
2021-03-06 11:04:01 +00:00
}
catch(e) {
console.error(e);
notify(tr("Failed to load conversation!"), "danger");
}
2017-06-18 07:15:50 +00:00
},
2017-06-18 09:32:31 +00:00
/**
* Unload a chat window
*
* @param {Integer} conversationID The ID of the conversation to unload
* @param {Boolean} keepInfos Keep informations about the chat window
* @return {Boolean} True for a success
*/
unload: function(conversationID, keepInfos){
if(!this.__conversationsCache["conversation-"+conversationID]){
ComunicWeb.debug.logMessage("Couldn't unload conversation: " + conversationID +". It seems not to be loaded...");
return false;
}
//Log action
ComunicWeb.debug.logMessage("Unloading a conversation: " + conversationID);
//Get informations
var conversationInfos = this.__conversationsCache["conversation-"+conversationID];
//Empty messages area
emptyElem(conversationInfos.box.messagesArea);
2017-06-25 17:10:26 +00:00
conversationInfos.box.messagesArea.innerHTML = "";
//Un-register conversation
ComunicWeb.components.conversations.service.unregisterConversation(conversationID);
2017-06-18 09:32:31 +00:00
//Remove informations if required
if(!keepInfos){
delete this.__conversationsCache["conversation-"+conversationID];
}
//Success
return true;
},
/**
* Unload all chat windows
*
* @return {Boolean} True for a success
*/
unloadAll: function(){
//Clear conversation object
clearObject(this.__conversationsCache);
//Success
return true;
},
/**
* Change the name of the converation at the top of the windows
*
* @param {String} newName The new name for the conversation window
* @param {Ojbect} info Information about the conversation window
* @return {Boolean} True for a success
*/
changeName: function(newName, info){
2018-08-16 10:37:03 +00:00
//Reduce new name
if(newName.length > 18)
newName = newName.slice(0, 17) + "...";
//Empty name field
emptyElem(info.boxTitle);
//Create conversation icon
createElem2({
type: "i",
appendTo: info.boxTitle,
class: "fa fa-comments",
ondblclick: () => {
openConversation(info.conversationID, true);
info.closeFunction();
}
});
//Add conversation title
var conversationTitle = createElem("span", info.boxTitle);
conversationTitle.innerHTML = " " + newName;
2017-06-17 08:09:37 +00:00
//Success
return true;
},
/**
* Update conversation members list
*
* @param {Object} conversation Informations about the conversation
* @return {Boolean} True for a success
*/
updateMembersList: function(conversation){
//First, make sure conversation members pane is empty
emptyElem(conversation.box.membersList);
//Then process each user
2021-03-06 11:04:01 +00:00
for(let member of conversation.infos.members) {
let user = conversation.membersInfos.get(member.user_id);
if(!user)
continue;
//Display user informations
var userLi = createElem("li", conversation.box.membersList);
var userLink = createElem("a", userLi);
//Add user account image
var userImage = createElem("img", userLink);
userImage.className = "contacts-list-img";
userImage.src = user.image;
//Add member informations
var memberInfosList = createElem2({
type: "div",
appendTo: userLink,
class: "contacts-list-info",
});
2017-06-17 08:09:37 +00:00
2021-03-06 11:04:01 +00:00
//Add user name
var memberName = createElem2({
type: "span",
appendTo: memberInfosList,
class: "contacts-list-name",
innerHTML: user.fullName,
});
2017-06-17 08:09:37 +00:00
2021-03-06 11:04:01 +00:00
//Add member status
createElem2({
type: "span",
appendTo: memberInfosList,
class: "contacts-list-msg",
innerHTML: member.is_admin ? tr("Admin") : tr("Member")
});
2017-06-17 08:09:37 +00:00
}
//Enable slimscrooll
$(conversation.box.membersList).slimscroll({
height: "100%",
color: "#FFFFFF"
});
//Success
return true;
2017-06-17 09:20:54 +00:00
},
/**
* Show conversation settings (button + pane)
*
2017-06-17 15:24:45 +00:00
* @param {Object} conversation Informations about the conversation
2017-06-17 09:20:54 +00:00
* @return {Boolean} True for a success
*/
2017-06-17 15:24:45 +00:00
showConversationSettings: function(conversation){
2017-06-17 09:40:57 +00:00
2017-06-18 09:14:26 +00:00
//First, check conversation settings button and pane don't exists yet
if(conversation.box.settingsButton){
if(conversation.box.settingsButton.remove){
conversation.box.settingsButton.remove();
}
}
if(conversation.box.settingsPane){
if(conversation.box.settingsPane.remove){
conversation.box.settingsPane.remove();
}
}
2017-06-17 09:20:54 +00:00
//Create and display conversation settings button wheel
2017-06-17 15:24:45 +00:00
conversation.box.settingsButton = createElem2({
2017-06-17 09:20:54 +00:00
type: "button",
2017-06-17 15:24:45 +00:00
insertBefore: conversation.box.membersButton,
2017-06-17 09:20:54 +00:00
class: "btn btn-box-tool",
type: "button"
});
//Add button icon
createElem2({
type: "i",
2017-06-17 15:24:45 +00:00
appendTo: conversation.box.settingsButton,
2017-06-17 09:20:54 +00:00
class: "fa fa-gear",
});
//Create settings pane
var settingsPane = createElem2({
type: "div",
2017-06-17 15:24:45 +00:00
appendTo: conversation.box.boxBody,
2017-06-17 09:20:54 +00:00
class: "conversation-settings-pane",
});
2017-06-18 09:14:26 +00:00
conversation.box.settingsPane = settingsPane;
2017-06-17 09:20:54 +00:00
//Make the settings button lives
2017-06-17 15:24:45 +00:00
conversation.box.settingsButton.onclick = function(){
2017-06-17 09:40:57 +00:00
//Update settings pane classname
2017-06-17 09:20:54 +00:00
if(settingsPane.className.includes(" open"))
settingsPane.className = settingsPane.className.replace(" open", ""); //Close the pane
else
settingsPane.className += " open"; //Open the pane
};
2017-06-17 09:40:57 +00:00
//Create the conversation form
2020-04-25 16:20:29 +00:00
const settingsForm = ConversationsUtils.createConversationForm(settingsPane);
2017-06-17 09:40:57 +00:00
//Update form informations
2017-06-17 15:24:45 +00:00
settingsForm.createButton.innerHTML = "Update settings";
2017-06-17 09:40:57 +00:00
//Update conversation name
2017-06-17 15:24:45 +00:00
if(conversation.infos.name)
settingsForm.conversationNameInput.value = conversation.infos.name;
2020-04-25 16:39:01 +00:00
//Update conversation members
2021-03-06 11:04:01 +00:00
ComunicWeb.components.userSelect.pushEntries(settingsForm.usersElement, conversation.infos.members.map(m => m.user_id));
2020-04-25 16:24:47 +00:00
2020-04-25 16:39:01 +00:00
// Update checkbox to allow or not everyone to add members
$(settingsForm.allowEveryoneToAddMembers).iCheck(conversation.infos.canEveryoneAddMembers ? "check" : "uncheck");
//Check if user is a conversation moderator or not
2021-03-06 11:04:01 +00:00
if(!conversation.infos.members.find(m => m.user_id == userID()).is_admin) {
2017-06-17 15:24:45 +00:00
//We disable name field
settingsForm.conversationNameInput.disabled = "true";
2017-06-17 09:40:57 +00:00
2020-04-25 16:44:40 +00:00
//We hide conversation users (presents in members pane - if user is not allowed to add new members)
if(!conversation.infos.canEveryoneAddMembers)
settingsForm.usersElement.parentNode.style.display = "none";
2020-04-25 16:20:29 +00:00
settingsForm.allowEveryoneToAddMembers.parentNode.parentNode.remove();
2017-06-17 15:24:45 +00:00
}
2017-06-17 09:40:57 +00:00
2017-06-18 09:14:26 +00:00
//Update follow conversation checkbox status
2020-04-25 16:20:29 +00:00
$(settingsForm.followConversationInput).iCheck(conversation.infos.following == "1" ? "check" : "uncheck");
2017-06-17 15:24:45 +00:00
//Save settings form in global form
conversation.settingsForm = settingsForm;
2017-06-17 09:40:57 +00:00
2017-06-17 15:24:45 +00:00
//Make update settings button lives
2020-04-25 16:20:29 +00:00
settingsForm.createButton.onclick = () => {
this.submitUpdateForm(conversation);
2017-06-17 15:24:45 +00:00
};
2017-06-17 09:40:57 +00:00
2017-06-17 09:20:54 +00:00
//Success
return true;
},
2017-06-17 08:09:37 +00:00
/**
* Add a call button to the conversation, if possible
*
* @param {Object} conversation Information about the conversation
*/
showCallButton: function(conversation){
//Check if calls are disabled
2020-04-10 09:24:46 +00:00
if(!conversation.infos.can_have_call)
return;
//Add the call button
2020-04-10 09:24:46 +00:00
const button = createElem2({
insertBefore: conversation.box.boxTools.firstChild,
type: "button",
class: "btn btn-box-tool",
innerHTML: "<i class='fa fa-phone'></i>"
});
conversation.box.callButton = button;
2019-01-24 13:40:36 +00:00
button.addEventListener("click", function(){
2020-04-10 09:24:46 +00:00
CallsController.Open(conversation.infos)
2019-01-24 13:40:36 +00:00
});
},
2017-06-17 15:24:45 +00:00
/**
* Process submited update conversation form
*
* @param {Object} conversation Information about the conversation
2017-06-17 15:24:45 +00:00
* @return {Boolean} True for a success
*/
submitUpdateForm: function(conversation){
//Then, get information about the input
2017-06-17 15:24:45 +00:00
var newValues = {
2017-06-17 15:32:21 +00:00
conversationID: conversation.infos.ID,
2017-06-17 15:24:45 +00:00
following: conversation.settingsForm.followConversationInput.checked,
}
2020-04-25 16:44:40 +00:00
//Get conversation members
if(conversation.infos.ID_owner == userID() || conversation.infos.canEveryoneAddMembers)
newValues.members = ComunicWeb.components.userSelect.getResults(conversation.settingsForm.usersElement);
2017-06-17 15:24:45 +00:00
//Add other fields if the user is a conversation moderator
if(conversation.infos.ID_owner == userID()){
//Specify conversation name
var nameValue = conversation.settingsForm.conversationNameInput.value
newValues.name = (nameValue === "" ? false : nameValue);
2020-04-25 16:44:40 +00:00
2017-06-17 15:24:45 +00:00
//Check if any users were selected
if(newValues.members.length === 0){
//Inform user that its input is invalid
2021-03-06 11:04:01 +00:00
notify("Please select at least one user !", "danger", 3);
2017-06-17 15:24:45 +00:00
return false;
}
2020-04-25 16:20:29 +00:00
newValues.canEveryoneAddMembers = conversation.settingsForm.allowEveryoneToAddMembers.checked;
2017-06-17 15:24:45 +00:00
}
//Now, freeze the submit button
2017-06-18 09:14:26 +00:00
conversation.settingsForm.createButton.disabled = true;
2017-06-17 15:24:45 +00:00
//Peform a request through the interface
2020-04-25 16:20:29 +00:00
ConversationsInterface.updateSettings(newValues, function(result){
2017-06-18 09:14:26 +00:00
//Enable again update button
conversation.settingsForm.createButton.disabled = false;
//Check for errors
if(result.error)
2021-03-06 11:04:01 +00:00
notify("An error occured while trying to update conversation settings !", "danger", 4);
2017-06-18 09:14:26 +00:00
//Reload the conversation
2017-06-18 09:32:31 +00:00
ComunicWeb.components.conversations.chatWindows.unload(conversation.infos.ID, true);
ComunicWeb.components.conversations.chatWindows.load(conversation.infos.ID, conversation.box);
2017-06-17 15:32:21 +00:00
});
2017-06-17 15:24:45 +00:00
//Success
return true;
},
2017-06-21 16:29:14 +00:00
/**
* Submit a new message form
*
* @param {Object} convInfos Information about the conversation
2017-06-21 16:29:14 +00:00
* @return {Boolean} True for a success
*/
submitMessageForm: function(convInfos){
2017-06-21 16:38:42 +00:00
2017-06-21 16:29:14 +00:00
//Log action
ComunicWeb.debug.logMessage("Send a new message in a conversation system.");
//Extract main fields
var form = convInfos.box.sendMessageForm;
2017-06-21 16:29:14 +00:00
//Check if message is empty
if(!checkString(form.inputText.value) && !form.inputImage.files[0]){
2021-03-06 11:04:01 +00:00
notify("Please type a valid message before trying to send it !", "danger", 2);
return false;
}
//Lock send button
form.sendButton.disabled = true;
//Prepare what to do next
2021-03-06 11:04:01 +00:00
var onceSent = (result) => {
//Check for errors
if(result.error){
2021-03-06 11:04:01 +00:00
notify("An error occured while trying to send message! Please try again...", "danger", 2);
//Unlock send button
form.sendButton.disabled = false;
return false;
}
//Reset the form
ComunicWeb.components.conversations.chatWindows.resetCreateMessageForm(convInfos);
}
//Send the message throught the interface
ComunicWeb.components.conversations.interface.sendMessage({
conversationID: convInfos.infos.ID,
message: form.inputText.value,
image: form.inputImage,
callback: onceSent
});
//Success
return true;
},
/**
* Reset a create a message form
*
* @param {Object} infos Information about the conversation
* @return {Boolean} True for a success
*/
resetCreateMessageForm: function(infos){
//Extract form informations
var form = infos.box.sendMessageForm;
//Unlock send button and reset its value
form.sendButton.disabled = false;
//Empty textarea
form.inputText.value = "";
form.textarea2.resetHeight();
//Remove image from image input
form.inputImage.value = "";
2017-06-21 16:29:14 +00:00
//Success
return true;
},
2017-06-25 17:10:26 +00:00
/**
* Add a message to a conversation window
*
* @param {Integer} conversationID The ID of the conversation to update
2018-04-27 16:26:16 +00:00
* @param {Object} messageInfo Information about the message to add
2017-06-25 17:10:26 +00:00
* @return {Boolean} True for a success
*/
2018-04-27 16:26:16 +00:00
addMessage: function(conversationID, messageInfo){
2017-06-25 17:10:26 +00:00
2018-04-27 17:05:06 +00:00
//First, check if the conversation information can be found
2017-06-25 17:10:26 +00:00
if(!this.__conversationsCache["conversation-"+conversationID]){
ComunicWeb.debug.logMessage("Conversation Chat Windows : Error ! Couldn't add a message to the conversation because the conversation was not found !");
return false;
}
//Else extract conversation informations
var convInfos = this.__conversationsCache["conversation-"+conversationID];
2017-06-26 09:16:14 +00:00
//Check if this is the first message of the conversation or not
2018-04-27 16:26:16 +00:00
if(!convInfos.messages){
convInfos.messages = [];
2017-06-26 09:16:14 +00:00
}
2017-06-25 17:10:26 +00:00
//Get message HTML element add append it
var uiMessageInfo = this._get_message_element(convInfos, messageInfo);
convInfos.box.messagesArea.appendChild(uiMessageInfo.rootElem);
//Perform post-processing operations
var num = convInfos.messages.push(uiMessageInfo);
//Check if it is not the first message from the current user
this._makeMessageFollowAnotherMessage(convInfos, num - 1);
//Enable slimscroll
$(convInfos.box.messagesArea).slimscroll({
height: "250px",
});
//Scroll to the bottom of the conversation
var scrollBottom = $(convInfos.box.messagesArea).prop("scrollHeight")+"px";
$(convInfos.box.messagesArea).slimScroll({
scrollTo: scrollBottom
});
//Initialize top scroll detection if required
this.initTopScrollDetection(conversationID);
//Success
return true;
},
2018-04-27 17:05:06 +00:00
/**
* Add old messages to a conversation window
*
* @param {number} conversationID The ID of the target conversation
* @param {array} messages The list of messages to add
*/
addOldMessages: function(conversationID, messages){
//First, check if the conversation information can be found
if(!this.__conversationsCache["conversation-"+conversationID]){
ComunicWeb.debug.logMessage("Conversation Chat Windows : Error ! Couldn't add a message to the conversation because the conversation was not found !");
return false;
}
//Else extract conversation informations
var conv = this.__conversationsCache["conversation-"+conversationID];
//Save the position of the oldest message element
var currOldestMessageElem = conv.messages[0].rootElem;
2018-04-27 17:05:06 +00:00
//Process the list of messages in reverse order
messages.reverse();
messages.forEach(function(message){
//Get message element
var uiMessageInfo = ComunicWeb.components.conversations.chatWindows._get_message_element(conv, message);
//Add the messages at the begining of the conversation
conv.box.messagesArea.insertBefore(uiMessageInfo.rootElem, conv.messages[0].rootElem);
//Add the message to the list
conv.messages.unshift(uiMessageInfo);
//Check if some information about the post can be updated
ComunicWeb.components.conversations.chatWindows._makeMessageFollowAnotherMessage(conv, 1);
});
//Update slimscroll
newScrollPos = currOldestMessageElem.offsetTop - 30;
if(newScrollPos < 0)
newScrollPos = 0;
$(conv.box.messagesArea).slimScroll({
scrollTo: newScrollPos + "px"
});
2018-04-27 17:05:06 +00:00
},
/**
* Generate message HTML node based on given information
*
* @param {object} conversationInfo Information about the created conversation
2021-03-06 11:04:01 +00:00
* @param {ConversationMessage} message Information about the target message
* @return {object} Information about the created message element
*/
_get_message_element: function(conversationInfo, message){
2018-04-27 16:26:16 +00:00
//Check if it is the current user who sent the message
2021-03-06 11:04:01 +00:00
var userIsPoster = message.user_id == userID();
2017-06-25 17:10:26 +00:00
2018-04-27 16:26:16 +00:00
//Create message element
2020-04-02 17:13:10 +00:00
const messageContainer = createElem2({
2018-04-27 16:26:16 +00:00
type: "div",
class: "direct-chat-msg " + (userIsPoster ? "right" : "")
});
2020-04-02 17:13:10 +00:00
messageContainer.setAttribute("data-chatwin-msg-id", message.ID)
2017-06-25 17:10:26 +00:00
2018-04-27 16:26:16 +00:00
//Display message header
var messageHeader = createElem2({
appendTo: messageContainer,
type: "div",
class: "direct-chat-info clearfix"
});
2017-06-26 09:16:14 +00:00
2018-05-02 14:16:18 +00:00
//Add top information
var topInfosElem = createElem2({
appendTo: messageHeader,
type: "div",
class: "direct-chat-name pull-" + (userIsPoster ? "right" : "left"),
});
2018-04-27 16:26:16 +00:00
//Add user name
var usernameElem = createElem2({
2018-05-02 14:16:18 +00:00
appendTo: topInfosElem,
2018-04-27 16:26:16 +00:00
type: "span",
innerHTML: "Loading",
});
2017-06-26 09:16:14 +00:00
2018-04-27 16:26:16 +00:00
//Hide user name if it is the current user
if(userIsPoster)
usernameElem.style.display = "none";
2017-06-26 09:16:14 +00:00
2018-04-27 16:26:16 +00:00
//Add user account image
var userAccountImage = createElem2({
appendTo: messageContainer,
type: "img",
class: "direct-chat-img",
src: ComunicWeb.__config.assetsURL + "img/defaultAvatar.png",
alt: "User account image",
});
2017-06-26 09:16:14 +00:00
2018-04-27 16:26:16 +00:00
//Load user informations
2021-03-06 11:04:01 +00:00
let userInfo = conversationInfo.membersInfos.get(message.user_id);
if(userInfo) {
2018-04-27 16:26:16 +00:00
//Replace poster name
2021-03-06 11:04:01 +00:00
usernameElem.innerHTML = userInfo.fullName;
userAccountImage.src = userInfo.image;
2017-06-26 09:16:14 +00:00
}
2017-06-25 17:10:26 +00:00
//Add message
var messageTargetElem = createElem2({
2017-06-26 09:16:14 +00:00
appendTo: messageContainer,
2017-06-25 17:10:26 +00:00
type: "div",
2018-04-27 16:26:16 +00:00
class: "direct-chat-text ",
2017-06-25 17:10:26 +00:00
});
//Add text message
var textMessage = createElem2({
2017-06-25 17:10:26 +00:00
appendTo: messageTargetElem,
type: "span",
innerHTML: removeHtmlTags(message.message), //Remove HTML tags
2017-06-25 17:10:26 +00:00
});
//Check if an image has to be added
if(message.image_path != null){
2017-06-26 13:36:29 +00:00
//Image link
var imageLink = createElem2({
2017-06-25 17:10:26 +00:00
appendTo: messageTargetElem,
2017-06-26 13:36:29 +00:00
type:"a",
href: message.image_path,
2017-06-26 13:36:29 +00:00
});
//Image element
createElem2({
appendTo: imageLink,
2017-06-25 17:10:26 +00:00
type: "img",
src: message.image_path,
2017-06-25 17:10:26 +00:00
class: "conversation-msg-image"
});
2017-06-26 13:36:29 +00:00
//Enable lightbox
imageLink.onclick = function(){
$(this).ekkoLightbox({
alwaysShowClose: true,
});
return false;
}
2017-06-25 17:10:26 +00:00
}
2018-05-02 14:16:18 +00:00
//Add date
var dateElem = createElem2({
appendTo: messageContainer,
type: "div",
class: "date-conversation-message",
2021-03-06 13:07:20 +00:00
innerHTML: ComunicWeb.common.date.timeDiffToStr(message.time_sent)
2018-05-02 14:16:18 +00:00
});
//Parse emojies in text message
2018-05-03 20:05:06 +00:00
ComunicWeb.components.textParser.parse({
element: textMessage,
2021-03-06 11:04:01 +00:00
user: userInfo,
});
2019-01-11 16:57:55 +00:00
//Add message dropdown menu
messageContainer.className += " dropdown";
var dropdownToggle = createElem2({
insertBefore: dateElem,
type: "i",
class: "hidden"
});
dropdownToggle.setAttribute("data-toggle", "dropdown");
var dropdownMenu = createElem2({
insertBefore: dateElem,
type: "ul",
class: "dropdown-menu"
});
dropdownMenu.setAttribute("role", "menu");
messageTargetElem.addEventListener("dblclick", function(){
$(dropdownToggle).dropdown("toggle");
});
//Add message options
if(userIsPoster){
//Update message content
var updateLi = createElem2({
type: "li",
appendTo: dropdownMenu
});
var updateLink = createElem2({
type: "a",
appendTo: updateLi,
innerHTML: "Edit"
});
updateLink.addEventListener("click", function(){
ComunicWeb.components.conversations.messageEditor.open(message, function(newContent){
2020-04-02 17:30:11 +00:00
/*
2021-03-06 11:04:01 +00:00
DEPRECATED WITH WEBSOCKETS
*/
});
});
2019-01-11 16:57:55 +00:00
//Delete the message
var deleteLi = createElem2({
type: "li",
appendTo: dropdownMenu
});
var deleteLink = createElem2({
type: "a",
appendTo: deleteLi,
innerHTML: "Delete"
});
deleteLink.addEventListener("click", function(){
ComunicWeb.common.messages.confirm(
"Do you really want to delete this message? The operation can not be reverted!",
function(confirm){
if(!confirm) return;
//Hide the message
messageTargetElem.style.display = "none";
//Execute the request
ComunicWeb.components.conversations.interface.DeleteSingleMessage(
message.ID,
function(result){
if(!result){
messageTargetElem.style.display = "block";
notify("Could delete conversation message!", "danger");
}
}
);
}
)
});
}
//Return information about the message
return {
2021-03-06 11:04:01 +00:00
userID: message.user_id,
2018-04-27 16:26:16 +00:00
rootElem: messageContainer,
userNameElem: usernameElem,
2018-05-02 14:16:18 +00:00
dateElem: dateElem,
2021-03-06 13:07:20 +00:00
time_sent: message.time_sent,
2018-04-27 16:26:16 +00:00
messageTargetElem: messageTargetElem,
accountImage: userAccountImage
};
},
2018-04-27 16:26:16 +00:00
/**
* Make a conversation message "follow" another conversation message from the
* same user
*
* @param {object} conv Information about the target conversation
* @param {number} num The number of the conversation message to update
*/
_makeMessageFollowAnotherMessage: function(conv, num){
2018-04-27 16:26:16 +00:00
if(conv.messages[num - 1]){
2018-04-27 16:26:16 +00:00
if(conv.messages[num-1].userID == conv.messages[num].userID){
2018-04-27 16:26:16 +00:00
//Update object class name
conv.messages[num].messageTargetElem.className += " not-first-message";
2018-04-27 16:26:16 +00:00
//Hide user name and account image
conv.messages[num].userNameElem.style.display = "none";
conv.messages[num].accountImage.style.display = "none";
2018-04-27 16:26:16 +00:00
//Update the class of the previous message
conv.messages[num-1].rootElem.className += " not-last-message-from-user";
2018-04-27 16:26:16 +00:00
}
2018-05-02 14:16:18 +00:00
//Check the difference of time between the two messages
2021-03-06 13:07:20 +00:00
if(conv.messages[num].time_sent - conv.messages[num - 1].time_sent < 3600
2018-05-02 14:16:18 +00:00
|| conv.messages[num].dateElem.innerHTML == conv.messages[num - 1].dateElem.innerHTML)
conv.messages[num].dateElem.style.display = "none";
2018-04-27 16:26:16 +00:00
}
2017-06-25 17:10:26 +00:00
},
/**
* Init top scroll detection (if required)
*
* @param {number} conversationID The ID of the target conversation
*/
initTopScrollDetection: function(conversationID){
//Extract conversation informations
var convInfo = this.__conversationsCache["conversation-"+conversationID];
//Check if nothing has to be done
if(convInfo.box.initializedScrollDetection)
return;
//Mark scroll detection as initialized
convInfo.box.initializedScrollDetection = true;
var scrollDetectionLocked = false;
var scrollTopCount = 0;
$(convInfo.box.messagesArea).slimScroll().bind("slimscrolling", function(e, pos){
if(scrollDetectionLocked)
return;
if(pos != 0){
scrollTopCount = 0;
}
scrollTopCount++;
//Check top count
if(scrollTopCount < 3)
return;
//Lock the detection
scrollDetectionLocked = true;
//Fetch older messages
2018-04-26 15:55:38 +00:00
ComunicWeb.components.conversations.interface.getOlderMessages(
conversationID,
ComunicWeb.components.conversations.service.getOldestMessageID(conversationID),
10,
function(result){
//Unlock scroll detection
scrollDetectionLocked = false;
//Check for errors
if(result.error){
notify("An error occured while trying to fetch older messages for the conversation !");
return;
}
//Check for results
if(result.length == 0){
//Lock scroll detection in order to avoid useless traffic
scrollDetectionLocked = true;
return;
}
//Save the ID of the oldest message
2018-04-27 17:05:06 +00:00
ComunicWeb.components.conversations.service.setOldestMessageID(conversationID, result[0].ID);
2018-04-26 15:55:38 +00:00
2018-04-27 17:05:06 +00:00
//Display the list of messages
ComunicWeb.components.conversations.chatWindows.addOldMessages(conversationID, result);
2018-04-26 15:55:38 +00:00
}
);
});
}
2017-06-18 09:32:31 +00:00
}
2020-04-02 17:13:10 +00:00
ComunicWeb.components.conversations.chatWindows = ConvChatWindow;
2017-06-18 09:32:31 +00:00
//Register conversations cache cleaning function
2020-04-02 17:30:11 +00:00
ComunicWeb.common.cacheManager.registerCacheCleaner("ComunicWeb.components.conversations.chatWindows.unloadAll");
// Register to messages update events
document.addEventListener("updatedConvMessage", (e) => {
const msg = e.detail;
// Get message target
2021-03-06 11:04:01 +00:00
const target = document.querySelector("[data-chatwin-msg-id='"+msg.id+"']");
2020-04-02 17:30:11 +00:00
if(!target)
return;
// Get conversation info
2021-03-06 11:04:01 +00:00
const convInfo = ConvChatWindow.__conversationsCache["conversation-"+msg.conv_id];
2020-04-02 17:30:11 +00:00
if(!convInfo)
return;
target.replaceWith(ConvChatWindow._get_message_element(convInfo, msg).rootElem)
});
// Register to message deletion events
document.addEventListener("deletedConvMessage", (e) => {
const msgID = e.detail;
// Get message target
const target = document.querySelector("[data-chatwin-msg-id='"+msgID+"'] .direct-chat-text");
if(!target)
return;
target.style.display = "none";
})