@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; @if (_init) {
@if (UserResponse.Host != null) { } @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; } } 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 void Bite() => Api.Users.BiteUserAsync(UserResponse.Id); 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 Mute() => GlobalComponentSvc.ConfirmDialog?.Confirm(new EventCallback(this, MuteCallback), Loc["Mute {0}?", UserResponse.DisplayName ?? UserResponse.Username], buttonText: Loc["Mute"]); private async Task MuteCallback(bool confirm) { if (!confirm) return; try { await Api.Users.MuteUserAsync(UserResponse.Id, null); await GlobalComponentSvc.NoticeDialog?.Display(Loc["Muted {0}", UserResponse.DisplayName ?? UserResponse.Username])!; Profile!.Relations += (int)Relations.Muting; StateHasChanged(); } catch (ApiException e) { await GlobalComponentSvc.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!; } } private void TemporaryMute() => GlobalComponentSvc.SelectDialog?.Select(new EventCallback(this, TemporaryMuteCallback), Loc["Mute {0}?", UserResponse.DisplayName ?? UserResponse.Username], [(Loc["For 1 hour"], (object)DateTime.Now.AddHours(1)), (Loc["For {0} hours", 3], (object)DateTime.Now.AddHours(3)), (Loc["For {0} hours", 8], (object)DateTime.Now.AddHours(8)), (Loc["For 1 day"], (object)DateTime.Now.AddDays(1)), (Loc["For 1 week"], (object)DateTime.Now.AddDays(7))], Loc["Mute"]); private async Task TemporaryMuteCallback(object? value) { if (value is not DateTime expires) return; try { await Api.Users.MuteUserAsync(UserResponse.Id, expires); await GlobalComponentSvc.NoticeDialog?.Display(Loc["Muted {0}", UserResponse.DisplayName ?? UserResponse.Username])!; Profile!.Relations += (int)Relations.Muting; StateHasChanged(); } catch (ApiException e) { await GlobalComponentSvc.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!; } } private void Unmute() => GlobalComponentSvc.ConfirmDialog?.Confirm(new EventCallback(this, UnmuteCallback), Loc["Unmute {0}?", UserResponse.DisplayName ?? UserResponse.Username], buttonText: Loc["Unmute"]); private async Task UnmuteCallback(bool confirm) { if (!confirm) return; try { await Api.Users.UnmuteUserAsync(UserResponse.Id); await GlobalComponentSvc.NoticeDialog?.Display(Loc["Unmuted {0}", UserResponse.DisplayName ?? UserResponse.Username])!; Profile!.Relations -= (int)Relations.Muting; StateHasChanged(); } catch (ApiException e) { await GlobalComponentSvc.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!; } } private void Block() => GlobalComponentSvc.ConfirmDialog?.Confirm(new EventCallback(this, BlockCallback), Loc["Block {0}?", UserResponse.DisplayName ?? UserResponse.Username], buttonText: Loc["Block"]); private async Task BlockCallback(bool confirm) { if (!confirm) return; try { await Api.Users.BlockUserAsync(UserResponse.Id); await GlobalComponentSvc.NoticeDialog?.Display(Loc["Blocked {0}", UserResponse.DisplayName ?? UserResponse.Username])!; Profile!.Relations += (int)Relations.Blocking; StateHasChanged(); } catch (ApiException e) { await GlobalComponentSvc.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!; } } private void Unblock() => GlobalComponentSvc.ConfirmDialog?.Confirm(new EventCallback(this, UnblockCallback), Loc["Unblock {0}?", UserResponse.DisplayName ?? UserResponse.Username], buttonText: Loc["Unblock"]); private async Task UnblockCallback(bool confirm) { if (!confirm) return; try { await Api.Users.UnblockUserAsync(UserResponse.Id); await GlobalComponentSvc.NoticeDialog?.Display(Loc["Unblocked {0}", UserResponse.DisplayName ?? UserResponse.Username])!; Profile!.Relations -= (int)Relations.Blocking; StateHasChanged(); } catch (ApiException e) { await GlobalComponentSvc.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!; } } 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)!; } } }