Bug 346009 - better subscription UI for feed preview. r=mconnor. See comment 31 on the bug.

This commit is contained in:
mozilla.mano%sent.com 2006-08-21 08:30:25 +00:00
Родитель b5e9afc9a0
Коммит f099483cd8
15 изменённых файлов: 714 добавлений и 538 удалений

Просмотреть файл

Просмотреть файл

@ -14,7 +14,8 @@
]> ]>
<html id="feedHandler" <html id="feedHandler"
xmlns="http://www.w3.org/1999/xhtml"> xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<head> <head>
<title>&feedPage.title;</title> <title>&feedPage.title;</title>
<link rel="stylesheet" href="chrome://browser/skin/feeds/subscribe.css" <link rel="stylesheet" href="chrome://browser/skin/feeds/subscribe.css"
@ -30,28 +31,10 @@
</p> </p>
<p id="feedSubscriptionInfo2">&feedSubscriptionInfo2;</p> <p id="feedSubscriptionInfo2">&feedSubscriptionInfo2;</p>
</div> </div>
<div id="feedSubscribeLine">
<div id="feedSubscribeLineHandlerChosen"> <!-- XXXmano this has to be in one line. Otherwise you would see
<button id="feedSubscribeLink" class="feedSubscribeLink" how much XUL-in-XHTML sucks, see bug 348830 -->
onclick="SubscribeHandler.subscribe();"> <div id="feedSubscribeLine"><xul:vbox><xul:hbox align="center"><xul:description>&subscribeUsing;</xul:description><xul:menulist id="handlersMenuList"><xul:menupopup menugenerated="true" id="handlersMenuPopup"><xul:menuitem id="liveBookmarksMenuItem" label="&feedLiveBookmarks;" class="menuitem-iconic" src="chrome://browser/skin/page-livemarks.png" selected="true"/><xul:menuseparator/></xul:menupopup></xul:menulist></xul:hbox><xul:hbox><xul:checkbox id="alwaysUse" checked="false"/></xul:hbox><xul:hbox align="center"><xul:spacer flex="1"/><span><xul:button label="&feedSubscribeNow;" id="subscribeButton"/></span></xul:hbox></xul:vbox></div></div>
<span class="feedSubscribeLinkBox">&feedSubscribeNow;</span>
</button>
&feedSubscribeUsing;
<span id="feedSubscribeHandler">
<a id="feedSubscribeHandleText"></a>
</span>
<a id="feedChangeSubscribeOptions" href="javascript:SubscribeHandler.changeOptions();">
&feedSubscribeChangeSubscribeOptions;</a>
</div>
<div id="feedSubscribeLineHandlerUnchosen" hidden="true">
<button id="feedChooseInitialReader" class="feedSubscribeLink"
onclick="SubscribeHandler.changeOptions();">
<span class="feedSubscribeLinkBox">&feedSubscribeChooseSubscribeOptions;</span>
</button>
&feedSubscribeChooseInfo;
</div>
</div>
</div>
<!-- XXXben - get rid of me when the feed processor is bug free! --> <!-- XXXben - get rid of me when the feed processor is bug free! -->
<div id="feedError" style="display:none;" dir="&locale.dir;"> <div id="feedError" style="display:none;" dir="&locale.dir;">

Просмотреть файл

@ -1,7 +1,5 @@
browser.jar: browser.jar:
* content/browser/feeds/subscribe.xhtml (content/subscribe.xhtml) * content/browser/feeds/subscribe.xhtml (content/subscribe.xhtml)
* content/browser/feeds/subscribe.js (content/subscribe.js) * content/browser/feeds/subscribe.js (content/subscribe.js)
* content/browser/feeds/options.xul (content/options.xul)
* content/browser/feeds/options.js (content/options.js)
* content/browser/feeds/addFeedReader.xul (content/addFeedReader.xul) * content/browser/feeds/addFeedReader.xul (content/addFeedReader.xul)
* content/browser/feeds/addFeedReader.js (content/addFeedReader.js) * content/browser/feeds/addFeedReader.js (content/addFeedReader.js)

Просмотреть файл

@ -44,7 +44,7 @@ interface nsIDOMWindow;
* is trusted so can access preferences etc, but page content isn't and so * is trusted so can access preferences etc, but page content isn't and so
* cannot. * cannot.
*/ */
[scriptable, uuid(25ad7625-a481-493d-90d5-4fa081a76dc5)] [scriptable, uuid(e4a39f75-93da-4264-8bf2-1a5bfb1f2f68)]
interface nsIFeedWriter : nsISupports interface nsIFeedWriter : nsISupports
{ {
/** /**
@ -55,19 +55,8 @@ interface nsIFeedWriter : nsISupports
*/ */
void write(in nsIDOMWindow window); void write(in nsIDOMWindow window);
/**
* Show a UI for changing feed reader and options
*/
void changeOptions();
/** /**
* Uninitialize the feed writer. * Uninitialize the feed writer.
*/ */
void close(); void close();
/**
* Subscribe to the current feed.
*/
void subscribe();
}; };

Просмотреть файл

@ -205,8 +205,10 @@ FeedConverter.prototype = {
// fall through -- let feed service handle error // fall through -- let feed service handle error
case "bookmarks": case "bookmarks":
case "client": case "client":
feedService.addToClientReader(this._request, result.uri.spec); try {
return; feedService.addToClientReader(this._request, result.uri.spec);
return;
} catch(ex) { /* fallback to preview mode */ }
} }
} }
} }
@ -343,13 +345,7 @@ var FeedResultService = {
switch (handler) { switch (handler) {
case "client": case "client":
try { var clientApp = prefs.getComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile);
var clientApp =
prefs.getComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile);
}
catch (e) {
return;
}
#ifdef XP_MACOSX #ifdef XP_MACOSX
// On OS X, the built in feed dispatcher (Safari) sends feeds to other // On OS X, the built in feed dispatcher (Safari) sends feeds to other
// applications (When Default Reader is adjusted) in the following format: // applications (When Default Reader is adjusted) in the following format:

Просмотреть файл

@ -21,6 +21,7 @@
# Contributor(s): # Contributor(s):
# Ben Goodger <beng@google.com> # Ben Goodger <beng@google.com>
# Jeff Walden <jwalden+code@mit.edu> # Jeff Walden <jwalden+code@mit.edu>
# Asaf Romano <mozilla.mano@sent.com>
# #
# Alternatively, the contents of this file may be used under the terms of # Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or # either the GNU General Public License Version 2 or later (the "GPL"), or
@ -58,6 +59,7 @@ function LOG(str) {
const XML_NS = "http://www.w3.org/XML/1998/namespace" const XML_NS = "http://www.w3.org/XML/1998/namespace"
const HTML_NS = "http://www.w3.org/1999/xhtml"; const HTML_NS = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed"; const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties"; const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
@ -66,6 +68,7 @@ const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
const PREF_SELECTED_ACTION = "browser.feeds.handler"; const PREF_SELECTED_ACTION = "browser.feeds.handler";
const PREF_SELECTED_READER = "browser.feeds.handler.default"; const PREF_SELECTED_READER = "browser.feeds.handler.default";
const PREF_SKIP_PREVIEW_PAGE = "browser.feeds.skip_preview_page"; const PREF_SKIP_PREVIEW_PAGE = "browser.feeds.skip_preview_page";
const PREF_SHOW_FIRST_RUN_UI = "browser.feeds.showFirstRunUI";
const FW_CLASSID = Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}"); const FW_CLASSID = Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}");
const FW_CLASSNAME = "Feed Writer"; const FW_CLASSNAME = "Feed Writer";
@ -311,7 +314,7 @@ FeedWriter.prototype = {
} }
#endif #endif
#ifdef XP_MACOSX #ifdef XP_MACOSX
var lfm = file.QueryInterface(Components.interfaces.nsILocalFileMac); var lfm = file.QueryInterface(Components.interfaces.nsILocalFileMac_MOZILLA_1_8_BRANCH);
try { try {
return lfm.bundleDisplayName; return lfm.bundleDisplayName;
} }
@ -326,90 +329,329 @@ FeedWriter.prototype = {
return url.fileName; return url.fileName;
}, },
_initSelectedHandler: function FW__initSelectedHandler() { /**
* Get moz-icon url for a file
* @param file
* A nsIFile to look up the name of
* @returns moz-icon url of the given file as a string
*/
_getFileIconURL: function FW__getFileIconURL(file) {
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
var fph = ios.getProtocolHandler("file")
.QueryInterface(Ci.nsIFileProtocolHandler);
var urlSpec = fph.getURLSpecFromFile(file);
return "moz-icon://" + urlSpec + "?size=16";
},
_chooseClientApp: function FW__chooseClientApp() {
try {
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(this._window,
this._getString("chooseApplicationDialogTitle"),
Ci.nsIFilePicker.modeOpen);
fp.appendFilters(Ci.nsIFilePicker.filterApps);
if (fp.show() == Ci.nsIFilePicker.returnOK) {
var selectedApp = fp.file;
if (selectedApp) {
// XXXben - we need to compare this with the running instance executable
// just don't know how to do that via script...
// XXXmano TBD: can probably add this to nsIShellService
#ifdef XP_WIN
if (fp.file.leafName != "firefox.exe") {
#else
#ifdef XP_MACOSX
if (fp.file.leafName != "Firefox.app") {
#else
if (fp.file.leafName != "firefox-bin") {
#endif
#endif
var selectedAppMenuItem =
this._document.getElementById("selectedAppMenuItem");
selectedAppMenuItem.wrappedJSObject.file = selectedApp;
selectedAppMenuItem.setAttribute("label",
this._getFileDisplayName(selectedApp));
selectedAppMenuItem.setAttribute("src",
this._getFileIconURL(selectedApp));
// Show and select the selected application menuitem
selectedAppMenuItem.wrappedJSObject.hidden = false;
selectedAppMenuItem.doCommand();
return;
}
}
}
}
catch(ex) { }
// Select the (per-prefs) selected handler if no application was selected
this._setSelectedHandler();
},
_setAlwaysUseCheckedState: function FW__setAlwaysUseCheckedState() {
var checkbox = this._document.getElementById("alwaysUse");
if (checkbox) {
var alwaysUse = false;
try {
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
if (prefs.getCharPref(PREF_SELECTED_ACTION) != "ask")
alwaysUse = true;
}
catch(ex) { }
checkbox.wrappedJSObject.checked = alwaysUse;
}
},
_setAlwaysUseLabel: function FW__setAlwaysUseLabel() {
var checkbox = this._document.getElementById("alwaysUse");
if (checkbox) {
var handlersMenuList = this._document.getElementById("handlersMenuList");
if (handlersMenuList) {
var handlerName = handlersMenuList.wrappedJSObject.selectedItem.getAttribute("label");
checkbox.wrappedJSObject.label = this._getFormattedString("alwaysUse", [handlerName]);
}
}
},
/**
* See nsIDOMEventListener
*/
handleEvent: function(event) {
if (event.target.ownerDocument != this._document) {
LOG("FeedWriter.handleEvent: Someone passed the feed writer as a listener to the events of another document!");
return;
}
if (event.type == "command") {
switch(event.target.id) {
case "subscribeButton":
this.subscribe();
break;
case "chooseApplicationMenuItem":
this._chooseClientApp();
break;
default:
this._setAlwaysUseLabel();
}
}
},
_setSelectedHandler: function FW__setSelectedHandler() {
var prefs = var prefs =
Cc["@mozilla.org/preferences-service;1"]. Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch); getService(Ci.nsIPrefBranch);
var chosen =
this._document.getElementById("feedSubscribeLineHandlerChosen"); var handler = "bookmarks";
var unchosen =
this._document.getElementById("feedSubscribeLineHandlerUnchosen");
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
try { try {
var iconURI = "chrome://browser/skin/places/livemarkItem.png"; handler = prefs.getCharPref(PREF_SELECTED_READER);
var handler = prefs.getCharPref(PREF_SELECTED_ACTION); }
catch (ex) { }
if (handler == "reader") switch (handler) {
handler = prefs.getCharPref(PREF_SELECTED_READER); case "web": {
var handlersMenuList = this._document.getElementById("handlersMenuList");
if (handlersMenuList) {
var url = prefs.getCharPref(PREF_SELECTED_WEB);
var handlers =
handlersMenuList.getElementsByAttribute("webhandlerurl", url);
if (handlers.length == 0) {
LOG("FeedWriter._setSelectedHandler: selected web handler isn't in the menulist")
return;
}
switch (handler) { handlers[0].doCommand();
case "client": }
var selectedApp =
prefs.getComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile);
var displayName = this._getFileDisplayName(selectedApp);
this._setContentText("feedSubscribeHandleText", displayName);
var url = ios.newFileURI(selectedApp).QueryInterface(Ci.nsIURL);
iconURI = "moz-icon://" + url.spec;
break; break;
}
case "client": {
var selectedAppMenuItem =
this._document.getElementById("selectedAppMenuItem");
if (selectedAppMenuItem) {
try {
var selectedApp = prefs.getComplexValue(PREF_SELECTED_APP,
Ci.nsILocalFile);
} catch(ex) { }
case "web": if (selectedApp) {
var webURI = prefs.getCharPref(PREF_SELECTED_WEB); selectedAppMenuItem.file = selectedApp;
var wccr = selectedAppMenuItem.setAttribute("label",
Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"]. this._getFileDisplayName(selectedApp));
getService(Ci.nsIWebContentConverterService); selectedAppMenuItem.setAttribute("src",
var title ="Unknown"; this._getFileIconURL(selectedApp));
var handler =
wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI);
if (handler)
title = handler.name;
var uri = ios.newURI(webURI, null, null);
iconURI = uri.prePath + "/favicon.ico";
this._setContentText("feedSubscribeHandleText", title); selectedAppMenuItem.wrappedJSObject.hidden = false;
break; selectedAppMenuItem.doCommand();
#ifdef ENABLE_SYSTEM_FEED_READER_CODE
// Only show the default reader menuitem if the default reader
// isn't the selected application
var defaultHandlerMenuItem =
this._document.getElementById("defaultHandlerMenuItem");
if (defaultHandlerMenuItem) {
defaultHandlerMenuItem.wrappedJSObject.hidden =
defaultHandlerMenuItem.file.path == selectedApp.path;
}
#endif
break;
}
}
}
case "bookmarks": case "bookmarks":
this._setContentText("feedSubscribeHandleText", default: {
this._getString("liveBookmarks")); var liveBookmarksMenuItem =
break; this._document.getElementById("liveBookmarksMenuItem");
if (liveBookmarksMenuItem)
liveBookmarksMenuItem.doCommand();
}
}
},
case "ask": _initSubscriptionUI: function FW__initSubscriptionUI() {
var alwaysAsk = true; var handlersMenuPopup =
break; this._document.getElementById("handlersMenuPopup");
if (!handlersMenuPopup)
return;
// Last-selected application
var selectedApp;
menuItem = this._document.createElementNS(XUL_NS, "menuitem");
menuItem.id = "selectedAppMenuItem";
menuItem.className = "menuitem-iconic";
try {
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
selectedApp = prefs.getComplexValue(PREF_SELECTED_APP,
Ci.nsILocalFile);
if (selectedApp.exists()) {
menuItem.setAttribute("label",
this._getFileDisplayName(selectedApp));
menuItem.setAttribute("src",
this._getFileIconURL(selectedApp));
menuItem.setAttribute("handlerType", "client");
menuItem.wrappedJSObject.file = selectedApp;
}
else {
// Hide the menuitem if the last selected application doesn't exist
menuItem.setAttribute("hidden", "true");
}
}
catch(ex) {
// Hide the menuitem until an application is selected
menuItem.setAttribute("hidden", "true");
}
handlersMenuPopup.appendChild(menuItem);
#ifdef ENABLE_SYSTEM_FEED_READER_CODE
// On Windows, also list the default feed reader
var defaultReader;
try {
const WRK = Ci.nsIWindowsRegKey;
var regKey =
Cc["@mozilla.org/windows-registry-key;1"].createInstance(WRK);
regKey.open(WRK.ROOT_KEY_CLASSES_ROOT,
"feed\\shell\\open\\command", WRK.ACCESS_READ);
var path = regKey.readStringValue("");
if (path.charAt(0) == "\"") {
// Everything inside the quotes
path = path.substr(1);
path = path.substr(0, path.indexOf("\""));
}
else {
// Everything up to the first space
path = path.substr(0, path.indexOf(" "));
} }
if (!alwaysAsk) { defaultReader = Cc["@mozilla.org/file/local;1"].
unchosen.setAttribute("hidden", "true"); createInstance(Ci.nsILocalFile);
chosen.removeAttribute("hidden"); defaultReader.initWithPath(path);
var button = this._document.getElementById("feedSubscribeLink");
button.focus();
if (defaultReader.exists()) {
menuItem = this._document.createElementNS(XUL_NS, "menuitem");
menuItem.id = "defaultHandlerMenuItem";
menuItem.className = "menuitem-iconic";
menuItem.setAttribute("label",
this._getFileDisplayName(defaultReader));
menuItem.setAttribute("src",
this._getFileIconURL(defaultReader));
menuItem.setAttribute("handlerType", "client");
menuItem.wrappedJSObject.file = defaultReader;
var displayArea = // Hide the default reader item if it points to the same application
this._document.getElementById("feedSubscribeHandleText"); // as the last-selected application
displayArea.style.setProperty("background-image", if (defaultReader.path == selectedApp.path)
"url(\"" + iconURI + "\")", ""); menuItem.setAttribute("hidden", "true");
return;
} else { handlersMenuPopup.appendChild(menuItem);
// user chose a feed reader but didn't make it the default -- fall }
// through to "no selected handlers" }
catch (e) {
LOG("No feed handler registered on system");
}
#endif
// "Choose Application..." menuitem
menuItem = this._document.createElementNS(XUL_NS, "menuitem");
menuItem.id = "chooseApplicationMenuItem";
menuItem.setAttribute("label", this._getString("chooseApplicationMenuItem"));
handlersMenuPopup.appendChild(menuItem);
// separator
handlersMenuPopup.appendChild(this._document.createElementNS(XUL_NS,
"menuseparator"));
// List of web handlers
var wccr =
Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
var handlers = wccr.getContentHandlers(TYPE_MAYBE_FEED, {});
if (handlers.length != 0) {
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
for (var i = 0; i < handlers.length; ++i) {
menuItem = this._document.createElementNS(XUL_NS, "menuitem");
menuItem.className = "menuitem-iconic";
menuItem.setAttribute("label", handlers[i].name);
menuItem.setAttribute("handlerType", "web");
menuItem.setAttribute("webhandlerurl", handlers[i].uri);
var uri = ios.newURI(handlers[i].uri, null, null);
menuItem.setAttribute("src", uri.prePath + "/favicon.ico");
handlersMenuPopup.appendChild(menuItem);
} }
} catch (e) {
// prefs mismatch (e.g., handler==web but no web handler set),
// or (more likely) no prefs set yet
} }
// No selected handlers, or user hasn't made his choice the default; this._setSelectedHandler();
// make the user choose...
chosen.setAttribute("hidden", "true");
unchosen.removeAttribute("hidden");
this._document.getElementById("feedHeader").setAttribute("firstrun", "true");
var button = this._document.getElementById("feedChooseInitialReader"); // "Always use..." checkbox initial state
button.focus(); this._setAlwaysUseCheckedState();
this._setAlwaysUseLabel();
// We update the "Always use.." checkbox label whenever the selected item
// in the list is changed
handlersMenuPopup.addEventListener("command", this, false);
// Set up the "Subscribe Now" button
this._document
.getElementById("subscribeButton")
.addEventListener("command", this, false);
// first-run ui
var showFirstRunUI = true;
try {
showFirstRunUI = prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI);
}
catch (ex) { }
if (showFirstRunUI) {
var feedHeader = this._document.getElementById("feedHeader");
if (feedHeader)
feedHeader.setAttribute("firstrun", "true");
prefs.setBoolPref(PREF_SHOW_FIRST_RUN_UI, false);
}
}, },
/** /**
@ -447,13 +689,14 @@ FeedWriter.prototype = {
LOG("Subscribe Preview: feed uri = " + this._window.location.href); LOG("Subscribe Preview: feed uri = " + this._window.location.href);
// Set up the displayed handler // Set up the subscription UI
this._initSelectedHandler(); this._initSubscriptionUI();
var prefs = var prefs =
Cc["@mozilla.org/preferences-service;1"]. Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2); getService(Ci.nsIPrefBranch2);
prefs.addObserver(PREF_SELECTED_ACTION, this, false); prefs.addObserver(PREF_SELECTED_ACTION, this, false);
prefs.addObserver(PREF_SELECTED_READER, this, false); prefs.addObserver(PREF_SELECTED_READER, this, false);
prefs.addObserver(PREF_SELECTED_WEB, this, false);
prefs.addObserver(PREF_SELECTED_APP, this, false); prefs.addObserver(PREF_SELECTED_APP, this, false);
// Set up the feed content // Set up the feed content
@ -475,23 +718,6 @@ FeedWriter.prototype = {
} }
}, },
/**
* See nsIFeedWriter
*/
changeOptions: function FW_changeOptions() {
var paramBlock =
Cc["@mozilla.org/embedcomp/dialogparam;1"].
createInstance(Ci.nsIDialogParamBlock);
// Used to tell the preview page that the user chose to subscribe with
// a particular reader, and so it should subscribe now.
const PARAM_USER_SUBSCRIBED = 0;
paramBlock.SetInt(PARAM_USER_SUBSCRIBED, 0);
this._window.openDialog("chrome://browser/content/feeds/options.xul", "",
"modal,centerscreen", "subscribe", paramBlock);
if (paramBlock.GetInt(PARAM_USER_SUBSCRIBED) == 1)
this.subscribe();
},
/** /**
* See nsIFeedWriter * See nsIFeedWriter
*/ */
@ -503,6 +729,7 @@ FeedWriter.prototype = {
getService(Ci.nsIPrefBranch2); getService(Ci.nsIPrefBranch2);
prefs.removeObserver(PREF_SELECTED_ACTION, this); prefs.removeObserver(PREF_SELECTED_ACTION, this);
prefs.removeObserver(PREF_SELECTED_READER, this); prefs.removeObserver(PREF_SELECTED_READER, this);
prefs.removeObserver(PREF_SELECTED_WEB, this);
prefs.removeObserver(PREF_SELECTED_APP, this); prefs.removeObserver(PREF_SELECTED_APP, this);
}, },
@ -510,50 +737,84 @@ FeedWriter.prototype = {
* See nsIFeedWriter * See nsIFeedWriter
*/ */
subscribe: function FW_subscribe() { subscribe: function FW_subscribe() {
// Subscribe to the feed using the selected handler and save prefs
var prefs = var prefs =
Cc["@mozilla.org/preferences-service;1"]. Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch); getService(Ci.nsIPrefBranch);
try { var defaultHandler = "reader";
var handler = prefs.getCharPref(PREF_SELECTED_ACTION); var useAsDefault = this._document.getElementById("alwaysUse")
if (handler == "reader" || handler == "ask") .getAttribute("checked");
// the actual handler will be stored in the reader preference
handler = prefs.getCharPref(PREF_SELECTED_READER); var selectedHandler = this._document.getElementById("handlersMenuList")
} .wrappedJSObject.selectedItem;
catch (e) { if (selectedHandler.hasAttribute("webhandlerurl")) {
// Something's bogus in preferences -- make the user fix it var webURI = selectedHandler.getAttribute("webhandlerurl");
this.changeOptions(); prefs.setCharPref(PREF_SELECTED_READER, "web");
return; prefs.setCharPref(PREF_SELECTED_WEB, webURI);
}
if (handler == "web") {
var webURI = prefs.getCharPref(PREF_SELECTED_WEB);
var wccr = var wccr =
Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"]. Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService); getService(Ci.nsIWebContentConverterService);
var handler = var handler = wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI);
wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI); if (handler) {
this._window.location.href = if (useAsDefault)
handler.getHandlerURI(this._window.location.href); wccr.setAutoHandler(TYPE_MAYBE_FEED, handler);
this._window.location.href =
handler.getHandlerURI(this._window.location.href);
}
} }
else { else {
// handles bookmarks, client cases switch (selectedHandler.id) {
var request = case "selectedAppMenuItem":
this._window.QueryInterface(Ci.nsIInterfaceRequestor). #ifdef ENABLE_SYSTEM_FEED_READER_CODE
getInterface(Ci.nsIWebNavigation). case "defaultHandlerMenuItem":
QueryInterface(Ci.nsIDocShell).currentDocumentChannel; #endif
var feedService = prefs.setCharPref(PREF_SELECTED_READER, "client");
Cc["@mozilla.org/browser/feeds/result-service;1"]. prefs.setComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile,
getService(Ci.nsIFeedResultService); selectedHandler.file);
break;
case "liveBookmarksMenuItem":
defaultHandler = "bookmarks";
prefs.setCharPref(PREF_SELECTED_READER, "bookmarks");
break;
}
var request = this._window
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.currentDocumentChannel;
var feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
getService(Ci.nsIFeedResultService);
feedService.addToClientReader(request, this._window.location.href); feedService.addToClientReader(request, this._window.location.href);
} }
// If "Always use..." is checked, we should set PREF_SELECTED_ACTION
// to either "reader" (If a web reader or if an application is selected), or
// to "bookmarks" (if the live bookmarks option is selected).
// Otherwise, we should set it to "ask"
if (useAsDefault)
prefs.setCharPref(PREF_SELECTED_ACTION, defaultHandler);
else
prefs.setCharPref(PREF_SELECTED_ACTION, "ask");
}, },
/** /**
* See nsIObserver * See nsIObserver
*/ */
observe: function FW_observe(subject, topic, data) { observe: function FW_observe(subject, topic, data) {
if (topic == "nsPref:changed") if (topic == "nsPref:changed") {
this._initSelectedHandler(); switch (data) {
case PREF_SELECTED_READER:
case PREF_SELECTED_WEB:
case PREF_SELECTED_APP:
this._setSelectedHandler();
break;
case PREF_SELECTED_ACTION:
this._setAlwaysUseCheckedState();
}
}
}, },
/** /**
@ -577,6 +838,7 @@ FeedWriter.prototype = {
QueryInterface: function FW_QueryInterface(iid) { QueryInterface: function FW_QueryInterface(iid) {
if (iid.equals(Ci.nsIFeedWriter) || if (iid.equals(Ci.nsIFeedWriter) ||
iid.equals(Ci.nsIClassInfo) || iid.equals(Ci.nsIClassInfo) ||
iid.equals(Ci.nsIDOMEventListener) ||
iid.equals(Ci.nsISupports)) iid.equals(Ci.nsISupports))
return this; return this;
throw Cr.NS_ERROR_NO_INTERFACE; throw Cr.NS_ERROR_NO_INTERFACE;

Просмотреть файл

@ -20,6 +20,7 @@
# the Initial Developer. All Rights Reserved. # the Initial Developer. All Rights Reserved.
# #
# Contributor(s): # Contributor(s):
# Asaf Romano <mozilla.mano@sent.com>
# #
# Alternatively, the contents of this file may be used under the terms of # Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or # either the GNU General Public License Version 2 or later (the "GPL"), or
@ -35,315 +36,198 @@
# #
# ***** END LICENSE BLOCK ***** # ***** END LICENSE BLOCK *****
#ifndef XP_MACOSX
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cr = Components.results;
var TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
#endif
/*
* Preferences:
*
* browser.feeds.handler
* - "bookmarks", "reader" (clarified further using the .default preference),
* or "ask" -- indicates the default handler being used to process feeds
*
* browser.feeds.handler.default
* - "bookmarks", "client" or "web" -- indicates the chosen feed reader used
* to display feeds, either transiently (i.e., when the "use as default"
* checkbox is unchecked, corresponds to when browser.feeds.handler=="ask")
* or more permanently (i.e., the item displayed in the dropdown in Feeds
* preferences)
*
* browser.feeds.handler.webservice
* - the URL of the currently selected web service used to read feeds
*
* browser.feeds.handlers.application
* - nsILocalFile, stores the current client-side feed reading app if one has
* been chosen
*/
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
const PREF_SELECTED_ACTION = "browser.feeds.handler";
const PREF_SELECTED_READER = "browser.feeds.handler.default";
var gFeedsPane = { var gFeedsPane = {
/** element: function(aID) {
* Ensures feed reader list is initialized before Feed Reader UI is return document.getElementById(aID);
* filled from preferences. },
*/
_feedReadersInited: false,
_pane: null, /* ........ QueryInterface .............. */
QueryInterface: function(aIID) {
if (aIID.equals(Ci.nsISupports) ||
aIID.equals(Ci.nsIObserver) ||
aIID.equals(Ci.nsISupportsWeakReference))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
/**
* See nsIObserver
*/
observe: function(aSubject, aTopic, aData) {
if (aTopic != "nsPref:changed" || aData != PREF_SELECTED_WEB)
return;
if (this.element(PREF_SELECTED_ACTION).value == "reader") {
var wccr =
Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
var handlerURL = this.element(PREF_SELECTED_WEB).valueFromPreferences;
var handler =
wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, handlerURL);
if (handler)
wccr.setAutoHandler(TYPE_MAYBE_FEED, handler);
}
},
/** /**
* Initializes this. * Initializes this.
*/ */
init: function () init: function () {
{ var _delayedPaneLoad = function(self) {
this._pane = document.getElementById("paneFeeds"); self._initFeedReaders();
self.updateSelectedReader();
this._initFeedReaders();
this._attachPreferenceBindings();
this.onReaderPrefsChange();
},
_attachPreferenceBindings: function ()
{
var feedClick = document.getElementById("feedClick");
feedClick.setAttribute("preference", "browser.feeds.handler");
var reader = document.getElementById("chooseFeedReader");
reader.setAttribute("preference", "browser.feeds.handler.default");
},
/*
* Preferences:
*
* browser.feeds.handler
* - "bookmarks", "reader" (clarified further using the .default preference),
* or "ask" -- indicates the default handler being used to process feeds
* browser.feeds.handler.default
* - "bookmarks", "client" or "web" -- indicates the chosen feed reader used
* to display feeds, either transiently (i.e., when the "use as default"
* checkbox is unchecked, corresponds to when browser.feeds.handler=="ask")
* or more permanently (i.e., the item displayed in the dropdown in Feeds
* preferences)
* browser.feeds.handler.webservice
* - the URL of the currently selected web service used to read feeds
* browser.feeds.handlers.application
* - nsILocalFile, stores the current client-side feed reading app if one has
* been chosen
*/
/**
* Converts the selected radio button into a preference value, sets any
* ancillary preferences (such as web/client readers), and returns the new
* value of browser.feeds.handler.
*/
writeFeedAction: function ()
{
var app = document.getElementById("browser.feeds.handlers.application");
var web = document.getElementById("browser.feeds.handlers.webservice");
var selReader = document.getElementById("browser.feeds.handler.default");
var feedAction = document.getElementById("feedClick").value;
switch (feedAction) {
case "reader":
var menu = document.getElementById("chooseFeedReader");
var reader = menu.selectedItem;
var type = reader.getAttribute("type");
switch (type) {
case "client":
app.value = reader.getAttribute("value");
selReader.value = type;
break;
case "web":
web.value = reader.getAttribute("value");
selReader.value = type;
break;
default:
throw "Unhandled reader type: " + feedAction;
}
break;
default:
throw "Unhandled feed action: " + feedAction;
case "ask":
case "bookmarks":
break;
} }
return feedAction; setTimeout(_delayedPaneLoad, 0, this);
// For web readers, we need to call setAutoHandler if the
// preview page should be skipped (i.e. PREF_SELECTED_ACTION="reader")
// To do so, we've to add a pref-observer in order to be notified on
// actual pref-changes (i.e. not on pref changes which may not take
// affect when the prefwindow is closed)
var prefBranch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
prefBranch.addObserver(PREF_SELECTED_WEB, this, true);
}, },
/** /**
* Converts the value of browser.feeds.handler.default into the appropriate * Populates the UI list of available feed readers.
* menu item in the menulist of readers, returning the value of that item.
*/ */
readFeedReader: function () _initFeedReaders: function() {
{ this.updateSelectedApplicationInfo();
var reader = document.getElementById("browser.feeds.handler");
var selReader = document.getElementById("browser.feeds.handler.default");
var web = document.getElementById("browser.feeds.handlers.webservice");
var app = document.getElementById("browser.feeds.handlers.application");
var menu = document.getElementById("chooseFeedReader");
// we have the type of reader being used -- get its corresponding value
// and return it
var defaultHandler = selReader.value;
switch (defaultHandler) {
case "web":
return web.value;
break;
case "client":
return app.value.path || app.value;
break;
case "bookmarks":
// we could handle this case with a preference specifically for the
// chosen reader, but honestly -- is it really worth it?
default:
menu.selectedIndex = 0;
return menu.value;
}
},
/**
* Determines the reader displayed in the feed reader menulist and stores that
* reader to preferences.
*/
writeFeedReader: function ()
{
var menu = document.getElementById("chooseFeedReader");
var reader = document.getElementById("browser.feeds.handler");
var selReader = document.getElementById("browser.feeds.handler.default");
var web = document.getElementById("browser.feeds.handlers.webservice");
var app = document.getElementById("browser.feeds.handlers.application");
var selected = menu.selectedItem;
var type = selected.getAttribute("type");
switch (type) {
case "web":
web.value = selected.value;
break;
case "client":
app.value = selected.value;
break;
case "add":
// we're choosing a new client app
var newApp = this._addNewReader();
if (newApp) {
this._initFeedReaders();
app.value = newApp;
type = "client";
} else {
type = selReader.value; // return to existing value
}
break;
default:
throw "Unhandled type: " + type;
}
return type;
},
/**
* Syncs current UI with the values stored in preferences. This is necessary
* because the UI items are represented using multiple preferences, so the
* sync can't happen automatically without extra code.
*/
onReaderPrefsChange: function ()
{
var handler = document.getElementById("browser.feeds.handler");
var selReader = document.getElementById("browser.feeds.handler.default");
handler.updateElements();
selReader.updateElements();
},
/**
* Populates the UI list of available feed readers. The current feed reader
* must be manually selected in the list.
*/
_initFeedReaders: function ()
{
// XXX make UI a listbox with icons, etc!
const Cc = Components.classes, Ci = Components.interfaces;
var readers = [];
// CLIENT-SIDE
// first, get the client reader in preferences
try {
var clientApp = document.getElementById("clientApp");
var app = document.getElementById("browser.feeds.handlers.application");
clientApp.file = app.value;
var client = { type: "client",
path: clientApp.file.path,
name: clientApp.label,
icon: clientApp.image };
readers.push(client);
}
catch (e) { /* no client feed reader set */ }
// get any readers stored in system preferences
#ifdef XP_WIN
try {
// look for current feed handler in the Windows registry
const WRK = Ci.nsIWindowsRegKey;
var regKey = Cc["@mozilla.org/windows-registry-key;1"]
.createInstance(WRK);
regKey.open(WRK.ROOT_KEY_CLASSES_ROOT,
"feed\\shell\\open\\command",
WRK.ACCESS_READ);
var path = regKey.readStringValue("");
if (path.charAt(0) == "\"") {
// Everything inside the quotes
path = path.substr(1);
path = path.substr(0, path.indexOf("\""));
}
else {
// Everything up to the first space
path = path.substr(0, path.indexOf(" "));
}
var file = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
file.initWithPath(path);
clientApp.file = file;
client = { type: "client",
path: clientApp.file.path,
name: clientApp.label,
icon: clientApp.image };
readers.push(client);
}
catch (e) { /* no feed: handler on system */ }
#endif
// WEB SERVICES
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
var wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"]
.getService(Ci.nsIWebContentConverterService);
var ios = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var wccr =
Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
var handlers = wccr.getContentHandlers(TYPE_MAYBE_FEED, {}); var handlers = wccr.getContentHandlers(TYPE_MAYBE_FEED, {});
for (var i = 0; i < handlers.length; i++) { if (handlers.length == 0)
return;
var appRow = this.element("selectedApplicationListitem");
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
for (var i = 0; i < handlers.length; ++i) {
var row = document.createElementNS(kXULNS, "listitem");
row.className = "listitem-iconic";
row.setAttribute("label", handlers[i].name);
row.setAttribute("webhandlerurl", handlers[i].uri);
var uri = ios.newURI(handlers[i].uri, null, null); var uri = ios.newURI(handlers[i].uri, null, null);
var webReader = { type: "web", row.setAttribute("image", uri.prePath + "/favicon.ico");
path: uri.spec,
name: handlers[i].name, appRow.parentNode.appendChild(row);
icon: uri.prePath + "/favicon.ico" };
readers.push(webReader);
} }
// Now that we have all the readers, sort them and add them to the UI
var menulist = document.getElementById("chooseFeedReader");
menulist.textContent = ""; // clear out any previous elements
var popup = document.createElement("menupopup");
// insert a blank item to indicate no selected preference, and an
// "add" item to allow addition of new readers
var bundle = document.getElementById("bundlePreferences");
readers.sort(function(a, b) { return (a.name.toLowerCase() < b.name.toLowerCase()) ? -1 : 1; });
for (var i = 0; i < readers.length; i++) {
var reader = readers[i];
item = document.createElement("menuitem");
item.setAttribute("label", reader.name);
item.setAttribute("value", reader.path);
item.setAttribute("type", reader.type);
item.setAttribute("path", reader.path);
popup.appendChild(item);
}
// put "add new reader" at end, since it won't be used much
item = document.createElement("menuitem");
item.setAttribute("label", bundle.getString("addReader"));
item.setAttribute("value", "add");
item.setAttribute("type", "add");
popup.appendChild(item);
menulist.appendChild(popup);
}, },
/** /**
* Displays a prompt from which the user may add a new (client) feed reader. * Updates the label and image of the client feed reader listitem
*
* @returns null if no new reader was added, or the path to the application if
* one was added
*/ */
_addNewReader: function () updateSelectedApplicationInfo: function() {
{ var appItemCell = this.element("selectedApplicationCell");
const Cc = Components.classes, Ci = Components.interfaces; var selectedAppFilefield = this.element("selectedAppFilefield")
selectedAppFilefield.file = this.element(PREF_SELECTED_APP).value;
if (selectedAppFilefield.file) {
appItemCell.setAttribute("label", selectedAppFilefield.label);
appItemCell.setAttribute("image", selectedAppFilefield.image);
}
else {
var noAppString =
this.element("stringbundle").getString("noApplicationSelected");
appItemCell.setAttribute("label", noAppString);
appItemCell.setAttribute("image", "");
}
},
/**
* Selects a item in the list without triggering a preference change.
*
* @param aItem
* the listitem to be selected
*/
_silentSelectReader: function(aItem) {
var readers = this.element("readers");
readers.setAttribute("suppressonselect", "true");
readers.selectItem(aItem);
readers.removeAttribute("suppressonselect");
},
/**
* Helper for updateSelectedReader. Syncs the selected item in the readers
* list with value stored invalues stored in PREF_SELECTED_WEB
*/
_updateSelectedWebHandlerItem: function() {
// We should select the new web handler only if the default handler
// is "web"
var readers = this.element("readers")
var readerElts =
readers.getElementsByAttribute("webhandlerurl",
this.element(PREF_SELECTED_WEB).value);
// XXXmano: handle the addition of a new web handler
if (readerElts.length > 0)
this._silentSelectReader(readerElts[0]);
},
/**
* Syncs the selected item in the readers list with the values stored in
* preferences.
*/
updateSelectedReader: function() {
var defaultReader = this.element(PREF_SELECTED_READER).value ||
"bookmarks";
switch (defaultReader) {
case "bookmarks":
this._silentSelectReader(this.element("liveBookmarksListItem"));
break;
case "client":
this._silentSelectReader(this.element("selectedApplicationListitem"));
break;
case "web":
this._updateSelectedWebHandlerItem();
break;
}
},
/**
* Displays a prompt from which the user may choose an a (client) feed reader.
*/
chooseClientApp: function () {
var fp = Cc["@mozilla.org/filepicker;1"] var fp = Cc["@mozilla.org/filepicker;1"]
.createInstance(Ci.nsIFilePicker); .createInstance(Ci.nsIFilePicker);
fp.init(window, document.title, Ci.nsIFilePicker.modeOpen); fp.init(window, document.title, Ci.nsIFilePicker.modeOpen);
@ -352,14 +236,79 @@ var gFeedsPane = {
// XXXben - we need to compare this with the running instance executable // XXXben - we need to compare this with the running instance executable
// just don't know how to do that via script... // just don't know how to do that via script...
if (fp.file.leafName == "firefox.exe") if (fp.file.leafName == "firefox.exe")
return null; return;
var pref = document.getElementById("browser.feeds.handlers.application"); this.element(PREF_SELECTED_APP).value = fp.file;
pref.value = fp.file; this.element(PREF_SELECTED_READER).value = "client";
return fp.file.path;
} }
return null; },
/**
* Disables the readers list if "Show preview..." is selected, enables
* it otherwise.
*/
onReadingMethodSelect: function() {
var disableList = this.element("readingMethod").value == "ask";
this.element("readers").disabled = disableList;
this.element("chooseClientApp").disabled = disableList;
},
/**
* Maps the value of PREF_SELECTED_ACTION to the parallel
* value in the radiogroup
*/
onReadingMethodSyncFromPreference: function() {
var pref = this.element(PREF_SELECTED_ACTION);
var newVal = pref.instantApply ? pref.valueFromPreferences : pref.value;
if (newVal != "ask")
return "reader";
return "ask";
},
/**
* Returns the value to be used for PREF_SELECTED_ACTION
* according to the current UI state.
*/
onReadingMethodSyncToPreference: function() {
var readers = this.element("readers");
// A reader must be choosed in order to skip the preview page
if (this.element("readingMethod").value == "ask" ||
!readers.currentItem)
return "ask";
if (readers.currentItem.id == "liveBookmarksListItem")
return "bookmarks";
return "reader";
},
/**
* Syncs PREF_SELECTED_READER with the selected item in the readers list
* Also updates PREF_SELECTED_ACTION if necessary
*/
writeSelectedFeedReader: function() {
// Force update of the action pref. This is needed for the case in which
// the user flipped from a reader to live bookmarks or vice-versa
this.element(PREF_SELECTED_ACTION).value =
this.onReadingMethodSyncToPreference();
var currentItem = this.element("readers").currentItem;
if (currentItem.hasAttribute("webhandlerurl")) {
this.element(PREF_SELECTED_WEB).value =
currentItem.getAttribute("webhandlerurl");
this.element(PREF_SELECTED_READER).value = "web";
}
else {
switch (currentItem.id) {
case "liveBookmarksListItem":
this.element(PREF_SELECTED_READER).value = "bookmarks";
break;
case "selectedApplicationListitem":
// PREF_SELECTED_APP is saved in chooseClientApp
this.element(PREF_SELECTED_READER).value = "client";
}
}
} }
}; };

Просмотреть файл

@ -22,6 +22,7 @@
# the Initial Developer. All Rights Reserved. # the Initial Developer. All Rights Reserved.
# #
# Contributor(s): # Contributor(s):
# Asaf Romano <mozilla.mano@sent.com>
# #
# Alternatively, the contents of this file may be used under the terms of # Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or # either the GNU General Public License Version 2 or later (the "GPL"), or
@ -38,17 +39,17 @@
# ***** END LICENSE BLOCK ***** # ***** END LICENSE BLOCK *****
<!DOCTYPE overlay [ <!DOCTYPE overlay [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
<!ENTITY % feedsDTD SYSTEM "chrome://browser/locale/preferences/feeds.dtd"> <!ENTITY % feedsDTD SYSTEM "chrome://browser/locale/preferences/feeds.dtd">
%brandDTD;
%feedsDTD; %feedsDTD;
]> ]>
<overlay id="FeedsPaneOverlay" <overlay id="FeedsPaneOverlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<prefpane id="paneFeeds" onpaneload="gFeedsPane.init();" <prefpane id="paneFeeds"
helpTopic="prefs-feeds" helpURI="chrome://browser/locale/help/help.rdf"> onpaneload="gFeedsPane.init();"
helpTopic="prefs-feeds"
helpURI="chrome://browser/locale/help/help.rdf">
<preferences id="feedsPreferences"> <preferences id="feedsPreferences">
<preference id="browser.feeds.handler" <preference id="browser.feeds.handler"
@ -56,48 +57,58 @@
type="string"/> type="string"/>
<preference id="browser.feeds.handler.default" <preference id="browser.feeds.handler.default"
name="browser.feeds.handler.default" name="browser.feeds.handler.default"
onchange="gFeedsPane.updateSelectedReader();"
type="string"/> type="string"/>
<preference id="browser.feeds.handlers.application" <preference id="browser.feeds.handlers.application"
name="browser.feeds.handlers.application" name="browser.feeds.handlers.application"
type="file" onchange="gFeedsPane.updateSelectedApplicationInfo();"
onchange="gFeedsPane.onReaderPrefsChange();"/> type="file"/>
<preference id="browser.feeds.handlers.webservice" <preference id="browser.feeds.handlers.webservice"
name="browser.feeds.handlers.webservice" name="browser.feeds.handlers.webservice"
type="string" onchange="gFeedsPane.updateSelectedReader();"
onchange="gFeedsPane.onReaderPrefsChange();"/> type="string"/>
</preferences> </preferences>
<script type="application/x-javascript" src="chrome://browser/content/preferences/feeds.js"/> <script type="application/x-javascript" src="chrome://browser/content/preferences/feeds.js"/>
<!-- to ease display of file stats, never displayed --> <filefield class="indent" id="selectedAppFilefield" disabled="true" hidden="true"/>
<filefield class="indent" id="clientApp" disabled="true" collapsed="true"/> <stringbundle id="stringbundle" src="chrome://browser/locale/preferences/feeds.properties"/>
<hbox id="chooseReaderBox" align="center"> <label value="&feedClick.label;"/>
<label control="chooseFeedReader" <radiogroup id="readingMethod"
accesskey="&feedReader.accesskey;">&feedReader.label;</label> class="indent"
preference="browser.feeds.handler"
<!-- preference: browser.feeds.handler.default, added after onload onsyncfrompreference="return gFeedsPane.onReadingMethodSyncFromPreference();"
because the menu is dynamically populated --> onsynctopreference="return gFeedsPane.onReadingMethodSyncToPreference();"
<menulist id="chooseFeedReader" onselect="gFeedsPane.onReadingMethodSelect();">
onsyncfrompreference="return gFeedsPane.readFeedReader();" <radio value="ask"
onsynctopreference="return gFeedsPane.writeFeedReader();"/> label="&showPreview.label;"
</hbox> accesskey="&showPreview.accesskey;"/>
<radio value="reader"
<separator class="thin"/> label="&subscribeUsing.label;"
accesskey="&subscribeUsing.accesskey;"/>
<label id="feedClickLabel" <hbox id="readerContainer" class="indent" flex="1">
control="feedClick">&feedClick.label;</label> <listbox id="readers" rows="5" flex="1"
onselect="gFeedsPane.writeSelectedFeedReader();">
<!-- preference: browser.feeds.handler, added after onload due to dynamic <listcols>
population issues --> <listcol flex="1"/>
<radiogroup id="feedClick" class="indent" <listcol/>
</listcols>
onsynctopreference="return gFeedsPane.writeFeedAction();"> <listitem id="liveBookmarksListItem"
<radio label="&ask.label;" accesskey="&ask.accesskey;" value="ask"/> label="&liveBookmarks.label;"
<radio label="&subLiveBookmark.label;" accesskey="&subLiveBookmark.accesskey;" value="bookmarks"/> class="listitem-iconic"
<radio label="&subReader.label;" accesskey="&subReader.accesskey;" value="reader"/> image="chrome://browser/skin/page-livemarks.png"/>
<listitem id="selectedApplicationListitem" allowevents="true">
<listcell id="selectedApplicationCell" class="listcell-iconic"/>
<listcell>
<button id="chooseClientApp"
label="&chooseApplication.label;"
accesskey="&chooseApplication.accesskey;"
oncommand="gFeedsPane.chooseClientApp();"/>
</listcell>
</listitem>
</listbox>
</hbox>
</radiogroup> </radiogroup>
</prefpane> </prefpane>
</overlay> </overlay>

