From 22d5a261c5f2fa94e7ca0f15269536cac2c0c6e3 Mon Sep 17 00:00:00 2001 From: Brian Bicknell Date: Tue, 17 Mar 2026 00:07:02 -0400 Subject: [PATCH] Fixed voice work supported language search. Include supported languages and original circle in the search result item. Several UI style updates. --- .../Queries/Search/VoiceWorkSearchResult.cs | 2 + .../VoiceWorks/VoiceWorkSearchProvider.cs | 90 +++++++++++- JSMR.UI.Blazor/Components/Chip.razor | 11 +- JSMR.UI.Blazor/Components/Icon.razor | 19 ++- JSMR.UI.Blazor/Components/JProduct.razor | 75 ++++++++-- JSMR.UI.Blazor/Components/ProductTag.razor | 19 ++- JSMR.UI.Blazor/Enums/Graphic.cs | 4 +- JSMR.UI.Blazor/Services/VoiceWorksClient.cs | 18 ++- JSMR.UI.Blazor/wwwroot/css/app.css | 138 ++++++++++++++++-- JSMR.UI.Blazor/wwwroot/css/theme-frozen.css | 6 + .../wwwroot/svg/cloud-download-fill.svg | 3 + JSMR.UI.Blazor/wwwroot/svg/cloud-download.svg | 4 + .../wwwroot/svg/microphone-fill.svg | 4 + JSMR.UI.Blazor/wwwroot/svg/microphone.svg | 4 + 14 files changed, 352 insertions(+), 45 deletions(-) create mode 100644 JSMR.UI.Blazor/wwwroot/svg/cloud-download-fill.svg create mode 100644 JSMR.UI.Blazor/wwwroot/svg/cloud-download.svg create mode 100644 JSMR.UI.Blazor/wwwroot/svg/microphone-fill.svg create mode 100644 JSMR.UI.Blazor/wwwroot/svg/microphone.svg diff --git a/JSMR.Application/VoiceWorks/Queries/Search/VoiceWorkSearchResult.cs b/JSMR.Application/VoiceWorks/Queries/Search/VoiceWorkSearchResult.cs index 1fc2371..8888173 100644 --- a/JSMR.Application/VoiceWorks/Queries/Search/VoiceWorkSearchResult.cs +++ b/JSMR.Application/VoiceWorks/Queries/Search/VoiceWorkSearchResult.cs @@ -28,8 +28,10 @@ public record VoiceWorkSearchResult public byte SubtitleLanguage { get; init; } public bool? IsValid { get; init; } public required VoiceWorkCircleItem Circle { get; set; } + public VoiceWorkCircleItem? OriginalCircle { get; set; } public VoiceWorkTagItem[] Tags { get; set; } = []; public VoiceWorkCreatorItem[] Creators { get; set; } = []; + public string[] SupportedLanguages { get; set; } = []; } public class VoiceWorkCircleItem diff --git a/JSMR.Infrastructure/Data/Repositories/VoiceWorks/VoiceWorkSearchProvider.cs b/JSMR.Infrastructure/Data/Repositories/VoiceWorks/VoiceWorkSearchProvider.cs index 63fc1b9..df05de8 100644 --- a/JSMR.Infrastructure/Data/Repositories/VoiceWorks/VoiceWorkSearchProvider.cs +++ b/JSMR.Infrastructure/Data/Repositories/VoiceWorks/VoiceWorkSearchProvider.cs @@ -3,6 +3,7 @@ using JSMR.Application.Enums; using JSMR.Application.VoiceWorks.Queries.Search; using JSMR.Domain.Entities; using JSMR.Domain.Enums; +using JSMR.Domain.ValueObjects; using JSMR.Infrastructure.Common.Queries; using Microsoft.EntityFrameworkCore; using System.Linq.Expressions; @@ -60,9 +61,10 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea break; } - if (criteria.SupportedLanguages.Length > 0) - filteredQuery = filteredQuery.Where(x => criteria.SupportedLanguages.AsEnumerable().Contains((Language)x.VoiceWork.SubtitleLanguage)); + //if (criteria.SupportedLanguages.Length > 0) + // filteredQuery = filteredQuery.Where(x => criteria.SupportedLanguages.AsEnumerable().Contains((Language)x.VoiceWork.SubtitleLanguage)); + filteredQuery = ApplySupportedLanguageFilter(filteredQuery, criteria); filteredQuery = ApplyCircleStatusFilter(filteredQuery, criteria); filteredQuery = ApplyTagStatusFilter(filteredQuery, criteria); filteredQuery = ApplyCreatorStatusFilter(filteredQuery, criteria); @@ -118,6 +120,26 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea return query.Where(x => voiceWorkIds.Contains(x.VoiceWork.VoiceWorkId)); } + + private IQueryable ApplySupportedLanguageFilter(IQueryable query, VoiceWorkSearchCriteria criteria) + { + if (criteria.SupportedLanguages.Length == 0) + return query; + + List languageCodes = []; + + foreach (Language language in criteria.SupportedLanguages) + { + if (SupportedLanguage.TryFromLanguage(language, out SupportedLanguage? supportedLanguage)) + languageCodes.Add(supportedLanguage.Code); + } + + if (languageCodes.Count == 0) + return query; + + return query.Where(q => context.VoiceWorkSupportedLanguages.Any(sl => sl.VoiceWorkId == q.VoiceWork.VoiceWorkId && languageCodes.Contains(sl.Language))); + } + private IQueryable ApplyCircleStatusFilter(IQueryable query, VoiceWorkSearchCriteria criteria) { if (criteria.CircleStatus is null) @@ -432,6 +454,7 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea PlannedReleaseDate = voiceWork.PlannedReleaseDate, Downloads = voiceWork.Downloads, WishlistCount = voiceWork.WishlistCount, + Rating = (AgeRating)voiceWork.Rating, Status = voiceWork.Status, SubtitleLanguage = voiceWork.SubtitleLanguage, HasTrial = voiceWork.HasTrial, @@ -449,16 +472,24 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea int[] voiceWorkIds = [.. items.Select(i => i.VoiceWorkId)]; - Dictionary tagsByVw = await GetTagsAsync(voiceWorkIds, cancellationToken); - Dictionary creatorsByVw = await GetCreatorsAsync(voiceWorkIds, cancellationToken); + var tagsByVoiceWork = await GetTagsAsync(voiceWorkIds, cancellationToken); + var creatorsByVoiceWork = await GetCreatorsAsync(voiceWorkIds, cancellationToken); + var supportedLanguagesByVoiceWork = await GetSupportedLanguagesAsync(voiceWorkIds, cancellationToken); + var originalCirclesByVoiceWork = await GetOriginalCircles(voiceWorkIds, cancellationToken); foreach (VoiceWorkSearchResult item in items) { - if (tagsByVw.TryGetValue(item.VoiceWorkId, out VoiceWorkTagItem[]? tags)) + if (tagsByVoiceWork.TryGetValue(item.VoiceWorkId, out VoiceWorkTagItem[]? tags)) item.Tags = tags; - if (creatorsByVw.TryGetValue(item.VoiceWorkId, out VoiceWorkCreatorItem[]? creators)) + if (creatorsByVoiceWork.TryGetValue(item.VoiceWorkId, out VoiceWorkCreatorItem[]? creators)) item.Creators = creators; + + if (supportedLanguagesByVoiceWork.TryGetValue(item.VoiceWorkId, out string[]? supportedLanguages)) + item.SupportedLanguages = supportedLanguages; + + if (originalCirclesByVoiceWork.TryGetValue(item.VoiceWorkId, out VoiceWorkCircleItem? voiceWorkCircleItem)) + item.OriginalCircle = voiceWorkCircleItem; } } @@ -499,4 +530,51 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea g => g.Select(r => new VoiceWorkCreatorItem { CreatorId = r.CreatorId, Name = r.Name, IsFavorite = r.Favorite, IsBlacklisted = r.Blacklisted }).ToArray() ); } + + private async Task> GetSupportedLanguagesAsync(int[] voiceWorkIds, CancellationToken cancellationToken) + { + var supportedLanguageRows = await ( + from voiceWorkSupportedLanguage in context.VoiceWorkSupportedLanguages.AsNoTracking() + where voiceWorkIds.Contains(voiceWorkSupportedLanguage.VoiceWorkId) + select new { voiceWorkSupportedLanguage.VoiceWorkId, voiceWorkSupportedLanguage.Language } + ).ToListAsync(cancellationToken); + + return supportedLanguageRows + .GroupBy(r => r.VoiceWorkId) + .ToDictionary( + g => g.Key, + g => g.Select(r => r.Language).ToArray() + ); + } + + private async Task> GetOriginalCircles(int[] voiceWorkIds, CancellationToken cancellationToken) + { + var originalCircleRows = await ( + from voiceWork in context.VoiceWorks.AsNoTracking() + join orignalVoiceWork in context.VoiceWorks.AsNoTracking() on voiceWork.OriginalProductId equals orignalVoiceWork.ProductId + join originalCircle in context.Circles.AsNoTracking() on orignalVoiceWork.CircleId equals originalCircle.CircleId + where voiceWorkIds.Contains(voiceWork.VoiceWorkId) + select new + { + voiceWork.VoiceWorkId, + originalCircle.Name, + originalCircle.MakerId, + originalCircle.Favorite, + originalCircle.Blacklisted + } + ).ToListAsync(cancellationToken); + + return originalCircleRows + .GroupBy(r => r.VoiceWorkId) + .ToDictionary( + g => g.Key, + g => g.Select(r => new VoiceWorkCircleItem() + { + Name = r.Name, + MakerId = r.MakerId, + IsFavorite = r.Favorite, + IsBlacklisted = r.Blacklisted + }).First() + ); + } } \ No newline at end of file diff --git a/JSMR.UI.Blazor/Components/Chip.razor b/JSMR.UI.Blazor/Components/Chip.razor index 5174406..186ea6c 100644 --- a/JSMR.UI.Blazor/Components/Chip.razor +++ b/JSMR.UI.Blazor/Components/Chip.razor @@ -3,12 +3,12 @@ @if (string.IsNullOrWhiteSpace(Url)) {
- @if (Graphic != null) + @if (Graphic != null && Graphic != Enums.Graphic.None) { + UseCurrentColor> } @ChildContent @@ -23,7 +23,7 @@ else Graphic="@Graphic.Value" Varient="@(IconVarient ?? Enums.IconVarient.None)" Size="@(IconSize ?? Enums.SizeVarient.Small)" - Color="@Color"> + UseCurrentColor> } @ChildContent @@ -94,6 +94,11 @@ else break; } + if (Varient == ElementVarient.Filled && Tone == ToneVarient.Tint) + { + classNames.Add($"varient-tint"); + } + if (Click.HasDelegate || string.IsNullOrWhiteSpace(Url) == false) { classNames.Add("is-clickable"); diff --git a/JSMR.UI.Blazor/Components/Icon.razor b/JSMR.UI.Blazor/Components/Icon.razor index b9507f2..91e9523 100644 --- a/JSMR.UI.Blazor/Components/Icon.razor +++ b/JSMR.UI.Blazor/Components/Icon.razor @@ -1,6 +1,6 @@ @using JSMR.UI.Blazor.Enums -
+
@code { [Parameter] @@ -15,20 +15,33 @@ [Parameter] public ColorVarient Color { get; set; } + [Parameter] + public bool UseCurrentColor { get; set; } + private string GetIconClasses() { string graphic = Varient == IconVarient.None ? Graphic.ToString().ToLower() : $"{Graphic.ToString().ToLower()}-{Varient.ToString().ToLower()}"; - + List classNames = [ $"j-icon", $"j-icon-{graphic}", $"size-{Size.ToString().ToLower()}", - $"background-color-{Color.ToString().ToLower()}" + //$"background-color-{Color.ToString().ToLower()}" ]; + if (!UseCurrentColor) + { + classNames.Add($"background-color-{Color.ToString().ToLower()}"); + } + return string.Join(" ", classNames); } + + private string? GetStyle() + { + return UseCurrentColor ? "background-color: currentColor;" : null; + } } \ No newline at end of file diff --git a/JSMR.UI.Blazor/Components/JProduct.razor b/JSMR.UI.Blazor/Components/JProduct.razor index 582741c..992d17f 100644 --- a/JSMR.UI.Blazor/Components/JProduct.razor +++ b/JSMR.UI.Blazor/Components/JProduct.razor @@ -15,34 +15,66 @@ -
- - + @* @Product.Maker - @* *@ - @foreach (var creator in Product.Creators) - { - @Product.Maker *@ + @* *@ + @Product.Maker + + @if (Product.OriginalCircle is not null) + { + @Product.OriginalCircle.Name + } + + @foreach (var creator in Product.Creators) + { + @* @creator.Name - @* *@ - } - -
+ Icon="@Icons.Material.Filled.Person">@creator.Name *@ + @* *@ + @creator.Name + } + + + @foreach (string supportedLanguage in Product.SupportedLanguages) + { + @GetSupportedLanguageDescription(supportedLanguage) + } + @if (Product.OriginalProductId is not null) + { + Translation + } + @if (Product.Rating == AgeRating.AllAges) + { + All Ages + } + else if (Product.Rating == AgeRating.R15) + { + R-15 + } + @if (Product.HasTrial || Product.HasChobit) + { + Trial + } + @if (Product.Favorite) + { + Favorite + } +
@Product.Description
@foreach (var tag in Product.Tags) { - @*
@tag.Name
*@ + @*
@tag.Name
*@ }
- @*
+ @*
@foreach (var tag in Product.Tags) { @@ -149,4 +181,17 @@ return "jp"; } } + + private string GetSupportedLanguageDescription(string code) + { + switch (code) + { + case "JPN": return "Japanese"; + case "ENG": return "English"; + case "CHI_HANS": return "Chinese (Simplified)"; + case "CHI_HANT": return "Chinese (Traditional)"; + case "KO_KR": return "Korean"; + default: return code; + } + } } diff --git a/JSMR.UI.Blazor/Components/ProductTag.razor b/JSMR.UI.Blazor/Components/ProductTag.razor index 35246c7..d575e27 100644 --- a/JSMR.UI.Blazor/Components/ProductTag.razor +++ b/JSMR.UI.Blazor/Components/ProductTag.razor @@ -1,11 +1,13 @@ @using JSMR.Application.Tags.Queries.Search.Contracts @using JSMR.Application.VoiceWorks.Queries.Search +@using JSMR.UI.Blazor.Enums @using JSMR.UI.Blazor.Filters @using JSMR.UI.Blazor.Services @using Microsoft.AspNetCore.WebUtilities -@Tag.Name +@* @Tag.Name *@ @* @Tag.Name *@ +@Tag.Name @code { [Inject] @@ -33,6 +35,21 @@ return string.Join(" ", classNames); } + private ColorVarient GetColorVarient() + { + if (Tag.IsFavorite) + { + return ColorVarient.Mint; + } + + if (Tag.IsFavorite) + { + return ColorVarient.Orange; + } + + return ColorVarient.Primary; + } + private void OnClick() { VoiceWorkFilterState state = new() diff --git a/JSMR.UI.Blazor/Enums/Graphic.cs b/JSMR.UI.Blazor/Enums/Graphic.cs index 13691a3..2c8f101 100644 --- a/JSMR.UI.Blazor/Enums/Graphic.cs +++ b/JSMR.UI.Blazor/Enums/Graphic.cs @@ -19,5 +19,7 @@ public enum Graphic Sort, Grid, Age, - Calendar + Calendar, + Download, + Microphone } \ No newline at end of file diff --git a/JSMR.UI.Blazor/Services/VoiceWorksClient.cs b/JSMR.UI.Blazor/Services/VoiceWorksClient.cs index 07b3153..6279838 100644 --- a/JSMR.UI.Blazor/Services/VoiceWorksClient.cs +++ b/JSMR.UI.Blazor/Services/VoiceWorksClient.cs @@ -3,32 +3,42 @@ using JSMR.Application.Creators.Queries.Search; using JSMR.Application.Tags.Queries.Search; using JSMR.Application.VoiceWorks.Queries.Search; using System.Net.Http.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace JSMR.UI.Blazor.Services; public class VoiceWorksClient(HttpClient http) { + private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web) + { + Converters = + { + new JsonStringEnumConverter() + } + }; + public async Task SearchAsync(SearchVoiceWorksRequest request, CancellationToken ct = default) { using var resp = await http.PostAsJsonAsync("/api/voiceworks/search", request, ct); - return await resp.Content.ReadFromJsonAsync(cancellationToken: ct); + return await resp.Content.ReadFromJsonAsync(JsonOptions, cancellationToken: ct); } public async Task SearchAsync(SearchCirclesRequest request, CancellationToken ct = default) { using var resp = await http.PostAsJsonAsync("/api/circles/search", request, ct); - return await resp.Content.ReadFromJsonAsync(cancellationToken: ct); + return await resp.Content.ReadFromJsonAsync(JsonOptions, cancellationToken: ct); } public async Task SearchAsync(SearchCreatorsRequest request, CancellationToken ct = default) { using var resp = await http.PostAsJsonAsync("/api/creators/search", request, ct); - return await resp.Content.ReadFromJsonAsync(cancellationToken: ct); + return await resp.Content.ReadFromJsonAsync(JsonOptions, cancellationToken: ct); } public async Task SearchAsync(SearchTagsRequest request, CancellationToken ct = default) { using var resp = await http.PostAsJsonAsync("/api/tags/search", request, ct); - return await resp.Content.ReadFromJsonAsync(cancellationToken: ct); + return await resp.Content.ReadFromJsonAsync(JsonOptions, cancellationToken: ct); } } \ No newline at end of file diff --git a/JSMR.UI.Blazor/wwwroot/css/app.css b/JSMR.UI.Blazor/wwwroot/css/app.css index 60c6732..d4c8c80 100644 --- a/JSMR.UI.Blazor/wwwroot/css/app.css +++ b/JSMR.UI.Blazor/wwwroot/css/app.css @@ -592,6 +592,7 @@ code { .j-tags { display: flex; gap: .75rem .5rem; + gap: .5rem .5rem; flex-wrap: wrap; /*gap: .5rem 1rem;*/ } @@ -647,41 +648,70 @@ code { .j-chip { display: inline-flex; align-items: center; - gap: .4rem; + gap: .5em; font-size: 1rem; font-weight: 500; font-size: .8rem; font-weight: 400; + /*--chip-rgb: var(--secondary-rgb, 148 163 184); + --chip-tint-alpha: 0.12;*/ + --chip-rgb: var(--secondary-rgb, 148 163 184); + --chip-bg-rgb: transparent; + --chip-fg-rgb: var(--chip-rgb); + --chip-border-rgb: transparent; --chip-tint-alpha: 0.12; + color: rgb(var(--chip-fg-rgb)); + background: rgb(var(--chip-bg-rgb)); + border: 1px solid rgb(var(--chip-border-rgb)); + padding: .5em 1em; + border-radius: 1rem; + border: 1px solid transparent; } .j-chip.is-clickable { cursor: pointer; user-select: none; - --chip-hover-alpha: 0.2; - transition: .2s linear; + transition: background .2s linear, color .2s linear, border-color .2s linear, filter .2s linear; } .j-chip.is-clickable:hover { - background: rgb(var(--chip-rgb) / var(--chip-hover-alpha)); + filter: brightness(1.2); } .j-chip.varient-filled { - padding: .4rem .8rem; - border-radius: 1rem; + --chip-bg-rgb: var(--chip-rgb); + --chip-border-rgb: var(--chip-rgb); } + /*.j-chip.varient-outlined { + --chip-bg-rgb: transparent; + --chip-fg-rgb: var(--chip-rgb); + --chip-border-rgb: var(--chip-rgb); + }*/ + .j-chip.varient-outlined { - border-width: 1px; - border-style: solid; - padding: .4rem .8rem; - border-radius: 1rem; - border-color: rgb(var(--chip-rgb)); + background: rgba(0,0,0,.35); + border: 1px solid rgb(var(--chip-rgb) / 0.65); color: rgb(var(--chip-rgb)); - background: transparent; } +/* .j-chip.varient-tint { + --chip-bg-rgb: var(--chip-rgb) / var(--chip-tint-alpha); + --chip-fg-rgb: var(--chip-rgb); + --chip-border-rgb: transparent; + }*/ + + .j-chip.varient-tint { + --chip-bg-alpha: 0.14; + --chip-border-alpha: 0.32; + color: rgb(var(--chip-rgb)); + background: rgb(var(--chip-rgb) / var(--chip-bg-alpha)); + /*border: 1px solid rgb(var(--chip-rgb) / var(--chip-border-alpha));*/ + } + + + /* Old ? */ .j-chip.tone-tint { background: rgb(var(--chip-rgb) / var(--chip-tint-alpha)); } @@ -698,6 +728,74 @@ code { --chip-rgb: var(--rgb-teal); } + /* New */ + .j-chip.color-primary { + --chip-rgb: var(--rgb-primary); + } + + .j-chip.varient-filled.color-primary { + --chip-fg-rgb: var(--rgb-on-primary, 0 0 0); + } + + .j-chip.color-secondary { + --chip-rgb: var(--rgb-secondary); + } + + .j-chip.varient-filled.color-secondary { + --chip-fg-rgb: var(--rgb-on-secondary, 0 0 0); + } + + .j-chip.color-mint { + --chip-rgb: var(--rgb-mint); + } + + .j-chip.varient-filled.color-mint { + --chip-fg-rgb: var(--rgb-on-mint, 0 0 0); + } + + .j-chip.color-green { + --chip-rgb: var(--rgb-green); + } + + .j-chip.varient-filled.color-green { + --chip-fg-rgb: var(--rgb-on-green, 255 255 255); + } + + .j-chip.color-yellow { + color: rgb(var(--chip-fg-rgb)); + --chip-rgb: var(--rgb-yellow); + } + + .j-chip.varient-filled.color-yellow { + --chip-fg-rgb: var(--rgb-on-yellow, 255 255 255); + } + + .j-chip.color-pink { + color: rgb(var(--chip-fg-rgb)); + --chip-rgb: var(--rgb-pink); + } + + .j-chip.varient-filled.color-pink { + --chip-fg-rgb: var(--rgb-on-pink, 255 255 255); + } + + .j-chip.color-teal { + --chip-rgb: var(--rgb-teal); + } + + .j-chip.varient-filled.color-teal { + --chip-fg-rgb: var(--rgb-on-teal, 255 255 255); + } + + .j-chip.color-black { + color: inherit; + --chip-rgb: 39 39 39; + } + + .j-chip.varient-filled.color-black { + --chip-fg-rgb: var(--primary-text-color); + } + /* Icons */ .j-icon { mask-repeat: no-repeat; @@ -825,6 +923,22 @@ code { mask-image: url("../svg/age-rating.svg"); } +.j-icon-download { + mask-image: url("../svg/cloud-download.svg"); +} + +.j-icon-download-fill { + mask-image: url("../svg/cloud-download-fill.svg"); +} + +.j-icon-microphone { + mask-image: url("../svg/microphone.svg"); +} + +.j-icon-microphone-fill { + mask-image: url("../svg/microphone-fill.svg"); +} + .j-icon-2 { background-repeat: no-repeat; background-position: center; diff --git a/JSMR.UI.Blazor/wwwroot/css/theme-frozen.css b/JSMR.UI.Blazor/wwwroot/css/theme-frozen.css index 2b5b2b6..90f5f82 100644 --- a/JSMR.UI.Blazor/wwwroot/css/theme-frozen.css +++ b/JSMR.UI.Blazor/wwwroot/css/theme-frozen.css @@ -40,9 +40,15 @@ --input-focus-border-color: #64b5f6; --input-focus-box-shadow: 0 0 0 1px #93cbf9; /* RGB Tokens */ + --rgb-primary: 180 200 214; + --rgb-secondary: 200 220 234; --rgb-mint: 167 243 208; --rgb-green: 175 224 125; --rgb-teal: 110 236 255; + --rgb-yellow: 255 224 115; + --rgb-on-yellow: 0 0 0; + --rgb-pink: 224 104 148; + --rgb-on-pink: 255 255 255; /* Colors */ --color-primary: rgb(180,200, 214); --color-secondary: rgb(200,220,234); diff --git a/JSMR.UI.Blazor/wwwroot/svg/cloud-download-fill.svg b/JSMR.UI.Blazor/wwwroot/svg/cloud-download-fill.svg new file mode 100644 index 0000000..e570ce7 --- /dev/null +++ b/JSMR.UI.Blazor/wwwroot/svg/cloud-download-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/JSMR.UI.Blazor/wwwroot/svg/cloud-download.svg b/JSMR.UI.Blazor/wwwroot/svg/cloud-download.svg new file mode 100644 index 0000000..f44cb73 --- /dev/null +++ b/JSMR.UI.Blazor/wwwroot/svg/cloud-download.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/JSMR.UI.Blazor/wwwroot/svg/microphone-fill.svg b/JSMR.UI.Blazor/wwwroot/svg/microphone-fill.svg new file mode 100644 index 0000000..c3a7c84 --- /dev/null +++ b/JSMR.UI.Blazor/wwwroot/svg/microphone-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/JSMR.UI.Blazor/wwwroot/svg/microphone.svg b/JSMR.UI.Blazor/wwwroot/svg/microphone.svg new file mode 100644 index 0000000..ef8eb33 --- /dev/null +++ b/JSMR.UI.Blazor/wwwroot/svg/microphone.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file