first commit
This commit is contained in:
+8
@@ -0,0 +1,8 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/agents/agents_tab_controls
|
||||
title: Agents Tab Controls (WPF Views)
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/Agents/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
Flat collection of WPF `UserControl` subclasses in namespace `ClassicAssist.UI.Views.Agents`, each paired with a `.xaml` + code-behind file. Code-behinds are minimal stubs inheriting from `System.Windows.Controls.UserControl` and only calling `InitializeComponent()`, delegating all logic to ViewModels defined under `ClassicAssist.Shared.UI.ViewModels.Agents` (e.g. `AutolootViewModel`). The XAML files declare the view's data context via `<agents:AutolootViewModel />` and compose shared UI building blocks from `ClassicAssist.UI.Controls`, `ClassicAssist.UI.Misc` behaviors (`ClipboardBehaviour`, `ItemsControlSelectNewEntryBehaviour`, `ListViewMultiSelectionBehaviour`), value converters, and localized strings from `ClassicAssist.Shared.Resources`. Each tab is a self-contained presentation layer with no cross-tab dependencies; consumers assemble them at a higher level (the agents tab host).
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
- Code-behind classes are empty stubs that inherit from `UserControl` and call only `InitializeComponent()`; all state and commands live in the ViewModel.
|
||||
- Each tab's XAML sets its `DataContext` inline by instantiating the matching ViewModel type from `ClassicAssist.Shared.UI.ViewModels.Agents` rather than using a DI container.
|
||||
- UI text is sourced through `{x:Static resources:Strings.*}` from `ClassicAssist.Shared.Resources` instead of hard-coded strings.
|
||||
- Reusable interactions are implemented as attached behaviors in `ClassicAssist.UI.Misc` (e.g. `ClipboardBehaviour`, `ItemsControlSelectNewEntryBehaviour`) applied via `i:Interaction.Behaviors`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF UserControl views that present the individual agent tabs — autoloot, counters, dress, friends, organizer, scavenger, and vendor buy/sell — bound to their corresponding ViewModels.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF (`System.Windows.Controls`) with XAML markup, Microsoft.Xaml.Behaviors for `Interaction.Behaviors`, and MVVM binding against ViewModels in the separate `ClassicAssist.Shared` assembly.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/agents/autoloot
|
||||
title: Autoloot Property Selection Dialogs (WPF)
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/Autoloot/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
Three sibling WPF `Window` views — `PropertySelectionWindow`, `CustomPropertiesWindow`, and `ClilocSelectionWindow` — each paired with a thin code-behind class inheriting from `System.Windows.Window`. The view-models live in the cross-cutting `ClassicAssist.Shared.UI.ViewModels.Autoloot` namespace (referenced via `xmlns:autoloot`) and are instantiated directly in XAML as `Window.DataContext`, so this module owns only presentation logic. All three windows share a uniform two-column layout (content on the left, action buttons on the right), load shared resources from `../../../Resources/Icons.xaml` and `ResourceDictionary.xaml`, bind localized UI text through `ClassicAssist.Shared.Resources.Strings`, and use `CloseOnClickBehaviour` attached via `System.Windows.Interactivity` to dismiss themselves after OK/Save actions. There is no internal sub-layering beyond the standard XAML/code-behind split.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
- Each window pairs a `.xaml` with an empty code-behind class whose sole job is `InitializeComponent()` and inherits from `System.Windows.Window`.
|
||||
- ViewModels are declared inline in XAML via `<autoloot:... />` and set as `Window.DataContext`, keeping code-behind free of binding setup.
|
||||
- All user-facing text is pulled from `ClassicAssist.Shared.Resources.Strings` using `{x:Static ...}` rather than hardcoded literals.
|
||||
- Dialog dismissal is handled uniformly by attaching `misc:CloseOnClickBehaviour` to OK/Save buttons instead of calling `Close()` in code.
|
||||
- Every window merges the same shared resource dictionaries (`Icons.xaml`, `ResourceDictionary.xaml`) and applies `ThemeWindowBackgroundBrush` plus `Topmost="True"`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF dialog windows that let players pick item properties for the autoloot feature, either by browsing item definitions or searching cliloc strings.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF (`System.Windows.Window`, `System.Windows.Interactivity`) with MVVM; localization via `ClassicAssist.Shared.Resources.Strings` and theme brushes from merged resource dictionaries.
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/agents
|
||||
title: Agents UI (WPF Tab Views & Autoloot Dialogs)
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/Agents/
|
||||
- ClassicAssist/UI/Views/Autoloot/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
Two sibling view folders share the same contract: every `*TabControl.xaml` in `Views/Agents/` instantiates a corresponding ViewModel from `ClassicAssist.Shared.UI.ViewModels.Agents` as its `DataContext`, while the `AutolootTabControl` additionally hosts the autoloot rule editor (items list + constraint grid) and opens the dialog windows under `Views/Autoloot/` (`ClilocSelectionWindow`, `CustomPropertiesWindow`, `PropertySelectionWindow`) through commands exposed on the same ViewModel. The code-behind of each tab control is a thin `InitializeComponent()` shell — all logic lives in the Shared ViewModels, so this module acts purely as the XAML binding layer between the game's Shared data models (`ClassicAssist.Data.Autoloot`, etc.) and the agents subsystem.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
- Each `*TabControl.xaml.cs` is a one-liner constructor calling only `InitializeComponent()`, with no event handlers or logic.
|
||||
- The XAML sets `DataContext` directly to a Shared ViewModel type (e.g. `<agents:AutolootViewModel />`) rather than relying on DI resolution at runtime.
|
||||
- Cross-cutting interactions (clipboard, multi-select, new-entry insertion) are implemented as attached behaviors from `ClassicAssist.UI.Misc` bound via `i:Interaction.Behaviors` instead of code-behind.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF views that compose the Agents tab page and its property-selection dialogs, wiring each agent's UserControl to a Shared ViewModel via DataContext.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/main_ui/agents_tab_controls
|
||||
title: Agents Tab Panel (WPF)
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/Agents/
|
||||
- ClassicAssist/UI/Views/AgentsTabControl.xaml
|
||||
- ClassicAssist/UI/Views/AgentsTabControl.xaml.cs
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
Two-layer WPF composition: `AgentsTabControl.xaml` is a thin `UserControl` hosting a `TabControl` whose `TabItem`s are declared purely in XAML and each hosts one child view from the `ClassicAssist.UI.Views.Agents` namespace. The eight agent views (`Organizer`, `Dress`, `Counters`, `Friends`, `VendorBuy`, `VendorSell`, `Scavenger`, `Autoloot`) live as sibling `*.xaml` / `*.xaml.cs` pairs under `Agents/`; their code-behind classes are empty `partial` classes inheriting from `System.Windows.Controls.UserControl` with only an `InitializeComponent()` constructor, so all logic is expected to be supplied via data binding to view-models defined elsewhere. Header text for every tab is resolved through `resources:Strings.*` static resources, keeping UI text out of markup. Dependency direction is strictly inward: the parent tab control depends on the child agents; children do not reference the parent.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
- Each agent feature ships as a paired `*.xaml` + `*.xaml.cs` where the code-behind is a minimal `partial class : UserControl` containing only `InitializeComponent()` in the constructor.
|
||||
- Tab headers are localized by referencing `resources:Strings.<Key>` static XAML bindings rather than hard-coded strings.
|
||||
- Child agent controls are referenced via a single `xmlns:agents="clr-namespace:ClassicAssist.UI.Views.Agents"` prefix and instantiated directly as XAML elements inside `TabItem` content.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF tabbed container that groups all player-agent management sub-panels — Organizer, Dress, Counters, Friends, Vendor Buy/Sell, Scavenger, and Autoloot — behind a single AgentsTabControl.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/main_ui/autoloot_windows
|
||||
title: Autoloot Property Selection Dialogs (WPF)
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/Autoloot/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
Three sibling WPF `Window` views — `PropertySelectionWindow`, `ClilocSelectionWindow`, and `CustomPropertiesWindow` — each paired with a minimal code-behind that only calls `InitializeComponent()`. All UI logic is delegated to view models in the cross-cutting `ClassicAssist.Shared.UI.ViewModels.Autoloot` namespace (`PropertySelectionViewModel`, `ClilocSelectionViewModel`, `CustomPropertiesViewModel`), which are instantiated directly in XAML via `<autoloot:... />` bindings. The `.xaml.cs` files depend on `System.Windows` (WPF), while the XAML markup additionally references shared resources (`ClassicAssist.Shared.Resources.Strings`, `ClassicAssist.UI.Misc.CloseOnClickBehaviour`, `ClassicAssist.UI.Resources.*`) and Expression Blend interactivity for button-close behavior. Dependency direction is strictly View → ViewModel; there is no controller or service layer inside this folder.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
- Each window has a one-line constructor that only invokes `InitializeComponent()`; all command handling lives in the bound ViewModel rather than in code-behind.
|
||||
- XAML sets `DataContext` inline via an `<autoloot:...ViewModel />` element so each window owns its own ViewModel instance instead of using DI.
|
||||
- OK/Cancel buttons use `CloseOnClickBehaviour` from `ClassicAssist.UI.Misc` through `i:Interaction.Behaviors` instead of explicit click handlers.
|
||||
- User-facing text is pulled from `ClassicAssist.Shared.Resources.Strings` via `{x:Static ...}` resource lookups, never hard-coded strings.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF dialog windows that let players pick autoloot properties by item, by cliloc key, or by defining custom property entries.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Windows Presentation Foundation (WPF) with XAML data binding, Expression Blend Interactivity (`i:Interaction.Behaviors`), and MVVM via view models defined in the shared `ClassicAssist.Shared` assembly.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/main_ui/core_game_features
|
||||
title: Classic Assist Game UI Panels (Chat, Skills, Hotkeys)
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/ChatWindow.xaml
|
||||
- ClassicAssist/UI/Views/SkillsTabControl.xaml
|
||||
- ClassicAssist/UI/Views/HotkeysTabControl.xaml
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
Three independent WPF views — a top-level `Window` (`ChatWindow.xaml`) and two reusable `UserControl`s (`SkillsTabControl.xaml`, `HotkeysTabControl.xaml`) — each declaring its own `DataContext` as an MVVM ViewModel from `ClassicAssist.UI.ViewModels` (e.g. `ChatViewModel`, `SkillsTabViewModel`, `HotkeysTabViewModel`). Views are purely declarative: they bind to ViewModel properties/commands via standard WPF bindings, use `ClassicAssist.UI.Misc.ValueConverters` for display logic, and delegate cross-cutting concerns to shared resources under `../../Resources/` (`DarkTheme.xaml`, `Icons.xaml`, `ResourceDictionary.xaml`). Interaction with non-visual state is routed through `ClassicAssist.UI.Misc` behaviors (`ItemsControlAutoScrollBehaviour`, `ComboBoxBehavior`, `BindableSelectedItemBehavior`) and `ClassicAssist.Misc.BindingProxy` to reach commands inside nested visual trees such as `ContextMenu`. The Chat window additionally hosts a custom title bar via `ClassicAssist.UI.Controls.CustomWindowTitleControl` and a right-hand user list split by a `GridSplitter`; the Skills panel uses a `ListView` with `GridView` columns backed by `SkillsGridViewColumn`, while the Hotkeys panel renders a hierarchical `TreeView` of `HotkeyEntry` items bound from `ClassicAssist.Data.Hotkeys`.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
- Each XAML file instantiates its ViewModel directly in markup via `<... .DataContext><viewModels:...ViewModel /></... .DataContext>` rather than setting it in code-behind.
|
||||
- Shared styling and icons are loaded by merging resource dictionaries from relative paths (`../../Resources/DarkTheme.xaml`, `../../Resources/Icons.xaml`, `../../Resources/ResourceDictionary.xaml`) inside the view's `UserControl.Resources` / `Window.Resources`.
|
||||
- Commands inside detached visual trees (e.g. `ContextMenu`, `DataTemplate`) are invoked through a `misc:BindingProxy` keyed as `Proxy` so the binding source can reach the parent DataContext.
|
||||
- UI interactions that need code-behind access are implemented as attached behaviors in `ClassicAssist.UI.Misc` (e.g. `ItemsControlAutoScrollBehaviour`, `ComboBoxBehavior`, `BindableSelectedItemBehavior`) wired via `i:Interaction.Behaviors`.
|
||||
- Localized strings are referenced through `x:Static resources:Strings.<Key>` from `ClassicAssist.Shared.Resources` instead of hard-coded text.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF XAML view definitions for the in-game chat window and two tabbed panels that let players manage skills and hotkeys.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/main_ui/utility_windows
|
||||
title: Debug & Utility Dialog Windows
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/DebugWindow.xaml
|
||||
- ClassicAssist/UI/Views/GIFRecorderWindow.xaml
|
||||
- ClassicAssist/UI/Views/HuePickerWindow.xaml
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
Three standalone WPF `Window` views (no code-behind logic here) that each own their ViewModel via inline `<Window.DataContext>` instantiation:
|
||||
- `DebugWindow.xaml` is a tabbed diagnostic shell (`TabControl`) hosting multiple sub-controls from the sibling `ClassicAssist.UI.Views.Debug` namespace (gumps, menus, buff icons, special moves, vendor buy, autoloot, properties, journal, assemblies), with its toolbar styling pulled in from `Debug/DebugToolBarStyle.xaml`. It binds to `ClassicAssist.Shared.UI.ViewModels.DebugViewModel`.
|
||||
- `GIFRecorderWindow.xaml` is a transparent, borderless, always-on-top overlay window using `CustomWindowTitleControl` plus three embedded `DrawingImage` resources (wait/play/stop/save) and a `misc:BindingProxy` to reach the `GIFRecorderViewModel` commands from nested controls.
|
||||
- `HuePickerWindow.xaml` is a filterable list of `HueEntryControl` items bound one-way to itself (`DataContext={RelativeSource Self}`), with OK/Cancel buttons wired to an MVVM command and closed via a shared `CloseOnClickBehaviour` attached through `System.Windows.Interactivity`.
|
||||
|
||||
All three follow the same dependency direction: XAML → `ClassicAssist.UI.Controls`, `ClassicAssist.UI.Misc`, `ClassicAssist.Shared.Resources.Strings`, and a dedicated ViewModel in either `ClassicAssist.UI.ViewModels` or `ClassicAssist.Shared.UI.ViewModels`; they do not import each other.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
- Each window declares its ViewModel directly in XAML via `<Window.DataContext><viewModels:... /></Window.DataContext>` rather than setting it in code-behind.
|
||||
- User-facing strings are resolved through `{x:Static resources:Strings.*}` from `ClassicAssist.Shared.Resources` instead of hard-coded literals.
|
||||
- Reusable UI chrome (window title bar, hex dump, hue entry) is composed by plugging in custom controls from `ClassicAssist.UI.Controls` rather than building visuals inline.
|
||||
- Cross-naming scope behavior (closing a dialog from a button inside a child control) is achieved via `misc:BindingProxy` + `ElementName` binding or `i:Interaction.Behaviors` with `CloseOnClickBehaviour`, keeping code-behind free.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF dialog windows providing in-game debugging, GIF recording, and hue selection utilities for ClassicAssist.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/main_ui/entity_tools
|
||||
title: Entity & Profile Inspector Dialogs (WPF)
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/EntityCollectionViewer.xaml
|
||||
- ClassicAssist/UI/Views/ObjectInpectorWindow.xaml
|
||||
- ClassicAssist/UI/Views/NewProfileWindow.xaml
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
Pure XAML view layer — each file is a `Window` subclass whose `DataContext` is instantiated inline in markup (`EntityCollectionViewerViewModel`, `ObjectInspectorViewModel`, `NewProfileViewModel`) rather than resolved through a DI container. The views depend on sibling ViewModels in `ClassicAssist.UI.ViewModels` / `ClassicAssist.Shared.UI.ViewModels`, shared resources in `ClassicAssist.Shared.Resources.Strings`, and reusable behaviors/styles from `ClassicAssist.UI.Misc` (e.g. `MultiSelectionBehaviour`, `ListViewDoubleClickBehaviour`, `CloseOnClickBehaviour`). `EntityCollectionViewer.xaml` composes the `EntityCollectionFilterControl` sub-view and merges its own `EntityCollectionViewerResourceDictionary.xaml` plus `Debug/DebugToolBarStyle.xaml`. `ObjectInspectorWindow.xaml` groups items by a `Category` property via a `CollectionViewSource.PropertyGroupDescription` and exposes an Expander-based group template. `NewProfileWindow.xaml` uses an `EnumMatchToBooleanConverter` to bind mutually exclusive radio buttons to a single enum property. All three follow MVVM with no code-behind logic visible here; interactivity is delegated to Expression Blend `i:Interaction.Behaviors` attached to controls.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
- ViewModels are created directly in XAML via `<viewModels:... />` DataContext declarations instead of being injected or resolved at runtime.
|
||||
- User-facing strings are pulled from `ClassicAssist.Shared.Resources.Strings` using `{x:Static resources:Strings.*}` bindings rather than hardcoded literals.
|
||||
- Cross-cutting UI interactions (multi-select, double-click-to-open, close-on-click) are implemented as Expression Blend `i:Interaction.Behaviors` from `ClassicAssist.UI.Misc` and attached declaratively.
|
||||
- Toolbar/menu actions drive commands on the ViewModel with `CommandParameter` carrying strongly-typed enum values (e.g. `EntityCollectionSortStyle`) instead of string tags.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Three WPF dialog windows that let users browse entity collections, inspect object properties in a grouped list, and create new profiles via a small confirmation form.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/main_ui/filters_windows
|
||||
title: Filter Configuration Dialogs (WPF)
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/Filters/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
Two independent WPF `Window` subclasses under the `ClassicAssist.UI.Views.Filters` namespace:
|
||||
- `ClilocFilterConfigureWindow` follows MVVM: its XAML sets `DataContext` to a view model (`filters:ClilocFilterConfigureViewModel`) declared inline, while the code-behind is a minimal `InitializeComponent()` constructor. The UI composes a toolbar (save/remove), a `ListView` of configured Cliloc entries with an editable `Replacement` column via `controls:EditTextBlock`, and a lower pane that lets users search/filter available clilocs and add them.
|
||||
- `RepeatedMessagesFilterConfigureWindow` uses self-binding (`DataContext="{Binding RelativeSource={RelativeSource Self}}")` and implements `INotifyPropertyChanged` directly on the window class, exposing a `MessageFilterOptions` object whose properties (`SendToJournal`, `MessageLimit`, `TimeLimit`, `BlockedTime`) are bound two-way to Xceed `IntegerUpDown` controls and a checkbox.
|
||||
Both windows depend only on shared resources (`ClassicAssist.Shared.Resources.Strings`), custom controls (`ClassicAssist.UI.Controls`), value converters (`ClassicAssist.UI.Misc.ValueConverters`), and filter option models (`ClassicAssist.Data.Filters`). No cross-window communication — each dialog owns its own options instance.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
- User-facing text is never hardcoded in XAML; all labels, headers, and tooltips are resolved through `x:Static resources:Strings.<Key>` from `ClassicAssist.Shared.Resources`.
|
||||
- Dialogs expose their configuration state as a dedicated Options/ViewModel property and bind UI elements two-way to it, rather than reading/writing controls directly in code-behind.
|
||||
- Command-driven actions (Save, Remove, Add, Close) are wired in XAML via `Command`/`CommandParameter` bindings or attached behaviors instead of Click event handlers.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF dialog windows for configuring ClassicAssist's in-game message filters, including Cliloc replacement and repeated-message suppression.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF (System.Windows) with Xceed WPF Toolkit (`xctk:IntegerUpDown`) for numeric input; Expression Blend Interactivity (`http://schemas.microsoft.com/expression/2010/interactivity`) used by `CloseOnClickBehaviour` to close dialogs without code-behind event handlers.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/main_ui/macros_windows
|
||||
title: Macros Editor & Command Browser (WPF)
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/Macros/
|
||||
- ClassicAssist/UI/Views/MacrosTabControl.xaml
|
||||
- ClassicAssist/UI/Views/MacrosTabControl.xaml.cs
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
Two WPF views driven by MVVM in the `ClassicAssist.Shared` assembly:
|
||||
- `MacrosTabControl.xaml/.cs` is a `UserControl` hosting a left-side list of `MacroEntry` items (new/save/remove/record/play/stop/hotkey binding) and a right-side `ICSharpCode.AvalonEdit.TextEditor` bound to `SelectedItem.Macro`. The code-behind performs view-only initialization: loads the embedded `Python.Dark.xshd` highlighting, scans the executing assembly for public static methods decorated with `CommandsDisplayAttribute` under namespace `*Macros.Commands`, and wires AvalonEdit's completion window on text entry. A `GridSplitter` separates the two panes.
|
||||
- `MacrosCommandWindow.xaml/.cs` is a standalone `Window` whose `DataContext` is `MacrosCommandViewModel`; it groups command items by `Category` via a `CollectionViewSource` and exposes an Insert button that pushes the selected command into the editor.
|
||||
- Both views consume shared resources from `ClassicAssist.Shared` (`Strings`, `ShortcutKeys`, `MacroEntry`) and reuse custom controls/behaviors from `ClassicAssist.UI.Controls` and `ClassicAssist.UI.Misc` (e.g. `AvalonEditBehaviour`, `ItemsControlSelectNewEntryBehaviour`, `CloseOnClickBehaviour`).
|
||||
- Dependency direction: Views → ViewModels (in `ClassicAssist.Shared`) → data model (`ClassicAssist.Data.Macros`); the code-behind only touches AvalonEdit plumbing and never owns business logic.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
- View markup declares its ViewModel as `<xxx.DataContext>` inline and binds through `{Binding ...}` without any code-behind property wiring.
|
||||
- Button/command bindings use `Mode=OneWay` for the `Command` property so the view cannot accidentally overwrite the VM's command reference.
|
||||
- UI strings are sourced exclusively from `ClassicAssist.Shared.Resources.Strings` via `x:Static resources:Strings.Xxx` rather than hard-coded literals.
|
||||
- AvalonEdit editor state is synchronized with the model through reusable `misc:AvalonEditBehaviour` / `misc:AvalonBindingBehaviour` attached behaviors instead of direct TextEditor property access in the VM.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF UI for browsing, editing, recording and executing ClassicAssist macros, plus a popup window that lists discoverable macro commands for insertion into scripts.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF + XAML with ICSharpCode.AvalonEdit for syntax-highlighted Python scripting; Expression Blend Interactivity (`i:`) for behaviors; dynamic discovery of macro commands via reflection over `*Macros.Commands` types annotated with `CommandsDisplayAttribute`.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/main_ui/app_shell_and_settings
|
||||
title: Main Window Shell & Settings UI
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/MainWindow.xaml
|
||||
- ClassicAssist/UI/Views/AboutControl.xaml
|
||||
- ClassicAssist/UI/Views/GeneralControl.xaml
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
Three XAML views form the top-level UI: `MainWindow.xaml` is an `Avalonia.Window` (not WPF — despite the folder name) that instantiates `MainWindowViewModel`, attaches `LoadOptionsOnWindowLoaded` and `WindowResizeBehaviour` via `System.Windows.Interactivity.Behaviors`, and hosts a `TabControl` whose tabs compose sibling user-controls (`GeneralControl`, `OptionsTabControl`, `HotkeysTabControl`, `MacrosTabControl`, `SkillsTabControl`, `AgentsTabControl`, `browser:MacroBrowserControl`, `AboutControl`). Each tab control is a leaf `UserControl` whose `DataContext` is created inline in markup (e.g. `<viewModels:GeneralControlViewModel />`) from the shared `ClassicAssist.Shared` assembly; no code-behind wiring is used. Shared resources (icons, theme brushes) are pulled in by merging `../../Resources/Icons.xaml` and `../../Resources/ResourceDictionary.xaml` into each view's `Window.Resources` / `UserControl.Resources`. All text is localized through `ClassicAssist.Shared.Resources.Strings` static properties rather than hard-coded strings. The module depends outward on `ClassicAssist.UI.Controls`, `ClassicAssist.UI.ViewModels`, `ClassicAssist.UI.Misc`, `ClassicAssist.Browser`, and `ClassicAssist.Shared`; nothing inside this scope references other UI modules.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
- Each view declares its ViewModel directly in XAML via `<viewModels:...ViewModel />` as `DataContext`, avoiding code-behind instantiation.
|
||||
- Localized UI text is read exclusively through `{x:Static r:Strings.<Key>}` from `ClassicAssist.Shared.Resources`, never hard-coded literals.
|
||||
- Shared icons and theme brushes are loaded by merging `../../Resources/Icons.xaml` and `../../Resources/ResourceDictionary.xaml` into each view's Resources dictionary.
|
||||
- Complex interactions (window loading, resize handling, combo-box command binding) are implemented as `Interaction.Behaviors` in `ClassicAssist.UI.Misc` rather than event handlers in code-behind.
|
||||
- Designer previewability is enabled per-control via `d:DesignInstance` / `d:DesignStyle` so views render with sample data at design time.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF shell hosting the ClassicAssist main window with a tabbed settings surface (General, Options, Hotkeys, Macros, Skills, Agents, Macro Browser, About) and its About/General view controls.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Avalonia UI (XAML + MVVM) targeting Windows, using `System.Windows.Interactivity` for behaviors and `ClassicAssist.Shared` for ViewModels and localized string resources.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/main_ui
|
||||
title: Classic Assist WPF Game UI Layer
|
||||
scope:
|
||||
- ClassicAssist/UI/Views/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
The Views folder is a flat collection of XAML/XAML.cs pairs with no shared base class or MVVM framework — each file owns one window or control. Cross-cutting wiring happens at two levels: (1) `MainWindow.xaml` hosts an `AgentsTabControl` plus a `MacrosTabControl`, which in turn compose the sub-panels under `Agents/` (Organizer, Dress, Counters, Friends, VendorBuy/Sell, Scavenger, Autoloot); (2) top-level dialogs (`ChatWindow`, `DebugWindow`, `GIFRecorderWindow`, `HuePickerWindow`, `ObjectInpectorWindow`, `ActiveObjectsWindow`, `EntityCollectionViewer`, `NewProfileWindow`) are launched by the shell rather than embedded. All children depend on the same ClassicAssist core assemblies for data binding; there is no cross-view messaging contract inside this scope — communication flows through the application service layer outside Views.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
- Every XAML view has a sibling `.xaml.cs` code-behind file; no separate ViewModel classes live under Views.
|
||||
- Dialog-style windows derive from `RepositionableGumpWindow` to share drag-to-reposition behavior.
|
||||
- Tabbed surfaces follow the pattern `<XxxTabControl>.xaml` hosting child panels via `<ContentPresenter>` or nested tabs.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF view layer that wires the main window shell, tabbed settings surface, and all in-game dialog windows for ClassicAssist's Ultima Online client.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/data_utils
|
||||
title: Hotkey Commands, Macro Completion & Skill Comparer
|
||||
scope:
|
||||
- ClassicAssist/Data/Hotkeys/
|
||||
- ClassicAssist/Data/Macros/
|
||||
- ClassicAssist/Data/Skills/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
Three independent leaf sub-packages with no internal dependencies on each other:
|
||||
- `Hotkeys/Commands/` — each file is a concrete `HotkeyCommand` subclass decorated with `[HotkeyCommand(Name=..., Category=...)]`, registered by convention at startup; `Execute()` bridges game state (`ClassicAssist.Shared.UO.Commands`, `Engine.Items/Mobiles`) to WPF views in `ClassicAssist.UI.Views` (e.g. `EntityCollectionViewer`, `ChatWindow`, `GIFRecorderWindow`).
|
||||
- `Macros/PythonCompletionData.cs` — implements `ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData` so the macro editor can offer Python keyword completions.
|
||||
- `Skills/SkillComparer.cs` — implements `System.Collections.IComparer` over `SkillEntry`, driven by `SkillsGridViewColumn.Enums` and `ListSortDirection`, used by the skills grid view.
|
||||
Dependency direction is one-way: this module depends on `Shared`, `UI`, and `UO.Objects`; nothing here is depended on by Shared/UI.
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
- Hotkey actions are declared as classes deriving from `HotkeyCommand` and marked with the `[HotkeyCommand]` attribute carrying `Name` (and optional `Category`), with logic placed in an overridden `Execute()` method.
|
||||
- WPF window launchers spin up a new background thread, set `ApartmentState.STA`, construct the window, call `Show()` / `ShowDialog()`, then pump the dispatcher via `Dispatcher.Run()`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Small data-layer utilities: hotkey command implementations that open UI windows, a Python macro completion entry for AvalonEdit, and the skills grid sort comparer.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/browser
|
||||
title: Macro Browser WPF Control
|
||||
scope:
|
||||
- ClassicAssist/Browser/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
MVVM layering inside a single WPF UserControl:
|
||||
- `MacroBrowserControl.xaml/.xaml.cs` is the view; it wires AvalonEdit syntax highlighting (Python.Dark.xshd) and opens hyperlinks via `Process.Start`.
|
||||
- `MacroBrowserViewModel : BaseViewModel` owns all UI state (`ObservableCollection<string>` for Authors/Eras/Shards/Macros, `Category` filter), exposes `RelayCommand`/`RelayCommandAsync` actions, and drives data loading on construction by invoking a `_data` dictionary of `Func<Task<string[]>>` entries backed by the singleton `Database`.
|
||||
- `Data/Database` is a thread-safe singleton wrapping an in-process LiteDB file (`macros.db`) with three collections — `repository`, `manifest`, `macros` — plus an `HttpClient` and `GitHubClient`. It fetches `metadata.json` from the repo's raw URL, caches it for 15 minutes (or until the master branch SHA changes), and lazily downloads macro source text keyed by name+SHA1.
|
||||
- `Models/` holds LiteDB-persisted entities (`Macro`, `Manifest`, `Metadata`, `Repository`) plus a `Category` used as a hierarchical filter value.
|
||||
- `Data/Filter` + `FilterType` model the shard/era/author/category predicate applied against the manifest before returning macro names.
|
||||
- `Controls/ClearableComboBox` is a reusable ComboBox extension exposing a `ClearCommand` DP bound to the ViewModel's `ClearCommand`.
|
||||
Dependency direction: View → ViewModel → Data/Models; Models are pure POCOs decorated with `[BsonId]`; no cross-dependencies between sibling subfolders except ViewModel depending on both Data and Models.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
- UI state properties follow the `SetProperty(ref _field, value)` pattern inherited from `BaseViewModel`, with filter setters additionally calling `ApplyFilter()` to re-query the database.
|
||||
- Commands are exposed as lazy-initialized read-only properties using `??=` with `new RelayCommand(...)` / `new RelayCommandAsync(...)`, guarded by a can-execute lambda over `SelectedItem`.
|
||||
- Background work uses `Task.Run` followed by `.ContinueWith` or `_dispatcher.Invoke`/`_dispatcher.InvokeAsync` to marshal results back onto the UI thread before touching `ObservableCollection`s.
|
||||
- Long-running async operations wrap their body in try/catch/finally that sets `Loading = false` and surfaces errors through `MessageBox.Show` with localized `Strings.Error`.
|
||||
- LiteDB entities are plain POCOs annotated with `[BsonId]` and stored in collections created via `database.GetCollection<T>("name")` with `EnsureIndex(x => x.Id)`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF user control that browses, filters, previews, and installs UO macros from the official ClassicAssist-Macros GitHub repository.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF with XAML code-behind, MVVM via `ClassicAssist.UI.ViewModels.BaseViewModel` and `RelayCommand`, AvalonEdit for macro preview syntax highlighting, LiteDB for local persistence (`macros.db`), Newtonsoft.Json for deserializing the remote `metadata.json`, and Octokit/GitHub REST API for commit-hash comparison.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/engine_support
|
||||
title: WPF Engine Host & UI Abstractions
|
||||
scope:
|
||||
- ClassicAssist/Engine.cs
|
||||
- ClassicAssist/WPFDispatcher.cs
|
||||
- ClassicAssist/WPFUIInvoker.cs
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
Three cooperating types form the WPF-specific host layer around `ClassicAssist.Shared.Engine`:
|
||||
- `Engine.cs` (namespace `Assistant`) is the single entry point consumed by the plugin loader. `Install(PluginHeader*)` loads `ClassicAssist.Shared.dll`, subscribes to `AssemblyResolve` to resolve dependencies from `StartupPath` plus the runtime directory (with a special-case rename for `Colletions` → `System.Collections`), then spawns a background STA thread where it constructs `WPFDispatcher`/`WPFUIInvoker`, installs the shared engine via `SEngine.Install(plugin, new WPFMessageBoxProvider())`, hooks `Options.LoadEvent`/`SaveEvent` to serialize/deserialize every `BaseViewModel` implementing `ISettingProvider`, creates `MainWindow`, and runs `Dispatcher.Run()`.
|
||||
- `WPFDispatcher.cs` implements the cross-platform `IDispatcher` interface by forwarding `Invoke`/`InvokeAsync` to `System.Windows.Threading.Dispatcher`.
|
||||
- `WPFUIInvoker.cs` implements `IUIInvoker`: `Invoke`/`InvokeDialog<T>` reflectively locate a `Window` subclass by name in the executing assembly, construct it with optional ctor/data-context parameters, set `DataContext`, and show it on the dispatcher thread; `GetHueAsync` spins up its own STA thread to host `HuePickerWindow`; clipboard helpers call `System.Windows.Clipboard` directly.
|
||||
|
||||
Dependency direction: this module depends on `ClassicAssist.Shared` (for `SEngine`, `IDispatcher`, `IUIInvoker`, `WPFMessageBoxProvider`) and on the WPF UI project (`ClassicAssist.UI.Views`, `ClassicAssist.UI.ViewModels`, `ClassicAssist.Data`, `ClassicAssist.Misc`, `CUO_API`). The shared engine never references WPF — WPF concerns are isolated behind the two interfaces so the same core can be hosted elsewhere.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
- Cross-thread UI access is always funneled through `IDispatcher.Invoke`/`InvokeAsync` rather than calling WPF APIs directly from background code.
|
||||
- Window discovery uses string-typed names resolved via `Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(t => t.Name == typeName && t.IsSubclassOf(typeof(Window)))`, throwing `ArgumentNullException` when not found.
|
||||
- Optional constructor and data-context parameters are passed through as `object[]` arrays and materialized with `Activator.CreateInstance` at invocation time.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Hosts the ClassicAssist WPF application by bootstrapping the shared engine, wiring a WPF dispatcher and UI invoker, and running the main window on an STA thread.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF (`System.Windows.Threading.Dispatcher`, `System.Windows.Window`, `System.Windows.Clipboard`) as the concrete UI platform; reflection + `Activator.CreateInstance` for string-based window resolution; `TaskCompletionSource` to bridge STA dialog threads into async callers.
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/resources_assets
|
||||
title: WPF Theme & Embedded Resources
|
||||
scope:
|
||||
- ClassicAssist/Resources/
|
||||
- ClassicAssist/Properties/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
Two parallel resource tracks coexist in the project:
|
||||
|
||||
- WPF XAML resources under `Resources/` are organised as a merged-dictionary chain: `ResourceDictionary.xaml` is the single entry point that merges `DarkTheme.xaml`, which in turn merges `Colours.xaml`. `Icons.xaml` holds all vector icons as `DrawingImage` entries keyed by name (e.g. `unlinkedIcon`, `PythonIcon`, `WebIcon`) and can be merged wherever needed; `LeftRightIconToggleButton.xaml` defines a reusable control template that references those icons. `Shrink.txt` is an embedded text asset.
|
||||
- .NET ResX resources under `Properties/Resources.resx` + `Resources.Designer.cs` expose strongly-typed `System.Drawing.Bitmap` and string properties (`arrow_down`, `arrow_up`, `padlock`, `python`, `Shrink`) backed by `ResourceManager` lookups. The `.resx` file points at sibling PNGs via relative paths (`..\Resources\*.png`).
|
||||
|
||||
Dependency direction is one-way: `DarkTheme.xaml` → `Colours.xaml`; `ResourceDictionary.xaml` → `DarkTheme.xaml`; `Icons.xaml` is standalone and consumed by consumers via merge. No C# code lives in this module — it is purely declarative assets consumed by other assemblies.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF theme assets for ClassicAssist, providing a dark colour palette, per-control styles, inline DrawingImage icons, and .NET ResX-embedded bitmaps/text.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf/ui_layer
|
||||
title: WPF UI Controls, Behaviours & Value Converters
|
||||
scope:
|
||||
- ClassicAssist/UI/Controls/
|
||||
- ClassicAssist/UI/Misc/
|
||||
- ClassicAssist/UI/Models/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
Three sibling sub-packages with a flat dependency direction (UI → Core/Misc, never the reverse):
|
||||
- `Controls/` — self-contained `UserControl`s (`CustomWindowTitleControl`, `HueEntryControl`, `HexDumpControl`, `EditTextBlock`, `TextBoxKey`) plus a layout helper (`StretchyWrapPanel`). Each control exposes its bindable surface via `DependencyProperty` + CLR wrapper pairs.
|
||||
- `Misc/` — behaviour/utility layer split into three groups: (1) `System.Windows.Interactivity.Behavior<T>` subclasses (`AvalonEditBehaviour`, `AutoScrollBehaviour`, `WindowResizeBehaviour`, `ItemsControlSelectNewEntryBehaviour`, …) that attach to existing WPF elements without subclassing; (2) `ValueConverters/` implementing `IValueConverter` for data-binding transformations, with `ValueConverterGroup` enabling chained conversion in XAML; (3) markup extensions (`EnumBindingSourceExtension`) and cross-cutting helpers (`BindingProxy`, `ClipboardBehaviour`, `WPFMessageBoxProvider` which implements `IMessageBoxProvider` from `ClassicAssist.Misc` to bridge WinForms `MessageBox` into the app's abstraction).
|
||||
- `Models/` — tiny INotifyPropertyChanged view-model fragments (`EntityCollectionFilter`, `EntityCollectionSortStyle`) that encapsulate filter/sort state consumed by list/grid views.
|
||||
|
||||
No MVVM framework is used; binding relies on standard WPF `INotifyPropertyChanged` and `DependencyObject`. The only external runtime dependencies are `System.Windows.Interactivity` (for `Behavior<T>`) and `ICSharpCode.AvalonEdit` (for `TextEditor`), while higher-level abstractions like `IMessageBoxProvider` keep this leaf decoupled from concrete message-box implementations.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
- Public bindable properties are exposed as `static readonly DependencyProperty` registered with `FrameworkPropertyMetadata(..., FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)` plus a thin CLR wrapper that calls `GetValue`/`SetValue`.
|
||||
- Attached behaviours extend third-party controls by subclassing `System.Windows.Interactivity.Behavior<T>` and wiring/unwiring events inside `OnAttached`/`OnDetaching` rather than subclassing the target control.
|
||||
- View-models implement `INotifyPropertyChanged` through a shared `SetProperty(ref T obj, T value, [CallerMemberName])` helper that also calls `CommandManager.InvalidateRequerySuggested()` to refresh bound commands.
|
||||
- XAML-only helpers live as paired `.xaml` + `.xaml.cs` files where the code-behind contains only the `InitializeComponent` constructor and property wrappers, keeping logic in attached behaviours or converters.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Reusable WPF presentation primitives — custom controls, attached behaviours, markup extensions, value converters, and lightweight view-model helpers used by ClassicAssist's XAML views.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF with `System.Windows.Interactivity` for attached behaviours, `ICSharpCode.AvalonEdit` for code editing, and `System.Windows.Forms.MessageBox` (via `WPFMessageBoxProvider`) as the concrete message-box implementation.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
schema_version: 1
|
||||
module_path: classic_assist_wpf
|
||||
title: Classic Assist WPF Application Host
|
||||
scope:
|
||||
- ClassicAssist/
|
||||
source_files: []
|
||||
depends_on: []
|
||||
related_to: []
|
||||
+1
@@ -0,0 +1 @@
|
||||
The `Engine.Install` entry point is the single cross-child wiring point: it loads `ClassicAssist.Shared.dll`, registers a `WPFDispatcher`/`WPFUIInvoker` on `SEngine`, installs `WPFMessageBoxProvider`, subscribes to `Options.LoadEvent`/`SaveEvent` to persist every `BaseViewModel` implementing `ISettingProvider`, then creates `MainWindow` on an STA thread. `WPFUIInvoker` exposes `IUIInvoker.Invoke`/`InvokeDialog` so the shared engine can open any `Window` subclass by name with optional DataContext — this is how hotkey commands in `Data/Hotkeys/Commands` (e.g. `ShowChatWindowCommand`, `ShowGIFCaptureWindow`) and other engine code trigger UI across the `main_ui`, `agents`, and `browser` view modules. All XAML resources are merged centrally via `Resources/ResourceDictionary.xaml` (dark theme, icons, colours), consumed uniformly by every child's Views. The project is split into presentation concerns (`Browser`, `UI/*`, `Agents`, `Main Window`) plus thin data helpers (`Data/Hotkeys`, `Data/Macros`, `Data/Skills`) that depend only on the shared engine abstractions rather than each other.
|
||||
+1
@@ -0,0 +1 @@
|
||||
WPF application host that boots the shared engine, wires STA-threaded UI primitives, and composes the main window shell from tabbed agent, macro, skills, and debug views.
|
||||
Reference in New Issue
Block a user