Repository navigation
UX: fix-now batch, layout model, Client registry, trigger builder, Light settings - #96
Draft
HarryCordewener wants to merge 50 commits into
Draft
HarryCordewener wants to merge 50 commits into
HarryCordewener wants to merge 50 commits into
Conversation
The status row wrapped to a second row at 80x24, the meters vanished below 120 columns, and F2/F4 drew their editors off the right-hand edge at 80. The status row now drops its encoding and palette hints before wrapping, meters fall back to a compact percentage form, two-column screens too narrow for both columns show the one the keyboard is in, and header/footer bars elide text rather than clipping their keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
--plain had no way to add a world on a first run: the settings screens are not usable there. /connect <host> [port] [tls] saves a new world and dials it; /connect <name> opens a configured one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
A machine with no Nerd Font installed drew every chrome icon in the window as a box, and text fell back to whatever monospace face the system had. The window now carries JetBrains Mono (OFL 1.1) and Symbols Nerd Font Mono (MIT) as embedded resources, used after any preferred installed face, and ships their licences beside the executable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
A header too narrow for its hints now shortens them from the middle, so the key that closes the screen stays on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
|
… availability Core only, no UI wiring. A layout (Layouts/LayoutDefinition) places panels by id in regions with an order, a relative size, a collapsed flag and an optional tab host. Roleplay and Combat are built in and read-only; LayoutLibrary saves, updates, renames and deletes the player's layouts in AppConfiguration.Layouts, turning an update of a built-in into a saved copy. LayoutResolver picks the character's layout, then the world's, then the world's accepted suggestion, then Roleplay, passing over ids that name nothing. LayoutSuggester suggests Combat on vitals and Roleplay otherwise, saying whether the MSSP codebase was a MUSH-family one. PanelAvailability says which panels have data for a session, and LayoutFold folds a layout into the workspace's own split tree. New config fields are optional with old-behaviour defaults, so no migration and no schema version change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…mands from it A new UI-agnostic project, SharpMUTerm.Client (Core only), holds the shared client shell's first piece: ContributionRegistry, with six kinds of contribution (commands, panels, settings sections, status cells, overlays, output decorators), each with a stable id unique within its kind and an owner. The built-in ⌃P catalog moves out of Core's CommandCatalog.Build into BuiltInCommands, registered as contributions; the Tui supplies the work (RunBuiltInCommand). The command surface, the pointer menu and DispatchCommand all read the registry, so a package or host can add commands. The catalog is unchanged entry for entry. New suite: SharpMUTerm.Client.Tests (in CI). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…match kinds, and a live test on F2 Ctrl+P > "Make a trigger from the selection" (and the output right-click menu) makes a rule from the selected line, with numbers, quoted speech and known GMCP player names turned into * wildcards, and opens F2 on it with the pattern being typed and the regex shown behind it. Triggers gain a match type (contains the text, starts with, * wildcards, regular expression; regex stays the default), and F2's pattern editor shows how many of the last 2,000 held lines match, with the newest three highlighted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…ind readers Settings screens (D6): ScreenPalette's constants become roles spelt as the Dark theme's values. A new immutable ScreenTheme, built once from the app's theme, resolves renderer markup and control colours at the view boundary (ScreenChrome.Panel/Band/VerticalRule, ScreenTheme.Colour), so renderers and their tests are untouched and there is no mutable global. Dark resolves to the constants byte for byte; Light mirrors L*, Solarized takes its background's hue, and every ink is held to Contrast.Floor on its planes. Threaded through every *ScreenView.Build (required), SettingsOverlay, ComposeOverlay, ListOverlay and EditReviewOverlay. FrameContrastTests gains 13 settings views on all three themes; ScreenThemeTests checks that no Light settings frame paints a dark-palette plane. Tints: ColourVision (Core) simulates protanopia/deuteranopia/tritanopia (Machado 2009) and measures CIEDE2000. The ten anchors were re-picked within 40 degrees of each name: the worst dichromat pair goes from 0.28 to 1.99, and the worst pair for typical vision from 3.71 to 3.96. TintColourVisionTests holds 1.9 / 3.5 on all themes. Names kept. A tinted character's rail and tab tooltips name the colour, at no cell cost. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…hread-izbu0c # Conflicts: # CHANGELOG.md
…rnings The palette's ranking and grouping move into SharpMUTerm.Client (CommandPaletteModel, FuzzyMatch, RecentCommands, KeyGlyphs) so the window's palette can list the same rows; Core's CommandMatcher is removed. Matching is word-by-word subsequence with word-start/consecutive/prefix scoring and highlighted matches. An empty query lists RECENT (in memory, eight) and SUGGESTED (from CommandContext) before the groups. Keys sit in a right-aligned column in one glyph vocabulary and are never elided. F4 marks a binding that wins over a client key (MacroKeys.YieldedBy) with an amber triangle and a shadowed duplicate as dead; ⌃P lists "Key clashes (N)" while N > 0. New snapshot views menu-fuzzy and menu-recent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…uggestion A character's resolved layout is realised as one pane per panel that has data (LayoutFold -> LayoutRealiser -> WorkspaceLayout.ReplaceTree); output, chat and map are the existing windows, every other panel a panel:<id>:<key> window whose control comes from a factory registered in TerminalPanels. Re-folds are rate limited and rebuild only when the drawn panels change, and stop once the player rearranges the panes. A restored workspace wins at startup; only the live entry point applies layouts on its own. Alt+M and Ctrl+P > Layouts open the list (apply, save changes, save as new, use for world/character); F5 gains a layout row on worlds and characters; a world's first connect accepts a suggestion and says so once. LayoutCapture reads an arrangement back into placements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…hread-izbu0c # Conflicts: # CHANGELOG.md
…, meter table F7 and F8 are drawn from settings sections declared in SharpMUTerm.Client (BuiltInSettings): each field has a group heading and a SettingBinding over the configuration, whose default is read off a fresh AppConfiguration. F7 is now "Text & display", grouped under Colour & legibility, Text, Links & pictures, Status row & meters, Activity and Sound, and windowed to the screen height so nothing runs off a 24-row terminal. - `/` on any settings screen opens a search over every declared field and every screen title, with a per-section match count; Enter goes to the field on its own screen, Esc puts the screen back. - A field away from its default is marked "● changed"; `r` resets it through the same save funnel. The header names `r reset` only there. - F7's meters are a table: label, value path, maximum path and a live `now` column from the focused session's game data, [+ meter], Delete to remove, a box of received paths while the cursor is in the table, and the path fields offer those paths with their values. Snapshot views settings-search, settings-meters, settings-meters-pick and settings-changed, in the parity list and FrameContrastTests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…hread-izbu0c # Conflicts: # CHANGELOG.md # src/SharpMUTerm.Tui/SharpMUTermApp.cs
Four panels plug into the layouts seam (TerminalPanels.Register from RegisterTerminalPanels): who is here from GMCP Room.Players and the room's item list (a click puts look <name> on the command line), a one-row vitals strip of reserved fields with bars, values, a low mark and the combat target, a quick bar of function-key macros run through the key's own path, and the F1 editor docked as a pane sharing F1's draft. While the composer's pane is in front it is armed: the focus pin targets its editor, Esc hands the keyboard back to the command line, and arriving at the pane arms it again. Each is on Ctrl+P and has a snapshot view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…hread-izbu0c # Conflicts: # CHANGELOG.md
A headless app runs OnUiThread inline, so the picture host's deliveries ran on the thread pool while the test or snapshot appended the next line. The reserved-picture draw and the append that reads ReservedPicture.Drawn raced over the pane buffer, and a row could be left blank: the intermittent APictureStopsAtTheFirstLineWithoutItsCells. Headless picture work is now queued and run at the next frame or while InlineImagesSettled is awaited. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
… cells The window host draws native views in a layer above the cell view, fed through IPointerPresenter (the scrollbars' channel): a Layouts button over the header's three trailing blank cells, whose menu is built by the client from the layout library's registry commands; native vitals gauges drawn from the VitalsModel the cell strip now renders from; and a native map canvas (zoom, pan, click to walk through the client's speedwalk). The cells underneath are unchanged, so no pane rectangle moves and host parity is untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
Scrolling a pane back now splits it inside its own rectangle: the history
being read on top, a band ("scrolled back N rows · End returns · ⌥F
freezes"), and the newest lines still arriving below. It reuses freeze's
two-viewport layout with the window's own control and viewport kept on top,
so the scroll keys, wheel, search landing and status row are unchanged; the
tail is a re-fed copy of the buffer's last lines and indexes nothing. A
split pane is not "scrolled back" for unread badging. F7 ▸ SCROLLBACK turns
it off.
F5 ▸ join wraps (per world, off by default) joins rows a server broke at
its own column, at ingest and before the triggers, through a conservative
ServerWrapJoiner: full row, unpunctuated end, lower-case continuation, same
style, no prompts, structure or column layouts. A full row is held until
the next line or 250 ms of quiet.
New snapshot views: scrollback-split, reflow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
The vitals strip and the quick bar are exactly one row, with no tab strip over a one-tab strip, and the docked composer has an editor's floor. A pane's height claim (PaneNode.FixedRows/MinRows) is derived from what it holds on every rebuild (PanelSizing) and honoured by the grid and by LayoutSolver (PaneExtent.DistributeRows); a divider beside a fixed strip neither hovers nor drags, and the resize keys take rows from a pane beyond it or refuse out loud. The status row leaves its meters out while the vitals strip is showing them. Layout panels are WindowKind.Panel: no rail row, no Alt+number, no Go to entry, so map and capture windows keep their digits. Alt+M renames (r) and deletes (d, then y) saved layouts. New snapshot view: layout-roleplay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…hread-izbu0c # Conflicts: # CHANGELOG.md
…onnect A client with no worlds opens on a welcome: connect to a host (a form that goes through /connect's own path, adding the character it names), browse games from the package index (still fetched only when asked; says so in place when no index is set), or open F5, with the /connect line spelt out and a starting layout to pick (suggested by default, so the client's suggestion still applies). Esc closes it for the run; /welcome and Ctrl+P > Welcome reopen it. Under --plain (ClientHost.ScreenIsSeen false) the choices are announced as commands and /welcome layout picks the layout. The first connect of a configuration that started empty puts one chrome row naming Ctrl+P, Alt+M, F1 and F5, owed through AppConfiguration.KeyTourPending so it is shown once and survives a restart. Ctrl+P > Key tour hides and shows it. Snapshot views welcome, welcome-connect and tour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…hread-izbu0c # Conflicts: # CHANGELOG.md # src/SharpMUTerm.Tui/ListOverlay.cs # tests/SharpMUTerm.Tui.Tests/FrameContrastTests.cs
In a stacked split no row is spent on a divider above a pane that draws its own tab strip: the strip is the boundary, and its empty run past the last tab is the divider's handle (hover cue, drag, double-click to even, tooltip). Fixed strip panels sit flush with no divider on either side and, unfocused, are recessed a step so they never share an unfocused pane's plane. Side by side is unchanged. The freed rows go to the panes (a NAWS change). PaneExtent.DividerRows is the one rule, read by LayoutSolver, PaneExtent, PaneResize and the terminal's grid. Adds the split-stacked snapshot view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
Built from the Client setting declarations, with the shared search, reset and meter table. Other sections open their cell screens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…he window HeaderModel and SidebarModel (Client) are what the cell header and rail are rendered from, and what the window's NativeHeader and NativeSidebar draw over those cells. Clicks hand back the model's own targets to the rail's handler and the palette; cells, frames and pane rectangles are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
The window draws a native who-here list (presence dots, idle text, NPCs dimmed, hover plate, full-name tooltip) and native quick-bar buttons (+N overflow menu, F4 edits keys link) over their panes, from new host-neutral WhoHereModel/QuickBarModel in SharpMUTerm.Client that the cell renderers now draw from too. A click is PanelOverlay.Pick(index), read back by the client from what it published and acted on through the cell links' own methods on the panel's character; the window builds no command and never takes keyboard focus. Native panels are withdrawn while a modal is open, so they no longer sit on top of F4 or Ctrl+P. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…hread-izbu0c # Conflicts: # src/SharpMUTerm.Avalonia/DesktopLayer.cs
The window host gets ClientHost.NativePalette (INativePalette, null in the terminal, snapshot, tests and parity harness). ToggleMenu/OpenMenu are the one funnel: Ctrl+P, the native header's search box and brand, the pointer menu's new "More commands..." entry and the menu* views all ask the host first. The client captures a PaletteSession (Client) on its own thread; the window's PaletteOverlay filters it with CommandPaletteModel, so both hosts list the same rows, and runs the chosen id back through RunFromPalette so recents are recorded identically. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…09104d18e798 # Conflicts: # src/SharpMUTerm.Avalonia/MainWindow.cs # src/SharpMUTerm.Avalonia/WindowHost.cs # src/SharpMUTerm.Tui/Hosting/ClientHost.cs # src/SharpMUTerm.Tui/SharpMUTermApp.cs # tests/SharpMUTerm.Avalonia.Tests/HostParityTests.cs
ClientHost.Chrome (HostChrome(Header, Rail), required) says which chrome the host draws; the client then leaves no cell for it (hidden header band, no rail column), so the veto, the layout, PaneOutputRects and per-pane NAWS follow from arranged bounds. The window draws a 42 px header and a 232 px sidebar (48 px folded) and moves TerminalView into what is left; modals draw in the cell area with the chrome inert beside them, and an armed Ctrl+B shows its keys in the native header. The header's search box opens the palette and a second click while it is up is not a refusal. HostParityTests compares both hosts under both arrangements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
SurfaceCatalog (Client/Surfaces) declares every surface a host may draw with its own controls - header, sidebar, folded rail strip, armed Ctrl+B keymap, vitals, map, who-here, quick bar, settings, the Layouts menu and Ctrl+P - with its Client model, its actions and the client method each ends in, how each host draws it, its cell renderer and its native views. Three suites hold the hosts to it: - SurfaceCatalogTests (Client): ids, hosts, models in Client/Core, a native-only door names where the cells offer it. - SurfaceCellTests (Tui): every cell renderer takes its model, every action's method exists, every command resolves; F4's terminal verdicts. - SurfaceParityTests (Avalonia): every Control in the window is declared and handed its model; each native model equals the one the cells drew in the same frame; each native action and its cell link leave two clients in the same state; F4 and the quick bar's window verdicts. F4 and the quick bar are per host: MacroKeys.Verdict and the keypad, clash and quick-bar code take HostKeys, and HostKeys.ReportsChordsWhole says the window delivers Ctrl+digit and friends as themselves. Divergences fixed on the way: the quick bar's "F4 edits keys" is a cell link too; the map's anchor with no current room is one rule (and the native map gets the model instance the cells drew); the Layouts menu is a MenuModel whose choices come back through HeaderAction.Dispatch and are refused unless offered; the Ctrl+B keymap is one model (exit hint included) for the cell panel and the native header; the sidebar's fold button has a Ctrl+P command, layout:toggle-rail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…us row Below 100 columns the connection rail folds itself to its strip (whichever rail is drawn, through SidebarModel.Collapsed; the window measures its whole width via IPointerPresenter.WindowColumns so the fold cannot undo itself), acting only when the width crosses the line so a player's own fold wins. Below 100 columns or 30 rows an empty command line is one row and grows as before; a growing bar now takes back the editor's scroll. While the focused pane is scrolled back, split, frozen, carrying the search bar, or a docked composer holds the keyboard, the status row names that mode's keys (ModeHints, Client), resolved through the host's spellings, in place of the pane hints and only where they fit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
… both maps A notice is now a Client model (NoticeModel: text, severity, optional action command, time). The terminal draws the status row from it exactly as before; the window also shows it as a toast bottom-right above the pane area, held while hovered, faded after six seconds, never focused, and a click runs its action through the registry (refused unless a notice offered it). Declared as the `notice` surface with model and action probes in SurfaceParityTests. MapViewModel carries area colours (MapAreaPalette: stable per area name, dark and light sets that clear the floor on every theme), stairs flags and the area an exit leads to. The cell map colours rooms through Contrast.Legible and draws a one-line legend; the native map adds names at zoom, a hover plate, stairs marks, a current-room halo and a legend. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…hread-izbu0c # Conflicts: # CHANGELOG.md # src/SharpMUTerm.Tui/Pointer/PointerTarget.cs
F7 opens with a THEME group: one row per theme (built-ins, the customised theme in force, CustomThemes) with a seven-row preview of the theme under the cursor - an ANSI pane, the focused pane with a tab strip, a tinted pane and the armed command line - drawn from one Client model (ThemePreview / ThemeCard, built by Tui ThemePreviews). Moving the cursor paints the screen in that theme; Esc closes with nothing committed; Enter commits through ScreenEdits.Apply, and SaveConfiguration puts the new theme into force (ApplyThemeIfChanged / ApplyTheme), with a notice that output already on screen keeps its colours. The desktop settings window draws the same model as native cards (ThemeCardView); a click uses the theme and the window follows the variant. SettingBinding now reads a SettingTarget (configuration, world, character) with ForWorld/ForCharacter factories and a section Scope. F5's world fields and F9's character fields are declared (BuiltInSettings.World and .Character) with TextRules shared by both surfaces. The cell F5 builds its world, security and character rows from those declarations in its own ordinal order; the settings window edits them with a subject picker and a door to the cell screen for the lists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…hread-izbu0c # Conflicts: # CHANGELOG.md
A theme change now formats every pane line again against the new reading plane, in place: a PaneLine keeps the StyledLine it was formatted from (Source) and a chrome bar the function that draws it (Bar), so freeze, away/missed/search bars, picture anchors and the selection all survive. About 106 ms and 743 KiB at the 2,000-line pane cap. Space on a theme row does what Enter does. Alt+C moves the keyboard into the connection sidebar in both hosts (SidebarModel.Cursor, layout:rail-keys, the rail-keys view): arrows, Home and End walk, Enter goes, Esc or any other key returns. The cell rail bands the row; the native sidebar rings it. The native sidebar scrolls with the wheel and an overlay bar, and a right click on a row opens the client's menu of registry commands for it (SidebarRowMenu), which the cell rail's pointer menu also uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
F1 opens a native TextBox editor over the cell area and the docked composer is a native editor over its pane, both drawn from one Client ComposerModel (target, draft, escaping, MOO edit, dictionary, marks as ranges, key row) that the cell composers now render from too. Gestures go back through a ComposerSession to the methods the cell keys end in, so ⌃S sends the same command (ComposeMessage.Build) and a MOO edit saves its lines. Misspellings get a real wavy underline from the same SpellChecker, with suggestions and Add to dictionary in the right-click menu. New host member ClientHost.NativeComposer (INativeComposer); the terminal, headless and snapshot hosts pass null. Declared in the surface catalog (compose, composer) with model comparison and wire-level outcome probes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…il editor A list declaration kind in Client (SettingsCollection, item-scoped bindings, SettingsContext): add, duplicate, delete, reorder, enable and move to another set, every change through the form's one commit and replacing lists rather than editing them. Package sets are listed read-only with copy-to-edit. The cell screens build their rows from the declarations with every ordinal and frame unchanged, plus Alt+Up/Down to move an item within its set. The desktop window draws each list section as a master-detail editor with the F2 live test under the pattern, and the trigger builder opens it on the new rule. F4's key field asks the host's own MacroKeys verdict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
…f1f08ec52caa # Conflicts: # CHANGELOG.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx
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.
Requested by Grave · project thread
The fix-now batch from the UX audit, plus the first wave of the UX plan.
What changed
Fix-now batch
82/100does not fit they show82%instead.ScreenChrome.TooNarrowForTwoandSingle) instead of drawing their editors off the right edge.SpreadTitle) shorten from the middle, so the close key stays./connect <host> [port] [tls]saves a world and dials it./connect <name>opens a world that is already configured.sharpmuterm-window, with their licences copied tolicenses/.Wave 1
Core/Layouts):config.jsonlayouts).WorldDefinition.LayoutandCharacterDefinition.Layout.LayoutResolvertries the character's layout, then the world's, then the accepted suggestion, then Roleplay.LayoutSuggestersuggests Combat when vitals arrive, and Roleplay when MSSP reports a MUSH-family codebase.PanelAvailabilitysays which panels have data yet.LayoutFoldturns a layout into the existingPaneNode/SplitNodetree.SharpMUTerm.Client, a new project with no UI dependencies:ContributionRegistrywith six kinds: commands, panels, settings sections, status cells, overlays and output decorators.DispatchCommandnow read their commands from the registry. The catalog was checked against the old one across 12,288 states before the old one was deleted.SharpMUTerm.Client.Tests, also added toci.yml.Trigger.MatchType: contains, starts with,*wildcards, or regex. Regex is the default, so old configs load unchanged.trigger-builder.ScreenThemeis passed through every view; there is no global state. Dark is byte-identical.FrameContrastTests.Testing
dotnet build -c Release SharpMUTerm.slnx: 0 errors.AReadOnlyCacheDirectory_DegradesToMemoryOnlyfails only because this sandbox runs as root.🤖 Generated with Claude Code
https://claude.ai/code/session_01Rqqt7SPYixp6Cg4JDKRTwx