Added UI app.

This commit is contained in:
2025-06-01 22:29:14 -04:00
parent 1348684144
commit 7dbcdc6169
36 changed files with 1645 additions and 25 deletions

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Application
x:Class="MangaReader.WinUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MangaReader.WinUI">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
<ResourceDictionary Source="/Resources/Fonts.xaml"/>
<ResourceDictionary Source="/Resources/Styles.xaml"/>
<ResourceDictionary Source="/Resources/ViewModels.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,37 @@
using MangaReader.WinUI.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
using System;
namespace MangaReader.WinUI;
public partial class App : Application
{
private Window? _window;
public static IServiceProvider ServiceProvider { get; private set; }
static App()
{
ServiceCollection services = new();
services.AddSingleton<MainWindow>();
services.AddSingleton<SearchViewModel>();
services.AddMangaReader();
ServiceProvider = services.BuildServiceProvider();
}
public App()
{
InitializeComponent();
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
_window = ServiceProvider.GetRequiredService<MainWindow>();
_window.Activate();
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="MangaReader.WinUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MangaReader.WinUI"
xmlns:views="using:MangaReader.WinUI.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MangaReader.WinUI">
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<views:SearchView></views:SearchView>
<!--<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal" Spacing="10">
<TextBox Name="KeywordTextBox" Width="300"></TextBox>
<Button Content="Search" Click="Button_Click"></Button>
</StackPanel>
<Image Name="CoverImage" Width="256" Height="364" Source="https://mangadex.org/covers/a920060c-7e39-4ac1-980c-f0e605a40ae4/07d02b26-cbd0-4323-8774-9d83579863d5.jpg.256.jpg"></Image>
</StackPanel>-->
</Grid>
</Window>

View File

@@ -0,0 +1,62 @@
using MangaReader.Core.Search;
using MangaReader.Core.Sources.MangaDex.Api;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using Windows.Foundation;
using Windows.Foundation.Collections;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace MangaReader.WinUI
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainWindow : Window
{
private readonly IMangaSearchCoordinator _mangaSearchCoordinator;
private readonly IMangaDexClient _mangaDexClient;
private CancellationTokenSource? _cancellationTokenSource;
public MainWindow(IMangaSearchCoordinator mangaSearchCoordinator, IMangaDexClient mangaDexClient)
{
InitializeComponent();
_mangaSearchCoordinator = mangaSearchCoordinator;
_mangaDexClient = mangaDexClient;
}
//private async void Button_Click(object sender, RoutedEventArgs e)
//{
// if (string.IsNullOrWhiteSpace(KeywordTextBox.Text))
// return;
// _cancellationTokenSource?.Cancel();
// _cancellationTokenSource = new();
// var result = await _mangaSearchCoordinator.SearchAsync(KeywordTextBox.Text, _cancellationTokenSource.Token);
// //Guid mangaGuid = new("a920060c-7e39-4ac1-980c-f0e605a40ae4");
// //var coverArtResult = await _mangaDexClient.GetCoverArtAsync(mangaGuid, _cancellationTokenSource.Token);
// // if ( (coverArtResult is MangaDexC)
// // {
// // }
// // if (coverArtResult.)
//}
}
}

View File

@@ -0,0 +1,88 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>MangaReader.WinUI</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x86;x64;ARM64</Platforms>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<Nullable>enable</Nullable>
<WindowsPackageType>None</WindowsPackageType>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\Fonts\Poppins-Medium.otf" />
<None Remove="Assets\Fonts\Poppins-Regular.otf" />
<None Remove="Assets\Fonts\Poppins-SemiBold.otf" />
<None Remove="Resources\ViewModels.xaml" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<!--
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
Tools extension to be activated for this project even if the Windows App SDK Nuget
package has not yet been restored.
-->
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4188" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MangaReader.Core\MangaReader.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Page Update="Resources\Styles.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Resources\Fonts.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\SearchView.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Resources\ViewModels.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<!--
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
Explorer "Package and Publish" context menu entry to be enabled for this project even if
the Windows App SDK Nuget package has not yet been restored.
-->
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
</PropertyGroup>
<!-- Publish Properties -->
<PropertyGroup>
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
<PublishTrimmed Condition="'$(Configuration)' == 'Debug'">False</PublishTrimmed>
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity
Name="cdba7326-1a2b-45f0-a233-463a21c91c91"
Publisher="CN=Brian"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="cdba7326-1a2b-45f0-a233-463a21c91c91" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>MangaReader.WinUI</DisplayName>
<PublisherDisplayName>Brian</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="MangaReader.WinUI"
Description="MangaReader.WinUI"
BackgroundColor="transparent"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

View File

@@ -0,0 +1,10 @@
{
"profiles": {
"MangaReader.WinUI (Package)": {
"commandName": "MsixPackage"
},
"MangaReader.WinUI (Unpackaged)": {
"commandName": "Project"
}
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MangaReader.WinUI.ViewModels">
<FontFamily x:Key="PoppinsRegular">ms-appx:///Assets/Fonts/Poppins-Regular.ttf#Poppins Regular</FontFamily>
<FontFamily x:Key="PoppinsMedium">ms-appx:///Assets/Fonts/Poppins-Medium.ttf#Poppins Medium</FontFamily>
<FontFamily x:Key="PoppinsSemiBold">ms-appx:///Assets/Fonts/Poppins-SemiBold.ttf#Poppins SemiBold</FontFamily>
</ResourceDictionary>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Media="using:CommunityToolkit.WinUI.Media">
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PoppinsRegular}" />
</Style>
<Media:AttachedCardShadow x:Key="CommonShadow" Offset="5" BlurRadius="10" Opacity=".4" />
</ResourceDictionary>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MangaReader.WinUI.ViewModels">
<vm:ViewModelLocator x:Key="Locator" />
</ResourceDictionary>

View File

@@ -0,0 +1,67 @@
using CommunityToolkit.Mvvm.Input;
using MangaReader.Core.Search;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
namespace MangaReader.WinUI.ViewModels;
public partial class SearchViewModel(IMangaSearchCoordinator searchCoordinator) : ViewModelBase
{
private CancellationTokenSource? _cancellationTokenSource;
private string? _keyword;
public string? Keyword
{
get
{
return _keyword;
}
set
{
SetProperty(ref _keyword, value);
}
}
private ObservableCollection<MangaSearchResult> _searchResults = [];
public ObservableCollection<MangaSearchResult> SearchResults
{
get
{
return _searchResults;
}
set
{
SetProperty(ref _searchResults, value);
}
}
public ICommand SearchCommand => new AsyncRelayCommand(SearchAsync);
public async Task SearchAsync()
{
if (string.IsNullOrWhiteSpace(Keyword))
return;
_cancellationTokenSource?.Cancel();
_cancellationTokenSource = new();
Dictionary<string, MangaSearchResult[]> result = await searchCoordinator.SearchAsync(Keyword, _cancellationTokenSource.Token);
List<MangaSearchResult> searchResults = [];
foreach (var item in result)
{
foreach (MangaSearchResult searchResult in item.Value)
{
searchResults.Add(searchResult);
}
}
SearchResults = new(searchResults);
}
}

View File

@@ -0,0 +1,8 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace MangaReader.WinUI.ViewModels;
public partial class ViewModelBase : ObservableObject
{
}

View File

@@ -0,0 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
namespace MangaReader.WinUI.ViewModels;
public class ViewModelLocator
{
public static SearchViewModel SearchViewModel
=> App.ServiceProvider.GetRequiredService<SearchViewModel>();
}

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="MangaReader.WinUI.Views.SearchView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MangaReader.WinUI.Views"
xmlns:vm="using:MangaReader.WinUI.ViewModels"
xmlns:search="using:MangaReader.Core.Search"
xmlns:UI="using:CommunityToolkit.WinUI"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{Binding Source={StaticResource Locator}, Path=SearchViewModel}"
d:DataContext="{d:DesignInstance Type=vm:SearchViewModel, IsDesignTimeCreatable=True}"
mc:Ignorable="d">
<UserControl.Resources>
<DataTemplate x:Key="MangaSearchResultTemplate" x:DataType="search:MangaSearchResult">
<Grid Padding="20" ColumnSpacing="20" MaxHeight="600" VerticalAlignment="Top" Background="{StaticResource CardBackgroundFillColorDefault}" CornerRadius="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Width="300">
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" CornerRadius="8">
<Image Source="{x:Bind Thumbnail, Mode=OneWay}" MaxWidth="300" UI:Effects.Shadow="{StaticResource CommonShadow}"></Image>
<Canvas Background="#19000000"></Canvas>
</Grid>
</Border>
<Grid Grid.Column="1" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{x:Bind Title}" FontSize="24" FontFamily="{StaticResource PoppinsSemiBold}" TextWrapping="Wrap"></TextBlock>
<ScrollViewer Grid.Row="1">
<TextBlock Text="{x:Bind Description}" Foreground="{StaticResource TextFillColorSecondaryBrush}" FontSize="16" TextWrapping="Wrap" LineStackingStrategy="BlockLineHeight" LineHeight="22"></TextBlock>
</ScrollViewer>
</Grid>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid Padding="0" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center" Padding="20">
<TextBox Text="{Binding Keyword, Mode=TwoWay}" Width="300"></TextBox>
<Button Content="Search" Command="{Binding SearchCommand}"></Button>
</StackPanel>
<ScrollViewer Grid.Row="1" RenderTransformOrigin=".5,.5" Padding="50">
<ScrollViewer.RenderTransform>
<ScaleTransform ScaleX="1" ScaleY="1" />
</ScrollViewer.RenderTransform>
<ItemsRepeater ItemsSource="{Binding SearchResults, Mode=OneWay}" ItemTemplate="{StaticResource MangaSearchResultTemplate}">
<ItemsRepeater.Layout>
<UniformGridLayout MinRowSpacing="50" MinColumnSpacing="50" ItemsStretch="Fill" MinItemWidth="800"></UniformGridLayout>
</ItemsRepeater.Layout>
</ItemsRepeater>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,12 @@
using MangaReader.Core.Search;
using Microsoft.UI.Xaml.Controls;
namespace MangaReader.WinUI.Views;
public sealed partial class SearchView : UserControl
{
public SearchView()
{
InitializeComponent();
}
}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MangaReader.WinUI.app"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- The ID below informs the system that this application is compatible with OS features first introduced in Windows 10.
It is necessary to support features in unpackaged applications, for example the custom titlebar implementation.
For more info see https://docs.microsoft.com/windows/apps/windows-app-sdk/use-windows-app-sdk-run-time#declare-os-compatibility-in-your-application-manifest -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>