Added more UI logic. Added a manga pipeline test.
This commit is contained in:
8
MangaReader.Core/Common/Language.cs
Normal file
8
MangaReader.Core/Common/Language.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace MangaReader.Core.Common;
|
||||||
|
|
||||||
|
public enum Language
|
||||||
|
{
|
||||||
|
Japanese,
|
||||||
|
Romanji,
|
||||||
|
English
|
||||||
|
}
|
||||||
@@ -81,12 +81,12 @@ public class MangaContext(DbContextOptions options) : DbContext(options)
|
|||||||
.HasKey(mangaTitle => mangaTitle.MangaTitleId);
|
.HasKey(mangaTitle => mangaTitle.MangaTitleId);
|
||||||
|
|
||||||
modelBuilder.Entity<MangaTitle>()
|
modelBuilder.Entity<MangaTitle>()
|
||||||
.HasIndex(mangaTitle => new { mangaTitle.MangaId, mangaTitle.TitleEntry })
|
.HasIndex(mangaTitle => new { mangaTitle.MangaId, mangaTitle.Name })
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.Entity<MangaTitle>()
|
.Entity<MangaTitle>()
|
||||||
.HasIndex(mangaTitle => mangaTitle.TitleEntry);
|
.HasIndex(mangaTitle => mangaTitle.Name);
|
||||||
|
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.Entity<MangaTitle>()
|
.Entity<MangaTitle>()
|
||||||
|
|||||||
14
MangaReader.Core/Data/MangaDescription.cs
Normal file
14
MangaReader.Core/Data/MangaDescription.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using MangaReader.Core.Common;
|
||||||
|
|
||||||
|
namespace MangaReader.Core.Data;
|
||||||
|
|
||||||
|
public class MangaDescription
|
||||||
|
{
|
||||||
|
public int MangaTitleId { get; set; }
|
||||||
|
|
||||||
|
public int MangaId { get; set; }
|
||||||
|
public required Manga Manga { get; set; }
|
||||||
|
|
||||||
|
public required string Name { get; set; }
|
||||||
|
public required Language Language { get; set; }
|
||||||
|
}
|
||||||
@@ -7,6 +7,6 @@ public class MangaTitle
|
|||||||
public int MangaId { get; set; }
|
public int MangaId { get; set; }
|
||||||
public required Manga Manga { get; set; }
|
public required Manga Manga { get; set; }
|
||||||
|
|
||||||
public required string TitleEntry { get; set; }
|
public required string Name { get; set; }
|
||||||
public TitleType TitleType { get; set; }
|
public TitleType TitleType { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
using MangaReader.Core.Metadata;
|
namespace MangaReader.Core.Pipeline;
|
||||||
|
|
||||||
namespace MangaReader.Core.Pipeline;
|
|
||||||
|
|
||||||
public interface IMangaPipeline
|
public interface IMangaPipeline
|
||||||
{
|
{
|
||||||
Task RunAsync(SourceManga mangaDto);
|
Task RunAsync(MangaPipelineRequest request);
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,12 @@ namespace MangaReader.Core.Pipeline;
|
|||||||
|
|
||||||
public partial class MangaPipeline(MangaContext context) : IMangaPipeline
|
public partial class MangaPipeline(MangaContext context) : IMangaPipeline
|
||||||
{
|
{
|
||||||
public async Task RunAsync(SourceManga sourceManga)
|
public async Task RunAsync(MangaPipelineRequest request)
|
||||||
{
|
{
|
||||||
|
string sourceName = request.SourceName;
|
||||||
|
SourceManga sourceManga = request.SourceManga;
|
||||||
|
|
||||||
|
Source source = await GetOrAddSourceAsync(sourceName);
|
||||||
Manga manga = await GetOrAddMangaAsync(sourceManga);
|
Manga manga = await GetOrAddMangaAsync(sourceManga);
|
||||||
|
|
||||||
foreach (SourceMangaTitle alternateTitle in sourceManga.AlternateTitles)
|
foreach (SourceMangaTitle alternateTitle in sourceManga.AlternateTitles)
|
||||||
@@ -29,6 +33,23 @@ public partial class MangaPipeline(MangaContext context) : IMangaPipeline
|
|||||||
context.SaveChanges();
|
context.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<Source> GetOrAddSourceAsync(string sourceName)
|
||||||
|
{
|
||||||
|
Source? source = await context.Sources.FirstOrDefaultAsync(s => s.Name == sourceName);
|
||||||
|
|
||||||
|
if (source != null)
|
||||||
|
return source;
|
||||||
|
|
||||||
|
source = new()
|
||||||
|
{
|
||||||
|
Name = sourceName
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Sources.Add(source);
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<Manga> GetOrAddMangaAsync(SourceManga sourceManga)
|
private async Task<Manga> GetOrAddMangaAsync(SourceManga sourceManga)
|
||||||
{
|
{
|
||||||
Manga? manga = await context.Mangas.FirstOrDefaultAsync(manga => manga.Title == sourceManga.Title);
|
Manga? manga = await context.Mangas.FirstOrDefaultAsync(manga => manga.Title == sourceManga.Title);
|
||||||
@@ -65,7 +86,7 @@ public partial class MangaPipeline(MangaContext context) : IMangaPipeline
|
|||||||
private async Task AddTitleAsync(Manga manga, SourceMangaTitle sourceMangaTitle)
|
private async Task AddTitleAsync(Manga manga, SourceMangaTitle sourceMangaTitle)
|
||||||
{
|
{
|
||||||
MangaTitle? mangaTitle = await context.MangaTitles.FirstOrDefaultAsync(mt =>
|
MangaTitle? mangaTitle = await context.MangaTitles.FirstOrDefaultAsync(mt =>
|
||||||
mt.Manga == manga && mt.TitleEntry == sourceMangaTitle.Title);
|
mt.Manga == manga && mt.Name == sourceMangaTitle.Title);
|
||||||
|
|
||||||
if (mangaTitle != null)
|
if (mangaTitle != null)
|
||||||
return;
|
return;
|
||||||
@@ -73,7 +94,7 @@ public partial class MangaPipeline(MangaContext context) : IMangaPipeline
|
|||||||
mangaTitle = new()
|
mangaTitle = new()
|
||||||
{
|
{
|
||||||
Manga = manga,
|
Manga = manga,
|
||||||
TitleEntry = sourceMangaTitle.Title,
|
Name = sourceMangaTitle.Title,
|
||||||
};
|
};
|
||||||
|
|
||||||
context.MangaTitles.Add(mangaTitle);
|
context.MangaTitles.Add(mangaTitle);
|
||||||
|
|||||||
9
MangaReader.Core/Pipeline/MangaPipelineRequest.cs
Normal file
9
MangaReader.Core/Pipeline/MangaPipelineRequest.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using MangaReader.Core.Metadata;
|
||||||
|
|
||||||
|
namespace MangaReader.Core.Pipeline;
|
||||||
|
|
||||||
|
public class MangaPipelineRequest
|
||||||
|
{
|
||||||
|
public required string SourceName { get; init; }
|
||||||
|
public required SourceManga SourceManga { get; init; }
|
||||||
|
}
|
||||||
@@ -7,4 +7,5 @@ public record MangaSearchResult
|
|||||||
public string? Thumbnail { get; init; }
|
public string? Thumbnail { get; init; }
|
||||||
public string? Author { get; init; }
|
public string? Author { get; init; }
|
||||||
public string? Description { get; init; }
|
public string? Description { get; init; }
|
||||||
|
public string[] Genres { get; init; } = [];
|
||||||
}
|
}
|
||||||
@@ -67,6 +67,7 @@ public partial class MangaDexSearchProvider(IMangaDexClient mangaDexClient) : IM
|
|||||||
{
|
{
|
||||||
Title = title,
|
Title = title,
|
||||||
Description = GetDescription(mangaAttributes),
|
Description = GetDescription(mangaAttributes),
|
||||||
|
Genres = GetGenres(mangaAttributes),
|
||||||
Url = $"https://mangadex.org/title/{mangaEntity.Id}/{slug}",
|
Url = $"https://mangadex.org/title/{mangaEntity.Id}/{slug}",
|
||||||
Thumbnail = GetThumbnail(mangaEntity, coverArtEntites)
|
Thumbnail = GetThumbnail(mangaEntity, coverArtEntites)
|
||||||
};
|
};
|
||||||
@@ -95,9 +96,33 @@ public partial class MangaDexSearchProvider(IMangaDexClient mangaDexClient) : IM
|
|||||||
if (attributes.Description.TryGetValue("en", out string? description))
|
if (attributes.Description.TryGetValue("en", out string? description))
|
||||||
return description;
|
return description;
|
||||||
|
|
||||||
|
if (attributes.Description.Count > 0)
|
||||||
|
return attributes.Description.ElementAt(0).Value;
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string[] GetGenres(MangaAttributes attributes)
|
||||||
|
{
|
||||||
|
if (attributes.Tags == null || attributes.Tags.Count == 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
List<string> tags = [];
|
||||||
|
|
||||||
|
foreach (TagEntity tagEntity in attributes.Tags)
|
||||||
|
{
|
||||||
|
if (tagEntity.Attributes == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (tagEntity.Attributes.Name == null || tagEntity.Attributes.Name.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tags.Add(tagEntity.Attributes.Name.FirstOrDefault().Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [.. tags];
|
||||||
|
}
|
||||||
|
|
||||||
public static string GenerateSlug(string title)
|
public static string GenerateSlug(string title)
|
||||||
{
|
{
|
||||||
// title.ToLowerInvariant().Normalize(NormalizationForm.FormD);
|
// title.ToLowerInvariant().Normalize(NormalizationForm.FormD);
|
||||||
|
|||||||
@@ -40,7 +40,8 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.5" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
<PackageReference Include="Shouldly" Version="4.3.0" />
|
<PackageReference Include="Shouldly" Version="4.3.0" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
|
|||||||
53
MangaReader.Tests/Pipeline/MangaPipelineTests.cs
Normal file
53
MangaReader.Tests/Pipeline/MangaPipelineTests.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using MangaReader.Core.Data;
|
||||||
|
using MangaReader.Core.Metadata;
|
||||||
|
using MangaReader.Core.Pipeline;
|
||||||
|
using MangaReader.Tests.Utilities;
|
||||||
|
|
||||||
|
namespace MangaReader.Tests.Pipeline;
|
||||||
|
|
||||||
|
public class MangaPipelineTests(TestDbContextFactory factory) : IClassFixture<TestDbContextFactory>
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task RunAsync_SavesMangaTitlesChaptersGenres()
|
||||||
|
{
|
||||||
|
using MangaContext context = factory.CreateContext();
|
||||||
|
var pipeline = new MangaPipeline(context);
|
||||||
|
|
||||||
|
var sourceManga = new SourceManga
|
||||||
|
{
|
||||||
|
Title = "Fullmetal Alchemist",
|
||||||
|
AlternateTitles =
|
||||||
|
[
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Hagane no Renkinjutsushi",
|
||||||
|
Language = SourceMangaLanguage.Romanji
|
||||||
|
}
|
||||||
|
],
|
||||||
|
Genres = ["Action", "Adventure"],
|
||||||
|
Chapters =
|
||||||
|
[
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Number = 1,
|
||||||
|
Title = "The Two Alchemists",
|
||||||
|
Volume = 1,
|
||||||
|
Url = string.Empty
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
MangaPipelineRequest request = new()
|
||||||
|
{
|
||||||
|
SourceName = "MySource",
|
||||||
|
SourceManga = sourceManga
|
||||||
|
};
|
||||||
|
|
||||||
|
await pipeline.RunAsync(request);
|
||||||
|
|
||||||
|
Assert.Single(context.Mangas);
|
||||||
|
Assert.Single(context.MangaTitles);
|
||||||
|
Assert.Equal(2, context.Genres.Count());
|
||||||
|
Assert.Single(context.MangaChapters);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
MangaReader.Tests/Utilities/TestDbContextFactory.cs
Normal file
36
MangaReader.Tests/Utilities/TestDbContextFactory.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using MangaReader.Core.Data;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace MangaReader.Tests.Utilities;
|
||||||
|
|
||||||
|
public class TestDbContextFactory : IDisposable
|
||||||
|
{
|
||||||
|
private readonly SqliteConnection _connection;
|
||||||
|
private readonly DbContextOptions<MangaContext> _options;
|
||||||
|
|
||||||
|
public TestDbContextFactory()
|
||||||
|
{
|
||||||
|
_connection = new SqliteConnection("DataSource=:memory:");
|
||||||
|
_connection.Open();
|
||||||
|
|
||||||
|
_options = new DbContextOptionsBuilder<MangaContext>()
|
||||||
|
.UseSqlite(_connection)
|
||||||
|
.EnableSensitiveDataLogging() // Optional: helps with debugging
|
||||||
|
.Options;
|
||||||
|
|
||||||
|
using MangaContext context = new(_options);
|
||||||
|
context.Database.EnsureCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MangaContext CreateContext()
|
||||||
|
{
|
||||||
|
return new MangaContext(_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_connection.Close();
|
||||||
|
_connection.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||||
<!-- Other merged dictionaries here -->
|
<!-- Other merged dictionaries here -->
|
||||||
|
<ResourceDictionary Source="/Resources/Converters.xaml"/>
|
||||||
<ResourceDictionary Source="/Resources/Fonts.xaml"/>
|
<ResourceDictionary Source="/Resources/Fonts.xaml"/>
|
||||||
<ResourceDictionary Source="/Resources/Styles.xaml"/>
|
<ResourceDictionary Source="/Resources/Styles.xaml"/>
|
||||||
<ResourceDictionary Source="/Resources/ViewModels.xaml"/>
|
<ResourceDictionary Source="/Resources/ViewModels.xaml"/>
|
||||||
|
|||||||
BIN
MangaReader.WinUI/Assets/Images/MangaReader.png
Normal file
BIN
MangaReader.WinUI/Assets/Images/MangaReader.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
20
MangaReader.WinUI/Converters/UppercaseConverter.cs
Normal file
20
MangaReader.WinUI/Converters/UppercaseConverter.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MangaReader.WinUI.Converters;
|
||||||
|
|
||||||
|
public partial class UppercaseConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object? Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return value.ToString().ToUpperInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,9 +16,18 @@
|
|||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"></RowDefinition>
|
||||||
<RowDefinition Height="*"></RowDefinition>
|
<RowDefinition Height="*"></RowDefinition>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<views:SearchView></views:SearchView>
|
<Grid x:Name="AppTitleBar" Grid.Row="0" VerticalAlignment="Center" Padding="10">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||||
|
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Image Grid.Column="0" x:Name="TitleBarIcon" Source="ms-appx:///Assets/Images/MangaReader.png" Width="20" Height="20" Margin="0 0 10 0" />
|
||||||
|
<TextBlock Grid.Column="1" x:Name="AppTitle" Text="{x:Bind Title, Mode=OneWay}" Style="{StaticResource CaptionTextBlockStyle}" VerticalAlignment="Center" />
|
||||||
|
</Grid>
|
||||||
|
<views:SearchView Grid.Row="1"></views:SearchView>
|
||||||
<!--<StackPanel Orientation="Vertical">
|
<!--<StackPanel Orientation="Vertical">
|
||||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||||
<TextBox Name="KeywordTextBox" Width="300"></TextBox>
|
<TextBox Name="KeywordTextBox" Width="300"></TextBox>
|
||||||
|
|||||||
@@ -1,62 +1,19 @@
|
|||||||
using MangaReader.Core.Search;
|
using MangaReader.Core.Search;
|
||||||
using MangaReader.Core.Sources.MangaDex.Api;
|
using MangaReader.Core.Sources.MangaDex.Api;
|
||||||
using Microsoft.UI.Xaml;
|
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,
|
namespace MangaReader.WinUI;
|
||||||
// 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
|
public sealed partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
private readonly IMangaSearchCoordinator _mangaSearchCoordinator;
|
private const string ApplicationTitle = "Manga Reader";
|
||||||
private readonly IMangaDexClient _mangaDexClient;
|
|
||||||
|
|
||||||
private CancellationTokenSource? _cancellationTokenSource;
|
|
||||||
|
|
||||||
public MainWindow(IMangaSearchCoordinator mangaSearchCoordinator, IMangaDexClient mangaDexClient)
|
public MainWindow(IMangaSearchCoordinator mangaSearchCoordinator, IMangaDexClient mangaDexClient)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
_mangaSearchCoordinator = mangaSearchCoordinator;
|
Title = ApplicationTitle;
|
||||||
_mangaDexClient = mangaDexClient;
|
ExtendsContentIntoTitleBar = true; // enable custom titlebar
|
||||||
}
|
SetTitleBar(AppTitleBar); // set user ui element as titlebar
|
||||||
|
|
||||||
//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.)
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
<None Remove="Assets\Fonts\Poppins-Medium.otf" />
|
<None Remove="Assets\Fonts\Poppins-Medium.otf" />
|
||||||
<None Remove="Assets\Fonts\Poppins-Regular.otf" />
|
<None Remove="Assets\Fonts\Poppins-Regular.otf" />
|
||||||
<None Remove="Assets\Fonts\Poppins-SemiBold.otf" />
|
<None Remove="Assets\Fonts\Poppins-SemiBold.otf" />
|
||||||
|
<None Remove="Assets\Images\MangaReader.png" />
|
||||||
<None Remove="Resources\ViewModels.xaml" />
|
<None Remove="Resources\ViewModels.xaml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||||
<Content Include="Assets\StoreLogo.png" />
|
<Content Include="Assets\StoreLogo.png" />
|
||||||
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
|
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
|
||||||
|
<Content Include="MangaReader.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -45,6 +47,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||||
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250402" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
|
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
|
||||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4188" />
|
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4188" />
|
||||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
|
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
|
||||||
@@ -53,6 +56,9 @@
|
|||||||
<ProjectReference Include="..\MangaReader.Core\MangaReader.Core.csproj" />
|
<ProjectReference Include="..\MangaReader.Core\MangaReader.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Page Update="Resources\Converters.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
<Page Update="Resources\Styles.xaml">
|
<Page Update="Resources\Styles.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
@@ -84,5 +90,6 @@
|
|||||||
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
|
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
|
||||||
<PublishTrimmed Condition="'$(Configuration)' == 'Debug'">False</PublishTrimmed>
|
<PublishTrimmed Condition="'$(Configuration)' == 'Debug'">False</PublishTrimmed>
|
||||||
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>
|
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>
|
||||||
|
<ApplicationIcon>MangaReader.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
BIN
MangaReader.WinUI/MangaReader.ico
Normal file
BIN
MangaReader.WinUI/MangaReader.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
9
MangaReader.WinUI/Resources/Converters.xaml
Normal file
9
MangaReader.WinUI/Resources/Converters.xaml
Normal 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:converters="using:MangaReader.WinUI.Converters">
|
||||||
|
|
||||||
|
<converters:UppercaseConverter x:Key="UppercaseConverter" />
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
@@ -7,47 +7,69 @@
|
|||||||
xmlns:vm="using:MangaReader.WinUI.ViewModels"
|
xmlns:vm="using:MangaReader.WinUI.ViewModels"
|
||||||
xmlns:search="using:MangaReader.Core.Search"
|
xmlns:search="using:MangaReader.Core.Search"
|
||||||
xmlns:UI="using:CommunityToolkit.WinUI"
|
xmlns:UI="using:CommunityToolkit.WinUI"
|
||||||
|
xmlns:Controls="using:CommunityToolkit.WinUI.Controls"
|
||||||
|
xmlns:Media="using:CommunityToolkit.WinUI.Media"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
DataContext="{Binding Source={StaticResource Locator}, Path=SearchViewModel}"
|
DataContext="{Binding Source={StaticResource Locator}, Path=SearchViewModel}"
|
||||||
d:DataContext="{d:DesignInstance Type=vm:SearchViewModel, IsDesignTimeCreatable=True}"
|
d:DataContext="{d:DesignInstance Type=vm:SearchViewModel, IsDesignTimeCreatable=True}"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
|
<Media:AttachedCardShadow x:Key="CommonShadow" Offset="5" BlurRadius="10" Opacity=".4" />
|
||||||
|
|
||||||
<DataTemplate x:Key="MangaSearchResultTemplate" x:DataType="search:MangaSearchResult">
|
<DataTemplate x:Key="MangaSearchResultTemplate" x:DataType="search:MangaSearchResult">
|
||||||
<Grid Padding="20" ColumnSpacing="20" MaxHeight="600" VerticalAlignment="Top" Background="{StaticResource CardBackgroundFillColorDefault}" CornerRadius="8">
|
<Grid Padding="20" ColumnSpacing="20" MaxHeight="400" VerticalAlignment="Stretch" Background="{StaticResource CardBackgroundFillColorDefault}" CornerRadius="8">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Border Grid.Column="0" Width="300">
|
<Border Grid.Column="0" MaxWidth="300" UI:Effects.Shadow="{StaticResource CommonShadow}" VerticalAlignment="Top" HorizontalAlignment="Left">
|
||||||
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" CornerRadius="8">
|
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" CornerRadius="8">
|
||||||
<Image Source="{x:Bind Thumbnail, Mode=OneWay}" MaxWidth="300" UI:Effects.Shadow="{StaticResource CommonShadow}"></Image>
|
<Image Source="{x:Bind Thumbnail, Mode=OneWay}" MaxWidth="300"></Image>
|
||||||
<Canvas Background="#19000000"></Canvas>
|
<Canvas Background="#19000000"></Canvas>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
<Grid Grid.Column="1" RowSpacing="20">
|
<Grid Grid.Column="1" RowSpacing="20">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"></RowDefinition>
|
||||||
<RowDefinition Height="Auto"></RowDefinition>
|
<RowDefinition Height="Auto"></RowDefinition>
|
||||||
<RowDefinition Height="*"></RowDefinition>
|
<RowDefinition Height="*"></RowDefinition>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBlock Grid.Row="0" Text="{x:Bind Title}" FontSize="24" FontFamily="{StaticResource PoppinsSemiBold}" TextWrapping="Wrap"></TextBlock>
|
<TextBlock Grid.Row="0" Text="{x:Bind Title}" FontSize="24" FontFamily="{StaticResource PoppinsSemiBold}" TextWrapping="Wrap"></TextBlock>
|
||||||
<ScrollViewer Grid.Row="1">
|
<ItemsControl Grid.Row="1" ItemsSource="{x:Bind Genres, Mode=OneWay}" ItemTemplate="{StaticResource GenreTemplate}">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<Controls:WrapPanel Orientation="Horizontal" HorizontalSpacing="10" VerticalSpacing="10" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
</ItemsControl>
|
||||||
|
<ScrollViewer Grid.Row="3">
|
||||||
<TextBlock Text="{x:Bind Description}" Foreground="{StaticResource TextFillColorSecondaryBrush}" FontSize="16" TextWrapping="Wrap" LineStackingStrategy="BlockLineHeight" LineHeight="22"></TextBlock>
|
<TextBlock Text="{x:Bind Description}" Foreground="{StaticResource TextFillColorSecondaryBrush}" FontSize="16" TextWrapping="Wrap" LineStackingStrategy="BlockLineHeight" LineHeight="22"></TextBlock>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
|
<DataTemplate x:Key="GenreTemplate" x:DataType="x:String">
|
||||||
|
<Border>
|
||||||
|
<TextBlock FontSize="12" Foreground="{StaticResource TextFillColorTertiary}" Text="{x:Bind Mode=OneWay, Converter={StaticResource UppercaseConverter}}" FontFamily="{StaticResource PoppinsSemiBold}"></TextBlock>
|
||||||
|
</Border>
|
||||||
|
</DataTemplate>
|
||||||
|
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
<Grid Padding="0" RowSpacing="20">
|
<Grid Padding="0" RowSpacing="20">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"></RowDefinition>
|
<RowDefinition Height="Auto"></RowDefinition>
|
||||||
<RowDefinition Height="*"></RowDefinition>
|
<RowDefinition Height="*"></RowDefinition>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center" Padding="20">
|
<Border HorizontalAlignment="Stretch">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center" Padding="10">
|
||||||
<TextBox Text="{Binding Keyword, Mode=TwoWay}" Width="300"></TextBox>
|
<TextBox Text="{Binding Keyword, Mode=TwoWay}" Width="300"></TextBox>
|
||||||
<Button Content="Search" Command="{Binding SearchCommand}"></Button>
|
<Button Content="Search" Command="{Binding SearchCommand}"></Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
<ScrollViewer Grid.Row="1" RenderTransformOrigin=".5,.5" Padding="50">
|
<ScrollViewer Grid.Row="1" RenderTransformOrigin=".5,.5" Padding="50">
|
||||||
<ScrollViewer.RenderTransform>
|
<ScrollViewer.RenderTransform>
|
||||||
<ScaleTransform ScaleX="1" ScaleY="1" />
|
<ScaleTransform ScaleX="1" ScaleY="1" />
|
||||||
|
|||||||
Reference in New Issue
Block a user