Browse Source

fix searching when queries include non-ascii characters (#271)

pull/272/head
Jason Dove 5 years ago committed by GitHub
parent
commit
b580125e86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 58
      ErsatzTV/Extensions/StringExtensions.cs
  3. 17
      ErsatzTV/Pages/Artist.razor
  4. 19
      ErsatzTV/Pages/ArtistList.razor
  5. 19
      ErsatzTV/Pages/EpisodeList.razor
  6. 31
      ErsatzTV/Pages/Movie.razor
  7. 19
      ErsatzTV/Pages/MovieList.razor
  8. 19
      ErsatzTV/Pages/MusicVideoList.razor
  9. 44
      ErsatzTV/Pages/Search.razor
  10. 8
      ErsatzTV/Pages/TelevisionEpisodeList.razor
  11. 23
      ErsatzTV/Pages/TelevisionSeasonList.razor
  12. 19
      ErsatzTV/Pages/TelevisionShowList.razor
  13. 4
      ErsatzTV/Shared/LetterBar.razor
  14. 18
      ErsatzTV/Shared/MainLayout.razor

1
CHANGELOG.md

@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix blazor error font color
- Fix some audio stream languages missing from UI and search index
- Fix audio stream selection for languages with multiple codes
- Fix searching when queries contain non-ascii characters
## [0.0.46-prealpha] - 2021-06-14
### Added

58
ErsatzTV/Extensions/StringExtensions.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Primitives;
namespace ErsatzTV.Extensions
{
public static class StringExtensions
{
public static string GetSearchQuery(this string uri)
{
try
{
string query = new Uri(uri).Query;
Dictionary<string, StringValues> parsed = QueryHelpers.ParseQuery(query);
if (parsed.TryGetValue("query", out StringValues value))
{
return value;
}
if (parsed.TryGetValue("b64query", out StringValues base64Value))
{
return base64Value.DecodeBase64();
}
}
catch (Exception)
{
// do nothing
}
return string.Empty;
}
public static string GetRelativeSearchQuery(this string query)
{
(string key, string value) = EncodeQuery(query);
return $"/search?{key}={value}";
}
private static string DecodeBase64(this StringValues input) =>
Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(input));
public static EncodedQueryResult EncodeQuery(this string query)
{
string encoded = Uri.EscapeDataString(query);
// TODO: remove this on dotnet 6
// see https://github.com/dotnet/aspnetcore/pull/26769
var fakeAbsolute = $"https://whatever.com/test?query={encoded}";
return Uri.IsWellFormedUriString(fakeAbsolute, UriKind.Absolute)
? new EncodedQueryResult("query", encoded)
: new EncodedQueryResult("b64query", WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(query)));
}
public record EncodedQueryResult(string Key, string Value);
}
}

17
ErsatzTV/Pages/Artist.razor

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
@using ErsatzTV.Application.ProgramSchedules
@using ErsatzTV.Application.ProgramSchedules.Commands
@using System.Globalization
@using ErsatzTV.Extensions
@using Unit = LanguageExt.Unit
@inject IMediator _mediator
@inject IDialogService _dialog
@ -73,11 +74,11 @@ @@ -73,11 +74,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Languages:&nbsp;</MudText>
<MudLink Href="@($"/search?query=language%3a%22{Uri.EscapeDataString(_sortedLanguages.Head().EnglishName.ToLowerInvariant())}%22")">@_sortedLanguages.Head().EnglishName</MudLink>
<MudLink Href="@(@$"language:""{_sortedLanguages.Head().EnglishName.ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedLanguages.Head().EnglishName</MudLink>
@foreach (CultureInfo language in _sortedLanguages.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=language%3a%22{Uri.EscapeDataString(language.EnglishName.ToLowerInvariant())}%22")">@language.EnglishName</MudLink>
<MudLink Href="@(@$"language:""{language.EnglishName.ToLowerInvariant()}""".GetRelativeSearchQuery())">@language.EnglishName</MudLink>
}
</div>
}
@ -85,11 +86,11 @@ @@ -85,11 +86,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Genres:&nbsp;</MudText>
<MudLink Href="@($"/search?query=genre%3a%22{Uri.EscapeDataString(_sortedGenres.Head())}%22")">@_sortedGenres.Head()</MudLink>
<MudLink Href="@(@$"genre:""{_sortedGenres.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedGenres.Head()</MudLink>
@foreach (string genre in _sortedGenres.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=genre%3a%22{Uri.EscapeDataString(genre)}%22")">@genre</MudLink>
<MudLink Href="@(@$"genre:""{genre.ToLowerInvariant()}""".GetRelativeSearchQuery())">@genre</MudLink>
}
</div>
}
@ -97,11 +98,11 @@ @@ -97,11 +98,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Styles:&nbsp;</MudText>
<MudLink Href="@($"/search?query=style%3a%22{Uri.EscapeDataString(_sortedStyles.Head())}%22")">@_sortedStyles.Head()</MudLink>
<MudLink Href="@(@$"style:""{_sortedStyles.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedStyles.Head()</MudLink>
@foreach (string style in _sortedStyles.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=style%3a%22{Uri.EscapeDataString(style)}%22")">@style</MudLink>
<MudLink Href="@(@$"style:""{style.ToLowerInvariant()}""".GetRelativeSearchQuery())">@style</MudLink>
}
</div>
}
@ -109,11 +110,11 @@ @@ -109,11 +110,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Moods:&nbsp;</MudText>
<MudLink Href="@($"/search?query=mood%3a%22{Uri.EscapeDataString(_sortedMoods.Head())}%22")">@_sortedMoods.Head()</MudLink>
<MudLink Href="@(@$"mood:""{_sortedMoods.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedMoods.Head()</MudLink>
@foreach (string mood in _sortedMoods.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=mood%3a%22{Uri.EscapeDataString(mood)}%22")">@mood</MudLink>
<MudLink Href="@(@$"mood:""{mood.ToLowerInvariant()}""".GetRelativeSearchQuery())">@mood</MudLink>
}
</div>
}

19
ErsatzTV/Pages/ArtistList.razor

@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
@page "/media/music/artists/page/{PageNumber:int}"
@using LanguageExt.UnsafeValueAccess
@using Microsoft.AspNetCore.WebUtilities
@using Microsoft.Extensions.Primitives
@using ErsatzTV.Application.MediaCards
@using ErsatzTV.Application.MediaCollections
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Application.Search.Queries
@using ErsatzTV.Extensions
@using Unit = LanguageExt.Unit
@inherits MultiSelectBase<MusicVideoList>
@inject NavigationManager _navigationManager
@ -90,16 +90,7 @@ @@ -90,16 +90,7 @@
PageNumber = 1;
}
string query = new Uri(_navigationManager.Uri).Query;
if (QueryHelpers.ParseQuery(query).TryGetValue("query", out StringValues value))
{
_query = value;
}
else
{
_query = null;
}
_query = _navigationManager.Uri.GetSearchQuery();
return RefreshData();
}
@ -114,7 +105,8 @@ @@ -114,7 +105,8 @@
var uri = $"/media/music/artists/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}
@ -124,7 +116,8 @@ @@ -124,7 +116,8 @@
var uri = $"/media/music/artists/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}

19
ErsatzTV/Pages/EpisodeList.razor

@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
@page "/media/tv/episodes/page/{PageNumber:int}"
@using LanguageExt.UnsafeValueAccess
@using Microsoft.AspNetCore.WebUtilities
@using Microsoft.Extensions.Primitives
@using ErsatzTV.Application.MediaCards
@using ErsatzTV.Application.MediaCollections
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Application.Search.Queries
@using ErsatzTV.Extensions
@using Unit = LanguageExt.Unit
@inherits MultiSelectBase<EpisodeList>
@inject NavigationManager _navigationManager
@ -90,16 +90,7 @@ @@ -90,16 +90,7 @@
PageNumber = 1;
}
string query = new Uri(_navigationManager.Uri).Query;
if (QueryHelpers.ParseQuery(query).TryGetValue("query", out StringValues value))
{
_query = value;
}
else
{
_query = null;
}
_query = _navigationManager.Uri.GetSearchQuery();
return RefreshData();
}
@ -114,7 +105,8 @@ @@ -114,7 +105,8 @@
var uri = $"/media/tv/episodes/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}
@ -124,7 +116,8 @@ @@ -124,7 +116,8 @@
var uri = $"/media/tv/episodes/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}

31
ErsatzTV/Pages/Movie.razor

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
@using ErsatzTV.Application.MediaCards
@using ErsatzTV.Application.MediaCollections
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Extensions
@inject IMediator _mediator
@inject IDialogService _dialog
@inject NavigationManager _navigationManager
@ -67,11 +68,11 @@ @@ -67,11 +68,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Content Ratings:&nbsp;</MudText>
<MudLink Href="@($"/search?query=content_rating%3a%22{Uri.EscapeDataString(_sortedContentRatings.Head())}%22")">@_sortedContentRatings.Head()</MudLink>
<MudLink Href="@(@$"content_rating:""{_sortedContentRatings.Head()}""".GetRelativeSearchQuery())">@_sortedContentRatings.Head()</MudLink>
@foreach (string contentRating in _sortedContentRatings.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=content_rating%3a%22{Uri.EscapeDataString(contentRating)}%22")">@contentRating</MudLink>
<MudLink Href="@(@$"content_rating:""{contentRating}""".GetRelativeSearchQuery())">@contentRating</MudLink>
}
</div>
}
@ -79,11 +80,11 @@ @@ -79,11 +80,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Languages:&nbsp;</MudText>
<MudLink Href="@($"/search?query=language%3a%22{Uri.EscapeDataString(_sortedLanguages.Head().EnglishName.ToLowerInvariant())}%22")">@_sortedLanguages.Head().EnglishName</MudLink>
<MudLink Href="@(@$"language:""{_sortedLanguages.Head().EnglishName.ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedLanguages.Head().EnglishName</MudLink>
@foreach (CultureInfo language in _sortedLanguages.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=language%3a%22{Uri.EscapeDataString(language.EnglishName.ToLowerInvariant())}%22")">@language.EnglishName</MudLink>
<MudLink Href="@(@$"language:""{language.EnglishName.ToLowerInvariant()}""".GetRelativeSearchQuery())">@language.EnglishName</MudLink>
}
</div>
}
@ -91,11 +92,11 @@ @@ -91,11 +92,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Studios:&nbsp;</MudText>
<MudLink Href="@($"/search?query=studio%3a%22{Uri.EscapeDataString(_sortedStudios.Head())}%22")">@_sortedStudios.Head()</MudLink>
<MudLink Href="@(@$"studio:""{_sortedStudios.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedStudios.Head()</MudLink>
@foreach (string studio in _sortedStudios.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=studio%3a%22{Uri.EscapeDataString(studio)}%22")">@studio</MudLink>
<MudLink Href="@(@$"studio:""{studio.ToLowerInvariant()}""".GetRelativeSearchQuery())">@studio</MudLink>
}
</div>
}
@ -103,11 +104,11 @@ @@ -103,11 +104,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Directors:&nbsp;</MudText>
<MudLink Href="@($"/search?query=director%3a%22{Uri.EscapeDataString(_sortedDirectors.Head())}%22")">@_sortedDirectors.Head()</MudLink>
<MudLink Href="@(@$"director:""{_sortedDirectors.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedDirectors.Head()</MudLink>
@foreach (string director in _sortedDirectors.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=director%3a%22{Uri.EscapeDataString(director)}%22")">@director</MudLink>
<MudLink Href="@(@$"director:""{director.ToLowerInvariant()}""".GetRelativeSearchQuery())">@director</MudLink>
}
</div>
}
@ -115,11 +116,11 @@ @@ -115,11 +116,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Writers:&nbsp;</MudText>
<MudLink Href="@($"/search?query=writer%3a%22{Uri.EscapeDataString(_sortedWriters.Head())}%22")">@_sortedWriters.Head()</MudLink>
<MudLink Href="@(@$"writer:""{_sortedWriters.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedWriters.Head()</MudLink>
@foreach (string writer in _sortedWriters.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=writer%3a%22{Uri.EscapeDataString(writer)}%22")">@writer</MudLink>
<MudLink Href="@(@$"writer:""{writer.ToLowerInvariant()}""".GetRelativeSearchQuery())">@writer</MudLink>
}
</div>
}
@ -127,11 +128,11 @@ @@ -127,11 +128,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Genres:&nbsp;</MudText>
<MudLink Href="@($"/search?query=genre%3a%22{Uri.EscapeDataString(_sortedGenres.Head())}%22")">@_sortedGenres.Head()</MudLink>
<MudLink Href="@(@$"genre:""{_sortedGenres.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedGenres.Head()</MudLink>
@foreach (string genre in _sortedGenres.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=genre%3a%22{Uri.EscapeDataString(genre)}%22")">@genre</MudLink>
<MudLink Href="@(@$"genre:""{genre.ToLowerInvariant()}""".GetRelativeSearchQuery())">@genre</MudLink>
}
</div>
}
@ -139,11 +140,11 @@ @@ -139,11 +140,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Tags:&nbsp;</MudText>
<MudLink Href="@($"/search?query=tag%3a%22{Uri.EscapeDataString(_sortedTags.Head())}%22")">@_sortedTags.Head()</MudLink>
<MudLink Href="@(@$"tag:""{_sortedTags.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedTags.Head()</MudLink>
@foreach (string tag in _sortedTags.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=tag%3a%22{Uri.EscapeDataString(tag)}%22")">@tag</MudLink>
<MudLink Href="@(@$"tag:""{tag.ToLowerInvariant()}""".GetRelativeSearchQuery())">@tag</MudLink>
}
</div>
}
@ -159,7 +160,7 @@ @@ -159,7 +160,7 @@
@foreach (ActorCardViewModel actor in _movie.Actors)
{
<MediaCard Data="@actor"
Link="@($"/search?query=actor%3a%22{Uri.EscapeDataString(actor.Name.ToLowerInvariant())}%22")"
Link="@(@$"actor:""{actor.Name.ToLowerInvariant()}""".GetRelativeSearchQuery())"
IsRemoteArtwork="true"
ArtworkKind="ArtworkKind.Thumbnail"/>
}

19
ErsatzTV/Pages/MovieList.razor

@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
@page "/media/movies/page/{PageNumber:int}"
@using LanguageExt.UnsafeValueAccess
@using Microsoft.AspNetCore.WebUtilities
@using Microsoft.Extensions.Primitives
@using ErsatzTV.Application.MediaCards
@using ErsatzTV.Application.MediaCollections
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Application.Search.Queries
@using ErsatzTV.Extensions
@using Unit = LanguageExt.Unit
@inherits MultiSelectBase<MovieList>
@inject NavigationManager _navigationManager
@ -89,16 +89,7 @@ @@ -89,16 +89,7 @@
PageNumber = 1;
}
string query = new Uri(_navigationManager.Uri).Query;
if (QueryHelpers.ParseQuery(query).TryGetValue("query", out StringValues value))
{
_query = value;
}
else
{
_query = null;
}
_query = _navigationManager.Uri.GetSearchQuery();
return RefreshData();
}
@ -113,7 +104,8 @@ @@ -113,7 +104,8 @@
var uri = $"/media/movies/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}
@ -123,7 +115,8 @@ @@ -123,7 +115,8 @@
var uri = $"/media/movies/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}

19
ErsatzTV/Pages/MusicVideoList.razor

@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
@page "/media/music/videos/page/{PageNumber:int}"
@using LanguageExt.UnsafeValueAccess
@using Microsoft.AspNetCore.WebUtilities
@using Microsoft.Extensions.Primitives
@using ErsatzTV.Application.MediaCards
@using ErsatzTV.Application.MediaCollections
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Application.Search.Queries
@using ErsatzTV.Extensions
@using Unit = LanguageExt.Unit
@inherits MultiSelectBase<MusicVideoList>
@inject NavigationManager _navigationManager
@ -90,16 +90,7 @@ @@ -90,16 +90,7 @@
PageNumber = 1;
}
string query = new Uri(_navigationManager.Uri).Query;
if (QueryHelpers.ParseQuery(query).TryGetValue("query", out StringValues value))
{
_query = value;
}
else
{
_query = null;
}
_query = _navigationManager.Uri.GetSearchQuery();
return RefreshData();
}
@ -114,7 +105,8 @@ @@ -114,7 +105,8 @@
var uri = $"/media/music/videos/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}
@ -124,7 +116,8 @@ @@ -124,7 +116,8 @@
var uri = $"/media/music/videos/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}

44
ErsatzTV/Pages/Search.razor

@ -4,8 +4,8 @@ @@ -4,8 +4,8 @@
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Application.Search
@using ErsatzTV.Application.Search.Queries
@using ErsatzTV.Extensions
@using Microsoft.AspNetCore.WebUtilities
@using Microsoft.Extensions.Primitives
@using Unit = LanguageExt.Unit
@inherits MultiSelectBase<Search>
@inject NavigationManager _navigationManager
@ -35,27 +35,27 @@ @@ -35,27 +35,27 @@
else
{
<MudText Style="margin-bottom: auto; margin-top: auto">@_query</MudText>
if (_movies.Count > 0)
if (_movies?.Count > 0)
{
<MudLink Class="ml-4" Href="@(_navigationManager.Uri.Split("#").Head() + "#movies")" Style="margin-bottom: auto; margin-top: auto">@_movies.Count Movies</MudLink>
}
if (_shows.Count > 0)
if (_shows?.Count > 0)
{
<MudLink Class="ml-4" Href="@(_navigationManager.Uri.Split("#").Head() + "#shows")" Style="margin-bottom: auto; margin-top: auto">@_shows.Count Shows</MudLink>
}
if (_episodes.Count > 0)
if (_episodes?.Count > 0)
{
<MudLink Class="ml-4" Href="@(_navigationManager.Uri.Split("#").Head() + "#episodes")" Style="margin-bottom: auto; margin-top: auto">@_episodes.Count Episodes</MudLink>
}
if (_artists.Count > 0)
if (_artists?.Count > 0)
{
<MudLink Class="ml-4" Href="@(_navigationManager.Uri.Split("#").Head() + "#artists")" Style="margin-bottom: auto; margin-top: auto">@_artists.Count Artists</MudLink>
}
if (_musicVideos.Count > 0)
if (_musicVideos?.Count > 0)
{
<MudLink Class="ml-4" Href="@(_navigationManager.Uri.Split("#").Head() + "#music_videos")" Style="margin-bottom: auto; margin-top: auto">@_musicVideos.Count Music Videos</MudLink>
}
@ -71,7 +71,7 @@ @@ -71,7 +71,7 @@
</div>
</MudPaper>
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Style="margin-top: 96px">
@if (_movies.Count > 0)
@if (_movies?.Count > 0)
{
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
<MudText Typo="Typo.h4"
@ -98,7 +98,7 @@ @@ -98,7 +98,7 @@
</MudContainer>
}
@if (_shows.Count > 0)
@if (_shows?.Count > 0)
{
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
<MudText Typo="Typo.h4"
@ -125,7 +125,7 @@ @@ -125,7 +125,7 @@
</MudContainer>
}
@if (_episodes.Count > 0)
@if (_episodes?.Count > 0)
{
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
<MudText Typo="Typo.h4"
@ -153,7 +153,7 @@ @@ -153,7 +153,7 @@
</MudContainer>
}
@if (_artists.Count > 0)
@if (_artists?.Count > 0)
{
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
<MudText Typo="Typo.h4"
@ -181,7 +181,7 @@ @@ -181,7 +181,7 @@
</MudContainer>
}
@if (_musicVideos.Count > 0)
@if (_musicVideos?.Count > 0)
{
<div class="mb-4" style="align-items: baseline; display: flex; flex-direction: row;">
<MudText Typo="Typo.h4"
@ -220,12 +220,9 @@ @@ -220,12 +220,9 @@
protected override async Task OnInitializedAsync()
{
string query = new Uri(_navigationManager.Uri).Query;
if (QueryHelpers.ParseQuery(query).TryGetValue("query", out StringValues value))
_query = _navigationManager.Uri.GetSearchQuery();
if (!string.IsNullOrWhiteSpace(_query))
{
_query = value;
_movies = await Mediator.Send(new QuerySearchIndexMovies($"type:movie AND ({_query})", 1, 50));
_shows = await Mediator.Send(new QuerySearchIndexShows($"type:show AND ({_query})", 1, 50));
_episodes = await Mediator.Send(new QuerySearchIndexEpisodes($"type:episode AND ({_query})", 1, 50));
@ -362,7 +359,8 @@ @@ -362,7 +359,8 @@
var uri = "/media/movies/page/1";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
return uri;
}
@ -372,7 +370,8 @@ @@ -372,7 +370,8 @@
var uri = "/media/tv/shows/page/1";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
return uri;
}
@ -382,7 +381,8 @@ @@ -382,7 +381,8 @@
var uri = "/media/tv/episodes/page/1";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
return uri;
}
@ -392,7 +392,8 @@ @@ -392,7 +392,8 @@
var uri = "/media/music/artists/page/1";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
return uri;
}
@ -402,7 +403,8 @@ @@ -402,7 +403,8 @@
var uri = "/media/music/videos/page/1";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
return uri;
}

8
ErsatzTV/Pages/TelevisionEpisodeList.razor

@ -116,11 +116,11 @@ @@ -116,11 +116,11 @@
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Directors:&nbsp;</MudText>
<MudLink Href="@($"/search?query=director%3a%22{Uri.EscapeDataString(sorted.Head())}%22")">@sorted.Head()</MudLink>
<MudLink Href="@(@$"director:""{sorted.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@sorted.Head()</MudLink>
@foreach (string director in sorted.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=director%3a%22{Uri.EscapeDataString(director)}%22")">@director</MudLink>
<MudLink Href="@(@$"director:""{director.ToLowerInvariant()}""".GetRelativeSearchQuery())">@director</MudLink>
}
</div>
}
@ -130,11 +130,11 @@ @@ -130,11 +130,11 @@
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Writers:&nbsp;</MudText>
<MudLink Href="@($"/search?query=writer%3a%22{Uri.EscapeDataString(sorted.Head())}%22")">@sorted.Head()</MudLink>
<MudLink Href="@(@$"writer:""{sorted.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@sorted.Head()</MudLink>
@foreach (string writer in sorted.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=writer%3a%22{Uri.EscapeDataString(writer)}%22")">@writer</MudLink>
<MudLink Href="@(@$"writer:""{writer.ToLowerInvariant()}""".GetRelativeSearchQuery())">@writer</MudLink>
}
</div>
}

23
ErsatzTV/Pages/TelevisionSeasonList.razor

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Application.ProgramSchedules
@using ErsatzTV.Application.ProgramSchedules.Commands
@using ErsatzTV.Extensions
@using Unit = LanguageExt.Unit
@inject IMediator _mediator
@inject ILogger<TelevisionSeasonList> _logger
@ -81,11 +82,11 @@ @@ -81,11 +82,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Content Ratings:&nbsp;</MudText>
<MudLink Href="@($"/search?query=content_rating%3a%22{Uri.EscapeDataString(_sortedContentRatings.Head())}%22")">@_sortedContentRatings.Head()</MudLink>
<MudLink Href="@(@$"content_rating:""{_sortedContentRatings.Head()}""".GetRelativeSearchQuery())">@_sortedContentRatings.Head()</MudLink>
@foreach (string contentRating in _sortedContentRatings.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=content_rating%3a%22{Uri.EscapeDataString(contentRating)}%22")">@contentRating</MudLink>
<MudLink Href="@(@$"content_rating:""{contentRating}""".GetRelativeSearchQuery())">@contentRating</MudLink>
}
</div>
}
@ -93,11 +94,11 @@ @@ -93,11 +94,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Languages:&nbsp;</MudText>
<MudLink Href="@($"/search?query=language%3a%22{Uri.EscapeDataString(_sortedLanguages.Head().EnglishName.ToLowerInvariant())}%22")">@_sortedLanguages.Head().EnglishName</MudLink>
<MudLink Href="@(@$"language:""{_sortedLanguages.Head().EnglishName.ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedLanguages.Head().EnglishName</MudLink>
@foreach (CultureInfo language in _sortedLanguages.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=language%3a%22{Uri.EscapeDataString(language.EnglishName.ToLowerInvariant())}%22")">@language.EnglishName</MudLink>
<MudLink Href="@(@$"language:""{language.EnglishName.ToLowerInvariant()}""".GetRelativeSearchQuery())">@language.EnglishName</MudLink>
}
</div>
}
@ -105,11 +106,11 @@ @@ -105,11 +106,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Studios:&nbsp;</MudText>
<MudLink Href="@($"/search?query=studio%3a%22{Uri.EscapeDataString(_sortedStudios.Head())}%22")">@_sortedStudios.Head()</MudLink>
<MudLink Href="@(@$"studio:""{_sortedStudios.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedStudios.Head()</MudLink>
@foreach (string studio in _sortedStudios.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=studio%3a%22{Uri.EscapeDataString(studio)}%22")">@studio</MudLink>
<MudLink Href="@(@$"studio:""{studio.ToLowerInvariant()}""".GetRelativeSearchQuery())">@studio</MudLink>
}
</div>
}
@ -117,11 +118,11 @@ @@ -117,11 +118,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Genres:&nbsp;</MudText>
<MudLink Href="@($"/search?query=genre%3a%22{Uri.EscapeDataString(_sortedGenres.Head())}%22")">@_sortedGenres.Head()</MudLink>
<MudLink Href="@(@$"genre:""{_sortedGenres.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedGenres.Head()</MudLink>
@foreach (string genre in _sortedGenres.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=genre%3a%22{Uri.EscapeDataString(genre)}%22")">@genre</MudLink>
<MudLink Href="@(@$"genre:""{genre.ToLowerInvariant()}""".GetRelativeSearchQuery())">@genre</MudLink>
}
</div>
}
@ -129,11 +130,11 @@ @@ -129,11 +130,11 @@
{
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
<MudText GutterBottom="true">Tags:&nbsp;</MudText>
<MudLink Href="@($"/search?query=tag%3a%22{Uri.EscapeDataString(_sortedTags.Head())}%22")">@_sortedTags.Head()</MudLink>
<MudLink Href="@(@$"tag:""{_sortedTags.Head().ToLowerInvariant()}""".GetRelativeSearchQuery())">@_sortedTags.Head()</MudLink>
@foreach (string tag in _sortedTags.Skip(1))
{
<MudText>,&nbsp;</MudText>
<MudLink Href="@($"/search?query=tag%3a%22{Uri.EscapeDataString(tag)}%22")">@tag</MudLink>
<MudLink Href="@(@$"tag:""{tag.ToLowerInvariant()}""".GetRelativeSearchQuery())">@tag</MudLink>
}
</div>
}
@ -160,7 +161,7 @@ @@ -160,7 +161,7 @@
@foreach (ActorCardViewModel actor in _show.Actors)
{
<MediaCard Data="@actor"
Link="@($"/search?query=actor%3a%22{Uri.EscapeDataString(actor.Name.ToLowerInvariant())}%22")"
Link="@(@$"actor:""{actor.Name.ToLowerInvariant()}""".GetRelativeSearchQuery())"
IsRemoteArtwork="true"
ArtworkKind="ArtworkKind.Thumbnail"/>
}

19
ErsatzTV/Pages/TelevisionShowList.razor

@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
@page "/media/tv/shows/page/{PageNumber:int}"
@using LanguageExt.UnsafeValueAccess
@using Microsoft.AspNetCore.WebUtilities
@using Microsoft.Extensions.Primitives
@using ErsatzTV.Application.MediaCards
@using ErsatzTV.Application.MediaCollections
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Application.Search.Queries
@using ErsatzTV.Extensions
@using Unit = LanguageExt.Unit
@inherits MultiSelectBase<TelevisionShowList>
@inject NavigationManager _navigationManager
@ -89,16 +89,7 @@ @@ -89,16 +89,7 @@
PageNumber = 1;
}
string query = new Uri(_navigationManager.Uri).Query;
if (QueryHelpers.ParseQuery(query).TryGetValue("query", out StringValues value))
{
_query = value;
}
else
{
_query = null;
}
_query = _navigationManager.Uri.GetSearchQuery();
return RefreshData();
}
@ -113,7 +104,8 @@ @@ -113,7 +104,8 @@
var uri = $"/media/tv/shows/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}
@ -123,7 +115,8 @@ @@ -123,7 +115,8 @@
var uri = $"/media/tv/shows/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
uri = QueryHelpers.AddQueryString(uri, "query", _query);
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
_navigationManager.NavigateTo(uri);
}

4
ErsatzTV/Shared/LetterBar.razor

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
@using ErsatzTV.Core.Search
@using ErsatzTV.Extensions
@using Microsoft.AspNetCore.WebUtilities
<div class="letter-bar-container">
<div class="letter-bar">
@ -48,7 +49,8 @@ @@ -48,7 +49,8 @@
var uri = $"{BaseUri}/page/{PageMap.PageMap[letter]}";
if (!string.IsNullOrWhiteSpace(Query))
{
uri = QueryHelpers.AddQueryString(uri, "query", Query);
(string key, string value) = Query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
return uri + $"#letter-{letter}";
}

18
ErsatzTV/Shared/MainLayout.razor

@ -1,7 +1,5 @@ @@ -1,7 +1,5 @@
@using System.Reflection
@using Microsoft.AspNetCore.WebUtilities
@using Microsoft.Extensions.Primitives
@using System.Web
@using ErsatzTV.Extensions
@inherits LayoutComponentBase
@inject NavigationManager _navigationManager
@ -107,22 +105,12 @@ @@ -107,22 +105,12 @@
protected override async Task OnParametersSetAsync()
{
await base.OnParametersSetAsync();
string query = new Uri(_navigationManager.Uri).Query;
if (QueryHelpers.ParseQuery(query).TryGetValue("query", out StringValues value))
{
_query = value;
}
else
{
_query = string.Empty;
}
_query = _navigationManager.Uri.GetSearchQuery();
}
private void PerformSearch()
{
string query = HttpUtility.UrlEncode(_query);
_navigationManager.NavigateTo($"/search?query={query}", true);
_navigationManager.NavigateTo(_query.GetRelativeSearchQuery(), true);
StateHasChanged();
}

Loading…
Cancel
Save