Creat GUI project framework.
This commit is contained in:
@@ -6,20 +6,26 @@
|
|||||||
dotnet build # Build all projects
|
dotnet build # Build all projects
|
||||||
dotnet test # Run all tests
|
dotnet test # Run all tests
|
||||||
dotnet test --filter "FullyQualifiedName~ClassName.MethodName" # Run single test
|
dotnet test --filter "FullyQualifiedName~ClassName.MethodName" # Run single test
|
||||||
|
dotnet run --project src/GUI # Launch the Avalonia desktop app
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture
|
## 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` — class library: audio file scanning, metadata reading (ATL), SQLite persistence (Dapper)
|
||||||
- `Core.Tests` — xUnit + FluentAssertions + Moq
|
- `Core.Tests` — xUnit + FluentAssertions + Moq
|
||||||
- `AtlFieldExtractor` — CLI that dumps ATL metadata fields from WAV files to `.atl.txt`
|
- `AtlFieldExtractor` — CLI that dumps ATL metadata fields from WAV files to `.atl.txt` to test ATL library
|
||||||
- **No Avalonia UI yet** — README mentions it but only the Core library exists.
|
- `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<T>()` 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`).
|
- Target framework: `net10.0` (requires .NET 10 SDK — currently `10.0.103`).
|
||||||
|
|
||||||
## Known Issues / Gotchas
|
## 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.
|
- **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.
|
- **`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.
|
- **`.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
|
## Conventions
|
||||||
|
|
||||||
- Code and comments are in **Chinese**.
|
- 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 助手工具说明
|
## AI 助手工具说明
|
||||||
|
|
||||||
Generated
+48
@@ -0,0 +1,48 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<root>
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
@@ -28,4 +28,19 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Core\Core.csproj" />
|
<ProjectReference Include="..\Core\Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="Assets\Locale.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Locale.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Assets\Locale.Designer.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Locale.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -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.ScanReadWritePipeline_ShouldGenerateDatabase</TestId>
|
||||||
<TestId>xUnit::24F92458-FB39-44BE-A32F-41275183AF1B::net10.0::Core.Tests.IntegratedTest</TestId>
|
<TestId>xUnit::24F92458-FB39-44BE-A32F-41275183AF1B::net10.0::Core.Tests.IntegratedTest</TestId>
|
||||||
</TestAncestor>
|
</TestAncestor>
|
||||||
</SessionState></s:String></wpf:ResourceDictionary>
|
</SessionState></s:String>
|
||||||
|
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=GUI_002FAssets_002FLocale/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=GUI_002FLocale/@EntryIndexedValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=GUI_002FLocale/@EntryIndexRemoved">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=GUI_002FResources1/@EntryIndexedValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=GUI_002FResources1/@EntryIndexRemoved">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
Reference in New Issue
Block a user