james.maesandClaude Opus 5.5 20c95cffaa refactor: fix analyzer findings and add header comments
Fixes every finding the new quality gate reports, without changing behavior:

- One type per file (MA0048): AppBrand, Attribution, NullActivityLog,
  LogSnapshot, ISanitizable, AppTheme, UpdateCheckResult, UpdateText,
  IUpdateBackend, ContentDialogPrompter, WindowExtensions, MessageBoxPrompter,
  and the samples' SampleSettings/SampleSettingsContext get their own files
  (the samples now link samples/Shared/*.cs).
- Regex match timeouts on the two generated regexes (MA0009).
- AppInfo.Id reports nameof(value) as the parameter (MA0015); test updated.
- Splash dismissal is a named DismissAfterAsync started through the
  dispatcher (MA0147, MA0134), and the WinUI splash constructor is split into
  builders (MA0051). The WPF countdown must go through the dispatcher: the
  sample builds its window before Application.Run, when no synchronization
  context exists.
- The WinUI sample's startup update check is a named method (MA0147).
- CA1859 in BrandTool and the version tests; private static readonly fields
  renamed to s_camelCase (IDE1006).
- A header comment on every type and method (K22-CODE-09/CS-04): hand-written
  for library, sample, and tool code; test methods summarize their
  Subject_Behavior names.

Verified: zero-warning x64 build, 115 unit tests with 100% line coverage of
KofTwentyTwo.AppKit and KofTwentyTwo.AppKit.Updates, 12 UI tests, and
dotnet format --verify-no-changes --severity warn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
2026-10-09 10:23:40 -05:00

AppKit

The shared foundation for KofTwentyTwo Windows apps. Everything a desktop app needs that has nothing to do with what the app actually does: identity, per-user data paths, crash-safe logging, settings, secret storage, a branded splash and About screen, a live log viewer, a crash safety net, theming, and Velopack self-update with stable/dev channels. Extracted from gclo, where every piece shipped in a 1.0 release first.

License: MIT .NET 10 Platform: Windows

Packages

Package Target What it gives you
KofTwentyTwo.AppKit net10.0 AppInfo identity, AppPaths, BuildVersion, FileActivityLog + LogTail, SettingsStore<T> + ShellSettings, CredentialManagerVault, IUserPrompter
KofTwentyTwo.AppKit.Updates net10.0 VelopackStartup, VelopackUpdateService (GitHub Releases, stable/dev channel), UpdateCoordinator (the "Check for updates" flow)
KofTwentyTwo.AppKit.WinUI net10.0-windows10.0.19041.0 SplashOverlay, AboutDialog, LogWindow, DialogGuard, ContentDialogPrompter, WinUIShell (crash net, theme), DPI-aware window helpers
KofTwentyTwo.AppKit.Wpf net10.0-windows SplashOverlay, AboutWindow, LogWindow, MessageBoxPrompter, WpfShell (crash net, Fluent theme)

The two framework-free packages are held to 100% line coverage in CI. The UI packages are built in code rather than XAML, so they work identically in packaged (MSIX) and unpackaged (Velopack) apps, and are exercised end-to-end by FlaUI tests that drive the sample apps.

Using it

New apps should start from the app template rather than wiring this by hand; it references these packages and has everything below already in place. To add AppKit to an existing WinUI app:

// One identity, declared once.
static class MyApp
{
    public static AppInfo Info { get; } = new()
    {
        Id = "myapp",                                    // data folder, log prefix, credential prefix
        DisplayName = "My App",
        Tagline = "Does one thing well",
        RepositoryUrl = new Uri("https://github.com/KofTwentyTwo/myapp"), // also the update feed
        Author = "James Maes",
        Copyright = "Copyright (c) 2026 James Maes",
    };
    public static AppPaths Paths { get; } = new(Info);
}

// Program.Main (with DISABLE_XAML_GENERATED_MAIN): Velopack goes first.
VelopackStartup.Run();

// App constructor
WinUIShell.InstallCrashNet(this, () => Log);
WinUIShell.ApplyTheme(this, settings.ThemeKind);

// Main window
SplashOverlay.ShowOver(RootGrid, MyApp.Info, settings);
var updates = new UpdateCoordinator(
    new VelopackUpdateService(MyApp.Info.RepositoryUrl!),
    new ContentDialogPrompter(() => Content.XamlRoot),
    MyApp.Info.DisplayName, Log);
// Help menu
await updates.CheckInteractivelyAsync();
await AboutDialog.ShowAsync(MyApp.Info, Content.XamlRoot);
LogWindow.ShowSingle(Log, MyApp.Info);

Apps reference Microsoft.WindowsAppSDK themselves (the WinUI package does not carry its build targets), and copy their brand assets (Assets/Brand/app-icon.svg, app.ico) to the output directory. See samples/ for complete WinUI and WPF apps.

Repository layout

src/        the four packages
tests/      unit tests (100% gate) and FlaUI end-to-end tests of the samples
samples/    minimal WinUI and WPF apps wired to every service
tools/      BrandTool: generates app-icon.svg and a multi-size app.ico from one definition
build/      scripts CI shares with every app repo (coverage gate)

Building

dotnet build AppKit.slnx -p:Platform=x64 -warnaserror          # zero warnings, always
dotnet test tests/KofTwentyTwo.AppKit.Tests --settings coverage.runsettings --collect:"XPlat Code Coverage" --results-directory TestResults
./build/Assert-Coverage.ps1 -ResultsDirectory TestResults -Packages KofTwentyTwo.AppKit,KofTwentyTwo.AppKit.Updates
dotnet test tests/KofTwentyTwo.AppKit.UiTests                   # drives the samples; needs a desktop
dotnet format AppKit.slnx --verify-no-changes --severity error

See CONTRIBUTING.md for the branch model and PR expectations, and docs/RELEASING.md for how packages are published.

License

MIT © 2026 James Maes

S
Description
Shared foundation for KofTwentyTwo Windows apps: identity, logging, settings, secrets, splash/About/log UI for WinUI 3 and WPF, and Velopack self-update.
Readme MIT
476 KiB
0 Stars 2 Watchers 0 Forks
AppKit 0.1.0
Latest
2026-10-10 13:51:02 +00:00
Languages
C# 98.5%
PowerShell 1.5%