channel logo and watermark fixes (#2100)

* channel logo and watermark fixes

* update changelog
This commit is contained in:
Jason Dove
2025-07-01 13:40:30 +00:00
committed by GitHub
parent e2ffa70529
commit f6249d9fa4
39 changed files with 23584 additions and 76 deletions
+5 -5
View File
@@ -63,17 +63,17 @@ public class ArtworkController : ControllerBase
public async Task<IActionResult> GetPoster(string fileName, CancellationToken cancellationToken)
{
Either<BaseError, CachedImagePathViewModel> cachedImagePath =
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Poster, 440), cancellationToken);
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Poster, string.Empty, 440), cancellationToken);
return cachedImagePath.Match<IActionResult>(
Left: _ => new NotFoundResult(),
Right: r => new PhysicalFileResult(r.FileName, r.MimeType));
}
[HttpGet("/artwork/watermarks/{fileName}")]
public async Task<IActionResult> GetWatermark(string fileName, CancellationToken cancellationToken)
public async Task<IActionResult> GetWatermark(string fileName, [FromQuery] string contentType, CancellationToken cancellationToken)
{
Either<BaseError, CachedImagePathViewModel> cachedImagePath =
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Watermark), cancellationToken);
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Watermark, contentType), cancellationToken);
return cachedImagePath.Match<IActionResult>(
Left: _ => new NotFoundResult(),
Right: r => new PhysicalFileResult(r.FileName, r.MimeType));
@@ -83,7 +83,7 @@ public class ArtworkController : ControllerBase
public async Task<IActionResult> GetFanArt(string fileName, CancellationToken cancellationToken)
{
Either<BaseError, CachedImagePathViewModel> cachedImagePath =
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.FanArt), cancellationToken);
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.FanArt, string.Empty), cancellationToken);
return cachedImagePath.Match<IActionResult>(
Left: _ => new NotFoundResult(),
Right: r => new PhysicalFileResult(r.FileName, r.MimeType));
@@ -155,7 +155,7 @@ public class ArtworkController : ControllerBase
public async Task<IActionResult> GetThumbnail(string fileName, CancellationToken cancellationToken)
{
Either<BaseError, CachedImagePathViewModel> cachedImagePath =
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Thumbnail, 220), cancellationToken);
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Thumbnail, string.Empty, 220), cancellationToken);
return cachedImagePath.Match<IActionResult>(
Left: _ => new NotFoundResult(),
Right: r => new PhysicalFileResult(r.FileName, r.MimeType));
+2 -2
View File
@@ -271,10 +271,10 @@ public class IptvController : ControllerBase
[HttpGet("iptv/logos/{fileName}")]
[HttpHead("iptv/logos/{fileName}.jpg")]
[HttpGet("iptv/logos/{fileName}.jpg")]
public async Task<IActionResult> GetImage(string fileName)
public async Task<IActionResult> GetImage(string fileName, [FromQuery] string contentType)
{
Either<BaseError, CachedImagePathViewModel> cachedImagePath =
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Logo));
await _mediator.Send(new GetCachedImagePath(fileName, ArtworkKind.Logo, contentType));
return cachedImagePath.Match<IActionResult>(
Left: _ => new NotFoundResult(),
Right: r => new PhysicalFileResult(r.FileName, r.MimeType));
+8 -6
View File
@@ -1,5 +1,7 @@
@page "/channels/{Id:int?}"
@page "/channels/add"
@using System.Net
@using ErsatzTV.Application.Artworks
@using ErsatzTV.Application.Channels
@using ErsatzTV.Application.FFmpegProfiles
@using ErsatzTV.Application.Filler
@@ -124,9 +126,9 @@
<MudGrid Class="mt-3" Style="align-items: center" Justify="Justify.Center">
<MudItem xs="6">
<InputFile id="fileInput" OnChange="UploadLogo" hidden/>
@if (!string.IsNullOrWhiteSpace(_model.Logo) || !string.IsNullOrWhiteSpace(_model.ExternalLogoUrl))
@if (!string.IsNullOrWhiteSpace(_model.Logo?.Path) || !string.IsNullOrWhiteSpace(_model.ExternalLogoUrl))
{
<MudElement HtmlTag="img" src="@(string.IsNullOrWhiteSpace(_model.ExternalLogoUrl) ? _model.Logo : _model.ExternalLogoUrl)" Style="max-height: 50px"/>
<MudElement HtmlTag="img" src="@(string.IsNullOrWhiteSpace(_model.ExternalLogoUrl) ? _model.Logo.UrlWithContentType : _model.ExternalLogoUrl)" Style="max-height: 50px"/>
}
</MudItem>
<MudItem xs="6">
@@ -216,9 +218,9 @@
_model.Number = channelViewModel.Number;
_model.FFmpegProfileId = channelViewModel.FFmpegProfileId;
if (Artwork.IsExternalUrl(channelViewModel.Logo))
if (channelViewModel.Logo.IsExternalUrl)
{
_model.ExternalLogoUrl = channelViewModel.Logo;
_model.ExternalLogoUrl = channelViewModel.Logo.Path;
}
else
{
@@ -304,11 +306,11 @@
try
{
Either<BaseError, string> maybeCacheFileName =
await Mediator.Send(new SaveArtworkToDisk(e.File.OpenReadStream(10 * 1024 * 1024), ArtworkKind.Logo), _cts.Token);
await Mediator.Send(new SaveArtworkToDisk(e.File.OpenReadStream(10 * 1024 * 1024), ArtworkKind.Logo, e.File.ContentType), _cts.Token);
maybeCacheFileName.Match(
relativeFileName =>
{
_model.Logo = $"iptv/logos/{relativeFileName}";
_model.Logo = new ArtworkContentTypeModel($"iptv/logos/{relativeFileName}", e.File.ContentType);
_model.ExternalLogoUrl = null;
StateHasChanged();
},
+2 -2
View File
@@ -43,9 +43,9 @@
<RowTemplate>
<MudTd DataLabel="Number">@context.Number</MudTd>
<MudTd DataLabel="Logo">
@if (!string.IsNullOrWhiteSpace(context.Logo))
@if (!string.IsNullOrWhiteSpace(context.Logo?.Path))
{
<MudElement HtmlTag="img" src="@context.Logo" Style="max-height: 50px"/>
<MudElement HtmlTag="img" src="@context.Logo.UrlWithContentType" Style="max-height: 50px"/>
}
else
{
+6 -5
View File
@@ -1,5 +1,6 @@
@page "/watermarks/{Id:int}"
@page "/watermarks/add"
@using ErsatzTV.Application.Artworks
@using ErsatzTV.Application.Images
@using ErsatzTV.Application.Watermarks
@using ErsatzTV.FFmpeg.State
@@ -38,9 +39,9 @@
<MudGrid Class="mt-3" Style="align-items: center" Justify="Justify.Center">
<MudItem xs="6">
<InputFile id="watermarkFileInput" OnChange="UploadWatermark" style="display: none;"/>
@if (!string.IsNullOrWhiteSpace(_model.Image) && _model.ImageSource == ChannelWatermarkImageSource.Custom)
@if (!string.IsNullOrWhiteSpace(_model.Image?.Path) && _model.ImageSource == ChannelWatermarkImageSource.Custom)
{
<MudElement HtmlTag="img" src="@($"artwork/watermarks/{_model.Image}")" Style="max-height: 50px"/>
<MudElement HtmlTag="img" src="@($"artwork/watermarks/{_model.Image.UrlWithContentType}")" Style="max-height: 50px"/>
}
<ValidationMessage For="@(() => _model.Image)" style="color: #f44336 !important;"/>
</MudItem>
@@ -183,7 +184,7 @@
{
Name = string.Empty,
Mode = ChannelWatermarkMode.Permanent,
Image = string.Empty,
Image = ArtworkContentTypeModel.None,
Location = WatermarkLocation.BottomRight,
Size = WatermarkSize.Scaled,
Width = 15,
@@ -224,12 +225,12 @@
try
{
Either<BaseError, string> maybeCacheFileName = await Mediator.Send(
new SaveArtworkToDisk(e.File.OpenReadStream(10 * 1024 * 1024), ArtworkKind.Watermark),
new SaveArtworkToDisk(e.File.OpenReadStream(10 * 1024 * 1024), ArtworkKind.Watermark, e.File.ContentType),
_cts.Token);
maybeCacheFileName.Match(
relativeFileName =>
{
_model.Image = relativeFileName;
_model.Image = new ArtworkContentTypeModel(relativeFileName, e.File.ContentType);
_messageStore.Clear();
_editContext.Validate();
StateHasChanged();
+2 -2
View File
@@ -27,9 +27,9 @@
<RowTemplate>
<MudTd DataLabel="Name">@context.Name</MudTd>
<MudTd DataLabel="Image">
@if (!string.IsNullOrWhiteSpace(context.Image))
@if (!string.IsNullOrWhiteSpace(context.Image?.Path))
{
<MudElement HtmlTag="img" src="@($"artwork/watermarks/{context.Image}")" Style="max-height: 50px"/>
<MudElement HtmlTag="img" src="@($"artwork/watermarks/{context.Image.UrlWithContentType}")" Style="max-height: 50px"/>
}
else if (context.ImageSource == ChannelWatermarkImageSource.ChannelLogo)
{
+5 -4
View File
@@ -1,4 +1,5 @@
using ErsatzTV.Application.Channels;
using ErsatzTV.Application.Artworks;
using ErsatzTV.Application.Channels;
using ErsatzTV.Core.Domain;
namespace ErsatzTV.ViewModels;
@@ -16,7 +17,7 @@ public class ChannelEditViewModel
public string StreamSelector { get; set; }
public string PreferredAudioLanguageCode { get; set; }
public string PreferredAudioTitle { get; set; }
public string Logo { get; set; }
public ArtworkContentTypeModel Logo { get; set; }
public string ExternalLogoUrl { get; set; }
public ChannelProgressMode ProgressMode { get; set; }
public StreamingMode StreamingMode { get; set; }
@@ -43,7 +44,7 @@ public class ChannelEditViewModel
Group,
Categories,
FFmpegProfileId,
string.IsNullOrWhiteSpace(ExternalLogoUrl) ? Logo : ExternalLogoUrl,
string.IsNullOrWhiteSpace(ExternalLogoUrl) ? Logo : new ArtworkContentTypeModel(ExternalLogoUrl, string.Empty),
StreamSelectorMode,
StreamSelector,
PreferredAudioLanguageCode,
@@ -66,7 +67,7 @@ public class ChannelEditViewModel
Group,
Categories,
FFmpegProfileId,
string.IsNullOrWhiteSpace(ExternalLogoUrl) ? Logo : ExternalLogoUrl,
string.IsNullOrWhiteSpace(ExternalLogoUrl) ? Logo : new ArtworkContentTypeModel(ExternalLogoUrl, string.Empty),
StreamSelectorMode,
StreamSelector,
PreferredAudioLanguageCode,
@@ -1,4 +1,5 @@
using ErsatzTV.Application.Watermarks;
using ErsatzTV.Application.Artworks;
using ErsatzTV.Application.Watermarks;
using ErsatzTV.Core.Domain;
using ErsatzTV.FFmpeg.State;
@@ -30,7 +31,7 @@ public class WatermarkEditViewModel
public int Id { get; set; }
public string Name { get; set; }
public string Image { get; set; }
public ArtworkContentTypeModel Image { get; set; }
public ChannelWatermarkMode Mode { get; set; }
public ChannelWatermarkImageSource ImageSource { get; set; }
public WatermarkLocation Location { get; set; }