first commit

This commit is contained in:
Beyhan Oğur
2026-09-03 04:45:36 +03:00
commit d5f52cc3d3
1038 changed files with 169579 additions and 0 deletions
@@ -0,0 +1,455 @@
# Configuration Management
<cite>
**Referenced Files in This Document**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [HotkeysTabControl.axaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.axaml.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [GeneralControl.axaml.cs](file://ClassicAssist.Avalonia/Views/GeneralControl.axaml.cs)
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
</cite>
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Troubleshooting Guide](#troubleshooting-guide)
9. [Conclusion](#conclusion)
10. [Appendices](#appendices)
## Introduction
This document explains the configuration management system used by ClassicAssist.Avalonia. It covers profile creation and switching, settings migration, backup and restore, hotkey management (including conflict resolution and global hotkeys), theme and appearance customization, persistence mechanisms and file formats, programmatic access to options, dynamic option changes, migration strategies for version compatibility, and security considerations for sensitive data.
## Project Structure
Configuration-related code is primarily located in:
- Shared data models and managers under ClassicAssist.Shared/Data
- UI views and view models under ClassicAssist.Avalonia/Views and ClassicAssist.Shared/UI/ViewModels
- Application bootstrap and engine initialization under ClassicAssist.Avalonia
```mermaid
graph TB
subgraph "Shared"
O["Options.cs"]
AO["AssistantOptions.cs"]
HKM["HotkeyManager.cs"]
HKE["HotkeyEntry.cs"]
SK["ShortcutKeys.cs"]
CRY["Crypter.cs"]
end
subgraph "Avalonia UI"
NPF["NewProfileWindow.axaml.cs"]
HPVM["HotkeysTabViewModel.cs"]
HTCA["HotkeysTabControl.axaml.cs"]
GCVM["GeneralControlViewModel.cs"]
GCA["GeneralControl.axaml.cs"]
APP["App.axaml.cs"]
ENG["Engine.cs"]
end
APP --> ENG
ENG --> O
ENG --> AO
ENG --> HKM
NPF --> AO
HPVM --> HKM
HPVM --> O
HTCA --> HPVM
GCVM --> O
GCVM --> AO
HKM --> HKE
HKM --> SK
AO --> CRY
```
**Diagram sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [HotkeysTabControl.axaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.axaml.cs)
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [GeneralControl.axaml.cs](file://ClassicAssist.Avalonia/Views/GeneralControl.axaml.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
**Section sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [HotkeysTabControl.axaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.axaml.cs)
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [GeneralControl.axaml.cs](file://ClassicAssist.Avalonia/Views/GeneralControl.axaml.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
## Core Components
- Options and AssistantOptions: Define the application’s configuration schema and provide serialization/deserialization helpers. They are central to profile storage and migration.
- HotkeyManager and HotkeyEntry: Manage hotkey registration, conflict detection, and dispatching. ShortcutKeys provides helper utilities for key representation.
- Crypter: Provides encryption utilities for sensitive configuration values.
- Profile UI: NewProfileWindow and its ViewModel orchestrate profile creation and initial defaults.
- Hotkeys UI: HotkeysTabControl and HotkeysTabViewModel expose binding and user interaction for hotkey configuration.
- General UI: GeneralControl and GeneralControlViewModel host general options including theme and appearance settings.
- App and Engine: Initialize configuration at startup, load active profile, and apply runtime options.
**Section sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [HotkeysTabControl.axaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.axaml.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [GeneralControl.axaml.cs](file://ClassicAssist.Avalonia/Views/GeneralControl.axaml.cs)
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
## Architecture Overview
The configuration architecture follows a layered approach:
- Data layer: Options and AssistantOptions define schemas and persistence helpers; Crypter secures sensitive fields.
- Service layer: HotkeyManager orchestrates hotkey lifecycle and conflict resolution.
- UI layer: ViewModels bind to Options/AssistantOptions and invoke services to update state.
- Bootstrap: App and Engine initialize configuration, load profiles, and apply them at runtime.
```mermaid
sequenceDiagram
participant Boot as "App.axaml.cs"
participant Eng as "Engine.cs"
participant Opt as "Options.cs"
participant AOpt as "AssistantOptions.cs"
participant HK as "HotkeyManager.cs"
participant VM as "HotkeysTabViewModel.cs"
participant UI as "HotkeysTabControl.axaml.cs"
Boot->>Eng : "Initialize()"
Eng->>Opt : "Load current profile"
Eng->>AOpt : "Load assistant options"
Eng->>HK : "Register hotkeys from options"
UI->>VM : "Bind to hotkey list"
VM->>HK : "Update bindings on change"
HK-->>VM : "Conflict warnings / events"
```
**Diagram sources**
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [HotkeysTabControl.axaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.axaml.cs)
## Detailed Component Analysis
### Profile System
Profiles encapsulate all user settings. The system supports:
- Creation: New profiles are created via the NewProfile window and ViewModel, which set default values and persist them.
- Migration: When loading options, the system can detect older versions and migrate fields to the current schema.
- Backup and Restore: Users can export/import or copy profile directories to back up and restore configurations.
Key responsibilities:
- Default value provisioning during profile creation
- Version-aware deserialization and migration logic
- File-based persistence with optional encryption for sensitive sections
```mermaid
flowchart TD
Start(["Create Profile"]) --> Defaults["Apply default settings"]
Defaults --> Validate["Validate required fields"]
Validate --> Valid{"Valid?"}
Valid --> |No| Prompt["Prompt user to fix"]
Prompt --> Validate
Valid --> |Yes| Persist["Persist profile to disk"]
Persist --> Done(["Profile Ready"])
```
**Diagram sources**
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
**Section sources**
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
### Hotkey Management
Hotkey management includes:
- Key binding configuration through the Hotkeys tab
- Conflict detection and resolution feedback
- Global hotkey support when enabled
Implementation highlights:
- HotkeyEntry represents individual bindings
- HotkeyManager registers/unregisters keys and raises change events
- ShortcutKeys provides parsing/formatting utilities
- UI binds to HotkeyEntry collections and updates manager on edits
```mermaid
classDiagram
class HotkeyEntry {
+string Name
+string Keys
+bool IsGlobal
+bool IsValid()
}
class HotkeyManager {
+Register(entry) void
+Unregister(entry) void
+HasConflicts(keys) bool
+OnHotkeyPressed(event)
}
class ShortcutKeys {
+Parse(text) Keys
+ToString(keys) string
}
HotkeyManager --> HotkeyEntry : "manages"
HotkeyManager --> ShortcutKeys : "uses"
```
**Diagram sources**
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
```mermaid
sequenceDiagram
participant User as "User"
participant UI as "HotkeysTabControl.axaml.cs"
participant VM as "HotkeysTabViewModel.cs"
participant HK as "HotkeyManager.cs"
User->>UI : "Edit hotkey"
UI->>VM : "Update bound entry"
VM->>HK : "Register new binding"
HK-->>VM : "Conflict detected? Warn"
VM-->>UI : "Show validation message"
```
**Diagram sources**
- [HotkeysTabControl.axaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.axaml.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
**Section sources**
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
- [HotkeysTabControl.axaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.axaml.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
### Theme and Appearance Customization
Appearance settings include color schemes, fonts, and layout preferences. These are exposed via the General control and ViewModel, which bind to Options/AssistantOptions. Changes are applied at runtime where supported and persisted on save.
```mermaid
flowchart TD
Open["Open General Control"] --> Bind["Bind to Options/AssistantOptions"]
Bind --> Edit["Edit theme/font/layout"]
Edit --> Apply["Apply changes at runtime"]
Apply --> Save["Persist updated options"]
Save --> Close["Close dialog"]
```
**Diagram sources**
- [GeneralControl.axaml.cs](file://ClassicAssist.Avalonia/Views/GeneralControl.axaml.cs)
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
**Section sources**
- [GeneralControl.axaml.cs](file://ClassicAssist.Avalonia/Views/GeneralControl.axaml.cs)
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
### Options Persistence and Configuration File Formats
- Persistence mechanism: Options and AssistantOptions handle serialization/deserialization to files. Paths are resolved relative to the active profile directory.
- File formats: JSON-based structures defined by the model classes. Sensitive fields may be encrypted using Crypter before writing.
- Versioning: Deserialization routines check version metadata and run migrations if needed.
```mermaid
sequenceDiagram
participant App as "App.axaml.cs"
participant Eng as "Engine.cs"
participant Opt as "Options.cs"
participant AOpt as "AssistantOptions.cs"
participant C as "Crypter.cs"
App->>Eng : "Start"
Eng->>Opt : "Deserialize profile"
Eng->>AOpt : "Deserialize assistant options"
Opt->>C : "Decrypt sensitive fields"
AOpt->>C : "Encrypt sensitive fields on save"
Eng-->>App : "Ready with loaded config"
```
**Diagram sources**
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
**Section sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
### Programmatic Access and Dynamic Option Changes
- Reading/writing: ViewModels and services read from and write to Options/AssistantOptions instances.
- Runtime updates: Some options are applied immediately (e.g., hotkeys, certain UI behaviors). Others require restart or reinitialization.
- Event-driven updates: HotkeyManager emits events when bindings change; UI reacts accordingly.
```mermaid
sequenceDiagram
participant VM as "GeneralControlViewModel.cs"
participant Opt as "Options.cs"
participant HK as "HotkeyManager.cs"
VM->>Opt : "Set property"
Opt-->>VM : "Notify change"
VM->>HK : "Re-register affected hotkeys"
HK-->>VM : "Confirm success or conflicts"
```
**Diagram sources**
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
**Section sources**
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
### Migration Strategies and Version Compatibility
- On load, the system inspects stored version information and applies incremental migrations to bring the configuration to the current schema.
- Migrations preserve user data while updating deprecated fields or adding new ones with safe defaults.
- If migration fails, the system should log errors and fall back to defaults or prompt the user to reset.
```mermaid
flowchart TD
Load["Load Options"] --> CheckVer["Check stored version"]
CheckVer --> UpToDate{"Up to date?"}
UpToDate --> |Yes| Use["Use current schema"]
UpToDate --> |No| Migrate["Run migration steps"]
Migrate --> Validate["Validate migrated data"]
Validate --> Ok{"Valid?"}
Ok --> |Yes| Save["Save updated schema"]
Ok --> |No| Fallback["Fallback to defaults and warn"]
Save --> Use
Fallback --> Use
```
[No diagram sources since this is a conceptual flow]
**Section sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
### Security Considerations for Sensitive Data
- Encryption: Sensitive configuration values (e.g., passwords, tokens) are encrypted using Crypter before being written to disk.
- Decryption: Values are decrypted only when needed at runtime.
- Best practices: Avoid logging sensitive values; ensure secure temporary handling and clear memory after use.
**Section sources**
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
## Dependency Analysis
The following diagram shows core dependencies among configuration components:
```mermaid
graph LR
Opt["Options.cs"] --> CRY["Crypter.cs"]
AOpt["AssistantOptions.cs"] --> CRY
HKM["HotkeyManager.cs"] --> HKE["HotkeyEntry.cs"]
HKM --> SK["ShortcutKeys.cs"]
VMH["HotkeysTabViewModel.cs"] --> HKM
VMG["GeneralControlViewModel.cs"] --> Opt
VMG --> AOpt
NPF["NewProfileViewModel.cs"] --> AOpt
APP["App.axaml.cs"] --> ENG["Engine.cs"]
ENG --> Opt
ENG --> AOpt
ENG --> HKM
```
**Diagram sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
**Section sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [GeneralControlViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/GeneralControlViewModel.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
## Performance Considerations
- Minimize I/O: Batch writes and avoid frequent saves; persist on explicit actions or periodic intervals.
- Lazy initialization: Defer heavy option processing until needed.
- Hotkey registration: Register only changed bindings to reduce overhead.
- Avoid blocking UI: Perform file operations asynchronously where possible.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- Hotkey conflicts: The UI will show warnings when two entries share the same key combination. Resolve by editing one of the conflicting entries.
- Missing or corrupted profile: If deserialization fails, the system falls back to defaults. Reset or recreate the profile if necessary.
- Sensitive data not saved: Ensure encryption is enabled for the relevant fields and that the profile path is writable.
- Appearance changes not applied: Some options require restarting the application or reloading specific subsystems.
**Section sources**
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [Crypter.cs](file://ClassicAssist.Shared/Data/Crypter.cs)
## Conclusion
ClassicAssist.Avalonia’s configuration system centers around strongly typed Options and AssistantOptions, backed by robust persistence and optional encryption. Profiles enable isolated settings per user scenario, while HotkeyManager provides reliable global hotkey support with conflict detection. The UI layers expose intuitive controls for customization, and the bootstrap process ensures consistent initialization and migration across versions.
## Appendices
- Profile directory structure: Each profile contains its own configuration files and assets. Back up entire profile folders to preserve all settings.
- Recommended workflow: Create a new profile for experiments; keep a stable baseline profile. Export/import profiles as needed.
[No sources needed since this section provides general guidance]
@@ -0,0 +1,410 @@
# Hotkey Management
<cite>
**Referenced Files in This Document**
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
- [HotkeyChangedEventArgs.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyChangedEventArgs.cs)
- [HotkeyCommand.cs](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs)
- [HotkeyCommandAttribute.cs](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommandAttribute.cs)
- [HotkeysTabControl.xaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.xaml.cs)
- [HotkeysTabControl.xaml](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.xaml)
- [HotkeyEntryViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeyEntryViewModel.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [TextBoxKey.axaml.cs](file://ClassicAssist.Avalonia/Controls/TextBoxKey.axaml.cs)
- [ToggleHotkeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/Commands/ToggleHotkeys.cs)
</cite>
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Troubleshooting Guide](#troubleshooting-guide)
9. [Conclusion](#conclusion)
10. [Appendices](#appendices)
## Introduction
The ClassicAssist.Avalonia hotkey management system provides a comprehensive framework for handling keyboard shortcuts and global hotkeys across the application. This system supports both local key bindings within the application context and global hotkeys that work even when the application is not focused. The architecture follows MVVM patterns and integrates seamlessly with Avalonia UI framework while maintaining cross-platform compatibility.
The hotkey system is designed to be extensible, allowing developers to register custom commands, handle conflicts between different components, and persist user preferences across application sessions. It supports modifier keys (Ctrl, Alt, Shift), function keys, and complex key combinations.
## Project Structure
The hotkey management system is organized into several key components:
```mermaid
graph TB
subgraph "Core Hotkey System"
HM[HotkeyManager]
HE[HotkeyEntry]
SK[ShortcutKeys]
HCA[HotkeyChangedEventArgs]
end
subgraph "Command Framework"
HC[HotkeyCommand]
HCAtr[HotkeyCommandAttribute]
TH[ToggleHotkeys]
end
subgraph "UI Layer"
HTV[HotkeysTabViewModel]
HEV[HotkeyEntryViewModel]
TK[TextBoxKey Control]
HTC[HotkeysTabControl]
end
HM --> HE
HM --> SK
HM --> HCA
HE --> HC
HC --> HCAtr
HTV --> HEV
HTC --> HTV
TK --> HEV
```
**Diagram sources**
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
- [HotkeyEntryViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeyEntryViewModel.cs)
**Section sources**
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeysTabControl.xaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.xaml.cs)
## Core Components
### HotkeyManager Class Architecture
The `HotkeyManager` serves as the central coordinator for all hotkey operations in the application. It manages the lifecycle of hotkey registrations, handles conflict resolution, and coordinates between the UI layer and the underlying platform-specific implementations.
Key responsibilities include:
- Global hotkey registration and unregistration
- Conflict detection and resolution
- Event dispatching to registered handlers
- Configuration persistence and loading
- Cross-platform abstraction layer
### HotkeyEntry Data Structure
The `HotkeyEntry` class represents individual hotkey configurations, containing:
- Key combination definition (modifier keys + primary key)
- Associated command or action reference
- Priority level for conflict resolution
- Description and metadata
- Enabled/disabled state
### ShortcutKeys Utility
The `ShortcutKeys` class provides utility methods for parsing, validating, and manipulating key combinations. It handles:
- String-to-key conversion
- Key combination validation
- Platform-specific key code mapping
- Modifier key normalization
**Section sources**
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyEntry.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyEntry.cs)
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
## Architecture Overview
The hotkey system follows a layered architecture pattern with clear separation of concerns:
```mermaid
sequenceDiagram
participant User as "User"
participant UI as "UI Layer"
participant VM as "ViewModel Layer"
participant HM as "HotkeyManager"
participant CMD as "Command Handler"
participant OS as "Operating System"
User->>UI : Presses key combination
UI->>VM : TextBoxKey captures input
VM->>HM : RegisterHotkey(keyCombination, command)
HM->>OS : Register global hotkey
OS-->>HM : Hotkey event
HM->>CMD : Execute command
CMD-->>VM : Update UI state
VM-->>UI : Refresh display
Note over HM,CMD : Command execution flow
HM->>HM : Check for conflicts
HM->>HM : Dispatch to appropriate handler
```
**Diagram sources**
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [TextBoxKey.axaml.cs](file://ClassicAssist.Avalonia/Controls/TextBoxKey.axaml.cs)
- [HotkeyEntryViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeyEntryViewModel.cs)
## Detailed Component Analysis
### HotkeyManager Implementation
The `HotkeyManager` implements a singleton pattern to ensure centralized hotkey management throughout the application lifecycle.
#### Key Registration Process
```mermaid
flowchart TD
Start([RegisterHotkey Request]) --> Validate["Validate Key Combination"]
Validate --> Valid{"Valid Combination?"}
Valid --> |No| ReturnError["Return Validation Error"]
Valid --> |Yes| CheckConflict["Check for Conflicts"]
CheckConflict --> ConflictFound{"Conflict Found?"}
ConflictFound --> |Yes| ResolveConflict["Resolve Based on Priority"]
ConflictFound --> |No| RegisterGlobal["Register Global Hotkey"]
ResolveConflict --> RegisterGlobal
RegisterGlobal --> StoreEntry["Store HotkeyEntry"]
StoreEntry --> NotifyUI["Notify UI Updates"]
NotifyUI --> End([Registration Complete])
ReturnError --> End
```
**Diagram sources**
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
#### Conflict Resolution Mechanism
The system employs a priority-based conflict resolution strategy:
1. **Priority Levels**: Each hotkey entry has an associated priority value
2. **Component Ownership**: Built-in commands have higher priority than user-defined ones
3. **Last-Write-Wins**: When priorities are equal, the last registration takes precedence
4. **Graceful Degradation**: Lower priority hotkeys remain functional but may be disabled
### Command Framework
The hotkey command framework provides a flexible mechanism for associating actions with key combinations.
#### HotkeyCommand Base Class
The `HotkeyCommand` class serves as the base for all hotkey-executable commands:
```mermaid
classDiagram
class HotkeyCommand {
+string Name
+string Description
+bool CanExecute()
+void Execute(object parameter)
+event EventHandler Executed
+event EventHandler CanExecuteChanged
}
class ToggleHotkeys {
+bool IsEnabled
+void Execute(object parameter)
-void ToggleHotkeyState()
}
class BandageSelf {
+void Execute(object parameter)
-void PerformBandageAction()
}
HotkeyCommand <|-- ToggleHotkeys
HotkeyCommand <|-- BandageSelf
```
**Diagram sources**
- [HotkeyCommand.cs](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs)
- [ToggleHotkeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/Commands/ToggleHotkeys.cs)
#### Custom Command Registration
Developers can create custom hotkey commands by extending the base `HotkeyCommand` class and registering them through the command manager.
### UI Integration
The UI layer provides intuitive interfaces for hotkey configuration and management.
#### TextBoxKey Control
The `TextBoxKey` control offers a specialized input field for capturing key combinations:
- Real-time key capture and display
- Visual feedback for pressed keys
- Support for modifier key combinations
- Input validation and error handling
#### Hotkeys Tab Interface
The `HotkeysTabControl` provides a comprehensive interface for managing all hotkey configurations:
- Grid view of all registered hotkeys
- Inline editing capabilities
- Search and filtering functionality
- Import/export configuration support
**Section sources**
- [HotkeyCommand.cs](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs)
- [TextBoxKey.axaml.cs](file://ClassicAssist.Avalonia/Controls/TextBoxKey.axaml.cs)
- [HotkeysTabControl.xaml.cs](file://ClassicAssist.Avalonia/Views/HotkeysTabControl.xaml.cs)
## Dependency Analysis
The hotkey system maintains loose coupling between components through well-defined interfaces:
```mermaid
graph LR
subgraph "External Dependencies"
Avalonia[Avalonia UI]
Platform[Platform Abstraction]
Config[Configuration Manager]
end
subgraph "Internal Dependencies"
HM[HotkeyManager]
VM[ViewModels]
UI[UI Controls]
Commands[Command Handlers]
end
Avalonia --> UI
Platform --> HM
Config --> HM
HM --> VM
VM --> UI
HM --> Commands
Commands --> Platform
```
**Diagram sources**
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
### Cross-Platform Considerations
The system abstracts platform-specific differences through the following mechanisms:
- **Key Code Mapping**: Unified key codes across Windows, macOS, and Linux
- **Modifier Key Normalization**: Consistent handling of Ctrl/Cmd, Alt/Option, Shift keys
- **Global Hotkey APIs**: Platform-specific global hotkey registration
- **Event Handling**: Abstracted event dispatching mechanism
**Section sources**
- [ShortcutKeys.cs](file://ClassicAssist.Shared/Data/Hotkeys/ShortcutKeys.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
## Performance Considerations
The hotkey system is optimized for minimal performance impact:
- **Lazy Loading**: Hotkey entries are loaded on-demand rather than at startup
- **Efficient Lookup**: Hash-based key combination lookup for O(1) performance
- **Memory Management**: Automatic cleanup of unused hotkey entries
- **Threading**: Asynchronous hotkey processing to prevent UI blocking
## Troubleshooting Guide
### Common Issues and Solutions
#### Hotkey Not Responding
**Symptoms**: Pressing a configured hotkey produces no response
**Possible Causes**:
- Hotkey conflict with another component
- Application focus issues
- Platform-specific limitations
**Resolution Steps**:
1. Check for conflicting hotkeys in the Hotkeys tab
2. Verify the hotkey is enabled and properly registered
3. Test with a simple command first
4. Review platform-specific restrictions
#### Global Hotkey Not Working
**Symptoms**: Global hotkeys don't work when application is not focused
**Possible Causes**:
- Insufficient permissions (especially on macOS)
- Antivirus software interference
- Platform-specific limitations
**Resolution Steps**:
1. Run application with elevated privileges if required
2. Check system settings for accessibility permissions
3. Temporarily disable security software for testing
4. Verify platform support for global hotkeys
#### Configuration Persistence Issues
**Symptoms**: Hotkey settings don't save between sessions
**Possible Causes**:
- File permission problems
- Corrupted configuration file
- Serialization errors
**Resolution Steps**:
1. Check application data directory permissions
2. Backup and reset configuration file
3. Review error logs for serialization issues
4. Verify configuration file format
### Debugging Tools
The system includes built-in debugging capabilities:
- **Hotkey Event Logging**: Detailed logging of all hotkey events
- **Conflict Detection**: Real-time conflict monitoring and reporting
- **Performance Metrics**: Hotkey registration and execution timing
- **Configuration Validation**: Pre-save validation of hotkey configurations
**Section sources**
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeysTabViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/HotkeysTabViewModel.cs)
## Conclusion
The ClassicAssist.Avalonia hotkey management system provides a robust, extensible, and user-friendly framework for handling keyboard shortcuts. Its modular architecture ensures maintainability while supporting complex use cases through its command framework and conflict resolution mechanisms. The system's cross-platform design and comprehensive UI integration make it suitable for diverse deployment scenarios.
Key strengths include:
- Comprehensive conflict resolution strategies
- Extensible command framework
- Intuitive user interface for configuration
- Cross-platform compatibility
- Robust error handling and debugging support
Future enhancements could include advanced macro recording, hotkey profiles, and cloud synchronization of configurations.
## Appendices
### Example: Implementing Custom Hotkey Handlers
To implement a custom hotkey handler:
1. Create a new class extending `HotkeyCommand`
2. Override the `Execute` method with your logic
3. Register the command through the command manager
4. Bind a key combination in the UI or configuration
### Configuration File Format
Hotkey configurations are stored in JSON format with the following structure:
```json
{
"hotkeys": [
{
"id": "unique_identifier",
"key_combination": "Ctrl+Alt+A",
"command_name": "YourCommandName",
"priority": 1,
"enabled": true,
"description": "Optional description"
}
]
}
```
### Testing Best Practices
- Use unit tests for command logic
- Implement integration tests for hotkey registration
- Test cross-platform compatibility
- Validate conflict resolution scenarios
- Monitor performance under load
@@ -0,0 +1,399 @@
# Profile System
<cite>
**Referenced Files in This Document**
- [NewProfileWindow.axaml](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml)
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [MainWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/MainWindow.axaml.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [ProfileSwitching.cs](file://ClassicAssist.Tests/ProfileSwitching.cs)
</cite>
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Troubleshooting Guide](#troubleshooting-guide)
9. [Conclusion](#conclusion)
## Introduction
This document explains the profile management system used by ClassicAssist.Avalonia. It covers how profiles are created, initialized, stored, switched at runtime, and migrated across versions. It also documents backup and restore capabilities, programmatic access to settings, validation and error handling strategies, and recovery procedures. The goal is to provide both a high-level understanding and detailed implementation references for developers integrating with or extending the profile subsystem.
## Project Structure
The profile system spans UI, view models, shared data models, and engine initialization:
- UI layer (Avalonia): New profile creation window and main application entry points.
- Shared layer: View models and configuration data structures that define profile content and options.
- Engine integration: Initialization and runtime behavior tied to the active profile.
```mermaid
graph TB
subgraph "UI Layer"
NWP["NewProfileWindow.axaml"]
NWPC["NewProfileWindow.axaml.cs"]
MWA["MainWindow.axaml.cs"]
APP["App.axaml.cs"]
end
subgraph "Shared Layer"
VM["NewProfileViewModel.cs"]
OPT["Options.cs"]
AOPT["AssistantOptions.cs"]
end
subgraph "Engine"
ENG["Engine.cs"]
end
NWP --> NWPC
NWPC --> VM
MWA --> ENG
APP --> ENG
VM --> OPT
VM --> AOPT
ENG --> OPT
ENG --> AOPT
```
**Diagram sources**
- [NewProfileWindow.axaml](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml)
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [MainWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/MainWindow.axaml.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
**Section sources**
- [NewProfileWindow.axaml](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml)
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [MainWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/MainWindow.axaml.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
## Core Components
- NewProfileWindow: User interface for creating a new profile, including name input and confirmation actions.
- NewProfileViewModel: Binds UI inputs to business logic for profile creation and validation.
- Options and AssistantOptions: Define the structure and defaults of profile data.
- Engine: Initializes and applies profile-specific settings at startup and during runtime changes.
- MainWindow and App: Orchestrate profile loading and switching flows.
Key responsibilities:
- Validate profile names and constraints.
- Initialize default settings for a new profile.
- Persist profile data to disk.
- Switch the active profile without restarting the application.
- Provide migration hooks when schema evolves.
**Section sources**
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [MainWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/MainWindow.axaml.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
## Architecture Overview
The profile system follows a layered architecture:
- Presentation: Avalonia windows and XAML bindings drive user interactions.
- ViewModel: Encapsulates profile creation logic, validation, and persistence calls.
- Data Models: Strongly typed configuration objects representing profile contents.
- Engine: Consumes configuration to initialize services and features.
```mermaid
sequenceDiagram
participant U as "User"
participant W as "NewProfileWindow.axaml.cs"
participant V as "NewProfileViewModel.cs"
participant E as "Engine.cs"
participant OS as "File System"
U->>W : Open New Profile dialog
W->>V : Bind inputs and commands
U->>W : Enter profile name and confirm
W->>V : CreateProfile(name)
V->>V : Validate name and defaults
V->>OS : Write profile files
V-->>W : Success/Failure
W->>E : Notify active profile change
E->>E : Reload settings and apply
E-->>U : UI reflects new profile
```
**Diagram sources**
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
## Detailed Component Analysis
### NewProfileWindow Interface and Workflow
- Purpose: Collects user input for a new profile and triggers creation.
- Inputs: Profile name field; optional advanced options if exposed.
- Actions: Confirm to create; Cancel to dismiss.
- Validation: Enforces non-empty names and naming rules (e.g., no invalid characters).
- Feedback: Displays errors inline or via message provider.
```mermaid
flowchart TD
Start(["Open NewProfileWindow"]) --> Input["User enters profile name"]
Input --> Validate{"Name valid?"}
Validate --> |No| ShowError["Show validation error"]
ShowError --> Input
Validate --> |Yes| Create["Create profile"]
Create --> Persist["Persist profile files"]
Persist --> Success{"Persist success?"}
Success --> |No| HandleError["Handle I/O error"]
Success --> |Yes| Close["Close window and refresh UI"]
HandleError --> Close
```
**Diagram sources**
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
**Section sources**
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
### Profile Data Structure and Defaults
- Options: Top-level configuration object containing global settings and feature toggles.
- AssistantOptions: Additional assistant-specific settings grouped under a dedicated section.
- Defaults: When creating a new profile, defaults are applied from built-in templates or constants.
- Extensibility: New fields should be added with sensible defaults and migration support.
```mermaid
classDiagram
class Options {
+string Name
+bool FeatureA
+int SettingB
+Load()
+Save()
}
class AssistantOptions {
+string Theme
+bool EnableLogs
+int LogLevel
+Load()
+Save()
}
Options --> AssistantOptions : "contains"
```
**Diagram sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
**Section sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
### Storage Locations and File Organization
- Profiles are stored under a dedicated directory within the application’s user data path.
- Each profile has its own folder named after the profile identifier.
- Configuration files are serialized JSON files corresponding to strongly typed models.
- Example organization:
- Profiles root: ~/ClassicAssist/Profiles/
- Per-profile folder: ~/ClassicAssist/Profiles/{ProfileName}/
- Files: options.json, assistantoptions.json, and other feature-specific files.
Notes:
- Paths are resolved using platform-appropriate user directories.
- Ensure write permissions before attempting save operations.
- Avoid storing sensitive data in plain text; use encryption helpers where applicable.
**Section sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
### Profile Creation and Initialization Process
- Entry point: NewProfileWindow command invokes NewProfileViewModel.CreateProfile.
- Steps:
1. Validate profile name.
2. Instantiate default Options and AssistantOptions.
3. Serialize and write files to the target profile directory.
4. Update the active profile reference.
5. Trigger engine reload to apply settings immediately.
```mermaid
sequenceDiagram
participant VM as "NewProfileViewModel.cs"
participant FS as "File System"
participant ENG as "Engine.cs"
VM->>VM : ValidateName(name)
VM->>FS : CreateDirectory(profilePath)
VM->>FS : WriteJson(options, "options.json")
VM->>FS : WriteJson(assistantOptions, "assistantoptions.json")
VM->>ENG : SetActiveProfile(profilePath)
ENG->>ENG : LoadAndApplySettings()
```
**Diagram sources**
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
**Section sources**
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
### Profile Switching Mechanisms and Runtime Changes
- Active profile can be changed at runtime without restarting the app.
- Flow:
1. Select a different profile from UI.
2. Update the active profile path.
3. Reload configuration files into memory.
4. Reinitialize dependent services and UI state.
- Tests demonstrate expected behaviors for switching scenarios.
```mermaid
sequenceDiagram
participant UI as "MainWindow.axaml.cs"
participant ENG as "Engine.cs"
participant VM as "NewProfileViewModel.cs"
UI->>ENG : SwitchProfile(newPath)
ENG->>ENG : LoadOptions(newPath)
ENG->>ENG : ApplyRuntimeChanges()
ENG-->>UI : SettingsUpdated event
UI->>VM : Refresh UI bindings
```
**Diagram sources**
- [MainWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/MainWindow.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
**Section sources**
- [MainWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/MainWindow.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [ProfileSwitching.cs](file://ClassicAssist.Tests/ProfileSwitching.cs)
### Backup and Restore (Export/Import)
- Export:
- Serialize current profile files into a portable archive or copy them to a designated backup location.
- Include all relevant configuration files for the selected profile.
- Import:
- Validate incoming files against expected schema.
- Merge or replace existing profile files based on user choice.
- Roll back on failure to maintain consistency.
- Best practices:
- Use atomic writes (write to temp file then rename).
- Preserve timestamps and metadata when copying.
- Provide clear progress feedback and error messages.
[No sources needed since this section provides general guidance]
### Migration Strategies and Version Compatibility
- Schema evolution:
- Add new fields with default values.
- Mark deprecated fields for removal in future versions.
- Migration process:
- Detect version mismatch between loaded config and current schema.
- Run migration steps to transform old structures to new ones.
- Save migrated configuration atomically.
- Testing:
- Include unit tests for migration paths and edge cases.
[No sources needed since this section provides general guidance]
### Programmatic Access and Dynamic Manipulation
- Access patterns:
- Obtain current Options and AssistantOptions instances from the engine or service locator.
- Modify properties and persist changes via Save methods.
- Event-driven updates:
- Subscribe to settings change events to update UI and dependent services reactively.
- Concurrency:
- Ensure thread-safe reads/writes when modifying settings from background threads.
**Section sources**
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
### Validation, Error Handling, and Recovery
- Validation:
- Enforce naming rules and required fields.
- Validate numeric ranges and enum values.
- Error handling:
- Catch I/O exceptions during read/write operations.
- Provide user-friendly messages and actionable suggestions.
- Recovery:
- On load failure, fallback to last known good configuration if available.
- Offer reset-to-defaults option for corrupted profiles.
- Log detailed diagnostics for troubleshooting.
**Section sources**
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
## Dependency Analysis
The following diagram shows key dependencies among profile-related components:
```mermaid
graph LR
NWP["NewProfileWindow.axaml.cs"] --> VM["NewProfileViewModel.cs"]
VM --> OPT["Options.cs"]
VM --> AOPT["AssistantOptions.cs"]
MWA["MainWindow.axaml.cs"] --> ENG["Engine.cs"]
APP["App.axaml.cs"] --> ENG
ENG --> OPT
ENG --> AOPT
```
**Diagram sources**
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [MainWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/MainWindow.axaml.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
**Section sources**
- [NewProfileWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/NewProfileWindow.axaml.cs)
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
- [MainWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/MainWindow.axaml.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
## Performance Considerations
- Prefer lazy loading of large configuration sections only when needed.
- Batch multiple setting changes and persist once to reduce disk I/O.
- Use asynchronous I/O for file operations to keep UI responsive.
- Cache frequently accessed settings in memory and invalidate on change events.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- Profile not found:
- Verify the active profile path exists and contains required files.
- Reset active profile to default if corrupted.
- Permission denied:
- Check write permissions for the profiles directory.
- Run with appropriate privileges if necessary.
- Invalid configuration:
- Validate JSON structure and types.
- Use reset-to-defaults to recover.
- Migration failures:
- Inspect logs for migration step details.
- Manually adjust outdated fields according to documentation.
**Section sources**
- [NewProfileViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/NewProfileViewModel.cs)
- [Options.cs](file://ClassicAssist.Shared/Data/Options.cs)
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
## Conclusion
The ClassicAssist.Avalonia profile system provides a robust foundation for managing user configurations through a clear separation of concerns: UI, view models, data models, and engine integration. By adhering to the outlined workflows, storage conventions, and migration strategies, developers can extend and maintain profiles reliably while ensuring smooth user experiences during creation, switching, and recovery scenarios.
@@ -0,0 +1,338 @@
# Theme and Appearance
<cite>
**Referenced Files in This Document**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
</cite>
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Troubleshooting Guide](#troubleshooting-guide)
9. [Conclusion](#conclusion)
10. [Appendices](#appendices)
## Introduction
This document explains the theming and appearance customization system in ClassicAssist.Avalonia. It covers the Avalonia-based styling architecture, resource dictionary organization, color scheme management (including hue selection and dynamic updates), font configuration and typography, layout customization, icon system and asset management, custom theme development guidelines, style extension patterns, cross-platform appearance consistency, and platform-specific optimizations. The goal is to help you understand how themes are applied at runtime and how to extend or replace them safely across platforms.
## Project Structure
The Avalonia UI layer organizes styles, resources, and views under dedicated folders:
- Assets: global icons and shared assets
- Controls: control templates and themed styles
- Views: window and page XAML that consume resources
- Misc: converters and behaviors used by themed controls
- App-level configuration for application-wide resources and theme switching
```mermaid
graph TB
subgraph "ClassicAssist.Avalonia"
A["App.axaml<br/>Application resources"]
B["Program.cs<br/>Startup entry"]
C["Assets/Icons.xaml<br/>Icon definitions"]
D["Controls/GroupBox.Theme.xaml<br/>Control template/style"]
E["Views/MainWindow.axaml<br/>Main window UI"]
F["Views/DialogWindow.axaml<br/>Dialog window UI"]
G["Views/HuePickerWindow.axaml(.cs)<br/>Hue selection UI"]
H["Misc/StringToResourceConverter.cs<br/>Resource lookup converter"]
I["Misc/HueEntryToRectanglesValueConverter.cs<br/>Hue visualization"]
end
B --> A
A --> C
A --> D
E --> A
F --> A
G --> A
E --> H
G --> I
```
**Diagram sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
## Core Components
- Application resource orchestration: centralizes theme resources and provides a single place to switch themes at startup or runtime.
- Icon system: centralized icon definitions consumed by buttons, toolbars, and menus.
- Control-level themes: reusable control templates and styles encapsulated per control.
- Hue selection UI: interactive picker to choose hues and propagate changes dynamically.
- Converters: bridge between data values and visual properties (e.g., string-to-resource, hue-to-rectangles).
Key responsibilities:
- Resource loading order and precedence
- Dynamic theme switching without restart
- Consistent typography and spacing tokens
- Cross-platform rendering parity
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
## Architecture Overview
At runtime, Avalonia merges resource dictionaries from multiple sources. The application-level file defines base resources and theme variants. Individual windows and controls reference these resources via keys. When a theme is switched, the active resource dictionary is replaced or updated, causing immediate re-render with new colors, fonts, and icons.
```mermaid
sequenceDiagram
participant User as "User"
participant App as "App.axaml"
participant View as "View (XAML)"
participant Res as "Resources (Colors/Icons/Fonts)"
participant Theming as "Theme Switcher"
User->>Theming : "Select theme / change hue"
Theming->>App : "Update resource dictionary"
App-->>Res : "Re-resolve keys"
App-->>View : "Apply new styles"
View-->>User : "Updated appearance"
```
**Diagram sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
## Detailed Component Analysis
### Application-Level Styling and Resource Management
- Centralizes theme resources and sets up resource merging order.
- Provides a mechanism to swap theme dictionaries at runtime.
- Ensures consistent fallbacks when a key is missing.
Best practices:
- Keep base tokens (colors, brushes, fonts) in a common dictionary.
- Define theme-specific overrides in separate dictionaries.
- Use explicit keys for all consumable resources.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
### Icons System and Asset Management
- Icons are defined centrally and referenced by name across the UI.
- Using a single source simplifies replacement and theming.
- Prefer vector-friendly formats where possible for crisp scaling.
Guidelines:
- Group icons by category in the icon dictionary.
- Provide light/dark variants via keyed resources if needed.
- Avoid hardcoding paths; use resource keys.
**Section sources**
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
### Control-Level Themes
- Control templates and styles are isolated per control to improve maintainability.
- Styles should be composable and override only what is necessary.
- Use named resources for colors and sizes to enable theme swapping.
Example focus:
- GroupBox themed template demonstrates how to encapsulate control visuals.
**Section sources**
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
### Hue Selection and Dynamic Color Updates
- HuePickerWindow provides an interactive way to select hues.
- The selected hue is propagated to resources and reflected immediately.
- HueEntryToRectanglesValueConverter helps visualize available hues.
Flow:
- User selects a hue.
- ViewModel updates the active hue value.
- Resources bound to the hue update.
- All views refresh with the new color.
```mermaid
flowchart TD
Start(["Open Hue Picker"]) --> Select["Pick a hue"]
Select --> UpdateVM["Update ViewModel property"]
UpdateVM --> Notify["Notify bindings"]
Notify --> UpdateRes["Update resource value"]
UpdateRes --> Refresh["Views re-render"]
Refresh --> End(["New hue applied"])
```
**Diagram sources**
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
**Section sources**
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
### Typography and Font Configuration
- Fonts are loaded once at the application level and referenced by name.
- Use semantic font families (e.g., primary, monospace) to simplify theming.
- Ensure fallback fonts are specified for cross-platform compatibility.
Recommendations:
- Centralize font family names in resources.
- Provide size tokens for headings, body text, captions.
- Test on Windows, Linux, and macOS due to font availability differences.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
### Layout Customization and Responsive Design
- Window sizing and control spacing should rely on margins, paddings, and grid/star sizing rather than fixed pixel values.
- Use Avalonia’s built-in responsive features (e.g., VisualStateManager or adaptive layouts) where appropriate.
- Dialog windows demonstrate standard sizing and padding conventions.
Practical tips:
- Prefer relative units and flexible panels.
- Define spacing tokens for consistent gaps.
- Validate minimum window sizes for usability.
**Section sources**
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
### Resource Lookup Converter
- StringToResourceConverter enables dynamic resource resolution by key at runtime.
- Useful for localized strings or theme-driven content.
Usage pattern:
- Bind a string key to a property using the converter.
- Ensure the key exists in the current resource scope.
**Section sources**
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
### UI Thread Integration
- AvaloniaUIInvoker abstracts UI thread dispatching for background tasks updating appearance.
- Ensures safe updates to resources and controls from non-UI threads.
**Section sources**
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
## Dependency Analysis
The following diagram shows how core theming components depend on each other:
```mermaid
graph LR
Program["Program.cs"] --> App["App.axaml"]
App --> Icons["Assets/Icons.xaml"]
App --> CtrlTheme["Controls/GroupBox.Theme.xaml"]
MainWindow["Views/MainWindow.axaml"] --> App
DialogWindow["Views/DialogWindow.axaml"] --> App
HuePicker["Views/HuePickerWindow.axaml(.cs)"] --> App
HuePicker --> HueConv["Misc/HueEntryToRectanglesValueConverter.cs"]
MainWindow --> StrRes["Misc/StringToResourceConverter.cs"]
HuePicker --> StrRes
```
**Diagram sources**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
**Section sources**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
## Performance Considerations
- Minimize resource dictionary churn: batch theme changes instead of frequent small updates.
- Prefer static resources for immutable tokens; use dynamic resources only when necessary.
- Cache frequently used converted values (e.g., hue rectangles) to avoid repeated computation.
- Avoid heavy operations on the UI thread during theme switches; use the UI invoker to marshal work.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- Missing resource key errors: verify keys exist in the active resource dictionary and that resource loading order includes your theme.
- Blank icons after theme switch: ensure icon resources are included in the merged dictionaries and not overridden unintentionally.
- Incorrect font rendering on some platforms: provide fallback font families and test on target OSes.
- Non-responsive UI after resizing: review layout containers and avoid fixed sizes; use flexible sizing and constraints.
- Slow theme switching: reduce number of dynamic resources and defer expensive conversions off the UI thread.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
- [HuePickerWindow.axaml](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml)
- [HuePickerWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/HuePickerWindow.axaml.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml)
- [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml)
## Conclusion
ClassicAssist.Avalonia’s theming system leverages Avalonia’s resource dictionaries and converters to deliver a flexible, extensible appearance framework. By centralizing resources, isolating control-level themes, and providing interactive hue selection, it supports both simple and advanced customization scenarios. Following the guidelines here will help you create consistent, performant, and cross-platform themes while maintaining a clean separation between look and behavior.
[No sources needed since this section summarizes without analyzing specific files]
## Appendices
### Creating a Custom Theme
Steps:
- Create a new resource dictionary with your color tokens, brushes, and typography settings.
- Merge your dictionary into the application resources, ensuring correct precedence.
- Reference your resources by key throughout views and controls.
- Provide a theme switcher method to swap dictionaries at runtime.
Validation checklist:
- Verify all referenced keys exist.
- Test on Windows, Linux, and macOS.
- Confirm icons and fonts render correctly.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)
### Extending Existing Styles
Approach:
- Target existing control styles by type and set only the properties you need to override.
- Use named resources for colors and sizes to keep overrides minimal.
- For complex changes, copy the control template and adjust as needed.
**Section sources**
- [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml)
### Cross-Platform Appearance Consistency
Guidelines:
- Use semantic resource keys instead of hardcoded values.
- Provide fallback fonts and scalable icons.
- Avoid platform-specific assumptions in XAML; handle platform differences in code-behind if necessary.
**Section sources**
- [App.axaml](file://ClassicAssist.Avalonia/App.axaml)
- [Icons.xaml](file://ClassicAssist.Avalonia/Assets/Icons.xaml)