/dev/tomkiewicz/new-smileys: 222e69060b4a: Remote smileys: displ...

Tomasz Wasilczyk twasilczyk at pidgin.im
Fri Apr 4 14:30:17 EDT 2014


Changeset: 222e69060b4a3a10fa1b8f29b25d35df6409ffcd
Author:	 Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date:	 2014-04-04 20:30 +0200
Branch:	 default
URL: https://hg.pidgin.im/dev/tomkiewicz/new-smileys/rev/222e69060b4a

Description:

Remote smileys: display them even on the first time

diffstat:

 libpurple/conversation.c    |   3 ++
 libpurple/smiley-remote.c   |  14 +++++++----
 pidgin/gtkconv.c            |  56 ++++++++++++++++++++++++++++++++++++++++++--
 pidgin/themes/Template.html |  27 ++++++++++++++++++++-
 4 files changed, 90 insertions(+), 10 deletions(-)

diffs (177 lines):

diff --git a/libpurple/conversation.c b/libpurple/conversation.c
--- a/libpurple/conversation.c
+++ b/libpurple/conversation.c
@@ -965,6 +965,9 @@ purple_conversation_add_remote_smiley(Pu
 		return NULL;
 	}
 
+	/* TODO: connect to the failed signal, to make it possible returning this smiley object again (later). Maybe just remove from the list on fail */
+	/* TODO: test it by doing failed on the first retrieval, succ on the second */
+
 	/* smiley was already added */
 	if (smiley)
 		return NULL;
diff --git a/libpurple/smiley-remote.c b/libpurple/smiley-remote.c
--- a/libpurple/smiley-remote.c
+++ b/libpurple/smiley-remote.c
@@ -42,18 +42,18 @@ enum
 	PROP_0,
 	PROP_LAST
 };
+#endif
 
 enum
 {
-	SIG_READY,
+	SIG_FAILED,
 	SIG_LAST
 };
-#endif
 
 static GObjectClass *parent_class;
 
+static guint signals[SIG_LAST];
 #if 0
-static guint signals[SIG_LAST];
 static GParamSpec *properties[PROP_LAST];
 #endif
 
@@ -104,7 +104,7 @@ purple_remote_smiley_close(PurpleRemoteS
 	priv->contents = NULL;
 
 	g_object_set(smiley, "is-ready", TRUE, NULL);
-	/* TODO: call ready signal */
+	g_signal_emit_by_name(smiley, "ready");
 }
 
 void
@@ -120,7 +120,7 @@ purple_remote_smiley_failed(PurpleRemote
 		return;
 
 	g_object_set(smiley, "failed", TRUE, NULL);
-	/* TODO: call failed signal */
+	g_signal_emit(smiley, signals[SIG_FAILED], 0);
 }
 
 static PurpleStoredImage *
@@ -222,6 +222,10 @@ purple_remote_smiley_class_init(PurpleRe
 
 	g_object_class_install_properties(gobj_class, PROP_LAST, properties);
 #endif
+
+	signals[SIG_FAILED] = g_signal_new("failed", G_OBJECT_CLASS_TYPE(klass),
+		0, 0, NULL, NULL,
+		g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 }
 
 GType
diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c
--- a/pidgin/gtkconv.c
+++ b/pidgin/gtkconv.c
@@ -6582,6 +6582,53 @@ replace_message_tokens(
 	return g_string_free(str, FALSE);
 }
 
+static gulong
+pidgin_smiley_get_unique_id(PurpleSmiley *smiley)
+{
+	static gulong max_id = 0;
+	gulong id;
+	g_return_val_if_fail(smiley != NULL, 0);
+
+	id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(smiley),
+		"pidgin-conv-smiley-unique-id"));
+	if (id != 0)
+		return id;
+
+	id = ++max_id;
+
+	g_object_set_data(G_OBJECT(smiley), "pidgin-conv-smiley-unique-id",
+		GINT_TO_POINTER(id));
+
+	return id;
+}
+
+static void
+pidgin_conv_remote_smiley_got(PurpleSmiley *smiley, gpointer _conv)
+{
+	PurpleConversation *conv = _conv;
+	PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
+	PurpleStoredImage *img;
+	gulong smiley_id;
+	int image_id;
+	gchar *js;
+
+	if (!gtkconv)
+		return;
+
+	img = purple_smiley_get_image(smiley);
+	smiley_id = pidgin_smiley_get_unique_id(smiley);
+	image_id = purple_imgstore_add_with_id(img);
+
+	purple_debug_info("gtkconv", "Smiley '%s' (%ld) is ready for display",
+		purple_smiley_get_shortcut(smiley), smiley_id);
+
+	js = g_strdup_printf("emoticonIsReady(%ld, '"
+		PURPLE_STORED_IMAGE_PROTOCOL "%d')", smiley_id, image_id);
+	pidgin_webview_safe_execute_script(
+		PIDGIN_WEBVIEW(gtkconv->webview), js);
+	g_free(js);
+}
+
 static void
 pidgin_conv_write_smiley(GString *out, PurpleSmiley *smiley,
 	PurpleConversation *conv, gpointer _proto_name)
@@ -6606,9 +6653,12 @@ pidgin_conv_write_smiley(GString *out, P
 			PURPLE_STORED_IMAGE_PROTOCOL "%d\" />",
 			escaped_shortcut, escaped_shortcut, imgid);
 	} else {
-		g_string_append_printf(out,
-			"<span class=\"emoticon pending\">%s</span>",
-			escaped_shortcut);
+		g_string_append_printf(out, "<span class=\"emoticon pending "
+			"emoticon-id-%ld\">%s</span>",
+			pidgin_smiley_get_unique_id(smiley), escaped_shortcut);
+		g_signal_connect_object(smiley, "ready",
+			G_CALLBACK(pidgin_conv_remote_smiley_got), conv, 0);
+
 		/* TODO: watch for "is-ready" state changes
 		 * (it's not possible without conv handle here) */
 		/* XXX: avoid race condition between is-ready
diff --git a/pidgin/themes/Template.html b/pidgin/themes/Template.html
--- a/pidgin/themes/Template.html
+++ b/pidgin/themes/Template.html
@@ -236,8 +236,31 @@
 
 		//If true is passed, view will be scrolled down
 		function alignChat(shouldScroll) {
-			if (shouldScroll)
-				scrollToBottom();
+			if (!shouldScroll)
+				return;
+
+			scrollToBottom();
+			/* wait for images to load and scroll again */
+			setTimeout(scrollToBottom, 10);
+		}
+
+		function emoticonIsReady(emoticonId, url) {
+			var shouldScroll = nearBottom();
+			var emoticons;
+
+			emoticons = document.getElementsByClassName('emoticon-id-' + emoticonId);
+			for (var i = 0; i < emoticons.length; i++) {
+				var node = emoticons[i];
+				var img = document.createElement('img');
+				var alt = node.textContent.trim();
+				img.setAttribute('src', url);
+				img.setAttribute('alt', alt);
+				img.setAttribute('title', alt);
+				img.className = 'emoticon';
+				node.parentNode.replaceChild(img, node);
+			}
+
+			alignChat(shouldScroll);
 		}
 
 		window.onresize = function windowDidResize(){



More information about the Commits mailing list