Просмотреть файл

Просмотреть файл

@ -10,24 +10,10 @@
"You can subscribe to this feed to receive updates when this content changes."> "You can subscribe to this feed to receive updates when this content changes.">
<!ENTITY feedSubscribeNow <!ENTITY feedSubscribeNow
"Subscribe Now"> "Subscribe Now">
<!ENTITY feedSubscribeUsing <!ENTITY subscribeUsing
"using: "> "Subscribe to this feed using ">
<!ENTITY feedSubscribeChangeSubscribeOptions <!ENTITY feedLiveBookmarks
"Change Reader..."> "Live Bookmarks">
<!ENTITY feedSubscribeDoneChangingOptions
"&#171; Done">
<!ENTITY feedSubscribePreferredReader
"Choose a Feed Reader:">
<!ENTITY feedSubscribeReaderClient
"Use an Application:">
<!ENTITY feedSubscribeReaderWeb
"Use a Web Site:">
<!ENTITY feedSubscribeReaderLiveBookmarks
"Use Firefox Live Bookmarks">
<!ENTITY feedSubscribeChooseSubscribeOptions
"Choose a Feed Reader">
<!ENTITY feedSubscribeChooseInfo
"to subscribe to this feed.">
<!ENTITY error.title <!ENTITY error.title
"Error Processing Feed"> "Error Processing Feed">
<!ENTITY error.message <!ENTITY error.message

