diff --git a/chrome/content/zotero/preferences/librariesToSync.xul b/chrome/content/zotero/preferences/librariesToSync.xul
new file mode 100644
index 0000000000..e11d842c2d
--- /dev/null
+++ b/chrome/content/zotero/preferences/librariesToSync.xul
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+ %prefWindow;
+
+ %common;
+]>
+
+
\ No newline at end of file
diff --git a/chrome/content/zotero/preferences/preferences_sync.js b/chrome/content/zotero/preferences/preferences_sync.js
index a5d2ee6211..7f83bd2897 100644
--- a/chrome/content/zotero/preferences/preferences_sync.js
+++ b/chrome/content/zotero/preferences/preferences_sync.js
@@ -148,7 +148,6 @@ Zotero_Preferences.Sync = {
Zotero.Sync.Runner.deleteAPIKey();
return;
}
-
this.displayFields(json.username);
}),
@@ -195,8 +194,138 @@ Zotero_Preferences.Sync = {
}
this.displayFields();
+ Zotero.Prefs.clear('sync.librariesToSync');
yield Zotero.Sync.Runner.deleteAPIKey();
}),
+
+
+ showLibrariesToSyncDialog: function() {
+ var io = {};
+ window.openDialog('chrome://zotero/content/preferences/librariesToSync.xul',
+ "zotero-preferences-librariesToSyncDialog", "chrome,modal,centerscreen", io);
+ },
+
+
+ dblClickLibraryToSync: function (event) {
+ var tree = document.getElementById("libraries-to-sync-tree");
+ var row = {}, col = {}, child = {};
+ tree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, child);
+
+ if (col.value.element.id == 'libraries-to-sync-checked') {
+ return;
+ }
+ // if dblclicked anywhere but the checkbox update pref
+ return this.toggleLibraryToSync(row.value);
+ },
+
+
+ clickLibraryToSync: function (event) {
+ var tree = document.getElementById("libraries-to-sync-tree");
+ var row = {}, col = {}, child = {};
+ tree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, child);
+
+ if (col.value.element.id != 'libraries-to-sync-checked') {
+ return;
+ }
+ // if clicked on checkbox update pref
+ return this.toggleLibraryToSync(row.value);
+ },
+
+
+ toggleLibraryToSync: function (index) {
+ var treechildren = document.getElementById('libraries-to-sync-rows');
+ if (index >= treechildren.childNodes.length) {
+ return;
+ }
+ var row = treechildren.childNodes[index];
+ var val = row.firstChild.childNodes[1].getAttribute('value');
+ if (!val) {
+ return
+ }
+
+ var librariesToSkip = JSON.parse(Zotero.Prefs.get('sync.librariesToSkip') || '[]');
+ var indexOfId = librariesToSkip.indexOf(val);
+ if (indexOfId == -1) {
+ librariesToSkip.push(val);
+ } else {
+ librariesToSkip.splice(indexOfId, 1);
+ }
+ Zotero.Prefs.set('sync.librariesToSkip', JSON.stringify(librariesToSkip));
+
+ var cell = row.firstChild.firstChild;
+ cell.setAttribute('value', indexOfId != -1);
+ },
+
+
+ initLibrariesToSync: Zotero.Promise.coroutine(function* () {
+ var tree = document.getElementById("libraries-to-sync-tree");
+ var treechildren = document.getElementById('libraries-to-sync-rows');
+ while (treechildren.hasChildNodes()) {
+ treechildren.removeChild(treechildren.firstChild);
+ }
+
+ function addRow(libraryName, id, checked=false, editable=true) {
+ var treeitem = document.createElement('treeitem');
+ var treerow = document.createElement('treerow');
+ var checkboxCell = document.createElement('treecell');
+ var nameCell = document.createElement('treecell');
+
+ nameCell.setAttribute('label', libraryName);
+ nameCell.setAttribute('value', id);
+ nameCell.setAttribute('editable', false);
+ checkboxCell.setAttribute('value', checked);
+ checkboxCell.setAttribute('editable', editable);
+
+ treerow.appendChild(checkboxCell);
+ treerow.appendChild(nameCell);
+ treeitem.appendChild(treerow);
+ treechildren.appendChild(treeitem);
+ }
+
+ // Add loading row while we're loading a group list
+ var loadingLabel = Zotero.getString("zotero.preferences.sync.librariesToSync.loadingLibraries");
+ addRow(loadingLabel, "loading", false, false);
+
+ var apiKey = Zotero.Sync.Data.Local.getAPIKey();
+ var client = Zotero.Sync.Runner.getAPIClient({apiKey});
+ var groups = [];
+ try {
+ // Load up remote groups
+ var keyInfo = yield Zotero.Sync.Runner.checkAccess(client, {timeout: 5000});
+ groups = yield client.getGroups(keyInfo.userID);
+ }
+ catch (e) {
+ // Connection problems
+ if ((e instanceof Zotero.HTTP.UnexpectedStatusException)
+ || (e instanceof Zotero.HTTP.TimeoutException)
+ || (e instanceof Zotero.HTTP.BrowserOfflineException)) {
+ Zotero.alert(
+ window,
+ Zotero.getString('general.error'),
+ Zotero.getString('sync.error.checkConnection', Zotero.clientName)
+ );
+ }
+ else {
+ throw e;
+ }
+ document.getElementsByTagName('dialog')[0].acceptDialog();
+ }
+
+ // Remove the loading row
+ treechildren.removeChild(treechildren.firstChild);
+
+ var librariesToSkip = JSON.parse(Zotero.Prefs.get('sync.librariesToSkip') || '[]');
+ // Add default rows
+ addRow(Zotero.getString("pane.collections.libraryAndFeeds"), "L" + Zotero.Libraries.userLibraryID,
+ librariesToSkip.indexOf("L" + Zotero.Libraries.userLibraryID) == -1);
+ addRow(Zotero.getString("pane.collections.publications"), "L" + Zotero.Libraries.publicationsLibraryID,
+ librariesToSkip.indexOf("L" + Zotero.Libraries.publicationsLibraryID) == -1);
+
+ // Add group rows
+ for (let group of groups) {
+ addRow(group.data.name, "G" + group.id, librariesToSkip.indexOf("G" + group.id) == -1);
+ }
+ }),
updateStorageSettingsUI: Zotero.Promise.coroutine(function* () {
diff --git a/chrome/content/zotero/preferences/preferences_sync.xul b/chrome/content/zotero/preferences/preferences_sync.xul
index 266546723e..0155d05607 100644
--- a/chrome/content/zotero/preferences/preferences_sync.xul
+++ b/chrome/content/zotero/preferences/preferences_sync.xul
@@ -103,46 +103,45 @@
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -267,7 +266,7 @@
-
+
&zotero.preferences.sync.reset.warning1;&zotero.preferences.sync.reset.warning3;
diff --git a/chrome/content/zotero/xpcom/sync/syncAPIClient.js b/chrome/content/zotero/xpcom/sync/syncAPIClient.js
index 40b7dab50b..80457da0ae 100644
--- a/chrome/content/zotero/xpcom/sync/syncAPIClient.js
+++ b/chrome/content/zotero/xpcom/sync/syncAPIClient.js
@@ -75,12 +75,26 @@ Zotero.Sync.APIClient.prototype = {
return this._parseJSON(xmlhttp.responseText);
}),
+ /**
+ * Get group metadata for userID
+ *
+ * @param {Integer} userID
+ * @return {Object} - Group metadata response
+ */
+ getGroups: Zotero.Promise.coroutine(function* (userID) {
+ if (!userID) throw new Error("User ID not provided");
+
+ var uri = this.baseURL + "users/" + userID + "/groups";
+ var xmlhttp = yield this.makeRequest("GET", uri);
+ return this._parseJSON(xmlhttp.responseText);
+ }),
+
/**
* @param {Integer} groupID
* @return {Object|false} - Group metadata response, or false if group not found
*/
- getGroupInfo: Zotero.Promise.coroutine(function* (groupID) {
+ getGroup: Zotero.Promise.coroutine(function* (groupID) {
if (!groupID) throw new Error("Group ID not provided");
var uri = this.baseURL + "groups/" + groupID;
diff --git a/chrome/content/zotero/xpcom/sync/syncRunner.js b/chrome/content/zotero/xpcom/sync/syncRunner.js
index f8bc98b2d6..126e1c4651 100644
--- a/chrome/content/zotero/xpcom/sync/syncRunner.js
+++ b/chrome/content/zotero/xpcom/sync/syncRunner.js
@@ -452,7 +452,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
// Update metadata and permissions on missing or outdated groups
for (let groupID of groupsToDownload) {
- let info = yield client.getGroupInfo(groupID);
+ let info = yield client.getGroup(groupID);
if (!info) {
throw new Error("Group " + groupID + " not found");
}
diff --git a/chrome/locale/en-US/zotero/preferences.dtd b/chrome/locale/en-US/zotero/preferences.dtd
index f23c5bafcf..1e5e2bed60 100644
--- a/chrome/locale/en-US/zotero/preferences.dtd
+++ b/chrome/locale/en-US/zotero/preferences.dtd
@@ -76,6 +76,10 @@
+
+
+
+
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties
index 363bb2f05b..a9fcacf583 100644
--- a/chrome/locale/en-US/zotero/zotero.properties
+++ b/chrome/locale/en-US/zotero/zotero.properties
@@ -180,6 +180,7 @@ pane.collections.rename = Rename collection:
pane.collections.library = My Library
pane.collections.publications = My Publications
pane.collections.feeds = Feeds
+pane.collections.libraryAndFeeds = My Library & Feeds
pane.collections.groupLibraries = Group Libraries
pane.collections.feedLibraries = Feeds
pane.collections.trash = Trash
@@ -568,6 +569,7 @@ zotero.preferences.sync.purgeStorage.title = Purge Attachment Files on Zotero
zotero.preferences.sync.purgeStorage.desc = If you plan to use WebDAV for file syncing and you previously synced attachment files in My Library to the Zotero servers, you can purge those files from the Zotero servers to give you more storage space for groups.\n\nYou can purge files at any time from your account settings on zotero.org.
zotero.preferences.sync.purgeStorage.confirmButton = Purge Files Now
zotero.preferences.sync.purgeStorage.cancelButton = Do Not Purge
+zotero.preferences.sync.librariesToSync.loadingLibraries = Loading libraries…
zotero.preferences.sync.reset.userInfoMissing = You must enter a username and password in the %S tab before using the reset options.
zotero.preferences.sync.reset.restoreFromServer = All data in this copy of Zotero will be erased and replaced with data belonging to user '%S' on the Zotero server.
zotero.preferences.sync.reset.replaceLocalData = Replace Local Data