Repository navigation
Conversation
The Avalonia detail view now answers the menus of an etymology, an extended note, a note's examples, an example, a pronunciation, Variant Info and a picture itself: Move Up and Move Down, Delete, the Inserts, Insert Sound or Movie and Picture Properties all display and run from the row. Until now each of these menus still built the hidden WinForms DataTree to answer them. The WinForms view's Move and Insert Sound or Movie commands now run the same shared rules. Owned by the native authority from this change: * mnuDataTree-Etymology * mnuDataTree-ExtendedNote * mnuDataTree-ExtendedNote-Examples * mnuDataTree-Example * mnuDataTree-Pronunciation * mnuDataTree-VariantSpec * mnuDataTree-Picture, which no Avalonia row reaches until the composer loads the generated parts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1207 +/- ##
==========================================
+ Coverage 39.93% 39.99% +0.06%
==========================================
Files 1542 1544 +2
Lines 355165 355256 +91
Branches 41317 41345 +28
==========================================
+ Hits 141833 142087 +254
+ Misses 183999 183839 -160
+ Partials 29333 29330 -3
🚀 New features to boost your workflow:
|
thejambi
approved these changes
Oct 26, 2026
thejambi
left a comment
Contributor
There was a problem hiding this comment.
@thejambi reviewed 10 files and all commit messages, and made 1 comment.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on mark-sil).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Start here:
Src/xWorks/Avalonia/Hosting/RecordEditView.LexiconMenus.cs-- the four new answerers (Move Up/Down, Insert Sound or Movie, Picture Properties) and theCommandActsOnguard, at the end of the file.In Lexicon Edit's Avalonia detail view, the row menus of an etymology, an extended note, a note's examples, an example, a pronunciation, Variant Info and a picture now display and run without the hidden WinForms DataTree. Seven ids switch over (
PinnedOwnedIds41 -> 48). Two shared rules carry the logic, and the legacy handlers now call them:DetailSequenceMove(Move, with the EntryRefs complex-form slot) andMediaFileInsertion(Insert Sound or Movie).Does legacy behave differently now? Only the undo text: "Undo Create Pronuciation" is now spelled correctly and comes from
xWorksStrings. Move enablement, the EntryRefs rule and media link order are unchanged. Legacy appends each pick at the old end of the list, so names land reversed, and the file dialog lists the last pick first.mnuDataTree-Picturehas no Avalonia row yet. The composer never loadsGeneratedParts.xml, which holdsLexSense-Detail-Pictures(LT-22772). The id is owned and proved on a built Caption row against the hidden tree, which does render pictures. The tripwireLexiconMenuAuthorityTests.NoAvaloniaRowBindsThePictureMenu_UntilPicturesComposefails once picture rows compose. Its message lists the clean-up for whoever fixes LT-22772, and every workaround comment is taggedLT-22772.Where to look
DetailSequenceMove.CanMoveUpagainst the oldDTMenuHandlerdisplay rule --DetailSequenceMoveTests.CommandActsOnhiding Delete/Move on the owner rows --DeleteLeaf_IsAbsentWhereTheRowsObjectIsTheOwner, the equivalence contract.InsertSoundOrMovie_OnAnEntryWithoutPronunciations_....Deliberately not here
mnuDataTree-Sense(demote, promote, split): PR E.Verification. Merges into
main, no dependency.build.ps1 -CommentHygiene -TokenHygieneis clean. Targeted runs passed: 56/56 for the authority, execution and media fixtures, 157/157 for the neighbouring menu, integrity and focus fixtures, and the new rule fixtures. A 17-step manual pass in Sena 3 passed in both UIs.Next: approve, or flag a divergence below to revisit.
Reading this a year from now -- start here
Stage 2 PR D1 of LT-22691, which retires the hidden WinForms DataTree command adapter from the Avalonia detail view one context-menu id at a time. The predicate-owned
LexiconMenuAuthorityowns an id once every leaf under it has a native answerer, andLexiconMenuAuthorityTests.PinnedOwnedIdspins the exact owned list. This PR adds four answerers, and the seven ids they complete switch over. No working documents were kept on the branch; the reasoning is below.Deliberate rules
LexEntryRefis a complex form, the second ref cannot move up. The rule covers Move Up only, asDTMenuHandler's display rule always has. It lives inDetailSequenceMove.CanMoveUp, which the legacy handler now calls.RecordEditView.CommandActsOnpasses when the command'sclassNameis the row object's class, or names the owner whosefieldholds the object (the picture commands nameLexSense/Pictures). A command with noclassName, or one naming a class the model lacks (CmdDataTree-Delete-SubentrymisspellsReversalIndexEntry), acts on any object. Delete and Move use it.FocusObjectOnNextShow). Row automation ids are position-based (item0,item1), so a row request would land on the neighbour.xWorksStrings:ksUndoUpdatePicture,ksRedoUpdatePicture,ksUndoCreatePronunciation,ksRedoCreatePronunciation.Avalonia vs legacy divergences
The header rows exist only in Avalonia. #1201 removed the banners over senses, etymologies and extended notes; these two remain. If they go too, three tests that look the banner up fail on purpose and need a small update:
MoveLeaves_FollowThePosition_AndAreAbsentOffAnItemsOwnRows,DeleteLeaf_IsAbsentWhereTheRowsObjectIsTheOwner, and the equivalence contract'sRowIsTheSequencesOwnercase.The LT-22772 picture-row workaround, and its clean-up
DetailComposerloads onlyLanguage Explorer/Configuration/Parts, whileLexSense-Detail-Picturesis inDistFiles/Parts/GeneratedParts.xml(LT-22772, also LT-22856).-Pictureis owned now so that nothing else changes when that is fixed.PictureMenu_IsOfferedForAPicture_AndRendersWhatTheAdapterPathRenderedchecks it against the hidden tree on a built Caption row (PictureRow()), andPictureProperties_PointsThePictureAtTheFileTheUserPicks_InOneUndoableStepruns it end to end.NoAvaloniaRowBindsThePictureMenu_UntilPicturesComposefails once the composed entry has a row bound tomnuDataTree-Picture. Its message lists the clean-up: add-PicturetoLexiconLabelMenuIds; replacePictureRow()and the built row inLexiconMenuExecutionTests; delete the comments taggedLT-22772in both files; delete the test.Decisions, and why
-Picturenow rather than defer it. The answerer is small, and owning it means the LT-22772 fix needs no menu work. The tripwire keeps the workaround from outliving its reason.PicturePropertiesDialogand the media file dialog withMoveOrCopyFilesControllerare reached throughPictureFileChosenandMediaFilesToInsert, asDeleteConfirmationandConversionLossAcceptedare, so every native command runs headlessly in tests.Paths not taken
Evidence
OwnsExactlyThePinnedIds_AndAnswersEveryLeafOfEachOneOwnedMenu_RendersWhatTheAdapterPathRendered_OnEveryLexiconRowThatBindsOneOwnedMenus_AreBuiltWithoutTheAdapterOrTheMediatorDetailSequenceMoveTests(5),VariantInfoMoveUp_IsDisabled_BehindTheComplexForm,MoveVariantInfoUp_MovesTheRef_NeverPastTheComplexFormMediaFileInsertionTests(6), bothInsertSoundOrMovie_*PictureMenu_*,PictureProperties_*DetailRulesBoundaryTestsTwelve new tests in xWorksTests, eleven in FdoUiTests. Manual: a 17-step pass in Sena 3 covering etymology, extended note, note example, example, Variant Info and pronunciation menus in both UIs, plus multi-file media order in legacy. All passed.
Preflight review details
Code Review Summary
Branch: LT-22691r (local claude/lt-22691r-72ec79)
Base: main (merge base c734bff)
Date: 2026-10-26
Review model: Claude (Claude Code)
Files changed: 10 (1 commit)
Overview
Stage 2 PR D1 of LT-22691: the Avalonia detail view answers seven more Lexicon item menus
natively instead of building the hidden WinForms DataTree:
mnuDataTree-Etymology,-ExtendedNote,-ExtendedNote-Examples,-Example,-Pronunciation,-VariantSpecand-Picture. The new answerers are Move Up / Move Down (shared ruleDetailSequenceMove, with theEntryRefs first-slot rule), Insert Sound or Movie (shared rule
MediaFileInsertion) and PictureProperties; Delete and the Inserts were already native. The WinForms Move and Insert Sound or
Movie handlers call the same rules.
The analysis found the implementation complete for every reachable id.
-Picturehas no Avaloniarow until the composer loads
GeneratedParts.xml(LT-22772); it is owned and proved on a builtrow against the hidden tree, and a tripwire test fails once picture rows compose.
Contract/API Changes
SIL.FieldWorks.Common.DetailRules.DetailSequenceMoveandMediaFileInsertion(FdoUi).DTMenuHandler: public handler signatures unchanged; privateInsertMediaFilereshaped; newinternal static
ChooseMediaFiles.xWorksStringskeys:ksUndoUpdatePicture,ksRedoUpdatePicture,ksUndoCreatePronunciation,ksRedoCreatePronunciation.Findings
Critical - Must address before merge
None.
Important - Should address before merge
None.
Minor - Consider
(WinForms behaviour deliberately leftSrc/xWorks/DTMenuHandler.cs: the WinForms Insert Sound or Movie still creates theentry's first pronunciation before the file dialog, so Cancel leaves an empty pronunciation; the
New UI creates it only once files are picked.
unchanged.)
(The dialog isSrc/xWorks/Avalonia/Hosting/RecordEditView.LexiconMenus.cs:EditPicturePropertiesrepeats
PictureSlice.showProperties(dialog plus theUpdatePicturestep).WinForms and stays in each host.)
(Parity rulingRecordEditView.CommandActsOn: Delete and Move are hidden on the Avalonia-only owner rows(Pronunciations header; a note's Examples header and empty-note prompt row).
by the author: those rows' object is the owner, so the item commands do not act there.)
Required Validation / Evidence
./build.ps1 -CommentHygiene -TokenHygiene: clean../test.ps1 -TestFilter(class names, totals checked): LexiconMenuAuthorityTests +LexiconMenuExecutionTests + MediaFileInsertionTests 56/56; DetailSequenceMoveTests,
DetailRulesBoundaryTests, DetailObjectDeletionTests green; DetailObjectCommandExecutionTests,
WindowConfigurationIntegrityTests, DataTreeMoveReachabilityTests, DetailMenuRequestTests,
DetailObjectInsertionTests, DetailFocusMemoryTests, DetailEditorParityTests 157/157.
Positive Observations
Src/FdoUi/DetailRules/under the boundary guard; the WinForms path callsthem, so the two UIs cannot drift.
MediaFilesToInsert,PictureFileChosen), soevery native command is tested end to end headlessly.
Interview Notes
consumer. D2 keeps E6 merge, E10 and E12.
-Pictureis owned now although no Avalonia row reaches it; the author chose authority-levelproof plus a tripwire over deferring the id. LT-22772 is not fixed here.
CommandActsOn) is a parity ruling: WinForms' only precedent for an item id onits owner is the ghost slice.
restored (each link at the old end) on both paths and re-tested.
Suggested Review Focus
DetailSequenceMove.CanMoveUp's EntryRefs rule against the oldDTMenuHandlerdisplay rule.RecordEditView.CommandActsOnand the owner rows it hides Delete and Move on.MediaFileInsertion.Insertordering, and the one-step Undo inInsertMediaFiles.🤖 Generated with Claude Code
This change is