Previously only individual objects from successful requests that
couldn't be processed for some reason would be added to the queue.
`Sync.APIClient.downloadObjects()` now returns clearer and more
consistent results. It now returns an array of promises for objects with
a `keys` array of requested keys and either a `json` array of returned
API JSON objects or an `error` Error, depending on whether the request
succeeded or failed. This makes it easier to detect remotely missing
objects and request failures.
This adds a very basic reimplementation of the annotation widget for use
in the CR window. It's not pixel-perfect, but it's close enough that
most people probably won't notice. We'll want to replace this with a
real version that's shared between the PDF reader and the rest of the
codebase.
Image annotations currently show an "[image not shown]" placeholder.
Showing images is tricky: we don't have the remote cache image, so if
the remote position has changed, we could only show an image by
rendering it from the file, and only if the file itself hasn't changed.
Just for a better user experience, we could use the local image as long
as the position and file are both the same, but that would take some
rejiggering of the CR window.
Tags aren't shown because they're not shown for CR at all, though that
could be changed in the future.
Added Zotero.DataObjects.sortByParent() to sort child items immediately
after their parent items. Zotero.DataObjects.sortByLevel(), which is
used for collections, sorts each level together, but that's less
appropriate for items where, e.g., an embedded-image attachment should
immediately follow the note that depends on it.
E.g., if a local item has been modified in a way that conflicts with a
remote item that also has a new, unknown field, don't show the CR
window -- just add the item to the sync queue and show the
some-data-could-not-be-downloaded error.
Previously, if an object was uploaded but the API returned 'unchanged',
the uploaded data would be written to the sync cache, which, given that
most requests are patch requests, could result in an empty or mostly
empty object being saved to the sync cache. That would cause the next
sync to treat most/all local fields as changed and either upload them
unnecessarily or trigger a conflict instead of merging changes
automatically.
Say "Use the [local|remote] version for all remaining conflicts" for
everything instead of saying "Use [local|remote] fields for all
remaining conflicts" for some conflicts.
This also fixes a test failure after 54343c49fb.
This changes the way item types, item fields, creator types, and CSL
mappings are defined and handled, in preparation for updated types and
fields.
Instead of being predefined in SQL files or code, type/field info is
read from a bundled JSON file shared with other parts of the Zotero
ecosystem [1], referred to as the "global schema". Updates to the
bundled schema file are automatically applied to the database at first
run, allowing changes to be made consistently across apps.
When syncing, invalid JSON properties are now rejected instead of being
ignored and processed later, which will allow for schema changes to be
made without causing problems in existing clients. We considered many
alternative approaches, but this approach is by far the simplest,
safest, and most transparent to the user.
For now, there are no actual changes to types and fields, since we'll
first need to do a sync cut-off for earlier versions that don't reject
invalid properties.
For third-party code, the main change is that type and field IDs should
no longer be hard-coded, since they may not be consistent in new
installs. For example, code should use `Zotero.ItemTypes.getID('note')`
instead of hard-coding `1`.
[1] https://github.com/zotero/zotero-schema
Check file-editing access for the group from the API before offering to
reset, update the filesEditable setting properly, and restart the sync
automatically after resetting.
Restores the "Restore to Zotero Server" functionality, now using the
API:
1. Get all remote keys and send `DELETE` for any that don't exist
locally.
2. Upload all local objects in full (non-patch) mode using only library
version so that the remotes are overwritten.
3. Reset file sync history, causing all files to be uploaded (or, more
likely, reassociated with existing remote files).
Since these are treated as regular updates on the server, they'll sync
down to other clients normally. Unsynced changes by other clients might
still trigger conflicts.
This and Reset File Sync History can also now be run on group libraries,
with a library selector in the Reset pane (which I forgot to do with
React).
The full sync option is now removed from the Reset pane, since there
wasn't ever really a reason to run it manually.
We should be able to reimplement Restore from Online Library (#1386)
using the inverse of this approach.
Closes#914
While objects in the sync queue that fail to save should remain in the
queue, objects that just don't exist remotely need to be removed, or
else they'll be retried forever.
If an object exists locally but not remotely and the local version has a
version number, that's an error. I don't think that should ever happen,
but it can if things somehow get out of sync due to other bugs.
To address, reprocess the API delete log during a full sync and then
reset the version number of all remaining local objects that don't exist
remotely (not just unmodified objects, as was the case previously) to 0
for uploading.
When remote deletions are reprocessed, delete local objects that haven't
been modified and show the conflict resolution window for any local
items that have.
Also:
- Clean up checking of last remote library version during download
syncs
- Add Zotero.DataObjects.getAllKeys()
If the item was deleted on one side and moved to the trash on the other,
just delete the item on the trash side. Since trash emptying happens
automatically, this would otherwise result in a conflict even if the
user carefully avoided making changes before a manual sync.
If the API returns a modified item after an upload (e.g., to strip invalid
characters), don't update the Date Modified field when saving those changes to
the local version (though it would still be good to avoid API-side changes as
much as possible).
And omit in ZFS file sync requests
The API previously didn't allow these properties to be set for group items,
because they were set atomically during the file upload process, but 1) that's
not really necessary (makes a little sense for 'filename', but not really a big
deal if an old file is renamed on another computer before the new file is
synced down) and 2) skipping them results in the properties getting erased
after items are uploaded and the empty values returned by the server overwrite
the local values.