2017-06-14 14:39:34 +00:00
/ * *
* 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 ;
} ,
2017-06-21 14:44:10 +00:00
/ * *
* 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
2019-01-23 14:45:19 +00:00
infosBox . rootElem . className += " chat-window direct-chat direct-chat-primary" ;
2017-06-21 14:44:10 +00:00
//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
2017-06-24 17:23:55 +00:00
infosBox . messagesArea = createElem2 ( {
appendTo : infosBox . boxBody ,
type : "div" ,
class : "direct-chat-messages" ,
2017-06-25 17:10:26 +00:00
innerHTML : "" ,
2017-06-24 17:23:55 +00:00
} ) ;
2017-06-21 14:44:10 +00:00
//Add button to get conversation members
2019-01-23 14:45:19 +00:00
infosBox . membersButton = createElem2 ( {
type : "button" ,
insertBefore : infosBox . closeButton ,
elemType : "button" ,
class : "btn btn-box-tool" ,
title : "Conversation members"
} ) ;
2017-06-21 14:44:10 +00:00
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" ;
2019-01-23 14:45:19 +00:00
2017-06-21 14:44:10 +00:00
//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 ( {
2017-06-21 14:44:10 +00:00
appendTo : infosBox . boxFooter ,
2017-06-21 16:29:14 +00:00
type : "form" ,
2017-06-21 14:44:10 +00:00
class : "create-message-form"
} ) ;
2017-06-21 16:29:14 +00:00
//Create input group
2017-06-21 14:44:10 +00:00
var inputGroup = createElem2 ( {
2018-03-25 07:43:39 +00:00
appendTo : conversationFormContainer ,
2017-06-21 14:44:10 +00:00
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" ,
2017-06-21 14:44:10 +00:00
class : "form-control" ,
2021-03-06 13:37:18 +00:00
placeholder : tr ( "New message..." ) ,
2017-06-21 14:44:10 +00:00
} ) ;
2017-06-26 08:56:12 +00:00
inputText . maxLength = 200 ;
2017-06-21 14:44:10 +00:00
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 ,
} ) ;
2021-03-06 13:37:18 +00:00
//Create file input (for optionnal file)
var fileInput = createElem2 ( {
2017-06-21 16:29:14 +00:00
type : "input" ,
elemType : "file" ,
} ) ;
2017-06-21 14:44:10 +00:00
//Create button group
var buttonGroup = createElem2 ( {
appendTo : inputGroup ,
type : "span" ,
class : "input-group-btn" ,
} ) ;
2018-04-21 06:38:45 +00:00
//Add emojie button
var emojiButton = createElem2 ( {
appendTo : buttonGroup ,
type : "button" ,
elemType : "button" ,
class : "btn btn-flat btn-add-emoji" ,
} ) ;
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
2021-03-06 13:37:18 +00:00
const fileButton = createElem2 ( {
2017-06-21 16:29:14 +00:00
appendTo : buttonGroup ,
type : "button" ,
elemType : "button" ,
class : "btn btn-flat btn-add-image" ,
} ) ;
2021-03-06 13:37:18 +00:00
fileButton . onclick = function ( ) {
2017-06-21 16:29:14 +00:00
//Call file selector
2021-03-06 13:37:18 +00:00
fileInput . click ( ) ;
2017-06-21 16:29:14 +00:00
} ;
//Add image icon
createElem2 ( {
type : "i" ,
2021-03-06 13:37:18 +00:00
appendTo : fileButton ,
2017-06-21 16:29:14 +00:00
class : "fa fa-image"
} ) ;
2017-06-21 14:44:10 +00:00
//Add send button
var sendButton = createElem2 ( {
appendTo : buttonGroup ,
2017-06-23 15:25:29 +00:00
type : "button" ,
2017-06-21 14:44:10 +00:00
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 14:44:10 +00:00
} ) ;
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 ,
} ;
2017-06-21 14:44:10 +00:00
//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 ) {
2017-06-24 17:23:55 +00:00
2021-03-06 11:04:01 +00:00
try {
2017-06-24 17:23:55 +00:00
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 ) ;
2017-06-24 17:23:55 +00:00
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
} ;
2019-01-23 14:45:19 +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 ) ;
2017-06-24 17:23:55 +00:00
//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 = "" ;
2017-06-24 17:23:55 +00:00
//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 ;
} ,
2017-06-16 09:42:28 +00:00
/ * *
* Change the name of the converation at the top of the windows
*
* @ param { String } newName The new name for the conversation window
2019-05-16 16:40:39 +00:00
* @ param { Ojbect } info Information about the conversation window
2017-06-16 09:42:28 +00:00
* @ return { Boolean } True for a success
* /
2019-05-16 16:40:39 +00:00
changeName : function ( newName , info ) {
2017-06-16 09:42:28 +00:00
2018-08-16 10:37:03 +00:00
//Reduce new name
if ( newName . length > 18 )
newName = newName . slice ( 0 , 17 ) + "..." ;
2017-06-16 09:42:28 +00:00
//Empty name field
2019-05-16 16:40:39 +00:00
emptyElem ( info . boxTitle ) ;
2017-06-16 09:42:28 +00:00
//Create conversation icon
2019-05-16 16:40:39 +00:00
createElem2 ( {
type : "i" ,
appendTo : info . boxTitle ,
class : "fa fa-comments" ,
ondblclick : ( ) => {
openConversation ( info . conversationID , true ) ;
info . closeFunction ( ) ;
}
} ) ;
2017-06-16 09:42:28 +00:00
//Add conversation title
2019-05-16 16:40:39 +00:00
var conversationTitle = createElem ( "span" , info . boxTitle ) ;
2017-06-16 09:42:28 +00:00
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"
} ) ;
2017-06-16 09:42:28 +00:00
//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
2019-01-23 14:45:19 +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 )
2019-01-23 14:45:19 +00:00
return ;
//Add the call button
2020-04-10 09:24:46 +00:00
const button = createElem2 ( {
2019-01-23 14:45:19 +00:00
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
} ) ;
2019-01-23 14:45:19 +00:00
} ,
2017-06-17 15:24:45 +00:00
/ * *
* Process submited update conversation form
*
2019-01-23 14:45:19 +00:00
* @ param { Object } conversation Information about the conversation
2017-06-17 15:24:45 +00:00
* @ return { Boolean } True for a success
* /
submitUpdateForm : function ( conversation ) {
2019-01-23 14:45:19 +00:00
//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
*
2019-01-23 14:45:19 +00:00
* @ param { Object } convInfos Information about the conversation
2017-06-21 16:29:14 +00:00
* @ return { Boolean } True for a success
* /
2021-03-06 13:37:18 +00:00
submitMessageForm : async function ( convInfos ) {
2017-06-22 09:16:53 +00:00
2021-03-06 13:37:18 +00:00
try {
2017-06-22 09:16:53 +00:00
2021-03-06 13:37:18 +00:00
//Extract main fields
var form = convInfos . box . sendMessageForm ;
2017-06-22 09:16:53 +00:00
2021-03-06 13:37:18 +00:00
//Check if message is empty.
let message = form . inputText . value ;
2017-06-22 09:16:53 +00:00
2021-03-06 13:37:18 +00:00
if ( message . length == 0 )
return ;
2017-06-22 09:16:53 +00:00
2021-03-06 13:37:18 +00:00
if ( message . length < ServerConfig . conf . min _conversation _message _len || message . length > ServerConfig . conf . max _conversation _message _len ) {
notify ( tr ( "Invalid message length!" ) , "danger" , 2 ) ;
return ;
2017-06-22 09:16:53 +00:00
}
2021-03-06 13:37:18 +00:00
//Lock send button
form . sendButton . disabled = true ;
2017-06-22 09:16:53 +00:00
2021-03-06 13:37:18 +00:00
await ConversationsInterface . sendMessage ( convInfos . infos . id , message ) ;
2017-06-22 09:16:53 +00:00
//Reset the form
2021-03-06 13:37:18 +00:00
ConvChatWindow . resetCreateMessageForm ( convInfos ) ;
2017-06-22 09:16:53 +00:00
}
2021-03-06 13:37:18 +00:00
catch ( e )
{
console . error ( e )
notify ( "An error occured while trying to send message! Please try again..." , "danger" , 2 ) ;
}
//Unlock send button
form . sendButton . disabled = false ;
2017-06-22 09:16:53 +00:00
} ,
/ * *
* Reset a create a message form
*
2019-01-23 14:45:19 +00:00
* @ param { Object } infos Information about the conversation
2017-06-22 09:16:53 +00:00
* @ 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 ( ) ;
2017-06-21 16:29:14 +00:00
} ,
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
2018-04-27 16:41:57 +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 ] ;
2018-04-28 08:04:12 +00:00
//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 ) ;
} ) ;
2018-04-28 08:04:12 +00:00
//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
} ,
2018-04-27 16:41:57 +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
2018-04-27 16:41:57 +00:00
* @ return { object } Information about the created message element
* /
_get _message _element : function ( conversationInfo , message ) {
2021-03-06 13:25:41 +00:00
if ( message . user _id != null && message . user _id > 0 )
return this . _get _user _message ( conversationInfo , message ) ;
else
return this . _get _server _message ( conversationInfo , message ) ;
} ,
2018-04-27 16:41:57 +00:00
2021-03-06 13:25:41 +00:00
/ * *
* @ param { Object } conversationInfo
* @ param { ConversationMessage } message
* /
_get _user _message : ( 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" : "" )
} ) ;
2021-03-06 13:25:41 +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 ) {
usernameElem . innerHTML = userInfo . fullName ;
userAccountImage . src = userInfo . image ;
2017-06-26 09:16:14 +00:00
}
2017-06-25 17:10:26 +00:00
2021-03-06 13:09:19 +00:00
else {
async ( ) => {
try {
const userInfo = await userInfo ( message . user _id ) ;
usernameElem . innerHTML = userInfo . fullName ;
userAccountImage . src = userInfo . image ;
} catch ( e ) {
console . error ( e ) ;
}
}
}
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
2017-06-26 08:56:12 +00:00
var textMessage = createElem2 ( {
2017-06-25 17:10:26 +00:00
appendTo : messageTargetElem ,
type : "span" ,
2018-04-27 16:41:57 +00:00
innerHTML : removeHtmlTags ( message . message ) , //Remove HTML tags
2017-06-25 17:10:26 +00:00
} ) ;
//Check if an image has to be added
2018-04-27 16:41:57 +00:00
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" ,
2018-04-27 16:41:57 +00:00
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" ,
2018-04-27 16:41:57 +00:00
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
} ) ;
2017-06-26 08:56:12 +00:00
//Parse emojies in text message
2018-05-03 20:05:06 +00:00
ComunicWeb . components . textParser . parse ( {
2017-06-26 08:56:12 +00:00
element : textMessage ,
2021-03-06 11:04:01 +00:00
user : userInfo ,
2017-06-26 08:56:12 +00:00
} ) ;
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 ) {
2019-01-11 17:17:37 +00:00
//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 17:17:37 +00:00
} ) ;
} ) ;
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
2021-03-06 13:25:41 +00:00
ConversationsInterface . DeleteSingleMessage (
2021-03-06 13:37:59 +00:00
message . id ,
2019-01-11 16:57:55 +00:00
function ( result ) {
if ( ! result ) {
messageTargetElem . style . display = "block" ;
notify ( "Could delete conversation message!" , "danger" ) ;
}
}
) ;
}
)
} ) ;
}
2018-04-27 16:41:57 +00:00
//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:41:57 +00:00
} ,
2018-04-27 16:26:16 +00:00
2021-03-06 13:25:41 +00:00
/ * *
* Apply a server message
*
* @ param { Object } convInfo Information about the conversation
* @ param { ConversationMessage } message The message
* /
_get _server _message : ( convInfo , message ) => {
//Create message element
const messageContainer = createElem2 ( {
type : "div" ,
class : "direct-chat-msg "
} ) ;
messageContainer . setAttribute ( "data-chatwin-msg-id" , message . id ) ;
//Add message
let messageTargetElem = createElem2 ( {
appendTo : messageContainer ,
type : "div" ,
class : "server_message" ,
} ) ;
( async ( ) => {
try {
let ids = ConversationsUtils . getUsersIDForMessage ( message )
let users = await getUsers ( ids ) ;
let msg = ConversationsUtils . getServerMessage ( message , users ) ;
messageTargetElem . innerHTML = msg
}
catch ( e ) {
console . error ( e ) ;
notify ( tr ( "Failed to load a server message!" ) )
}
} ) ( ) ;
return {
userID : null ,
rootElem : messageContainer ,
userNameElem : document . createElement ( "span" ) ,
dateElem : document . createElement ( "span" ) ,
time _sent : message . time _sent ,
messageTargetElem : messageTargetElem ,
accountImage : document . createElement ( "span" )
} ;
} ,
2018-04-27 16:41:57 +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
2018-04-27 16:41:57 +00:00
if ( conv . messages [ num - 1 ] ) {
2018-04-27 16:26:16 +00:00
2018-04-27 16:41:57 +00:00
if ( conv . messages [ num - 1 ] . userID == conv . messages [ num ] . userID ) {
2018-04-27 16:26:16 +00:00
//Update object class name
2018-04-27 16:41:57 +00:00
conv . messages [ num ] . messageTargetElem . className += " not-first-message" ;
2018-04-27 16:26:16 +00:00
//Hide user name and account image
2018-04-27 16:41:57 +00:00
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
2018-04-27 16:41:57 +00:00
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
} ,
2018-04-26 04:50:23 +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
2021-03-06 13:25:41 +00:00
ConversationsInterface . getOlderMessages (
2018-04-26 15:55:38 +00:00
conversationID ,
2021-03-06 13:25:41 +00:00
ConvService . getOldestMessageID ( conversationID ) ,
2018-04-26 15:55:38 +00:00
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
2021-03-06 13:29:15 +00:00
ConvService . 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
}
) ;
2018-04-26 04:50:23 +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 )
2020-04-03 07:04:41 +00:00
} ) ;
// 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" ;
} )