123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- @inherits ViewBase
- @code {
- private Dictionary<string, string> AllTrackSet;
- private string searchName { get => LocalStorage.Get<string>(); set => LocalStorage.Set(value); }
- private string searchArtist { get => LocalStorage.Get<string>(); set => LocalStorage.Set(value); }
- private string searchFind { get => LocalStorage.Get<string>() ?? "Track"; set => LocalStorage.Set(value); }
- private string searchTrackSetKey { get => LocalStorage.Get<string>() ?? "main"; set => LocalStorage.Set(value); }
- private int searchLimitCount { get => LocalStorage.Get<int?>() ?? 20; set => LocalStorage.Set(value); }
- private bool isSearching = false;
- private ProgressBar searchProgressBar;
- private static string resultText;
- private static IGrouping<FeDisc, FeTrack>[] resultTracks;
- private static FeDisc[] resultDiscs;
- private DiscDialog dlgDisc;
- }
- <div class="row">
- <div class="col-12">
- <fieldset class="border rounded-3 p-2">
- <legend class="float-none w-auto px-2 d-flex flex-row align-items-center">
- <span>Filter</span>
- </legend>
- <div class="input-group">
- <div class="form-floating">
- <InputText type="search" class="form-control" placeholder="Name"
- Value="@searchName"
- ValueExpression="@(()=>searchName)"
- @oninput="x=> searchName = x?.Value?.ToString()?.Trim() ?? string.Empty"
- onsearch="@SearchGo">
- </InputText>
- <label>Name</label>
- </div>
- </div>
- <div class="input-group mt-1">
- <div class="form-floating">
- <InputText type="search" class="form-control" placeholder="Artist"
- Value="@searchArtist"
- ValueExpression="@(()=>searchArtist)"
- @oninput="x=> searchArtist = x?.Value?.ToString()?.Trim() ?? string.Empty"
- onsearch="@SearchGo">
- </InputText>
- <label>Artist</label>
- </div>
- </div>
- <div class="row mt-3">
- <label class="col-sm-2 col-form-label">Find</label>
- <div class="col-sm-10">
- <FnzRadioGroup TValue="string"
- DataSource="@(new[] { "Track", "Disc" })"
- Value="searchFind"
- ValueChanged="async (v) => {searchFind = v; StateHasChanged(); await SearchGo(); }">
- </FnzRadioGroup>
- </div>
- </div>
- @if (searchFind == "Track")
- {
- <div class="row mt-3">
- <label class="col-sm-2 col-form-label">Track set</label>
- <div class="col-sm-10">
- <FnzRadioGroup TValue="string"
- DataSource="@AllTrackSet?.Keys.KeepNoEmpty()"
- Value="searchTrackSetKey"
- TextFormat="x=>x.ToUpper()"
- ValueChanged="async (v) => {searchTrackSetKey = v; StateHasChanged(); await SearchGo(); }">
- </FnzRadioGroup>
- </div>
- </div>
- }
- <div class="row mt-3">
- <label class="col-sm-2 col-form-label">Result count</label>
- <div class="col-sm-10">
- <FnzRadioGroup TValue="int"
- DataSource="@(new [] { 20, 50, 100, 200 })"
- Value="searchLimitCount"
- ValueChanged="async (v) => {searchLimitCount = v; StateHasChanged(); await SearchGo(); }">
- </FnzRadioGroup>
- </div>
- </div>
- <div class="row mt-3">
- <div class="col-12 text-end">
- <button @onclick="@SearchGo" class="btn btn-primary" type="button">Search</button>
- </div>
- </div>
- </fieldset>
- </div>
- </div>
- @if (isSearching)
- {
- <div class="row mt-4">
- <div class="col-12">
- <div class="btn-group w-100">
- <ProgressBar @ref="searchProgressBar" Throttle="333" class="btn border w-75"></ProgressBar>
- <button class="btn border btn-danger" @onclick="()=>isSearching=false">Stop search</button>
- </div>
- </div>
- </div>
- }
- <div class="row mt-3">
- <div class="col-12">
- <fieldset class="border rounded-3 p-2">
- <legend class="float-none w-auto px-2 d-flex flex-row align-items-center">
- <span>Result</span>
- </legend>
- <div class="mb-3 text-center">@resultText</div>
- @if (searchFind == "Track" && resultTracks?.Length > 0)
- {
- foreach (var item in resultTracks)
- {
- <SearchResultGroup DataSource="item" SearchName="searchName" SearchArtist="searchArtist"></SearchResultGroup>
- }
- }
- @if (searchFind == "Disc" && resultDiscs?.Length > 0)
- {
- <div class="row">
- @foreach (var disc in resultDiscs)
- {
- <DiscCard Disc="disc"></DiscCard>
- }
- </div>
- }
- </fieldset>
- </div>
- </div>
- @code {
- private async Task SearchGo()
- {
- if (isSearching) return;
- isSearching = true;
- StateHasChanged();
- await Task.Delay(1);
- var matchedCount = 0;
- var flagPlus = false;
- //var filterExpression
- if (searchFind == "Track")
- {
- var filteredList = new List<FeTrack>(searchLimitCount);
- var filters = new List<Func<FeTrack, bool>> { p => p.TrackSetKey == searchTrackSetKey };
- if (string.IsNullOrEmpty(searchName) == false)
- {
- filters.Add(p => p.GetTitleOrFilename().Contains(searchName, StringComparison.OrdinalIgnoreCase));
- }
- if (string.IsNullOrEmpty(searchArtist) == false)
- {
- filters.Add(p => p.Tag?.Artist.Contains(searchArtist, StringComparison.OrdinalIgnoreCase) == true);
- }
- for (var i = 0; i < DataSet.AllTracks.Length && isSearching; i++)
- {
- var item = DataSet.AllTracks[i];
- if (filters.All(p => p(item)))
- {
- ++matchedCount;
- if (filteredList.Count < searchLimitCount)
- {
- filteredList.Add(item);
- }
- else if (matchedCount >= searchLimitCount * 2)
- {
- flagPlus = true;
- break;
- }
- }
- await searchProgressBar.SetProgress((float)i / DataSet.AllTracks.Length, $"Searching {i + 1}/{DataSet.AllTracks.Length} matched:{matchedCount}");
- }
- resultText = $"Result for {searchName.NullOrEmptyEscape("<NONE>")} on {DataSet.AllTracksSet.Where(p => p.Key == searchTrackSetKey).Select(p => p.Name).FirstOrDefault() ?? "?"} limit {searchLimitCount} of {matchedCount}{(flagPlus ? "+" : "")}";
- resultTracks = filteredList
- .GroupBy(p => p.Disc)
- .ToArray();
- }
- else if (searchFind == "Disc")
- {
- var filteredList = new List<FeDisc>(searchLimitCount);
- var filters = new List<Func<FeDisc, bool>> { };
- if (string.IsNullOrEmpty(searchName) == false)
- {
- filters.Add(p => p.Name.Contains(searchName, StringComparison.OrdinalIgnoreCase));
- }
- if (string.IsNullOrEmpty(searchArtist) == false)
- {
- filters.Add(p => p.TrackSets.Any(s => s.Tracks.Any(t => t.Tag?.Artist.Contains(searchArtist, StringComparison.OrdinalIgnoreCase) == true)));
- }
- for (var i = 0; i < DataSet.AllDisc.Length && isSearching; i++)
- {
- var item = DataSet.AllDisc[i];
- if (filters.All(p => p(item)))
- {
- ++matchedCount;
- if (filteredList.Count < searchLimitCount)
- {
- filteredList.Add(item);
- }
- else if (matchedCount >= searchLimitCount * 2)
- {
- flagPlus = true;
- break;
- }
- }
- await searchProgressBar.SetProgress((float)i / DataSet.AllDisc.Length, $"Searching {i + 1}/{DataSet.AllDisc.Length} matched:{matchedCount}");
- }
- resultText = $"Result for Discs limit {searchLimitCount} of {matchedCount}{(flagPlus ? "+" : "")}";
- resultDiscs = filteredList.ToArray();
- }
- isSearching = false;
- StateHasChanged();
- }
- protected override async Task OnAfterRenderAsync(bool firstRender)
- {
- await base.OnAfterRenderAsync(firstRender);
- if (firstRender)
- {
- AllTrackSet = DataSet.AllTracksSet.GroupBy(p => p.Key).ToDictionary(p => p.Key, p => p.First().Name);
- if (searchFind == "Track" && resultTracks == null) await SearchGo();
- if (searchFind == "Disc" && resultDiscs == null) await SearchGo();
- else StateHasChanged();
- }
- }
- }
|