Skip to content

Architecture

Isaac M. Good edited this page Sep 19, 2026 · 2 revisions

Architecture Overview

MVVM

  • Models: plain data classes (mods, profiles, settings)
  • ViewModels: expose observable state and commands. Use CommunityToolkit.Mvvm source generators ([ObservableProperty], [RelayCommand])
  • Views: Avalonia XAML with data bindings

Dependency Injection

All services are singletons registered in App.axaml.cs via Microsoft.Extensions.DependencyInjection. The container is exposed as App.Services for cases like XAML markup extensions.

Service Layer

Every service has an I*Service interface.

Service Responsibility
ISettingsService Load/save settings.json
IGameDetectionService Find game path, detect running game
IModDiscoveryService Scan mod folders, watch for changes
IModInstallService Activate, deactivate, install, uninstall, update, rollback
IVersionCacheService Archive versions, manage cache size
IProfileService Profile CRUD, import/export, diff computation
IGitHubModsService Query GitHub Releases API
INexusModsService Query Nexus Mods GraphQL API
IUpdateService Orchestrate update checks (GitHub then Nexus)
ILocalizationService CSV-based i18n with live switching
IDialogService File pickers, confirmation dialogs

Key Data Flows

Mod Discovery

GameDetectionService finds game path
  -> ModDiscoveryService scans Mods/ and Mods.inactive/
  -> Reads Info.json for each folder (via InfoJsonLocator)
  -> MainWindowViewModel creates ModItemViewModels
  -> UI binds to AvailableMods / ActiveMods

Mod Activation

User clicks Activate -> MainWindowViewModel.ActivateModCommand
  -> ModInstallService.ActivateAsync (moves folder)
  -> ModDiscoveryService detects change via FileSystemWatcher (500ms debounce)
  -> MainWindowViewModel refreshes mod lists
  -> AutoActivateDependenciesAsync runs BFS on Requirements

Profile Application

User selects profile -> MainWindowViewModel.ApplyProfileCommand
  -> ProfileService.ComputeDiff (current mods vs profile)
  -> Executes: activate, deactivate, rollback, download
  -> SettingsService updates ActiveProfileName

Cross-Platform

Concern Windows Linux
Game detection Registry + Steam VDF ~/.steam/steam + ~/.local/share/Steam
Open URL/folder Process.Start with UseShellExecute xdg-open
Info.json case Exact match Case-insensitive fallback
App data %APPDATA% $XDG_CONFIG_HOME or ~/.config
Drag-and-drop STA thread Works natively

External Integrations

Integration Library Purpose
GitHub API Octokit 14.0.0 Query releases, download assets
Nexus Mods HttpClient + GraphQL Query mod versions
Steam Registry + VDF parsing Game detection
Steam launch steam://launch/588030/dialog Start game button

Logging

FileLoggerProvider writes rolling daily log files via a BlockingCollection<string> queue and a dedicated background writer thread. Format: [HH:mm:ss.fff] [LVL] [Category] Message.

See Also

Clone this wiki locally