If the user has too many collections to comfortably
navigate via context menu, do not render the collection hierarchy
via menus, and instead have the user select the collection
via dialog that has a full collectionTree.
Two hidden prefs determine when the dialog will appear:
- collectionsMenu.maxEntriesTotal (default 5000) - max
collections in specified libraries
- collectionsMenu.maxEntriesAtOneLevel (default 100) - max
collections on any single level (e.g max top level collections)
If there are more collections than maxEntriesTotal or one
collection has more than maxEntriesAtOneLevel children,
the dialog will be used.
It also takes care of some performance issues caused by
trying to render too many collections.
Fixes: #5693
- move collectionTree canDropCheck and canDropCheckAsync
to Zotero.Collection::canMoveToTarget and Zotero.Collection::canMoveToTargetAsync
per https://github.com/zotero/zotero/pull/4420#issuecomment-2406579899
That way, we share the logic to determine if collection row can
be dropped onto another row, as well as to disable/enable context menus.
- allow to copy a collection to another library if
there already is a linked collection but it is in trash.
Fixes: #4862
When stop() or stopOnError rejected queued task promises, the rejection
handlers (via Promise.allSettled) weren't attached yet, causing Mozilla
to report each one as "uncaught exception: Object". Add no-op catch
handlers before rejecting so the runtime knows they'll be handled
downstream. Also fix stopOnError path to reject with CanceledException
instead of undefined, and remove legacy Bluebird handledRejection flag.
Track when attachments are last opened or read, storing a `lastRead` Unix timestamp on the attachment. For user library items, `lastRead` syncs as an attachment property in item JSON. For group library items, it syncs via a per-user synced setting (like `lastPageIndex`).
- Add `lastRead` column to `itemAttachments`
- Add `AttachmentReadObserver` to update `lastRead` on file open and page change (throttled to 5 min for page changes)
- Add "Recently Read" virtual collection (items read in last 14 days, sorted by `lastRead` descending)
- Add `lastRead` search condition with date operators
- Add `lastRead` item tree column with new `dependsOnChildren` property for parent item aggregation
- Add `getItemLastRead()` to return max `lastRead` across child attachments
Also:
- Generalize collection tree SCSS to support universal (context-fill) icons alongside themed icons
---------
Co-authored-by: Dan Stillman <dstillman@zotero.org>
After editing the parent item, switching back to the attachment item before the parent item's save completes creates a race condition between the save and the attachment render.
Moved item pane tests related to file renaming to a separate describe() block.
The firstCreator/sortCreator SQL now falls back through primary →
editor → director → contributor. This ensures Video Recording items
with only a Director creator show that creator in the items list.
Also refactors the repetitive SQL-building in _getFirstCreatorSQL()
and _getSortCreatorSQL() into helper functions.
Closes#5720
The %PDF- sniffer entry had no offset constraint, so it matched anywhere
in the file sample. This could cause ZIP files containing PDFs to be
misidentified as application/pdf when opened, since %PDF- could appear
within the first 200 bytes of the archive. Pin the match to offset 0,
where it must appear in a valid PDF.
Fixes https://forums.zotero.org/discussion/130161/zip-files-and-indexing
Plus guidance-panel changes:
- Fix description not updating when multiple panels exist
in the document
- Fix nonfunctional noautohide attribute
- Show "Got It" button for noautohide with no navigation
---------
Co-authored-by: Dan Stillman <dstillman@zotero.org>
resetData() clears user data and sync state using application APIs
instead of doing a full Zotero shutdown/reinit cycle, making it much
faster for tests that just need clean state between runs.
Also make Tags.init(), Creators.init(), Users.init(), and
SyncedSettings.loadAll() properly clear their caches before reloading,
so they are safe to call more than once.
Instead of testing against the build/ directory directly, zip it up first
and then unzip it back into build/ before running tests. This ensures
tests run against the same artifact that gets uploaded to S3 and used by
the deployment scripts, catching issues that only manifest after a zip
round-trip (e.g., resolved symlinks, missing files).
Also makes Ruby setup conditional on deployment branches