Added common language enum. Fixed "romaji" spelling. More UI updates.
This commit is contained in:
@@ -1,7 +1,15 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using MangaReader.Core.Search;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
@@ -10,6 +18,8 @@ namespace MangaReader.WinUI.ViewModels;
|
||||
|
||||
public partial class SearchViewModel(IMangaSearchCoordinator searchCoordinator) : ViewModelBase
|
||||
{
|
||||
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
private CancellationTokenSource? _cancellationTokenSource;
|
||||
|
||||
private string? _keyword;
|
||||
@@ -40,6 +50,20 @@ public partial class SearchViewModel(IMangaSearchCoordinator searchCoordinator)
|
||||
}
|
||||
}
|
||||
|
||||
private ObservableCollection<ObservableMangaSearchResult> _searchResults2 = [];
|
||||
|
||||
public ObservableCollection<ObservableMangaSearchResult> SearchResults2
|
||||
{
|
||||
get
|
||||
{
|
||||
return _searchResults2;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetProperty(ref _searchResults2, value);
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand SearchCommand => new AsyncRelayCommand(SearchAsync);
|
||||
|
||||
public async Task SearchAsync()
|
||||
@@ -53,15 +77,114 @@ public partial class SearchViewModel(IMangaSearchCoordinator searchCoordinator)
|
||||
Dictionary<string, MangaSearchResult[]> result = await searchCoordinator.SearchAsync(Keyword, _cancellationTokenSource.Token);
|
||||
|
||||
List<MangaSearchResult> searchResults = [];
|
||||
|
||||
List<ObservableMangaSearchResult> mangaSearchResults = [];
|
||||
|
||||
foreach (var item in result)
|
||||
{
|
||||
foreach (MangaSearchResult searchResult in item.Value)
|
||||
{
|
||||
//searchResults.Add(searchResult);
|
||||
|
||||
ObservableMangaSearchResult mangaSearchResult = new()
|
||||
{
|
||||
Title = searchResult.Title,
|
||||
Thumbnail = searchResult.Thumbnail,
|
||||
Description = searchResult.Description,
|
||||
Genres = searchResult.Genres
|
||||
};
|
||||
|
||||
Task.Run(() => mangaSearchResult.LoadThumbnailAsync(_dispatcherQueue)); // or defer this if you want lazy loading
|
||||
|
||||
searchResults.Add(searchResult);
|
||||
mangaSearchResults.Add(mangaSearchResult);
|
||||
}
|
||||
}
|
||||
|
||||
SearchResults = new(searchResults);
|
||||
SearchResults2 = new(mangaSearchResults);
|
||||
}
|
||||
|
||||
public static async Task<BitmapImage?> LoadWebpAsBitmapImageAsync(string? url)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
return null;
|
||||
|
||||
using var httpClient = new HttpClient();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:139.0) Gecko/20100101 Firefox/139.0");
|
||||
using var webpStream = await httpClient.GetStreamAsync(url);
|
||||
|
||||
using var image = await Image.LoadAsync(webpStream); // from SixLabors.ImageSharp
|
||||
using var ms = new MemoryStream();
|
||||
//await image.SaveAsPngAsync(ms); // Convert to PNG in memory
|
||||
await image.SaveAsJpegAsync(ms);
|
||||
ms.Position = 0;
|
||||
|
||||
var bitmap = new BitmapImage();
|
||||
await bitmap.SetSourceAsync(ms.AsRandomAccessStream());
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ObservableMangaSearchResult : ObservableObject
|
||||
{
|
||||
public string? Title { get; init; }
|
||||
public string? Description { get; init; }
|
||||
public string? Thumbnail { get; init; }
|
||||
public string[] Genres { get; init; } = [];
|
||||
|
||||
private BitmapImage? _thumbnailBitmap;
|
||||
|
||||
public BitmapImage? ThumbnailBitmap
|
||||
{
|
||||
get
|
||||
{
|
||||
return _thumbnailBitmap;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetProperty(ref _thumbnailBitmap, value);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task LoadThumbnailAsync(DispatcherQueue dispatchQueue)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Thumbnail))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
using var httpClient = new HttpClient();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0");
|
||||
|
||||
using var stream = await httpClient.GetStreamAsync(Thumbnail);
|
||||
using var image = await Image.LoadAsync(stream); // Important: use a pixel type
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.SaveAsJpegAsync(ms); // or SaveAsPngAsync
|
||||
ms.Position = 0;
|
||||
|
||||
TaskCompletionSource taskCompletionSource = new();
|
||||
|
||||
dispatchQueue.TryEnqueue(async () => {
|
||||
var bitmap = new BitmapImage();
|
||||
await bitmap.SetSourceAsync(ms.AsRandomAccessStream());
|
||||
|
||||
ThumbnailBitmap = bitmap;
|
||||
|
||||
taskCompletionSource.SetResult();
|
||||
});
|
||||
|
||||
taskCompletionSource.Task.GetAwaiter().GetResult();
|
||||
|
||||
//var bitmap = new BitmapImage();
|
||||
//await bitmap.SetSourceAsync(ms.AsRandomAccessStream());
|
||||
|
||||
//ThumbnailBitmap = bitmap;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[Thumbnail Load Failed] {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user