Commit graph

663 commits

Author SHA1 Message Date
Dan Stillman
73f4273e2d Make Original Date a date field
Update the global schema to 45, resolve a field's date type through its
base-field mapping in ItemFields.isDate() (to cover priorityDate), and
convert stored values of date-type fields to multipart dates on schema
upgrade.
2026-08-20 12:57:46 -04:00
windingwind
09249bfb73
fx153: Interface should load with nsIID instead of string (#6008) 2026-08-05 14:18:32 -04:00
Abe Jellinek
9dd17a212e Track data object versions locally
Add a clientVersion column for items, collections, searches, and
libraries, incremented once per library per transaction on every
object save or deletion. The local API reports these versions instead
of synced versions -- in object JSON, format=versions, since=
filtering, and Last-Modified-Version -- since synced versions don't
reflect local changes and are 0 for unsynced objects. Group metadata
responses keep reporting the synced group version, which has no local
counterpart.

---------

Co-authored-by: Dan Stillman <dstillman@zotero.org>
2026-07-28 09:57:43 -04:00
Dan Stillman
ee68452b05 Disallow slashes in stored-file attachment paths
Someone ended up (via a plugin, presumably) with stored-file attachments
with a full path after 'storage:', which broke file syncing. Throw when
setting a stored-file path containing a slash, and strip paths from
existing filenames in a schema update step. No particular reason to
think that the file with that basename will exist in the storage dir,
but at least it will be looking for the right file and not be totally
broken.

Separately, the dataserver will clean up filenames with full paths and
block going forward.

https://forums.zotero.org/discussion/132822/reference-sychronization-error
2026-07-21 10:40:59 -04:00
Dan Stillman
5877952954 Add accented stop-words to abbreviations word list
Accented stop-words weren't matched by the existing unaccented
entries (e.g., "fur"), so automatic journal abbreviation kept and
capitalized them: "Jahrbuch für Heimatkunde" became "Jahrb. Für
Heimatkunde" instead of "Jahrb. Heimatkunde".

https://groups.google.com/g/zotero-dev/c/uP18QEKe2JU/m/AsoGWxd9AwAJ
2026-07-20 22:52:51 -04:00
Dan Stillman
f8f83cceac Update global schema (locales) 2026-07-16 12:29:53 -04:00
Dan Stillman
5ade25f5f5 Drop the unused savedSearchConditions required column (#5962)
The condition `required` flag was removed in #5962, but the column was
kept so older clients could still read the database. The full-text
search changes bump the userdata compatibility version, locking out
those clients, so the column can now be dropped.
2026-07-15 15:36:40 -04:00
Dan Stillman
7c2a1d127d Add full-text content search via FTS5
Index attachment content into a contentless trigram FTS5 table in a
separate, attached fulltext.sqlite, normalized so matching is accent-
and case-insensitive. For content containing CJK characters, a companion
'ascii'-tokenized table holds bigrams so 1-2 character CJK queries, which
the trigram tokenizer can't match, still work. The extracted text still
lives in the .zotero-ft-cache files, so the index is fully derived and
rebuildable.

Use the FTS index for the fulltextContent condition, falling back to the
cached-text scan for queries too short to index, and point quick
search's content matching at the FTS index in place of the now-removed
word index. (One side effect: quick search now matches attachment
content by substring rather than by word.)

Already-extracted content is migrated into the index at startup, slowing
down on active usage. A background queue then extracts not-yet-indexed
attachments gradually when Zotero is idle. Attachments with no local
file or full-text content are recorded as missing. Content downloaded
via sync is processed into the index immediately when the sync finishes,
rather than waiting for idle like it did before, so it's searchable
immediately in on-demand file-download mode.

The index DB is tied to the main DB via the local user key and rebuilt
if they don't match (e.g., after a delete-and-resync). We compact it by
running FTS5's 'optimize' command once the indexing queue drains, and we
vacuum the attached database when necessary to reclaim disk space.

Closes #2038, #2044
Addresses #1595
2026-07-15 15:36:40 -04:00
Dan Stillman
3bd8d641b8 Make item search accent-insensitive
Search now ignores accents, so "seance" matches "séance" and vice versa.

Text is normalized with Unicode NFKD compatibility decomposition (which
also handles typographic ligatures, superscripts, full-width forms,
etc.) plus a small map for letters NFKD leaves alone (ø, œ, æ, ß, ...)
and the fraction slash, via Z.Utilities.Internal.normalizeForSearch().
The HTML tags we support in item fields are stripped, so markup isn't
matched (#81). Typographic quotes (#29, #1876) and dashes are folded to
ASCII.

Each searchable column gets a normalized shadow column --
itemDataValues.valueNormalized, tags.nameNormalized,
creators.firstNameNormalized/lastNameNormalized, and
itemAnnotations.textNormalized/commentNormalized -- populated at write
time and matched via COALESCE(normalized, raw) LIKE. NULL is stored when
normalizing only changes case, so plain-ASCII values are only stored
once. This covers the contains/doesNotContain/beginsWith operators in
both quick search and Advanced Search.

The new columns are local-only derived data and aren't synced. Older
clients will ignore them, so this doesn't break DB compatibility.
Existing rows are backfilled after the startup sync by
Zotero.Schema.populateNormalizedSearchColumns(), which should only take
a few seconds on most databases.

Closes #29, #81, #1300, #1876
2026-07-15 15:36:40 -04:00
Dan Stillman
4f45db5009 Update translators submodule 2026-07-15 12:52:54 -04:00
Abe Jellinek
f3328b02ee
Item/collection tree: Resize using ResizeObserver, not debounce (#5977) 2026-06-30 08:44:18 -04:00
Dan Stillman
2239dd20a4 Update global schema version for search-condition-group gate (#5962)
Some checks are pending
CI / Build, Upload, Test (push) Waiting to run
2026-06-25 16:14:38 -04:00
Christopher Holmes
31b3ead557
Abbreviate Atmospheric as Atmos. (#5938)
Some checks are pending
CI / Build, Upload, Test (push) Waiting to run
example: 
"Atmospheric Chemistry and Physics" is currently incorrectly abbreviated as "Atmospheric Chem. Phys." should be abbreviated "Atmos. Chem. Phys."
2026-06-04 15:38:42 -04:00
Abe Jellinek
e029354a35
Fix US-formatted Last Read dates in en-* alias locales (#5934) 2026-06-03 02:35:15 -04:00
Adomas Venčkauskas
5ca1fbb167 Item tree refactor megacommit
Split ItemTree megaclass into:
- ItemTree - concerned with drawing the virtualized table container and
  column interaction
- ItemTreeRowProvider - provides rows and issues notifications for
  render updates
- ItemTreeRow and subclasses - contains row-specific data and rendering
  logic
- CollectionViewItemTree and its accompanying classes - a version of
  ItemTree that renders items attached to a given Collection or
  CollectionView (CollectionTreeRow).

Various improvements in logic and rendering, separation of concerns.
2026-04-27 14:44:39 -04:00
Dan Stillman
7f9fdc0786 Update translators, styles, CSL locales, and renamed-styles.json 2026-04-02 15:51:43 -04:00
Tom Najdek
862573eabc
Per-group file renaming settings (#5862)
Also:

- Add `isAdmin` property to libraries
 
---------

Co-authored-by: Dan Stillman <dstillman@zotero.org>
2026-04-02 15:15:06 -04:00
Dan Stillman
e629a3c456 Update global schema to version 42 to enable lastRead fetching 2026-03-21 13:31:11 -04:00
Dan Stillman
d20cac39c9 Fix unhandled promise rejections in ConcurrentCaller when clearing queue
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.
2026-03-17 13:59:52 -04:00
Abe Jellinek
34039991f8
Track attachment last-read time, add Recently Read virtual collection (#2854)
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>
2026-03-17 13:52:00 -04:00
Abe Jellinek
13f1606dc7 Read Aloud: Implement onPurchaseReadAloudCredits() 2026-03-02 14:47:14 -05:00
Dan Stillman
85bff00a3c Update translators 2026-01-27 13:46:49 -05:00
Adomas Ven
6697db1dba
Delete duplicate renamed styles on init (#5734)
After citation-style-language/styles#7928 renamed Vancouver styles to
NLM terminology, Zotero installations end up with both vancouver.csl
and nlm-citation-sequence.csl. To fix, on init, delete any installed style
whose ID appears in the renamed-styles mapping if the target style
also exists.

---------

Co-authored-by: Dan Stillman <dstillman@zotero.org>
2026-01-26 10:35:43 -05:00
Dan Stillman
67c10a9ff7 Update bundled styles and renamed styles 2026-01-25 22:12:52 -05:00
Dan Stillman
cc95b93741 Update translators 2026-01-20 12:06:55 -05:00
Dan Stillman
e9bcf6f10a Update global schema
Locale updates
2026-01-20 12:06:54 -05:00
Dan Stillman
72321ead34 Update bundled styles and renamed-styles.json 2026-01-13 12:05:38 -05:00
Dan Stillman
42b559dda2 Update global schema 2026-01-13 12:05:38 -05:00
Dan Stillman
689e59f161 Update global schema
Remove "Creator" from "Audio Recording"
2025-12-26 23:45:24 -05:00
Dan Stillman
3256273015 Update global schema
"Uploader" → "Creator" on Video Recording
2025-12-26 23:35:43 -05:00
Dan Stillman
f0ff173ad2 Update global schema to remove arXivID field 2025-12-26 15:36:13 -05:00
Dan Stillman
f0bbb9b370 Update global schema 2025-12-25 00:20:34 -05:00
Dan Stillman
611acd0703 Update global schema 2025-12-24 22:00:52 -05:00
windingwind
e522f6185e
Add note as tab (#5528) 2025-12-18 23:49:42 -05:00
Dan Stillman
4ca9bbdae5 Automatically show post-upgrade banner for each new major version
And remove the density switcher
2025-12-16 13:50:27 -05:00
Dan Stillman
34508e145c Update translators, styles, and CSL locales 2025-12-16 10:42:48 -05:00
Dan Stillman
d1f478fc4e Update translators, styles, and CSL locales 2025-10-14 12:03:25 -04:00
Abe Jellinek
afc02141ce
Replace CSL validator with reproducible WASM build (#5525) 2025-08-29 00:40:41 -04:00
Abe Jellinek
23567b0395
ESMify feed processing code (#5520) 2025-08-26 23:42:00 -04:00
Dan Stillman
e7805914f4 ConcurrentCaller: Increment numRunning in the correct place 2025-07-30 22:31:09 -04:00
Dan Stillman
0f560f4e4c ConcurrentCaller: Fix return value in comment after Bluebird removal 2025-07-30 22:31:09 -04:00
Dan Stillman
5c172e3be9 ConcurrentCaller: Reject queued promises when stopping queue
Previously, we simply cleared the queue, leaving any pending promises
unresolved, and we checked for isResolved()/isPending() in
storageEngine.js (and maybe other places). storageEngine.js was changed
to simply await those promises, but that results in a hang if the queue
is stopped, since the promises were never resolved. Instead, when
stopping the queue, reject queued promises with a CanceledException and
ignore those promises in storageEngine.js.
2025-07-30 22:31:08 -04:00
Dan Stillman
1500fb9fa3 ConcurrentCaller: Revert to Promise.delay()
We're shimming it, and we override it with a stub in a syncAPIClient
test.
2025-07-30 22:31:07 -04:00
Adomas Venčkauskas
601a1f2292 fx140: ESMify word-processor-plugin-installer 2025-07-30 22:30:52 -04:00
Abe Jellinek
9be57b3110 Update ConcurrentCaller to use native promises 2025-07-30 22:30:29 -04:00
Abe Jellinek
a080b7c9c6 fx140: Give require()'d modules a window context 2025-07-30 22:18:36 -04:00
Abe Jellinek
ece2b59700 fx140: More progress toward startup 2025-07-30 22:18:36 -04:00
Abe Jellinek
c506e41072 fx140: Add working require.js, more progress toward startup 2025-07-30 22:18:36 -04:00
Abe Jellinek
8d0923f119 fx140: Remove Bluebird
All module code runs in strict mode, and that breaks Bluebird.

And add a partial shim for the simplest and most useful methods. Not
sure if we actually want that, or if we should just replace it entirely
with native methods.
2025-07-30 22:18:35 -04:00
Dan Stillman
7a4aef1b32 Update styles and CSL locales
Including new Chicago styles
2025-07-15 00:46:09 -04:00