From 7af80d01199378b6bcc6becc1f7756117ecc125e Mon Sep 17 00:00:00 2001 From: foudfou Date: Sun, 7 Apr 2013 16:45:17 +0200 Subject: [PATCH] handle blinking on new messages for twitter accounts No 'new-directed-incoming-message' event is issued on new messages for twitter accounts, which seem to be considered chatrooms (instead of private conversations). --- src/modules/FiretrayChat.jsm | 77 ++++++++++++++++---- src/modules/FiretrayHandler.jsm | 8 +- src/modules/commons.js | 2 +- src/modules/ctypes/linux/gtk.jsm | 2 +- src/modules/linux/FiretrayChatStatusIcon.jsm | 2 +- src/modules/linux/FiretrayWindow.jsm | 10 ++- 6 files changed, 78 insertions(+), 23 deletions(-) diff --git a/src/modules/FiretrayChat.jsm b/src/modules/FiretrayChat.jsm index b6c29a4..14e9fec 100644 --- a/src/modules/FiretrayChat.jsm +++ b/src/modules/FiretrayChat.jsm @@ -25,10 +25,10 @@ firetray.Chat = { log.debug("Enabling Chat"); firetray.Utils.addObservers(firetray.Chat, [ - // "*" // debugging + // "*", // debugging "account-connected", "account-disconnected", "idle-time-changed", "new-directed-incoming-message", "status-changed", - "unread-im-count-changed" + "unread-im-count-changed", "new-text" ]); firetray.ChatStatusIcon.init(); @@ -47,8 +47,27 @@ firetray.Chat = { this.initialized = false; }, + // FIXME: the listener should probably attached on the conv entry in the + // contactlist during startIconBlinkingMaybe + attachSelectListeners: function(win) { + log.debug("attachSelectListeners"); + ["contactlistbox", "tabmail"].forEach(function(eltId) { + win.document.getElementById(eltId) + .addEventListener('select', firetray.Chat.onSelect); + }); + }, + + detachSelectListeners: function(win) { + ["contactlistbox", "tabmail"].forEach(function(eltId) { + win.document.getElementById(eltId) + .removeEventListener('select', firetray.Chat.onSelect); + }); + }, + observe: function(subject, topic, data) { log.debug("RECEIVED Chat: "+topic+" subject="+subject+" data="+data); + let conv = null; + switch (topic) { case "account-connected": case "account-disconnected": @@ -58,19 +77,25 @@ firetray.Chat = { break; case "new-directed-incoming-message": // when PM or cited in channel - let conv = subject.QueryInterface(Ci.prplIMessage).conversation; + conv = subject.QueryInterface(Ci.prplIMessage).conversation; log.debug("conversation name="+conv.name); // normalizedName shouldn't be necessary + this.startIconBlinkingMaybe(conv); + break; - let convIsCurrentlyShown = this.isConvCurrentlyShown(conv); - log.debug("convIsCurrentlyShown="+convIsCurrentlyShown); - if (!convIsCurrentlyShown) { // don't blink when conv tab already on top - this.acknowledgeOnFocus.must = true; - this.acknowledgeOnFocus.conv = conv; - firetray.ChatStatusIcon.setIconBlinking(true); - } + /* Twitter is obviously considered a chatroom, not a private + conversation. This is why we need to detect incoming messages and switch + to the conversation differently. The actual read should be caught by + focus-in-event and 'select' event on tabmail and contactlist */ + case "new-text": + conv = subject.QueryInterface(Ci.prplIMessage).conversation; + log.info("new-text from "+conv.title); + let proto = conv.account.QueryInterface(Ci.imIAccount).protocol; + if (proto.normalizedName === 'twitter') + this.startIconBlinkingMaybe(conv); break; case "unread-im-count-changed": + log.debug("unread-im-count-changed"); let unreadMsgCount = data; if (unreadMsgCount == 0) this.stopIconBlinkingMaybe(); @@ -87,7 +112,18 @@ firetray.Chat = { } }, - stopIconBlinkingMaybe: function(xid) { + // FIXME: implement a pool of conv which initiated a warning + startIconBlinkingMaybe: function(conv) { + let convIsCurrentlyShown = this.isConvCurrentlyShown(conv); + log.debug("convIsCurrentlyShown="+convIsCurrentlyShown); + if (!convIsCurrentlyShown) { // don't blink when conv tab already on top + this.acknowledgeOnFocus.must = true; + this.acknowledgeOnFocus.conv = conv; + firetray.ChatStatusIcon.setIconBlinking(true); + } + }, + + stopIconBlinkingMaybe: function(xid) { // xid optional log.debug("acknowledgeOnFocus.must="+this.acknowledgeOnFocus.must); if (!this.acknowledgeOnFocus.must) return; @@ -96,23 +132,34 @@ firetray.Chat = { log.debug("convIsCurrentlyShown="+convIsCurrentlyShown); if (this.acknowledgeOnFocus.must && convIsCurrentlyShown) { + log.debug("do stop icon blinking !!!"); firetray.ChatStatusIcon.setIconBlinking(false); this.acknowledgeOnFocus.must = false; } }, + onSelect: function(event) { + log.debug("select event ! "); + firetray.Chat.stopIconBlinkingMaybe(); + }, + isConvCurrentlyShown: function(conv, xid) { + log.debug("isConvCurrentlyShown"); let activeWin = xid || firetray.Handler.findActiveWindow(); if (!firetray.Handler.windows[activeWin]) return false; + log.debug("1 ***"); let activeChatTab = this.findSelectedChatTab(activeWin); if (!activeChatTab) return false; + log.debug("2 ***"); - // for now there is only one Chat tab, so we don't need to - // findSelectedChatTabFromTab(activeChatTab.tabNode). And, as there is only - // one forlderPaneBox, there will also probably be only one contactlistbox - // for all Chat tabs anyway + /* for now there is only one Chat tab, so we don't need to + findSelectedChatTabFromTab(activeChatTab.tabNode). And, as there is only + one forlderPaneBox, there will also probably be only one contactlistbox + for all Chat tabs anyway */ let selectedConv = this.findSelectedConv(activeWin); + if (!selectedConv) return false; + log.debug("3 ***"); log.debug("conv.title='"+conv.title+"' selectedConv.title='"+selectedConv.title+"'"); return (conv.id == selectedConv.id); diff --git a/src/modules/FiretrayHandler.jsm b/src/modules/FiretrayHandler.jsm index 0bf8a21..2b68c25 100644 --- a/src/modules/FiretrayHandler.jsm +++ b/src/modules/FiretrayHandler.jsm @@ -255,12 +255,16 @@ firetray.Handler = { if (enabled) { firetray.Chat.init(); - for (let winId in firetray.Handler.windows) + for (let winId in firetray.Handler.windows) { firetray.ChatStatusIcon.attachOnFocusInCallback(winId); + firetray.Chat.attachSelectListeners(firetray.Handler.windows[winId].chromeWin); + } } else { - for (let winId in firetray.Handler.windows) + for (let winId in firetray.Handler.windows) { firetray.ChatStatusIcon.detachOnFocusInCallback(winId); + firetray.Chat.detachSelectListeners(firetray.Handler.windows[winId].chromeWin); + } firetray.Chat.shutdown(); } }, diff --git a/src/modules/commons.js b/src/modules/commons.js index 7406848..e0b44c9 100644 --- a/src/modules/commons.js +++ b/src/modules/commons.js @@ -200,7 +200,7 @@ firetray.Utils = { str += "obj["+i+"]: Unavailable\n"; } } - log.debug(str); + log.info(str); }, _nsResolver: function(prefix) { diff --git a/src/modules/ctypes/linux/gtk.jsm b/src/modules/ctypes/linux/gtk.jsm index 6aa3c1b..782bff8 100644 --- a/src/modules/ctypes/linux/gtk.jsm +++ b/src/modules/ctypes/linux/gtk.jsm @@ -78,7 +78,7 @@ function gtk_defines(lib) { this.GCallbackWindowStateEvent_t = ctypes.FunctionType( ctypes.default_abi, gobject.gboolean, [this.GtkWidget.ptr, gdk.GdkEventWindowState.ptr, gobject.gpointer]).ptr; - this.GCallbackWidgetFocuEvent_t = ctypes.FunctionType( + this.GCallbackWidgetFocusEvent_t = ctypes.FunctionType( ctypes.default_abi, gobject.gboolean, [this.GtkWidget.ptr, gdk.GdkEventFocus.ptr, gobject.gpointer]).ptr; diff --git a/src/modules/linux/FiretrayChatStatusIcon.jsm b/src/modules/linux/FiretrayChatStatusIcon.jsm index 18e6ecd..379702d 100644 --- a/src/modules/linux/FiretrayChatStatusIcon.jsm +++ b/src/modules/linux/FiretrayChatStatusIcon.jsm @@ -98,7 +98,7 @@ firetray.ChatStatusIcon = { attachOnFocusInCallback: function(xid) { log.debug("attachOnFocusInCallback xid="+xid); this.signals['focus-in'].callback[xid] = - gtk.GCallbackWidgetFocuEvent_t(firetray.ChatStatusIcon.onFocusIn); + gtk.GCallbackWidgetFocusEvent_t(firetray.ChatStatusIcon.onFocusIn); this.signals['focus-in'].handler[xid] = gobject.g_signal_connect( firetray.Handler.gtkWindows.get(xid), "focus-in-event", firetray.ChatStatusIcon.signals['focus-in'].callback[xid], null); diff --git a/src/modules/linux/FiretrayWindow.jsm b/src/modules/linux/FiretrayWindow.jsm index 78832e4..8816328 100644 --- a/src/modules/linux/FiretrayWindow.jsm +++ b/src/modules/linux/FiretrayWindow.jsm @@ -215,8 +215,10 @@ firetray.Window = { return false; } - if (firetray.Handler.isChatEnabled() && firetray.Chat.initialized) + if (firetray.Handler.isChatEnabled() && firetray.Chat.initialized) { firetray.ChatStatusIcon.detachOnFocusInCallback(xid); + firetray.Chat.detachSelectListeners(firetray.Handler.windows[xid].chromeWin); + } if (!delete firetray.Handler.windows[xid]) throw new DeleteError(); @@ -298,7 +300,7 @@ firetray.Window = { firetray.Handler.windows[xid].savedHeight, false); // repaint - ['savedX', 'savedX', 'savedWidth', 'savedHeight'].forEach(function(element, index, array) { + ['savedX', 'savedX', 'savedWidth', 'savedHeight'].forEach(function(element) { delete firetray.Handler.windows[xid][element]; }); }, @@ -658,8 +660,10 @@ firetray.Handler.registerWindow = function(win) { this.windows[xid].startupFilterCb = gdk.GdkFilterFunc_t(firetray.Window.startupFilter); gdk.gdk_window_add_filter(gdkWin, this.windows[xid].startupFilterCb, null); - if (firetray.Handler.isChatEnabled() && firetray.Chat.initialized) + if (firetray.Handler.isChatEnabled() && firetray.Chat.initialized) { firetray.ChatStatusIcon.attachOnFocusInCallback(xid); + firetray.Chat.attachSelectListeners(win); + } } catch (x) { firetray.Window.unregisterWindowByXID(xid);