When the items list contains items from more than one library, group them by
library -- in collections-list order, independent of the active sort -- with a
section heading above each library's items. The first heading sits flush at the
top; each later one has a gap above it and a hairline below separating it from
its items.
Grouping is triggered automatically by an items list spanning more than
one library, not the kind of selection behind it, so any future source
of multi-library items would be separated the same way. Today the
cross-library collection selection is the only such source.
Allow selecting multiple collections, saved searches, or library roots in the
collection tree -- within a library or across libraries -- and show the union
of their items. The selection is threaded through the pane as an array
(getCollectionTreeRows(), changeCollectionTreeRows(), etc.); the item pane, tag
selector, reports, and export operate on all selected rows.
Adding items (new items and notes, drag-and-drop, the attachment dialog,
import, Add by Identifier) targets every selected collection. Only rows that can
share an items view may be combined: collections, saved searches, and library
roots mix freely, and multiple Recently Read rows can be combined across
libraries, but other special views (Trash, Duplicates, etc.) and rows from
different visibility groups can't be shown together, so a selection mixing them
keeps only the focused row. In-window advanced search runs across all selected
collections.
Advanced search value autocomplete is now scoped to the searched library, fixing
a long-standing TODO where suggestions were drawn from all libraries regardless
of the search scope; for a cross-library selection it spans the selected
libraries.
For a cross-library selection, the tag selector shows the union of tags
(colored tags only when a single library is in scope, since colors are
per-library), and deleting a tag spans all selected libraries while
rename/color/split are disabled. If advanced search is open, the
collection and saved-search conditions are omitted, since each is scoped
to a single library.
- Include the Advanced Search button in the quick-search tab sequence
- Tab: quick-search textbox -> Advanced Search button -> item tree
- Shift-Tab: Advanced Search button -> quick-search textbox
- Shift-Tab: item tree -> Advanced Search button (when the deck is
closed)
- Shift-Tab: Advanced Search collapse button -> New Item button
- Fix Shift-Tab from the item tree doing nothing when the Advanced
Search deck is open; now moves focus to the deck's last focusable
element
- add tooltiptext to expand/collapse and close btns
PubMed saves can include a PMCID even when DOI-based full-text lookup
fails to produce a PDF. In that case the connector asks the desktop
attachment resolver flow for fallback sources, but getFileResolvers()
only considered DOI and URL data, so Zotero never tried the matching
PMC article URL.
Treat PMCID as a valid signal for file lookup eligibility and add a
PubMed Central OA resolver before DOI-based OA lookup. Cover the new
fallback path in attachment resolver tests and the connector
hasAttachmentResolvers endpoint.
1. 862573eab added references to fileRenaming.ftl strings but didn't
add a <link> to it, so document.l10n.formatMessages() returned
nothing. It fell back to Zotero.getString(), which threw an error
due to a missing string in en-US. We didn't catch that, so the entire
search process aborted every time.
2. message.attributes is an optional array of { name, value } objects,
not an object itself, so we were never successfully adding FTL .title
and .label attributes to the parsed strings.
This fixes the 862573eab regression, and makes search match FTL
attributes as it was always intended to.
Fixes#5947
(Confirmed on macOS, but probably Linux too)
Pass openNotExclusive to avoid acquiring an exclusive lock at the OS level
at open time, which fails with an I/O error on network shares. We still set
locking_mode=EXCLUSIVE, so the connection holds an exclusive SQLite lock for
its lifetime and keeps the WAL index in heap memory (no -shm file).
Regression in Zotero 7 (Fx115)
Fixes#4860
The temporary advanced search saved silently under an auto-generated
"Untitled" name. Prompt for a name instead (defaulting to that name),
and label its button "Save Search…" to signal the dialog. The saved-search
editor's button, which saves changes directly, is now just "Save".
https://github.com/zotero/zotero/pull/5658#issuecomment-4696398750
Deleting the saved search being edited triggered onCollectionSelected's
save-changes prompt, which doesn't make sense for a search that's gone.
Detect the deleted search and close the editor without prompting.
The menu was focused programmatically (in response to the filter-button
click), so :focus-visible wasn't set and no focus ring showed. Pass
focusVisible to force the ring.
The remove button on the sole remaining condition is now enabled once a
value is entered, and clicking it replaces the condition with the default
empty one shown when the pane is first opened, instead of staying
disabled.
macOS-normalize-controls zeros margins on inputs and checkboxes but not
menulists or buttons, so their native platform margins threw off the
spacing. Zero them and restore spacing via the containers' gaps.
https://github.com/zotero/zotero/pull/5658#issuecomment-4696398750
The inner <deck> stacks both panes in one grid cell, so the area was
always sized to the taller (saved-search) pane and never shrank back.
The non-selected pane is now removed from layout entirely.
https://github.com/zotero/zotero/pull/5658#issuecomment-4696398750
When conditions are removed, shift conditionIDs so that
conditionIDs always go in increments of 1 (0, 1, 2 ...).
It prevents conditionIDs from conflicting with each other
when conditions are rearranged.
Fixes: #3434
After the first bubble is added, the focused input gets a placeholder
indicating that typing a number will add it as a page to the just-added
bubble. The placeholder is truncated if it's too close to the edge in
multi-item citations.
Also add a tip to the item details popup explaining that locators can
be typed into the main input field, with a link to the documentation.
The tip stops appearing once a typed locator has been used.
---------
Co-authored-by: Dan Stillman <dstillman@zotero.org>
- allow to accept the dialog via cmd/ctrl+Enter from
inside of a panel
- enable click-through on item details panel, so
one can click on the "Accept" button without having
to close the popup first
These two measures allow one to add a bubble, modify
the citation via item details popup, and accept it
with one less step (without having to close the popup first)
Zotero never sets a primary password, so if one is set on the NSS key
database, it was either corrupted or copied in from a Firefox profile,
and stored logins can never be decrypted, since there's no
primary-password prompt. This previously made it impossible to save
credentials without manually deleting cert9.db, key4.db, and
logins.json from the profile directory.
If reading or saving credentials fails and a primary password is set,
clear stored logins and reset the key database so that credentials can
be saved again. Saving the API key or WebDAV password is retried
automatically, so logging in completes without a manual fix, and if
previously stored credentials are lost to a reset, show a one-time
alert prompting the user to log in again.
The once-per-minute rate limit from e40fff6a7d (5.0.91) was inverted,
and the last-error time was never initialized, so the alert hasn't
appeared since 2020.
Wraps the values stored in nsILoginManager with OSKeyStore, which derives
its master key from Keychain on macOS, DPAPI on Windows, and libsecret on
Linux. A copy of the profile alone is no longer enough to extract these
credentials.
Existing plaintext entries are mirrored once per session to a new
"(encrypted)" realm but preserved in the original realm so a user can
still downgrade to a release that doesn't know about encryption. Active
credential changes (sign in, sign out, password change) write to the
encrypted realm only and remove the legacy entry. A future version can
clear any remaining legacy entries on startup.
Patches MOZ_APP_BASENAME in the bundled runtime so the keychain master
key is labeled "Zotero Encrypted Storage" rather than "Firefox Encrypted
Storage", with a check_line guard so a future Mozilla change to the
OSKeyStore label format fails the build instead of silently rebranding
the entry. Also fixes check_line to take an explicit file argument.
The local-file-change watcher added in f21e1b2d32 accumulated changed
item keys globally but was drained separately by each library's storage
engine, with the drained keys filtered to that library. The first
library to file-sync (normally My Library) consumed all pending events,
and keys belonging to other libraries were silently discarded, so files
modified on disk in group libraries were never marked for upload. The
initial and periodic full-scan fallbacks on Windows and Linux were
likewise global, so only the first library ever received them, and
changes made in other libraries while Zotero was closed were never
detected at all.
The sync runner now drains the watcher once per sync session and
immediately runs the modification check on the changed items across all
libraries, recording any changes in the database, and the per-library
storage engines skip the check entirely unless the watcher reports that
the library needs a full scan:
- On all platforms, a library that has never been scanned gets one full
scan, which also gives libraries one recovery scan for changes dropped
by affected releases.
- On Windows/Linux, where the watchers only capture events while Zotero
is running, each library gets a full scan on its first file sync of
the session, on every manual sync, and daily during background syncs
(instead of the previous 3-hour interval, which dated from when scans
were the primary detection mechanism).
- On macOS, libraries scanned since the last FSEvents journal
discontinuity are tracked in a pref, since the journal -- and
therefore the validity of previous scans -- survives restarts.
Also:
- Check FSEvents event flags and fall back to full scans when events
were dropped or coalesced (MustScanSubDirs/UserDropped/KernelDropped/
EventIdsWrapped), and skip HistoryDone sentinel events
- Disable the watcher for the session and fall back to legacy scanning
on backend errors, including when the inotify watch limit is reached,
instead of continuing with silently incomplete coverage
- Prune scan records for deleted libraries, since SQLite can reuse a
deleted library's libraryID
https://forums.zotero.org/discussion/132120/
On macOS 27 and later, the installer gets access to the Word startup
folder via a folder-selection dialog rather than an OS permission
prompt, so support an adjusted banner message and add strings for the
folder dialog.
createDirectoryForItem() wipes and recreates the item's storage
directory before moving in a downloaded file. If removeDir() failed
(e.g., a locked file on Windows), the error bubbled up to zfs.js and
became the generic sync error. Route it through checkFileAccessError()
instead, so the user gets the actionable locked-file message and a
Show Parent Directory button.
https://forums.zotero.org/discussion/132097/
In Add/Edit Citation mode, display a preview of the citation
in the bottom section. The section can be hidden/displayed
via the toggle in the right corner.
Remove io.preview from editor instance, so that citation
dialog knows not to show the preview even if the preference
is set.
A minor refactor to have resizeWindow() resolve
when the animation is fully over, and clear minHeight
on window in list mode before resizing, restoring
it when resizing animation is done, same as in library mode.
It allows us to fully expand the window in list mode before
showing the preview.
Fixes: zotero#5910
The item tree's DOM id carries a view-specific suffix (e.g.
"item-tree-main-default", "item-tree-main-recentlyRead"), but three
call sites compared against a single hardcoded "item-tree-main":
- Collection highlighting on Ctrl/Option (zoteroPane.js) -- match on
the "item-tree-main" prefix to cover all views. This restores
highlighting in Recently Read, where it silently failed.
- Focusing the items list after Add Item by Identifier (lookup.js) --
use the current view's tree id instead of a literal that resolved to
null and threw.
- Shift-Tab from the item tree to the toolbar (zoteroPane.js) -- key the
actionsMap on the current view's tree id.
Add a test confirming focus lands on the items list after a lookup.
https://forums.zotero.org/discussion/130968/collection-of-selected-papers-is-not-highlighted-in-recently-read-panel
The earlier fix (ef7896ab5f) migrated 9.0.x's "<id>-default" prefs
forward to the refactor's new "<id>" key, but that left 9.0.x and 10
beta keying differently in treePrefs.json, so switching between versions
always reset 9.0.x to defaults.
Put the `-default` suffix back so Z9 and Z10 read and write the same
key, and migrate any unsuffixed `<id>` data written by an earlier beta
back to `<id>-default` on first load. The migration runs once per
process and can be removed in a future release once beta users have all
updated.
https://forums.zotero.org/discussion/131653/zotero-10-beta-5-reinitializes-the-columns-in-main-pane
example:
"Atmospheric Chemistry and Physics" is currently incorrectly abbreviated as "Atmospheric Chem. Phys." should be abbreviated "Atmos. Chem. Phys."
Zotero.Tags.init() keyed the id cache by the raw tag name from the
database, but getID() and Items._loadTags() both normalize names via
cleanData() (trim + NFC). A tag stored in a non-normalized form (e.g.,
non-NFC or with surrounding whitespace) could therefore never be matched
by getID(), which returned false. When such a tag was removed from an
item, that false was bound as the tagID parameter in the DELETE FROM
itemTags query, throwing "Invalid boolean parameter 1 'false'" and
aborting the save. Since this fired while applying changes during sync,
it persistently blocked sync.
To fix, normalize names in init() to match getID()/_loadTags().
https://forums.zotero.org/discussion/131901/error-report-seems-to-be-preventing-sync