Bug #252391 --> add support for multiple feeds sharing the same RSS folder. Includes new feed property

dialog UI to support specifying a destination for a folder.

Bug #252394 --> making the act of parsing and storing RSS feed items asynch, coming up for air between storing each item to the folder.
This commit is contained in:
scott%scott-macgregor.org 2004-07-21 18:28:25 +00:00
parent 0d957e4e54
commit 127020b08d
8 changed files with 244 additions and 229 deletions

View File

@ -25,6 +25,7 @@ function Feed(resource) {
this.author = null;
this.request = null;
this.folder = null;
this.downloadCallback = null;
@ -83,10 +84,10 @@ Feed.onDownloaded = function(event) {
var feed = gFzFeedCache[url];
if (!feed)
throw("error after downloading " + url + ": couldn't retrieve feed from request");
feed.parse();
if (feed.downloadCallback)
feed.downloadCallback.downloaded(feed);
// parse will asynchronously call the download callback when it is done
}
Feed.onProgress = function(event) {
@ -207,6 +208,10 @@ Feed.prototype.parseAsRSS2 = function() {
this.invalidateItems();
var itemNodes = this.request.responseXML.getElementsByTagName("item");
gItemsToStore = new Array();
gItemsToStoreIndex = 0;
for ( var i=0 ; i<itemNodes.length ; i++ ) {
var itemNode = itemNodes[i];
var item = new FeedItem();
@ -236,11 +241,10 @@ Feed.prototype.parseAsRSS2 = function() {
|| itemNode.getElementsByTagName("date")[0])
|| item.date;
item.store();
item.markValid();
gItemsToStore[i] = item;
}
this.removeInvalidItems();
storeNextItem();
}
Feed.prototype.parseAsRSS1 = function() {
@ -271,6 +275,10 @@ Feed.prototype.parseAsRSS1 = function() {
if (!items.hasMoreElements())
items = ds.GetSources(RDF_TYPE, RSS_ITEM, true);
gItemsToStore = new Array();
gItemsToStoreIndex = 0;
var index = 0;
while (items.hasMoreElements()) {
var itemResource = items.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
var item = new FeedItem();
@ -295,10 +303,10 @@ Feed.prototype.parseAsRSS1 = function() {
item.date = getRDFTargetValue(ds, itemResource, DC_DATE) || item.date;
item.content = getRDFTargetValue(ds, itemResource, RSS_CONTENT_ENCODED);
item.store();
item.markValid();
gItemsToStore[index++] = item;
}
this.removeInvalidItems();
storeNextItem();
}
Feed.prototype.parseAsAtom = function() {
@ -319,6 +327,10 @@ Feed.prototype.parseAsAtom = function() {
this.invalidateItems();
var items = this.request.responseXML.getElementsByTagName("entry");
gItemsToStore = new Array();
gItemsToStoreIndex = 0;
for ( var i=0 ; i<items.length ; i++ ) {
var itemNode = items[i];
var item = new FeedItem();
@ -389,10 +401,10 @@ Feed.prototype.parseAsAtom = function() {
}
item.content = content;
item.store();
item.markValid();
gItemsToStore[i] = item;
}
this.removeInvalidItems();
storeNextItem();
}
Feed.prototype.invalidateItems = function invalidateItems() {
@ -429,3 +441,37 @@ Feed.prototype.removeInvalidItems = function() {
}
}
var gItemsToStore;
var gItemsToStoreIndex = 0;
// gets the next item from gItemsToStore and forces that item to be stored
// to the folder. If more items are left to be stored, fires a timer for the next one.
// otherwise it triggers a download done notification to the UI
function storeNextItem()
{
var item = gItemsToStore[gItemsToStoreIndex++];
item.store();
item.markValid();
// eventually we'll report individual progress here....
if (gItemsToStoreIndex < gItemsToStore.length)
{
if ('setTimeout' in this)
setTimeout(storeNextItem, 50); // fire off a timer for the next item to store
else
{
debug('set timeout is not defined if this call originated from newsblog.js\n');
storeNextItem();
}
}
else
{
item.feed.removeInvalidItems();
if (item.feed.downloadCallback)
item.feed.downloadCallback.downloaded(item.feed);
gItemsToStore = "";
gItemsToStoreIndex = 0;
}
}

View File

@ -173,22 +173,19 @@ FeedItem.prototype.isStored = function() {
else
server = getIncomingServer();
var folder;
var folder = this.feed.folder;
try {
//var folder = server.rootMsgFolder.FindSubFolder(feed);
folder = server.rootMsgFolder.getChildNamed(this.feed.name);
} catch(e) {
folder = null;
}
if (!folder)
folder = server.rootMsgFolder.getChildNamed(this.feed.name);
} catch(e) {}
if (!folder)
{
debug(this.feed.name + " folder doesn't exist; creating");
debug("creating " + this.feed.name + "as child of " + server.rootMsgFolder + "\n");
server.rootMsgFolder.createSubfolder(this.feed.name, getMessageWindow());
folder = server.rootMsgFolder.FindSubFolder(this.feed.name);
var msgdb = folder.getMsgDatabase(null);
var folderInfo = msgdb.dBFolderInfo;
folderInfo.setCharPtrProperty("feedUrl", this.url);
debug(this.identity + " not stored (folder didn't exist)");
return false;
}
@ -349,7 +346,7 @@ FeedItem.prototype.writeToFolder = function() {
debug(this.identity + " is " + source.length + " characters long");
// Get the folder and database storing the feed's messages and headers.
var folder = server.rootMsgFolder.getChildNamed(this.feed.name);
var folder = this.feed.folder ? this.feed.folder : server.rootMsgFolder.getChildNamed(this.feed.name);
folder = folder.QueryInterface(Components.interfaces.nsIMsgLocalMailFolder);
folder.addMessage(source);
this.markStored();

View File

@ -32,22 +32,38 @@
* ***** END LICENSE BLOCK ***** */
function onLoad()
{
if (window.arguments[0].feedName)
document.getElementById('feedName').value = window.arguments[0].feedName;
{
if (window.arguments[0].feedLocation)
document.getElementById('feedLocation').value = window.arguments[0].feedLocation;
// root the location picker to the news & blogs server
document.getElementById('selectFolder').setAttribute('ref', window.arguments[0].serverURI);
SetFolderPicker(window.arguments[0].folderURI ? window.arguments[0].folderURI : window.arguments[0].serverURI, 'selectFolder');
}
function onOk()
{
// eventually, add some validation code to make sure they've entered a location and a name
// before trying to create a feed entry...
window.arguments[0].feedName = document.getElementById('feedName').value;
window.arguments[0].feedLocation = document.getElementById('feedLocation').value
window.arguments[0].feedLocation = document.getElementById('feedLocation').value;
window.arguments[0].folderURI = document.getElementById('selectFolder').value;
window.arguments[0].result = true;
return true;
}
function PickedMsgFolder(selection,pickerID)
{
var selectedUri = selection.getAttribute('id');
SetFolderPicker(selectedUri,pickerID);
}
function SetFolderPicker(uri,pickerID)
{
var picker = document.getElementById(pickerID);
var msgfolder = GetMsgFolderFromUri(uri, true);
if (!msgfolder)
return;
picker.setAttribute("label",msgfolder.name);
picker.setAttribute("uri",uri);
}

View File

@ -33,7 +33,6 @@
<?xml-stylesheet href="chrome://messenger/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://messenger-newsblog/locale/feed-properties.dtd">
<dialog id="feedPropertyDialog"
@ -44,8 +43,9 @@
buttons="accept,cancel"
onload="onLoad();"
ondialogaccept="return onOk();">
<script type="application/x-javascript" src="feed-properties.js"/>
<script type="application/x-javascript" src="chrome://messenger/content/widgetglue.js"/>
<grid flex="1">
<columns>
@ -54,12 +54,10 @@
</columns>
<rows>
<row>
<label value="&feedName.label;" accesskey="&feedName.accesskey;" control="feedName"/>
<hbox>
<textbox flex="1" id="feedName"/>
<spacer flex="4"/>
</hbox>
<label value="&feedLocation.label;" accesskey="&feedLocation.accesskey;" control="feedLocation"/>
<textbox id="feedLocation"/>
</row>
<row>
@ -67,8 +65,27 @@
</row>
<row>
<label value="&feedLocation.label;" accesskey="&feedLocation.accesskey;" control="feedLocation"/>
<textbox id="feedLocation"/>
<label value="&feedFolder.label;" accesskey="&feedFolder.accesskey;" control="selectFolder"/>
<menulist id="selectFolder"
containment="http://home.netscape.com/NC-rdf#child"
sortResource="http://home.netscape.com/NC-rdf#FolderTreeName"
sortDirection="ascending"
datasources="rdf:msgaccountmanager rdf:mailnewsfolders"
ref="...">
<template>
<menupopup>
<menuitem uri="..." value="..."
class="folderMenuItem menuitem-iconic"
oncommand="PickedMsgFolder(event.target,'selectFolder')"
SpecialFolder="rdf:http://home.netscape.com/NC-rdf#SpecialFolder"
BiffState="rdf:http://home.netscape.com/NC-rdf#BiffState"
IsServer="rdf:http://home.netscape.com/NC-rdf#IsServer"
IsSecure="rdf:http://home.netscape.com/NC-rdf#IsSecure"
ServerType="rdf:http://home.netscape.com/NC-rdf#ServerType"
label="rdf:http://home.netscape.com/NC-rdf#Name"/>
</menupopup>
</template>
</menulist>
</row>
<!-- Eventually we'll add a folder picker here to pick the folder associated with the feed -->

View File

@ -34,6 +34,8 @@
*
* ***** END LICENSE BLOCK ***** */
var kFeedUrlDelimiter = '|'; // the delimiter used to delimit feed urls in the msg folder database "feedUrl" property
function doLoad() {
// Display the list of feed subscriptions.
var file = getSubscriptionsFile();
@ -75,31 +77,19 @@ var feedDownloadCallback = {
// feed is null if our attempt to parse the feed failed
if (feed)
{
debug("after download, feed name = " + feed.name + "\n");
updateStatusItem('progressMeter', 100);
updateStatusItem('statusText', document.getElementById("bundle_newsblog").getString('subscribe-validFeedFound'));
updateStatusItem('statusText', 'Valid Feed Found!');
var server = getIncomingServer();
var folder;
try {
var folder = server.rootMsgFolder.getChildNamed(feed.name);
}
catch(e) {
// If we're here, it's probably because the folder doesn't exist yet,
// so create it.
debug("folder for new feed " + feed.name + " doesn't exist; creating");
debug("creating " + feed.name + "as child of " + server.rootMsgFolder + "\n");
server.rootMsgFolder.createSubfolder(feed.name, getMessageWindow());
folder = server.rootMsgFolder.FindSubFolder(feed.name);
var msgdb = folder.getMsgDatabase(null);
var folderInfo = msgdb.dBFolderInfo;
folderInfo.setCharPtrProperty("feedUrl", feed.url);
}
// if we get here...we should always have a folder by now...either
// in feed.folder or FeedItems created the folder for us....
var folder = feed.folder ? feed.folder : server.rootMsgFolder.getChildNamed(feed.name);
updateFolderFeedUrl(folder, feed.url, false);
// add feed just adds the feed we have validated and downloaded to the subscription UI.
// it also flushes the subscription database
// it also flushes the subscription datasource
addFeed(feed.url, feed.name, null, folder);
}
else
@ -113,32 +103,52 @@ var feedDownloadCallback = {
onProgress: function(aProgress, aProgressMax)
{
updateStatusItem('progressMeter', (aProgress * 100) / aProgressMax);
updateStatusItem('progressMeter', (aProgress * 100) / aProgressMax);
},
}
// updates the "feedUrl" property in the message database for the folder in question.
function updateFolderFeedUrl(aFolder, aFeedUrl, aRemoveUrl)
{
var msgdb = aFolder.QueryInterface(Components.interfaces.nsIMsgFolder).getMsgDatabase(null);
var folderInfo = msgdb.dBFolderInfo;
var oldFeedUrl = folderInfo.getCharPtrProperty("feedUrl");
if (aRemoveUrl)
{
// remove our feed url string from the list of feed urls
var newFeedUrl = oldFeedUrl.replace(kFeedUrlDelimiter + aFeedUrl, "");
folderInfo.setCharPtrProperty("feedUrl", newFeedUrl);
}
else
folderInfo.setCharPtrProperty("feedUrl", oldFeedUrl + kFeedUrlDelimiter + aFeedUrl);
}
function doAdd() {
var userAddedFeed = false;
var feedProperties = { feedName: "", feedLocation: "", result: userAddedFeed};
var server = getIncomingServer();
var feedProperties = { feedName: "", feedLocation: "", serverURI: server.serverURI, folderURI: "", result: userAddedFeed};
feedProperties = openFeedEditor(feedProperties);
// if the user hit cancel, exit without doing anything
if (!feedProperties.result)
{
debug("feedProperties.result empty\n");
return;
}
if (!feedProperties.feedLocation)
{
debug("feedProperties.feedLocation empty\n");
return;
}
var itemResource = rdf.GetResource(feedProperties.feedLocation);
feed = new Feed(itemResource);
// if the user specified a specific folder to add the feed too, then set it here
if (feedProperties.folderURI)
{
var folderResource = rdf.GetResource(feedProperties.folderURI);
if (folderResource)
feed.folder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
}
// update status text
updateStatusItem('statusText', document.getElementById("bundle_newsblog").getString('subscribe-validating'));
updateStatusItem('progressMeter', 0);
@ -159,188 +169,108 @@ function doEdit() {
var tree = document.getElementById('subscriptions');
var item = tree.view.getItemAtIndex(tree.view.selection.currentIndex);
var resource = rdf.GetResource(item.id);
var old_title = ds.GetTarget(resource, DC_TITLE, true);
old_title =
old_title ? old_title.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : "";
var old_url = ds.GetTarget(resource, DC_IDENTIFIER, true);
old_url =
old_url ? old_url.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : "";
old_url = old_url ? old_url.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : "";
var currentFolder = ds.GetTarget(resource, FZ_DESTFOLDER, true);
var currentFolderURI = currentFolder.QueryInterface(Components.interfaces.nsIRDFResource).Value;
currentFolder = rdf.GetResource(currentFolderURI).QueryInterface(Components.interfaces.nsIMsgFolder);
var server = getIncomingServer();
var userModifiedFeed = false;
var feedProperties = { feedName: old_title, feedLocation: old_url, result: userModifiedFeed};
var feedProperties = { feedLocation: old_url, serverURI: server.serverURI, folderURI: currentFolderURI, result: userModifiedFeed};
feedProperties = openFeedEditor(feedProperties);
if (!feedProperties.result) // did the user cancel?
return;
if (feedProperties.feedName != old_title) {
var server = getIncomingServer();
var msgWindow = getMessageWindow();
// did the user change the folder URI for storing the feed?
if (feedProperties.folderURI && feedProperties.folderURI != currentFolderURI)
{
// unassert the older URI, add an assertion for the new URI...
ds.Change(resource, FZ_DESTFOLDER, currentFolder, rdf.GetResource(feedProperties.folderURI));
// Throwing an error 0x80004005 seems to be getChildNamed()'s way
// of saying that a folder doesn't exist, so we need to trap that
// since it isn't fatal in our case. XXX We should probably check
// the error code in the catch statement to verify the problem.
var old_folder;
try {
old_folder = server.rootMsgFolder.getChildNamed(old_title);
old_folder = old_folder.QueryInterface(Components.interfaces.nsIMsgFolder);
} catch(e) {}
var new_folder;
try {
new_folder = server.rootMsgFolder.getChildNamed(feedProperties.feedName);
new_folder = new_folder.QueryInterface(Components.interfaces.nsIMsgFolder);
} catch(e) {}
// we need to update the feed url attributes on the databases for each folder
var folderResource = rdf.GetResource(feedProperties.folderURI);
var newFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
currentFolder = rdf.GetResource(currentFolderURI).QueryInterface(Components.interfaces.nsIMsgFolder);
if (old_folder && new_folder) {
// We could move messages from the old folder to the new folder
// and then delete the old folder (code for doing so is below),
// but how do we distinguish between messages in the old folder
// from this feed vs. from another feed? Until we can do that,
// which probably requires storing the feed ID in the message headers,
// we're better off just leaving the old folder as it is.
//var messages = old_folder.getMessages(msgWindow);
//var movees =
// Components
// .classes["@mozilla.org/supports-array;1"]
// .createInstance(Components.interfaces.nsISupportsArray);
//var message;
//while (messages.hasMoreElements()) {
// message = messages.getNext();
// movees.AppendElement(message);
//}
//gFoldersBeingDeleted.push(old_folder);
//new_folder.copyMessages(old_folder,
// movees,
// true /*isMove*/,
// msgWindow /* nsIMsgWindow */,
// null /* listener */,
// false /* isFolder */,
// false /*allowUndo*/ );
}
else if (old_folder) {
// We could rename the old folder to the new folder
// (code for doing so is below), but what if other feeds
// are using the old folder? Until we write code to determine
// whether they are or not (and perhaps even then), better to leave
// the old folder as it is and merely create a new folder.
//old_folder.rename(new_title, msgWindow);
server.rootMsgFolder.createSubfolder(feedProperties.feedName, msgWindow);
folder = rootMsgFolder.FindSubFolder(feedProperties.feedName);
var msgdb = folder.getMsgDatabase(null);
msgdb.dBFolderInfo.setCharPtrProperty("feedUrl", feedProperties.feedLocation);
}
else if (new_folder) {
// Do nothing, as everything is as it should be.
}
else {
// Neither old nor new folders exist, so just create the new one.
server.rootMsgFolder.createSubfolder(feedProperties.feedName, msgWindow);
folder = rootMsgFolder.FindSubFolder(feedProperties.feedName);
var msgdb = folder.getMsgDatabase(null);
msgdb.dBFolderInfo.setCharPtrProperty("feedUrl", feedProperties.feedLocation);
}
updateTitle(item.id, feedProperties.feedName);
updateFolderFeedUrl(currentFolder, old_url, true); // remove our feed url property from the current folder
updateFolderFeedUrl(newFolder, feedProperties.feedLocation, false); // add our feed url property to the new folder
currentFolder = newFolder; // the folder has changed
}
if (!feedProperties.feedLocation) {
// The user cancelled the edit, but not until after potentially changing
// the title, so despite the cancellation we should still redownload
// the feed if the title has changed.
if (new_title != old_title) {
feed = new Feed(item.id);
feed.download();
}
return;
// check to see if the location changed
if (feedProperties.feedLocation && feedProperties.feedLocation != old_url)
{
ds.Change(resource, DC_IDENTIFIER, rdf.GetLiteral(old_url), rdf.GetLiteral(feedProperties.feedLocation));
// now update our feed url property on the destination folder
updateFolderFeedUrl(currentFolder, old_url, false); // remove the old url
updateFolderFeedUrl(currentFolder, feedProperties.feedLocation, true); // add the new one
}
else if (feedProperties.feedLocation != old_url)
updateURL(item.id, feedProperties.feedLocation);
feed = new Feed(item.id);
feed.download();
// feed = new Feed(item.id);
// feed.download();
}
function doRemove() {
var tree = document.getElementById('subscriptions');
var item = tree.view.getItemAtIndex(tree.view.selection.currentIndex);
var resource = rdf.GetResource(item.id);
var feed = new Feed(resource);
var ds = getSubscriptionsDS();
// remove the feed from the subscriptions ds
var feeds = getSubscriptionsList();
var index = feeds.IndexOf(resource);
if (index != -1) {
var title = ds.GetTarget(resource, DC_TITLE, true);
if (title) {
title = title.QueryInterface(Components.interfaces.nsIRDFLiteral);
// We could delete the folder, but what if other feeds are using it?
// XXX Should we check for other feeds using the folder and delete it
// if there aren't any? What if the user is using the folder
// for other purposes?
var server = getIncomingServer();
var openerResource = server.rootMsgFolder.QueryInterface(Components.interfaces.nsIRDFResource);
var titleValue = title ? title.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : "";
var feed = new Feed(resource);
try {
var folderResource = server.rootMsgFolder.getChildNamed(feed.name).QueryInterface(Components.interfaces.nsIRDFResource);
var foo = window.opener.messenger.DeleteFolders(window.opener.GetFolderDatasource(), openerResource, folderResource);
} catch (e) {}
try {
// If the folder still exists, then it wasn't deleted,
// which means the user answered "no" to the question of whether
// they wanted to move the folder into the trash. That probably
// means they changed their minds about removing the feed,
// so don't remove it.
folder = server.rootMsgFolder.getChildNamed(feed.name);
if (folder)
return;
}
catch (e) {}
ds.Unassert(resource, DC_TITLE, title, true);
}
if (index != -1)
feeds.RemoveElementAt(index, false);
var url = ds.GetTarget(resource, DC_IDENTIFIER, true);
if (url) {
url = url.QueryInterface(Components.interfaces.nsIRDFLiteral);
ds.Unassert(resource, DC_IDENTIFIER, url, true);
}
// remove the feed property string from the folder data base
var currentFolder = ds.GetTarget(resource, FZ_DESTFOLDER, true);
var currentFolderURI = currentFolder.QueryInterface(Components.interfaces.nsIRDFResource).Value;
currentFolder = rdf.GetResource(currentFolderURI).QueryInterface(Components.interfaces.nsIMsgFolder);
var feedUrl = ds.GetTarget(resource, DC_IDENTIFIER, true);
ds.Unassert(resource, DC_IDENTIFIER, feedUrl, true);
feedUrl = feedUrl ? feedUrl.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : "";
updateFolderFeedUrl(currentFolder, feedUrl, true); // remove the old url
feeds.RemoveElementAt(index, true);
}
// Remove all assertions about the feed from the subscriptions database.
removeAssertions(ds, feed);
removeAssertions(ds, resource);
ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource).Flush(); // flush any changes
// Remove all assertions about items in the feed from the items database.
ds = getItemsDS();
var itemds = getItemsDS();
feed.invalidateItems();
feed.removeInvalidItems();
ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource).Flush(); // flush any changes
itemds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource).Flush(); // flush any changes
// If we don't have any more subscriptions pointing into
// this folder, then I think we should offer to delete it...
// Cheat and look at the feed url property to see if anyone else is still using the feed...
// you could also accomplish this by looking at some properties in the data source...
var msgdb = currentFolder.QueryInterface(Components.interfaces.nsIMsgFolder).getMsgDatabase(null);
var folderInfo = msgdb.dBFolderInfo;
var oldFeedUrl = folderInfo.getCharPtrProperty("feedUrl");
if (!oldFeedUrl) // no more feeds pointing to the folder?
{
try {
var server = getIncomingServer();
var openerResource = server.rootMsgFolder.QueryInterface(Components.interfaces.nsIRDFResource);
var folderResource = currentFolder.QueryInterface(Components.interfaces.nsIRDFResource);
window.opener.messenger.DeleteFolders(window.opener.GetFolderDatasource(), openerResource, folderResource);
} catch (e) { }
}
}
/*
* Stuff
*/
function updateTitle(item, new_title) {
var ds = getSubscriptionsDS();
item = rdf.GetResource(item);
var old_title = ds.GetTarget(item, DC_TITLE, true);
if (old_title)
ds.Change(item, DC_TITLE, old_title, rdf.GetLiteral(new_title));
else
ds.Assert(item, DC_TITLE, rdf.GetLiteral(new_title), true);
}
function updateURL(item, new_url) {
var ds = getSubscriptionsDS();
var item = rdf.GetResource(item);
var old_url = ds.GetTarget(item, DC_IDENTIFIER, true);
if (old_url)
ds.Change(item, DC_IDENTIFIER, old_url, rdf.GetLiteral(new_url));
else
ds.Assert(item, DC_IDENTIFIER, rdf.GetLiteral(new_url), true);
}
function getIncomingServer() {
return window.opener.getIncomingServer();
}

View File

@ -94,14 +94,12 @@
</conditions>
<bindings>
<binding subject="?feed" predicate="http://purl.org/dc/elements/1.1/title" object="?title"/>
<binding subject="?feed" predicate="http://purl.org/dc/elements/1.1/identifier" object="?url"/>
</bindings>
<action>
<treechildren flex="1">
<treeitem uri="?feed">
<treerow>
<treecell src="" label="?title"/>
<treecell src="" label="?url"/>
</treerow>
</treeitem>
</treechildren>
@ -110,8 +108,6 @@
</template>
<treecols>
<treecol id="subs-name-column" flex="1" label="&feedNameTreeCol.label;" primary="true"/>
<splitter class="tree-splitter"/>
<treecol id="subs-url-column" flex="3" label="&locationTreeCol.label;" hidden="false"/>
</treecols>
</tree>
</row>

View File

@ -42,17 +42,30 @@ var nsNewsBlogFeedDownloader =
if (!gExternalScriptsLoaded)
loadScripts();
// aUrl may be a delimited list of feeds for a particular folder. We need to kick off a download
// for each feed.
var feedUrlArray = aUrl.split("|");
// we might just pull all these args out of the aFolder DB, instead of passing them in...
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
id = rdf.GetResource(aUrl);
feed = new Feed(id);
feed.urlListener = aUrlListener;
feed.folder = aFolder;
feed.msgWindow = aMsgWindow;
feed.download();
var index = 0;
for (url in feedUrlArray)
{
if (feedUrlArray[url])
{
id = rdf.GetResource(feedUrlArray[url]);
feed = new Feed(id);
feed.urlListener = aUrlListener;
feed.folder = aFolder;
feed.msgWindow = aMsgWindow;
feed.download();
}
}
},
QueryInterface: function(aIID)
{
if (aIID.equals(Components.interfaces.nsINewsBlogFeedDownloader) ||

View File

@ -1,10 +1,10 @@
<!-- Feed Properties Dialog -->
<!ENTITY window.title "News Feed Properties">
<!ENTITY feedName.label "Name: ">
<!ENTITY feedName.accesskey "N">
<!ENTITY feedFolder.label "Store Feed Articles in: ">
<!ENTITY feedFolder.accesskey "S">
<!ENTITY feedLocation.label "Location URL: ">
<!ENTITY feedLocation.accesskey "L">
<!ENTITY feedLocation.label "Feed URL: ">
<!ENTITY feedLocation.accesskey "F">