Skip to content

Replace XhtmlDocView's SelectedPublication broadcasts with direct calls - #1195

Merged
mark-sil merged 1 commit into
mainfrom
claude/pubsub-selected-publication-d85c54
Oct 20, 2026
Merged

mark-sil merged 1 commit into
mainfrom
claude/pubsub-selected-publication-d85c54

Conversation

@mark-sil

@mark-sil mark-sil commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Start here: ShowConfiguration and ShowSelectedPublication in Src/xWorks/XhtmlDocView.cs, then their two callers, RefreshAllContent and OnShowAllEntries.

XhtmlDocView no longer broadcasts SelectedPublication to itself. RefreshAllContent (reached by F5, the Configure dialog's DictionaryConfigured event and RefreshCurrentView) and OnShowAllEntries (the pane bar's "All Entries" item) now store the property with the broadcast flag off and run the handler's work directly: choose the configuration valid for the publication, then load it. Each loads the content once.

Does the end state change? No. When the current layout excluded the selected publication, RefreshAllContent stored the new publication, loaded the layout it already had, and the queued broadcast then loaded the layout valid for the new publication. UpdateContent's duplicate-load guard usually hid that second load. It still ran when the publication fell back to All Entries or the valid layout was another file, and only the queue order put the right layout last. A synchronous call in the old position would have loaded the stale layout last. ShowConfiguration now chooses before it loads, so its one load is of the layout the deferred handler used to end on.

Where to look

  • Reversal Indexes, switching to another language's layout that also excludes the publication: the load now runs before the reversal list reloads for the new index, as it already did when the publication stayed valid. Checked manually against that case.
  • Show All Entries now loads inside the menu command, as F5 already does. Choosing it while already selected is still a no-op.
  • The OnPropertyChanged case for SelectedPublication stays: the pane bar publication menus (ChoiceGroup), the window's default properties and the first read of an unset property still broadcast the name.

Not here: those three paths keep the Mediator broadcast until property-change delivery moves to Pub/Sub.

Verification

  1. build.ps1 -CommentHygiene -TokenHygiene: clean.
  2. test.ps1 -TestProject xWorksTests: 1794 passed, 2 skipped, 0 failed.
  3. Five new tests in XhtmlDocViewTests assert one load, the right configuration and no queued broadcast.
  4. Manual, in Indonesian-ForDictionary and Sena 3: choosing a publication, F5, removing the publication from the current layout (with and without other publications left), Show All Entries, the same in Reversal Indexes, and a reversal language switch with the publication excluded.

Next: approve.


Reading this a year from now -- start here

This is one step of moving xCore PropertyTable change notification (SetProperty(..., true) -> Mediator.BroadcastString("OnPropertyChanged", name), delivered from the window's message pump after the caller returns) to direct calls or FwUtils Pub/Sub. Sites whose only listener is the setter itself are converted by calling the listener's work directly, at the point where the deferred delivery used to take effect. The value is still stored, because readers depend on it, but without the broadcast.

Decisions, and why
  • One shared method, called by the handler case and both setters. ShowSelectedPublication is exactly what the SelectedPublication handler case did. Keeping the menu path and the direct paths on the same code means the two cannot drift.
  • ShowConfiguration decides before loading. In RefreshAllContent the publication check now chooses between "load the configuration passed in" and "move the publication, then load its valid configuration", instead of loading first and correcting later. That removes both the stale-order hazard and the second load.
  • The guard in OnShowAllEntries. SetProperty broadcast only when the value changed. Choosing All Entries while it is selected did nothing, and still does nothing.
  • UpdateContent is protected virtual so the test subclass can record loads without Gecko or a progress dialog. Nothing in production derives from XhtmlDocView.
  • m_updateContentLater and the layout handler are untouched. Neither depended on the SelectedPublication broadcast arriving later.
Who still broadcasts SelectedPublication
  • ChoiceGroup singlePropertyAtomicValue menus: Lexicon/areaConfiguration.xml (Dictionary tool pane bar) and Main.xml (Reversal Indexes pane bar), through ChoiceGroup.ChooseSinglePropertyAtomicValue.
  • xWindow.LoadDefaultProperties, for the SelectedPublication default "Main Dictionary" when no value exists yet.
  • PropertyTable.GetStringProperty / GetValue with a default, which store and broadcast the default when the property is missing. Readers: GetCurrentPublication in XhtmlDocView and XhtmlRecordDocView, ConfiguredLcmGenerator.CurrentDecorator, XhtmlDocView.IsObjectVisible.
Preflight review details

Code Review Summary

Branch: claude/pubsub-selected-publication-d85c54
Base: main
Review model: Claude Opus 5.5
Files changed: 2

Overview

Converts XhtmlDocView's two self-broadcasting SelectedPublication sets to plain sets plus a direct call of the handler's work, loading once with the end state the deferred handler produced. Developer-facing Pub/Sub migration step. The behaviour a tester can see is one load instead of an occasional two.

Contract/API Changes

None outside the class. UpdateContent moved from private to protected virtual. ShowConfiguration is a new internal method.

Findings

Important - Should address before merge

  • The description of the old behaviour said "two loads" in every case (fixed during review: the commit message and test steps now say the second load ran only for the All Entries fallback or a different valid layout)
  • No test where the valid configuration differs from the one passed in (fixed during review: ShowConfiguration_ValidConfigurationIsAnotherFile_LoadsOnlyTheValidOne)

Minor - Consider

  • Reversal layout switch with the publication excluded now loads before the list reload (same order as the valid-publication path; verified manually)
  • Show All Entries loads synchronously inside the menu command (F5 already does the same)
  • Exceptions from configuration gathering now surface through Publish (the same subscribers already read the same files in UpdateContent)
  • UpdateContent widened for the test seam (no production subclasses)
  • The All Entries guard skips an unset property (reading an unset property stores and broadcasts the default, so the end state is unchanged)

Required Validation / Evidence

Build and xWorksTests as listed above. All manual steps were run and passed.

Interview Notes

All manual tests passed, and the code and the commit message were reviewed. Pub/Sub migration work carries no Jira ticket for now.

🤖 Generated with Claude Code


This change is Reviewable

XhtmlDocView set SelectedPublication with the broadcast flag at two
sites whose only listener is the view itself: RefreshAllContent, which
F5's MasterRefresh and the DictionaryConfigured event reach, when the
current configuration excludes the selected publication, and
OnShowAllEntries, the handler of the ShowAllEntries command. The xCore
Mediator delivered those broadcasts after the caller had returned, so
RefreshAllContent loaded the configuration it had computed and the
deferred handler then asked for the configuration valid for the new
publication. A second load followed whenever that was another file or
the publication fell back to All Entries, and the right configuration
ended up loaded only because the deferred load came last.

Both sites now store SelectedPublication without a broadcast and do
the handler's work directly, in place of the deferred load.
RefreshAllContent loads once: the configuration valid for the
publication it moved to, or the current configuration when the
publication stays. Show All Entries loads once, and choosing it while
All Entries is already selected changes nothing, as the PropertyTable's
change-only broadcast made it before.

The OnPropertyChanged case for SelectedPublication stays, because the
publication menus (ChoiceGroup) and the window's default properties
still set the name with a broadcast. The value stays in the
PropertyTable because GetCurrentPublication, XhtmlRecordDocView and
ConfiguredLcmGenerator read it while the content is generated. The
DictionaryPublicationLayout and ReversalIndexPublicationLayout handler
and m_updateContentLater are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov-commenter

codecov-commenter commented Oct 20, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 72.22222% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 39.75%. Comparing base (e8487e6) to head (9a87fdc).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
Src/xWorks/XhtmlDocView.cs 72.22% 4 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1195      +/-   ##
==========================================
+ Coverage   39.63%   39.75%   +0.12%     
==========================================
  Files        1541     1544       +3     
  Lines      354882   355096     +214     
  Branches    41176    41248      +72     
==========================================
+ Hits       140662   141175     +513     
+ Misses     184831   184562     -269     
+ Partials    29389    29359      -30     
Files with missing lines Coverage Δ
Src/xWorks/XhtmlDocView.cs 11.20% <72.22%> (+3.52%) ⬆️

... and 33 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown

NUnit Tests

    1 files  ±0      1 suites  ±0   13m 57s ⏱️ + 4m 10s
6 729 tests +5  6 644 ✅ +5  85 💤 ±0  0 ❌ ±0 
6 738 runs  +5  6 653 ✅ +5  85 💤 ±0  0 ❌ ±0 

Results for commit 9a87fdc. ± Comparison against base commit 620cd99.

@thejambi thejambi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@thejambi reviewed 2 files and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on mark-sil).

@mark-sil
mark-sil merged commit 363d3c8 into main Oct 20, 2026
9 checks passed
@mark-sil
mark-sil deleted the claude/pubsub-selected-publication-d85c54 branch October 20, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants