Skip to content

[PB Extension] Let a caller name a lexicon without owning the project setting #2626

Description

@imnasnainaec

Why

The interlinearizer extension is adding a lexicon chooser (sillsdev/interlinearizer-extension#44). A Paratext 10 project is linked to exactly one FW Lite lexicon, and that link is changeable but deliberately hard to change — the same rule this extension already enforces through lexicon.lexiconCode.

The interlinearizer records that link in a project setting of its own rather than reusing lexicon.lexiconCode, because an FW Lite lexicon code cannot name a non-FW-Lite lexicon and the interlinearizer has to keep that option open (sillsdev/interlinearizer-extension#46). Two things here assume this extension's own setting is the only way to name a lexicon.

Both are breaking changes, and neither is a compatibility risk: both extensions are pre-release. Neither should change anything a user of this extension on its own can see — see the note under each.

  • Make IEntryService lexicon-addressed.

    Every method takes a Paratext projectId (src/types/lexicon.d.ts) and uses it for exactly one thing: ProjectManager.getLexiconCode(projectId) (src/services/entry-service.ts). The parameter is never used as a project id, so the service already addresses a lexicon — just indirectly, through ambient project state.

    That indirection is a correctness problem for any caller that records the link elsewhere. Two settings then describe the same fact and can drift, and a project-addressed call silently resolves through this extension's setting — so reads and writes would land in a different lexicon than the caller recorded, with nothing to detect it.

    Replace the parameter with a lexicon handle and keep the project→lexicon mapping in this extension's own commands and WebViews. Touches src/services/entry-service.ts, src/types/lexicon.d.ts, the three WebViews that consume the network object (add-word, find-word, find-related-words), and the consumption pattern published in README.md.

    Small, with no UX change. The callers already do the work this asks for. Every command that opens a lexicon WebView resolves the code up front via getLexiconCodeOrOpenSelector() (src/main.ts:126, :149) and returns early when there is none, so the "no lexicon selected → open the selector" prompt lives in those handlers rather than in the service. The WebViews already receive the code as a prop — LexiconOptions.lexiconCode, populated by getLexiconWebViewOptions (src/utils/project-manager.ts:104-111). So each WebView passes a value it already holds instead of projectId, and nothing about the standalone flow moves.

    It also closes a latent split-brain: today a WebView holds one lexiconCode prop while every service call independently re-resolves the setting, so if the setting changes while a webview is open, the two disagree about which lexicon is in play. Afterward there is one source, and openWebView already reloads an open webview with fresh options.

    Keep deliberately: getLexiconCodeOrOpenSelector also clears a stored code that no longer resolves and notifies the user (src/utils/project-manager.ts:62-69). That is tied to the setting, not the service, so it survives the change — but those command handlers become the only remaining readers of lexicon.lexiconCode, so it is worth retaining on purpose rather than by luck.

  • Let the selector report a chosen or created lexicon instead of committing it — as an added mode.

    select-lexicon.web-view.tsx routes both selection and creation through lexicon.selectLexicon(projectId, code), which writes lexicon.lexiconCode, and ProjectManager.openSelector opens it bound to a project. A caller that records the link elsewhere needs the code handed back instead.

    The CreateLexicon component is already caller-agnostic — it takes createLexicon and onCreated(code) as props — so the coupling is in the WebView wrapper and the commands, not the form. Note also that lexicon.lexicons and lexicon.createLexicon already return values without writing any setting; only lexicon.selectLexicon commits.

    Additive, so standalone behavior is untouched. Built as a report-don't-commit mode passed through LexiconWebViewOptions, this extension's own path keeps committing exactly as it does now. Built instead as a replacement, the standalone flow gains a step and two behaviors have to be preserved deliberately — auto-select after create, and the "Lexicon selection saved" confirmation — both of which live in the onCreated / selectLexicon callbacks that would move.

    Open question: how the result reaches the caller. papi.webViews.openWebView returns a WebView id, not a value, so this needs a callback command the WebView invokes, an event, or a caller-supplied command name passed through LexiconWebViewOptions. Worth settling before implementing.

    This one is conditional. It is only needed if the interlinearizer reuses this extension's selector UI. If it builds its own chooser on the two commands that already return values, nothing here has to change. That call is open on the interlinearizer side.

Not in scope

Removing the dev-only lexicon.changeLexicon and the sticky-selection cleanup it belongs to. Related (it is the other place a selection gets written), but independent of this. Neither ask touches sign-in or the sticky-selection UX.

Related

sillsdev/interlinearizer-extension#44 and its plan comment; sillsdev/interlinearizer-extension#46.


Drafted by Claude Opus 5.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions