Skip to content

feat: editable adversary name in runner with uniqueness validation (#68)#76

Merged
gwillish merged 3 commits into
mainfrom
feat/editable-adversary-name
Apr 12, 2026
Merged

feat: editable adversary name in runner with uniqueness validation (#68)#76
gwillish merged 3 commits into
mainfrom
feat/editable-adversary-name

Conversation

@gwillish
Copy link
Copy Markdown
Owner

@gwillish gwillish commented Apr 11, 2026

Summary

  • Tap the adversary name in the expanded AdversaryRunnerCard header to rename it inline
  • On commit, validates that the trimmed name is non-empty and unique across all slots in the session; shows "Name already in use" inline on conflict
  • Empty/whitespace input reverts silently (no error)
  • Cancel discards the pending edit without changing state
  • Display updates immediately in both the expanded card and the collapsed row — propagated automatically through @Observable EncounterSession
  • Mutation routes through EncounterSession.renameAdversary(id:name:) (added in feat: add renameAdversary(id:name:) to EncounterSession DHModels#23); the view does not write to AdversaryState directly

Package update

Depends on gwillish/DHModels#23 (already merged). Package.resolved is gitignored; Xcode will pick up the new renameAdversary method on next resolve from main.

Test plan

  • All unit tests pass (xcodebuild test -scheme Encounter -destination 'platform=macOS')
  • Tap adversary name in expanded card → TextField appears pre-filled with current name
  • Type a new unique name, tap Done → card header and collapsed row both update immediately
  • Press Return/Enter → same as Done
  • Type a name already used by another slot → "Name already in use" error appears inline
  • Clear the field, tap Done → reverts silently to previous name
  • Tap Cancel → reverts with no change, no error
  • Collapse button remains accessible during normal (non-editing) state

Closes #68

Tap the adversary name in the expanded card to rename it inline.
Validates that the trimmed name is non-empty and unique across all
slots; shows an inline error on conflict. Empty input reverts silently.
Mutation routes through EncounterSession.renameAdversary(id:name:).
Covers all 7 items from the test plan: tap-to-edit, Done button,
Return key, duplicate name error, empty-field revert, Cancel revert,
and collapse button accessibility. Includes a two-same-adversary
navigation helper for the uniqueness validation scenario.
- AdversaryRunnerCard: add @focusstate for immediate keyboard focus on
  rename, add AX identifiers to Done/Cancel buttons, clean up nameError init
- AdversaryRunnerSection: include active conditions in collapsed row
  accessibilityLabel (PR #75 broke this by switching from accessibilityValue
  to an explicit label that omitted condition state)
- EncounterUITestCase: new shared base class for RunnerUITests and
  RenameAdversaryUITests, eliminating ~180 lines of duplicated helpers
- Navigation helpers: fix iOS 26 toolbar overflow — builder toolbar items
  collapse into OverflowBarButtonItem; use builder.add-adversary-button
  (in-form) for compendium and tap overflow before "Run Encounter"
- replaceText: remove redundant initial tap on iOS; triple-tap alone
  handles both pre-focused (@focusstate) and unfocused states correctly

All 9 iOS UI tests and all macOS unit tests pass.
@gwillish gwillish merged commit 38af06a into main Apr 12, 2026
@gwillish gwillish deleted the feat/editable-adversary-name branch April 12, 2026 01:28
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.

Editable adversary name in runner with uniqueness validation

1 participant