Commit 5b137bea authored by Guillaume Roguez's avatar Guillaume Roguez Committed by Philippe Gorley
Browse files

chatview: Add data transfer support



Add the ability to send and receives files via the chatview.

Change-Id: I529b3e1c75030c3bc2c5e535e9e9584dde9bb4cb
Reviewed-by: Philippe Gorley's avatarPhilippe Gorley <philippe.gorley@savoirfairelinux.com>
parent 1140f871
......@@ -25,6 +25,9 @@
// std
#include <algorithm>
// GTK
#include <glib/gi18n.h>
// LRC
#include <api/contactmodel.h>
#include <api/conversationmodel.h>
......@@ -160,6 +163,34 @@ button_add_to_conversations_clicked(ChatView *self)
priv->accountContainer_->info.conversationModel->makePermanent(priv->conversation_->uid);
}
static gchar*
file_to_manipulate(GtkWindow* top_window, bool send)
{
GtkWidget* dialog;
GtkFileChooserAction action = send? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE;
gint res;
gchar* filename = nullptr;
dialog = gtk_file_chooser_dialog_new(send? _("Send File") : _("Save File"),
top_window,
action,
_("_Cancel"),
GTK_RESPONSE_CANCEL,
send? _("_Open"): _("_Save"),
GTK_RESPONSE_ACCEPT,
nullptr);
res = gtk_dialog_run (GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
auto chooser = GTK_FILE_CHOOSER(dialog);
filename = gtk_file_chooser_get_filename(chooser);
}
gtk_widget_destroy (dialog);
return filename;
}
static void
webkit_chat_container_script_dialog(G_GNUC_UNUSED GtkWidget* webview, gchar *interaction, ChatView* self)
{
......@@ -176,6 +207,42 @@ webkit_chat_container_script_dialog(G_GNUC_UNUSED GtkWidget* webview, gchar *int
// Get text body
auto toSend = order.substr(std::string("SEND:").size());
priv->accountContainer_->info.conversationModel->sendMessage(priv->conversation_->uid, toSend);
} else if (order.find("SEND_FILE") == 0) {
if (auto model = priv->accountContainer_->info.conversationModel.get()) {
if (auto filename = file_to_manipulate(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(self))), true))
model->sendFile(priv->conversation_->uid, filename, g_path_get_basename(filename));
}
} else if (order.find("ACCEPT_FILE:") == 0) {
if (auto model = priv->accountContainer_->info.conversationModel.get()) {
try {
auto interactionId = std::stoull(order.substr(std::string("ACCEPT_FILE:").size()));
if (auto filename = file_to_manipulate(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(self))), false))
model->acceptTransfer(priv->conversation_->uid, interactionId, filename);
else
model->cancelTransfer(priv->conversation_->uid, interactionId);
} catch (...) {
// ignore
}
}
} else if (order.find("REFUSE_FILE:") == 0) {
if (auto model = priv->accountContainer_->info.conversationModel.get()) {
try {
auto interactionId = std::stoull(order.substr(std::string("REFUSE_FILE:").size()));
model->cancelTransfer(priv->conversation_->uid, interactionId);
} catch (...) {
// ignore
}
}
} else if (order.find("OPEN_FILE:") == 0) {
// Get text body
auto filename {"file://" + order.substr(std::string("OPEN_FILE:").size())};
filename.erase(std::find_if(filename.rbegin(), filename.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), filename.end());
GError* error = nullptr;
if (!gtk_show_uri(nullptr, filename.c_str(), GDK_CURRENT_TIME, &error)) {
g_debug("Could not open file: %s", error->message);
g_error_free(error);
}
}
}
......@@ -242,6 +309,7 @@ print_interaction_to_buffer(ChatView* self, uint64_t interactionId, const lrc::a
webkit_chat_container_print_new_interaction(
WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
*priv->accountContainer_->info.conversationModel,
interactionId,
interaction
);
......@@ -253,6 +321,7 @@ update_interaction(ChatView* self, uint64_t interactionId, const lrc::api::inter
ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
webkit_chat_container_update_interaction(
WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
*priv->accountContainer_->info.conversationModel,
interactionId,
interaction
);
......@@ -299,6 +368,7 @@ print_text_recording(ChatView *self)
if (!priv->conversation_) return;
webkit_chat_container_print_history(
WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
*priv->accountContainer_->info.conversationModel,
priv->conversation_->interactions
);
......
......@@ -1001,7 +1001,7 @@ CppImpl::refreshAccountSelectorWidget(int selection_row, bool show)
gtk_combo_box_set_model(
GTK_COMBO_BOX(widgets->combobox_account_selector),
GTK_TREE_MODEL (store)
GTK_TREE_MODEL(store)
);
gtk_combo_box_set_active(GTK_COMBO_BOX(widgets->combobox_account_selector), selection_row);
gtk_widget_set_visible(widgets->combobox_account_selector, show && enabled_accounts > 1);
......
......@@ -31,6 +31,7 @@
// LRC
#include <globalinstances.h>
#include <api/conversationmodel.h>
// Ring Client
#include "native/pixbufmanipulator.h"
......@@ -142,7 +143,9 @@ webview_chat_context_menu(G_GNUC_UNUSED WebKitChatContainer *self,
}
QJsonObject
build_interaction_json(const uint64_t msgId, const lrc::api::interaction::Info& interaction)
build_interaction_json(lrc::api::ConversationModel& conversation_model,
const uint64_t msgId,
const lrc::api::interaction::Info& interaction)
{
auto sender = QString(interaction.authorUri.c_str());
auto timestamp = QString::number(interaction.timestamp);
......@@ -155,6 +158,7 @@ build_interaction_json(const uint64_t msgId, const lrc::api::interaction::Info&
interaction_object.insert("sender_contact_method", QJsonValue(sender));
interaction_object.insert("timestamp", QJsonValue(timestamp));
interaction_object.insert("direction", QJsonValue(direction));
switch (interaction.type)
{
case lrc::api::interaction::Type::TEXT:
......@@ -166,11 +170,23 @@ build_interaction_json(const uint64_t msgId, const lrc::api::interaction::Info&
case lrc::api::interaction::Type::CONTACT:
interaction_object.insert("type", QJsonValue("contact"));
break;
case lrc::api::interaction::Type::OUTGOING_DATA_TRANSFER:
case lrc::api::interaction::Type::INCOMING_DATA_TRANSFER: {
interaction_object.insert("type", QJsonValue("data_transfer"));
lrc::api::datatransfer::Info info = {};
conversation_model.getTransferInfo(msgId, info);
if (info.status != lrc::api::datatransfer::Status::INVALID) {
interaction_object.insert("totalSize", QJsonValue(qint64(info.totalSize)));
interaction_object.insert("progress", QJsonValue(qint64(info.progress)));
}
break;
}
case lrc::api::interaction::Type::INVALID:
default:
interaction_object.insert("type", QJsonValue(""));
break;
}
switch (interaction.status)
{
case lrc::api::interaction::Status::READ:
......@@ -180,11 +196,33 @@ build_interaction_json(const uint64_t msgId, const lrc::api::interaction::Info&
interaction_object.insert("delivery_status", QJsonValue("sent"));
break;
case lrc::api::interaction::Status::FAILED:
case lrc::api::interaction::Status::TRANSFER_ERROR:
interaction_object.insert("delivery_status", QJsonValue("failure"));
break;
case lrc::api::interaction::Status::TRANSFER_UNJOINABLE_PEER:
interaction_object.insert("delivery_status", QJsonValue("unjoinable peer"));
break;
case lrc::api::interaction::Status::SENDING:
interaction_object.insert("delivery_status", QJsonValue("sending"));
break;
case lrc::api::interaction::Status::TRANSFER_CREATED:
interaction_object.insert("delivery_status", QJsonValue("connecting"));
break;
case lrc::api::interaction::Status::TRANSFER_ACCEPTED:
interaction_object.insert("delivery_status", QJsonValue("accepted"));
break;
case lrc::api::interaction::Status::TRANSFER_CANCELED:
interaction_object.insert("delivery_status", QJsonValue("canceled"));
break;
case lrc::api::interaction::Status::TRANSFER_ONGOING:
interaction_object.insert("delivery_status", QJsonValue("ongoing"));
break;
case lrc::api::interaction::Status::TRANSFER_AWAITING:
interaction_object.insert("delivery_status", QJsonValue("awaiting"));
break;
case lrc::api::interaction::Status::TRANSFER_FINISHED:
interaction_object.insert("delivery_status", QJsonValue("finished"));
break;
case lrc::api::interaction::Status::INVALID:
case lrc::api::interaction::Status::UNKNOWN:
case lrc::api::interaction::Status::UNREAD:
......@@ -196,17 +234,20 @@ build_interaction_json(const uint64_t msgId, const lrc::api::interaction::Info&
}
QString
interaction_to_json_interaction_object(const uint64_t msgId, const lrc::api::interaction::Info& interaction)
interaction_to_json_interaction_object(lrc::api::ConversationModel& conversation_model,
const uint64_t msgId,
const lrc::api::interaction::Info& interaction)
{
auto interaction_object = build_interaction_json(msgId, interaction);
auto interaction_object = build_interaction_json(conversation_model, msgId, interaction);
return QString(QJsonDocument(interaction_object).toJson(QJsonDocument::Compact));
}
QString
interactions_to_json_array_object(const std::map<uint64_t, lrc::api::interaction::Info> interactions) {
interactions_to_json_array_object(lrc::api::ConversationModel& conversation_model,
const std::map<uint64_t, lrc::api::interaction::Info> interactions) {
QJsonArray array;
for (const auto& interaction: interactions)
array.append(build_interaction_json(interaction.first, interaction.second));
array.append(build_interaction_json(conversation_model, interaction.first, interaction.second));
return QString(QJsonDocument(array).toJson(QJsonDocument::Compact));
}
......@@ -551,12 +592,13 @@ webkit_chat_container_clear(WebKitChatContainer *view)
void
webkit_chat_container_update_interaction(WebKitChatContainer *view,
lrc::api::ConversationModel& conversation_model,
uint64_t msgId,
const lrc::api::interaction::Info& interaction)
{
WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
auto interaction_object = interaction_to_json_interaction_object(msgId, interaction).toUtf8();
auto interaction_object = interaction_to_json_interaction_object(conversation_model, msgId, interaction).toUtf8();
gchar* function_call = g_strdup_printf("ring.chatview.updateMessage(%s);", interaction_object.constData());
webkit_web_view_run_javascript(
WEBKIT_WEB_VIEW(priv->webview_chat),
......@@ -570,12 +612,13 @@ webkit_chat_container_update_interaction(WebKitChatContainer *view,
void
webkit_chat_container_print_new_interaction(WebKitChatContainer *view,
lrc::api::ConversationModel& conversation_model,
uint64_t msgId,
const lrc::api::interaction::Info& interaction)
{
WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
auto interaction_object = interaction_to_json_interaction_object(msgId, interaction).toUtf8();
auto interaction_object = interaction_to_json_interaction_object(conversation_model, msgId, interaction).toUtf8();
gchar* function_call = g_strdup_printf("ring.chatview.addMessage(%s);", interaction_object.constData());
webkit_web_view_run_javascript(
WEBKIT_WEB_VIEW(priv->webview_chat),
......@@ -588,11 +631,13 @@ webkit_chat_container_print_new_interaction(WebKitChatContainer *view,
}
void
webkit_chat_container_print_history(WebKitChatContainer *view, const std::map<uint64_t, lrc::api::interaction::Info> interactions)
webkit_chat_container_print_history(WebKitChatContainer *view,
lrc::api::ConversationModel& conversation_model,
const std::map<uint64_t, lrc::api::interaction::Info> interactions)
{
WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
auto interactions_str = interactions_to_json_array_object(interactions).toUtf8();
auto interactions_str = interactions_to_json_array_object(conversation_model, interactions).toUtf8();
gchar* function_call = g_strdup_printf("ring.chatview.printHistory(%s)", interactions_str.constData());
webkit_web_view_run_javascript(
WEBKIT_WEB_VIEW(priv->webview_chat),
......
......@@ -27,6 +27,10 @@
// LRC
#include <api/interaction.h>
namespace lrc { namespace api {
class ConversationModel;
}};
G_BEGIN_DECLS
#define WEBKIT_CHAT_CONTAINER_TYPE (webkit_chat_container_get_type ())
......@@ -42,9 +46,9 @@ GType webkit_chat_container_get_type (void) G_GNUC_CONST;
GtkWidget* webkit_chat_container_new (void);
void webkit_chat_container_clear (WebKitChatContainer *view);
void webkit_chat_container_clear_sender_images (WebKitChatContainer *view);
void webkit_chat_container_print_new_interaction(WebKitChatContainer *view, uint64_t msgId, const lrc::api::interaction::Info& interaction);
void webkit_chat_container_print_history (WebKitChatContainer *view, const std::map<uint64_t, lrc::api::interaction::Info> interactions);
void webkit_chat_container_update_interaction (WebKitChatContainer *view, uint64_t msgId, const lrc::api::interaction::Info& interaction);
void webkit_chat_container_print_new_interaction(WebKitChatContainer *view, lrc::api::ConversationModel& conversation_model, uint64_t msgId, const lrc::api::interaction::Info& interaction);
void webkit_chat_container_update_interaction (WebKitChatContainer *view, lrc::api::ConversationModel& conversation_model, uint64_t msgId, const lrc::api::interaction::Info& interaction);
void webkit_chat_container_print_history (WebKitChatContainer *view, lrc::api::ConversationModel& conversation_model, const std::map<uint64_t, lrc::api::interaction::Info> interactions);
void webkit_chat_container_set_sender_image (WebKitChatContainer *view, const std::string& sender, const std::string& senderImage);
gboolean webkit_chat_container_is_ready (WebKitChatContainer *view);
void webkit_chat_container_set_display_links (WebKitChatContainer *view, bool display);
......
......@@ -32,7 +32,6 @@ body {
color: white;
padding: 10px 20px 10px 20px;
vertical-align: middle;
}
.button-green {
......@@ -169,7 +168,7 @@ input[placeholder], [placeholder], *[placeholder] {
color: #d3d3d3;
}
#sendBtn {
.msg-button {
border-radius: 50%;
border: 0;
width: 40px;
......@@ -178,13 +177,13 @@ input[placeholder], [placeholder], *[placeholder] {
transition: all 0.3s ease;
}
#sendBtn.hover,
#sendBtn:hover {
.msg-button.hover,
.msg-button:hover {
background: #bae5f0;
}
#sendBtn.hover svg,
#sendBtn:hover svg {
.msg-button.hover svg,
.msg-button:hover svg {
fill: black;
}
......@@ -502,26 +501,34 @@ pre {
width: 100%;
}
.message_type_data_transfer .message_timestamp,
.message_type_data_transfer .message_delivery_status,
.message_type_data_transfer .sent-checkmark,
.message_type_call .sent-checkmark,
.message_type_call .message_sender,
.message_type_call .message_delivery_status,
.message_type_call .message_timestamp,
.message_type_call .message_sender_image,
.message_type_call .message_progress_bar,
.message_type_contact .sent-checkmark,
.message_type_contact .message_sender,
.message_type_contact .message_delivery_status,
.message_type_contact .message_timestamp,
.message_type_contact .message_sender_image {
.message_type_contact .message_sender_image,
.message_type_contact .message_progress_bar,
.message_type_text .message_progress_bar {
visibility: hidden;
display: none;
}
.message_type_contact .message_wrapper:before,
.message_type_data_transfer .message_wrapper:before,
.message_type_call .message_wrapper:before {
display: none;
}
.message_type_call .message_wrapper:after,
.message_type_data_transfer .message_wrapper:after,
.message_type_contact .message_wrapper:after {
display: none;
}
......@@ -561,3 +568,63 @@ pre {
color: red;
font-size: 1.25em;
}
.message_type_data_transfer .message_wrapper
{
padding: 0;
width: 30%;
display: flex;
flex-wrap: wrap;
}
.message_type_data_transfer #left_buttons
{
width: 25%;
display: flex;
padding-left: 5px;
overflow: hidden;
}
.message_type_data_transfer #text
{
width: 70%;
text-align: center;
padding-top: 14px;
margin-bottom: 12px;
}
.message_type_data_transfer #filename
{
font-weight: bold;
overflow: hidden;
}
.message_type_data_transfer #informations
{
color: #555;
font-size: 0.8em;
}
.message_progress_bar {
margin-top: 12px;
width: 100%;
height: 12px;
position: relative;
overflow: hidden;
background-color: #eee;
border-radius: 2px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset;
}
.message_progress_bar > span {
display: inline;
height: 100%;
background-color: #01a2b8;
position: absolute;
overflow: hidden;
}
.message_type_data_transfer .flat-button
{
padding: 0;
}
......@@ -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 @@ ring.chatview = (function(){
}
}
/**
* 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 @@ ring.chatview = (function(){
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 @@ ring.chatview = (function(){
}
}
/**
* 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);