Просмотреть файл

@ -1,8 +1,10 @@
linkTitleTextFormat=Go to %S linkTitleTextFormat=Go to %S
liveBookmarks=Live Bookmarks
addHandler=Add "%S" as a feed reader? addHandler=Add "%S" as a feed reader?
addHandlerYes=Yes addHandlerYes=Yes
addHandlerNo=No addHandlerNo=No
handlerRegistered="%S" is already registered as a Feed Reader handlerRegistered="%S" is already registered as a Feed Reader
liveBookmarks=Live Bookmarks
subscribeNow=Subscribe Now subscribeNow=Subscribe Now
subscribeTitle=Choose a Feed Reader chooseApplicationMenuItem=Choose Application...
chooseApplicationDialogTitle=Choose Application
alwaysUse=Always use %S to subscribe to feeds

Просмотреть файл

@ -1,10 +0,0 @@
<!ENTITY feedReader.label "Feed Reader:">
<!ENTITY feedReader.accesskey "F">
<!ENTITY feedClick.label "When I click on a web feed:">
<!ENTITY ask.label "Ask me what to use">
<!ENTITY ask.accesskey "A">
<!ENTITY subLiveBookmark.label "Always subscribe with a Live Bookmark">
<!ENTITY subLiveBookmark.accesskey "L">
<!ENTITY subReader.label "Always subscribe using the Feed Reader">
<!ENTITY subReader.accesskey "R">

