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

@@ -21,43 +21,83 @@ public partial class MangaDexSearchProvider(IMangaDexClient mangaDexClient) : IM
if (response == null || (response is not MangaDexCollectionResponse collectionResponse))
return [];
List<MangaSearchResult> mangaSearchResults = [];
MangaEntity[] mangaEntities = [.. collectionResponse.Data.Where(entity => entity is MangaEntity).Cast<MangaEntity>()];
foreach (MangaDexEntity entity in collectionResponse.Data)
if (mangaEntities.Length == 0)
return [];
Dictionary<Guid, List<CoverArtEntity>> mangaCoverArtMap = await GetCoverArtFileNamesAsync(mangaEntities, cancellationToken);
List<MangaSearchResult> mangaSearchResults = [];
Dictionary<Guid, MangaSearchResult> thing = [];
foreach (MangaEntity mangaEntity in mangaEntities)
{
MangaSearchResult? mangaSearchResult = GetMangaSearchResult(entity);
CoverArtEntity[] coverArtEntites = [.. mangaCoverArtMap[mangaEntity.Id]];
MangaSearchResult? mangaSearchResult = GetMangaSearchResult(mangaEntity, coverArtEntites);
if (mangaSearchResult == null)
continue;
mangaSearchResults.Add(mangaSearchResult);
}
if (thing.Count > 0)
{
Guid[] mangaGuids = thing.Select(x => x.Key).ToArray();
var reults = await GetCoverArtFileNamesAsync(mangaGuids, cancellationToken);
//var reults = await mangaDexClient.GetCoverArtAsync(mangaGuids, cancellationToken);
}
return [.. mangaSearchResults];
}
private static MangaSearchResult? GetMangaSearchResult(MangaDexEntity entity)
private static MangaSearchResult? GetMangaSearchResult(MangaEntity mangaEntity, CoverArtEntity[] coverArtEntites)
{
if (entity is not MangaEntity mangaEntity)
MangaAttributes? mangaAttributes = mangaEntity.Attributes;
if (mangaAttributes == null)
return null;
if (mangaEntity.Attributes == null)
return null;
string title = mangaEntity.Attributes.Title.FirstOrDefault().Value;
string title = GetTitle(mangaAttributes);
string slug = GenerateSlug(title);
MangaSearchResult mangaSearchResult = new()
{
Title = title,
Description = GetDescription(mangaAttributes),
Url = $"https://mangadex.org/title/{mangaEntity.Id}/{slug}",
Thumbnail = GetThumbnail(mangaEntity)
Thumbnail = GetThumbnail(mangaEntity, coverArtEntites)
};
return mangaSearchResult;
}
private static string GetTitle(MangaAttributes attributes)
{
var alternateTitle = attributes.AltTitles.Where(x => x.ContainsKey("en")).FirstOrDefault();
if (alternateTitle?.Count > 0)
return alternateTitle["en"];
if (attributes.Title.TryGetValue("en", out string? title))
return title;
if (attributes.Title.Count > 0)
return attributes.Title.ElementAt(0).Value;
return string.Empty;
}
private static string GetDescription(MangaAttributes attributes)
{
if (attributes.Description.TryGetValue("en", out string? description))
return description;
return string.Empty;
}
public static string GenerateSlug(string title)
{
// title.ToLowerInvariant().Normalize(NormalizationForm.FormD);
@@ -70,7 +110,18 @@ public partial class MangaDexSearchProvider(IMangaDexClient mangaDexClient) : IM
return title.Trim('-');
}
private static string? GetThumbnail(MangaDexEntity mangaDexEntity)
private static string? GetThumbnail(MangaDexEntity mangaDexEntity, CoverArtEntity[] coverArtEntites)
{
string? fileName = GetCoverArtFileNameFromMangaEntity(mangaDexEntity)
?? GetCoverArtFileNameFromCoverArtEntities(coverArtEntites);
if (string.IsNullOrWhiteSpace(fileName))
return null;
return $"https://mangadex.org/covers/{mangaDexEntity.Id}/{fileName}";
}
private static string? GetCoverArtFileNameFromMangaEntity(MangaDexEntity mangaDexEntity)
{
CoverArtEntity? coverArtEntity = (CoverArtEntity?)mangaDexEntity.Relationships.FirstOrDefault(entity =>
entity is CoverArtEntity);
@@ -78,11 +129,59 @@ public partial class MangaDexSearchProvider(IMangaDexClient mangaDexClient) : IM
if (coverArtEntity == null || string.IsNullOrWhiteSpace(coverArtEntity.Attributes?.FileName))
return null;
string? fileName = coverArtEntity.Attributes?.FileName;
return coverArtEntity.Attributes?.FileName;
}
if (string.IsNullOrWhiteSpace(coverArtEntity.Attributes?.FileName))
return null;
private static string? GetCoverArtFileNameFromCoverArtEntities(CoverArtEntity[] coverArtEntites)
{
return coverArtEntites.Where(coverArtEntity =>
string.IsNullOrWhiteSpace(coverArtEntity.Attributes?.FileName) == false).FirstOrDefault()?.Attributes!.FileName;
}
return $"https://mangadex.org/covers/{mangaDexEntity.Id}/{fileName}";
private async Task<Dictionary<Guid, List<CoverArtEntity>>> GetCoverArtFileNamesAsync(MangaEntity[] mangaEntities, CancellationToken cancellationToken)
{
Guid[] mangaGuids = [.. mangaEntities.Select(entity => entity.Id)];
return await GetCoverArtFileNamesAsync(mangaGuids, cancellationToken);
}
private async Task<Dictionary<Guid, List<CoverArtEntity>>> GetCoverArtFileNamesAsync(Guid[] mangaGuids, CancellationToken cancellationToken)
{
Dictionary<Guid, List<CoverArtEntity>> result = [];
foreach (Guid mangaGuid in mangaGuids)
{
result.Add(mangaGuid, []);
}
MangaDexResponse? response = await mangaDexClient.GetCoverArtAsync(mangaGuids, cancellationToken);
if (response == null || (response is not MangaDexCollectionResponse collectionResponse))
return result;
CoverArtEntity[] coverArtEntities = [.. collectionResponse.Data.Where(entity => entity is CoverArtEntity).Cast<CoverArtEntity>()];
if (coverArtEntities.Length == 0)
return result;
CoverArtEntity[] orderedCoverArtEntities = [.. coverArtEntities.OrderBy(x => x.Attributes?.Volume)];
foreach (var coverArtEntity in orderedCoverArtEntities)
{
if (coverArtEntity.Attributes == null)
continue;
MangaEntity? mangaEntity = (MangaEntity?)coverArtEntity.Relationships.FirstOrDefault(relationship => relationship is MangaEntity);
if (mangaEntity == null)
continue;
if (result.ContainsKey(mangaEntity.Id) == false)
continue;
result[mangaEntity.Id].Add(coverArtEntity);
}
return result;
}
}