Bug 602685 - Sync UI: Implement easy setup for Fennec [r=mbrubeck]

This commit is contained in:
Mark Finkle 2010-11-16 01:13:37 -05:00
parent 356b96367b
commit 0130393c8f
7 changed files with 214 additions and 77 deletions

View File

@ -51,6 +51,10 @@
%brandDTD;
<!ENTITY % prefsDTD SYSTEM "chrome://browser/locale/preferences.dtd">
%prefsDTD;
#ifdef MOZ_SERVICES_SYNC
<!ENTITY % syncDTD SYSTEM "chrome://browser/locale/sync.dtd">
%syncDTD;
#endif
]>
<window id="main-window"
@ -438,13 +442,14 @@
</setting>
#ifdef MOZ_SERVICES_SYNC
<settings id="prefs-sync" label="&sync.title;">
<setting id="sync-account" type="string" title="&sync.account2;"/>
<setting id="sync-pass" type="string" inputtype="password" title="&sync.password;"/>
<setting id="sync-secret" type="string" inputtype="string" title="&sync.syncKey;"/>
<setting id="sync-device" type="string" title="&sync.deviceName;" onchange="WeaveGlue.changeName(this);" collapsed="true"/>
<setting id="sync-connect" type="control">
<button label="&sync.connect;" oncommand="WeaveGlue.connect();" />
<setting id="sync-connect" title="&sync.notconnected;" type="control">
<button label="&sync.connect;" oncommand="WeaveGlue.show();" />
</setting>
<setting id="sync-connected" title="&sync.connected;" type="control" collapsed="true">
<button id="sync-details" label="&sync.details;" type="checkbox" autocheck="true" checked="false" oncommand="WeaveGlue.showDetails();" />
</setting>
<setting id="sync-autosync" type="bool" title="&sync.synchronize.label;" onlabel="&sync.synchronize.yes;" offlabel="&sync.synchronize.no;" onchange="WeaveGlue.changeSync();" collapsed="true"/>
<setting id="sync-device" type="string" title="&sync.deviceName;" onchange="WeaveGlue.changeName(this);" collapsed="true"/>
<setting id="sync-disconnect" type="control" collapsed="true">
<button label="&sync.disconnect;" oncommand="WeaveGlue.disconnect();" />
</setting>
@ -513,6 +518,55 @@
#endif
</vbox>
#ifdef MOZ_SERVICES_SYNC
<vbox id="syncsetup-container" class="panel-dark window-width window-height" hidden="true">
<scrollbox align="center" orient="vertical" flex="1">
<vbox id="syncsetup-jpake" align="center" style="padding: 8px" flex="1">
<description>&sync.setup.title;</description>
<separator/>
<hbox align="start">
<description flex="1">&sync.setup.jpake;</description>
</hbox>
<separator/>
<vbox align="center">
<textbox readonly="true">code</textbox>
<textbox readonly="true">goes</textbox>
<textbox readonly="true">here</textbox>
</vbox>
<separator/>
<description style="font-size: 18px; text-decoration: underline" onclick="document.getElementById('syncsetup-jpake').hidden = true; document.getElementById('syncsetup-manual').hidden = false;">&sync.fallback;</description>
<separator/>
<hbox pack="center">
<button oncommand="WeaveGlue.close();">Cancel</button>
</hbox>
</vbox>
<vbox id="syncsetup-manual" style="padding: 8px" flex="1" hidden="true">
<hbox pack="center">
<description>&sync.setup.title;</description>
</hbox>
<separator/>
<description>&sync.setup.manual;</description>
<separator/>
<textbox id="syncsetup-account" placeholder="&sync.account;"/>
<textbox id="syncsetup-password" placeholder="&sync.password;" type="password"/>
<textbox id="syncsetup-synckey" placeholder="&sync.syncKey;"/>
<separator/>
<button id="syncsetup-customserver-checkbox" type="checkbox" class="button-checkbox" pack="start">
<image class="button-image-icon"/>
<description class="prompt-checkbox-label" flex="1">&sync.customServer;</description>
</button>
<textbox id="syncsetup-customserver" placeholder="&sync.serverURL;"/>
<separator/>
<hbox pack="center">
<button oncommand="WeaveGlue.close();">Cancel</button>
<separator/>
<button oncommand="WeaveGlue.close(); WeaveGlue.connect();">Connect</button>
</hbox>
</vbox>
</scrollbox>
</vbox>
#endif
<arrowbox id="search-engines-popup" hidden="true" class="window-width" offset="18">
<hbox id="search-engines-list" class="prompt-buttons window-width"/>
</arrowbox>

View File

@ -40,6 +40,9 @@ let WeaveGlue = {
init: function init() {
Components.utils.import("resource://services-sync/main.js");
this._bundle = Services.strings.createBundle("chrome://browser/locale/sync.properties");
this._msg = document.getElementById("prefs-messages");
this._addListeners();
// Generating keypairs is expensive on mobile, so disable it
@ -49,42 +52,75 @@ let WeaveGlue = {
this.autoConnect = Services.prefs.getBoolPref("services.sync.autoconnect");
if (this.autoConnect) {
// Put the settings UI into a state of "connecting..." if we are going to auto-connect
this._settings.account.collapsed = true;
this._settings.pass.collapsed = true;
this._settings.secret.collapsed = true;
this._settings.connect.collapsed = false;
this._settings.device.collapsed = false;
this._settings.disconnect.collapsed = true;
this._settings.sync.collapsed = false;
this._elements.connect.collapsed = false;
this._elements.sync.collapsed = false;
this._settings.connect.firstChild.disabled = true;
this._settings.sync.firstChild.disabled = true;
this._elements.connect.firstChild.disabled = true;
this._elements.sync.firstChild.disabled = true;
let bundle = Services.strings.createBundle("chrome://weave/locale/services/sync.properties");
this._settings.connect.setAttribute("title", bundle.GetStringFromName("connecting.label"));
this._elements.connect.setAttribute("title", this._bundle.GetStringFromName("connecting.label"));
this._elements.autosync.value = true;
try {
this._settings.device.value = Services.prefs.getCharPref("services.sync.client.name");
this._elements.device.value = Services.prefs.getCharPref("services.sync.client.name");
} catch(e) {}
}
}
},
show: function show() {
// Show the connect UI
document.getElementById("syncsetup-container").hidden = false;
document.getElementById("syncsetup-jpake").hidden = false;
document.getElementById("syncsetup-manual").hidden = true;
},
close: function close() {
// Close the connect UI
document.getElementById("syncsetup-container").hidden = true;
},
showDetails: function showDetails() {
// Show the connect UI detail settings
let show = this._elements.details.checked;
this._elements.autosync.collapsed = show;
this._elements.device.collapsed = show;
this._elements.disconnect.collapsed = show;
},
connect: function connect() {
// Cause the Sync system to reset internals if we seem to be switching accounts
if (this._settings.account.value != Weave.Service.account)
if (this._elements.account.value != Weave.Service.account)
Weave.Service.startOver();
// Remove any leftover connection string
this._settings.connect.removeAttribute("desc");
this._elements.connect.removeAttribute("desc");
// Sync will use the account value and munge it into a username, as needed
Weave.Service.account = this._settings.account.value;
Weave.Service.login(Weave.Service.username, this._settings.pass.value, this.normalizePassphrase(this._settings.secret.value));
Weave.Service.account = this._elements.account.value;
Weave.Service.login(Weave.Service.username, this._elements.password.value, this.normalizePassphrase(this._elements.synckey.value));
Weave.Service.persistLogin();
},
disconnect: function disconnect() {
let message = this._bundle.GetStringFromName("notificationDisconnect.label");
let button = this._bundle.GetStringFromName("notificationDisconnect.button");
let buttons = [ {
label: button,
accessKey: "",
callback: function() { WeaveGlue.connect(); }
} ];
this.showMessage(message, "undo-disconnect", buttons);
// XXX change to an event that fires when panel is changed or closed
setTimeout(function(self) {
let notification = self._msg.getNotificationWithValue("undo-disconnect");
if (notification)
notification.close();
}, 10000, this);
// TODO: When the notification closes, not from the "undo" button, we should clean up the credentials
Weave.Service.logout();
},
@ -111,22 +147,27 @@ let WeaveGlue = {
}, false);
},
get _settings() {
get _elements() {
// Do a quick test to see if the options exist yet
let syncButton = document.getElementById("sync-syncButton");
if (syncButton == null)
return;
return null;
// Get all the setting nodes from the add-ons display
let settings = {};
let ids = ["account", "pass", "secret", "device", "connect", "disconnect", "sync"];
ids.forEach(function(id) {
settings[id] = document.getElementById("sync-" + id);
let elements = {};
let setupids = ["account", "password", "synckey", "customserver"];
setupids.forEach(function(id) {
elements[id] = document.getElementById("syncsetup-" + id);
});
let settingids = ["device", "connect", "connected", "disconnect", "sync", "autosync", "details"];
settingids.forEach(function(id) {
elements[id] = document.getElementById("sync-" + id);
});
// Replace the getter with the collection of settings
delete this._settings;
return this._settings = settings;
delete this._elements;
return this._elements = elements;
},
observe: function observe(aSubject, aTopic, aData) {
@ -141,46 +182,50 @@ let WeaveGlue = {
Util.forceOnline();
// Can't do anything before settings are loaded
if (this._settings == null)
if (this._elements == null)
return;
// Make some aliases
let account = this._settings.account;
let pass = this._settings.pass;
let secret = this._settings.secret;
let connect = this._settings.connect;
let device = this._settings.device;
let disconnect = this._settings.disconnect;
let sync = this._settings.sync;
let syncStr = Weave.Str.sync;
let account = this._elements.account;
let password = this._elements.password;
let synckey = this._elements.synckey;
let connect = this._elements.connect;
let connected = this._elements.connected;
let autosync = this._elements.autosync;
let device = this._elements.device;
let disconnect = this._elements.disconnect;
let sync = this._elements.sync;
// Make sure the options are in the right state
account.collapsed = loggedIn;
pass.collapsed = loggedIn;
secret.collapsed = loggedIn;
connect.collapsed = loggedIn;
device.collapsed = !loggedIn;
disconnect.collapsed = !loggedIn;
connected.collapsed = !loggedIn;
sync.collapsed = !loggedIn;
if (connected.collapsed) {
connect.setAttribute("title", this._bundle.GetStringFromName("notconnected.label"));
this._elements.details.checked = false;
this._elements.autosync.collapsed = true;
this._elements.device.collapsed = true;
this._elements.disconnect.collapsed = true;
}
// Check the lock on a timeout because it's set just after notifying
setTimeout(function() {
setTimeout(function(self) {
// Prevent certain actions when the service is locked
if (Weave.Service.locked) {
connect.firstChild.disabled = true;
sync.firstChild.disabled = true;
if (aTopic == "weave:service:login:start")
connect.setAttribute("title", syncStr.get("connecting.label"));
connect.setAttribute("title", self._bundle.GetStringFromName("connecting.label"));
if (aTopic == "weave:service:sync:start")
sync.setAttribute("title", syncStr.get("lastSyncInProgress.label"));
sync.setAttribute("title", self._bundle.GetStringFromName("lastSyncInProgress.label"));
} else {
connect.firstChild.disabled = false;
sync.firstChild.disabled = false;
connect.setAttribute("title", syncStr.get("disconnected.label"));
}
}, 0);
}, 0, this);
// Move the disconnect and sync settings out to make connect the last item
let parent = connect.parentNode;
@ -190,14 +235,14 @@ let WeaveGlue = {
parent.appendChild(sync);
// Dynamically generate some strings
let connectedStr = syncStr.get("connected.label", [Weave.Service.account]);
disconnect.setAttribute("title", connectedStr);
let accountStr = this._bundle.formatStringFromName("account.label", [Weave.Service.account], 1);
disconnect.setAttribute("title", accountStr);
// Show the day-of-week and time (HH:MM) of last sync
let lastSync = Weave.Svc.Prefs.get("lastSync");
if (lastSync != null) {
let syncDate = new Date(lastSync).toLocaleFormat("%a %R");
let dateStr = syncStr.get("lastSync.label", [syncDate]);
let dateStr = this._bundle.formatStringFromName("lastSync.label", [syncDate], 1);
sync.setAttribute("title", dateStr);
}
@ -227,17 +272,16 @@ let WeaveGlue = {
}
if (clientOutdated || remoteOutdated) {
let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
let brand = Services.strings.createBundle("chrome://branding/locale/brand.properties");
let brandName = brand.GetStringFromName("brandShortName");
let type = clientOutdated ? "client" : "remote";
let message = bundle.GetStringFromName("sync.update." + type);
let message = this._bundle.GetStringFromName("sync.update." + type);
message = message.replace("#1", brandName);
message = message.replace("#2", Services.appinfo.version);
let title = bundle.GetStringFromName("sync.update.title")
let button = bundle.GetStringFromName("sync.update.button")
let close = bundle.GetStringFromName("sync.update.close")
let title = this._bundle.GetStringFromName("sync.update.title")
let button = this._bundle.GetStringFromName("sync.update.button")
let close = this._bundle.GetStringFromName("sync.update.close")
let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_IS_STRING;
@ -249,11 +293,11 @@ let WeaveGlue = {
// Load the values for the string inputs
account.value = Weave.Service.account || "";
pass.value = Weave.Service.password || "";
password.value = Weave.Service.password || "";
let pp = Weave.Service.passphrase || "";
if (pp.length == 20)
pp = this.hyphenatePassphrase(pp);
secret.value = pp;
synckey.value = pp;
device.value = Weave.Clients.localName || "";
},
@ -263,6 +307,18 @@ let WeaveGlue = {
aInput.value = Weave.Clients.localName;
},
changeSync: function changeSync() {
// XXX enable/disable sync without actually disconnecting
},
showMessage: function showMessage(aMsg, aValue, aButtons) {
let notification = this._msg.getNotificationWithValue(aValue);
if (notification)
return;
this._msg.appendNotification(aMsg, aValue, "", this._msg.PRIORITY_WARNING_LOW, aButtons);
},
hyphenatePassphrase: function(passphrase) {
// Hyphenate a 20 character passphrase in 4 groups of 5
return passphrase.slice(0, 5) + '-'

View File

@ -199,13 +199,3 @@ pageactions.password=Password
# Open Search
opensearch.searchWith=Search With:
opensearch.searchFor=Search for "%S"
# Mobile Sync
# LOCALIZATION NOTE (sync.clientUpdate, sync.remoteUpdate):
# #1 is the "application name"
# #2 is the "version"
sync.update.client=#1 #2 is not compatible with the latest version of Firefox Sync. Please update to the latest version.
sync.update.remote=#1 #2 is not compatible with older versions of Firefox Sync. Please update Firefox on your other computer(s).
sync.update.title=Firefox Sync
sync.update.button=Learn More
sync.update.close=Close

View File

@ -18,11 +18,3 @@
<!ENTITY homepage.none "Blank Page">
<!ENTITY homepage.default "&brandShortName; Start">
<!ENTITY homepage.currentpage "Use Current Page">
<!ENTITY sync.title "Sync">
<!ENTITY sync.account2 "Account Name">
<!ENTITY sync.password "Password">
<!ENTITY sync.syncKey "Sync Key">
<!ENTITY sync.deviceName "Device Name">
<!ENTITY sync.connect "Connect">
<!ENTITY sync.disconnect "Disconnect">
<!ENTITY sync.syncNow "Sync Now">

View File

@ -0,0 +1,21 @@
<!ENTITY sync.title "Sync">
<!ENTITY sync.notconnected "Not connected">
<!ENTITY sync.connect "Connect">
<!ENTITY sync.connected "Connected">
<!ENTITY sync.details "Details">
<!ENTITY sync.synchronize.label "Synchronize">
<!ENTITY sync.synchronize.yes "On">
<!ENTITY sync.synchronize.no "Off">
<!ENTITY sync.deviceName "This device">
<!ENTITY sync.disconnect "Disconnect">
<!ENTITY sync.syncNow "Sync Now">
<!ENTITY sync.setup.title "Connect to Sync">
<!ENTITY sync.setup.jpake "From a Firefox Sync-connected computer, go to Sync options and select &#x0022;Add a device&#x0022;">
<!ENTITY sync.fallback "I'm not near my computer…">
<!ENTITY sync.setup.manual "Enter your Sync account information">
<!ENTITY sync.account "Account Name">
<!ENTITY sync.password "Password">
<!ENTITY sync.syncKey "Sync Key">
<!ENTITY sync.customServer "Use custom server">
<!ENTITY sync.serverURL "Server URL">

View File

@ -0,0 +1,22 @@
# Mobile Sync
# %S is the date and time at which the last sync successfully completed
lastSync.label=Last update: %S
lastSyncInProgress.label=Last update: in progress…
# %S is the username logged in
account.label=Account: %S
notconnected.label=Not connected
connecting.label=Connecting…
notificationDisconnect.label=Your Firefox Sync account has been removed
notificationDisconnect.button=Undo
# LOCALIZATION NOTE (sync.clientUpdate, sync.remoteUpdate):
# #1 is the "application name"
# #2 is the "version"
sync.update.client=#1 #2 is not compatible with the latest version of Firefox Sync. Please update to the latest version.
sync.update.remote=#1 #2 is not compatible with older versions of Firefox Sync. Please update Firefox on your other computer(s).
sync.update.title=Firefox Sync
sync.update.button=Learn More
sync.update.close=Close

View File

@ -13,6 +13,8 @@
locale/@AB_CD@/browser/preferences.dtd (%chrome/preferences.dtd)
locale/@AB_CD@/browser/checkbox.dtd (%chrome/checkbox.dtd)
locale/@AB_CD@/browser/notification.dtd (%chrome/notification.dtd)
locale/@AB_CD@/browser/sync.dtd (%chrome/sync.dtd)
locale/@AB_CD@/browser/sync.properties (%chrome/sync.properties)
locale/@AB_CD@/browser/prompt.dtd (%chrome/prompt.dtd)
locale/@AB_CD@/browser/feedback.dtd (%chrome/feedback.dtd)
locale/@AB_CD@/browser/bookmarks.json (bookmarks.json)