@page "/settings/profile" @using Iceshrimp.Assets.PhosphorIcons @using Iceshrimp.Frontend.Components @using Iceshrimp.Frontend.Core.Miscellaneous @using Iceshrimp.Frontend.Core.Services @using Iceshrimp.Frontend.Localization @using Iceshrimp.Shared.Schemas.Web @using Microsoft.AspNetCore.Authorization @using Microsoft.Extensions.Localization @using Microsoft.AspNetCore.Components.Sections @attribute [Authorize] @layout SettingsLayout @inject ApiService Api; @inject ILogger Logger; @inject IStringLocalizer Loc; @inject IJSRuntime Js @inject GlobalComponentSvc GlobalComponentSvc @Loc["Profile"]
@if (State is State.Loaded) {

@Loc["Banner"]

@if (Banner != null) {
} @if (Banner != null || BannerFile != null) { }

@Loc["Avatar"]

@if (Avatar != null) { @Avatar.Description
} @if (Avatar != null || AvatarFile != null) { }

@Loc["Display Name"]

@Loc["Bio"]

@Loc["Birthday"]

@Loc["Location"]

@Loc["Pronouns"]

@foreach (var entry in Pronouns) {
}
@foreach (var language in _languages.Where(l => !Pronouns.Select(p => p.Language).Contains(l.Key))) { }

@Loc["Additional Fields"]

@foreach (var entry in UserProfile.Fields) {
}

@Loc["Other"]

@Loc["Save"] @Loc["Error"] @Loc["Saved"]
} @if (State is State.Loading) {
Loading!
}
@code { private UserProfileEntity UserProfile { get; set; } = null!; private State State { get; set; } = State.Loading; private string FieldName { get; set; } = ""; private string FieldValue { get; set; } = ""; private StateButton SaveButton { get; set; } = null!; private IBrowserFile? AvatarFile { get; set; } private bool DelAvatar { get; set; } private IBrowserFile? BannerFile { get; set; } private bool DelBanner { get; set; } private DateTime Birthday { get; set; } = DateTime.Now; private bool SetBirthday { get; set; } private ElementReference Description { get; set; } private ElementReference EmojiButton { get; set; } private DriveFileResponse? Avatar { get; set; } private DriveFileResponse? Banner { get; set; } private List Pronouns { get; set; } = []; private string PronounsLanguage { get; set; } = ""; private string PronounsValue { get; set; } = ""; private Dictionary _languages = LanguageHelper.Bcp47Languages; private IJSObjectReference _module = null!; private class UserPronouns { public required string Language { get; set; } public required string Value { get; set; } } protected override async Task OnInitializedAsync() { _module = await Js.InvokeAsync("import", "./Pages/Settings/Profile.razor.js"); try { UserProfile = await Api.Profile.GetProfileAsync(); if (UserProfile.Birthday != null) { Birthday = DateTime.Parse(UserProfile.Birthday); SetBirthday = true; } State = State.Loaded; Pronouns = UserProfile.Pronouns.Select(p => new UserPronouns { Language = p.Key, Value = p.Value }).ToList(); Avatar = await Api.Profile.GetAvatarAsync(); Banner = await Api.Profile.GetBannerAsync(); UserProfile.AvatarAlt = Avatar?.Description; UserProfile.BannerAlt = Banner?.Description; } catch (ApiException e) { Logger.LogError($"Profile load failed: {e.Message}"); State = State.Error; } } private void AddField() { UserProfile.Fields.Add(new UserProfileEntity.Field { Name = FieldName, Value = FieldValue }); FieldName = ""; FieldValue = ""; } private void DeleteField(UserProfileEntity.Field field) { UserProfile.Fields.Remove(field); } private void AddPronouns() { Pronouns.Add(new UserPronouns { Language = PronounsLanguage, Value = PronounsValue }); PronounsLanguage = ""; PronounsValue = ""; Pronouns = Pronouns.OrderBy(p => p.Language).ToList(); } private async Task SaveChanges() { try { SaveButton.State = StateButton.StateEnum.Loading; if (!SetBirthday) UserProfile.Birthday = null; else UserProfile.Birthday = Birthday.ToString("yyyy-MM-dd"); UserProfile.Pronouns = Pronouns.Where(p => !string.IsNullOrWhiteSpace(p.Value)).ToDictionary(p => p.Language, p => p.Value.Trim()); if (DelAvatar) { await Api.Profile.DeleteAvatarAsync(); UserProfile.AvatarAlt = null; } else if (AvatarFile != null) { await Api.Profile.UpdateAvatarAsync(AvatarFile, UserProfile.AvatarAlt); UserProfile.AvatarAlt = null; } if (DelBanner) { await Api.Profile.DeleteBannerAsync(); UserProfile.BannerAlt = null; } else if (BannerFile != null) { await Api.Profile.UpdateBannerAsync(BannerFile, UserProfile.BannerAlt); UserProfile.BannerAlt = null; } await Api.Profile.UpdateProfileAsync(UserProfile); SaveButton.State = StateButton.StateEnum.Success; } catch (ApiException e) { Logger.LogError($"Failed to update profile: {e.Message}"); SaveButton.State = StateButton.StateEnum.Failed; } } private void OnAvatarFileChange(InputFileChangeEventArgs e) { AvatarFile = e.GetMultipleFiles().First(p => p.ContentType.StartsWith("image/")); UserProfile.AvatarAlt = ""; } private void OnBannerFileChange(InputFileChangeEventArgs e) { BannerFile = e.GetMultipleFiles().First(p => p.ContentType.StartsWith("image/")); UserProfile.BannerAlt = ""; } private void ToggleEmojiPicker() { GlobalComponentSvc.EmojiPicker?.Open(EmojiButton, new EventCallback(this, AddEmoji)); } private async Task AddEmoji(EmojiResponse emoji) { var pos = await _module.InvokeAsync("getSelectionStart", Description); var text = UserProfile.Description ?? ""; var emojiString = $":{emoji.Name}: "; UserProfile.Description = text.Insert(pos, emojiString); StateHasChanged(); } }