Remove the isLinked item-list column and introduce an Unlinked Items
container row, with a localized label in zotero.properties.
Grouped mode now activates when unlinked items are present, and selection/
activation logic explicitly targets item rows while allowing container-row
navigation.
Replace Proxy-wrapped items and hacky rendering overrides
with proper ItemTreeRow subclasses and a custom
ItemTreeRowProvider.
- LibraryItemTreeRow: expandable container for library
grouping with sortChildren opt-in
- CitationExplorerItemTreeRow: row with citation metadata,
explicit id for CSL-only items, isContainer/
isContainerEmpty overrides to suppress twisties
- CitationExplorerRowProvider: groups items by library,
delegates sorting to base class via _sort()/_compareRows()
- CitationExplorerItemTree: custom tree with row provider
- Enable all standard columns (hidden by default) with
column picker and persistence
- isLinked column excluded from picker via
showInColumnPicker: false
- Remove persistColumns from citationDialog (consolidated
into columnPicker in prior commit)
- Add .library-container-row styling
If the keystore's secret is replaced -- say, after a keyring reset --
the stored value won't be able to be decrypted again, so tell them to
try logging in again instead of trying to fix their keyring.
https://forums.zotero.org/discussion/133603/
unload() closes and re-adds the tab, and the close recorded an undo-close
history entry, so Undo Close Tab could open a duplicate of a tab that was
still open.
_addEntry() wrote the row with REPLACE INTO, listing only itemID and
data, so flag reverted to its default of 0. It's called for every match
on every update, not just new ones, so a retraction the user had hidden
came back as soon as the list changed and Zotero restarted.
A window is marked as closed before its unload handlers run, so the tab
events fired from ZoteroPane.destroy() warned about every observer that
the closing window hadn't torn down yet. The leak check now also requires
the window to be detached from its docShell, and it covers functions. It
caught an observer that outlived its window -- the sync-reminder API key
observer, which is now unregistered on teardown.
Listeners added to the item and collection trees' event bindings
survived unregister() and held ZoteroPane and the views for as long
as the tree objects did. makeClassEventDispatcher() now provides
clearEventListeners(), which the trees call on unregister, so callers
don't need to remove their own listeners. The collection tree focus
listener, a plain DOM listener, is removed in destroy().
Hiding the tag selector destroyed the TagSelectorContainer but left
its media-query listener registered, keeping the destroyed instance
alive for the lifetime of the window and firing setState() on the
unmounted component when the display density changed. The fontSize
pref observer id was also overwritten by the uiDensity registration,
so it was never unregistered.
Selecting a collection doesn't wait for the tag selector to re-render,
so waitForTagSelector() could be resolved by the initial render instead
of the awaited change, and the assertions could run against a stale tag
list.
The cached retractions list is saved with the current data version from
the code, which we can bump to make clients discard their cached data
and refetch it. We've never actually done that, but if we did, it
would've hit a bug: init() would've started the refetch but still sent
the cached ETag, so if the list itself hadn't changed, the server
would've returned 304 and nothing would have been updated. The stale
version then would have survived, so the refetch would have been retried
on every startup.
Retraction Watch has renamed, merged, and added reason terms since these
were added, leaving only 65 of the 102 entries matching a term still in
use. 90% of retracted items had at least one reason that didn't show a
description, and 21% showed none at all. Rebuilt from the current
Appendix B list, which covers every reason in the data.
Windows returns this for ERROR_FILE_CORRUPT/ERROR_DISK_CORRUPT. It's not
in xpc.msg, so the exception has an empty name and isn't in
Components.results, and it was falling through to the generic file sync
error instead of the file access error with the path. Show a message
about the reported corruption in place of the usual permissions advice.
https://forums.zotero.org/discussion/133592/
The shims from 5697ee0af7 keep old plugins working for users, but
beta/dev/source builds should still throw to get the attention of
developers and (hopefully breakage-tolerant) beta users.
Status messages were left aligned for the multi-paragraph intro text,
but in a narrow window, that made single lines that wrapped sit
off-center, so center those instead.
Plugins written for earlier versions call methods like
CollectionTree#getSelectedSearch(), which now throw. We did this
intentionally to make old code more obviously broken, even with single
selection, so developers would fix their code, but we're not yet
blocking plugins that illegitimately declared compatibility with a
future version, so some haven't been updated and are breaking Zotero.
With a single row selected, the pre-10 functions can technically
continue to work, so for now, restore them and just warn and name the
plugin instead of throwing. They still need to throw if multiple rows
are selected, since plugins that haven't been updated can't safely act
on a selection that might span collections or libraries.
https://forums.zotero.org/discussion/133565/