Skip to content

Replace Avalonia entity browser view with HTML-based renderer using ControllableWebViewControl #41

Closed as not planned

Description

@JoshuaRowePhantom

Summary

The entity browser (EntityBrowserWorkspaceTabView) currently renders entities as a tree of native Avalonia EntityCardControl instances inside a ScrollViewer + ItemsControl. The proposal is to replace the entire rendering layer with an HTML surface driven by ControllableWebViewControl / IControllableBrowser, reusing the JS-bridge plumbing already established for the chat output control.

The view is read-only. No Avalonia entity card content is retained. Editing is explicitly out of scope.

Architecture

Replace the ScrollViewer + ItemsControl + EntityCardControl stack with a single ControllableWebViewControl, driven by a new EntityBrowserHtmlModel analogous to ChatOutputHtmlModel:

EntityBrowserWorkspaceTabView
  └── ControllableWebViewControl (IControllableBrowser)
        ↕ JS bridge (JSON commands)
        EntityBrowserHtmlModel
          ├── EntityCardHtmlRenderer  (pure HTML generation, stateless)
          └── EntityCardHtmlTransformer  (collection-change → DOM ops)

FieldEditorFactory and all EntityFieldEditorViewModel subclasses are retained. They already encode all field-type identification and rendering decisions. EntityCardHtmlRenderer reads from the view model tree and emits HTML — it does not re-implement field-type logic.


Rendering decisions

Card shell

Each entity card renders:

  • Header row: DisplayName (title style) + EntityType (muted label)
  • Actions row (top-right): interest badges, status badges, shortcut buttons (in that order)
  • Field list: one row per field editor (see per-type rules below)
  • Cards separated by border radius and card-surface background, matching the existing entity-card style

Interest badges (BadgeModel)

Each BadgeModel has: Glyph, Tooltip, IsActive (bool).

  • Render as small clickable buttons in the header actions row.
  • Active badges are visually highlighted (e.g. filled/accent background).
  • Clicking sends { type: "toggleInterest", interestTypeName: "...", entityId: "..." } to the host.

Status badges (StatusBadgeModel)

Each StatusBadgeModel has: StatusValue (text), BrushKey (color key), Tooltip.

  • Render as colored pills (background color from BrushKey, resolved to a CSS variable at render time).
  • Display-only — not interactive.
  • Tooltip shows the field name (disambiguates multiple status fields).

Shortcuts (EntityShortcutViewModel / Shortcut)

Known shortcuts: Open (↗), Json ({}), Delete (🗑), StartAgentSession (🤖), StartShell (💻).
Each has Label (the glyph/text displayed), HoverText (tooltip), and IsEnabled.

  • Render as small buttons in the header actions row after status badges.
  • Disabled shortcuts are greyed / pointer-events: none.
  • Clicking sends { type: "shortcut", shortcutName: "...", entityId: "..." } to the host.

Field rendering rules by view model type

StringFieldEditorViewModel

  • Render Value as plain text.

BooleanToggleFieldEditorViewModel

  • Render DisplayValue ("true" or "false") as plain text.

LocalStringFieldEditorViewModel

  • Render the active locale's Value as plain text.
  • If IsLocalized, append the active locale tag in muted style.

MimeAttachmentFieldEditorViewModel

  • Inline mode (IsInline == true): render content body only, no field label, no chrome. Used for note content fields.
  • Non-inline mode (ShowChrome == true): render expandable block with mime-type, optional url, and content.
    • text/markdown → Markdown HTML inside the expander.
    • Other mime types → <pre> block inside the expander.

LocalizedMimeAttachmentFieldEditorViewModel

  • Delegate to ActiveEditor following the inline/chrome rules above.
  • If IsLocalized, append active locale tag in muted style.

JsonSchemaFieldEditorViewModel

  • Render MarkdownText (pre-formatted as a ```json ``` fenced block) as Markdown HTML.

EntityReferenceFieldEditorViewModel

  • Render ResolvedDisplayName as a clickable link.
  • Clicking sends { type: "openEntity", entityId: "..." } to host.
  • Tooltip: TooltipText (entity names + id).

EntityListFieldEditorViewModel

  • Render each EntityReferenceListItemViewModel as a clickable link (same openEntity message).
  • Empty list renders as muted "(none)" or is omitted.

ObjectFieldEditorViewModel

  • Render Fields recursively as a nested field list (indented).

ArrayFieldEditorViewModel

  • Render Items recursively as a bulleted list.

Field label rule

  • FieldName shown as a muted prefix for simple scalar fields.
  • Inline mime attachments suppress the label entirely.
  • Object/array fields show the label above the nested content.

Markdown rendering

text/markdown mime fields and JsonSchemaFieldEditorViewModel.MarkdownText are rendered via Markdig with a safe pipeline (no raw HTML), consistent with #37.


Theme propagation

Map Avalonia resource keys → CSS custom properties, send on Ready, re-send on OnActualThemeVariantChanged (not repeating the #38 mistake). CSS variables cover: background, foreground, card-surface, muted, accent, link, status badge colours (good/bad/other).


Incremental updates

EntityBrowserHtmlModel subscribes to EntityListViewModel.Items collection changes. EntityCardHtmlTransformer diffs and emits update/remove/append commands — same CollectionTransformer pattern as ChatMessageHtmlTransformer. Individual field updates diff at the field-editor level using a content key.


Open design questions

  1. Bridge command protocol. Extend ChatOutputBrowserCommands into a shared BrowserCommands (preferred) or define a separate EntityBrowserCommands?
  2. HTML shell. Separate entity-browser-shell.html embedded resource, or a shared shell parameterised at load time?
  3. Status badge colors. BrushKey resolves to an Avalonia brush in the current code. The HTML renderer needs the resolved CSS hex at render time, or a CSS variable per status class (good/bad/other) set via the Theme command.

Affected files (expected)

  • Phantom.Workspaces/Templates/EntityBrowserWorkspaceTabView.axaml — replace with ControllableWebViewControl
  • Phantom.Workspaces/Templates/EntityBrowserWorkspaceTabView.axaml.cs — wiring EntityBrowserHtmlModel
  • Phantom.Workspaces/ViewModels/EntityBrowserHtmlModel.cs — new
  • Phantom.Workspaces/ViewModels/EntityCardHtmlRenderer.cs — new
  • Phantom.Workspaces/Assets/entity-browser-shell.html — new
  • Possibly shared BrowserCommands replacing ChatOutputBrowserCommands

Related

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

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions