commit 2e389de471fc76f330e9f7e357bbed8c0e4c0703
parent 77a95b5e6db6335642d82fe7ac0d2ceb7e82ca00
Author: Adomas Venčkauskas <adomas.ven@gmail.com>
Date: Wed, 23 Dec 2015 09:56:47 +0000
Closes #833, Displays a warning dialog if API key present but library empty
Diffstat:
4 files changed, 94 insertions(+), 4 deletions(-)
diff --git a/chrome/content/zotero/xpcom/data/library.js b/chrome/content/zotero/xpcom/data/library.js
@@ -567,6 +567,15 @@ Zotero.Library.prototype.updateSearches = Zotero.Promise.coroutine(function* ()
this._hasSearches = !!(yield Zotero.DB.valueQueryAsync(sql, this.libraryID));
});
+Zotero.Library.prototype.hasItems = Zotero.Promise.coroutine(function* () {
+ if (!this.id) {
+ throw new Error("Library is not saved yet");
+ }
+ let sql = 'SELECT COUNT(*)>0 FROM items WHERE libraryID=?';
+
+ return Zotero.DB.valueQueryAsync(sql, this.libraryID);
+});
+
Zotero.Library.prototype.hasItem = function (item) {
if (!(item instanceof Zotero.Item)) {
throw new Error("item must be a Zotero.Item");
diff --git a/chrome/content/zotero/xpcom/sync/syncRunner.js b/chrome/content/zotero/xpcom/sync/syncRunner.js
@@ -136,14 +136,20 @@ Zotero.Sync.Runner_Module = function (options = {}) {
try {
let client = this.getAPIClient({ apiKey });
-
let keyInfo = yield this.checkAccess(client, options);
- if (!keyInfo) {
+
+ let emptyLibraryContinue = yield this.checkEmptyLibrary(keyInfo);
+ if (!emptyLibraryContinue) {
this.end();
- Zotero.debug("Syncing cancelled");
+ Zotero.debug("Syncing cancelled because user library is empty");
return false;
}
-
+
+ if (!Zotero.Users.getCurrentUserID()) {
+ Zotero.Users.setCurrentUserID(keyInfo.userID);
+ Zotero.Users.setCurrentUsername(keyInfo.username);
+ }
+
let engineOptions = {
apiClient: client,
caller: this.caller,
@@ -231,6 +237,45 @@ Zotero.Sync.Runner_Module = function (options = {}) {
return json;
});
+
+
+ // Prompt if library empty and there is no userID stored
+ this.checkEmptyLibrary = Zotero.Promise.coroutine(function* (keyInfo) {
+ let library = Zotero.Libraries.userLibrary;
+ let userID = Zotero.Users.getCurrentUserID();
+
+ if (!userID) {
+ let hasItems = yield library.hasItems();
+ if (!hasItems) {
+ let ps = Services.prompt;
+ let index = ps.confirmEx(
+ null,
+ Zotero.getString('general.warning'),
+ Zotero.getString('sync.warning.emptyLibrary', [keyInfo.username, Zotero.clientName]) + "\n\n"
+ + Zotero.getString('sync.warning.existingDataElsewhere', Zotero.clientName),
+ (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING)
+ + (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL)
+ + (ps.BUTTON_POS_2 * ps.BUTTON_TITLE_IS_STRING),
+ Zotero.getString('sync.sync'),
+ null,
+ Zotero.getString('dataDir.changeDataDirectory'),
+ null, {}
+ );
+ if (index == 1) {
+ return false;
+ }
+ else if (index == 2) {
+ var win = Services.wm.getMostRecentWindow("navigator:browser");
+ win.openDialog("chrome://zotero/content/preferences/preferences.xul", null, null, {
+ pane: 'zotero-prefpane-advanced',
+ tabIndex: 1
+ });
+ return false;
+ }
+ }
+ }
+ return true;
+ });
this.checkLibraries = Zotero.Promise.coroutine(function* (client, options, keyInfo, libraries = []) {
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties
@@ -112,6 +112,7 @@ dataDir.notFound = The Zotero data directory could not be found.
dataDir.previousDir = Previous directory:
dataDir.useProfileDir = Use %S profile directory
dataDir.selectDir = Select a Zotero data directory
+dataDir.changeDataDirectory = Change Data Directory…
dataDir.unsafeLocation.selected.dropbox = Choosing a data directory within Dropbox may corrupt your database.
dataDir.unsafeLocation.selected.useAnyway = Use this directory anyway?
dataDir.unsafeLocation.existing.dropbox = Your Zotero data directory is within Dropbox, which may lead to data corruption.
@@ -828,6 +829,8 @@ sync.localDataWillBeCombined = If you continue, local Zotero data will be combi
sync.localGroupsWillBeRemoved1 = Local groups, including any with changed items, will also be removed from this computer.
sync.avoidCombiningData = To avoid combining data, revert to the '%S' account or use the Reset options in the Sync pane of the Zotero preferences.
sync.unlinkWarning = Are you sure you want to unlink this account?\n\n%S will no longer sync your data, but your data will remain locally.
+sync.warning.emptyLibrary = You are about to sync the ‘%1$S’ account to an empty %2$S database. This could happen if you removed your previous %2$S database or if the location of your data directory changed.
+sync.warning.existingDataElsewhere = If your %S data exists elsewhere on your computer, you should move it to your current data directory or change your data directory location to point to the existing data.
sync.conflict.autoChange.alert = One or more locally deleted Zotero %S have been modified remotely since the last sync.
sync.conflict.autoChange.log = A Zotero %S has changed both locally and remotely since the last sync:
diff --git a/test/tests/libraryTest.js b/test/tests/libraryTest.js
@@ -256,6 +256,39 @@ describe("Zotero.Library", function() {
assert.isFalse(library.hasSearches());
})
});
+ describe("#hasItems()", function() {
+ it("should throw if called before saving a library", function* () {
+ let library = new Zotero.Library();
+ try {
+ yield library.hasItems();
+ assert.isFalse(true, "Library#hasItems did not throw an error");
+ } catch (e) {
+ assert.ok(e);
+ }
+ });
+ it("should stay up to date as items are added and removed", function* () {
+ let library = yield createGroup({ editable: true });
+ let libraryID = library.libraryID;
+ var hasItems = yield library.hasItems();
+ assert.isFalse(hasItems);
+
+ let i1 = yield createDataObject('item', { libraryID });
+ hasItems = yield library.hasItems();
+ assert.isTrue(hasItems);
+
+ let i2 = yield createDataObject('item', { libraryID });
+ hasItems = yield library.hasItems();
+ assert.isTrue(hasItems);
+
+ yield i1.eraseTx();
+ hasItems = yield library.hasItems();
+ assert.isTrue(hasItems);
+
+ yield i2.eraseTx();
+ hasItems = yield library.hasItems();
+ assert.isFalse(hasItems);
+ });
+ });
describe("#updateLastSyncTime()", function() {
it("should set sync time to current time", function* () {
let group = yield createGroup();