Skip to content

Bug: efc-item-controller-keyboard-registration-defects #459

Description

@drmoisan
  • Work Mode: full-bug

Summary

Three related defects in EfcItemController keyboard-action registration: the KbdActions<> indexer
setter silently drops unregistered keys, the async expansion path never registers or removes the
'B'/'D' jump keys that the sync path does, and the resulting asymmetry can make a later sync
expansion throw ArgumentException.

Environment

  • OS/version: Windows 11 Pro 10.0.26200
  • Runtime: .NET Framework 4.8.1 WinForms VSTO add-in
  • UI path: QuickFiler/Controllers/EfcItemController.cs expansion and keyboard-registration paths
  • Data source or fixture: n/a

Steps to Reproduce

Defect B is the user-visible one:

  1. Open the Email Filer and expand an item through the async expansion path (ToggleExpansionAsync).
  2. Press B or D to jump to the message body / detail.
  3. Observe that the jump keys are not registered.
  4. Now expand through the sync path (ToggleExpansion(ToggleState.On)), collapse through the async
    path, then expand through the sync path again.
  5. Observe an ArgumentException from KbdActions<>.Add.

Expected Behavior

  • RegisterActions registers the actions it is given.
  • The async and sync expansion paths produce the same keyboard-action state.
  • Repeated expand/collapse cycles in any order do not throw.

Actual Behavior

A - RegisterActions registers nothing (EfcItemController.cs:691).
_keyboardHandler.CharActions[action.Key] = action.Value uses the KbdActions<> indexer setter
(KbdActions.cs:38-47), which performs a Find(key) and only assigns when the element is non-null.
A missing key is a silent no-op, not an insert. Combined with the !overwriteDuplicates filter at
:687-690 - which removes exactly the keys that are present - the overwriteDuplicates: false path
is guaranteed to register nothing. RegisterActions currently has zero call sites, so this is latent.

B - async and sync expansion paths are not equivalent (EfcItemController.cs:931-956 vs :862-905).
ToggleExpansion(ToggleState.On) registers 'B'/'D' in CharActions (:879-888) and
ToggleExpansion(Off) removes them (:902-903). ToggleExpansionOn() (:944-956) and
ToggleExpansionOff() (:931-942) - the bodies dispatched by ToggleExpansionAsync (:913, :922) -
do neither.

C - duplicate registration throws (EfcItemController.cs:879-888).
KbdActions<>.Add throws ArgumentException when the (sourceId, key) pair already exists
(KbdActions.cs:92-98). Because of B, a sync-On -> async-Off -> sync-On sequence leaves the
"Item"/'B' and "Item"/'D' entries in place and the second sync-On throws on a UI-thread call path.

Logs / Screenshots

  • Attached minimal logs or screenshot
  • Code-read evidence recorded above (verified 2026-08-07 against the working tree).

Impact / Severity

  • Blocker
  • High
  • Medium
  • Low

Defect C is an unhandled exception on a UI-thread call path. Defect B silently removes documented
keyboard navigation. Defect A is latent today but will surface the moment RegisterActions is wired up.

Source

From: docs/features/potential/2026-08-07-efc-item-controller-keyboard-registration-defects.md

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions