Load synced settings (incl. tag colors) at startup
This commit is contained in:
parent
60830c27ee
commit
8e5016ae4d
17 changed files with 252 additions and 184 deletions
|
@ -137,7 +137,8 @@
|
||||||
return Zotero.spawn(function* () {
|
return Zotero.spawn(function* () {
|
||||||
if (type == 'setting') {
|
if (type == 'setting') {
|
||||||
if (ids.some(function (val) val.split("/")[1] == 'tagColors') && this.item) {
|
if (ids.some(function (val) val.split("/")[1] == 'tagColors') && this.item) {
|
||||||
return this.reload();
|
this.reload();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == 'item-tag') {
|
else if (type == 'item-tag') {
|
||||||
|
@ -194,7 +195,8 @@
|
||||||
}
|
}
|
||||||
else if (type == 'tag') {
|
else if (type == 'tag') {
|
||||||
if (event == 'modify') {
|
if (event == 'modify') {
|
||||||
return this.reload();
|
this.reload();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
@ -204,38 +206,32 @@
|
||||||
|
|
||||||
<method name="reload">
|
<method name="reload">
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
return Zotero.spawn(function* () {
|
Zotero.debug('Reloading tags box');
|
||||||
Zotero.debug('Reloading tags box');
|
|
||||||
|
// Cancel field focusing while we're updating
|
||||||
// Cancel field focusing while we're updating
|
this._reloading = true;
|
||||||
this._reloading = true;
|
|
||||||
|
this.id('addButton').hidden = !this.editable;
|
||||||
this.id('addButton').hidden = !this.editable;
|
|
||||||
|
this._tagColors = Zotero.Tags.getColors(this.item.libraryID);
|
||||||
this._tagColors = yield Zotero.Tags.getColors(this.item.libraryID)
|
|
||||||
.tap(() => Zotero.Promise.check(this.mode));
|
var rows = this.id('tagRows');
|
||||||
|
while(rows.hasChildNodes()) {
|
||||||
var rows = this.id('tagRows');
|
rows.removeChild(rows.firstChild);
|
||||||
while(rows.hasChildNodes()) {
|
}
|
||||||
rows.removeChild(rows.firstChild);
|
var tags = this.item.getTags();
|
||||||
}
|
|
||||||
var tags = this.item.getTags();
|
// Sort tags alphabetically
|
||||||
|
var collation = Zotero.getLocaleCollation();
|
||||||
// Sort tags alphabetically
|
tags.sort(function (a, b) collation.compareString(1, a.tag, b.tag));
|
||||||
var collation = Zotero.getLocaleCollation();
|
|
||||||
tags.sort(function (a, b) collation.compareString(1, a.tag, b.tag));
|
for (let i=0; i<tags.length; i++) {
|
||||||
|
this.addDynamicRow(tags[i], i+1);
|
||||||
for (let i=0; i<tags.length; i++) {
|
}
|
||||||
this.addDynamicRow(tags[i], i+1);
|
this.updateCount(tags.length);
|
||||||
}
|
|
||||||
this.updateCount(tags.length);
|
this._reloading = false;
|
||||||
|
this._focusField();
|
||||||
this._reloading = false;
|
|
||||||
this._focusField();
|
|
||||||
|
|
||||||
var event = new Event('refresh');
|
|
||||||
this.dispatchEvent(event);
|
|
||||||
}, this);
|
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
@ -711,7 +707,7 @@
|
||||||
this._lastTabIndex = this.item.getTags().length;
|
this._lastTabIndex = this.item.getTags().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield this.reload();
|
this.reload();
|
||||||
}
|
}
|
||||||
// Single tag at end
|
// Single tag at end
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -236,8 +236,7 @@
|
||||||
var emptyRegular = true;
|
var emptyRegular = true;
|
||||||
var tagsBox = this.id('tags-box');
|
var tagsBox = this.id('tags-box');
|
||||||
|
|
||||||
var tagColors = yield Zotero.Tags.getColors(this.libraryID)
|
var tagColors = Zotero.Tags.getColors(this.libraryID);
|
||||||
.tap(() => Zotero.Promise.check(this.mode));
|
|
||||||
|
|
||||||
// If new data, rebuild boxes
|
// If new data, rebuild boxes
|
||||||
if (fetch || this._dirty) {
|
if (fetch || this._dirty) {
|
||||||
|
@ -375,45 +374,43 @@
|
||||||
<method name="insertSorted">
|
<method name="insertSorted">
|
||||||
<parameter name="tagObjs"/>
|
<parameter name="tagObjs"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
return Zotero.spawn(function* () {
|
var tagColors = Zotero.Tags.getColors(this._libraryID);
|
||||||
var tagColors = yield Zotero.Tags.getColors(this._libraryID);
|
|
||||||
|
var collation = Zotero.getLocaleCollation();
|
||||||
var collation = Zotero.getLocaleCollation();
|
tagObjs.sort(function (a, b) {
|
||||||
tagObjs.sort(function (a, b) {
|
return collation.compareString(1, a.tag, b.tag);
|
||||||
return collation.compareString(1, a.tag, b.tag);
|
});
|
||||||
});
|
|
||||||
|
// Create tag elements in sorted order
|
||||||
// Create tag elements in sorted order
|
var tagsBox = this.id('tags-box');
|
||||||
var tagsBox = this.id('tags-box');
|
var tagElems = tagsBox.childNodes;
|
||||||
var tagElems = tagsBox.childNodes;
|
var j = 0;
|
||||||
var j = 0;
|
loop:
|
||||||
loop:
|
for (let i = 0; i < tagObjs.length; i++) {
|
||||||
for (let i = 0; i < tagObjs.length; i++) {
|
let tagObj = tagObjs[i];
|
||||||
let tagObj = tagObjs[i];
|
while (j < tagElems.length) {
|
||||||
while (j < tagElems.length) {
|
let elem = tagElems[j];
|
||||||
let elem = tagElems[j];
|
let comp = collation.compareString(
|
||||||
let comp = collation.compareString(
|
1, tagObj.tag, elem.textContent
|
||||||
1, tagObj.tag, elem.textContent
|
|
||||||
);
|
|
||||||
// If tag already exists, update type if new one is lower
|
|
||||||
if (comp == 0) {
|
|
||||||
let tagType = elem.getAttribute('tagType');
|
|
||||||
if (parseInt(tagObj.type) < parseInt(tagType)) {
|
|
||||||
elem.setAttribute('tagType', tagObj.type);
|
|
||||||
}
|
|
||||||
continue loop;
|
|
||||||
}
|
|
||||||
if (comp < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
this._insertClickableTag(tagsBox, tagObj, tagElems[j]);
|
|
||||||
this._updateClickableTag(
|
|
||||||
tagElems[j], tagElems[j].textContent, tagColors
|
|
||||||
);
|
);
|
||||||
|
// If tag already exists, update type if new one is lower
|
||||||
|
if (comp == 0) {
|
||||||
|
let tagType = elem.getAttribute('tagType');
|
||||||
|
if (parseInt(tagObj.type) < parseInt(tagType)) {
|
||||||
|
elem.setAttribute('tagType', tagObj.type);
|
||||||
|
}
|
||||||
|
continue loop;
|
||||||
|
}
|
||||||
|
if (comp < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
}, this);
|
this._insertClickableTag(tagsBox, tagObj, tagElems[j]);
|
||||||
|
this._updateClickableTag(
|
||||||
|
tagElems[j], tagElems[j].textContent, tagColors
|
||||||
|
);
|
||||||
|
}
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
@ -512,7 +509,7 @@
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
if (tagObjs.length) {
|
if (tagObjs.length) {
|
||||||
yield this.insertSorted(tagObjs);
|
this.insertSorted(tagObjs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Don't add anything for item or collection-item; just update scope
|
// Don't add anything for item or collection-item; just update scope
|
||||||
|
@ -671,7 +668,7 @@
|
||||||
// Colored tags don't need to exist, so in that case
|
// Colored tags don't need to exist, so in that case
|
||||||
// just rename the color setting
|
// just rename the color setting
|
||||||
else {
|
else {
|
||||||
let color = yield Zotero.Tags.getColor(this.libraryID, oldName);
|
let color = Zotero.Tags.getColor(this.libraryID, oldName);
|
||||||
if (!color) {
|
if (!color) {
|
||||||
throw new Error("Can't rename missing tag");
|
throw new Error("Can't rename missing tag");
|
||||||
}
|
}
|
||||||
|
@ -715,18 +712,6 @@
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<method name="getColor">
|
|
||||||
<parameter name="tagIDs"/>
|
|
||||||
<body><![CDATA[
|
|
||||||
return Zotero.spawn(function* () {
|
|
||||||
tagIDs = tagIDs.split('-');
|
|
||||||
var name = yield Zotero.Tags.getName(tagIDs[0]);
|
|
||||||
var colorData = yield Zotero.Tags.getColor(this.libraryID, name);
|
|
||||||
return colorData ? colorData.color : '#000000';
|
|
||||||
}.bind(this));
|
|
||||||
]]></body>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
|
|
||||||
<method name="_insertClickableTag">
|
<method name="_insertClickableTag">
|
||||||
<parameter name="tagsBox"/>
|
<parameter name="tagsBox"/>
|
||||||
|
@ -877,7 +862,7 @@
|
||||||
name: name
|
name: name
|
||||||
};
|
};
|
||||||
|
|
||||||
var tagColors = yield Zotero.Tags.getColors(this.libraryID);
|
var tagColors = Zotero.Tags.getColors(this.libraryID);
|
||||||
if (tagColors.size >= Zotero.Tags.MAX_COLORED_TAGS && !tagColors.has(io.name)) {
|
if (tagColors.size >= Zotero.Tags.MAX_COLORED_TAGS && !tagColors.has(io.name)) {
|
||||||
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||||
.getService(Components.interfaces.nsIPromptService);
|
.getService(Components.interfaces.nsIPromptService);
|
||||||
|
|
|
@ -30,7 +30,7 @@ Zotero.Creators = new function() {
|
||||||
|
|
||||||
var _cache = {};
|
var _cache = {};
|
||||||
|
|
||||||
this.init = Zotero.Promise.coroutine(function* (libraryID) {
|
this.init = Zotero.Promise.coroutine(function* () {
|
||||||
var sql = "SELECT * FROM creators";
|
var sql = "SELECT * FROM creators";
|
||||||
var rows = yield Zotero.DB.queryAsync(sql);
|
var rows = yield Zotero.DB.queryAsync(sql);
|
||||||
for (let i = 0; i < rows.length; i++) {
|
for (let i = 0; i < rows.length; i++) {
|
||||||
|
|
|
@ -373,12 +373,13 @@ Zotero.DataObjects.prototype._loadDataType = Zotero.Promise.coroutine(function*
|
||||||
Zotero.debug(`Loaded ${dataType} in ${libraryName} in ${new Date() - t} ms`);
|
Zotero.debug(`Loaded ${dataType} in ${libraryName} in ${new Date() - t} ms`);
|
||||||
});
|
});
|
||||||
|
|
||||||
Zotero.DataObjects.prototype.loadAllData = Zotero.Promise.coroutine(function* (libraryID, ids) {
|
Zotero.DataObjects.prototype.loadAll = Zotero.Promise.coroutine(function* (libraryID, ids) {
|
||||||
var t = new Date();
|
var t = new Date();
|
||||||
var libraryName = Zotero.Libraries.get(libraryID).name;
|
var libraryName = Zotero.Libraries.get(libraryID).name;
|
||||||
|
|
||||||
Zotero.debug("Loading all data"
|
Zotero.debug("Loading "
|
||||||
+ (ids ? " for " + ids.length + " " + this._ZDO_objects : '')
|
+ (ids ? ids.length : "all") + " "
|
||||||
|
+ (ids && ids.length == 1 ? this._ZDO_object : this._ZDO_objects)
|
||||||
+ " in " + libraryName);
|
+ " in " + libraryName);
|
||||||
|
|
||||||
let dataTypes = this.ObjectClass.prototype._dataTypes;
|
let dataTypes = this.ObjectClass.prototype._dataTypes;
|
||||||
|
|
|
@ -3548,7 +3548,7 @@ Zotero.Item.prototype.getImageSrcWithTags = Zotero.Promise.coroutine(function* (
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagColors = yield Zotero.Tags.getColors(this.libraryID);
|
var tagColors = Zotero.Tags.getColors(this.libraryID);
|
||||||
var colorData = [];
|
var colorData = [];
|
||||||
for (let i=0; i<tags.length; i++) {
|
for (let i=0; i<tags.length; i++) {
|
||||||
let tag = tags[i];
|
let tag = tags[i];
|
||||||
|
|
|
@ -315,6 +315,16 @@ Zotero.Library.prototype._reloadFromDB = Zotero.Promise.coroutine(function* () {
|
||||||
this._loadDataFromRow(row);
|
this._loadDataFromRow(row);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load object data in this library
|
||||||
|
*/
|
||||||
|
Zotero.Library.prototype.loadAllDataTypes = Zotero.Promise.coroutine(function* () {
|
||||||
|
yield Zotero.SyncedSettings.loadAll(this.libraryID);
|
||||||
|
yield Zotero.Collections.loadAll(this.libraryID);
|
||||||
|
yield Zotero.Searches.loadAll(this.libraryID);
|
||||||
|
yield Zotero.Items.loadAll(this.libraryID);
|
||||||
|
});
|
||||||
|
|
||||||
Zotero.Library.prototype.isChildObjectAllowed = function(type) {
|
Zotero.Library.prototype.isChildObjectAllowed = function(type) {
|
||||||
return this._childObjectTypes.indexOf(type) != -1;
|
return this._childObjectTypes.indexOf(type) != -1;
|
||||||
};
|
};
|
||||||
|
@ -461,6 +471,8 @@ Zotero.Library.prototype._finalizeSave = Zotero.Promise.coroutine(function* (env
|
||||||
yield this._reloadFromDB();
|
yield this._reloadFromDB();
|
||||||
|
|
||||||
Zotero.Libraries.register(this);
|
Zotero.Libraries.register(this);
|
||||||
|
|
||||||
|
yield this.loadAllDataTypes();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ Zotero.Tags = new function() {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all tags indexed by tagID
|
* Get all tags in library
|
||||||
*
|
*
|
||||||
* @param {Number} libraryID
|
* @param {Number} libraryID
|
||||||
* @param {Array} [types] Tag types to fetch
|
* @param {Array} [types] Tag types to fetch
|
||||||
|
@ -181,7 +181,7 @@ Zotero.Tags = new function() {
|
||||||
|
|
||||||
// We need to know if the old tag has a color assigned so that
|
// We need to know if the old tag has a color assigned so that
|
||||||
// we can assign it to the new name
|
// we can assign it to the new name
|
||||||
var oldColorData = yield this.getColor(libraryID, oldName);
|
var oldColorData = this.getColor(libraryID, oldName);
|
||||||
|
|
||||||
yield Zotero.DB.executeTransaction(function* () {
|
yield Zotero.DB.executeTransaction(function* () {
|
||||||
var oldItemIDs = yield this.getTagItems(libraryID, oldTagID);
|
var oldItemIDs = yield this.getTagItems(libraryID, oldTagID);
|
||||||
|
@ -393,13 +393,13 @@ Zotero.Tags = new function() {
|
||||||
*
|
*
|
||||||
* @param {Integer} libraryID
|
* @param {Integer} libraryID
|
||||||
* @param {String} name Tag name
|
* @param {String} name Tag name
|
||||||
* @return {Promise} A Q promise for the tag color as a hex string (e.g., '#990000')
|
* @return {Object|false} An object containing 'color' as a hex string (e.g., '#990000') and
|
||||||
|
* 'position', or false if no colored tag with that name
|
||||||
*/
|
*/
|
||||||
this.getColor = function (libraryID, name) {
|
this.getColor = function (libraryID, name) {
|
||||||
return this.getColors(libraryID)
|
// Cache colors
|
||||||
.then(function () {
|
this.getColors(libraryID);
|
||||||
return _libraryColorsByName[libraryID].get(name) || false;
|
return _libraryColorsByName[libraryID].get(name) || false;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -408,14 +408,12 @@ Zotero.Tags = new function() {
|
||||||
*
|
*
|
||||||
* @param {Integer} libraryID
|
* @param {Integer} libraryID
|
||||||
* @param {Integer} position The position of the tag, starting at 0
|
* @param {Integer} position The position of the tag, starting at 0
|
||||||
* @return {Promise} A promise for an object containing 'name' and 'color'
|
* @return {Object|false} An object containing 'name' and 'color', or false if no color at
|
||||||
|
* the given position
|
||||||
*/
|
*/
|
||||||
this.getColorByPosition = function (libraryID, position) {
|
this.getColorByPosition = function (libraryID, position) {
|
||||||
return this.getColors(libraryID)
|
this.getColors(libraryID);
|
||||||
.then(function () {
|
return _libraryColors[libraryID][position] ? _libraryColors[libraryID][position] : false;
|
||||||
return _libraryColors[libraryID][position]
|
|
||||||
? _libraryColors[libraryID][position] : false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -423,20 +421,19 @@ Zotero.Tags = new function() {
|
||||||
* Get colored tags within a given library
|
* Get colored tags within a given library
|
||||||
*
|
*
|
||||||
* @param {Integer} libraryID
|
* @param {Integer} libraryID
|
||||||
* @return {Promise<Map>} - A promise for a Map with tag names as keys and
|
* @return {Map} - A Map with tag names as keys and objects containing 'color' and 'position'
|
||||||
* objects containing 'color' and 'position' as values
|
* as values
|
||||||
*/
|
*/
|
||||||
this.getColors = Zotero.Promise.coroutine(function* (libraryID) {
|
this.getColors = function (libraryID) {
|
||||||
|
if (!libraryID) {
|
||||||
|
throw new Error("libraryID not provided");
|
||||||
|
}
|
||||||
|
|
||||||
if (_libraryColorsByName[libraryID]) {
|
if (_libraryColorsByName[libraryID]) {
|
||||||
return _libraryColorsByName[libraryID];
|
return _libraryColorsByName[libraryID];
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagColors = yield Zotero.SyncedSettings.get(libraryID, 'tagColors');
|
var tagColors = Zotero.SyncedSettings.get(libraryID, 'tagColors');
|
||||||
|
|
||||||
// If the colors became available from another run
|
|
||||||
if (_libraryColorsByName[libraryID]) {
|
|
||||||
return _libraryColorsByName[libraryID];
|
|
||||||
}
|
|
||||||
|
|
||||||
tagColors = tagColors || [];
|
tagColors = tagColors || [];
|
||||||
|
|
||||||
|
@ -452,7 +449,7 @@ Zotero.Tags = new function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return _libraryColorsByName[libraryID];
|
return _libraryColorsByName[libraryID];
|
||||||
});
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -465,7 +462,7 @@ Zotero.Tags = new function() {
|
||||||
throw new Error("libraryID must be an integer");
|
throw new Error("libraryID must be an integer");
|
||||||
}
|
}
|
||||||
|
|
||||||
yield this.getColors(libraryID);
|
this.getColors(libraryID);
|
||||||
|
|
||||||
var tagColors = _libraryColors[libraryID];
|
var tagColors = _libraryColors[libraryID];
|
||||||
|
|
||||||
|
@ -541,7 +538,7 @@ Zotero.Tags = new function() {
|
||||||
delete _libraryColorsByName[libraryID];
|
delete _libraryColorsByName[libraryID];
|
||||||
|
|
||||||
// Get the tag colors for each library in which they were modified
|
// Get the tag colors for each library in which they were modified
|
||||||
let tagColors = yield Zotero.SyncedSettings.get(libraryID, 'tagColors');
|
let tagColors = Zotero.SyncedSettings.get(libraryID, 'tagColors');
|
||||||
if (!tagColors) {
|
if (!tagColors) {
|
||||||
tagColors = [];
|
tagColors = [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,12 +170,11 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
|
||||||
if (coloredTagsRE.test(key)) {
|
if (coloredTagsRE.test(key)) {
|
||||||
let libraryID = self.collectionTreeRow.ref.libraryID;
|
let libraryID = self.collectionTreeRow.ref.libraryID;
|
||||||
let position = parseInt(key) - 1;
|
let position = parseInt(key) - 1;
|
||||||
let colorData = yield Zotero.Tags.getColorByPosition(libraryID, position);
|
let colorData = Zotero.Tags.getColorByPosition(libraryID, position);
|
||||||
// If a color isn't assigned to this number or any
|
// If a color isn't assigned to this number or any
|
||||||
// other numbers, allow key navigation
|
// other numbers, allow key navigation
|
||||||
if (!colorData) {
|
if (!colorData) {
|
||||||
let colors = yield Zotero.Tags.getColors(libraryID);
|
return !Zotero.Tags.getColors(libraryID).size;
|
||||||
return !colors.size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var items = self.getSelectedItems();
|
var items = self.getSelectedItems();
|
||||||
|
|
|
@ -815,7 +815,7 @@ Zotero.Search.prototype.search = Zotero.Promise.coroutine(function* (asTempTable
|
||||||
/**
|
/**
|
||||||
* Populate the object's data from an API JSON data object
|
* Populate the object's data from an API JSON data object
|
||||||
*
|
*
|
||||||
* If this object is identified (has an id or library/key), loadAllData() must have been called.
|
* If this object is identified (has an id or library/key), loadAll() must have been called.
|
||||||
*/
|
*/
|
||||||
Zotero.Search.prototype.fromJSON = function (json) {
|
Zotero.Search.prototype.fromJSON = function (json) {
|
||||||
if (!json.name) {
|
if (!json.name) {
|
||||||
|
|
|
@ -290,7 +290,7 @@ Zotero.Sync.Data.Engine.prototype._startDownload = Zotero.Promise.coroutine(func
|
||||||
}
|
}
|
||||||
|
|
||||||
if (objectType == 'setting') {
|
if (objectType == 'setting') {
|
||||||
let meta = yield Zotero.SyncedSettings.getMetadata(this.libraryID, key);
|
let meta = Zotero.SyncedSettings.getMetadata(this.libraryID, key);
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
* @namespace
|
* @namespace
|
||||||
*/
|
*/
|
||||||
Zotero.SyncedSettings = (function () {
|
Zotero.SyncedSettings = (function () {
|
||||||
|
var _cache = {};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Public methods
|
// Public methods
|
||||||
//
|
//
|
||||||
|
@ -34,47 +36,95 @@ Zotero.SyncedSettings = (function () {
|
||||||
idColumn: "setting",
|
idColumn: "setting",
|
||||||
table: "syncedSettings",
|
table: "syncedSettings",
|
||||||
|
|
||||||
get: Zotero.Promise.coroutine(function* (libraryID, setting) {
|
loadAll: Zotero.Promise.coroutine(function* (libraryID) {
|
||||||
var sql = "SELECT value FROM syncedSettings WHERE setting=? AND libraryID=?";
|
Zotero.debug("Loading synced settings for library " + libraryID);
|
||||||
var json = yield Zotero.DB.valueQueryAsync(sql, [setting, libraryID]);
|
|
||||||
if (!json) {
|
if (!_cache[libraryID]) {
|
||||||
return false;
|
_cache[libraryID] = {};
|
||||||
}
|
}
|
||||||
return JSON.parse(json);
|
|
||||||
|
var invalid = [];
|
||||||
|
|
||||||
|
var sql = "SELECT setting, value, synced, version FROM syncedSettings "
|
||||||
|
+ "WHERE libraryID=?";
|
||||||
|
yield Zotero.DB.queryAsync(
|
||||||
|
sql,
|
||||||
|
libraryID,
|
||||||
|
{
|
||||||
|
onRow: function (row) {
|
||||||
|
var setting = row.getResultByIndex(0);
|
||||||
|
|
||||||
|
var value = row.getResultByIndex(1);
|
||||||
|
try {
|
||||||
|
value = JSON.parse(value);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
invalid.push([libraryID, setting]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cache[libraryID][setting] = {
|
||||||
|
value,
|
||||||
|
synced: !!row.getResultByIndex(2),
|
||||||
|
version: row.getResultByIndex(3)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: Delete invalid settings
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return settings object
|
||||||
|
*
|
||||||
|
* @return {Object|null}
|
||||||
|
*/
|
||||||
|
get: function (libraryID, setting) {
|
||||||
|
if (!_cache[libraryID]) {
|
||||||
|
throw new Zotero.Exception.UnloadedDataException(
|
||||||
|
"Synced settings not loaded for library " + libraryID,
|
||||||
|
"syncedSettings"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_cache[libraryID][setting]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse(JSON.stringify(_cache[libraryID][setting].value));
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by sync and tests
|
* Used by sync and tests
|
||||||
*
|
*
|
||||||
* @return {Object} - Object with 'synced' and 'version' properties
|
* @return {Object} - Object with 'synced' and 'version' properties
|
||||||
*/
|
*/
|
||||||
getMetadata: Zotero.Promise.coroutine(function* (libraryID, setting) {
|
getMetadata: function (libraryID, setting) {
|
||||||
var sql = "SELECT * FROM syncedSettings WHERE setting=? AND libraryID=?";
|
if (!_cache[libraryID]) {
|
||||||
var row = yield Zotero.DB.rowQueryAsync(sql, [setting, libraryID]);
|
throw new Zotero.Exception.UnloadedDataException(
|
||||||
if (!row) {
|
"Synced settings not loaded for library " + libraryID,
|
||||||
return false;
|
"syncedSettings"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var o = _cache[libraryID][setting];
|
||||||
|
if (!o) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
synced: !!row.synced,
|
synced: o.synced,
|
||||||
version: row.version
|
version: o.version
|
||||||
};
|
};
|
||||||
}),
|
},
|
||||||
|
|
||||||
set: Zotero.Promise.coroutine(function* (libraryID, setting, value, version = 0, synced) {
|
set: Zotero.Promise.coroutine(function* (libraryID, setting, value, version = 0, synced) {
|
||||||
if (typeof value == undefined) {
|
if (typeof value == undefined) {
|
||||||
throw new Error("Value not provided");
|
throw new Error("Value not provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: get rid of this once we have proper affected rows handling
|
var currentValue = this.get(libraryID, setting);
|
||||||
var sql = "SELECT value FROM syncedSettings WHERE setting=? AND libraryID=?";
|
var hasCurrentValue = currentValue !== null;
|
||||||
var currentValue = yield Zotero.DB.valueQueryAsync(sql, [setting, libraryID]);
|
|
||||||
|
|
||||||
// Make sure we can tell the difference between a
|
|
||||||
// missing setting (FALSE as returned by valueQuery())
|
|
||||||
// and a FALSE setting (FALSE as returned by JSON.parse())
|
|
||||||
var hasCurrentValue = currentValue !== false;
|
|
||||||
|
|
||||||
currentValue = JSON.parse(currentValue);
|
|
||||||
|
|
||||||
// Value hasn't changed
|
// Value hasn't changed
|
||||||
if (value === currentValue) {
|
if (value === currentValue) {
|
||||||
|
@ -93,7 +143,7 @@ Zotero.SyncedSettings = (function () {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentValue === false) {
|
if (!hasCurrentValue) {
|
||||||
var event = 'add';
|
var event = 'add';
|
||||||
var extraData = {};
|
var extraData = {};
|
||||||
}
|
}
|
||||||
|
@ -102,6 +152,7 @@ Zotero.SyncedSettings = (function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
synced = synced ? 1 : 0;
|
synced = synced ? 1 : 0;
|
||||||
|
version = parseInt(version);
|
||||||
|
|
||||||
if (hasCurrentValue) {
|
if (hasCurrentValue) {
|
||||||
var sql = "UPDATE syncedSettings SET value=?, version=?, synced=? "
|
var sql = "UPDATE syncedSettings SET value=?, version=?, synced=? "
|
||||||
|
@ -117,6 +168,13 @@ Zotero.SyncedSettings = (function () {
|
||||||
sql, [setting, libraryID, JSON.stringify(value), version, synced]
|
sql, [setting, libraryID, JSON.stringify(value), version, synced]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cache[libraryID][setting] = {
|
||||||
|
value,
|
||||||
|
synced: !!synced,
|
||||||
|
version
|
||||||
|
}
|
||||||
|
|
||||||
yield Zotero.Notifier.trigger(event, 'setting', [id], extraData);
|
yield Zotero.Notifier.trigger(event, 'setting', [id], extraData);
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
|
@ -124,22 +182,16 @@ Zotero.SyncedSettings = (function () {
|
||||||
clear: Zotero.Promise.coroutine(function* (libraryID, setting, options) {
|
clear: Zotero.Promise.coroutine(function* (libraryID, setting, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
// TODO: get rid of this once we have proper affected rows handling
|
var currentValue = this.get(libraryID, setting);
|
||||||
var sql = "SELECT value FROM syncedSettings WHERE setting=? AND libraryID=?";
|
var hasCurrentValue = currentValue !== null;
|
||||||
var currentValue = yield Zotero.DB.valueQueryAsync(sql, [setting, libraryID]);
|
|
||||||
if (currentValue === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
currentValue = JSON.parse(currentValue);
|
|
||||||
|
|
||||||
var id = libraryID + '/' + setting;
|
var id = libraryID + '/' + setting;
|
||||||
|
|
||||||
var extraData = {};
|
var extraData = {};
|
||||||
extraData[id] = {
|
extraData[id] = {
|
||||||
changed: {}
|
changed: {
|
||||||
};
|
value: currentValue
|
||||||
extraData[id].changed = {
|
}
|
||||||
value: currentValue
|
|
||||||
};
|
};
|
||||||
if (options.skipDeleteLog) {
|
if (options.skipDeleteLog) {
|
||||||
extraData[id].skipDeleteLog = true;
|
extraData[id].skipDeleteLog = true;
|
||||||
|
@ -148,6 +200,8 @@ Zotero.SyncedSettings = (function () {
|
||||||
var sql = "DELETE FROM syncedSettings WHERE setting=? AND libraryID=?";
|
var sql = "DELETE FROM syncedSettings WHERE setting=? AND libraryID=?";
|
||||||
yield Zotero.DB.queryAsync(sql, [setting, libraryID]);
|
yield Zotero.DB.queryAsync(sql, [setting, libraryID]);
|
||||||
|
|
||||||
|
delete _cache[libraryID][setting];
|
||||||
|
|
||||||
yield Zotero.Notifier.trigger('delete', 'setting', [id], extraData);
|
yield Zotero.Notifier.trigger('delete', 'setting', [id], extraData);
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
|
|
|
@ -629,9 +629,8 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
|
||||||
|
|
||||||
let libraryIDs = Zotero.Libraries.getAll().map(x => x.libraryID);
|
let libraryIDs = Zotero.Libraries.getAll().map(x => x.libraryID);
|
||||||
for (let libraryID of libraryIDs) {
|
for (let libraryID of libraryIDs) {
|
||||||
yield Zotero.Collections.loadAllData(libraryID);
|
let library = Zotero.Libraries.get(libraryID);
|
||||||
yield Zotero.Searches.loadAllData(libraryID);
|
yield library.loadAllDataTypes();
|
||||||
yield Zotero.Items.loadAllData(libraryID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
yield Zotero.QuickCopy.init();
|
yield Zotero.QuickCopy.init();
|
||||||
|
|
|
@ -150,6 +150,11 @@ describe("Zotero.Library", function() {
|
||||||
yield library.saveTx();
|
yield library.saveTx();
|
||||||
assert.isFalse(Zotero.Libraries.isEditable(library.libraryID));
|
assert.isFalse(Zotero.Libraries.isEditable(library.libraryID));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should initialize library after creation", function* () {
|
||||||
|
let library = yield createGroup({});
|
||||||
|
Zotero.SyncedSettings.get(library.libraryID, "tagColors");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe("#erase()", function() {
|
describe("#erase()", function() {
|
||||||
it("should erase a group library", function* () {
|
it("should erase a group library", function* () {
|
||||||
|
|
|
@ -239,10 +239,10 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
assert.equal(Zotero.Libraries.getVersion(userLibraryID), 3);
|
assert.equal(Zotero.Libraries.getVersion(userLibraryID), 3);
|
||||||
|
|
||||||
// Make sure local objects exist
|
// Make sure local objects exist
|
||||||
var setting = yield Zotero.SyncedSettings.get(userLibraryID, "tagColors");
|
var setting = Zotero.SyncedSettings.get(userLibraryID, "tagColors");
|
||||||
assert.lengthOf(setting, 1);
|
assert.lengthOf(setting, 1);
|
||||||
assert.equal(setting[0].name, 'A');
|
assert.equal(setting[0].name, 'A');
|
||||||
var settingMetadata = yield Zotero.SyncedSettings.getMetadata(userLibraryID, "tagColors");
|
var settingMetadata = Zotero.SyncedSettings.getMetadata(userLibraryID, "tagColors");
|
||||||
assert.equal(settingMetadata.version, 2);
|
assert.equal(settingMetadata.version, 2);
|
||||||
assert.isTrue(settingMetadata.synced);
|
assert.isTrue(settingMetadata.synced);
|
||||||
|
|
||||||
|
@ -812,7 +812,7 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
yield engine._startDownload();
|
yield engine._startDownload();
|
||||||
|
|
||||||
// Make sure objects were deleted
|
// Make sure objects were deleted
|
||||||
assert.isFalse(yield Zotero.SyncedSettings.get(userLibraryID, 'tagColors'));
|
assert.isNull(Zotero.SyncedSettings.get(userLibraryID, 'tagColors'));
|
||||||
assert.isFalse(Zotero.Collections.exists(collectionID));
|
assert.isFalse(Zotero.Collections.exists(collectionID));
|
||||||
assert.isFalse(Zotero.Searches.exists(searchID));
|
assert.isFalse(Zotero.Searches.exists(searchID));
|
||||||
assert.isFalse(Zotero.Items.exists(itemID));
|
assert.isFalse(Zotero.Items.exists(itemID));
|
||||||
|
@ -901,7 +901,7 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
yield engine._startDownload();
|
yield engine._startDownload();
|
||||||
|
|
||||||
// Make sure objects weren't deleted
|
// Make sure objects weren't deleted
|
||||||
assert.ok(yield Zotero.SyncedSettings.get(userLibraryID, 'tagColors'));
|
assert.ok(Zotero.SyncedSettings.get(userLibraryID, 'tagColors'));
|
||||||
assert.ok(Zotero.Collections.exists(collectionID));
|
assert.ok(Zotero.Collections.exists(collectionID));
|
||||||
assert.ok(Zotero.Searches.exists(searchID));
|
assert.ok(Zotero.Searches.exists(searchID));
|
||||||
})
|
})
|
||||||
|
@ -1212,10 +1212,10 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
yield engine._fullSync();
|
yield engine._fullSync();
|
||||||
|
|
||||||
// Check settings
|
// Check settings
|
||||||
var setting = yield Zotero.SyncedSettings.get(userLibraryID, "tagColors");
|
var setting = Zotero.SyncedSettings.get(userLibraryID, "tagColors");
|
||||||
assert.lengthOf(setting, 1);
|
assert.lengthOf(setting, 1);
|
||||||
assert.equal(setting[0].name, 'A');
|
assert.equal(setting[0].name, 'A');
|
||||||
var settingMetadata = yield Zotero.SyncedSettings.getMetadata(userLibraryID, "tagColors");
|
var settingMetadata = Zotero.SyncedSettings.getMetadata(userLibraryID, "tagColors");
|
||||||
assert.equal(settingMetadata.version, 2);
|
assert.equal(settingMetadata.version, 2);
|
||||||
assert.isTrue(settingMetadata.synced);
|
assert.isTrue(settingMetadata.synced);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ describe("Tag Selector", function () {
|
||||||
var win, doc, collectionsView;
|
var win, doc, collectionsView;
|
||||||
|
|
||||||
var clearTagColors = Zotero.Promise.coroutine(function* (libraryID) {
|
var clearTagColors = Zotero.Promise.coroutine(function* (libraryID) {
|
||||||
var tagColors = yield Zotero.Tags.getColors(libraryID);
|
var tagColors = Zotero.Tags.getColors(libraryID);
|
||||||
for (let name of tagColors.keys()) {
|
for (let name of tagColors.keys()) {
|
||||||
yield Zotero.Tags.setColor(libraryID, name, false);
|
yield Zotero.Tags.setColor(libraryID, name, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,4 +64,38 @@ describe("Zotero.Tags", function () {
|
||||||
assert.isFalse(yield Zotero.Tags.getName(tagID));
|
assert.isFalse(yield Zotero.Tags.getName(tagID));
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
describe("#setColor()", function () {
|
||||||
|
var libraryID;
|
||||||
|
|
||||||
|
before(function* () {
|
||||||
|
libraryID = Zotero.Libraries.userLibraryID;
|
||||||
|
|
||||||
|
// Clear library tag colors
|
||||||
|
var colors = Zotero.Tags.getColors(libraryID);
|
||||||
|
for (let color of colors.keys()) {
|
||||||
|
yield Zotero.Tags.setColor(libraryID, color);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should set color for a tag", function* () {
|
||||||
|
var aColor = '#ABCDEF';
|
||||||
|
var bColor = '#BCDEF0';
|
||||||
|
yield Zotero.Tags.setColor(libraryID, "A", aColor);
|
||||||
|
yield Zotero.Tags.setColor(libraryID, "B", bColor);
|
||||||
|
|
||||||
|
var o = Zotero.Tags.getColor(libraryID, "A")
|
||||||
|
assert.equal(o.color, aColor);
|
||||||
|
assert.equal(o.position, 0);
|
||||||
|
var o = Zotero.Tags.getColor(libraryID, "B")
|
||||||
|
assert.equal(o.color, bColor);
|
||||||
|
assert.equal(o.position, 1);
|
||||||
|
|
||||||
|
var o = Zotero.SyncedSettings.get(libraryID, 'tagColors');
|
||||||
|
assert.isArray(o);
|
||||||
|
assert.lengthOf(o, 2);
|
||||||
|
assert.sameMembers(o.map(c => c.color), [aColor, bColor]);
|
||||||
|
});
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,17 +14,6 @@ describe("Item Tags Box", function () {
|
||||||
win.close();
|
win.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
function waitForTagsBox() {
|
|
||||||
var deferred = Zotero.Promise.defer();
|
|
||||||
var tagsbox = doc.getElementById('zotero-editpane-tags');
|
|
||||||
var onRefresh = function (event) {
|
|
||||||
tagsbox.removeEventListener('refresh', onRefresh);
|
|
||||||
deferred.resolve();
|
|
||||||
}
|
|
||||||
tagsbox.addEventListener('refresh', onRefresh);
|
|
||||||
return deferred.promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("#notify()", function () {
|
describe("#notify()", function () {
|
||||||
it("should update an existing tag on rename", function* () {
|
it("should update an existing tag on rename", function* () {
|
||||||
var tag = Zotero.Utilities.randomString();
|
var tag = Zotero.Utilities.randomString();
|
||||||
|
@ -43,7 +32,6 @@ describe("Item Tags Box", function () {
|
||||||
|
|
||||||
var tabbox = doc.getElementById('zotero-view-tabbox');
|
var tabbox = doc.getElementById('zotero-view-tabbox');
|
||||||
tabbox.selectedIndex = 2;
|
tabbox.selectedIndex = 2;
|
||||||
yield waitForTagsBox();
|
|
||||||
var tagsbox = doc.getElementById('zotero-editpane-tags');
|
var tagsbox = doc.getElementById('zotero-editpane-tags');
|
||||||
var rows = tagsbox.id('tagRows').getElementsByTagName('row');
|
var rows = tagsbox.id('tagRows').getElementsByTagName('row');
|
||||||
assert.equal(rows.length, 1);
|
assert.equal(rows.length, 1);
|
||||||
|
@ -77,7 +65,6 @@ describe("Item Tags Box", function () {
|
||||||
|
|
||||||
var tabbox = doc.getElementById('zotero-view-tabbox');
|
var tabbox = doc.getElementById('zotero-view-tabbox');
|
||||||
tabbox.selectedIndex = 2;
|
tabbox.selectedIndex = 2;
|
||||||
yield waitForTagsBox();
|
|
||||||
var tagsbox = doc.getElementById('zotero-editpane-tags');
|
var tagsbox = doc.getElementById('zotero-editpane-tags');
|
||||||
var rows = tagsbox.id('tagRows').getElementsByTagName('row');
|
var rows = tagsbox.id('tagRows').getElementsByTagName('row');
|
||||||
|
|
||||||
|
@ -108,7 +95,6 @@ describe("Item Tags Box", function () {
|
||||||
|
|
||||||
var tabbox = doc.getElementById('zotero-view-tabbox');
|
var tabbox = doc.getElementById('zotero-view-tabbox');
|
||||||
tabbox.selectedIndex = 2;
|
tabbox.selectedIndex = 2;
|
||||||
yield waitForTagsBox();
|
|
||||||
var tagsbox = doc.getElementById('zotero-editpane-tags');
|
var tagsbox = doc.getElementById('zotero-editpane-tags');
|
||||||
var rows = tagsbox.id('tagRows').getElementsByTagName('row');
|
var rows = tagsbox.id('tagRows').getElementsByTagName('row');
|
||||||
assert.equal(rows.length, 1);
|
assert.equal(rows.length, 1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue