Skip to content

Stage J8: DialogService, dialogs in Dialogs/, and a dialog redesign - #117

Merged
uyujkk merged 18 commits into
mainfrom
claude/ui-j8-dialogs
Nov 10, 2026
Merged

uyujkk merged 18 commits into
mainfrom
claude/ui-j8-dialogs

Conversation

@uyujkk

@uyujkk uyujkk commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Summary

Stage J8, done in one pass with design work (docs/development/UI-Structure-Plan.md, J8; docs/development/UI-Fluent-Design-Plan.md, "对话框(J8)"). Before this there were 39 places that built a ContentDialog, in 29 files. The inventory is in the plan.

Structure (no change in behaviour or text)

  • ba0fd46: DialogService.
    • Every dialog now goes through it, which sets the window, theme and default style.
    • Only one dialog shows at a time; the queue logic is in Core (52ba67e, DialogQueueTests).
    • It offers message, confirm, danger confirm, error and text input.
  • d80d38b: App.xaml split.
    • Colours stay in Themes/Tokens.xaml; control styles go to Styles/Controls.xaml, shared page surfaces to Styles/Pages.xaml.
    • Window-only styles move into the window's resources; five unused styles are removed.
  • Pure moves into Dialogs/: 39c5cec 9 short confirmations, 32acfcf 8 previews before a change, 9eecc1c 16 forms and multi-step flows, including the 363-line Endfield settings.

Design (before → after)

  • Buttons (c2e318d): 21 confirmations said "确定/Confirm" and 10 name prompts said "OK" → each main button names its action (Delete, Replace, Restore, Rename, Save, Install…).
  • Destructive actions (c2e318d, 894c5a9):
    • 14 delete, remove and overwrite dialogs → a filled red button in a fixed danger colour that never follows the accent. They have no default button and keyboard focus is on Cancel, so Enter and Esc both cancel.
    • The workspace's "Remove from target folder" uses the same red.
    • This fixes primary and destructive buttons looking alike with a red system accent.
  • Previews (5d128e3): restoring a preset, installing a bundle and the organized import showed one flat list → groups with counts (will add / will remove / kept / skipped).
  • Forms (7c9c212):
    • The Endfield settings use card sections in the Windows Settings style.
    • Validation errors sit in red right under their field.
    • Multi-step flows show "Step n of m" and a progress bar.
    • Long content scrolls after 400 px.
  • Errors (e16d7ae, 894c5a9): error notifications and error dialogs get "View details" (exception type and code, message, stack and log path) with a copy button.
  • Command palette (a10bc83): headings for pages, characters, Mods and commands, plus a shadow.
  • Title bar (dfb35db): below 1120 px wide the search box becomes an icon button that opens the palette.
  • Not done: replacing some notice dialogs with an InfoBar or TeachingTip (Fluent plan item 4).

Fixes from the maintainer's try of the package

  • e938a7a: step 2 of the getting-started tips opened outside the window. It opened while the page was still scrolling to the path settings and was placed beside that full-width card.

    • The page now scrolls first, then the tip opens.
    • A placement rule in Core (TipPlacementPolicyTests) opens it below its target, else above, else in the middle of the page, never to the side, and keeps it inside the window.
  • 16d4c56: selection felt laggy. Every page switch re-applied all interface text, refreshed every page and saved settings before the new selection could show. The page and its selection now show first and the rest runs right after. The page-entrance animation is lighter (70% start opacity, 6 px, 110/130 ms); "Reduce motion" still turns it off.

    Median from a real mouse click until the selection shows:

    Where Before After
    Dashboard 54 ms 36 ms
    Mod workspace 88 ms 67 ms
    Online 56 ms 25 ms
    Updates 53 ms 43 ms
    Shortcuts 63 ms 42 ms
    Settings 97 ms 16 ms
    Settings card switch 119 ms 105 ms (not improved, cause unconfirmed)

    A delayed settings save was tried and dropped because it made no measurable difference.

  • df0f391: a test that a setting changed just before closing is still there after a restart.

MainWindow partial files: 21,406 → 20,073 lines.

Test plan

  • scripts\test-all.ps1: 1,753 Core tests, Release build 0 warnings, Core coverage 94.0% line / 88.3% branch
  • UI tests 52/52 on the same build (-Application). New tests:
    • DangerConfirm_CancelIsTheDefaultAndEscDoesNothing.
    • Getting-started tips stay inside the window: zh/en/ru at 1000×800 with paths folded and expanded, Russian at 1400×900 and maximized, and real first installs.
    • A setting changed just before closing is kept.
  • Code-style check
  • Screenshots: 36 for the dialogs, palette and title bar (zh/en/ru × light/dark), plus 27 for the tips. No Russian truncation.
  • Full package driven with the real mouse:
    • all three tip steps inside the window;
    • 26 page switches and 20 rapid clicks between the workspace lists;
    • 5 Updates view switches;
    • the delete, restore-preview and rename dialogs and the command palette.
    • No errors were logged.
  • The Updates view switcher and the filter weren't measured: the tool couldn't detect the switch, and the test data doesn't show the filter.

🤖 Generated with Claude Code

uyujkk and others added 18 commits November 9, 2026 14:17
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DialogService now sets the XamlRoot, theme and DefaultContentDialogStyle
and queues dialogs so only one is open at a time; a dialog closed while
still queued (progress dialogs) is skipped. It builds the common message,
confirmation, dangerous confirmation, error and text-input dialogs; the
window's ShowMessageAsync, ShowConfirmAsync and PromptForTextAsync forward
to it, and all 39 dialogs are shown by it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Control styles (text, status badges, buttons, the shortcut input) go to
Styles/Controls.xaml and the page surfaces shared by several pages (card,
page header, inset) to Styles/Pages.xaml; colours stay in
Themes/Tokens.xaml. Styles only the window's own XAML uses (command
surface, detail pane, sticky action, metric card and value, list views)
move into its RootGrid resources. Five styles nothing used are removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pure move, same texts and behaviour: restarting a restored download,
download options, an existing online installation, install conflicts,
reading the existing file (Shortcuts overlay), menu-state variables,
Mod updates available, what's new, and the Mod details pane shown as a
dialog. Each is a class in Dialogs/ that gets the data and returns the
answer; the window keeps what happens with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pure move, same texts and behaviour: broken Mod links, restoring a state
slot or a user.ini snapshot (with the shared "apply while running"
option), importing a shared preset, restoring a combination preset (its
row texts, the choice enum and the preview row record move with it) and
installing a combination bundle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pure move, same texts and behaviour: organized import (destination,
preview, progress, undo, interrupted imports), local tags, character
avatar binding, the overlay's single-Mod preset, batch Mod actions, the
character region, update and replace, the download file picker, the
download location, the category mapping, authors and saved Mods, batch
downloads (reading and review) and the Endfield launch settings (J4 left
it in the window). Each class gets its data, and a small Host record of
window actions where the dialog itself triggers them; the window keeps
what is saved and run afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Confirmation and name dialogs say what their main button does (Delete,
Remove, Replace, Restore, Create, Rename, Save, Export, Install...)
instead of OK or Confirm; the avatar binding says Bind.

Delete, remove and overwrite confirmations (14: Mods, presets, state
slots, repositories, external folders, tracking records, broken links,
undo of a deployment or an import, writing Mod defaults, restoring a
backup, replacing a Mod with its update) get a filled button in a fixed
red that never follows the accent colour, and Cancel is the default
button, so Enter and Esc cancel. The workspace's "Remove from target"
uses the same red; "Deploy" keeps the accent. Other confirmations make
their action the default. Text dialogs scroll after 400 px.

New strings in zh-CN, en-US and ru-RU; Dialogs.Confirm is no longer used
and removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The previews before restoring a combination preset, installing a bundle
and an organized import list their items in groups headed with a count:
added, removed, kept and skipped (empty groups are left out), with the
action under each item and its path as a tooltip, instead of one flat
list. The import preview's list scrolls inside the dialog. New group
headings in zh-CN, en-US and ru-RU.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Endfield launch settings group launch method, game and loader, and
checks into cards like Windows Settings (DialogLayout.Section), with
hints in the secondary text style; a launch profile that cannot be saved
is reported beside the launch settings as well as in the result area.
Validation messages of the tags, batch Mod actions and single-Mod preset
dialogs, and a library folder that does not exist in the organized
import, show in the critical colour right under their field. The
organized import (3 dialogs) and batch downloads (2) show which step the
dialog is, and their running steps show a progress bar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An error notification of a failed action and the error dialogs of online
actions now offer "View details": the exception type and code, its
message and stack, and the path of app-errors.log, read-only and with a
copy button for a report. The notification keeps its short message; the
status service carries the failure along. New strings in zh-CN, en-US
and ru-RU.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Results are grouped under Pages, Characters, Mods and Commands headings,
each keeping the search ranking; the headings are not selectable and the
arrow keys skip them. The panel casts the system ThemeShadow onto a
transparent layer over the dimmed window (outside a popup a ThemeShadow
needs such a receiver). New headings in zh-CN, en-US and ru-RU.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At 1000 px and other widths below the compact navigation threshold the
search box gives way to a search icon button with the same name and
tooltip, which opens the command palette; turning the search off in
Settings hides both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The queue behind DialogService moves to Core (DialogQueue) with unit
tests: a second dialog waits until the first closes, one closed before
its turn is skipped, and a dialog that fails to open does not block the
next. A dangerous dialog also moves the keyboard focus to Cancel when it
opens. UI test: deleting a combination preset opens with Cancel focused,
and Esc or Enter close the dialog with the preset kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…etails

The screenshots showed two things. ContentDialog draws its default button
in the accent colour, so with Cancel as the default and a red system
accent, Cancel looked like the red Delete button beside it. Dangerous
dialogs now have no default button; Cancel takes the keyboard focus just
after the dialog opens, so Enter and Esc both cancel. And the error
details showed only their first line in a read-only TextBox; they are now
selectable wrapped text that scrolls after 200 px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The user saw step 2 (the path settings) open outside the window. The tip
opened in the same pass that started scrolling its target into view, so
it was placed against where the path settings had been, and Auto
placement put it beside the full-width card, past the window's left edge.

Now the page scrolls the target into view without animation, leaving at
least a tip's height above it, the layout is brought up to date, and
only then is the tip placed and opened. TipPlacementPolicy (Core, unit
tested) opens it below the target when the whole target and the tip fit,
above it when its top edge is visible (so the tall opened path settings
are pointed at from above), and otherwise in the middle of the page
pointing at nothing; never beside it. The tip is constrained to the
window.

UI tests: each step's text and buttons lie inside the window and step 2
sits next to the path settings, in zh-CN, en-US and ru-RU at 1000x800
(path settings folded and opened), in ru-RU at 1400x900 and maximized,
and after real first installs (a game chosen or "later") at 1000x800,
maximized and 1400x900.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A page switch ran ApplyLanguage, every page's refresh and a settings
save before the new selection could render: 50-105 ms between the click
and the selection on every switch. Now the page and the navigation
selection change at once and the refreshes run right after that frame
(a newer switch replaces a refresh that has not run yet, keeping a
pending list refresh). The entrance animation starts mostly visible and
is shorter: from 70 % opacity and 6 px over 110/130 ms instead of 25 %,
12 px and 170/210 ms; reduce motion still turns it off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant