Commit 02a627c7 authored by Sébastien Blin's avatar Sébastien Blin Committed by Philippe Gorley
Browse files

chatview: support drag-and-drop for sending files



Add the ability to send files by dragging a file uri into the
chatview.

Note: clean some warnings

Change-Id: Ia27663e9544462fa897c27d53dfaa274839d23c4
Reviewed-by: Philippe Gorley's avatarPhilippe Gorley <philippe.gorley@savoirfairelinux.com>
parent b95686c2
......@@ -66,6 +66,7 @@ struct _ChatViewPrivate
gulong webkit_ready;
gulong webkit_send_text;
gulong webkit_drag_drop;
};
G_DEFINE_TYPE_WITH_PRIVATE(ChatView, chat_view, GTK_TYPE_BOX);
......@@ -102,6 +103,8 @@ chat_view_dispose(GObject *object)
priv->webkit_ready = 0;
g_signal_handler_disconnect(priv->webkit_chat_container, priv->webkit_send_text);
priv->webkit_send_text = 0;
g_signal_handler_disconnect(priv->webkit_chat_container, priv->webkit_drag_drop);
priv->webkit_drag_drop = 0;
gtk_container_remove(
GTK_CONTAINER(priv->box_webkit_chat_container),
......@@ -205,7 +208,7 @@ webkit_chat_container_script_dialog(GtkWidget* webview, gchar *interaction, Chat
auto contactUri = priv->conversation_->participants.front();
auto& contact = (*priv->accountInfo_)->contactModel->getContact(contactUri);
(*priv->accountInfo_)->contactModel->addContact(contact);
} catch (std::out_of_range) {
} catch (std::out_of_range&) {
g_debug("webkit_chat_container_script_dialog: oor while retrieving invalid contact info. Chatview bug ?");
}
} else if (order.find("PLACE_CALL") == 0) {
......@@ -521,6 +524,31 @@ update_chatview_frame(ChatView* self)
bestName);
}
static void
on_webkit_drag_drop(GtkWidget*, gchar* data, ChatView* self)
{
g_return_if_fail(IS_CHAT_VIEW(self));
ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
if (!priv->conversation_) return;
if (!data) return;
std::string data_str = data;
// Only take files
if (data_str.find("file://") != 0) return;
if (data_str.find("\r\n") == std::string::npos) return;
const auto LEN_URI = std::string("file://").length();
const auto LEN_END = std::string("\r\n").length();
if (data_str.length() > LEN_URI + LEN_END) {
// remove file and \r\n from the string
data_str = data_str.substr(LEN_URI, data_str.length() - LEN_URI - LEN_END);
}
if (auto model = (*priv->accountInfo_)->conversationModel.get()) {
model->sendFile(priv->conversation_->uid, data_str, g_path_get_basename(data_str.c_str()));
}
}
static void
build_chat_view(ChatView* self)
{
......@@ -543,6 +571,13 @@ build_chat_view(ChatView* self)
G_CALLBACK(webkit_chat_container_script_dialog),
self);
priv->webkit_drag_drop = g_signal_connect(
priv->webkit_chat_container,
"data-dropped",
G_CALLBACK(on_webkit_drag_drop),
self
);
if (webkit_chat_container_is_ready(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)))
webkit_chat_container_ready(self);
}
......@@ -567,8 +602,6 @@ void
chat_view_update_temporary(ChatView* self, bool showAddButton, bool showInvitation)
{
g_return_if_fail(IS_CHAT_VIEW(self));
auto priv = CHAT_VIEW_GET_PRIVATE(self);
update_chatview_frame(self);
}
......
......@@ -55,6 +55,7 @@ struct _WebKitChatContainerPrivate
GtkWidget* box_webview_chat;
bool chatview_debug;
gchar* data_received;
/* Array of javascript libraries to load. Used during initialization */
GList* js_libs_to_load;
......@@ -69,6 +70,7 @@ G_DEFINE_TYPE_WITH_PRIVATE(WebKitChatContainer, webkit_chat_container, GTK_TYPE_
enum {
READY,
SCRIPT_DIALOG,
DATA_DROPPED,
LAST_SIGNAL
};
......@@ -117,6 +119,15 @@ webkit_chat_container_class_init(WebKitChatContainerClass *klass)
nullptr,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
webkit_chat_container_signals[DATA_DROPPED] = g_signal_new("data-dropped",
G_TYPE_FROM_CLASS(klass),
(GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED),
0,
nullptr,
nullptr,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
}
static gboolean
......@@ -419,6 +430,39 @@ webview_chat_load_changed(WebKitWebView *webview_chat,
}
}
static void
webview_chat_on_drag_data_received(GtkWidget*,
GdkDragContext*,
gint,
gint,
GtkSelectionData *data,
guint,
guint32,
WebKitChatContainer* self)
{
g_return_if_fail(IS_WEBKIT_CHAT_CONTAINER(self));
WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(self);
auto* filename = (gchar*)(gtk_selection_data_get_data(data));
if (filename) {
priv->data_received = g_strdup_printf("%s", filename);
}
}
static gboolean
webview_chat_on_drag_data(GtkWidget*,
GdkDragContext*,
gint,
gint,
guint,
WebKitChatContainer* self)
{
g_return_val_if_fail(IS_WEBKIT_CHAT_CONTAINER(self), true);
WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(self);
g_signal_emit(G_OBJECT(self), webkit_chat_container_signals[DATA_DROPPED], 0, priv->data_received);
return true;
}
static void
build_view(WebKitChatContainer *view)
{
......@@ -477,7 +521,8 @@ build_view(WebKitChatContainer *view)
/* Set the WebKitSettings */
webkit_web_view_set_settings(WEBKIT_WEB_VIEW(priv->webview_chat), webkit_settings);
gtk_drag_dest_unset(priv->webview_chat); // remove drag and drop to prevent unwanted reloading
g_signal_connect(priv->webview_chat, "drag-data-received", G_CALLBACK(webview_chat_on_drag_data_received), view);
g_signal_connect(priv->webview_chat, "drag-drop", G_CALLBACK(webview_chat_on_drag_data), view);
g_signal_connect(priv->webview_chat, "load-changed", G_CALLBACK(webview_chat_load_changed), view);
g_signal_connect_swapped(priv->webview_chat, "context-menu", G_CALLBACK(webview_chat_context_menu), view);
g_signal_connect_swapped(priv->webview_chat, "script-dialog", G_CALLBACK(webview_script_dialog), view);
......@@ -637,7 +682,7 @@ webkit_chat_container_remove_interaction(WebKitChatContainer *view, uint64_t int
{
WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
gchar* function_call = g_strdup_printf("removeInteraction(%i);", interactionId);
gchar* function_call = g_strdup_printf("removeInteraction(%lu);", interactionId);
webkit_web_view_run_javascript(
WEBKIT_WEB_VIEW(priv->webview_chat),
function_call,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment