From fae4b1433e11ece9817d0e7cbe338015838ad38b Mon Sep 17 00:00:00 2001 From: Carlos Hernandez Date: Sat, 11 Mar 2017 14:04:24 +0100 Subject: [PATCH 1/5] first try on notifications. Not working so well --- dist/chat.js | 63 ++++++++++++++++++++++++++++++++++++--- js/chat.js | 60 +++++++++++++++++++++++++++++++++++-- template/ias_segment.html | 1 + template/ias_style.html | 12 ++++++++ 4 files changed, 130 insertions(+), 6 deletions(-) diff --git a/dist/chat.js b/dist/chat.js index 371fa41..3b0565b 100644 --- a/dist/chat.js +++ b/dist/chat.js @@ -27,6 +27,7 @@ function IASChat(config) { // Prepare listeners var show = document.getElementById('ias-show'); + var showNotifications = document.getElementById('ias-show-notifications'); var ias = document.getElementById('ias'); var topbar = document.getElementById('ias_topbar'); var close = document.getElementById('ias_topbar-close'); @@ -47,6 +48,8 @@ function IASChat(config) { var lastHash = ''; var lastPage = ''; + var lastMessage = {}; + // Listen event submit if(show) { show.addEventListener('click', showIAS.bind(this)); @@ -98,9 +101,12 @@ function IASChat(config) { userRef = firebase.database().ref('users/' + cid); userRef.on('value', function(data) { + var key = data.key; var user = data.val(); + lastMessage = user.lastMessage; + var printData = { name: defaultSupportName, pic: defaultSupportPic @@ -131,11 +137,11 @@ function IASChat(config) { // If shall show button, add it to interface (from html/show-button.html) if(button) { - ias += '
' + ias += '
' } // Also add the styles from css/style.css - ias += ''; + ias += ''; var printplace = null; @@ -278,6 +284,10 @@ function IASChat(config) { firebase.database().ref('messages/' + cid).push(msg); firebase.database().ref('users/' + cid).once('value').then(function(snapshot) { + + var userLastMsg = msg; + userLastMsg.read = false; + if(!snapshot.val()) { // Add user firebase.database().ref('users/' + cid).set({ @@ -285,10 +295,10 @@ function IASChat(config) { pic: pic, isSupporter: false, supporter: -1, - lastMessage: msg + lastMessage: userLastMsg }); } else { - firebase.database().ref('users/' + cid).update({lastMessage: msg}); + firebase.database().ref('users/' + cid).update({lastMessage: userLastMsg}); if(!snapshot.val().profile) { generateUserData(cid) } @@ -314,6 +324,34 @@ function IASChat(config) { printMessage(text); } else { printMessage(text, true); + + // If chat is open, set the message as read. Else, set a notification ;) + if(isHidden()) { + setNotifications() + } else { + readLastMessage(); + } + } + } + + function readLastMessage() { + console.log('IAS SHOWN, MARK LAST MESSAGE AS READ'); + firebase.database().ref('users/' + cid + '/lastMessage').update({read: true}); + } + + function setNotifications() { + if(lastMessage.uid !== uid && !lastMessage.read) { + if (showNotifications.classList) { + showNotifications.classList.remove('hidden'); + } else { + showNotifications.className = showNotifications.className.replace(new RegExp('(^|\\b)' + 'hidden'.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); + } + } else { + if (showNotifications.classList) { + showNotifications.classList.add('hidden'); + } else { + showNotifications.className += ' ' + 'hidden'; + } } } @@ -338,6 +376,9 @@ function IASChat(config) { // Also set url hash to true; addUrlHash(); + + // And read last message + readLastMessage(); } function hideIAS(e) { @@ -355,6 +396,20 @@ function IASChat(config) { remUrlHash(); } + function isHidden(e) { + if(typeof(e) !== 'undefined') { + e.preventDefault(); + } + + var className = 'hidden'; + + if (ias.classList) { + return ias.classList.contains(className); + } else { + return new RegExp('(^| )' + className + '( |$)', 'gi').test(ias.className); + } + } + /* ### URL Hash ### */ function visibilityUrlHash() { diff --git a/js/chat.js b/js/chat.js index ac0a7e1..b4d94c7 100644 --- a/js/chat.js +++ b/js/chat.js @@ -27,6 +27,7 @@ function IASChat(config) { // Prepare listeners var show = document.getElementById('ias-show'); + var showNotifications = document.getElementById('ias-show-notifications'); var ias = document.getElementById('ias'); var topbar = document.getElementById('ias_topbar'); var close = document.getElementById('ias_topbar-close'); @@ -47,6 +48,8 @@ function IASChat(config) { var lastHash = ''; var lastPage = ''; + var lastMessage = {}; + // Listen event submit if(show) { show.addEventListener('click', showIAS.bind(this)); @@ -98,9 +101,12 @@ function IASChat(config) { userRef = firebase.database().ref('users/' + cid); userRef.on('value', function(data) { + var key = data.key; var user = data.val(); + lastMessage = user.lastMessage; + var printData = { name: defaultSupportName, pic: defaultSupportPic @@ -278,6 +284,10 @@ function IASChat(config) { firebase.database().ref('messages/' + cid).push(msg); firebase.database().ref('users/' + cid).once('value').then(function(snapshot) { + + var userLastMsg = msg; + userLastMsg.read = false; + if(!snapshot.val()) { // Add user firebase.database().ref('users/' + cid).set({ @@ -285,10 +295,10 @@ function IASChat(config) { pic: pic, isSupporter: false, supporter: -1, - lastMessage: msg + lastMessage: userLastMsg }); } else { - firebase.database().ref('users/' + cid).update({lastMessage: msg}); + firebase.database().ref('users/' + cid).update({lastMessage: userLastMsg}); if(!snapshot.val().profile) { generateUserData(cid) } @@ -314,6 +324,35 @@ function IASChat(config) { printMessage(text); } else { printMessage(text, true); + + // If chat is open, set the message as read. Else, set a notification ;) + if(isHidden()) { + setNotifications() + } else { + readLastMessage(); + } + } + } + + function readLastMessage() { + console.log('IAS SHOWN, MARK LAST MESSAGE AS READ'); + firebase.database().ref('users/' + cid + '/lastMessage').update({read: true}); + setNotifications(); + } + + function setNotifications() { + if(lastMessage.uid !== uid && !lastMessage.read) { + if (showNotifications.classList) { + showNotifications.classList.remove('hidden'); + } else { + showNotifications.className = showNotifications.className.replace(new RegExp('(^|\\b)' + 'hidden'.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); + } + } else { + if (showNotifications.classList) { + showNotifications.classList.add('hidden'); + } else { + showNotifications.className += ' ' + 'hidden'; + } } } @@ -338,6 +377,9 @@ function IASChat(config) { // Also set url hash to true; addUrlHash(); + + // And read last message + readLastMessage(); } function hideIAS(e) { @@ -355,6 +397,20 @@ function IASChat(config) { remUrlHash(); } + function isHidden(e) { + if(typeof(e) !== 'undefined') { + e.preventDefault(); + } + + var className = 'hidden'; + + if (ias.classList) { + return ias.classList.contains(className); + } else { + return new RegExp('(^| )' + className + '( |$)', 'gi').test(ias.className); + } + } + /* ### URL Hash ### */ function visibilityUrlHash() { diff --git a/template/ias_segment.html b/template/ias_segment.html index 631c940..02a2f06 100644 --- a/template/ias_segment.html +++ b/template/ias_segment.html @@ -3,4 +3,5 @@ + \ No newline at end of file diff --git a/template/ias_style.html b/template/ias_style.html index f46eb6a..71b99ea 100644 --- a/template/ias_style.html +++ b/template/ias_style.html @@ -151,6 +151,18 @@ right: 16px; width: 56px; } + #ias-show-notifications { + height: 16px; + width: 16px; + background: red; + position: absolute; + left: 1px; + top: 1px; + border-radius: 50%; + } + #ias-show-notifications.hidden { + display: none; + } @media screen and (min-width: 842px) { #ias { From 99e6a86cd7c0734ccc9fb17220482b3da25d26e2 Mon Sep 17 00:00:00 2001 From: Carlos Hernandez Date: Sat, 11 Mar 2017 18:25:31 +0100 Subject: [PATCH 2/5] Client norifications working --- dist/chat.js | 62 +++++++++++++++++++++++++++++---------------------- js/chat.js | 63 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 72 insertions(+), 53 deletions(-) diff --git a/dist/chat.js b/dist/chat.js index 3b0565b..0641c72 100644 --- a/dist/chat.js +++ b/dist/chat.js @@ -48,8 +48,10 @@ function IASChat(config) { var lastHash = ''; var lastPage = ''; + var user = null; var lastMessage = {}; + // Listen event submit if(show) { show.addEventListener('click', showIAS.bind(this)); @@ -86,7 +88,19 @@ function IASChat(config) { name = config.name || ''; pic = config.pic || ''; - setChatData(); + // Get chat info + userRef = firebase.database().ref('users/' + cid); + userRef.on('value', function(data) { + + user = data.val(); + + lastMessage = user.lastMessage; + // console.log(lastMessage); + + setChatData(); + setNotifications(); + }); + clearMessages(); @@ -99,13 +113,7 @@ function IASChat(config) { function setChatData() { - userRef = firebase.database().ref('users/' + cid); - userRef.on('value', function(data) { - - var key = data.key; - var user = data.val(); - - lastMessage = user.lastMessage; + if(user) { var printData = { name: defaultSupportName, @@ -124,8 +132,9 @@ function IASChat(config) { document.getElementById('ias_topbar-text').innerHTML = printData.name; document.getElementById('ias_topbar-pic').firstChild.setAttribute('src', printData.pic); - }); - + } else { + setTimeout(setChatData, 100); + } } @@ -225,7 +234,7 @@ function IASChat(config) { var text = e.srcElement.children[1].value if(text === '' && attatchment === null) { - console.log('tried to send empty form. Rejected.'); + console.warn('tried to send empty form. Rejected.'); return false; } @@ -325,32 +334,33 @@ function IASChat(config) { } else { printMessage(text, true); - // If chat is open, set the message as read. Else, set a notification ;) - if(isHidden()) { - setNotifications() - } else { + // If chat is open, set the message as read + if(!isHidden()) { readLastMessage(); } } } function readLastMessage() { - console.log('IAS SHOWN, MARK LAST MESSAGE AS READ'); firebase.database().ref('users/' + cid + '/lastMessage').update({read: true}); } function setNotifications() { - if(lastMessage.uid !== uid && !lastMessage.read) { - if (showNotifications.classList) { - showNotifications.classList.remove('hidden'); - } else { - showNotifications.className = showNotifications.className.replace(new RegExp('(^|\\b)' + 'hidden'.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); - } - } else { - if (showNotifications.classList) { - showNotifications.classList.add('hidden'); + + // Only set notifications if button are enabled + if(button) { + if(lastMessage.uid !== uid && !lastMessage.read) { + if (showNotifications.classList) { + showNotifications.classList.remove('hidden'); + } else { + showNotifications.className = showNotifications.className.replace(new RegExp('(^|\\b)' + 'hidden'.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); + } } else { - showNotifications.className += ' ' + 'hidden'; + if (showNotifications.classList) { + showNotifications.classList.add('hidden'); + } else { + showNotifications.className += ' ' + 'hidden'; + } } } } diff --git a/js/chat.js b/js/chat.js index b4d94c7..4fe1bca 100644 --- a/js/chat.js +++ b/js/chat.js @@ -48,8 +48,10 @@ function IASChat(config) { var lastHash = ''; var lastPage = ''; + var user = null; var lastMessage = {}; + // Listen event submit if(show) { show.addEventListener('click', showIAS.bind(this)); @@ -86,7 +88,19 @@ function IASChat(config) { name = config.name || ''; pic = config.pic || ''; - setChatData(); + // Get chat info + userRef = firebase.database().ref('users/' + cid); + userRef.on('value', function(data) { + + user = data.val(); + + lastMessage = user.lastMessage; + // console.log(lastMessage); + + setChatData(); + setNotifications(); + }); + clearMessages(); @@ -99,13 +113,7 @@ function IASChat(config) { function setChatData() { - userRef = firebase.database().ref('users/' + cid); - userRef.on('value', function(data) { - - var key = data.key; - var user = data.val(); - - lastMessage = user.lastMessage; + if(user) { var printData = { name: defaultSupportName, @@ -124,8 +132,9 @@ function IASChat(config) { document.getElementById('ias_topbar-text').innerHTML = printData.name; document.getElementById('ias_topbar-pic').firstChild.setAttribute('src', printData.pic); - }); - + } else { + setTimeout(setChatData, 100); + } } @@ -225,7 +234,7 @@ function IASChat(config) { var text = e.srcElement.children[1].value if(text === '' && attatchment === null) { - console.log('tried to send empty form. Rejected.'); + console.warn('tried to send empty form. Rejected.'); return false; } @@ -325,33 +334,33 @@ function IASChat(config) { } else { printMessage(text, true); - // If chat is open, set the message as read. Else, set a notification ;) - if(isHidden()) { - setNotifications() - } else { + // If chat is open, set the message as read + if(!isHidden()) { readLastMessage(); } } } function readLastMessage() { - console.log('IAS SHOWN, MARK LAST MESSAGE AS READ'); firebase.database().ref('users/' + cid + '/lastMessage').update({read: true}); - setNotifications(); } function setNotifications() { - if(lastMessage.uid !== uid && !lastMessage.read) { - if (showNotifications.classList) { - showNotifications.classList.remove('hidden'); - } else { - showNotifications.className = showNotifications.className.replace(new RegExp('(^|\\b)' + 'hidden'.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); - } - } else { - if (showNotifications.classList) { - showNotifications.classList.add('hidden'); + + // Only set notifications if button are enabled + if(button) { + if(lastMessage.uid !== uid && !lastMessage.read) { + if (showNotifications.classList) { + showNotifications.classList.remove('hidden'); + } else { + showNotifications.className = showNotifications.className.replace(new RegExp('(^|\\b)' + 'hidden'.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); + } } else { - showNotifications.className += ' ' + 'hidden'; + if (showNotifications.classList) { + showNotifications.classList.add('hidden'); + } else { + showNotifications.className += ' ' + 'hidden'; + } } } } From 5cb86dd70ab8ea531d4ef205e3edf5873741077f Mon Sep 17 00:00:00 2001 From: Carlos Hernandez Date: Sat, 11 Mar 2017 18:25:42 +0100 Subject: [PATCH 3/5] Provider notifications working --- dist/provider.js | 17 ++++++++++++++++- js/provider.js | 15 +++++++++++++++ template/ias_provider.html | 9 +++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/dist/provider.js b/dist/provider.js index d60947e..ec7e684 100644 --- a/dist/provider.js +++ b/dist/provider.js @@ -49,7 +49,7 @@ function IASChatProvider(config) { function printInterface(container) { // Compressed version of html/chat.html turned to string - var ias = '

Unassigned Users:

    Your Users:

      ' + var ias = '

      Unassigned Users:

        Your Users:

          ' // Also add the provider styles from css/provider-style.css // ias += ''; @@ -101,10 +101,25 @@ function IASChatProvider(config) { var supporter = data.supporter.uid || data.supporter; + var read = true; + + if(typeof data.lastMessage !== 'undefined' && typeof data.lastMessage.read !== 'undefined' && !data.lastMessage.read) { + read = false; + } + var user = document.createElement('li'); user.setAttribute("data-cid", data.uid); user.setAttribute("data-supporter", supporter); + + if(read) { user.innerHTML = '
          ' + data.name + '
          '; + } else { + var message = data.lastMessage.text; + if(data.lastMessage.text.length > 20) + message = data.lastMessage.text.slice(0, 20) + '...'; + + user.innerHTML = '
          ' + data.name + '
          ' + message + '
          '; + } user.addEventListener('click', usersChatManagement, false); diff --git a/js/provider.js b/js/provider.js index 297e5ee..2012049 100644 --- a/js/provider.js +++ b/js/provider.js @@ -101,10 +101,25 @@ function IASChatProvider(config) { var supporter = data.supporter.uid || data.supporter; + var read = true; + + if(typeof data.lastMessage !== 'undefined' && typeof data.lastMessage.read !== 'undefined' && !data.lastMessage.read) { + read = false; + } + var user = document.createElement('li'); user.setAttribute("data-cid", data.uid); user.setAttribute("data-supporter", supporter); + + if(read) { user.innerHTML = '
          ' + data.name + '
          '; + } else { + var message = data.lastMessage.text; + if(data.lastMessage.text.length > 20) + message = data.lastMessage.text.slice(0, 20) + '...'; + + user.innerHTML = '
          ' + data.name + '
          ' + message + '
          '; + } user.addEventListener('click', usersChatManagement, false); diff --git a/template/ias_provider.html b/template/ias_provider.html index 78a12e9..3153c4c 100644 --- a/template/ias_provider.html +++ b/template/ias_provider.html @@ -21,6 +21,15 @@

          Your Users:

          padding: 0; } + .iasProvider_users-chat-unread { + font-weight: bold; + } + + .iasProvider_users-chat-message { + font-weight: lighter; + font-family: .8em; + } + .iasProvider_users-chat li div { display: inline-block; vertical-align: middle; From e0d26f778168603d0ba8bcb38247b8d1a7243824 Mon Sep 17 00:00:00 2001 From: Carlos Hernandez Date: Sat, 11 Mar 2017 18:55:26 +0100 Subject: [PATCH 4/5] Add first callbacks Related to issue #17 Still sending ALL received messages, not only new ones, but also old messages, yours as sent --- README.md | 2 ++ demo/index.html | 16 +++++++++++++++- dist/chat.js | 9 +++++++++ js/chat.js | 9 +++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ee79efa..69cd5ed 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,8 @@ To configure the chat, just use the object passed on IASChat instantiation. *Bol - defaultSupportPic: String Default support picture (if no supporter assigned) - uploadFiles: Boolean Enable or disable the option to upload and send files (Default: true) - onlyPictures: Boolean Allow only pictures, or all file types (Default: true) + - onMessage: Function Execute a function on message recieved. Params message (all object) and key are passed to the function + - onSend: Function Execute a function when a message is sent. Params message (all object) and key are passed to the function In IASChatProvider, there are some extra features: - container: String Container for support panel (*#identifier* or *.className*. Default: *body*) diff --git a/demo/index.html b/demo/index.html index 0edf122..0b822a1 100644 --- a/demo/index.html +++ b/demo/index.html @@ -61,8 +61,22 @@

          User side support

          mainColor: '#ff9800', textColor: '#fff', defaultSupportName: 'John Doe', - defaultSupportPic: 'http://lorempixel.com/100/100/people' + defaultSupportPic: 'http://lorempixel.com/100/100/people', + onMessage: myFunction, + onSend: function(msg, key) { + console.log('Sent message. Id stored: ' + key); + console.log(msg) + } }); + + function myFunction(message, key) { + console.log('--------------------'); + console.log('- We got a message!'); + console.log(message); + console.log('- key:'); + console.log(key); + console.log('--------------------'); + } }; diff --git a/dist/chat.js b/dist/chat.js index 0641c72..c02df18 100644 --- a/dist/chat.js +++ b/dist/chat.js @@ -21,6 +21,8 @@ function IASChat(config) { var hashSign = config.hashSign || '?'; var uploadFiles = config.uploadFiles || true; var onlyPictures = config.onlyPictures || true; + var onSend = config.onSend || null; + var onMessage = config.onMessage || null; // Prepare interface printInterface(container); @@ -331,6 +333,9 @@ function IASChat(config) { if(message.uid == uid) { printMessage(text); + if(typeof onSend === 'function') { + onSend(message, key); + } } else { printMessage(text, true); @@ -338,6 +343,10 @@ function IASChat(config) { if(!isHidden()) { readLastMessage(); } + + if(typeof onMessage === 'function') { + onMessage(message, key); + } } } diff --git a/js/chat.js b/js/chat.js index 4fe1bca..338f0ee 100644 --- a/js/chat.js +++ b/js/chat.js @@ -21,6 +21,8 @@ function IASChat(config) { var hashSign = config.hashSign || '?'; var uploadFiles = config.uploadFiles || true; var onlyPictures = config.onlyPictures || true; + var onSend = config.onSend || null; + var onMessage = config.onMessage || null; // Prepare interface printInterface(container); @@ -331,6 +333,9 @@ function IASChat(config) { if(message.uid == uid) { printMessage(text); + if(typeof onSend === 'function') { + onSend(message, key); + } } else { printMessage(text, true); @@ -338,6 +343,10 @@ function IASChat(config) { if(!isHidden()) { readLastMessage(); } + + if(typeof onMessage === 'function') { + onMessage(message, key); + } } } From 0b774cff6c35b40eb51a6e235a80bf8fc1496047 Mon Sep 17 00:00:00 2001 From: Carlos Hernandez Date: Sat, 11 Mar 2017 21:03:21 +0100 Subject: [PATCH 5/5] Avoid initial callback dispatch Only execute callback if message timestamp is newer than lastMessage timestamp. This shall fix #17 --- demo/index.html | 8 ++++---- dist/chat.js | 4 ++-- js/chat.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/demo/index.html b/demo/index.html index 0b822a1..4954338 100644 --- a/demo/index.html +++ b/demo/index.html @@ -64,17 +64,17 @@

          User side support

          defaultSupportPic: 'http://lorempixel.com/100/100/people', onMessage: myFunction, onSend: function(msg, key) { - console.log('Sent message. Id stored: ' + key); + console.log('#################'); + console.log('- Message sent! Key: ' + key); console.log(msg) + console.log('#################'); } }); function myFunction(message, key) { console.log('--------------------'); - console.log('- We got a message!'); + console.log('- We got a message! key: ' + key); console.log(message); - console.log('- key:'); - console.log(key); console.log('--------------------'); } }; diff --git a/dist/chat.js b/dist/chat.js index c02df18..03504ea 100644 --- a/dist/chat.js +++ b/dist/chat.js @@ -333,7 +333,7 @@ function IASChat(config) { if(message.uid == uid) { printMessage(text); - if(typeof onSend === 'function') { + if(typeof onSend === 'function' && message.timestamp > lastMessage.timestamp) { onSend(message, key); } } else { @@ -344,7 +344,7 @@ function IASChat(config) { readLastMessage(); } - if(typeof onMessage === 'function') { + if(typeof onMessage === 'function' && message.timestamp > lastMessage.timestamp) { onMessage(message, key); } } diff --git a/js/chat.js b/js/chat.js index 338f0ee..a7f7c75 100644 --- a/js/chat.js +++ b/js/chat.js @@ -333,7 +333,7 @@ function IASChat(config) { if(message.uid == uid) { printMessage(text); - if(typeof onSend === 'function') { + if(typeof onSend === 'function' && message.timestamp > lastMessage.timestamp) { onSend(message, key); } } else { @@ -344,7 +344,7 @@ function IASChat(config) { readLastMessage(); } - if(typeof onMessage === 'function') { + if(typeof onMessage === 'function' && message.timestamp > lastMessage.timestamp) { onMessage(message, key); } }