_rollUpAnyToLevel() only followed an annotation's parent when the
attachment itself had a parent, so in a search for top-level items, a
tag on a standalone attachment's annotation matched nothing.
The condition seeded by _loadConditions() used `mode: undefined`, but
toJSON() only omits the "/mode" suffix when the mode is exactly false
(what parseCondition() returns), so a saved search migrated from the
obsolete childNote condition serialized -- and synced -- the condition
as "resultLevel/undefined".
_buildQuery() already uses the first top-level joinMode for the
full-text post-filter; with multiple top-level joinMode conditions (only
creatable via the API), combineConditions() used the last.
Extends existing handling for tag selection and quicksearch to handle
advanced search as well.
Fixes#5996 (not just for zotero://select but for all selectItems()
callers)
Instead of just prefixing the labels with "-", indent the whole row,
including the icon. This looks better and fixes FAYT on subcollection
names.
https://forums.zotero.org/discussion/132561/
The #focus() Tab/Shift-Tab tests dispatch synthetic keydowns and wait on
a focusin event to sync with the collections search field's async
(setTimeout) focus. Gecko only fires focus/blur events while the window
is active, so when the pane window wasn't active -- it opens in the
background on macOS/Windows and can lose activation on Linux/CI -- the
focusin never fired and the test hung until Mocha's timeout. Activate
the window in beforeEach, as the item pane and tags box focus tests
already do.
Also removes the temporary open-window logging added in e1f19f34f5.
Cache patches and compressed files by content hash so that they're reused
across FROM versions and releases. Cache entries are touched when used and
expire after 60 days.
The cache key includes a tag covering the xz/mbsdiff versions and the
compression options, so entries are invalidated when the toolchain changes.
Run the per-file mbsdiff/xz work in make_incremental_update.sh and
make_full_update.sh through a parallel job pool, largest files first, and
assemble the manifests serially afterward, producing byte-identical MARs.
Set UPDATE_PACKAGING_JOBS to override the number of parallel jobs.
Tests that shrink the window to test visibility-based rendering restore the
height on their last line without waiting for it to apply, so the next test
could start rendering while the window was still 100px tall. The attachments
box's async render is skipped for panes outside the viewport and only retried
on scroll, so the pane never rendered and assertions on it failed or timed
out.
waitForPreviewBoxRender() without an item id returns immediately if the box
still holds the previous item's completed render, so on a slow machine the
row assertions could run before the new item's async render started.
EPUB recognition translates the EPUB's RDF metadata, and
Zotero.Translators.save() requires translators to be loaded. The full test
run relied on an earlier test file having initialized translators.
Tests restore the stub at the end of the test body, so a failure left
Zotero.Translate.Search.prototype.translate wrapped and retries failed with
"Attempted to wrap translate which is already wrapped".
The reporter only showed the final failure, so if a retry failed differently
(e.g., from a stub left wrapped by the first failure), the original error was
lost.
Zotero.Cite.getLocatorString() requires Zotero.Styles.init() to have run.
The full test run relied on an earlier test file (bibliographyTest) having
initialized styles.
Pushes to branches in this repo already run CI, so run pull_request jobs only
for PRs from forks, which don't trigger push runs here. The push run's checks
still appear on the PR, since checks are attached to the head commit. (This
skips merge-commit testing for same-repo PRs -- the push run tests the branch
as-is.)
Each shard job builds and runs a quarter of the test files via runtests.sh -p.
The deployment ZIP upload and utilities tests move to separate jobs. With the
default fail-fast matrix behavior, a failure in one shard cancels the others.
The sorted file list is split into contiguous chunks of roughly equal total
file size, using size as a stand-in for run time, so new test files are
included automatically and slow test files are spread across shards rather
than landing in the same shard by chance. Contiguous chunks preserve the
alphabetical run order of a full run, so files keep the same preceding files
as in a full run except at chunk starts, and a shard can be reproduced locally
by passing its first and last files to -s and -e.
After a full build, dir_build saves a manifest of build/ files to
staging/.build-manifest. On subsequent runs, if all changed files are
ones that build.sh copies into omni.ja unmodified (chrome/, components/,
resource/, and test/ when tests are staged), zip just those files into
the staged omni.ja instead of rebuilding, taking rebuilds from ~15
seconds to ~0.3 seconds on an M1 Mac. Files are prescreened by size and
mtime so that only changed files need to be hashed. Zotero .ftl files
are also updated at their localization/<locale>/ paths, and test files
are also copied to the staged tests/ directory.
Any other change triggers an automatic full rebuild: files transformed
by build.sh (defaults/, chrome.manifest, version, translators/, styles/,
mozilla .ftl files, CSL locales), removed files, changes to build inputs
in app/ (detected via a size/mtime fingerprint, with xulrunner runtimes
covered by the hash-* files written by fetch_xulrunner), or requesting
tests or devtools that the staged build doesn't include.
Other changes:
- dir_build no longer takes -q and always skips omni.ja compression and
optimization, which only matter for distribution builds made via
build.sh. Use -f (dir_build or build_and_run) to force a full rebuild.
- build_and_run now always rebuilds. -r is deprecated, and -n skips the
rebuild and just launches the app.
- build_and_run no longer passes -purgecaches. Startup caches are
invalidated automatically when the BuildID changes, which now happens
whenever omni.ja is modified (including via add_omni_file), so
relaunching an unchanged build can use the startup cache.
- build_and_run and runtests.sh invoke js-build directly instead of via
'npm run', which saves ~270ms of npm overhead per build.
- The Word integration dylib is now ad-hoc-signed by dir_build, and only
on full rebuilds, since incremental updates don't invalidate the
existing signature. This also covers test builds, which were never
signed before.
- dir_build removes broken symlinks left in build/ when source files are
deleted, which previously broke rsync in prepare_build.
The reader now releases its rendered pages while its document is
hidden, which requires document.visibilityState to be truthful: it's
driven by docShellIsActive, which also controls event-loop throttling
for background tabs. The flag was maintained by scattered one-off
writes and went stale on the transitions they didn't cover: a tab
opened in the background ran at foreground priority (unthrottled rAF
and timers) with a 'visible' document until the next tab switch, and a
hidden tab kept an active docShell forever after its Read Aloud
playback was paused or stopped — in both cases keeping the reader from
ever releasing memory.
Replace the writes with a single _updateDocShellActivity() that
re-derives the state — active only while the tab is selected or
playing Read Aloud — called from the three places its inputs change:
tab creation, tab selection, and Read Aloud status changes.
If the preview fails, log the error and show "Preview unavailable"
instead of breaking the item-add flow with an unhandled rejection.
If io.sort() fails during accept, log and continue unsorted -- the
insert runs the same processor operation, so a real failure triggers the
document-update error dialog instead of a stuck progress window.
Skipping the sort doesn't affect the inserted citation, which the
processor sorts itself. It only determines the stored item order, and
with it the initial bubble order if the citation is edited later -- the
reopened dialog re-sorts once cited data has loaded.
Deleting a search in the collections pane moves it to the trash rather
than erasing it, so the check that closes the saved-search editor when
the edited search is deleted didn't catch it. The save-changes prompt
then appeared on the next selection change, and canceling couldn't
restore the removed row, so the prompt reappeared on every selection
until choosing Don't Save. Treat a trashed search like a deleted one
and close the editor without prompting.
Previously a search could be saved only at a library root. Now the Save
Search button is enabled when collections and/or saved searches within
a single editable library are selected, and the selection is added to
the saved search as collection/savedSearch conditions -- an 'any' group
of them when more than one row is selected. If the search's own join
mode is 'any', its existing conditions move into an 'any' group of
their own so the scope conditions apply to every result instead of
joining the OR. A 'recursive' condition is included per the
recursiveCollections pref.
https://forums.zotero.org/discussion/132528/beta-cannot-create-a-saved-search-from-a-collection
With "Hide Non-Matching Annotations" enabled, an attachment displayed as
empty and non-expandable if no annotations matched the search, so
searching by any non-annotation condition made it impossible to expand
attachments to browse their annotations. Now only hide the non-matching
annotations when the attachment actually has a matching one.
https://forums.zotero.org/discussion/132519/beta-advanced-search-cannot-expand-annotations-of-search-results
Previous command only worked with OpenSSL's labeled output where the hash is the second field; the update also handles LibreSSL (macOS), which prints just the bare hash.
When the item pane is dragged wide, the items pane is squeezed and the
quick search wrapper kept its intrinsic width and overflowed, pushing the
trailing Advanced Search button out under the item pane. Let the wrapper
shrink so the button stays within the pane.
Fixes#5982
The 'items in this view' count failed to update when the result set
changed without a selection change (e.g., quick search, tag filter, or
sort with nothing selected). The listener that refreshes the item pane
on refresh was registered in 8277277948 to fire only once, on initial
load, so later refreshes never recomputed the count.
This is all a regression from the items tree refactor (cbbff600a6),
which stopped running itemSelected() on every refresh.