@using System.Diagnostics.CodeAnalysis @using Iceshrimp.Assets.PhosphorIcons @* ReSharper disable once RedundantUsingDirective *@ @using Iceshrimp.Frontend.Components.Note @using Iceshrimp.Frontend.Core.Miscellaneous @using Iceshrimp.Frontend.Core.Services @using Iceshrimp.Frontend.Localization @using Iceshrimp.Shared.Schemas.Web @using Microsoft.Extensions.Localization @using Iceshrimp.Frontend.Core.Services.StateServicePatterns @inject IStringLocalizer Loc; @inject ApiService Api; @inject NavigationManager Navigation; @inject StateService StateService; @inject IJSRuntime Js; @if (_resultType == ResultType.Notes) {
@if (NoteSearchInstance?.NoteResponses != null) { foreach (var note in NoteSearchInstance?.NoteResponses!) {
}
}
} @if (_resultType == ResultType.Users) {
@if (UserSearchInstance?.UserResponses != null) { foreach (var user in UserSearchInstance?.UserResponses!) {
}
}
} @code { private string SearchString { get; set; } = ""; private SearchTypeEnum SearchType { get; set; } = SearchTypeEnum.Note; private NoteSearch? NoteSearchInstance { get; set; } private UserSearch? UserSearchInstance { get; set; } private IJSInProcessObjectReference Module { get; set; } = null!; private ElementReference Scroller { get; set; } private ResultType _resultType; private bool _setScroll; private float _scrollTop; protected override async Task OnInitializedAsync() { Module = (IJSInProcessObjectReference)await Js.InvokeAsync("import", "/Components/SearchComponent.razor.js"); var state = StateService.Search.GetState(); if (state != null) { NoteSearchInstance = new NoteSearch(state.SearchString, Api, state.SearchResults); _resultType = ResultType.Notes; _scrollTop = state.ScrollTop; _setScroll = true; } } protected override void OnAfterRender(bool firstRender) { if (_setScroll) { SetScrollY(_scrollTop); _setScroll = false; } } private async Task Search() { NoteSearchInstance = null; _resultType = ResultType.None; StateHasChanged(); try { var lookup = await Api.Search.LookupAsync(SearchString); if (lookup is not null && lookup.TargetUrl.Contains("user")) { var user = await Api.Users.GetUserAsync(lookup.TargetUrl.Split("users/")[1]); if (user is not null) { var username = $"@{user.Username}"; if (user.Host != null) username += $"@{user.Host}"; Navigation.NavigateTo($"/{username}"); } } else if (lookup is not null && lookup.TargetUrl.Contains("notes")) { Navigation.NavigateTo(lookup.TargetUrl); } } catch (ApiException) { if (SearchType == SearchTypeEnum.Note) { var searchRes = await Api.Search.SearchNotesAsync(SearchString, new PaginationQuery { Limit = 20 }); if (searchRes.Count > 0) { NoteSearchInstance = new NoteSearch(searchString: SearchString, api: Api, noteResponses: searchRes); _resultType = ResultType.Notes; StateHasChanged(); } } if (SearchType == SearchTypeEnum.User) { var searchRes = await Api.Search.SearchUsersAsync(SearchString, new PaginationQuery() { Limit = 20 }); if (searchRes.Count > 0) { UserSearchInstance = new UserSearch(searchString: SearchString, api: Api, userResponses: searchRes); _resultType = ResultType.Users; StateHasChanged(); } } } } private void OpenNote(string id) { StateService.Search.SetState(new SearchState { SearchResults = NoteSearchInstance!.NoteResponses, ScrollTop = GetScrollY(), SearchString = NoteSearchInstance!.SearchString }); Navigation.NavigateTo($"/notes/{id}"); } private void OpenProfile(UserResponse user) { var username = $"@{user.Username}"; if (user.Host != null) username += $"@{user.Host}"; Navigation.NavigateTo($"/{username}"); } private float GetScrollY() { return Module.Invoke("GetScrollY"); } private void SetScrollY(float scrollTop) { Module.InvokeVoid("SetScrollY", scrollTop); } private enum ResultType { Default, Notes, Users, None } private enum SearchTypeEnum { Note, User } [method: SetsRequiredMembers] private class UserSearch(string searchString, ApiService api, List userResponses) { internal required string MinId = userResponses.Last().Id; internal required string MaxId = userResponses.First().Id; internal required string SearchString = searchString; internal required ApiService Api = api; public required List UserResponses { get; init; } = userResponses; public bool SearchComplete = false; public async Task FetchOlder() { var pq = new PaginationQuery { Limit = 15, MaxId = MinId }; var res = await Api.Search.SearchUsersAsync(SearchString, pq); switch (res.Count) { case > 0: MinId = res.Last().Id; UserResponses.AddRange(res); break; case 0: SearchComplete = true; break; } } } [method: SetsRequiredMembers] private class NoteSearch(string searchString, ApiService api, List noteResponses) { internal required string MinId = noteResponses.Last().Id; internal required string MaxId = noteResponses.First().Id; public required string SearchString = searchString; internal required ApiService Api = api; public required List NoteResponses { get; init; } = noteResponses; public bool SearchComplete = false; public async Task FetchOlder() { var pq = new PaginationQuery { Limit = 15, MaxId = MinId }; var res = await Api.Search.SearchNotesAsync(SearchString, pq); switch (res.Count) { case > 0: MinId = res.Last().Id; NoteResponses.AddRange(res); break; case 0: SearchComplete = true; break; } } } }