From 0f73dfdb84acfd237d0b2f8fca6a3d10e3aafe75 Mon Sep 17 00:00:00 2001 From: Oliver Wong Date: Tue, 26 May 2026 13:57:11 +0800 Subject: [PATCH] Creat GUI project framework. --- llm-assist/AGENTS.md => AGENTS.md | 20 ++++++++----- src/GUI/Assets/Locale.Designer.cs | 48 ++++++++++++++++++++++++++++++ src/GUI/Assets/Locale.resx | 21 +++++++++++++ src/GUI/GUI.csproj | 15 ++++++++++ src/Resonance.sln.DotSettings.user | 8 ++++- 5 files changed, 104 insertions(+), 8 deletions(-) rename llm-assist/AGENTS.md => AGENTS.md (75%) create mode 100644 src/GUI/Assets/Locale.Designer.cs create mode 100644 src/GUI/Assets/Locale.resx diff --git a/llm-assist/AGENTS.md b/AGENTS.md similarity index 75% rename from llm-assist/AGENTS.md rename to AGENTS.md index 49cc1a1..d3e42ee 100644 --- a/llm-assist/AGENTS.md +++ b/AGENTS.md @@ -3,23 +3,29 @@ ## Build & Test ```bash -dotnet build # Build all projects -dotnet test # Run all tests +dotnet build # Build all projects +dotnet test # Run all tests dotnet test --filter "FullyQualifiedName~ClassName.MethodName" # Run single test +dotnet run --project src/GUI # Launch the Avalonia desktop app ``` ## Architecture -- **3-project solution** (`src/Resonance.sln`): +- **4-project solution** (`src/Resonance.sln`): - `Core` — class library: audio file scanning, metadata reading (ATL), SQLite persistence (Dapper) - `Core.Tests` — xUnit + FluentAssertions + Moq - - `AtlFieldExtractor` — CLI that dumps ATL metadata fields from WAV files to `.atl.txt` -- **No Avalonia UI yet** — README mentions it but only the Core library exists. + - `AtlFieldExtractor` — CLI that dumps ATL metadata fields from WAV files to `.atl.txt` to test ATL library + - `GUI` — Avalonia 12 desktop app: audio asset management UI +- **MVVM architecture** (GUI project): + - Based on **CommunityToolkit.Mvvm** v8.4.1 — source-generator-driven MVVM toolkit. + - Base class: `ViewModelBase` (abstract, extends `ObservableObject`). Use `[ObservableProperty]` for bindable properties, `[RelayCommand]` for commands, and `SetProperty()` for manual property change notification. + - View-ViewModel binding: `ViewLocator` implements `IDataTemplate` — convention-based resolution by replacing `"ViewModel"` with `"View"` in the type name (e.g., `MainWindowViewModel` → looks for `MainWindow` in `GUI.Views`). Uses `Activator.CreateInstance()`; **no DI container** is configured. + - Compiled bindings are enabled by default (`AvaloniaUseCompiledBindingsByDefault=true` in `.csproj`). Annotate XAML with `x:DataType="vm:MyViewModel"` for compile-time validation. + - `App.axaml` applies `FluentTheme` and registers `ViewLocator` globally. `App.axaml.cs` manually instantiates `MainWindow` → `MainWindowViewModel` in `OnFrameworkInitializationCompleted`. - Target framework: `net10.0` (requires .NET 10 SDK — currently `10.0.103`). ## Known Issues / Gotchas -- **Table name mismatch**: `Database.InitializeDatabase()` creates table `sounds`, but `AddEntry()` / `AddEntries()` / `EntryExists()` reference `audio_files`. Any call to insert or query will fail at runtime. `Database` currently has no test coverage. - **Tests create temp files/directories** under `Path.GetTempPath()` and clean them up via `IDisposable`. Don't rely on a real audio directory for tests. - **`AudioMetadataReader` tests** use real WAV files from `data/source/` (not in git). When files are absent, tests silently return early (`if (wavFiles.Length == 0) return;`) — they pass without actually running assertions, not `Skip.If`. Running `dotnet test` will report 12 passes regardless of whether the fixture files exist. - **`.atl.txt` fixture files** are generated by `AtlFieldExtractor`. If the WAV files or the ATL library version change, re-run the extractor to regenerate them before running metadata tests. @@ -35,7 +41,7 @@ dotnet test --filter "FullyQualifiedName~ClassName.MethodName" # Run single tes ## Conventions - Code and comments are in **Chinese**. -- Namespace: `OCES.Resonance.Core` (Core), `OCES.Resonance.AtlFieldExtractor` (extractor), `OCES.Resonance.Core.Tests` (tests). +- Namespace: `OCES.Resonance.Core` (Core), `OCES.Resonance.AtlFieldExtractor` (extractor), `Core.Tests` (tests), `GUI` / `GUI.Views` / `GUI.ViewModels` (GUI app). ## AI 助手工具说明 diff --git a/src/GUI/Assets/Locale.Designer.cs b/src/GUI/Assets/Locale.Designer.cs new file mode 100644 index 0000000..25b1099 --- /dev/null +++ b/src/GUI/Assets/Locale.Designer.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace GUI { + using System; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Locale { + + private static System.Resources.ResourceManager resourceMan; + + private static System.Globalization.CultureInfo resourceCulture; + + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Locale() { + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Resources.ResourceManager ResourceManager { + get { + if (object.Equals(null, resourceMan)) { + System.Resources.ResourceManager temp = new System.Resources.ResourceManager("GUI.Locale", typeof(Locale).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/src/GUI/Assets/Locale.resx b/src/GUI/Assets/Locale.resx new file mode 100644 index 0000000..a4c5284 --- /dev/null +++ b/src/GUI/Assets/Locale.resx @@ -0,0 +1,21 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/GUI/GUI.csproj b/src/GUI/GUI.csproj index ba7ee4f..59b4e5a 100644 --- a/src/GUI/GUI.csproj +++ b/src/GUI/GUI.csproj @@ -28,4 +28,19 @@ + + + + ResXFileCodeGenerator + Locale.Designer.cs + + + + + + True + True + Locale.resx + + diff --git a/src/Resonance.sln.DotSettings.user b/src/Resonance.sln.DotSettings.user index 6f3ac52..0023a56 100755 --- a/src/Resonance.sln.DotSettings.user +++ b/src/Resonance.sln.DotSettings.user @@ -23,4 +23,10 @@ <TestId>xUnit::24F92458-FB39-44BE-A32F-41275183AF1B::net10.0::Core.Tests.IntegratedTest.ScanReadWritePipeline_ShouldGenerateDatabase</TestId> <TestId>xUnit::24F92458-FB39-44BE-A32F-41275183AF1B::net10.0::Core.Tests.IntegratedTest</TestId> </TestAncestor> -</SessionState> \ No newline at end of file +</SessionState> + True + False + True + False + True + True \ No newline at end of file