Просмотреть файл

@ -46,7 +46,6 @@
#endif #endif
#ifdef MOZ_FEEDS #ifdef MOZ_FEEDS
locale/browser/feeds/subscribe.dtd (%chrome/browser/feeds/subscribe.dtd) locale/browser/feeds/subscribe.dtd (%chrome/browser/feeds/subscribe.dtd)
locale/browser/feeds/options.dtd (%chrome/browser/feeds/options.dtd)
locale/browser/feeds/addFeedReader.dtd (%chrome/browser/feeds/addFeedReader.dtd) locale/browser/feeds/addFeedReader.dtd (%chrome/browser/feeds/addFeedReader.dtd)
locale/browser/feeds/subscribe.properties (%chrome/browser/feeds/subscribe.properties) locale/browser/feeds/subscribe.properties (%chrome/browser/feeds/subscribe.properties)
#endif #endif
@ -63,6 +62,7 @@
locale/browser/preferences/downloadactions.dtd (%chrome/browser/preferences/downloadactions.dtd) locale/browser/preferences/downloadactions.dtd (%chrome/browser/preferences/downloadactions.dtd)
locale/browser/preferences/fallbackEULA.dtd (%chrome/browser/preferences/fallbackEULA.dtd) locale/browser/preferences/fallbackEULA.dtd (%chrome/browser/preferences/fallbackEULA.dtd)
locale/browser/preferences/feeds.dtd (%chrome/browser/preferences/feeds.dtd) locale/browser/preferences/feeds.dtd (%chrome/browser/preferences/feeds.dtd)
locale/browser/preferences/feeds.properties (%chrome/browser/preferences/feeds.properties)
locale/browser/preferences/fonts.dtd (%chrome/browser/preferences/fonts.dtd) locale/browser/preferences/fonts.dtd (%chrome/browser/preferences/fonts.dtd)
locale/browser/preferences/main.dtd (%chrome/browser/preferences/main.dtd) locale/browser/preferences/main.dtd (%chrome/browser/preferences/main.dtd)
locale/browser/preferences/languages.dtd (%chrome/browser/preferences/languages.dtd) locale/browser/preferences/languages.dtd (%chrome/browser/preferences/languages.dtd)

Просмотреть файл

@ -217,10 +217,20 @@ a[href] img {
-moz-padding-end: 14px; -moz-padding-end: 14px;
} }
.feedSubscribeButton { #handlersMenuList > menupopup > menuitem {
font-weight: bold; -moz-padding-start: 23px;
list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png");
} }
.feedSubscribeButton .button-icon {
-moz-margin-end: 3px; #handlersMenuList > menupopup > menuitem.menuitem-iconic {
-moz-padding-start: 2px;
}
#handlersMenuList > menupopup > .menuitem-iconic > .menu-iconic-left {
display: -moz-box;
min-width: 16px;
-moz-padding-end: 2px;
}
#feedHeader[dir="rtl"] #handlersMenuList > menupopup {
direction: rtl;
} }