From d62ae0b9fbb7417e6d80e81f4bd42e845029f7d0 Mon Sep 17 00:00:00 2001 From: Gregor Klevze Date: Tue, 11 Aug 2026 13:55:44 +0200 Subject: [PATCH] Polish AmiReel UI and improve render workflow --- .../accessibility.instructions.md | 62 +++ .../instructions/code-quality.instructions.md | 170 +++++++ .../design-principles.instructions.md | 134 ++++++ .../globalization.instructions.md | 55 +++ .../instructions/performance.instructions.md | 53 +++ .../instructions/security.instructions.md | 55 +++ .../instructions/testing.instructions.md | 284 ++++++++++++ .../instructions/windows-apis.instructions.md | 92 ++++ .../winui-best-practices.instructions.md | 420 ++++++++++++++++++ AmiReel.WinUI/.gitignore | 54 +++ AmiReel.WinUI/AGENTS.md | 270 +++++++++++ AmiReel.WinUI/AmiReel.WinUI.csproj | 84 ++++ AmiReel.WinUI/App.xaml | 16 + AmiReel.WinUI/App.xaml.cs | 47 ++ AmiReel.WinUI/Assets/AppIcon.ico | Bin 0 -> 370070 bytes .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 1090 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 12625 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 6357 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 1910 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 574 bytes ...go.targetsize-48_altform-lightunplated.png | Bin 0 -> 1091 bytes AmiReel.WinUI/Assets/StoreLogo.png | Bin 0 -> 1106 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 5843 bytes AmiReel.WinUI/MainPage.xaml | 182 ++++++++ AmiReel.WinUI/MainPage.xaml.cs | 293 ++++++++++++ AmiReel.WinUI/MainWindow.xaml | 34 ++ AmiReel.WinUI/MainWindow.xaml.cs | 27 ++ AmiReel.WinUI/Package.appxmanifest | 53 +++ AmiReel.WinUI/Properties/launchSettings.json | 10 + AmiReel.WinUI/app.manifest | 19 + AmigaDB.VideoRenderer.csproj | 8 + AmigaDB.VideoRenderer.sln | 31 +- MainWindow.xaml | 334 +++++++------- MainWindow.xaml.cs | 68 +++ Models/AppSettings.cs | 3 + Services/ProcessRunner.cs | 12 +- Services/RenderPipeline.cs | 21 +- Services/ToolExtractor.cs | 3 + 38 files changed, 2711 insertions(+), 183 deletions(-) create mode 100644 AmiReel.WinUI/.github/instructions/accessibility.instructions.md create mode 100644 AmiReel.WinUI/.github/instructions/code-quality.instructions.md create mode 100644 AmiReel.WinUI/.github/instructions/design-principles.instructions.md create mode 100644 AmiReel.WinUI/.github/instructions/globalization.instructions.md create mode 100644 AmiReel.WinUI/.github/instructions/performance.instructions.md create mode 100644 AmiReel.WinUI/.github/instructions/security.instructions.md create mode 100644 AmiReel.WinUI/.github/instructions/testing.instructions.md create mode 100644 AmiReel.WinUI/.github/instructions/windows-apis.instructions.md create mode 100644 AmiReel.WinUI/.github/instructions/winui-best-practices.instructions.md create mode 100644 AmiReel.WinUI/.gitignore create mode 100644 AmiReel.WinUI/AGENTS.md create mode 100644 AmiReel.WinUI/AmiReel.WinUI.csproj create mode 100644 AmiReel.WinUI/App.xaml create mode 100644 AmiReel.WinUI/App.xaml.cs create mode 100644 AmiReel.WinUI/Assets/AppIcon.ico create mode 100644 AmiReel.WinUI/Assets/LockScreenLogo.scale-200.png create mode 100644 AmiReel.WinUI/Assets/SplashScreen.scale-200.png create mode 100644 AmiReel.WinUI/Assets/Square150x150Logo.scale-200.png create mode 100644 AmiReel.WinUI/Assets/Square44x44Logo.scale-200.png create mode 100644 AmiReel.WinUI/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 AmiReel.WinUI/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png create mode 100644 AmiReel.WinUI/Assets/StoreLogo.png create mode 100644 AmiReel.WinUI/Assets/Wide310x150Logo.scale-200.png create mode 100644 AmiReel.WinUI/MainPage.xaml create mode 100644 AmiReel.WinUI/MainPage.xaml.cs create mode 100644 AmiReel.WinUI/MainWindow.xaml create mode 100644 AmiReel.WinUI/MainWindow.xaml.cs create mode 100644 AmiReel.WinUI/Package.appxmanifest create mode 100644 AmiReel.WinUI/Properties/launchSettings.json create mode 100644 AmiReel.WinUI/app.manifest diff --git a/AmiReel.WinUI/.github/instructions/accessibility.instructions.md b/AmiReel.WinUI/.github/instructions/accessibility.instructions.md new file mode 100644 index 0000000..e54c035 --- /dev/null +++ b/AmiReel.WinUI/.github/instructions/accessibility.instructions.md @@ -0,0 +1,62 @@ +--- +description: 'Accessibility requirements for interactive controls, keyboard navigation, screen readers, and contrast' +applyTo: '**/*.cs, **/*.xaml' +--- + +# Accessibility + +These rules apply to **every UI change**. They are not optional add-ons. + +--- + +## Rules + +- **Every interactive control** must have an `AutomationProperties.Name` or `AutomationProperties.LabeledBy`. +- Add a stable, unique `AutomationProperties.AutomationId` for controls targeted by UI automation tests (and for key interactive elements). +- Use semantic XAML controls — prefer `Button`, `HyperlinkButton`, `ListView` over styled `Border`/`Grid` with click handlers. +- Ensure **keyboard navigation** works for all features: + - Logical tab order via `TabIndex`. + - `AccessKey` bindings for frequently used actions. + - `KeyboardAccelerator` for shortcut keys. +- Maintain **minimum contrast ratios** (4.5:1 for normal text, 3:1 for large text) — test in High Contrast mode. +- Support **screen readers** (Narrator / NVDA): test that all content is announced correctly. +- Images must have `AutomationProperties.Name` describing the image purpose (or `AutomationProperties.AccessibilityView="Raw"` for decorative images). +- Do not rely on colour alone to convey meaning — add icons, text, or patterns. + +## Anti-patterns + +- Clickable `TextBlock` or `Image` without `AutomationProperties`. +- Custom controls that are not keyboard-focusable. +- Using `Visibility.Collapsed` to "hide" content from screen readers (use `AccessibilityView` instead). + +## Validation + +- Build & register the MSIX package — see **Build, Run & Deploy** in `.github/agents/Agents.md`. +- Test keyboard navigation: tab through every new/changed UI area. +- Test High Contrast: switch to Windows High Contrast theme and verify readability. +- Run Accessibility Insights for Windows on the app. + +### Verification Checklist + +- [ ] All interactive controls have `AutomationProperties.Name` +- [ ] Keyboard navigation works for the changed area +- [ ] Tested with High Contrast theme enabled +- [ ] Tab through the entire UI with keyboard only. +- [ ] Verify key interactive controls have stable, unique `AutomationProperties.AutomationId` values (especially controls used by UI automation tests). +- [ ] Switch to Windows High Contrast theme and verify readability. +- [ ] Run Narrator and verify all controls are announced correctly. +- [ ] Run **Accessibility Insights for Windows** on the app. + +## Must Read & Research + +> **Agent Rule:** Before any accessibility-related change, you **must** fetch and review these references using `fetch_webpage`. Apply what you learn. + +| # | Reference | When to consult | +|---|---|---| +| 1 | [Accessibility in WinUI](https://learn.microsoft.com/en-us/windows/apps/design/accessibility/accessibility) | Any UI change — verify accessibility approach | +| 2 | [AutomationProperties](https://learn.microsoft.com/en-us/windows/apps/design/accessibility/basic-accessibility-information) | Adding or modifying interactive controls | +| 3 | [Accessibility Insights](https://accessibilityinsights.io/docs/windows/overview/) | Testing tool — run before finalizing UI changes | +| 4 | [Keyboard Accessibility](https://learn.microsoft.com/en-us/windows/apps/design/accessibility/keyboard-accessibility) | Adding navigation, focus management, or shortcut keys | +| 5 | [High Contrast Themes](https://learn.microsoft.com/en-us/windows/apps/design/accessibility/high-contrast-themes) | Adding custom styles, colours, or theme resources | + + diff --git a/AmiReel.WinUI/.github/instructions/code-quality.instructions.md b/AmiReel.WinUI/.github/instructions/code-quality.instructions.md new file mode 100644 index 0000000..d18b4b8 --- /dev/null +++ b/AmiReel.WinUI/.github/instructions/code-quality.instructions.md @@ -0,0 +1,170 @@ +--- +description: 'Static analysis, StyleCop, EditorConfig, naming conventions, and code cleanup rules' +applyTo: '**/*.cs, **/*.editorconfig, **/stylecop.json' +--- + +# Code Quality — Static Analysis, StyleCop & Code Cleanup + +Maintain strict code quality through automated analysis and consistent style enforcement. + +--- + +## 1. Static Analysis (Roslyn Analyzers) + +### Required Analyzer Packages + +Add these to the `.csproj` if not already present: + +```xml + + + + + all + runtime; build; native; contentfiles; analyzers + + +``` + +### Analysis Configuration in `.csproj` + +```xml + + true + latest-recommended + true + false + enable + +``` + +### Rule Enforcement + +Follow **all** CA* (quality) and IDE* (code style) analyzer rules at their configured severity. Do not cherry-pick — obey every warning the analyzers report. When encountering a specific rule violation, fetch the corresponding documentation from the **Must Read & Research** references below to understand and apply the correct fix. + +### `.editorconfig` + +The project's `.editorconfig` in the solution root is the source of truth for code style. Obey all rules defined there. When creating or modifying `.editorconfig`, fetch the [EditorConfig Reference](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options) for the full list of available settings. + +Key project conventions enforced via `.editorconfig`: +- Private fields use `_camelCase` prefix (SA1101 suppressed, SA1309 suppressed). +- File-scoped namespaces are required. +- `this.` qualification is not used. + +--- + +## 2. StyleCop Rules + +### StyleCop Configuration (`stylecop.json`) + +Place this file in the project root alongside the `.csproj`: + +```json +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "YourProjectName", + "copyrightText": "Copyright (c) {companyName}. All rights reserved.", + "xmlHeader": false, + "documentInterfaces": true, + "documentExposedElements": true, + "documentInternalElements": false, + "documentPrivateElements": false, + "documentPrivateFields": false + }, + "orderingRules": { + "usingDirectivesPlacement": "outsideNamespace", + "systemUsingDirectivesFirst": true + }, + "layoutRules": { + "newlineAtEndOfFile": "require" + }, + "namingRules": { + "allowCommonHungarianPrefixes": false + } + } +} +``` + +### Rule Enforcement + +Follow **all** SA* (StyleCop) rules at their configured severity. When encountering a specific SA* violation, fetch the [StyleCop Rules Reference](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/DOCUMENTATION.md) to understand the rule and apply the correct fix. Do not suppress rules without justification in a code comment. + +--- + +## 3. Code Cleanup Rules (Always Enforced) + +### After Every Edit + +1. **Remove unused `using` statements** — No unused imports should remain. +2. **Remove commented-out code** — Version control tracks history; dead code is noise. +3. **Remove unused variables and fields** — If it's declared but never read, delete it. +4. **Remove empty methods** — If an event handler or override does nothing, remove it. +5. **Simplify code** — Apply IDE suggestions (IDE0001–IDE0090) for: + - Removing unnecessary casts + - Simplifying `default` expressions + - Using pattern matching + - Using null-coalescing operators + +### Naming Conventions + +| Element | Convention | Example | +|---|---|---| +| Class / Struct | PascalCase | `MainViewModel` | +| Interface | I + PascalCase | `INavigationService` | +| Public method | PascalCase | `LoadDataAsync()` | +| Private method | PascalCase | `ValidateInput()` | +| Public property | PascalCase | `CurrentPage` | +| Private field | _camelCase | `_settingsService` | +| Parameter | camelCase | `userName` | +| Local variable | camelCase | `itemCount` | +| Constant | PascalCase | `MaxRetryCount` | +| Async method | Suffix `Async` | `FetchDataAsync()` | +| Boolean | Prefix `Is/Has/Can` | `IsLoading`, `HasAccess` | + +### File Organization + +Each `.cs` file should follow this order: + +1. `using` directives (System first, then others, alphabetically) +2. Namespace declaration (file-scoped) +3. Class/struct/interface declaration +4. Inside the type: + 1. Constants + 2. Static fields + 3. Instance fields + 4. Constructors + 5. Properties + 6. Public methods + 7. Private/internal methods + 8. Event handlers + 9. Nested types + +--- + +## Validation + +- Build & register the MSIX package — see **Build, Run & Deploy** in `.github/agents/Agents.md`. +- Fix **all** warnings — do not suppress without justification in a code comment. +- Verify no unused `using` statements remain after every edit. +- Verify no commented-out code remains. +- Confirm naming conventions match the table above for every new symbol. + +--- + +## Must Read & Research + +> **Agent Rule:** Before configuring analyzers, fixing warnings, or adjusting code style, you **must** fetch and review the relevant references below using `fetch_webpage`. Apply what you learn — do not skip this step. + +| # | Reference | When to consult | +|---|---|---| +| 1 | [.NET Code Analysis Overview](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview) | Setting up or modifying analyzer configuration | +| 2 | [Code Style Rules (IDE0001–IDE0090)](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/) | Resolving IDE* warnings or adjusting `.editorconfig` | +| 3 | [Quality Rules (CA*)](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/) | Resolving CA* warnings or suppressing with justification | +| 4 | [StyleCop.Analyzers GitHub](https://github.com/DotNetAnalyzers/StyleCopAnalyzers) | Adding/updating StyleCop package or configuration | +| 5 | [StyleCop Rules Reference](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/DOCUMENTATION.md) | Understanding specific SA* rule violations | +| 6 | [EditorConfig Reference](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options) | Modifying `.editorconfig` style or severity settings | +| 7 | [.NET Naming Conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names) | Verifying naming patterns for types, members, parameters | + + diff --git a/AmiReel.WinUI/.github/instructions/design-principles.instructions.md b/AmiReel.WinUI/.github/instructions/design-principles.instructions.md new file mode 100644 index 0000000..296f716 --- /dev/null +++ b/AmiReel.WinUI/.github/instructions/design-principles.instructions.md @@ -0,0 +1,134 @@ +--- +description: 'Design principles (DRY, KISS, SOLID, YAGNI) enforced in every code change' +applyTo: '**/*.cs, **/*.xaml' +--- + +# Design Principles + +Apply these principles in **every change** you make to this codebase. When in doubt, favour simplicity and clarity over cleverness. + +--- + +## 1. DRY — Don't Repeat Yourself + +> *"Every piece of knowledge must have a single, unambiguous, authoritative representation within a system."* + +### Rules +- Before writing new code, **search** the codebase for existing implementations that solve the same problem. +- Extract shared logic into helper methods, base classes, or services. +- If you find duplicated code during a task, **refactor it** as part of the same change. +- Prefer generic/reusable components over copy-paste variations. + +### Anti-patterns to avoid +- Copy-pasting code between classes/files instead of extracting a shared method. +- Creating multiple converters/helpers that do the same thing. +- Duplicating validation logic across ViewModel and Model layers. + +--- + +## 2. KISS — Keep It Simple, Stupid + +> *"Simplicity is the ultimate sophistication."* + +### Rules +- Choose the **simplest approach** that meets the requirement. +- Avoid unnecessary abstractions, inheritance hierarchies, or patterns that add complexity without clear benefit. +- Write code that **reads like plain English** — favour descriptive names over comments. +- If a method is longer than ~30 lines, consider splitting it. +- If a class does more than one thing, split it (see SRP below). + +### Anti-patterns to avoid +- Over-engineering with factories/builders/strategies for simple object creation. +- Creating deep inheritance trees when composition would suffice. +- Using complex LINQ chains when a simple `foreach` is clearer. + +--- + +## 3. SOLID Principles + +### 3.1 SRP — Single Responsibility Principle +> *"A class should have only one reason to change."* + +- Each class/file should have **one clear responsibility**. +- ViewModels handle UI state & commands. Services handle business logic. Models hold data. +- If a class name contains "And" or "Manager", it likely violates SRP. + +### 3.2 OCP — Open/Closed Principle +> *"Software entities should be open for extension, but closed for modification."* + +- Use interfaces and abstract classes so behaviour can be extended without modifying existing code. +- Prefer adding new implementations over modifying existing ones. +- Use dependency injection to swap implementations. + +### 3.3 LSP — Liskov Substitution Principle +> *"Objects of a superclass should be replaceable with objects of its subclasses without altering correctness."* + +- Derived classes must honour the contracts of their base classes. +- Never throw `NotImplementedException` in overridden methods — if a subclass can't fulfil the contract, the inheritance is wrong. + +### 3.4 ISP — Interface Segregation Principle +> *"No client should be forced to depend on methods it does not use."* + +- Keep interfaces small and focused. +- Prefer multiple small interfaces over one large one. +- Example: `INavigationService`, `IDialogService`, `ISettingsService` — not `IAppService`. + +### 3.5 DIP — Dependency Inversion Principle +> *"Depend upon abstractions, not concretions."* + +- High-level modules must not depend on low-level modules. Both should depend on abstractions. +- Use constructor injection for dependencies. +- Register services in a DI container (e.g., `Microsoft.Extensions.DependencyInjection`). + +--- + +## 4. YAGNI — You Aren't Gonna Need It + +> *"Don't add functionality until it is necessary."* + +### Rules +- Only implement what is **explicitly requested** or **clearly needed right now**. +- Do not add "just in case" parameters, methods, or abstractions. +- If you're unsure whether something is needed, **leave it out** — it can always be added later. + +### Anti-patterns to avoid +- Adding unused interface methods "for future use". +- Building a generic framework when a single concrete class suffices. +- Creating configuration options nobody has asked for. + +--- + +## Quick Reference Checklist + +Before submitting any code change, verify: + +- [ ] No duplicated code exists (DRY) +- [ ] The solution is as simple as possible (KISS) +- [ ] Each class has one responsibility (SRP) +- [ ] New behaviour is added via extension, not modification (OCP) +- [ ] Derived types can substitute their base types (LSP) +- [ ] Interfaces are small and focused (ISP) +- [ ] Dependencies point toward abstractions (DIP) +- [ ] No speculative features were added (YAGNI) + +## Validation + +- Review every new/changed class for SRP violations — ask "does this class have more than one reason to change?" +- Search the codebase for duplicate logic before adding new helpers: `grep_search` for similar method names or patterns. +- Verify no speculative code was added — every line must trace back to the original request. +- Build & register the MSIX package — see **Build, Run & Deploy** in `.github/agents/Agents.md`. + +--- + +## Must Read & Research + +> **Agent Rule:** Before making any code change related to design principles, you **must** fetch and review the relevant references below using `fetch_webpage`. Apply what you learn — do not skip this step. + +| # | Reference | When to consult | +|---|---|---| +| 1 | [SOLID Principles in C# — Microsoft Learn](https://learn.microsoft.com/en-us/archive/msdn-magazine/2014/may/csharp-best-practices-dangers-of-violating-solid-principles-in-csharp) | Adding/refactoring classes, interfaces, or inheritance | +| 2 | [.NET Design Guidelines](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/) | Designing public APIs, naming, type design | +| 3 | [Framework Design Guidelines (Book)](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/) | Deep-dive on member design, exception patterns, collections | +| 4 | [Clean Code Summary](https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29) | Code readability, function size, naming clarity | + + diff --git a/AmiReel.WinUI/.github/instructions/globalization.instructions.md b/AmiReel.WinUI/.github/instructions/globalization.instructions.md new file mode 100644 index 0000000..6816b6d --- /dev/null +++ b/AmiReel.WinUI/.github/instructions/globalization.instructions.md @@ -0,0 +1,55 @@ +--- +description: 'Globalization & Localization requirements for user-facing strings, resource files, and culture-aware formatting' +applyTo: '**/*.cs, **/*.xaml, **/*.resw' +--- + +# Globalization & Localization + +These rules apply to **every feature and change** involving user-facing text. They are not optional add-ons. + +--- + +## Rules + +- **All user-facing strings** (UI text, error messages, tooltips) must come from `.resw` resource files — never hard-code them in XAML or C#. +- Resource file location: `Strings/en-us/Resources.resw` (default locale). +- Use `x:Uid` in XAML to bind controls to resource keys: + ```xml + + ``` + With a matching `.resw` entry: `WelcomeMessage.Text` = "Welcome!" +- In code-behind / ViewModels, use the `ResourceLoader`: + ```csharp + var loader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader(); + string message = loader.GetString("ErrorFileNotFound"); + ``` +- **Format dates, numbers, and currencies** using `CultureInfo.CurrentCulture` or `DateTimeFormatter` — never assume a specific regional format. +- Avoid concatenating translated strings — use format placeholders (`{0}`, `{1}`). +- Design UI layouts to accommodate text expansion (~30-40% longer for German vs. English). + +## Anti-patterns + +- Hard-coded strings in `.xaml` or `.cs` files (e.g., `Content="Save"`). +- Using `string.Format` with hard-coded ordinal assumptions. +- Fixed-width UI elements that clip translated text. + +## Validation + +- Build & register the MSIX package — see **Build, Run & Deploy** in `.github/agents/Agents.md`. +- Check for hard-coded strings: search `Content="` and `Text="` in `.xaml` files — replace with `x:Uid`. + +### Verification Checklist + +- [ ] All user-facing strings are in `.resw` resource files + +## Must Read & Research + +> **Agent Rule:** Before any localization-related change, you **must** fetch and review these references using `fetch_webpage`. Apply what you learn. + +| # | Reference | When to consult | +|---|---|---| +| 1 | [Globalize your WinUI app](https://learn.microsoft.com/en-us/windows/apps/design/globalizing/guidelines-and-checklist-for-globalizing-your-app) | Adding any new user-facing strings or culture-aware formatting | +| 2 | [Resource Management System](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/mrtcore/localize-strings) | Setting up or modifying `.resw` files and `ResourceLoader` usage | +| 3 | [WinUI Localization with x:Uid](https://learn.microsoft.com/en-us/windows/apps/develop/ui-input/localizing-strings) | Binding XAML controls to localized resources via `x:Uid` | + + diff --git a/AmiReel.WinUI/.github/instructions/performance.instructions.md b/AmiReel.WinUI/.github/instructions/performance.instructions.md new file mode 100644 index 0000000..09eed79 --- /dev/null +++ b/AmiReel.WinUI/.github/instructions/performance.instructions.md @@ -0,0 +1,53 @@ +--- +description: 'Performance requirements for data binding, layout, threading, and collection virtualization' +applyTo: '**/*.cs, **/*.xaml' +--- + +# Performance + +These rules apply to **every feature and change**. They are not optional add-ons. + +--- + +## Rules + +- **Use `x:Bind`** (compiled bindings) instead of `{Binding}` — it's faster and type-safe. +- Use **`x:Load`** (or `x:DeferLoadStrategy`) to defer loading of UI elements not immediately visible. +- Avoid heavy work on the UI thread — use `Task.Run` for CPU-bound work and `async/await` for I/O. +- Use **virtualizing panels** (`ItemsRepeater` with `StackLayout`, or `ListView`) for long lists — never use `StackPanel` with hundreds of items. +- **Cache** expensive computations and HTTP responses when appropriate. +- Minimize XAML visual tree depth — deep nesting hurts layout performance. +- Use **incremental loading** (`ISupportIncrementalLoading`) for large data sets. +- Profile with **Visual Studio Diagnostics Tools** and **PerfView** before and after optimizations. +- Be cautious with `DispatcherQueue.TryEnqueue` — don't flood the dispatcher queue. + +## Anti-patterns + +- Blocking the UI thread with `.Result` or `.GetAwaiter().GetResult()`. +- Loading all data upfront when only a subset is needed. +- Creating new `HttpClient` instances per request (use `IHttpClientFactory`). +- Using `FindName()` or `VisualTreeHelper` in tight loops. + +## Validation + +- Build & register the MSIX package — see **Build, Run & Deploy** in `.github/agents/Agents.md`. + +### Verification Checklist + +- [ ] No blocking calls on the UI thread +- [ ] `x:Bind` is used instead of `{Binding}` +- [ ] Large lists use virtualization + +## Must Read & Research + +> **Agent Rule:** Before any performance-sensitive change (data binding, layout, collections, async), you **must** fetch and review these references using `fetch_webpage`. Apply what you learn. + +| # | Reference | When to consult | +|---|---|---| +| 1 | [Performance best practices for WinUI 3](https://learn.microsoft.com/en-us/windows/apps/performance/) | Any change touching UI rendering, data loading, or threading | +| 2 | [x:Bind markup extension](https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/x-bind-markup-extension) | Adding or modifying XAML data bindings | +| 3 | [x:Load attribute](https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/x-load-attribute) | Deferring UI element loading | +| 4 | [Optimize XAML layout](https://learn.microsoft.com/en-us/windows/apps/performance/optimize-xaml-layout) | Restructuring XAML panels, reducing visual tree depth | +| 5 | [ListView optimization](https://learn.microsoft.com/en-us/windows/apps/performance/optimize-listview) | Working with lists, collections, or `ItemsRepeater` | + + diff --git a/AmiReel.WinUI/.github/instructions/security.instructions.md b/AmiReel.WinUI/.github/instructions/security.instructions.md new file mode 100644 index 0000000..6eeab88 --- /dev/null +++ b/AmiReel.WinUI/.github/instructions/security.instructions.md @@ -0,0 +1,55 @@ +--- +description: 'Security requirements for secrets management, input validation, permissions, and secure coding' +applyTo: '**/*.cs, **/*.appxmanifest' +--- + +# Security + +These rules apply to **every feature and change**. They are not optional add-ons. + +--- + +## Rules + +- **Never hard-code secrets** (API keys, passwords, connection strings) — use environment variables, Windows Credential Manager, or Azure Key Vault. +- Validate and sanitize **all external input** (user input, file content, network responses). +- Use `SecureString` or `PasswordVault` for sensitive data in memory when practical. +- Follow the **principle of least privilege** — request only the permissions the app actually needs in `Package.appxmanifest`. +- Keep NuGet packages up to date — run `dotnet list package --outdated` regularly. +- Enable **code signing** for published MSIX packages. Use the `winapp` CLI rather than hand-rolling `signtool`: + - Generate a development certificate matching the manifest publisher: `winapp cert generate --manifest .\Package.appxmanifest --install`. + - Inspect a cert before signing: `winapp cert info .\devcert.pfx`. + - Sign an existing file: `winapp sign .\MyApp.msix --cert .\devcert.pfx`. + - Build + sign in one step: `winapp pack .\bin\\Release\\win- --cert .\devcert.pfx`. + - Production releases must be signed by a trusted certificate authority -- never ship the development cert. +- When using `HttpClient`, always validate TLS certificates and use HTTPS. +- Never log sensitive data (PII, tokens, passwords). + +## Anti-patterns + +- Storing secrets in `appsettings.json` committed to source control. +- Disabling TLS validation for debugging and forgetting to re-enable it. +- Using `Process.Start` with unsanitized user input. +- Broad `try { } catch (Exception) { }` that swallows errors silently without any logging. + +## Validation + +- Build & register the MSIX package — see **Build, Run & Deploy** in `.github/agents/Agents.md`. +- Check for hard-coded secrets: search for `password`, `apikey`, `secret`, `connectionstring` in `.cs` files. + +### Verification Checklist + +- [ ] No secrets are hard-coded + +## Must Read & Research + +> **Agent Rule:** Before any security-related change (auth, input handling, permissions, HTTP), you **must** fetch and review these references using `fetch_webpage`. Apply what you learn. + +| # | Reference | When to consult | +|---|---|---| +| 1 | [.NET Security Best Practices](https://learn.microsoft.com/en-us/dotnet/standard/security/) | Any code handling credentials, tokens, or sensitive data | +| 2 | [Secure coding guidelines for .NET](https://learn.microsoft.com/en-us/dotnet/standard/security/secure-coding-guidelines) | Input validation, exception handling, type safety | +| 3 | [MSIX Security](https://learn.microsoft.com/en-us/windows/msix/msix-container) | Packaging, signing, or distribution changes | +| 4 | [Package.appxmanifest capabilities](https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations) | Adding or modifying app capabilities/permissions | + + diff --git a/AmiReel.WinUI/.github/instructions/testing.instructions.md b/AmiReel.WinUI/.github/instructions/testing.instructions.md new file mode 100644 index 0000000..8a08739 --- /dev/null +++ b/AmiReel.WinUI/.github/instructions/testing.instructions.md @@ -0,0 +1,284 @@ +--- +description: 'Unit testing standards, test project setup, naming, build & run commands' +applyTo: '**/*Tests.cs, **/*Test.cs, **/*.Tests.csproj' +--- + +# Testing — Unit Tests, Build & Run + +Every public method and class must have corresponding unit tests. Tests are not optional. + +--- + +## 1. Test Framework & Project Setup + +### Recommended Stack + +| Component | Package | Purpose | +|---|---|---| +| Test Framework | `MSTest` | Test runner & assertions | +| Mocking | `Moq` | Mock dependencies | +| UI Testing | `Microsoft.Windows.Apps.Test` | WinUI UI automation (optional) | + +### Test Project Setup + +Create a test project alongside the main project: + +``` +/ + / ← Main app project + .Tests/ ← Unit test project +``` + +Test project `.csproj` should reference the main project: + +```xml + + + + + true + enable + false + + + + + + + + + + + + + + +``` + +--- + +## 2. Test Writing Rules + +### What to Test +- **All public methods** in ViewModels, Services, Helpers, and Models. +- **Edge cases** — null inputs, empty collections, boundary values. +- **Error paths** — exception handling, invalid state transitions. +- **Business logic** — calculations, transformations, state management. + +### What NOT to Test (Directly) +- XAML layout / visual rendering (use UI tests for that). +- Framework internals (e.g., `InitializeComponent()`). +- Private methods — test them indirectly through public methods. + +### Test Naming Convention + +Use the pattern: `MethodName_Scenario_ExpectedResult` + +```csharp +[TestMethod] +public void CalculateTotal_WithEmptyCart_ReturnsZero() { } + +[TestMethod] +public void LoadDataAsync_WhenServiceThrows_SetsErrorState() { } + +[TestMethod] +public async Task SaveAsync_WithValidInput_ReturnsTrue() { } +``` + +### Test Structure (AAA Pattern) + +Every test follows **Arrange → Act → Assert**: + +```csharp +[TestMethod] +public void Add_TwoPositiveNumbers_ReturnsSum() +{ + // Arrange + var calculator = new Calculator(); + + // Act + int result = calculator.Add(2, 3); + + // Assert + Assert.AreEqual(5, result); +} +``` + +### ViewModel Testing Example + +```csharp +[TestMethod] +public async Task LoadItemsAsync_OnSuccess_PopulatesItems() +{ + // Arrange + var mockService = new Mock(); + mockService + .Setup(s => s.GetItemsAsync()) + .ReturnsAsync(new List { new("Test") }); + + var viewModel = new MainViewModel(mockService.Object); + + // Act + await viewModel.LoadItemsAsync(); + + // Assert + Assert.AreEqual(1, viewModel.Items.Count); + Assert.IsFalse(viewModel.IsLoading); +} +``` + +--- + +## 3. Test Organization + +### File Structure + +Mirror the main project's folder structure (defined in [winui-best-practices](winui-best-practices.instructions.md)) in the test project. As the main project grows with subfolders under `ViewModels/`, `Services/`, `Views/`, etc., the test project must grow organically in the same way. This alignment enables on-demand test runs scoped to the area you changed: + +``` +/ .Tests/ + Models/ Models/ + User.cs UserTests.cs + ViewModels/ ViewModels/ + MainViewModelTests.cs MainViewModelTests.cs + Settings/ Settings/ + ThemeViewModel.cs ThemeViewModelTests.cs + Services/ Services/ + DataService.cs DataServiceTests.cs + Auth/ Auth/ + AuthService.cs AuthServiceTests.cs + Helpers/ Helpers/ + StringHelper.cs StringHelperTests.cs + Converters/ Converters/ + BoolToVisibilityConverter.cs BoolToVisibilityConverterTests.cs +``` + +### One Test Class per Class Under Test + +```csharp +namespace .Tests.ViewModels; + +[TestClass] +public class MainViewModelTests +{ + // All tests for MainViewModel go here +} +``` + +### Running Tests On-Demand + +After a change, run only the tests related to the affected area instead of the full suite. Detect the platform first (matching the convention in `.github/agents/Agents.md`): + +```powershell +# Run from the test project folder +cd .Tests + +# Detect platform once per session (AMD64 -> x64; ARM64/x86 unchanged) +$arch = $env:PROCESSOR_ARCHITECTURE +$Platform = if ($arch -eq 'AMD64') { 'x64' } else { $arch } + +# Run tests for a specific class +dotnet test -c Debug -p:Platform=$Platform --filter "FullyQualifiedName~MainViewModelTests" + +# Run a single test +dotnet test -c Debug -p:Platform=$Platform --filter "FullyQualifiedName~MainViewModelTests.LoadItemsAsync_OnSuccess_PopulatesItems" + +# Run all tests in a namespace (e.g., all ViewModel tests) +dotnet test -c Debug -p:Platform=$Platform --filter "FullyQualifiedName~Tests.ViewModels" + +# Run tests in a subfolder namespace (e.g., only Settings ViewModels) +dotnet test -c Debug -p:Platform=$Platform --filter "FullyQualifiedName~Tests.ViewModels.Settings" + +# Run the full suite (for cross-cutting changes) +dotnet test -c Debug -p:Platform=$Platform +``` +``` + +--- + +## 4. Test-Specific Commands + +For general build and register commands, see **Build, Run & Deploy** in `.github/agents/Agents.md`. +For on-demand test filtering, see **Running Tests On-Demand** above. + +Below are additional test commands: + +### Build Only the Test Project + +```powershell +cd .Tests +$arch = $env:PROCESSOR_ARCHITECTURE +$Platform = if ($arch -eq 'AMD64') { 'x64' } else { $arch } +dotnet build -c Debug -p:Platform=$Platform +``` + +### Run Tests with Verbose Output + +```powershell +dotnet test -c Debug -p:Platform=$Platform --verbosity normal +``` + +--- + +## 5. Agent Workflow for Tests + +When you write or modify code, follow this sequence: + +1. **Implement the feature or fix** in the main project. +2. **Write unit tests** for every new/changed public method. +3. **Build** — see **Build, Run & Deploy** in `.github/agents/Agents.md`. Fix all errors and warnings. +4. **Run tests** — `dotnet test -c Debug -p:Platform=$Platform` (from the test project folder; detect `$Platform` as shown above) and ensure all pass. +5. **Review** — Confirm tests cover the happy path, edge cases, and error cases. + +### When Modifying Existing Code + +1. **Run existing tests first** to establish a baseline. +2. Make the code change. +3. **Run tests again** — fix any failures. +4. **Add new tests** if the change introduces new behaviour. + +### Coverage Goals + +- Aim for **80%+ code coverage** on business logic (ViewModels, Services). +- 100% coverage of utility/helper methods. +- UI code-behind is exempt from unit test coverage (tested via integration/UI tests). + +--- + +## 6. Common Test Pitfalls + +| Pitfall | Fix | +|---|---| +| Test depends on another test's state | Each test must be fully independent | +| Testing multiple things in one test | One assertion per logical concept | +| Tests pass but don't actually verify anything | Always have meaningful assertions | +| Mocking too much | Mock only external dependencies, not the class under test | +| Testing implementation details | Test behaviour and outcomes, not internal method calls | +| Async tests without `await` | Always `await` async methods and use `async Task` return type | + +--- + +## Validation + +- Build & run tests — see **Build, Run & Deploy** in `.github/agents/Agents.md`. +- Verify all tests pass — zero failures, zero skipped without justification. +- Verify naming follows `MethodName_Scenario_ExpectedResult` pattern. +- Verify AAA structure (Arrange/Act/Assert) in every test method. +- Confirm coverage goals: 80%+ on ViewModels/Services, 100% on helpers. + +--- + +## Must Read & Research + +> **Agent Rule:** Before writing or modifying tests, you **must** fetch and review the relevant references below using `fetch_webpage`. Apply what you learn — do not skip this step. + +| # | Reference | When to consult | +|---|---|---| +| 1 | [Unit testing C# with MSTest](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-mstest) | Setting up test project, writing first tests, MSTest attributes | +| 2 | [Unit testing best practices .NET](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices) | Every time you write tests — naming, structure, AAA pattern | +| 3 | [Moq Quickstart](https://github.com/devlooped/moq/wiki/Quickstart) | Mocking interfaces, setting up `Returns`/`Throws`, verifying calls | +| 4 | [FluentAssertions Documentation](https://fluentassertions.com/introduction) | Writing expressive assertions (`Should().Be()`, collections, exceptions) | +| 5 | [dotnet test CLI](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-test) | Running tests from terminal, filtering, verbosity options | +| 6 | [Test Explorer in Visual Studio](https://learn.microsoft.com/en-us/visualstudio/test/run-unit-tests-with-test-explorer) | Debugging tests, viewing coverage, understanding test output | + + diff --git a/AmiReel.WinUI/.github/instructions/windows-apis.instructions.md b/AmiReel.WinUI/.github/instructions/windows-apis.instructions.md new file mode 100644 index 0000000..002e776 --- /dev/null +++ b/AmiReel.WinUI/.github/instructions/windows-apis.instructions.md @@ -0,0 +1,92 @@ +--- +description: 'WinAppSDK & Windows Platform SDK -- API namespace catalog and lookup guidance' +applyTo: '**/*.cs, **/*.xaml, **/*.csproj' +--- + +# Windows APIs -- WinAppSDK & Windows Platform SDK + +## Sample-First Rule + +> **Agent Rule -- MANDATORY:** Before implementing **any** WinAppSDK or Windows Platform SDK API you have not used before, you **must** search the sample repositories below for a working example first. **Do not guess API usage patterns from documentation alone** -- the docs often omit critical details that only the sample code reveals. Search **all** of the following repos, not just one: + +| # | Repository | What it covers | +|---|---|---| +| 1 | [WindowsAppSDK-Samples](https://github.com/microsoft/WindowsAppSDK-Samples) | All WinAppSDK features (AI, windowing, lifecycle, notifications, etc.) | +| 2 | [AI Dev Gallery](https://github.com/microsoft/ai-dev-gallery) | On-device AI/ML patterns, model usage examples | +| 3 | [WinUI-Gallery](https://github.com/microsoft/WinUI-Gallery) | UI control patterns and XAML examples | + +### How to apply + +1. **Find the right API** -- Translate the user's scenario/requirement into common API/programming keywords, then search the API references (Part A-B below) using those keywords to identify which API fits. +2. **Search for samples** -- Once you know which API to use, search each sample repo above for the class name to find a working example. +3. **Study the sample** -- Read the sample's Model / ViewModel / Service layer to understand how the API is actually called -- object lifetime, required parameters, data preparation, error handling. +4. **Adapt** the sample pattern into our MVVM architecture -- don't copy the sample structure wholesale, but match its API call sequence exactly. + +--- + +> **Agent Rule:** Before implementing any feature that involves a platform capability, **consult this file** to check whether a built-in API already exists. Always verify exact class names, method signatures, and availability by following the reference links -- do not guess API shapes. + +--- + +## Part A -- Windows App SDK APIs + +**Full API reference:** + +> **Agent Rule:** Do not rely on a hardcoded namespace list -- the SDK is updated frequently. Instead, **search** the API reference above by converting the user's scenario into common programming keywords. + +### How to search + +1. **Translate** the user's request into API/programming terms. Examples: + - "I want to describe an image" -> search for: `image description`, `ImageDescription`, `describe image` + - "Add a notification" -> search for: `notification`, `toast`, `AppNotification` + - "Pick a file" -> search for: `file picker`, `StoragePicker`, `FileOpenPicker` + - "Make the window always on top" -> search for: `AppWindow`, `presenter`, `compact overlay` +2. **Search** the [WinAppSDK API reference](https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/) using `web_search` or `web_fetch` with those keywords. +3. **Verify** the class/method exists in the SDK version used by this project (check `.csproj` `` for `Microsoft.WindowsAppSDK` version). + +### Key reference links + +| # | Link | When to consult | +|---|---|---| +| 1 | [WinAppSDK API Reference (full)](https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/) | **Always** -- search and look up exact class/method signatures here | +| 2 | [Windows App SDK overview](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/) | Feature overview, architecture | +| 3 | [Release notes (stable)](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/stable-channel) | API availability, version support, breaking changes | +| 4 | [Windows AI overview](https://learn.microsoft.com/en-us/windows/ai/) | All AI options: Windows AI APIs, Windows ML, Foundry Local | +| 5 | [Get started with Windows AI APIs](https://learn.microsoft.com/en-us/windows/ai/apis/get-started) | Prerequisites, project setup, first AI call | +| 6 | [Windows ML overview](https://learn.microsoft.com/en-us/windows/ai/new-windows-ml/overview) | Custom ONNX model inference | +| 7 | [Foundry Local](https://learn.microsoft.com/en-us/windows/ai/foundry-local/get-started) | Run OSS LLMs locally | + +--- + +## Part B -- Windows Platform SDK (UWP / WinRT APIs) + +**Full API reference:** + +> **Agent Rule:** The Platform SDK (`Windows.*` namespaces) is very large and constantly evolving. Do not rely on a hardcoded list. **Search** the API reference by translating the user's requirement into programming keywords. + +### How to search + +1. **Translate** the user's request into API/programming terms. Examples: + - "Send a Bluetooth message" -> search for: `Bluetooth`, `RFCOMM`, `BluetoothDevice` + - "Get the user's location" -> search for: `geolocation`, `Geolocator`, `position` + - "Read text from an image" -> search for: `OCR`, `text recognition`, `OcrEngine` + - "Copy to clipboard" -> search for: `clipboard`, `DataTransfer`, `DataPackage` +2. **Search** the [Platform SDK API reference](https://learn.microsoft.com/en-us/uwp/api/) using `web_search` or `web_fetch` with those keywords. +3. **Check for WinAppSDK equivalent** -- some Platform SDK APIs have newer equivalents in Part A. Always prefer the WinAppSDK version when both exist. + +### Key reference links + +| # | Link | When to consult | +|---|---|---| +| 1 | [Platform SDK API Reference (full)](https://learn.microsoft.com/en-us/uwp/api/) | **Search here** for any Windows capability not in WinAppSDK | +| 2 | [Windows SDK downloads](https://developer.microsoft.com/windows/downloads/windows-sdk/) | SDK versions and downloads | + +--- + +## Validation + +- Before implementing any platform feature, confirm the API is available in the current Windows App SDK version by checking the [release notes](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/stable-channel). +- For features requiring specific hardware (NPU), provide a graceful fallback for unsupported devices. +- When both WinAppSDK and Platform SDK offer a similar API, prefer the WinAppSDK version. + + diff --git a/AmiReel.WinUI/.github/instructions/winui-best-practices.instructions.md b/AmiReel.WinUI/.github/instructions/winui-best-practices.instructions.md new file mode 100644 index 0000000..a8565ac --- /dev/null +++ b/AmiReel.WinUI/.github/instructions/winui-best-practices.instructions.md @@ -0,0 +1,420 @@ +--- +description: 'WinUI 3 / WinAppSDK architecture, MVVM, XAML patterns, DI, theming, and controls guidance' +applyTo: '**/*.cs, **/*.xaml, **/*.csproj' +--- + +# WinUI 3 / WinAppSDK -- Best Practices & Patterns + +This file covers WinUI 3-specific patterns, conventions, and architecture guidance for this project. + +--- + +## 1. Architecture -- MVVM Pattern + +### Overview + +Use **Model-View-ViewModel (MVVM)** for all UI features: + +| Layer | Responsibility | Example | +|---|---|---| +| **Model** | Data structures & business entities | `Item.cs`, `UserProfile.cs` | +| **View** | XAML UI -- layout, styles, animations | `MainPage.xaml` | +| **ViewModel** | UI state, commands, data transformation | `MainViewModel.cs` | +| **Service** | Business logic, data access, navigation | `IDataService.cs`, `NavigationService.cs` | + +### Project Folder Structure + +``` +/ + Models/ -> Data classes + ViewModels/ -> ViewModels (one per page/dialog) + Views/ -> XAML pages and windows + Services/ -> Business logic & platform services + Converters/ -> IValueConverter implementations + Helpers/ -> Static utility methods + Controls/ -> Custom/reusable controls + Strings/ + en-us/ + Resources.resw + Assets/ -> Images, icons, splash screens +``` + +### ViewModel Base + +Use `CommunityToolkit.Mvvm` (recommended) for boilerplate-free ViewModels: + +```xml + + +``` + +```csharp +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; + +public partial class MainViewModel : ObservableObject +{ + [ObservableProperty] + private string _title = string.Empty; + + [ObservableProperty] + private bool _isLoading; + + [RelayCommand] + private async Task LoadDataAsync() + { + IsLoading = true; + try + { + // Load data + } + finally + { + IsLoading = false; + } + } +} +``` + +### View-ViewModel Binding + +```xml + + + + + + + + +