chatview: Add data transfer support
Add the ability to send and receives files via the chatview.
Change-Id: I529b3e1c75030c3bc2c5e535e9e9584dde9bb4cb
Reviewed-by: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
diff --git a/web/chatview.html b/web/chatview.html
index 435ac79..721457e 100644
--- a/web/chatview.html
+++ b/web/chatview.html
@@ -20,11 +20,17 @@
<div id="sendMessage">
<textarea id="message" autofocus placeholder="Message" onkeyup="grow_text_area()" rows="1" disabled="false"></textarea>
- <div id="sendBtn" onclick="ring.chatview.sendMessage()" title="Send">
+ <div id="sendBtn" class="msg-button" onclick="ring.chatview.sendMessage()" title="Send">
<svg viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
<path xmlns="http://www.w3.org/2000/svg" d="M12,11.874v4.357l7-6.69l-7-6.572v3.983c-8.775,0-11,9.732-11,9.732C3.484,12.296,7.237,11.874,12,11.874z"/>
</svg>
</div>
+ <div id="send-file-btn" class="msg-button" onclick="ring.chatview.sendFile()" title="Send File">
+ <svg viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
+ <path d="M0 0h24v24H0z" fill="none"/>
+ <path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/>
+ </svg>
+ </div>
</div>
</form>
</div>
@@ -283,22 +289,22 @@
}
}
- /**
- * Returns HTML message from the message text.
- * Cleaned and linkified.
- */
- function getMessageHtml(message_text)
- {
- const escaped_message = escapeHtml(message_text);
- var linkified_message = linkifyHtml(escaped_message, {});
+ /**
+ * Returns HTML message from the message text.
+ * Cleaned and linkified.
+ */
+ function getMessageHtml(message_text)
+ {
+ const escaped_message = escapeHtml(message_text);
+ var linkified_message = linkifyHtml(escaped_message, {});
- const textPart = document.createElement('pre');
- var linkified_message = linkified_message.replace("📞", "<span id=\"green\">📞</span>")
- var linkified_message = linkified_message.replace("🕽", "<span id=\"red\">🕽</span>")
- textPart.innerHTML = linkified_message;
+ const textPart = document.createElement('pre');
+ var linkified_message = linkified_message.replace("📞", "<span id=\"green\">📞</span>")
+ var linkified_message = linkified_message.replace("🕽", "<span id=\"red\">🕽</span>")
+ textPart.innerHTML = linkified_message;
- return textPart.outerHTML;
- }
+ return textPart.outerHTML;
+ }
/**
* Returns the message status, formatted for display
@@ -309,19 +315,17 @@
switch(message_delivery_status)
{
- case "unknown":
- formatted_delivery_status = "";
- break;
case "sending":
- formatted_delivery_status = "Sending<svg overflow='visible' viewBox='0 -2 16 14' height='16px' width='16px'><circle class='status_circle anim-first' cx='4' cy='12' r='1'/><circle class='status_circle anim-second' cx='8' cy='12' r='1'/><circle class='status_circle anim-third' cx='12' cy='12' r='1'/></svg>"
- break;
- case "read":
- formatted_delivery_status = "";
+ case "ongoing":
+ formatted_delivery_status = "Sending<svg overflow='visible' viewBox='0 -2 16 14' height='16px' width='16px'><circle class='status_circle anim-first' cx='4' cy='12' r='1'/><circle class='status_circle anim-second' cx='8' cy='12' r='1'/><circle class='status_circle anim-third' cx='12' cy='12' r='1'/></svg>";
break;
case "failure":
- formatted_delivery_status = "Failure <svg overflow='visible' viewBox='0 -2 16 14' height='16px' width='16px'><path class='status-x x-first' stroke='#AA0000' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' fill='none' d='M4,4 L12,12'/><path class='status-x x-second' stroke='#AA0000' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' fill='none' d='M12,4 L4,12'/></svg>"
+ formatted_delivery_status = "Failure <svg overflow='visible' viewBox='0 -2 16 14' height='16px' width='16px'><path class='status-x x-first' stroke='#AA0000' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' fill='none' d='M4,4 L12,12'/><path class='status-x x-second' stroke='#AA0000' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' fill='none' d='M12,4 L4,12'/></svg>";
break;
case "sent":
+ case "finished":
+ case "unknown":
+ case "read":
formatted_delivery_status = "";
break;
default:
@@ -403,6 +407,115 @@
}
}
+ /**
+ * Convert a value in filesize
+ */
+ function humanFileSize(bytes) {
+ var thresh = 1024;
+ if(Math.abs(bytes) < thresh) {
+ return bytes + ' B';
+ }
+ var units = ['kB','MB','GB','TB','PB','EB','ZB','YB']
+ var u = -1;
+ do {
+ bytes /= thresh;
+ ++u;
+ } while(Math.abs(bytes) >= thresh && u < units.length - 1);
+ return bytes.toFixed(1)+' '+units[u];
+ }
+
+ /**
+ * Change the value of the progress bar
+ */
+ function updateProgressBar(progress_bar, message_object, message_delivery_status) {
+ var delivery_status = message_object["delivery_status"];
+ if ("progress" in message_object && !isErrorStatus(delivery_status) && message_object["progress"] !== 100) {
+ var progress_percent = (100 * message_object["progress"] / message_object["totalSize"]);
+ if (progress_percent !== 100)
+ progress_bar.childNodes[0].setAttribute("style", "width: " + progress_percent + "%");
+ else
+ progress_bar.setAttribute("style", "display: none");
+ } else
+ progress_bar.setAttribute("style", "display: none");
+ }
+
+ /**
+ * Check if a status is an error status
+ */
+ function isErrorStatus(status) {
+ return (status === 'failure'
+ || status === 'canceled'
+ || status === 'unjoinable peer');
+ }
+
+ /**
+ * Update a data transfer interaction
+ */
+ function updateDataTransferInteraction(message_div, message_object) {
+ var acceptSvg = '<svg fill="#ffffff" height="36" viewBox="0 0 24 24" width="36" xmlns="http://www.w3.org/2000/svg" style="width:50%; display:block; margin:auto;"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>',
+ refuseSvg = '<svg fill="#ffffff" height="36" viewBox="0 0 24 24" width="36" xmlns="http://www.w3.org/2000/svg" style="width:50%; display:block; margin:auto;"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/><path d="M0 0h24v24H0z" fill="none"/></svg>',
+ fileSvg = '<svg fill="#000000" height="36" viewBox="0 0 24 24" width="36" xmlns="http://www.w3.org/2000/svg" style="width:50%;"><path d="M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>',
+ warningSvg = '<svg fill="#000000" height="36" viewBox="0 0 24 24" width="36" xmlns="http://www.w3.org/2000/svg" style="width:50%;"><path d="M0 0h24v24H0z" fill="none"/><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>',
+ incomingSvg = '<svg fill="#000000" height="36" viewBox="0 0 24 24" width="36" xmlns="http://www.w3.org/2000/svg" style="width:50%;"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 5.41L18.59 4 7 15.59V9H5v10h10v-2H8.41z"/></svg>',
+ outgoingSvg = '<svg fill="#000000" height="36" viewBox="0 0 24 24" width="36" xmlns="http://www.w3.org/2000/svg" style="width:50%;"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5z"/></svg>';
+ var message_delivery_status = message_object["delivery_status"];
+ var message_direction = message_object["direction"];
+ var message_id = message_object["id"];
+
+ // Set informations text
+ var informations_div = message_div.querySelector("#informations");
+ var informations_txt = getMessageTimestampText(message_object["timestamp"], true);
+ if (message_object["totalSize"] && message_object["progress"]) {
+ if (message_delivery_status === 'finished') {
+ informations_txt += " - " + humanFileSize(message_object["totalSize"]);
+ } else {
+ informations_txt += " - " + humanFileSize(message_object["progress"])
+ + " / " + humanFileSize(message_object["totalSize"]);
+ }
+ }
+ informations_txt += " - " + message_delivery_status;
+ informations_div.innerText = informations_txt;
+
+ // Update flat buttons
+ var left_buttons = message_div.querySelector("#left_buttons");
+ left_buttons.innerHTML = '';
+ if (message_delivery_status === 'awaiting') {
+ // add buttons to accept or refuse a call.
+ var accept_button = document.createElement('div');
+ accept_button.innerHTML = acceptSvg;
+ accept_button.setAttribute("id", "accept-btn");
+ accept_button.setAttribute("title", "Accept");
+ accept_button.setAttribute("class", "flat-button button-green");
+ accept_button.onclick = function() {
+ window.prompt('ACCEPT_FILE:' + message_id);
+ }
+ left_buttons.appendChild(accept_button);
+ var refuse_button = document.createElement('div');
+ refuse_button.innerHTML = refuseSvg;
+ refuse_button.setAttribute("id", "refuse-btn");
+ refuse_button.setAttribute("title", "Refuse");
+ refuse_button.setAttribute("class", "flat-button button-red");
+ refuse_button.onclick = function() {
+ window.prompt('REFUSE_FILE:' + message_id);
+ }
+ left_buttons.appendChild(refuse_button);
+ } else {
+ var status_button = document.createElement('div');
+ var statusFile = fileSvg;
+ if (isErrorStatus(message_delivery_status))
+ statusFile = warningSvg;
+ status_button.innerHTML = statusFile;
+ status_button.setAttribute("class", "flat-button");
+ left_buttons.appendChild(status_button);
+ var direction_button = document.createElement('div');
+ var directionFile = message_direction === 'out' ? outgoingSvg: incomingSvg;
+ direction_button.innerHTML = directionFile;
+ direction_button.setAttribute("class", "flat-button");
+ left_buttons.appendChild(direction_button);
+ }
+ updateProgressBar(chatview_message_transfer_progress_bar, message_object);
+ }
+
/**
* Adds a message to the buffer, or update it if new_message is
* TRUE
@@ -428,10 +541,10 @@
chatview_message_sender_span,
chatview_message_sender_image,
chatview_message_div,
- sentAnimation = "<svg overflow='visible' viewBox='0 -2 16 14' height='16px' width='16px'><path class='status-check' stroke='#008000' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' fill='none' d='M2,8 L6,12 L14,4'/></svg>",
- chatview_sentCheckmark = document.createElement('span');
+ sentAnimation = "<svg overflow='visible' viewBox='0 -2 16 14' height='16px' width='16px'><path class='status-check' stroke='#008000' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' fill='none' d='M2,8 L6,12 L14,4'/></svg>";
- chatview_sentCheckmark.setAttribute("class", "sent-checkmark");
+ var chatview_sentCheckmark = document.createElement('span');
+ chatview_sentCheckmark.setAttribute("class", "sent-checkmark");
chatview_message_div = document.querySelector("#message_" + message_id);
if (new_message)
@@ -449,32 +562,56 @@
chatview_message_wrapper = document.createElement('div');
chatview_message_wrapper.setAttribute("class", "message_wrapper wc");
- chatview_message_text = document.createElement('span');
- chatview_message_text.setAttribute("class", "message_text");
+ if (message_type === 'data_transfer') {
+ var leftbuttons_div = document.createElement('div');
+ leftbuttons_div.setAttribute("id", "left_buttons");
+ chatview_message_wrapper.appendChild(leftbuttons_div);
+
+ var text_div = document.createElement('div');
+ text_div.setAttribute("id", "text");
+ text_div.addEventListener('click', function (event) {
+ // ask the soft to open the file
+ var filename = document.querySelector("#message_" + message_id + " #filename").innerText;
+ window.prompt('OPEN_FILE:' + filename);
+ });
+ chatview_message_text = document.createElement('div');
+ chatview_message_text.setAttribute("id", "filename");
+ var informations_div = document.createElement('div');
+ informations_div.setAttribute("id", "informations");
+ text_div.appendChild(chatview_message_text);
+ text_div.appendChild(informations_div);
+ chatview_message_wrapper.appendChild(text_div);
+
+ // DataTransfer progress bar
+ chatview_message_transfer_progress_bar = document.createElement('span');
+ chatview_message_transfer_progress_bar.setAttribute("class", "message_progress_bar");
+ chatview_message_transfer_progress_completion = document.createElement('span');
+ chatview_message_transfer_progress_bar.appendChild(chatview_message_transfer_progress_completion);
+ chatview_message_wrapper.appendChild(chatview_message_transfer_progress_bar);
+ } else {
+ chatview_message_text = document.createElement('span');
+ chatview_message_text.setAttribute("class", "message_text");
+ chatview_message_wrapper.appendChild(chatview_message_text);
+ chatview_message_delivery_status = document.createElement('span');
+ chatview_message_delivery_status.setAttribute("class", "message_delivery_status");
+ }
+
chatview_message_sender = document.createElement('span');
chatview_message_sender.setAttribute("class", "message_sender");
-
- chatview_message_delivery_status = document.createElement('span');
- chatview_message_delivery_status.setAttribute("class", "message_delivery_status");
-
- chatview_message_timestamp = document.createElement('span');
- chatview_message_timestamp.setAttribute("class", "message_timestamp");
-
- chatview_message_wrapper.appendChild(chatview_message_text);
chatview_message_wrapper.appendChild(chatview_message_sender);
-
- // Sender image
chatview_message_sender_span = document.createElement('span');
chatview_message_sender_span.setAttribute("class", "message_sender_image");
-
chatview_message_sender_image = document.createElement('span');
chatview_message_sender_image.setAttribute("class", "sender_image sender_image_" + message_sender_contact_method);
+ chatview_message_timestamp = document.createElement('span');
+ chatview_message_timestamp.setAttribute("class", "message_timestamp");
// Append elements to div
chatview_message_div.appendChild(chatview_message_sender_image);
chatview_message_div.appendChild(chatview_message_wrapper);
- chatview_message_div.appendChild(chatview_message_delivery_status);
+ if (message_type !== 'data_transfer')
+ chatview_message_div.appendChild(chatview_message_delivery_status);
// Get timestamp to add
const formattedTimestamp = getMessageTimestampText(message_timestamp, true);
@@ -487,7 +624,7 @@
];
date_elt.setAttribute("class", timestamp_div_classes.join(" "));
date_elt.setAttribute("message_timestamp", message_timestamp);
- // Remove last timestamp if it's the same
+ // Remove last timestamp if it's the same<h6></h6>
if (messages.querySelectorAll(".timestamp"))
cleanPreviousTimestamps(date_elt, messages.children.length);
@@ -500,20 +637,17 @@
messages.insertBefore(chatview_message_div, messages.firstChild);
}
} else {
-
- chatview_message_div = document.querySelector("#message_" + message_id);
-
if (chatview_message_div) {
+ if (message_type === 'data_transfer') {
+ chatview_message_text = chatview_message_div.querySelector("#filename");
+ } else {
chatview_message_text = chatview_message_div.querySelector(".message_text");
- chatview_message_sender_image = chatview_message_div.querySelector(".message_sender_image");
- chatview_message_sender = chatview_message_div.querySelector(".message_sender");
chatview_message_delivery_status = chatview_message_div.querySelector(".message_delivery_status");
- chatview_message_timestamp = chatview_message_div.querySelector(".message_timestamp");
-
+ }
+ chatview_message_timestamp = chatview_message_div.querySelector(".message_timestamp");
+ chatview_message_sender = chatview_message_div.querySelector(".message_sender");
} else {
-
console.log('no msg selector.');
-
}
}
@@ -522,20 +656,25 @@
if (new_message && displayLinksEnabled)
displayLinks(chatview_message_text);
chatview_message_sender.textContent = message_sender + ": ";
- chatview_message_delivery_status.innerHTML = getMessageDeliveryStatusText(message_delivery_status);
chatview_message_timestamp.textContent = getMessageTimestampText(message_timestamp);
- if (new_message) {
- if (message_direction === "out") {
- chatview_sentCheckmark.innerHTML = sentAnimation;
- chatview_message_div.querySelector(".message_wrapper").appendChild(chatview_sentCheckmark);
- }
+ if (message_type === 'data_transfer') {
+ updateDataTransferInteraction(chatview_message_div, message_object);
+ } else {
+ chatview_message_delivery_status.innerHTML = getMessageDeliveryStatusText(message_delivery_status);
+ }
- chatview_message_div.querySelector(".message_wrapper").appendChild(chatview_message_timestamp);
+ // Add timestamp and sent checkmark
+ if (new_message) {
+ if (message_direction === "out") {
+ chatview_sentCheckmark.innerHTML = sentAnimation;
+ chatview_message_div.querySelector(".message_wrapper").appendChild(chatview_sentCheckmark);
+ }
+ chatview_message_div.querySelector(".message_wrapper").appendChild(chatview_message_timestamp);
}
if (message_direction === "out") {
- if (message_delivery_status === "sent") {
+ if (message_delivery_status === "sent" || message_delivery_status === "finished") {
chatview_message_div.classList.add("message--sent");
}
}
@@ -678,6 +817,11 @@
}
}
+ function sendFile()
+ {
+ window.prompt('SEND_FILE');
+ }
+
return {
addMessage: addMessage,
printHistory: printHistory,
@@ -696,6 +840,8 @@
showInvitation: showInvitation,
hideInvitation: hideInvitation,
disableSendMessage: disableSendMessage,
+ updateTimestamps: updateTimestamps,
+ sendFile: sendFile,
}
})();