@page "/{User}" @using System.Text.RegularExpressions @using Iceshrimp.Frontend.Components @using Iceshrimp.Frontend.Components.Note @using Iceshrimp.Frontend.Core.Miscellaneous @using Iceshrimp.Frontend.Core.Services @using Iceshrimp.Shared.Schemas.Web @using Microsoft.AspNetCore.Authorization @using Iceshrimp.Assets.PhosphorIcons @using Iceshrimp.Frontend.Localization @using Microsoft.Extensions.Localization @attribute [Authorize] @inject ApiService Api @inject GlobalComponentSvc GlobalComponentSvc; @inject IJSRuntime Js; @inject IStringLocalizer Loc; @inject MetadataService MetadataService @inject NavigationManager Nav; @inject SessionService Session @if (_init) {
@if (UserResponse.BannerUrl != null) { }
@@@UserResponse.Username @if (UserResponse.Host != null) { var host = $"@{UserResponse.Host}"; @host } @if (Profile != null && Profile.Relations.HasFlag(Relations.FollowedBy)) { Follows you }
@if (UserNotes.Count > 0) {
@foreach (var note in UserNotes) {
}
}
} @if (_loading) {
} @if (_notFound) {
User does not exist!
} @if (_error) {
Failure
} @code { [Parameter] public string? User { get; set; } [Parameter] public string? Host { get; set; } private UserResponse UserResponse { get; set; } = null!; private UserProfileResponse? Profile { get; set; } private string? MinId { get; set; } private List UserNotes { get; set; } = []; private ElementReference MenuButton { get; set; } private Menu ContextMenu { get; set; } = null!; private bool _loading = true; private bool _init; private bool _notFound; private bool _error; private bool _fetchLock; private async Task GetNotes(string? minId) { var pq = new PaginationQuery { Limit = 10, MaxId = minId }; var notes = await Api.Users.GetUserNotesAsync(UserResponse.Id, pq); if (notes is not null && notes.Count > 0) { MinId = notes.Last().Id; UserNotes.AddRange(notes); StateHasChanged(); } } private async Task AddNotes() { if (_fetchLock == false) { _fetchLock = true; await GetNotes(MinId); _fetchLock = false; } } private async Task LoadProfile() { try { if (User is null) { _notFound = true; } else { var pattern = "^@([^@]+)@?(.+)?$"; var matches = Regex.Match(User, pattern); var userResponse = await Api.Users.LookupUserAsync(matches.Groups[1].Value, matches.Groups[2].Value); if (userResponse is null) { _notFound = true; } else { UserResponse = userResponse; Profile = await Api.Users.GetUserProfileAsync(UserResponse.Id); await GetNotes(null); _init = true; _loading = false; } } } catch (ApiException) { _loading = false; _error = true; } } private void OpenNote(string id) { Nav.NavigateTo($"/notes/{id}"); } protected override async Task OnInitializedAsync() { await LoadProfile(); } protected override async Task OnParametersSetAsync() { _init = false; _loading = true; UserNotes = []; MinId = null; Profile = null; StateHasChanged(); await LoadProfile(); } private void ToggleMenu() => ContextMenu.Toggle(MenuButton); private void EditProfile() => Nav.NavigateTo("/settings/profile"); private async Task Bite() { await Api.Users.BiteUserAsync(UserResponse.Id); await GlobalComponentSvc.NoticeDialog?.Display(Loc["Bit {0}", UserResponse.DisplayName ?? UserResponse.Username])!; } private async Task RemoveFromFollowersAction(bool confirm) { if (!confirm) return; var removed = await Api.Users.RemoveUserFromFollowersAsync(UserResponse.Id); if (!removed) return; await GlobalComponentSvc.NoticeDialog?.Display(Loc["Removed {0} from followers", UserResponse.DisplayName ?? UserResponse.Username])!; Profile!.Relations &= ~Relations.FollowedBy; StateHasChanged(); } private void RemoveFromFollowers() => GlobalComponentSvc.ConfirmDialog?.Confirm(new EventCallback(this, RemoveFromFollowersAction), Loc["Remove {0} from followers?", UserResponse.DisplayName ?? UserResponse.Username], buttonText: Loc["Remove follower"]); private void OpenOriginal() { if (Profile?.Url != null) Js.InvokeVoidAsync("open", Profile.Url, "_blank"); } private async Task CopyLink() { var instance = await MetadataService.Instance.Value; await Js.InvokeVoidAsync("navigator.clipboard.writeText", $"https://{instance.WebDomain}/@{UserResponse.Username}" + (UserResponse.Host != null ? $"@{UserResponse.Host}" : "")); } private void CopyLinkRemote() { if (Profile?.Url != null) Js.InvokeVoidAsync("navigator.clipboard.writeText", Profile.Url); } private void CopyUsername() => Js.InvokeVoidAsync("navigator.clipboard.writeText", $"@{UserResponse.Username}" + (UserResponse.Host != null ? $"@{UserResponse.Host}" : "")); private async Task RefetchUser() => await GlobalComponentSvc.ConfirmDialog?.Confirm(new EventCallback(this, RefetchUserCallback), Loc["Refetch {0}'s profile?", UserResponse.DisplayName ?? UserResponse.Username])!; private async Task RefetchUserCallback(bool refetch) { if (!refetch) return; try { var res = await Api.Users.RefetchUserAsync(UserResponse.Id); if (res != null) { UserResponse = res; var newProfile = await Api.Users.GetUserProfileAsync(UserResponse.Id); if (newProfile != null) Profile = newProfile; StateHasChanged(); await GlobalComponentSvc.NoticeDialog?.Display(Loc["Successfully refetched {0}'s profile", UserResponse.DisplayName ?? UserResponse.Username])!; } } catch (ApiException e) { await GlobalComponentSvc.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!; } } }