Normalize line endings to LF via .gitattributes
Репозиторий хранил фронтенд в CRLF, а часть бэкенда — вперемешку, хотя CI и Docker-сборка работают под Linux. Прибиваем LF атрибутом `* text=auto eol=lf` и разово нормализуем дерево, чтобы форматтеры не переписывали файлы целиком на каждом прогоне. Коммит чисто механический: изменений содержимого нет, только концы строк. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9d1c6d2fc3
commit
0442056367
@@ -1,89 +1,89 @@
|
||||
using LiteCqrs;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TeleWave.Application.Common.Interfaces;
|
||||
using TeleWave.Domain.Library;
|
||||
|
||||
namespace TeleWave.Application.Library.ListShows;
|
||||
|
||||
public sealed class ListShowsQueryHandler(IAppDbContext dbContext)
|
||||
: IQueryHandler<ListShowsQuery, IReadOnlyList<ShowSummaryDto>>
|
||||
{
|
||||
public async Task<IReadOnlyList<ShowSummaryDto>> Handle(
|
||||
ListShowsQuery query,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
var source = dbContext
|
||||
.Shows.AsNoTracking()
|
||||
.Include(s => s.Episodes)
|
||||
.Include(s => s.Genres)
|
||||
// Серии и жанры — сиблинги: одним запросом это честное перемножение (сериал на 200 серий
|
||||
// с тремя жанрами даёт 600 строк вместо 203). Разделяем.
|
||||
.AsSplitQuery()
|
||||
.Where(s =>
|
||||
query.Interstitials
|
||||
? s.Kind == ShowKind.Interstitial
|
||||
: s.Kind != ShowKind.Interstitial
|
||||
);
|
||||
|
||||
var filtered = query.GenreId is { } genreId
|
||||
? source.Where(s => s.Genres.Any(g => g.GenreId == genreId))
|
||||
: source;
|
||||
|
||||
var shows = await filtered.OrderBy(s => s.Name).ToListAsync(cancellationToken);
|
||||
|
||||
// Названия только для основных жанров — в списке показывается один.
|
||||
var primaryIds = shows
|
||||
.Select(s => s.PrimaryGenreId)
|
||||
.Where(id => id is not null)
|
||||
.Select(id => id!.Value)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
var genreNames = await dbContext
|
||||
.Genres.AsNoTracking()
|
||||
.Where(g => primaryIds.Contains(g.Id))
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Name, cancellationToken);
|
||||
|
||||
// Имена ассетов нужны, чтобы распознать сезоны (номера в модели не хранятся).
|
||||
var assetIds = shows
|
||||
.SelectMany(s => s.Episodes.Select(e => e.MediaAssetId))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
var names = await dbContext
|
||||
.MediaAssets.AsNoTracking()
|
||||
.Where(a => assetIds.Contains(a.Id))
|
||||
.Select(a => new { a.Id, a.OriginalFileName })
|
||||
.ToDictionaryAsync(a => a.Id, a => a.OriginalFileName, cancellationToken);
|
||||
|
||||
return shows
|
||||
.Select(s =>
|
||||
{
|
||||
var seasons = s
|
||||
.Episodes.Select(e =>
|
||||
names.TryGetValue(e.MediaAssetId, out var n)
|
||||
? EpisodeName.ParseSeason(n)
|
||||
: null
|
||||
)
|
||||
.Where(season => season is not null)
|
||||
.Distinct()
|
||||
.Count();
|
||||
return new ShowSummaryDto(
|
||||
s.Id,
|
||||
s.Name,
|
||||
s.OriginalName,
|
||||
s.Kind,
|
||||
s.Audience,
|
||||
s.Episodes.Count,
|
||||
seasons,
|
||||
s.Year,
|
||||
s.PosterImageId is not null,
|
||||
s.CreatedAt,
|
||||
s.PrimaryGenreId is { } primaryId
|
||||
&& genreNames.TryGetValue(primaryId, out var g)
|
||||
? g
|
||||
: null
|
||||
);
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
using LiteCqrs;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TeleWave.Application.Common.Interfaces;
|
||||
using TeleWave.Domain.Library;
|
||||
|
||||
namespace TeleWave.Application.Library.ListShows;
|
||||
|
||||
public sealed class ListShowsQueryHandler(IAppDbContext dbContext)
|
||||
: IQueryHandler<ListShowsQuery, IReadOnlyList<ShowSummaryDto>>
|
||||
{
|
||||
public async Task<IReadOnlyList<ShowSummaryDto>> Handle(
|
||||
ListShowsQuery query,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
var source = dbContext
|
||||
.Shows.AsNoTracking()
|
||||
.Include(s => s.Episodes)
|
||||
.Include(s => s.Genres)
|
||||
// Серии и жанры — сиблинги: одним запросом это честное перемножение (сериал на 200 серий
|
||||
// с тремя жанрами даёт 600 строк вместо 203). Разделяем.
|
||||
.AsSplitQuery()
|
||||
.Where(s =>
|
||||
query.Interstitials
|
||||
? s.Kind == ShowKind.Interstitial
|
||||
: s.Kind != ShowKind.Interstitial
|
||||
);
|
||||
|
||||
var filtered = query.GenreId is { } genreId
|
||||
? source.Where(s => s.Genres.Any(g => g.GenreId == genreId))
|
||||
: source;
|
||||
|
||||
var shows = await filtered.OrderBy(s => s.Name).ToListAsync(cancellationToken);
|
||||
|
||||
// Названия только для основных жанров — в списке показывается один.
|
||||
var primaryIds = shows
|
||||
.Select(s => s.PrimaryGenreId)
|
||||
.Where(id => id is not null)
|
||||
.Select(id => id!.Value)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
var genreNames = await dbContext
|
||||
.Genres.AsNoTracking()
|
||||
.Where(g => primaryIds.Contains(g.Id))
|
||||
.ToDictionaryAsync(g => g.Id, g => g.Name, cancellationToken);
|
||||
|
||||
// Имена ассетов нужны, чтобы распознать сезоны (номера в модели не хранятся).
|
||||
var assetIds = shows
|
||||
.SelectMany(s => s.Episodes.Select(e => e.MediaAssetId))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
var names = await dbContext
|
||||
.MediaAssets.AsNoTracking()
|
||||
.Where(a => assetIds.Contains(a.Id))
|
||||
.Select(a => new { a.Id, a.OriginalFileName })
|
||||
.ToDictionaryAsync(a => a.Id, a => a.OriginalFileName, cancellationToken);
|
||||
|
||||
return shows
|
||||
.Select(s =>
|
||||
{
|
||||
var seasons = s
|
||||
.Episodes.Select(e =>
|
||||
names.TryGetValue(e.MediaAssetId, out var n)
|
||||
? EpisodeName.ParseSeason(n)
|
||||
: null
|
||||
)
|
||||
.Where(season => season is not null)
|
||||
.Distinct()
|
||||
.Count();
|
||||
return new ShowSummaryDto(
|
||||
s.Id,
|
||||
s.Name,
|
||||
s.OriginalName,
|
||||
s.Kind,
|
||||
s.Audience,
|
||||
s.Episodes.Count,
|
||||
seasons,
|
||||
s.Year,
|
||||
s.PosterImageId is not null,
|
||||
s.CreatedAt,
|
||||
s.PrimaryGenreId is { } primaryId
|
||||
&& genreNames.TryGetValue(primaryId, out var g)
|
||||
? g
|
||||
: null
|
||||
);
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user