зеркало из https://github.com/mozilla/snowl.git
move subscribe function into Options, various glue to support this, localize subscribe status messages. only feed subscriptions (via rss icon/link click feed preview handler) displayed in a page now.
This commit is contained in:
Родитель
d048b55d5d
Коммит
8df73548c8
|
@ -251,13 +251,11 @@ let Snowl = {
|
|||
},
|
||||
|
||||
onSubscribe: function() {
|
||||
gBrowser.selectedTab =
|
||||
gBrowser.addTab("chrome://snowl/content/subscribe.xul");
|
||||
openPreferences("paneSnowl", { "snowlTab" : "snowlPrefsTabSubscribe" });
|
||||
},
|
||||
|
||||
onImportOPML: function() {
|
||||
gBrowser.selectedTab =
|
||||
gBrowser.addTab("chrome://snowl/content/subscribe.xul?tab=opml");
|
||||
Subscriber.importOPML();
|
||||
},
|
||||
|
||||
onExportOPML: function() {
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
id="snowlBrowserOverlay">
|
||||
|
||||
<script type="application/javascript" src="chrome://snowl/content/browser.js"/>
|
||||
<!-- Include strands.js and subscribe.js for onImportOPML -->
|
||||
<script type="application/javascript" src="chrome://snowl/content/strands.js"/>
|
||||
<script type="application/javascript" src="chrome://snowl/content/subscribe.js"/>
|
||||
|
||||
<menupopup id="viewSidebarMenu">
|
||||
<menuitem observes="viewSnowlList" label="&listViewSidebarMenuItem.label;"
|
||||
|
|
|
@ -38,11 +38,13 @@
|
|||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/x-javascript"><![CDATA[
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
var win = wm.getMostRecentWindow("navigator:browser");
|
||||
<script type="application/x-javascript"><![CDATA[
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
var win = wm.getMostRecentWindow("navigator:browser");
|
||||
try {
|
||||
win.openPreferences("paneSnowl");
|
||||
window.close();
|
||||
]]></script>
|
||||
} catch (e) {};
|
||||
window.close();
|
||||
]]></script>
|
||||
</dialog>
|
||||
|
|
|
@ -60,3 +60,38 @@ radio[pane="paneSnowl"]:active {
|
|||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Subscribe tab */
|
||||
|
||||
#statusIcon[status="active"] {
|
||||
list-style-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
}
|
||||
|
||||
#statusIcon[status="complete"] {
|
||||
list-style-image: url("chrome://snowl/content/icons/tick.png");
|
||||
}
|
||||
|
||||
#statusIcon[status="error"] {
|
||||
list-style-image: url("chrome://global/skin/icons/error-16.png");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Subscribe page */
|
||||
|
||||
content {
|
||||
border: 1px solid threedshadow;
|
||||
padding: 1em;
|
||||
-moz-border-radius: 10px;
|
||||
background-color: -moz-field;
|
||||
color: -moz-fieldtext;
|
||||
width: 44em;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-size: 2em;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5em;
|
||||
border-bottom: 1px solid threedlightshadow;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,3 +38,52 @@ const Cc = Components.classes;
|
|||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
// modules that come with Firefox
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
// modules that are generic
|
||||
Cu.import("resource://snowl/modules/log4moz.js");
|
||||
Cu.import("resource://snowl/modules/Observers.js");
|
||||
Cu.import("resource://snowl/modules/URI.js");
|
||||
|
||||
// Snowl-specific modules
|
||||
Cu.import("resource://snowl/modules/service.js");
|
||||
Cu.import("resource://snowl/modules/datastore.js");
|
||||
Cu.import("resource://snowl/modules/feed.js");
|
||||
Cu.import("resource://snowl/modules/twitter.js");
|
||||
|
||||
let SnowlPreferences = {
|
||||
// Logger
|
||||
get _log() {
|
||||
delete this._log;
|
||||
return this._log = Log4Moz.Service.getLogger("Snowl.Preferences");
|
||||
},
|
||||
|
||||
onPaneLoad: function() {
|
||||
// Select passed tab
|
||||
let snowlPrefs = document.getElementById("snowlPrefs");
|
||||
let extraArgs = window.arguments[1];
|
||||
if (extraArgs && extraArgs["snowlTab"])
|
||||
snowlPrefs.selectedTab = document.getElementById(extraArgs["snowlTab"]);
|
||||
|
||||
Subscriber.addObservers();
|
||||
window.addEventListener("unload", function() { Subscriber.removeObservers(); }, false);
|
||||
},
|
||||
|
||||
selectSubcribeDeck: function() {
|
||||
let index = document.getElementById("subscribeRadio").selectedIndex;
|
||||
let deck = document.getElementById("subscribeDeck");
|
||||
deck.setAttribute("selectedIndex", index);
|
||||
this.clearFields();
|
||||
},
|
||||
|
||||
clearFields: function() {
|
||||
document.getElementById("locationTextbox").value = "";
|
||||
document.getElementById("nameTextbox").value = "";
|
||||
document.getElementById("twitterUsername").value = "";
|
||||
document.getElementById("twitterPassword").value = "";
|
||||
Subscriber.setStatus("none", "");
|
||||
},
|
||||
|
||||
}
|
||||
|
|
|
@ -40,7 +40,9 @@
|
|||
|
||||
<!DOCTYPE overlay [
|
||||
<!ENTITY % snowlPreferencesDTD SYSTEM "chrome://snowl/locale/preferences.dtd">
|
||||
<!ENTITY % snowlLoginDTD SYSTEM "chrome://snowl/locale/login.dtd">
|
||||
%snowlPreferencesDTD;
|
||||
%snowlLoginDTD;
|
||||
]>
|
||||
|
||||
<overlay id="snowlPreferencesPaneOverlay"
|
||||
|
@ -49,15 +51,22 @@
|
|||
<prefwindow id="BrowserPreferences">
|
||||
|
||||
<script type="application/x-javascript" src="chrome://snowl/content/preferences.js"/>
|
||||
<script type="application/x-javascript" src="chrome://snowl/content/strands.js"/>
|
||||
<script type="application/x-javascript" src="chrome://snowl/content/subscribe.js"/>
|
||||
|
||||
<stringbundleset id="stringbundleset">
|
||||
<stringbundle id="snowlStringBundle"
|
||||
src="chrome://snowl/locale/preferences.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<prefpane id="paneSnowl"
|
||||
label="&paneSnowl.title;"
|
||||
onpaneload=""
|
||||
onpaneload="SnowlPreferences.onPaneLoad();"
|
||||
insertbefore="paneAdvanced">
|
||||
|
||||
<preferences id="snowlPreferences">
|
||||
<preference id="browser.preferences.snowl.selectedTabIndex"
|
||||
name="browser.preferences.snowl.selectedTabIndex"
|
||||
<preference id="extensions.snowl.preferences.selectedTabIndex"
|
||||
name="extensions.snowl.preferences.selectedTabIndex"
|
||||
type="int"/>
|
||||
</preferences>
|
||||
|
||||
|
@ -87,39 +96,32 @@
|
|||
gAdvancedPane.updateAutoItems();
|
||||
gAdvancedPane.updateModeItems();"/>
|
||||
</preferences>
|
||||
|
||||
<stringbundle id="bundleShell" src="chrome://browser/locale/shellservice.properties"/>
|
||||
<stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
|
||||
-->
|
||||
<script type="application/x-javascript" src="chrome://browser/content/preferences/advanced.js"/>
|
||||
|
||||
<tabbox id="snowlPrefs" flex="1"
|
||||
onselect="SnowPreferencesPane.tabSelectionChanged();">
|
||||
persist="selectedIndex">
|
||||
|
||||
<tabs id="snowlTabsElement">
|
||||
<tab id="snowlTab1"
|
||||
<tabs id="snowlPrefsTabs">
|
||||
<tab id="snowlPrefsTabGeneral"
|
||||
label="&generalTab.label;"
|
||||
helpTopic="prefs-advanced-general"/>
|
||||
<tab id="snowlTab2"
|
||||
XXXhelpTopic="prefs-snowl-general"/>
|
||||
<tab id="snowlPrefsTabSubscribe"
|
||||
label="&subscribeTab.label;"
|
||||
disabled="true"
|
||||
helpTopic="prefs-advanced-network"/>
|
||||
<tab id="snowlTab3"
|
||||
XXXhelpTopic="prefs-snowl-subscribe"/>
|
||||
<tab id="snowlPrefsTabOrganize"
|
||||
label="&organizeTab.label;"
|
||||
disabled="true"
|
||||
helpTopic="prefs-advanced-network"/>
|
||||
XXXhelpTopic="prefs-snowl-organize"/>
|
||||
</tabs>
|
||||
|
||||
<tabpanels flex="1">
|
||||
<tabpanels id="snowlPrefsPanels" flex="1">
|
||||
|
||||
<!-- General -->
|
||||
<tabpanel id="snowlPanel1" orient="vertical">
|
||||
|
||||
<tabpanel id="snowlPrefsGeneralPanel" orient="vertical">
|
||||
<!-- Layouts -->
|
||||
<groupbox id="snowlPanel1a" align="start">
|
||||
<caption label="Layouts"/>
|
||||
</groupbox>
|
||||
|
||||
<!-- Browsing -->
|
||||
<groupbox id="snowlPanel1b" align="start">
|
||||
<caption label="Other"/>
|
||||
|
@ -127,35 +129,122 @@
|
|||
</tabpanel>
|
||||
|
||||
<!-- Subscribe -->
|
||||
<tabpanel id="snowlPanel2" orient="vertical">
|
||||
<tabpanel id="snowlPrefsSubscribePanel" orient="vertical">
|
||||
<!-- New Source -->
|
||||
<groupbox>
|
||||
|
||||
<!-- -->
|
||||
<groupbox id="snowlPanel2a">
|
||||
<caption label="snowlPanel2a"/>
|
||||
<caption label="&source.label;"/>
|
||||
<radiogroup id="subscribeRadio"
|
||||
orient="horizontal"
|
||||
oncommand="SnowlPreferences.selectSubcribeDeck()">
|
||||
<radio label="&feeds.label;"
|
||||
accesskey="&feeds.accesskey;"/>
|
||||
<radio label="&twitter.label;"
|
||||
accesskey="&twitter.accesskey;"/>
|
||||
<radio label="&mail.label;" disabled="true"
|
||||
accesskey="&mail.accesskey;"/>
|
||||
<radio label="&newsgroup.label;" disabled="true"
|
||||
accesskey="&newsgroup.accesskey;"/>
|
||||
</radiogroup>
|
||||
<separator class="groove-thin"/>
|
||||
|
||||
</groupbox>
|
||||
<deck id="subscribeDeck">
|
||||
<grid id="feedSubscribe">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<hbox flex="1" pack="end">
|
||||
<label control="locationTextbox" value="&location.label;"/>
|
||||
</hbox>
|
||||
<textbox id="locationTextbox" clickSelectsAll="true"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox flex="1" pack="end">
|
||||
<label control="nameTextbox" value="&name.label;"/>
|
||||
</hbox>
|
||||
<textbox id="nameTextbox" readonly="true" clickSelectsAll="true"/>
|
||||
</row>
|
||||
<row>
|
||||
<box/>
|
||||
<hbox pack="start">
|
||||
<button label="&subscribeButton.label;" default="true"
|
||||
oncommand="Subscriber.subscribeFeed()"/>
|
||||
<spacer flex="1"/>
|
||||
<button label="&clearButton.label;"
|
||||
oncommand="SnowlPreferences.clearFields()"/>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
||||
<grid id="twitterSubscribe">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<hbox flex="1" pack="end">
|
||||
<label control="twitterUsername" value="&username.label;"/>
|
||||
</hbox>
|
||||
<textbox id="twitterUsername"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox flex="1" pack="end">
|
||||
<label control="twitterPassword" value="&password.label;"/>
|
||||
</hbox>
|
||||
<textbox id="twitterPassword" type="password"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<box/>
|
||||
<checkbox id="showTwitterPassword" label="&showPassword.label;"
|
||||
oncommand="Subscriber.showTwitterPassword()"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<box/>
|
||||
<checkbox id="rememberTwitterPassword" label="&rememberPassword.label;"/>
|
||||
</row>
|
||||
<row>
|
||||
<box/>
|
||||
<hbox >
|
||||
<button label="&subscribeButton.label;" default="true"
|
||||
oncommand="Subscriber.subscribeTwitter()"/>
|
||||
<spacer flex="1"/>
|
||||
<button label="&clearButton.label;"
|
||||
oncommand="SnowlPreferences.clearFields()"/>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</deck>
|
||||
|
||||
</groupbox>
|
||||
|
||||
<hbox id="statusBox">
|
||||
<vbox pack="center">
|
||||
<image id="statusIcon" />
|
||||
</vbox>
|
||||
<description id="statusMessage" flex="1"/>
|
||||
</hbox>
|
||||
|
||||
<!-- -->
|
||||
<groupbox id="snowlPanel2b">
|
||||
<caption label="snowlPanel2b"/>
|
||||
</groupbox>
|
||||
</tabpanel>
|
||||
|
||||
<!-- Organize -->
|
||||
<tabpanel id="snowlPanel3" orient="vertical">
|
||||
|
||||
<tabpanel id="snowlPrefsOrganizePanel" orient="vertical">
|
||||
<!-- -->
|
||||
<groupbox id="snowlPanel3a">
|
||||
<caption label="snowlPanel3a"/>
|
||||
|
||||
</groupbox>
|
||||
|
||||
<!-- -->
|
||||
<groupbox id="snowlPanel3b">
|
||||
<caption label="snowlPanel3b"/>
|
||||
</groupbox>
|
||||
</tabpanel>
|
||||
|
||||
</tabpanel>
|
||||
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type"text/css"?>
|
||||
<?xml-stylesheet href="chrome://snowl/content/subscribe.css" type"text/css"?>
|
||||
<?xml-stylesheet href="chrome://snowl/content/preferences.css" type"text/css"?>
|
||||
|
||||
<!DOCTYPE page [
|
||||
<!ENTITY % subscribeDTD SYSTEM "chrome://snowl/locale/sources.dtd">
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Snowl.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Myk Melez <myk@mozilla.org>
|
||||
*
|
||||
* 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
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#content {
|
||||
border: 1px solid threedshadow;
|
||||
padding: 3em;
|
||||
-moz-border-radius: 10px;
|
||||
background-color: -moz-field;
|
||||
color: -moz-fieldtext;
|
||||
width: 37em;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-size: 2em;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5em;
|
||||
border-bottom: 1px solid threedlightshadow;
|
||||
}
|
||||
|
||||
|
||||
toolbarbutton {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.toolbarbutton-icon {
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
||||
#statusBox[status="active"] > #statusIcon {
|
||||
list-style-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
}
|
||||
|
||||
#statusBox[status="complete"] > #statusIcon {
|
||||
list-style-image: url("chrome://snowl/content/icons/tick.png");
|
||||
}
|
||||
|
||||
#statusBox[status="error"] > #statusIcon {
|
||||
list-style-image: url("chrome://global/skin/icons/error-16.png");
|
||||
}
|
|
@ -34,30 +34,10 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
// modules that come with Firefox
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
// modules that are generic
|
||||
Cu.import("resource://snowl/modules/log4moz.js");
|
||||
Cu.import("resource://snowl/modules/Observers.js");
|
||||
Cu.import("resource://snowl/modules/URI.js");
|
||||
|
||||
// Snowl-specific modules
|
||||
Cu.import("resource://snowl/modules/service.js");
|
||||
Cu.import("resource://snowl/modules/datastore.js");
|
||||
Cu.import("resource://snowl/modules/feed.js");
|
||||
Cu.import("resource://snowl/modules/twitter.js");
|
||||
|
||||
window.addEventListener("load", function() { Subscriber.init() }, false);
|
||||
|
||||
function SubscriptionListener(subject, topic, data) {
|
||||
// FIXME: figure out why the SubscriptionListener hangs around and gets called
|
||||
// sometimes after the page has been unloaded and Subscriber is not defined.
|
||||
// XXX: onunload added to subscribe.xul and preferences.xul, should fix this
|
||||
if (typeof Subscriber == "undefined") {
|
||||
Log4Moz.Service.getLogger("Snowl.SubscriptionListener").warn(
|
||||
"called without Subscriber; subject: " + subject + "; topic: " + topic +
|
||||
|
@ -71,77 +51,80 @@ function SubscriptionListener(subject, topic, data) {
|
|||
if (subject != source)
|
||||
return;
|
||||
|
||||
let statusBox = document.getElementById("statusBox");
|
||||
let statusMessage = document.getElementById("statusMessage");
|
||||
|
||||
function setStatus(code, message) {
|
||||
statusBox.setAttribute("status", code);
|
||||
|
||||
while (statusMessage.hasChildNodes())
|
||||
statusMessage.removeChild(statusMessage.firstChild);
|
||||
|
||||
// Append a child node so it wraps if it's too long to fit on one line.
|
||||
// XXX Is there something we can do so the UI doesn't resize midstream?
|
||||
statusMessage.appendChild(document.createTextNode(message));
|
||||
}
|
||||
|
||||
let identity = source.name ||
|
||||
(source.humanURI ? source.humanURI.spec : null) ||
|
||||
(source.machineURI ? source.machineURI.spec : null) ||
|
||||
"unnamed source";
|
||||
let code, message;
|
||||
// If blank, fine
|
||||
let identity = source.name;
|
||||
let stringBundle = document.getElementById("snowlStringBundle");
|
||||
|
||||
switch(topic) {
|
||||
case "snowl:subscribe:connect:start":
|
||||
setStatus("active", "Connecting to " + identity);
|
||||
code = "active";
|
||||
message = stringBundle.getString("messageConnecting");
|
||||
break;
|
||||
case "snowl:subscribe:connect:end":
|
||||
let code, message;
|
||||
|
||||
if (data == "duplicate") {
|
||||
if (data.split(":")[0] == "duplicate") {
|
||||
code = "error";
|
||||
message = "Already subscribed to " + identity;
|
||||
message = stringBundle.getString("messageDuplicate");
|
||||
identity = data.split(":")[1];
|
||||
}
|
||||
else if (data == "invalid") {
|
||||
code = "error";
|
||||
message = stringBundle.getString("messageInvalid");
|
||||
}
|
||||
else if (data < 200 || data > 299) {
|
||||
code = "error";
|
||||
message = "Error connecting to " + identity;
|
||||
if (data == 401) {
|
||||
message += ": your credentials were not accepted. Please check " +
|
||||
"your username and password and try again.";
|
||||
}
|
||||
message = stringBundle.getString("messageConnectionError");
|
||||
if (data == 401)
|
||||
message = stringBundle.getString("messagePassword");
|
||||
}
|
||||
else {
|
||||
// Under most circumstances, this message will be replaced immediately
|
||||
// by the "getting messages" message.
|
||||
code = "complete";
|
||||
message = "Connected to " + identity;
|
||||
message = stringBundle.getString("messageConnected");
|
||||
}
|
||||
|
||||
setStatus(code, message);
|
||||
break;
|
||||
case "snowl:subscribe:get:start":
|
||||
setStatus("active", "Getting messages for " + identity);
|
||||
code = "active";
|
||||
message = stringBundle.getString("messageGettingMessages");
|
||||
break;
|
||||
case "snowl:subscribe:get:progress":
|
||||
return;
|
||||
break;
|
||||
case "snowl:subscribe:get:end":
|
||||
setStatus("complete", "You have subscribed to " + identity);
|
||||
code = "complete";
|
||||
message = stringBundle.getString("messageSuccess");
|
||||
break;
|
||||
}
|
||||
Subscriber.setStatus(code, message, identity);
|
||||
}
|
||||
|
||||
let Subscriber = {
|
||||
_log: Log4Moz.Service.getLogger("Snowl.Subscriber"),
|
||||
// Logger
|
||||
get _log() {
|
||||
delete this._log;
|
||||
return this._log = Log4Moz.Service.getLogger("Snowl.Subscribe");
|
||||
},
|
||||
|
||||
setStatus: function(code, message, identity) {
|
||||
let nameBox = document.getElementById("nameTextbox");
|
||||
nameBox.setAttribute("value", identity);
|
||||
let statusIcon = document.getElementById("statusIcon");
|
||||
let statusMessage = document.getElementById("statusMessage");
|
||||
statusIcon.setAttribute("status", code);
|
||||
|
||||
while (statusMessage.hasChildNodes())
|
||||
statusMessage.removeChild(statusMessage.firstChild);
|
||||
|
||||
statusMessage.appendChild(document.createTextNode(message));
|
||||
},
|
||||
|
||||
|
||||
//**************************************************************************//
|
||||
// Initialization & Destruction
|
||||
|
||||
init: function() {
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:connect:start");
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:connect:end");
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:get:start");
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:get:progress");
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:get:end");
|
||||
this.addObservers();
|
||||
|
||||
// Parse URL parameters
|
||||
let paramString = window.location.search.substr(1);
|
||||
|
@ -156,23 +139,19 @@ let Subscriber = {
|
|||
|
||||
if (params.feed) {
|
||||
document.getElementById("locationTextbox").value = params.feed;
|
||||
this.subscribeFeed();
|
||||
}
|
||||
else if (params.tab) {
|
||||
let tabbox = document.getElementById("tabbox");
|
||||
switch (params.tab) {
|
||||
// The feed tab is selected by default.
|
||||
case "twitter":
|
||||
tabbox.selectedTab = document.getElementById("twitterTab");
|
||||
break;
|
||||
case "opml":
|
||||
tabbox.selectedTab = document.getElementById("opmlTab");
|
||||
break;
|
||||
}
|
||||
this.subscribeFeed(params.feed);
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
addObservers: function() {
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:connect:start");
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:connect:end");
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:get:start");
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:get:progress");
|
||||
Observers.add(SubscriptionListener, "snowl:subscribe:get:end");
|
||||
},
|
||||
|
||||
removeObservers: function() {
|
||||
Observers.remove(SubscriptionListener, "snowl:subscribe:connect:start");
|
||||
Observers.remove(SubscriptionListener, "snowl:subscribe:connect:end");
|
||||
Observers.remove(SubscriptionListener, "snowl:subscribe:get:start");
|
||||
|
@ -184,8 +163,15 @@ let Subscriber = {
|
|||
//**************************************************************************//
|
||||
// Event Handlers
|
||||
|
||||
subscribeFeed: function() {
|
||||
let uri = URI.get(document.getElementById("locationTextbox").value);
|
||||
subscribeFeed: function(url) {
|
||||
let uri, typedUri;
|
||||
if (!url)
|
||||
// Url from user input in Options
|
||||
uri = URI.get(document.getElementById("locationTextbox").value);
|
||||
else
|
||||
// Url passed from feedparser
|
||||
uri = URI.get(url);
|
||||
|
||||
let feed = new SnowlFeed(null, null, null, uri);
|
||||
this._subscribe(feed);
|
||||
},
|
||||
|
@ -235,6 +221,14 @@ let Subscriber = {
|
|||
// FIXME: call this "source" instead of "feed".
|
||||
this.feed = twitter;
|
||||
|
||||
// XXX: Multiple twitter subsciptions allowed? How are they differentiated?
|
||||
// For now disallow since the database can be filled with bad records..
|
||||
// let name = SnowlService.hasSource(twitter.machineURI.spec)
|
||||
// if (name) {
|
||||
// Observers.notify(this.feed, "snowl:subscribe:connect:end", "duplicate:" + name);
|
||||
// return;
|
||||
// }
|
||||
|
||||
twitter.subscribe(credentials);
|
||||
},
|
||||
|
||||
|
@ -273,8 +267,14 @@ let Subscriber = {
|
|||
// so the progress listener can filter out events for some other feed.
|
||||
this.feed = feed;
|
||||
|
||||
if (SnowlService.hasSource(feed.machineURI.spec)) {
|
||||
Observers.notify(this.feed, "snowl:subscribe:connect:end", "duplicate");
|
||||
if (!feed.machineURI) {
|
||||
Observers.notify(this.feed, "snowl:subscribe:connect:end", "invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
let name = SnowlService.hasSource(feed.machineURI.spec)
|
||||
if (name) {
|
||||
Observers.notify(this.feed, "snowl:subscribe:connect:end", "duplicate:" + name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,114 +37,59 @@
|
|||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type"text/css"?>
|
||||
<?xml-stylesheet href="chrome://snowl/content/subscribe.css" type"text/css"?>
|
||||
<?xml-stylesheet href="chrome://snowl/content/preferences.css" type"text/css"?>
|
||||
|
||||
<!DOCTYPE page [
|
||||
<!ENTITY % subscribeDTD SYSTEM "chrome://snowl/locale/subscribe.dtd">
|
||||
<!ENTITY % subscribeDTD SYSTEM "chrome://snowl/locale/preferences.dtd">
|
||||
%subscribeDTD;
|
||||
<!ENTITY % loginDTD SYSTEM "chrome://snowl/locale/login.dtd">
|
||||
%loginDTD;
|
||||
]>
|
||||
|
||||
<page title="&page.title;"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
pack="center"
|
||||
align="center">
|
||||
align="center"
|
||||
onload="Subscriber.init()"
|
||||
onunload="Subscriber.removeObservers()">
|
||||
|
||||
<script type="application/x-javascript" src="chrome://snowl/content/preferences.js"/>
|
||||
<script type="application/x-javascript" src="chrome://snowl/content/strands.js"/>
|
||||
<script type="application/x-javascript" src="chrome://snowl/content/subscribe.js"/>
|
||||
|
||||
<stringbundleset id="stringbundleset">
|
||||
<stringbundle id="snowlStringBundle"
|
||||
src="chrome://snowl/locale/preferences.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<vbox id="content">
|
||||
<label flex="1" value="&page.title;" class="header"/>
|
||||
<separator class="groove-thin"/>
|
||||
<separator class="thin" orient="horizontal"/>
|
||||
|
||||
<tabbox id="tabbox">
|
||||
<tabs>
|
||||
<tab id="feedTab" label="&feedsTab.label;"/>
|
||||
<tab id="twitterTab" label="&twitterTab.label;"/>
|
||||
<tab id="opmlTab" label="&opmlTab.label;"/>
|
||||
</tabs>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<hbox flex="1" pack="end">
|
||||
<label control="locationTextbox" value="&location.label;"/>
|
||||
</hbox>
|
||||
<textbox id="locationTextbox" readonly="true" clickSelectsAll="true"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox flex="1" pack="end">
|
||||
<label control="nameTextbox" value="&name.label;"/>
|
||||
</hbox>
|
||||
<textbox id="nameTextbox" readonly="true" clickSelectsAll="true"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<separator class="groove-thin"/>
|
||||
|
||||
<tabpanels>
|
||||
<tabpanel orient="vertical">
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<hbox flex="1" pack="end">
|
||||
<label control="locationTextbox" value="&location.label;"/>
|
||||
</hbox>
|
||||
<textbox id="locationTextbox"/>
|
||||
</row>
|
||||
<row>
|
||||
<box/>
|
||||
<hbox pack="start">
|
||||
<button label="&subscribeButton.label;" default="true"
|
||||
oncommand="Subscriber.subscribeFeed()"/>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel orient="vertical">
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<hbox flex="1" pack="end">
|
||||
<label control="twitterUsername" value="&username.label;"/>
|
||||
</hbox>
|
||||
<textbox id="twitterUsername"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox flex="1" pack="end">
|
||||
<label control="twitterPassword" value="&password.label;"/>
|
||||
</hbox>
|
||||
<textbox id="twitterPassword" type="password"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<box/>
|
||||
<checkbox id="showTwitterPassword" label="&showPassword.label;"
|
||||
oncommand="Subscriber.showTwitterPassword()"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<box/>
|
||||
<checkbox id="rememberTwitterPassword" label="&rememberPassword.label;"/>
|
||||
</row>
|
||||
<row>
|
||||
<box/>
|
||||
<hbox pack="start">
|
||||
<button label="&subscribeButton.label;" default="true"
|
||||
oncommand="Subscriber.subscribeTwitter()"/>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel orient="vertical" pack="center" align="center">
|
||||
<button id="importOPMLButton" label="&importOPMLButton.label;"
|
||||
oncommand="Subscriber.importOPML()"/>
|
||||
</tabpanel>
|
||||
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
|
||||
<!-- Note: the status box should be align="baseline", but that looks ugly.
|
||||
- align="center" looks ugly for multi-line messages, but those are rare,
|
||||
- so this is the best option (for the moment, anyway). -->
|
||||
<hbox id="statusBox" align="center">
|
||||
<image id="statusIcon"/>
|
||||
<!-- FIXME: figure out how to allocate space in the UI for the message
|
||||
- such that setting it later doesn't resize the UI. -->
|
||||
<hbox id="statusBox">
|
||||
<vbox pack="center">
|
||||
<image id="statusIcon"/>
|
||||
</vbox>
|
||||
<description id="statusMessage" flex="1"/>
|
||||
</hbox>
|
||||
|
||||
|
|
|
@ -1,5 +1,27 @@
|
|||
<!-- Snowl Options -->
|
||||
<!ENTITY paneSnowl.title "Snowl">
|
||||
<!ENTITY noPreferences.message "Snowl does not yet have preferences.">
|
||||
<!ENTITY page.title "Snowl: Subscribe to Message Sources">
|
||||
|
||||
<!-- General tab -->
|
||||
<!ENTITY generalTab.label "General">
|
||||
|
||||
<!-- Subscribe tab -->
|
||||
<!ENTITY subscribeTab.label "Subscribe">
|
||||
<!ENTITY source.label "New Source">
|
||||
<!ENTITY feeds.label "Feed">
|
||||
<!ENTITY feeds.accesskey "F">
|
||||
<!ENTITY twitter.label "Twitter">
|
||||
<!ENTITY twitter.accesskey "T">
|
||||
<!ENTITY mail.label "Mail">
|
||||
<!ENTITY mail.accesskey "M">
|
||||
<!ENTITY newsgroup.label "Newsgroup">
|
||||
<!ENTITY newsgroup.accesskey "N">
|
||||
<!ENTITY location.label "Location:">
|
||||
<!ENTITY name.label "Name:">
|
||||
<!ENTITY subscribeButton.label "Subscribe">
|
||||
<!ENTITY closeButton.label "Close">
|
||||
<!ENTITY clearButton.label "Clear">
|
||||
|
||||
<!-- Organize tab -->
|
||||
<!ENTITY organizeTab.label "Organize">
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# Status messages when subscribing
|
||||
messageConnecting=Connecting...
|
||||
messageDuplicate=You have already subscribed.
|
||||
messageInvalid=The location is blank or invalid.
|
||||
messageConnectionError=Connection error or location cannot be found.
|
||||
messagePassword=Your credentials were not accepted. Please check your username and password and try again.
|
||||
messageConnected=Connected.
|
||||
messageGettingMessages=Getting messages...
|
||||
messageSuccess=You have successfully subscribed.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<!ENTITY page.title "Snowl: Subscribe to Message Sources">
|
||||
|
||||
<!ENTITY feedsTab.label "Feeds">
|
||||
<!ENTITY twitterTab.label "Twitter">
|
||||
<!ENTITY opmlTab.label "OPML">
|
||||
|
||||
<!ENTITY location.label "Location:">
|
||||
|
||||
<!ENTITY subscribeButton.label "Subscribe">
|
||||
<!ENTITY importOPMLButton.label "Import OPML File...">
|
||||
<!ENTITY closeButton.label "Close">
|
|
@ -412,23 +412,25 @@ let SnowlDatastore = {
|
|||
|
||||
get _selectHasSourceStatement() {
|
||||
let statement = this.createStatement(
|
||||
"SELECT 1 FROM sources WHERE machineURI = :machineURI"
|
||||
"SELECT name FROM sources WHERE machineURI = :machineURI"
|
||||
);
|
||||
this.__defineGetter__("_selectHasSourceStatement", function() { return statement });
|
||||
return this._selectHasSourceStatement;
|
||||
},
|
||||
|
||||
selectHasSource: function(aMachineURI) {
|
||||
let name;
|
||||
|
||||
try {
|
||||
this._selectHasSourceStatement.params.machineURI = aMachineURI;
|
||||
if (this._selectHasSourceStatement.step())
|
||||
return true;
|
||||
name = this._selectHasSourceStatement.row["name"];
|
||||
}
|
||||
finally {
|
||||
this._selectHasSourceStatement.reset();
|
||||
}
|
||||
|
||||
return false;
|
||||
return name;
|
||||
},
|
||||
|
||||
get _selectHasMessageStatement() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче