diff --git a/CHANGELOG.md b/CHANGELOG.md
index e782974f6..591702233 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix bug where tail or fallback filler would sometimes schedule much longer than expected
- This only happened with fixed start schedule items following a schedule item with tail or fallback filler
- Fix NFO reader bug that caused inaccurate warning messages about invalid XML and incomplete metadata
+- Fix reverse proxy SSL termination support by supporting `X-Forwarded-Proto` header
### Added
- Add music video credits template system
@@ -37,6 +38,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- All groups of part numbers (i.e. all part 1s, all part 2s) will be shuffled
- The playout order will then schedule a random part 1 followed by a random part 2, etc
- Un-split (`nil`) episodes will be randomly placed between re-combined parts (e.g. part1, part2, part3, un-split, part1, part2, part3)
+- Add `ETV_BASE_URL` environment variable to support reverse proxies that use paths (e.g. `/ersatztv`)
### Changed
- No longer place watermarks within content by default (e.g. within 4:3 content padded to a 16:9 resolution)
diff --git a/ErsatzTV.Infrastructure/Health/Checks/FileNotFoundHealthCheck.cs b/ErsatzTV.Infrastructure/Health/Checks/FileNotFoundHealthCheck.cs
index 2790b7c40..d17856142 100644
--- a/ErsatzTV.Infrastructure/Health/Checks/FileNotFoundHealthCheck.cs
+++ b/ErsatzTV.Infrastructure/Health/Checks/FileNotFoundHealthCheck.cs
@@ -58,7 +58,7 @@ public class FileNotFoundHealthCheck : BaseHealthCheck, IFileNotFoundHealthCheck
return WarningResult(
$"There are {count} items that do not exist on disk, including the following: {files}",
- "/media/trash");
+ "media/trash");
}
return OkResult();
diff --git a/ErsatzTV.Infrastructure/Health/Checks/UnavailableHealthCheck.cs b/ErsatzTV.Infrastructure/Health/Checks/UnavailableHealthCheck.cs
index f21f6f976..5d5d24f68 100644
--- a/ErsatzTV.Infrastructure/Health/Checks/UnavailableHealthCheck.cs
+++ b/ErsatzTV.Infrastructure/Health/Checks/UnavailableHealthCheck.cs
@@ -83,7 +83,7 @@ public class UnavailableHealthCheck : BaseHealthCheck, IUnavailableHealthCheck
return WarningResult(
$"There are {count} items that are unavailable because ErsatzTV cannot find them on disk, including the following: {files}",
- "/search?query=state%3aUnavailable");
+ "search?query=state%3aUnavailable");
}
return OkResult();
diff --git a/ErsatzTV/Controllers/IptvController.cs b/ErsatzTV/Controllers/IptvController.cs
index 91ff7846b..c61356ec9 100644
--- a/ErsatzTV/Controllers/IptvController.cs
+++ b/ErsatzTV/Controllers/IptvController.cs
@@ -77,7 +77,7 @@ public class IptvController : ControllerBase
mode = "ts";
break;
default:
- return Redirect($"/iptv/channel/{channelNumber}.m3u8");
+ return Redirect($"~/iptv/channel/{channelNumber}.m3u8");
}
}
}
@@ -167,7 +167,7 @@ public class IptvController : ControllerBase
mode = "segmenter";
break;
default:
- return Redirect($"/iptv/channel/{channelNumber}.ts");
+ return Redirect($"~/iptv/channel/{channelNumber}.ts");
}
}
}
@@ -184,7 +184,7 @@ public class IptvController : ControllerBase
"Session started; returning multi-variant playlist for channel {Channel}",
channelNumber);
return Content(GetMultiVariantPlaylist(channelNumber), "application/x-mpegurl");
- // return Redirect($"/iptv/session/{channelNumber}/hls.m3u8");
+ // return Redirect($"~/iptv/session/{channelNumber}/hls.m3u8");
},
error =>
{
@@ -195,7 +195,7 @@ public class IptvController : ControllerBase
"Session is already active; returning multi-variant playlist for channel {Channel}",
channelNumber);
return Content(GetMultiVariantPlaylist(channelNumber), "application/x-mpegurl");
- // return RedirectPreserveMethod($"/iptv/session/{channelNumber}/hls.m3u8");
+ // return RedirectPreserveMethod($"iptv/session/{channelNumber}/hls.m3u8");
default:
_logger.LogWarning(
"Failed to start segmenter for channel {ChannelNumber}: {Error}",
diff --git a/ErsatzTV/Extensions/StringExtensions.cs b/ErsatzTV/Extensions/StringExtensions.cs
index 343d797d1..921bd4543 100644
--- a/ErsatzTV/Extensions/StringExtensions.cs
+++ b/ErsatzTV/Extensions/StringExtensions.cs
@@ -33,7 +33,7 @@ public static class StringExtensions
public static string GetRelativeSearchQuery(this string query)
{
(string key, string value) = EncodeQuery(query);
- return $"/search?{key}={value}";
+ return $"search?{key}={value}";
}
private static string DecodeBase64(this StringValues input) =>
diff --git a/ErsatzTV/Pages/Artist.razor b/ErsatzTV/Pages/Artist.razor
index 0a2527a55..36623ab1c 100644
--- a/ErsatzTV/Pages/Artist.razor
+++ b/ErsatzTV/Pages/Artist.razor
@@ -16,7 +16,7 @@
@if (!string.IsNullOrWhiteSpace(_artist.FanArt))
{
-
+
}
@@ -25,7 +25,7 @@
{
+ src="@($"artwork/thumbnails/{_artist.Thumbnail}")" alt="artist thumbnail"/>
}
@_artist.Name
@@ -125,7 +125,7 @@
@if (!string.IsNullOrWhiteSpace(musicVideo.Poster))
{
-
+
@if (musicVideo.State == MediaItemState.FileNotFound)
{
@@ -245,7 +245,7 @@
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
{
await _mediator.Send(new AddArtistToCollection(collection.Id, ArtistId), _cts.Token);
- _navigationManager.NavigateTo($"/media/collections/{collection.Id}");
+ _navigationManager.NavigateTo($"media/collections/{collection.Id}");
}
}
@@ -259,7 +259,7 @@
if (!result.Cancelled && result.Data is ProgramScheduleViewModel schedule)
{
await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.Artist, null, null, null, ArtistId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null, null, null, null, null, null), _cts.Token);
- _navigationManager.NavigateTo($"/schedules/{schedule.Id}/items");
+ _navigationManager.NavigateTo($"schedules/{schedule.Id}/items");
}
}
diff --git a/ErsatzTV/Pages/ArtistList.razor b/ErsatzTV/Pages/ArtistList.razor
index b12255d8b..2ddc0ac3f 100644
--- a/ErsatzTV/Pages/ArtistList.razor
+++ b/ErsatzTV/Pages/ArtistList.razor
@@ -55,7 +55,7 @@
}
@@ -99,7 +99,7 @@
private void PrevPage()
{
- string uri = $"/media/music/artists/page/{PageNumber - 1}";
+ string uri = $"media/music/artists/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
@@ -110,7 +110,7 @@
private void NextPage()
{
- string uri = $"/media/music/artists/page/{PageNumber + 1}";
+ string uri = $"media/music/artists/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
diff --git a/ErsatzTV/Pages/Channels.razor b/ErsatzTV/Pages/Channels.razor
index 73e30e134..890887fa4 100644
--- a/ErsatzTV/Pages/Channels.razor
+++ b/ErsatzTV/Pages/Channels.razor
@@ -58,7 +58,7 @@
+ Link="@($"channels/{context.Id}")">
@@ -73,7 +73,7 @@
-
+
Add Channel
diff --git a/ErsatzTV/Pages/CollectionEditor.razor b/ErsatzTV/Pages/CollectionEditor.razor
index f03c99e6b..179168d64 100644
--- a/ErsatzTV/Pages/CollectionEditor.razor
+++ b/ErsatzTV/Pages/CollectionEditor.razor
@@ -83,7 +83,7 @@
_snackbar.Add(error.Value, Severity.Error);
_logger.LogError("Error saving collection: {Error}", error.Value);
},
- () => _navigationManager.NavigateTo(_model.Id > 0 ? $"/media/collections/{_model.Id}" : "/media/collections"));
+ () => _navigationManager.NavigateTo(_model.Id > 0 ? $"media/collections/{_model.Id}" : "media/collections"));
}
}
diff --git a/ErsatzTV/Pages/CollectionItems.razor b/ErsatzTV/Pages/CollectionItems.razor
index 72d9b6020..b4286819d 100644
--- a/ErsatzTV/Pages/CollectionItems.razor
+++ b/ErsatzTV/Pages/CollectionItems.razor
@@ -32,7 +32,7 @@
@_data.Name
+ Link="@($"media/collections/{Id}/edit")"/>
@if (_data.MovieCards.Any())
{
@@ -95,7 +95,7 @@
@foreach (MovieCardViewModel card in OrderMovies(_data.MovieCards))
{
m.SortTitle))
{
m.SortTitle))
{
e.Aired))
{
e.SortTitle))
{
-
+
Add Collection
-
+
Add Multi Collection
@@ -38,7 +38,7 @@
+ Link="@($"media/collections/{context.Id}")">
@@ -76,7 +76,7 @@
+ Link="@($"media/multi-collections/{context.Id}/edit")">
diff --git a/ErsatzTV/Pages/EpisodeList.razor b/ErsatzTV/Pages/EpisodeList.razor
index 1f543d561..b07439a1e 100644
--- a/ErsatzTV/Pages/EpisodeList.razor
+++ b/ErsatzTV/Pages/EpisodeList.razor
@@ -55,7 +55,7 @@
}
@@ -99,7 +99,7 @@
private void PrevPage()
{
- string uri = $"/media/tv/episodes/page/{PageNumber - 1}";
+ string uri = $"media/tv/episodes/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
@@ -110,7 +110,7 @@
private void NextPage()
{
- string uri = $"/media/tv/episodes/page/{PageNumber + 1}";
+ string uri = $"media/tv/episodes/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
diff --git a/ErsatzTV/Pages/FFmpeg.razor b/ErsatzTV/Pages/FFmpeg.razor
index fc763000a..c1c9d0097 100644
--- a/ErsatzTV/Pages/FFmpeg.razor
+++ b/ErsatzTV/Pages/FFmpeg.razor
@@ -3,8 +3,6 @@
@implements IDisposable
@inject IDialogService _dialog
@inject IMediator _mediator
-@inject ILogger _logger
-@inject ISnackbar _snackbar
@inject NavigationManager _navigationManager
@@ -44,7 +42,7 @@
+ Link="@($"ffmpeg/{context.Id}")">
@@ -61,7 +59,7 @@
-
+
Add Profile
@@ -105,7 +103,7 @@
DialogResult dialogResult = await dialog.Result;
if (!dialogResult.Cancelled && dialogResult.Data is FFmpegProfileViewModel data)
{
- _navigationManager.NavigateTo($"/ffmpeg/{data.Id}");
+ _navigationManager.NavigateTo($"ffmpeg/{data.Id}");
}
}
diff --git a/ErsatzTV/Pages/FillerPresetEditor.razor b/ErsatzTV/Pages/FillerPresetEditor.razor
index 32f9cd134..d6628f3f0 100644
--- a/ErsatzTV/Pages/FillerPresetEditor.razor
+++ b/ErsatzTV/Pages/FillerPresetEditor.razor
@@ -230,7 +230,7 @@
_snackbar.Add(error.Value, Severity.Error);
_logger.LogError("Error saving filler preset: {Error}", error.Value);
},
- () => _navigationManager.NavigateTo("/media/filler/presets"));
+ () => _navigationManager.NavigateTo("media/filler/presets"));
}
}
diff --git a/ErsatzTV/Pages/FillerPresets.razor b/ErsatzTV/Pages/FillerPresets.razor
index fa9bf45d2..b37cf4446 100644
--- a/ErsatzTV/Pages/FillerPresets.razor
+++ b/ErsatzTV/Pages/FillerPresets.razor
@@ -8,7 +8,7 @@
-
+
Add Filler Preset
@@ -49,7 +49,7 @@
+ Link="@($"media/filler/presets/{context.Id}/edit")">
diff --git a/ErsatzTV/Pages/Libraries.razor b/ErsatzTV/Pages/Libraries.razor
index d56049ef2..7e8608df1 100644
--- a/ErsatzTV/Pages/Libraries.razor
+++ b/ErsatzTV/Pages/Libraries.razor
@@ -77,7 +77,7 @@
}
+ Link="@($"search?query=library_id%3a{context.Id}")">
diff --git a/ErsatzTV/Pages/LocalLibraries.razor b/ErsatzTV/Pages/LocalLibraries.razor
index 64238ecd7..9d2e9670b 100644
--- a/ErsatzTV/Pages/LocalLibraries.razor
+++ b/ErsatzTV/Pages/LocalLibraries.razor
@@ -32,7 +32,7 @@
+ Link="@($"media/sources/local/{context.Id}/edit")">
@@ -45,7 +45,7 @@
-
+
Add Local Library
diff --git a/ErsatzTV/Pages/LocalLibraryEditor.razor b/ErsatzTV/Pages/LocalLibraryEditor.razor
index 97a877082..bfda00132 100644
--- a/ErsatzTV/Pages/LocalLibraryEditor.razor
+++ b/ErsatzTV/Pages/LocalLibraryEditor.razor
@@ -148,7 +148,7 @@
var request = new MoveLocalLibraryPath(libraryPath.Id, library.Id);
Either moveResult = await _mediator.Send(request, _cts.Token);
moveResult.Match(
- _ => _navigationManager.NavigateTo($"/media/sources/local/{library.Id}/edit"),
+ _ => _navigationManager.NavigateTo($"media/sources/local/{library.Id}/edit"),
error =>
{
_snackbar.Add(error.Value, Severity.Error);
@@ -214,7 +214,7 @@
_model.Paths.Map(p => p.Path).ToList()), _cts.Token);
result.Match(
- _ => _navigationManager.NavigateTo("/media/sources/local"),
+ _ => _navigationManager.NavigateTo("media/sources/local"),
error =>
{
_snackbar.Add(error.Value, Severity.Error);
diff --git a/ErsatzTV/Pages/LocalLibraryPathEditor.razor b/ErsatzTV/Pages/LocalLibraryPathEditor.razor
index b0ec99e03..fe12a5cd0 100644
--- a/ErsatzTV/Pages/LocalLibraryPathEditor.razor
+++ b/ErsatzTV/Pages/LocalLibraryPathEditor.razor
@@ -81,7 +81,7 @@
if (_locker.LockLibrary(_library.Id))
{
await _channel.WriteAsync(new ScanLocalLibraryIfNeeded(_library.Id), _cts.Token);
- _navigationManager.NavigateTo("/media/libraries");
+ _navigationManager.NavigateTo("media/libraries");
}
});
}
diff --git a/ErsatzTV/Pages/Movie.razor b/ErsatzTV/Pages/Movie.razor
index 4f2311a73..d3dda6e5b 100644
--- a/ErsatzTV/Pages/Movie.razor
+++ b/ErsatzTV/Pages/Movie.razor
@@ -19,7 +19,7 @@
}
else
{
-
+
}
}
@@ -38,7 +38,7 @@
{
+ src="@($"artwork/posters/{_movie.Poster}")" alt="movie poster"/>
}
@if (_movie.MediaItemState == MediaItemState.FileNotFound)
{
@@ -249,7 +249,7 @@
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
{
await _mediator.Send(new AddMovieToCollection(collection.Id, MovieId), _cts.Token);
- _navigationManager.NavigateTo($"/media/collections/{collection.Id}");
+ _navigationManager.NavigateTo($"media/collections/{collection.Id}");
}
}
diff --git a/ErsatzTV/Pages/MovieList.razor b/ErsatzTV/Pages/MovieList.razor
index b66da6069..d12255fee 100644
--- a/ErsatzTV/Pages/MovieList.razor
+++ b/ErsatzTV/Pages/MovieList.razor
@@ -55,7 +55,7 @@
}
@@ -98,7 +98,7 @@
private void PrevPage()
{
- string uri = $"/media/movies/page/{PageNumber - 1}";
+ string uri = $"media/movies/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
@@ -109,7 +109,7 @@
private void NextPage()
{
- string uri = $"/media/movies/page/{PageNumber + 1}";
+ string uri = $"media/movies/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
diff --git a/ErsatzTV/Pages/MultiCollectionEditor.razor b/ErsatzTV/Pages/MultiCollectionEditor.razor
index acdc1ea88..c004651ac 100644
--- a/ErsatzTV/Pages/MultiCollectionEditor.razor
+++ b/ErsatzTV/Pages/MultiCollectionEditor.razor
@@ -186,7 +186,7 @@
_snackbar.Add(error.Value, Severity.Error);
_logger.LogError("Error saving collection: {Error}", error.Value);
},
- () => _navigationManager.NavigateTo("/media/collections"));
+ () => _navigationManager.NavigateTo("media/collections"));
}
}
diff --git a/ErsatzTV/Pages/MusicVideoList.razor b/ErsatzTV/Pages/MusicVideoList.razor
index 9e554e75a..0da5482ad 100644
--- a/ErsatzTV/Pages/MusicVideoList.razor
+++ b/ErsatzTV/Pages/MusicVideoList.razor
@@ -67,7 +67,7 @@
@if (_data.PageMap.IsSome)
{
}
@@ -99,7 +99,7 @@
private void PrevPage()
{
- string uri = $"/media/music/videos/page/{PageNumber - 1}";
+ string uri = $"media/music/videos/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
@@ -110,7 +110,7 @@
private void NextPage()
{
- string uri = $"/media/music/videos/page/{PageNumber + 1}";
+ string uri = $"media/music/videos/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
diff --git a/ErsatzTV/Pages/OtherVideoList.razor b/ErsatzTV/Pages/OtherVideoList.razor
index 5439447e1..d0b60d925 100644
--- a/ErsatzTV/Pages/OtherVideoList.razor
+++ b/ErsatzTV/Pages/OtherVideoList.razor
@@ -67,7 +67,7 @@
@if (_data.PageMap.IsSome)
{
}
@@ -99,7 +99,7 @@
private void PrevPage()
{
- string uri = $"/media/other/videos/page/{PageNumber - 1}";
+ string uri = $"media/other/videos/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
@@ -110,7 +110,7 @@
private void NextPage()
{
- string uri = $"/media/other/videos/page/{PageNumber + 1}";
+ string uri = $"media/other/videos/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
diff --git a/ErsatzTV/Pages/Playouts.razor b/ErsatzTV/Pages/Playouts.razor
index 15c74e47f..5d063a292 100644
--- a/ErsatzTV/Pages/Playouts.razor
+++ b/ErsatzTV/Pages/Playouts.razor
@@ -7,7 +7,7 @@
@inject IMediator _mediator
-
+
Add Playout
+ Link="@($"media/sources/plex/{context.Id}/libraries")">
+ Link="@($"media/sources/plex/{context.Id}/paths")">
diff --git a/ErsatzTV/Pages/Schedules.razor b/ErsatzTV/Pages/Schedules.razor
index 82c637ea3..c0793a40a 100644
--- a/ErsatzTV/Pages/Schedules.razor
+++ b/ErsatzTV/Pages/Schedules.razor
@@ -34,12 +34,12 @@
+ Link="@($"schedules/{context.Id}")">
+ Link="@($"schedules/{context.Id}/items")">
@@ -54,7 +54,7 @@
-
+
Add Schedule
diff --git a/ErsatzTV/Pages/Search.razor b/ErsatzTV/Pages/Search.razor
index cd53c273c..0d04097ab 100644
--- a/ErsatzTV/Pages/Search.razor
+++ b/ErsatzTV/Pages/Search.razor
@@ -110,7 +110,7 @@
@foreach (MovieCardViewModel card in _movies.Cards.OrderBy(m => m.SortTitle))
{
s.SortTitle))
{
s.SortTitle))
{
s.SortTitle))
{
}
@@ -99,7 +99,7 @@
private void PrevPage()
{
- string uri = $"/media/music/songs/page/{PageNumber - 1}";
+ string uri = $"media/music/songs/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
@@ -110,7 +110,7 @@
private void NextPage()
{
- string uri = $"/media/music/songs/page/{PageNumber + 1}";
+ string uri = $"media/music/songs/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
diff --git a/ErsatzTV/Pages/TelevisionEpisodeList.razor b/ErsatzTV/Pages/TelevisionEpisodeList.razor
index 6b48a3657..04676f27c 100644
--- a/ErsatzTV/Pages/TelevisionEpisodeList.razor
+++ b/ErsatzTV/Pages/TelevisionEpisodeList.razor
@@ -23,7 +23,7 @@
}
else
{
-
+
}
}
@@ -41,11 +41,11 @@
{
+ src="@($"artwork/posters/{_season.Poster}")" alt="season poster"/>
}
}
-
+
@_season.Title
@_season.Name
@@ -81,7 +81,7 @@
}
else
{
-
+
}
@if (episode.State == MediaItemState.FileNotFound)
{
@@ -219,7 +219,7 @@
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
{
await _mediator.Send(new AddSeasonToCollection(collection.Id, SeasonId), _cts.Token);
- _navigationManager.NavigateTo($"/media/collections/{collection.Id}");
+ _navigationManager.NavigateTo($"media/collections/{collection.Id}");
}
}
@@ -234,7 +234,7 @@
if (!result.Cancelled && result.Data is ProgramScheduleViewModel schedule)
{
await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.TelevisionSeason, null, null, null, SeasonId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null, null, null, null, null, null), _cts.Token);
- _navigationManager.NavigateTo($"/schedules/{schedule.Id}/items");
+ _navigationManager.NavigateTo($"schedules/{schedule.Id}/items");
}
}
diff --git a/ErsatzTV/Pages/TelevisionSeasonList.razor b/ErsatzTV/Pages/TelevisionSeasonList.razor
index a5e2cd407..f30909d05 100644
--- a/ErsatzTV/Pages/TelevisionSeasonList.razor
+++ b/ErsatzTV/Pages/TelevisionSeasonList.razor
@@ -23,7 +23,7 @@
}
else
{
-
+
}
}
@@ -41,7 +41,7 @@
{
+ src="@($"artwork/posters/{_show.Poster}")" alt="movie poster"/>
}
}
@@ -144,7 +144,7 @@
@foreach (TelevisionSeasonCardViewModel card in _data.Cards)
{
}
@@ -215,7 +215,7 @@
if (!result.Cancelled && result.Data is MediaCollectionViewModel collection)
{
await _mediator.Send(new AddShowToCollection(collection.Id, ShowId), _cts.Token);
- _navigationManager.NavigateTo($"/media/collections/{collection.Id}");
+ _navigationManager.NavigateTo($"media/collections/{collection.Id}");
}
}
@@ -229,7 +229,7 @@
if (!result.Cancelled && result.Data is ProgramScheduleViewModel schedule)
{
await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.TelevisionShow, null, null, null, ShowId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null, null, null, null, null, null), _cts.Token);
- _navigationManager.NavigateTo($"/schedules/{schedule.Id}/items");
+ _navigationManager.NavigateTo($"schedules/{schedule.Id}/items");
}
}
diff --git a/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor b/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor
index ac7dd08f8..69dea28c7 100644
--- a/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor
+++ b/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor
@@ -55,7 +55,7 @@
}
@@ -98,7 +98,7 @@
private void PrevPage()
{
- string uri = $"/media/tv/seasons/page/{PageNumber - 1}";
+ string uri = $"media/tv/seasons/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
@@ -109,7 +109,7 @@
private void NextPage()
{
- string uri = $"/media/tv/seasons/page/{PageNumber + 1}";
+ string uri = $"media/tv/seasons/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
diff --git a/ErsatzTV/Pages/TelevisionShowList.razor b/ErsatzTV/Pages/TelevisionShowList.razor
index 934a23ea7..ca045c8e6 100644
--- a/ErsatzTV/Pages/TelevisionShowList.razor
+++ b/ErsatzTV/Pages/TelevisionShowList.razor
@@ -55,7 +55,7 @@
}
@@ -98,7 +98,7 @@
private void PrevPage()
{
- string uri = $"/media/tv/shows/page/{PageNumber - 1}";
+ string uri = $"media/tv/shows/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
@@ -109,7 +109,7 @@
private void NextPage()
{
- string uri = $"/media/tv/shows/page/{PageNumber + 1}";
+ string uri = $"media/tv/shows/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
diff --git a/ErsatzTV/Pages/TraktLists.razor b/ErsatzTV/Pages/TraktLists.razor
index 70d604deb..1c5984370 100644
--- a/ErsatzTV/Pages/TraktLists.razor
+++ b/ErsatzTV/Pages/TraktLists.razor
@@ -48,7 +48,7 @@
+ Link="@($"search?query=trakt_list%3a{context.TraktId}")">
diff --git a/ErsatzTV/Pages/Trash.razor b/ErsatzTV/Pages/Trash.razor
index 70efded27..e464389a0 100644
--- a/ErsatzTV/Pages/Trash.razor
+++ b/ErsatzTV/Pages/Trash.razor
@@ -107,7 +107,7 @@
@foreach (MovieCardViewModel card in _movies.Cards.OrderBy(m => m.SortTitle))
{
s.SortTitle))
{
s.SortTitle))
{
s.SortTitle))
{
+ Link="@($"watermarks/{context.Id}")">
@@ -65,7 +65,7 @@
-
+
Add Watermark
diff --git a/ErsatzTV/Pages/_Host.cshtml b/ErsatzTV/Pages/_Host.cshtml
index 00f642f25..d61c46c2a 100644
--- a/ErsatzTV/Pages/_Host.cshtml
+++ b/ErsatzTV/Pages/_Host.cshtml
@@ -29,7 +29,7 @@
$.ajax({
data: data,
type: 'POST',
- url: `/media/collections/${collectionId}/items`
+ url: `media/collections/${collectionId}/items`
});
}
});
diff --git a/ErsatzTV/Shared/MainLayout.razor b/ErsatzTV/Shared/MainLayout.razor
index 362e27a22..66f5a16c3 100644
--- a/ErsatzTV/Shared/MainLayout.razor
+++ b/ErsatzTV/Shared/MainLayout.razor
@@ -13,8 +13,8 @@
_isOpen = false)">
@@ -61,8 +61,8 @@
- M3U
- XMLTV
+ M3U
+ XMLTV
@* API *@
@@ -76,33 +76,33 @@
- Channels
- FFmpeg Profiles
- Watermarks
+ Channels
+ FFmpeg Profiles
+ Watermarks
- Local
- Emby
- Jellyfin
- Plex
+ Local
+ Emby
+ Jellyfin
+ Plex
- Libraries
- Trash
- TV Shows
- Movies
- Music
- Other Videos
- Songs
+ Libraries
+ Trash
+ TV Shows
+ Movies
+ Music
+ Other Videos
+ Songs
- Collections
- Trakt Lists
- Filler Presets
+ Collections
+ Trakt Lists
+ Filler Presets
- Schedules
- Playouts
- Settings
- Logs
+ Schedules
+ Playouts
+ Settings
+ Logs
ErsatzTV Version
diff --git a/ErsatzTV/Shared/MediaCard.razor b/ErsatzTV/Shared/MediaCard.razor
index b1784c9e0..972a764b9 100644
--- a/ErsatzTV/Shared/MediaCard.razor
+++ b/ErsatzTV/Shared/MediaCard.razor
@@ -153,7 +153,7 @@
return string.IsNullOrWhiteSpace(Data.Poster)
? "position: relative"
- : $"position: relative; background-image: url(/artwork/{PathForArtwork()}/{Data.Poster}); background-size: cover; background-position: center";
+ : $"position: relative; background-image: url(artwork/{PathForArtwork()}/{Data.Poster}); background-size: cover; background-position: center";
}
private string PathForArtwork() => ArtworkKind switch
diff --git a/ErsatzTV/Shared/RemoteMediaSourceEditor.razor b/ErsatzTV/Shared/RemoteMediaSourceEditor.razor
index 689dda27b..55a56bac1 100644
--- a/ErsatzTV/Shared/RemoteMediaSourceEditor.razor
+++ b/ErsatzTV/Shared/RemoteMediaSourceEditor.razor
@@ -53,7 +53,7 @@
{
Either result = await SaveSecrets(_model);
result.Match(
- _ => _navigationManager.NavigateTo($"/media/sources/{Name.ToLowerInvariant()}"),
+ _ => _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}"),
error =>
{
_snackbar.Add(error.Value, Severity.Error);
diff --git a/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor b/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor
index e733020c4..a7bcc137c 100644
--- a/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor
+++ b/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor
@@ -114,7 +114,7 @@
}
}
- _navigationManager.NavigateTo($"/media/sources/{Name.ToLowerInvariant()}");
+ _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}");
});
}
diff --git a/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor b/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor
index 67750dbc2..bceca3b2e 100644
--- a/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor
+++ b/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor
@@ -139,7 +139,7 @@
_snackbar.Add($"Unexpected error saving path replacements: {error.Value}", Severity.Error);
_logger.LogError("Unexpected error saving path replacements: {Error}", error.Value);
},
- () => _navigationManager.NavigateTo($"/media/sources/{Name.ToLowerInvariant()}"));
+ () => _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}"));
}
}
\ No newline at end of file
diff --git a/ErsatzTV/Shared/RemoteMediaSources.razor b/ErsatzTV/Shared/RemoteMediaSources.razor
index 0d05e45a1..e5a6502ee 100644
--- a/ErsatzTV/Shared/RemoteMediaSources.razor
+++ b/ErsatzTV/Shared/RemoteMediaSources.razor
@@ -35,12 +35,12 @@
+ Link="@($"media/sources/{Name.ToLowerInvariant()}/{context.Id}/libraries")">
+ Link="@($"media/sources/{Name.ToLowerInvariant()}/{context.Id}/paths")">
@@ -60,7 +60,7 @@
{
Connect @Name
@@ -70,7 +70,7 @@
{
Fix @Name Connection
diff --git a/ErsatzTV/Startup.cs b/ErsatzTV/Startup.cs
index d15a6e3c1..4d97d2c69 100644
--- a/ErsatzTV/Startup.cs
+++ b/ErsatzTV/Startup.cs
@@ -59,6 +59,7 @@ using FluentValidation.AspNetCore;
using Ganss.Xss;
using MediatR;
using MediatR.Courier.DependencyInjection;
+using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
@@ -87,6 +88,7 @@ public class Startup
{
BugsnagConfiguration bugsnagConfig = Configuration.GetSection("Bugsnag").Get();
services.Configure(Configuration.GetSection("Bugsnag"));
+ services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.All; });
services.AddBugsnag(
configuration =>
@@ -269,8 +271,16 @@ public class Startup
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
+ string baseUrl = Environment.GetEnvironmentVariable("ETV_BASE_URL");
+ if (!string.IsNullOrWhiteSpace(baseUrl))
+ {
+ app.UsePathBase(baseUrl);
+ }
+
app.UseCors("AllowAll");
+ app.UseForwardedHeaders();
+ // app.UseHttpLogging();
// app.UseSerilogRequestLogging();
app.UseStaticFiles();