Mercurial > snowl
changeset 282:76ee747a1dba
add messages progressively to the stream view rather than rebuilding the view each time
author | Myk Melez <myk@mozilla.org> |
---|---|
date | Mon, 01 Sep 2008 19:01:56 -0700 |
parents | 92bff6641dcd |
children | ae23e6f323db |
files | content/stream.js modules/feed.js modules/twitter.js |
diffstat | 3 files changed, 126 insertions(+), 113 deletions(-) [+] |
line wrap: on
line diff
--- a/content/stream.js Mon Sep 01 19:00:44 2008 -0700 +++ b/content/stream.js Mon Sep 01 19:01:56 2008 -0700 @@ -45,6 +45,7 @@ // modules that should come with Firefox Cu.import("resource://snowl/modules/log4moz.js"); Cu.import("resource://snowl/modules/URI.js"); +Cu.import("resource://snowl/modules/Observers.js"); // modules that are Snowl-specific Cu.import("resource://snowl/modules/datastore.js"); @@ -147,9 +148,7 @@ // Initialization & Destruction onLoad: function() { - // FIXME: listen for messages added and then insert those messages - // into the view rather than rebuilding the whole view. - this._obsSvc.addObserver(this, "messages:changed", true); + Observers.add(this, "snowl:message:added"); this.onResize(); @@ -163,7 +162,7 @@ this._collection.sortProperties = ["received"]; this._collection.sortOrder = -1; this._collection.sort(); - this.rebuildView(); + this._rebuildView(); }, @@ -173,8 +172,8 @@ // nsIObserver observe: function(subject, topic, data) { switch (topic) { - case "messages:changed": - this._onMessagesChanged(); + case "snowl:message:added": + this._onMessageAdded(subject); break; } }, @@ -192,12 +191,15 @@ this._updateRule(0, ".body > * { width: " + width + "px }"); }, - _onMessagesChanged: function() { - // FIXME: make the collection listen for message changes and invalidate - // itself, then rebuild the view in a timeout to give the collection time - // to do so. - this._collection.invalidate(); - this._rebuildView(); + _onMessageAdded: function(message) { + this._contentSandbox.messages = this._document.getElementById("contentBox"); + this._contentSandbox.messageBox = this._buildMessageView(message); + + let codeStr = "messages.insertBefore(messageBox, messages.firstChild)"; + Cu.evalInSandbox(codeStr, this._contentSandbox); + + this._contentSandbox.messages = null; + this._contentSandbox.messageBox = null; }, @@ -295,7 +297,7 @@ yield this._rebuildViewFuture.result(); }), - rebuildView: strand(function() { + _rebuildView: strand(function() { let begin = new Date(); let contentBox = this._document.getElementById("contentBox"); @@ -315,105 +317,7 @@ for (let i = 0; i < this._collection.messages.length; ++i) { let message = this._collection.messages[i]; - let messageBox = this._document.createElementNS(XUL_NS, "hbox"); - messageBox.className = "message"; - messageBox.setAttribute("index", i); - - // left column - let leftColumn = this._document.createElementNS(XUL_NS, "vbox"); - leftColumn.className = "leftColumn"; - let icon = document.createElementNS(XUL_NS, "image"); - icon.className = "icon"; - if (message.authorIcon) { - icon.setAttribute("src", message.authorIcon); - } - else { - let sourceFaviconURI = message.source.humanURI || URI.get("urn:use-default-icon"); - icon.setAttribute("src", this._faviconSvc.getFaviconImageForPage(sourceFaviconURI).spec); - } - leftColumn.appendChild(icon); - messageBox.appendChild(leftColumn); - - // center column - let centerColumn = this._document.createElementNS(XUL_NS, "vbox"); - centerColumn.className = "centerColumn"; - messageBox.appendChild(centerColumn); - - // Author or Source - if (message.author || message.source) { - let desc = this._document.createElementNS(XUL_NS, "description"); - desc.className = "author"; - desc.setAttribute("crop", "end"); - desc.setAttribute("value", message.author || message.source.name); - centerColumn.appendChild(desc); - } - - // Timestamp - // Commented out because the timestamp isn't that useful when we order - // by time received. Instead, we're going to group by time period - // received (this morning, yesterday, last week, etc.) to give users - // useful chronographic info. - //let lastUpdated = SnowlUtils._formatDate(new Date(message.timestamp)); - //if (lastUpdated) { - // let timestamp = this._document.createElementNS(XUL_NS, "description"); - // timestamp.className = "timestamp"; - // timestamp.setAttribute("crop", "end"); - // timestamp.setAttribute("value", lastUpdated); - // centerColumn.appendChild(timestamp); - //} - - // content (title or short message) - let body = this._document.createElementNS(XUL_NS, "description"); - body.className = "body"; - let div = this._document.createElementNS(HTML_NS, "div"); - let a = this._document.createElementNS(HTML_NS, "a"); - // FIXME: make this localizable. - let subject = message.subject || "empty message"; - - if (message.link) { - let a = this._document.createElementNS(HTML_NS, "a"); - this._unsafeSetURIAttribute(a, "href", message.link); - body.className += " text-link"; - a.appendChild(this._document.createTextNode(subject)); - div.appendChild(a); - } - else { - // Split the text into its plaintext and URL parts, which alternate - // in the array of results, with the first part always being plaintext. - // FIXME: turn this whole block into a function that other views - // can use. - let parts = subject.split(this._linkifyRegex); - for (let i = 0; i < parts.length; i++) { - if (i % 2 == 0) - div.appendChild(this._document.createTextNode(parts[i])); - else { - let a = this._document.createElementNS(HTML_NS, "a"); - this._unsafeSetURIAttribute(a, "href", parts[i]); - a.appendChild(this._document.createTextNode(parts[i])); - div.appendChild(a); - } - } - } - - body.appendChild(div); - centerColumn.appendChild(body); - - // Source - //let source = this._document.createElementNS(HTML_NS, "a"); - //source.className = "source"; - //let sourceIcon = document.createElementNS(HTML_NS, "img"); - //let sourceFaviconURI = message.source.humanURI || URI.get("urn:use-default-icon"); - //sourceIcon.src = this._faviconSvc.getFaviconImageForPage(sourceFaviconURI).spec; - //source.appendChild(sourceIcon); - //source.appendChild(this._document.createTextNode(message.source.name)); - //if (message.source.humanURI) - // this._unsafeSetURIAttribute(source, "href", message.source.humanURI.spec); - //centerColumn.appendChild(source); - - // right column - let rightColumn = this._document.createElementNS(XUL_NS, "vbox"); - rightColumn.className = "rightColumn"; - messageBox.appendChild(rightColumn); + let messageBox = this._buildMessageView(message); this._contentSandbox.messageBox = messageBox; @@ -434,6 +338,109 @@ //let serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"]. // createInstance(Ci.nsIDOMSerializer); //this._log.info(serializer.serializeToString(document.getElementById("contentBox"))); - }) + }), + + _buildMessageView: function(message) { + let messageBox = this._document.createElementNS(XUL_NS, "hbox"); + messageBox.className = "message"; + + // left column + let leftColumn = this._document.createElementNS(XUL_NS, "vbox"); + leftColumn.className = "leftColumn"; + let icon = document.createElementNS(XUL_NS, "image"); + icon.className = "icon"; + if (message.authorIcon) { + icon.setAttribute("src", message.authorIcon); + } + else { + let sourceFaviconURI = message.source.humanURI || URI.get("urn:use-default-icon"); + icon.setAttribute("src", this._faviconSvc.getFaviconImageForPage(sourceFaviconURI).spec); + } + leftColumn.appendChild(icon); + messageBox.appendChild(leftColumn); + + // center column + let centerColumn = this._document.createElementNS(XUL_NS, "vbox"); + centerColumn.className = "centerColumn"; + messageBox.appendChild(centerColumn); + + // Author or Source + if (message.author || message.source) { + let desc = this._document.createElementNS(XUL_NS, "description"); + desc.className = "author"; + desc.setAttribute("crop", "end"); + desc.setAttribute("value", message.author || message.source.name); + centerColumn.appendChild(desc); + } + + // Timestamp + // Commented out because the timestamp isn't that useful when we order + // by time received. Instead, we're going to group by time period + // received (this morning, yesterday, last week, etc.) to give users + // useful chronographic info. + //let lastUpdated = SnowlUtils._formatDate(new Date(message.timestamp)); + //if (lastUpdated) { + // let timestamp = this._document.createElementNS(XUL_NS, "description"); + // timestamp.className = "timestamp"; + // timestamp.setAttribute("crop", "end"); + // timestamp.setAttribute("value", lastUpdated); + // centerColumn.appendChild(timestamp); + //} + + // content (title or short message) + let body = this._document.createElementNS(XUL_NS, "description"); + body.className = "body"; + let div = this._document.createElementNS(HTML_NS, "div"); + let a = this._document.createElementNS(HTML_NS, "a"); + // FIXME: make this localizable. + let subject = message.subject || "empty message"; + + if (message.link) { + let a = this._document.createElementNS(HTML_NS, "a"); + this._unsafeSetURIAttribute(a, "href", message.link); + body.className += " text-link"; + a.appendChild(this._document.createTextNode(subject)); + div.appendChild(a); + } + else { + // Split the text into its plaintext and URL parts, which alternate + // in the array of results, with the first part always being plaintext. + // FIXME: turn this whole block into a function that other views + // can use. + let parts = subject.split(this._linkifyRegex); + for (let i = 0; i < parts.length; i++) { + if (i % 2 == 0) + div.appendChild(this._document.createTextNode(parts[i])); + else { + let a = this._document.createElementNS(HTML_NS, "a"); + this._unsafeSetURIAttribute(a, "href", parts[i]); + a.appendChild(this._document.createTextNode(parts[i])); + div.appendChild(a); + } + } + } + + body.appendChild(div); + centerColumn.appendChild(body); + + // Source + //let source = this._document.createElementNS(HTML_NS, "a"); + //source.className = "source"; + //let sourceIcon = document.createElementNS(HTML_NS, "img"); + //let sourceFaviconURI = message.source.humanURI || URI.get("urn:use-default-icon"); + //sourceIcon.src = this._faviconSvc.getFaviconImageForPage(sourceFaviconURI).spec; + //source.appendChild(sourceIcon); + //source.appendChild(this._document.createTextNode(message.source.name)); + //if (message.source.humanURI) + // this._unsafeSetURIAttribute(source, "href", message.source.humanURI.spec); + //centerColumn.appendChild(source); + + // right column + let rightColumn = this._document.createElementNS(XUL_NS, "vbox"); + rightColumn.className = "rightColumn"; + messageBox.appendChild(rightColumn); + + return messageBox; + } };
--- a/modules/feed.js Mon Sep 01 19:00:44 2008 -0700 +++ b/modules/feed.js Mon Sep 01 19:01:56 2008 -0700 @@ -54,6 +54,7 @@ Cu.import("resource://snowl/modules/datastore.js"); Cu.import("resource://snowl/modules/source.js"); Cu.import("resource://snowl/modules/identity.js"); +Cu.import("resource://snowl/modules/message.js"); // FIXME: factor this out into a common file. const PART_TYPE_CONTENT = 1; @@ -406,6 +407,8 @@ this._addMetadatum(messageID, field.name, field.value); } + Observers.notify(SnowlMessage.get(messageID), "snowl:message:added", null); + return messageID; },
--- a/modules/twitter.js Mon Sep 01 19:00:44 2008 -0700 +++ b/modules/twitter.js Mon Sep 01 19:01:56 2008 -0700 @@ -54,6 +54,7 @@ Cu.import("resource://snowl/modules/datastore.js"); Cu.import("resource://snowl/modules/source.js"); Cu.import("resource://snowl/modules/identity.js"); +Cu.import("resource://snowl/modules/message.js"); // FIXME: factor this out into a common file. const PART_TYPE_CONTENT = 1; @@ -427,6 +428,8 @@ this._addMetadatum(messageID, name, value); } + Observers.notify(SnowlMessage.get(messageID), "snowl:message:added", null); + return messageID; },