diff --git a/chrome/content/zotero/components/foo.jsx b/chrome/content/zotero/components/foo.jsx
deleted file mode 100644
index 3fd41a40dc..0000000000
--- a/chrome/content/zotero/components/foo.jsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import React, { useState } from 'react';
-
-function Foo() {
- // Declare a new state variable, which we'll call "count"
- const [count, setCount] = useState(0);
- Zotero.debug("RUNNING FOO");
-
- return (
-
-
You clicked {count} times
-
-
- );
-}
-
-module.exports = Foo;
\ No newline at end of file
diff --git a/chrome/content/zotero/components/watch_components b/chrome/content/zotero/components/watch_components
deleted file mode 100755
index fb53c1467c..0000000000
--- a/chrome/content/zotero/components/watch_components
+++ /dev/null
@@ -1 +0,0 @@
-fswatch -o . | xargs -n1 -I{} sh -c 'rsync -av --delete ./ ~/react-app/tmp/; find ~/react-app/tmp -name "*.jsx" -exec perl -pi -e "print \"import Zotero from \\\"zotero\\\"\; \/\/ eslint-disable-line no-unused-vars\n\" if $. == 1" \{\} \; ; rsync -av --delete ~/react-app/tmp/ ~/react-app/src/components/;' _
diff --git a/chrome/content/zotero/test.xul b/chrome/content/zotero/test.xul
deleted file mode 100644
index 8de021adc8..0000000000
--- a/chrome/content/zotero/test.xul
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/chrome/content/zotero/test2.html b/chrome/content/zotero/test2.html
deleted file mode 100644
index d976649824..0000000000
--- a/chrome/content/zotero/test2.html
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-Hello
-
-
-
\ No newline at end of file
diff --git a/chrome/content/zotero/xpcom/data/dataObject.js2 b/chrome/content/zotero/xpcom/data/dataObject.js2
deleted file mode 100644
index f8e08143a4..0000000000
--- a/chrome/content/zotero/xpcom/data/dataObject.js2
+++ /dev/null
@@ -1,1296 +0,0 @@
-/*
- ***** BEGIN LICENSE BLOCK *****
-
- Copyright © 2013 Center for History and New Media
- George Mason University, Fairfax, Virginia, USA
- http://zotero.org
-
- This file is part of Zotero.
-
- Zotero is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zotero is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zotero. If not, see .
-
- ***** END LICENSE BLOCK *****
-*/
-
-/**
- * @property {String} (readOnly) objectType
- * @property {String} (readOnly) libraryKey
- * @property {String|false|undefined} parentKey - False if no parent, or undefined if not
- * applicable (e.g. search objects)
- * @property {Integer|false|undefined} parentID - False if no parent, or undefined if not
- * applicable (e.g. search objects)
- */
-
-Zotero.DataObject = function () {
- let objectType = this._objectType;
- this._ObjectType = objectType[0].toUpperCase() + objectType.substr(1);
- this._objectTypePlural = Zotero.DataObjectUtilities.getObjectTypePlural(objectType);
- this._ObjectTypePlural = this._objectTypePlural[0].toUpperCase() + this._objectTypePlural.substr(1);
- this._ObjectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(objectType);
-
- this._id = null;
- this._libraryID = null;
- this._key = null;
- this._dateAdded = null;
- this._dateModified = null;
- this._version = null;
- this._synced = null;
- this._identified = false;
- this._parentID = null;
- this._parentKey = null;
-
- this._relations = [];
-
- // Set in dataObjects.js
- this._inCache = false;
-
- this._loaded = {};
- this._skipDataTypeLoad = {};
- this._markAllDataTypeLoadStates(false);
-
- this._clearChanged();
-};
-
-Zotero.DataObject.prototype._objectType = 'dataObject';
-Zotero.DataObject.prototype._dataTypes = ['primaryData'];
-
-Zotero.defineProperty(Zotero.DataObject.prototype, 'objectType', {
- get: function() { return this._objectType; }
-});
-Zotero.defineProperty(Zotero.DataObject.prototype, 'id', {
- get: function() { return this._id; }
-});
-Zotero.defineProperty(Zotero.DataObject.prototype, 'libraryID', {
- get: function() { return this._libraryID; }
-});
-Zotero.defineProperty(Zotero.DataObject.prototype, 'library', {
- get: function () {
- return Zotero.Libraries.get(this._libraryID);
- }
-});
-Zotero.defineProperty(Zotero.DataObject.prototype, 'key', {
- get: function() { return this._key; }
-});
-Zotero.defineProperty(Zotero.DataObject.prototype, 'libraryKey', {
- get: function() { return this._libraryID + "/" + this._key; }
-});
-Zotero.defineProperty(Zotero.DataObject.prototype, 'parentKey', {
- get: function () { return this._getParentKey(); },
- set: function(v) { return this._setParentKey(v); }
-});
-Zotero.defineProperty(Zotero.DataObject.prototype, 'parentID', {
- get: function() { return this._getParentID(); },
- set: function(v) { return this._setParentID(v); }
-});
-
-Zotero.defineProperty(Zotero.DataObject.prototype, '_canHaveParent', {
- value: true
-});
-
-Zotero.defineProperty(Zotero.DataObject.prototype, 'ObjectsClass', {
- get: function() { return this._ObjectsClass; }
-});
-
-
-Zotero.DataObject.prototype._get = function (field) {
- if (field != 'id') this._disabledCheck();
-
- if (this['_' + field] !== null) {
- return this['_' + field];
- }
- if (field != 'libraryID' && field != 'key' && field != 'id') {
- this._requireData('primaryData');
- }
- return null;
-}
-
-
-Zotero.DataObject.prototype._set = function (field, value) {
- this._disabledCheck();
-
- if (field == 'id' || field == 'libraryID' || field == 'key') {
- return this._setIdentifier(field, value);
- }
-
- this._requireData('primaryData');
-
- switch (field) {
- case 'name':
- value = value.trim().normalize();
- break;
-
- case 'version':
- value = parseInt(value);
- break;
-
- case 'synced':
- value = !!value;
- break;
- }
-
- if (this['_' + field] != value || field == 'synced') {
- this._markFieldChange(field, this['_' + field], value);
- }
-}
-
-
-Zotero.DataObject.prototype._setIdentifier = function (field, value) {
- switch (field) {
- case 'id':
- value = Zotero.DataObjectUtilities.checkDataID(value);
- if (this._id) {
- if (value === this._id) {
- return;
- }
- throw new Error("ID cannot be changed");
- }
- if (this._key) {
- throw new Error("Cannot set id if key is already set");
- }
- break;
-
- case 'libraryID':
- value = Zotero.DataObjectUtilities.checkLibraryID(value);
- break;
-
- case 'key':
- if (this._libraryID === null) {
- throw new Error("libraryID must be set before key");
- }
- value = Zotero.DataObjectUtilities.checkKey(value);
- if (this._key) {
- if (value === this._key) {
- return;
- }
- throw new Error("Key cannot be changed");
- }
- if (this._id) {
- throw new Error("Cannot set key if id is already set");
- }
- }
-
- if (value === this['_' + field]) {
- return;
- }
-
- // If primary data is loaded, the only allowed identifier change is libraryID, and then only
- // for unidentified objects, and then only either if a libraryID isn't yet set (because
- // primary data gets marked as loaded when fields are set for new items, but some methods
- // (setCollections(), save()) automatically set the user library ID after that if none is
- // specified), or for searches (for the sake of the library switcher in the advanced search
- // window, though that could probably be rewritten)
- if (this._loaded.primaryData) {
- if (!(!this._identified && field == 'libraryID'
- && (!this._libraryID || this._objectType == 'search'))) {
- throw new Error("Cannot change " + field + " after object is already loaded");
- }
- }
-
- if (field == 'id' || field == 'key') {
- this._identified = true;
- }
-
- this['_' + field] = value;
-}
-
-
-/**
- * Get the id of the parent object
- *
- * @return {Integer|false|undefined} The id of the parent object, false if none, or undefined
- * on object types to which it doesn't apply (e.g., searches)
- */
-Zotero.DataObject.prototype._getParentID = function () {
- if (this._parentID !== null) {
- return this._parentID;
- }
- if (!this._parentKey) {
- if (this._objectType == 'search') {
- return undefined;
- }
- return false;
- }
- return this._parentID = this.ObjectsClass.getIDFromLibraryAndKey(this._libraryID, this._parentKey);
-}
-
-
-/**
- * Set the id of the parent object
- *
- * @param {Number|false} [id=false]
- * @return {Boolean} True if changed, false if stayed the same
- */
-Zotero.DataObject.prototype._setParentID = function (id) {
- return this._setParentKey(
- id
- ? this.ObjectsClass.getLibraryAndKeyFromID(Zotero.DataObjectUtilities.checkDataID(id)).key
- : false
- );
-}
-
-
-Zotero.DataObject.prototype._getParentKey = function () {
- if (!this._canHaveParent) {
- return undefined;
- }
- return this._parentKey ? this._parentKey : false
-}
-
-/**
- * Set the key of the parent object
- *
- * @param {String|false} [key=false]
- * @return {Boolean} True if changed, false if stayed the same
- */
-Zotero.DataObject.prototype._setParentKey = function(key) {
- if (!this._canHaveParent) {
- throw new Error("Cannot set parent key for " + this._objectType);
- }
-
- key = Zotero.DataObjectUtilities.checkKey(key) || false;
-
- if (key === this._parentKey || (!this._parentKey && !key)) {
- return false;
- }
- this._markFieldChange('parentKey', this._parentKey, key);
- //this._parentKey = key;
- //this._parentID = null;
- return true;
-}
-
-//
-// Relations
-//
-/**
- * Returns all relations of the object
- *
- * @return {Object} - Object with predicates as keys and arrays of values
- */
-Zotero.DataObject.prototype.getRelations = function () {
- this._requireData('relations');
-
- var relations = {};
- for (let i=0; i rel[0] != predicate || rel[1] != object);
-
- if (oldSize != newRelations.length) {
- Zotero.debug("Relation " + predicate + " - " + object + " did not exist for "
- + this._objectType + " " + this.libraryKey);
- return;
- }
-
- Zotero.debug("Removing relation " + predicate + " - " + object + " from "
- + this._objectType + " " + this.libraryKey);
- this._markFieldChange('relations', this._relations, newRelations);
- //this._relations.splice(i, 1);
-}
-
-
-/**
- * Updates the object's relations
- *
- * @param {Object} newRelations Object with predicates as keys and URI[] as values
- * @return {Boolean} True if changed, false if stayed the same
- */
-Zotero.DataObject.prototype.setRelations = function (newRelations) {
- this._requireData('relations');
-
- if (typeof newRelations != 'object') {
- throw new Error(`Relations must be an object (${typeof newRelations} given)`);
- }
-
- var oldRelations = this._relations;
-
- // Limit predicates to letters and colons for now
- for (let p in newRelations) {
- if (!/^[a-z]+:[a-z]+$/i.test(p)) {
- throw new Error(`Invalid relation predicate '${p}'`);
- }
- }
-
- // Relations are stored internally as a flat array with individual predicate-object pairs,
- // so convert the incoming relations to that
- var newRelationsFlat = this.ObjectsClass.flattenRelations(newRelations);
-
- var changed = false;
- if (oldRelations.length != newRelationsFlat.length) {
- changed = true;
- }
- else {
- let sortFunc = function (a, b) {
- if (a[0] < b[0]) return -1;
- if (a[0] > b[0]) return 1;
- if (a[1] < b[1]) return -1;
- if (a[1] > b[1]) return 1;
- return 0;
- };
- oldRelations.sort(sortFunc);
- newRelationsFlat.sort(sortFunc);
-
- for (let i=0; i} Linked object, or false if not found
- */
-Zotero.DataObject.prototype._getLinkedObject = Zotero.Promise.coroutine(function* (libraryID, bidirectional) {
- if (!libraryID) {
- throw new Error("libraryID not provided");
- }
-
- if (libraryID == this._libraryID) {
- throw new Error(this._ObjectType + " is already in library " + libraryID);
- }
-
- var predicate = Zotero.Relations.linkedObjectPredicate;
- var libraryObjectPrefix = Zotero.URI.getLibraryURI(libraryID)
- + "/" + this._objectTypePlural + "/";
-
- // Try the relations with this as a subject
- var uris = this.getRelationsByPredicate(predicate);
- for (let i = 0; i < uris.length; i++) {
- let uri = uris[i];
- if (uri.startsWith(libraryObjectPrefix)) {
- let obj = yield Zotero.URI['getURI' + this._ObjectType](uri);
- if (!obj) {
- Zotero.debug("Referenced linked " + this._objectType + " '" + uri + "' not found "
- + "in Zotero." + this._ObjectType + "::getLinked" + this._ObjectType + "()", 2);
- continue;
- }
- return obj;
- }
- }
-
- // Then try relations with this as an object
- if (bidirectional) {
- var thisURI = Zotero.URI['get' + this._ObjectType + 'URI'](this);
- var objects = Zotero.Relations.getByPredicateAndObject(
- this._objectType, predicate, thisURI
- );
- for (let i = 0; i < objects.length; i++) {
- let obj = objects[i];
- if (obj.objectType != this._objectType) {
- Zotero.logError("Found linked object of different type "
- + "(expected " + this._objectType + ", found " + obj.objectType + ")");
- continue;
- }
- if (obj.libraryID == libraryID) {
- return obj;
- }
- }
- }
-
- return false;
-});
-
-
-/**
- * Add a linked-item relation to a pair of objects
- *
- * A separate save() is not required.
- *
- * @param {Zotero.DataObject} object
- * @param {Promise}
- */
-Zotero.DataObject.prototype._addLinkedObject = Zotero.Promise.coroutine(function* (object) {
- if (object.libraryID == this._libraryID) {
- throw new Error("Can't add linked " + this._objectType + " in same library");
- }
-
- var predicate = Zotero.Relations.linkedObjectPredicate;
- var thisURI = Zotero.URI['get' + this._ObjectType + 'URI'](this);
- var objectURI = Zotero.URI['get' + this._ObjectType + 'URI'](object);
-
- var exists = this.hasRelation(predicate, objectURI);
- if (exists) {
- Zotero.debug(this._ObjectTypePlural + " " + this.libraryKey
- + " and " + object.libraryKey + " are already linked");
- return false;
- }
-
- // If one of the items is a personal library, store relation with that. Otherwise, use
- // current item's library (which in calling code is the new, copied item, since that's what
- // the user definitely has access to).
- var userLibraryID = Zotero.Libraries.userLibraryID;
- if (this.libraryID == userLibraryID || object.libraryID != userLibraryID) {
- this.addRelation(predicate, objectURI);
- yield this.save({
- skipDateModifiedUpdate: true,
- skipSelect: true
- });
- }
- else {
- object.addRelation(predicate, thisURI);
- yield object.save({
- skipDateModifiedUpdate: true,
- skipSelect: true
- });
- }
-
- return true;
-});
-
-
-//
-// Bulk data loading functions
-//
-// These are called by Zotero.DataObjects.prototype.loadDataType().
-//
-Zotero.DataObject.prototype.loadPrimaryData = Zotero.Promise.coroutine(function* (reload, failOnMissing) {
- if (this._loaded.primaryData && !reload) return;
-
- var id = this._id;
- var key = this._key;
- var libraryID = this._libraryID;
-
- if (!id && !key) {
- throw new Error('ID or key not set in Zotero.' + this._ObjectType + '.loadPrimaryData()');
- }
-
- var columns = [], join = [], where = [];
- var primaryFields = this.ObjectsClass.primaryFields;
- var idField = this.ObjectsClass.idColumn;
- for (let i=0; i this._loaded[type]);
- }
-
- if (dataTypes && dataTypes.length) {
- for (let i=0; i} Promise for itemID of new item,
- * TRUE on item update, or FALSE if item was unchanged
- */
-Zotero.DataObject.prototype.save = Zotero.Promise.coroutine(function* (options = {}) {
- var env = {
- options: Object.assign({}, options),
- transactionOptions: {}
- };
-
- if (!env.options.tx && !Zotero.DB.inTransaction()) {
- Zotero.logError("save() called on Zotero." + this._ObjectType + " without a wrapping "
- + "transaction -- use saveTx() instead");
- Zotero.debug((new Error).stack, 2);
- env.options.tx = true;
- }
-
- if (env.options.skipAll) {
- [
- 'skipDateModifiedUpdate',
- 'skipClientDateModifiedUpdate',
- 'skipSyncedUpdate',
- 'skipEditCheck',
- 'skipNotifier',
- 'skipSelect'
- ].forEach(x => env.options[x] = true);
- }
-
- var proceed = yield this._initSave(env);
- if (!proceed) return false;
-
- if (env.isNew) {
- Zotero.debug('Saving data for new ' + this._objectType + ' to database', 4);
- }
- else {
- Zotero.debug('Updating database with new ' + this._objectType + ' data', 4);
- }
-
- try {
- if (Zotero.DataObject.prototype._finalizeSave == this._finalizeSave) {
- throw new Error("_finalizeSave not implemented for Zotero." + this._ObjectType);
- }
-
- env.notifierData = {};
- // Pass along any 'notifierData' values
- if (env.options.notifierData) {
- Object.assign(env.notifierData, env.options.notifierData);
- }
- if (env.options.skipSelect) {
- env.notifierData.skipSelect = true;
- }
- if (!env.isNew) {
- env.changed = {};
- this._previousData.forEach((value, key) => {
- env.changed[key, value];
- });
- }
-
- // Create transaction
- let result
- if (env.options.tx) {
- result = yield Zotero.DB.executeTransaction(function* () {
- Zotero.DataObject.prototype._saveData.call(this, env);
- yield this._saveData(env);
- yield Zotero.DataObject.prototype._finalizeSave.call(this, env);
- return this._finalizeSave(env);
- }.bind(this), env.transactionOptions);
- }
- // Use existing transaction
- else {
- Zotero.DB.requireTransaction();
- Zotero.DataObject.prototype._saveData.call(this, env);
- yield this._saveData(env);
- yield Zotero.DataObject.prototype._finalizeSave.call(this, env);
- result = this._finalizeSave(env);
- }
- this._postSave(env);
- return result;
- }
- catch(e) {
- return this._recoverFromSaveError(env, e)
- .catch(function(e2) {
- Zotero.debug(e2, 1);
- })
- .then(function() {
- if (env.options.errorHandler) {
- env.options.errorHandler(e);
- }
- else {
- Zotero.logError(e);
- }
- throw e;
- })
- }
-});
-
-
-Zotero.DataObject.prototype.saveTx = function (options = {}) {
- options = Object.assign({}, options);
- options.tx = true;
- return this.save(options);
-}
-
-
-Zotero.DataObject.prototype._initSave = Zotero.Promise.coroutine(function* (env) {
- // Default to user library if not specified
- if (this.libraryID === null) {
- this._libraryID = Zotero.Libraries.userLibraryID;
- }
-
- env.isNew = !this.id;
-
- if (!env.options.skipEditCheck) {
- this.editCheck();
- }
-
- let targetLib = Zotero.Libraries.get(this.libraryID);
- if (!targetLib.isChildObjectAllowed(this._objectType)) {
- throw new Error("Cannot add " + this._objectType + " to a " + targetLib.libraryType + " library");
- }
-
- if (!this.hasChanged()) {
- Zotero.debug(this._ObjectType + ' ' + this.id + ' has not changed', 4);
- return false;
- }
-
- // Undo registerObject() on failure
- if (env.isNew) {
- var func = function () {
- this.ObjectsClass.unload(this._id);
- }.bind(this);
- if (env.options.tx) {
- env.transactionOptions.onRollback = func;
- }
- else {
- Zotero.DB.addCurrentCallback("rollback", func);
- }
- }
-
- env.relationsToRegister = [];
- env.relationsToUnregister = [];
-
- return true;
-});
-
-Zotero.DataObject.prototype._saveData = function (env) {
- var libraryID = env.libraryID = this.libraryID || Zotero.Libraries.userLibraryID;
- var key = env.key = this._key = this.key ? this.key : this._generateKey();
-
- env.sqlColumns = [];
- env.sqlValues = [];
-
- if (env.isNew) {
- env.sqlColumns.push(
- 'libraryID',
- 'key'
- );
- env.sqlValues.push(
- libraryID,
- key
- );
- }
-
- if (this._changed.get('version')) {
- env.sqlColumns.push('version');
- env.sqlValues.push(this._changed.get('version') || 0);
- }
-
- if (this._changed.get('synced')) {
- env.sqlColumns.push('synced');
- env.sqlValues.push(this._changed.get('synced') ? 1 : 0);
- }
- // Set synced to 0 by default
- else if (!env.isNew && !env.options.skipSyncedUpdate) {
- env.sqlColumns.push('synced');
- env.sqlValues.push(0);
- }
-
- if (env.isNew || !env.options.skipClientDateModifiedUpdate) {
- env.sqlColumns.push('clientDateModified');
- env.sqlValues.push(Zotero.DB.transactionDateTime);
- }
-};
-
-Zotero.DataObject.prototype._finalizeSave = Zotero.Promise.coroutine(function* (env) {
- for (let [field, val] of this._changed.entries()) {
- Zotero.debug("CHANGED " + field + " is " + val);
- this['_' + field] = val;
- }
- this._changed.clear();
-
- // Relations
- var newRelations = this._changed.get('relations');
- if (newRelations) {
- let oldRelations = this._relations;
- let toAdd, toRemove;
- // Convert to individual JSON objects, diff, and convert back
- if (this._relations) {
- let oldRelationsJSON = oldRelations.map(x => JSON.stringify(x));
- let newRelationsJSON = newRelations.map(x => JSON.stringify(x));
- toAdd = Zotero.Utilities.arrayDiff(newRelationsJSON, oldRelationsJSON)
- .map(x => JSON.parse(x));
- toRemove = Zotero.Utilities.arrayDiff(oldRelationsJSON, newRelationsJSON)
- .map(x => JSON.parse(x));
- }
- else {
- toAdd = newRelations;
- toRemove = [];
- }
-
- if (toAdd.length) {
- let sql = "INSERT INTO " + this._objectType + "Relations "
- + "(" + this._ObjectsClass.idColumn + ", predicateID, object) VALUES ";
- // Convert predicates to ids
- for (let i = 0; i < toAdd.length; i++) {
- toAdd[i][0] = yield Zotero.RelationPredicates.add(toAdd[i][0]);
- env.relationsToRegister.push([toAdd[i][0], toAdd[i][1]]);
- }
- yield Zotero.DB.queryAsync(
- sql + toAdd.map(x => "(?, ?, ?)").join(", "),
- toAdd.map(x => [this.id, x[0], x[1]])
- .reduce((x, y) => x.concat(y))
- );
- }
-
- if (toRemove.length) {
- for (let i = 0; i < toRemove.length; i++) {
- let sql = "DELETE FROM " + this._objectType + "Relations "
- + "WHERE " + this._ObjectsClass.idColumn + "=? AND predicateID=? AND object=?";
- yield Zotero.DB.queryAsync(
- sql,
- [
- this.id,
- (yield Zotero.RelationPredicates.add(toRemove[i][0])),
- toRemove[i][1]
- ]
- );
- env.relationsToUnregister.push([toRemove[i][0], toRemove[i][1]]);
- }
- }
- }
-
- if (env.isNew) {
- if (!env.skipCache) {
- // Register this object's identifiers in Zotero.DataObjects. This has to happen here so
- // that the object exists for the reload() in objects' finalizeSave methods.
- this.ObjectsClass.registerObject(this);
- }
- // If object isn't being reloaded, disable it, since its data may be out of date
- else {
- this._disabled = true;
- }
- }
- else if (env.skipCache) {
- Zotero.logError("skipCache is only for new objects");
- }
-});
-
-
-/**
- * Actions to perform after DB transaction
- */
-Zotero.DataObject.prototype._postSave = function (env) {
- for (let [field, value] of this._changed.entries()) {
- this[field] = value;
- }
- this._changed.clear();
-
- for (let i = 0; i < env.relationsToRegister.length; i++) {
- let rel = env.relationsToRegister[i];
- Zotero.debug(rel);
- Zotero.Relations.register(this._objectType, this.id, rel[0], rel[1]);
- }
- for (let i = 0; i < env.relationsToUnregister.length; i++) {
- let rel = env.relationsToUnregister[i];
- Zotero.Relations.unregister(this._objectType, this.id, rel[0], rel[1]);
- }
-};
-
-
-Zotero.DataObject.prototype._recoverFromSaveError = Zotero.Promise.coroutine(function* (env) {
- yield this.reload(null, true);
- this._clearChanged();
-});
-
-
-/**
- * Update object version, efficiently
- *
- * Used by sync code
- *
- * @param {Integer} version
- * @param {Boolean} [skipDB=false]
- */
-Zotero.DataObject.prototype.updateVersion = Zotero.Promise.coroutine(function* (version, skipDB) {
- if (!this.id) {
- throw new Error("Cannot update version of unsaved " + this._objectType);
- }
- if (version != parseInt(version)) {
- throw new Error("'version' must be an integer");
- }
-
- this._version = parseInt(version);
-
- if (!skipDB) {
- var cl = this.ObjectsClass;
- var sql = "UPDATE " + cl.table + " SET version=? WHERE " + cl.idColumn + "=?";
- yield Zotero.DB.queryAsync(sql, [parseInt(version), this.id]);
- }
-
- if (this._changed.get('version')) {
- this._changed.delete('version');
- }
-});
-
-/**
- * Update object sync status, efficiently
- *
- * Used by sync code
- *
- * @param {Boolean} synced
- * @param {Boolean} [skipDB=false]
- */
-Zotero.DataObject.prototype.updateSynced = Zotero.Promise.coroutine(function* (synced, skipDB) {
- if (!this.id) {
- throw new Error("Cannot update sync status of unsaved " + this._objectType);
- }
- if (typeof synced != 'boolean') {
- throw new Error("'synced' must be a boolean");
- }
-
- this._synced = synced;
-
- if (!skipDB) {
- var cl = this.ObjectsClass;
- var sql = "UPDATE " + cl.table + " SET synced=? WHERE " + cl.idColumn + "=?";
- yield Zotero.DB.queryAsync(sql, [synced ? 1 : 0, this.id]);
- }
-
- if (this._changed.get('synced')) {
- this._changed.delete('synced');
- }
-});
-
-/**
- * Delete object from database
- *
- * @param {Object} [options]
- * @param {Boolean} [options.deleteItems] - Move descendant items to trash (Collection only)
- * @param {Boolean} [options.skipDeleteLog] - Don't add to sync delete log
- */
-Zotero.DataObject.prototype.erase = Zotero.Promise.coroutine(function* (options = {}) {
- if (!options || typeof options != 'object') {
- throw new Error("'options' must be an object (" + typeof options + ")");
- }
-
- var env = {
- options: Object.assign({}, options)
- };
-
- if (!env.options.tx && !Zotero.DB.inTransaction()) {
- Zotero.logError("erase() called on Zotero." + this._ObjectType + " without a wrapping "
- + "transaction -- use eraseTx() instead");
- Zotero.debug((new Error).stack, 2);
- env.options.tx = true;
- }
-
- let proceed = yield this._initErase(env);
- if (!proceed) return false;
-
- Zotero.debug('Deleting ' + this.objectType + ' ' + this.id);
-
- if (env.options.tx) {
- return Zotero.DB.executeTransaction(function* () {
- yield this._eraseData(env);
- yield this._finalizeErase(env);
- }.bind(this))
- }
- else {
- Zotero.DB.requireTransaction();
- yield this._eraseData(env);
- yield this._finalizeErase(env);
- }
-});
-
-Zotero.DataObject.prototype.eraseTx = function (options) {
- options = options || {};
- options.tx = true;
- return this.erase(options);
-};
-
-Zotero.DataObject.prototype._initErase = Zotero.Promise.method(function (env) {
- env.notifierData = {};
- env.notifierData[this.id] = {
- libraryID: this.libraryID,
- key: this.key
- };
-
- if (!env.options.skipEditCheck) this.editCheck();
-
- if (env.options.skipDeleteLog) {
- env.notifierData[this.id].skipDeleteLog = true;
- }
-
- return true;
-});
-
-Zotero.DataObject.prototype._finalizeErase = Zotero.Promise.coroutine(function* (env) {
- // Delete versions from sync cache
- if (this._objectType != 'feedItem') {
- yield Zotero.Sync.Data.Local.deleteCacheObjectVersions(
- this.objectType, this._libraryID, this._key
- );
- }
-
- Zotero.DB.addCurrentCallback("commit", function () {
- this.ObjectsClass.unload(env.deletedObjectIDs || this.id);
- }.bind(this));
-
- if (!env.options.skipNotifier) {
- Zotero.Notifier.queue(
- 'delete',
- this._objectType,
- Object.keys(env.notifierData).map(id => parseInt(id)),
- env.notifierData,
- env.options.notifierQueue
- );
- }
-});
-
-
-Zotero.DataObject.prototype.toResponseJSON = function (options = {}) {
- // TODO: library block?
-
- var json = {
- key: this.key,
- version: this.version,
- meta: {},
- data: this.toJSON(options)
- };
- if (options.version) {
- json.version = json.data.version = options.version;
- }
- return json;
-}
-
-
-Zotero.DataObject.prototype._preToJSON = function (options) {
- var env = { options };
- env.mode = options.mode || 'new';
- if (env.mode == 'patch') {
- if (!options.patchBase) {
- throw new Error("Cannot use patch mode if patchBase not provided");
- }
- }
- else if (options.patchBase) {
- if (options.mode) {
- Zotero.debug("Zotero.Item.toJSON: ignoring provided patchBase in " + env.mode + " mode", 2);
- }
- // If patchBase provided and no explicit mode, use 'patch'
- else {
- env.mode = 'patch';
- }
- }
- return env;
-}
-
-Zotero.DataObject.prototype._postToJSON = function (env) {
- if (env.mode == 'patch') {
- env.obj = Zotero.DataObjectUtilities.patch(env.options.patchBase, env.obj);
- }
- if (env.options.includeVersion === false) {
- delete env.obj.version;
- }
- return env.obj;
-}
-
-
-/**
- * Generates data object key
- * @return {String} key
- */
-Zotero.DataObject.prototype._generateKey = function () {
- return Zotero.Utilities.generateObjectKey();
-}
-
-Zotero.DataObject.prototype._disabledCheck = function () {
- if (this._disabled) {
- Zotero.logError(this._ObjectType + " is disabled -- "
- + "use Zotero." + this._ObjectTypePlural + ".getAsync()");
- }
-}
diff --git a/chrome/content/zotero/xpcom/undo.js b/chrome/content/zotero/xpcom/undo.js
deleted file mode 100644
index 4fee760f0a..0000000000
--- a/chrome/content/zotero/xpcom/undo.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- ***** BEGIN LICENSE BLOCK *****
-
- Copyright © 2019 Corporation for Digital Scholarship
- Vienna, Virginia, USA
- https://www.zotero.org
-
- This file is part of Zotero.
-
- Zotero is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zotero is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zotero. If not, see .
-
- ***** END LICENSE BLOCK *****
-*/
-
-Zotero.UndoStack = function (maxUndo) {
- this.maxUndo = maxUndo || 20;
- this._stack = [];
-}
-
-Zotero.UndoStack.prototype = {
- _index: 0,
-
- addBatch: function (name, steps) {
- // Remove forward from the current index and from the beginning to stay below the max size
- var start = Math.max((this._index + 1) - this.maxUndo, 0);
- this._stack = this._stack.slice(start, this._index);
-
- this._stack.push({ name, steps });
- this._index = this._stack.length;
-
- this._update();
- },
-
- undo: async function () {
- var steps = this._stack[--this._index].steps;
- for (let step of steps) {
- await step.undo();
- }
- this._update();
- },
-
- redo: async function () {
- var batch = this._stack[this._index++].steps;
- for (let step of steps) {
- await step.redo();
- }
- this._update();
- },
-
- clear: function () {
- this._stack = [];
- this._index = 0;
- this._update();
- },
-
- _update: function () {
- var win = Zotero.getTopWindow();
- if (!win) {
- return;
- }
- var doc = win.document;
- var undoMenuItem = doc.getElementById('menu_undo');
- var redoMenuItem = doc.getElementById('menu_redo');
- var undoCmd = doc.getElementById('cmd_undo');
- var redoCmd = doc.getElementById('cmd_redo');
- var undoStep = this._stack[this._index - 1];
- var redoStep = this._stack[this._index];
-
- if (undo) {
- undoMenuItem.label = undoStep ? Zotero.getString('general.undoX', undoStep.name) : null;
- undoCmd.removeAttribute('disabled');
- }
- else {
- undoMenuItem.label = Zotero.getString('general.undo');
- undoCmd.setAttribute('disabled', 'disabled');
- }
-
- if (redoStep) {
- redoMenuItem.label = redo ? Zotero.getString('general.redoX', redoStep.name) : null;
- redoCmd.removeAttribute('disabled');
- }
- else {
- redoMenuItem.label = Zotero.getString('general.redo');
- redoCmd.setAttribute('disabled', 'disabled');
- }
- }
-};
\ No newline at end of file
diff --git a/chrome/skin/default/zotero/extensionsOverlay.css b/chrome/skin/default/zotero/extensionsOverlay.css
deleted file mode 100644
index e7b77ebf28..0000000000
--- a/chrome/skin/default/zotero/extensionsOverlay.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.addon-view .legacy-warning {
- display: none;
-}
\ No newline at end of file