200 lines
No EOL
7.5 KiB
Text
200 lines
No EOL
7.5 KiB
Text
@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<Profile> Logger;
|
|
@inject IStringLocalizer<Localization> Loc;
|
|
|
|
<SectionContent SectionName="top-bar">
|
|
<Icon Name="Icons.User"></Icon>
|
|
@Loc["Profile"]
|
|
</SectionContent>
|
|
|
|
<div class="body">
|
|
@if (State is State.Loaded)
|
|
{
|
|
<div class="section">
|
|
<h3>@Loc["Banner"]</h3>
|
|
@if (!string.IsNullOrEmpty(BannerUrl))
|
|
{
|
|
<img class="banner" src="@BannerUrl" alt="banner"/>
|
|
<div>
|
|
<input type="checkbox" id="delete-banner" @bind="@DelBanner">
|
|
<label for="delete-banner">@Loc["Remove Banner"]</label>
|
|
</div>
|
|
}
|
|
<InputFile class="input" OnChange="OnBannerFileChange" accept="image/*" disabled="@DelBanner"/>
|
|
</div>
|
|
<div class="section">
|
|
<h3>@Loc["Avatar"]</h3>
|
|
@if (!string.IsNullOrEmpty(AvatarUrl))
|
|
{
|
|
<img class="avatar" src="@AvatarUrl" alt="avatar"/>
|
|
<div>
|
|
<input type="checkbox" id="delete-avatar" @bind="@DelAvatar">
|
|
<label for="delete-avatar">@Loc["Remove Avatar"]</label>
|
|
</div>
|
|
}
|
|
<InputFile class="input" OnChange="OnAvatarFileChange" accept="image/*" disabled="@DelAvatar"/>
|
|
</div>
|
|
<div class="section">
|
|
<h3>@Loc["Display Name"]</h3><input class="input" @bind="@DisplayName"/>
|
|
</div>
|
|
<div class="section">
|
|
<h3>@Loc["Profile Description"]</h3><textarea class="input" @bind="@UserProfile.Description"></textarea>
|
|
</div>
|
|
<div class="section">
|
|
<h3>@Loc["Birthday"]</h3><input class="input" @bind="@UserProfile.Birthday"/>
|
|
</div>
|
|
<div class="section">
|
|
<h3>@Loc["Location"]</h3><input class="input" @bind="@UserProfile.Location"/>
|
|
</div>
|
|
<div class="user-fields">
|
|
<h3>@Loc["Fields"]</h3>
|
|
<div class="fields">
|
|
@foreach (var entry in UserProfile.Fields)
|
|
{
|
|
<div class="field">
|
|
<input class="input" placeholder="@Loc["Name"]" @bind="@entry.Name"/>
|
|
<input class="input" placeholder="@Loc["Value"]" @bind="@entry.Value"/>
|
|
<button class="button" title="@Loc["Delete Field"]" @onclick="() => DeleteField(entry)">
|
|
<Icon Name="Icons.Trash"/>
|
|
</button>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="new-field">
|
|
<input class="input" placeholder="@Loc["Name"]" @bind="@FieldName"/>
|
|
<input class="input" placeholder="@Loc["Value"]" @bind="@FieldValue"/>
|
|
<button class="button" title="@Loc["Add Field"]" @onclick="AddField">
|
|
<Icon Name="Icons.Plus"/>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h3>@Loc["Other"]</h3>
|
|
<div>
|
|
<input type="checkbox" id="is-bot" @bind="@UserProfile.IsBot">
|
|
<label for="is-bot">@Loc["Mark as an automated (bot) account"]</label>
|
|
</div>
|
|
<div>
|
|
<input type="checkbox" id="is-cat" @bind="@UserProfile.IsCat">
|
|
<label for="is-cat">@Loc["Mark as a cat"]</label>
|
|
</div>
|
|
<div>
|
|
<input type="checkbox" id="speak-cat" @bind="@UserProfile.SpeakAsCat" disabled="@(!UserProfile.IsCat)">
|
|
<label for="speak-cat">@Loc["Speak as a cat"]</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<StateButton OnClick="SaveChanges" ExtraClasses="button" @ref="SaveButton">
|
|
<Initial>
|
|
<Icon Name="Icons.FloppyDisk"/>@Loc["Save"]
|
|
</Initial>
|
|
<Loading>
|
|
<Icon Name="Icons.Spinner"/>
|
|
</Loading>
|
|
<Failed>
|
|
<Icon Name="Icons.X"/>@Loc["Error"]
|
|
</Failed>
|
|
<Success>
|
|
<Icon Name="Icons.Check"/>@Loc["Saved"]
|
|
</Success>
|
|
</StateButton>
|
|
</div>
|
|
}
|
|
@if (State is State.Loading)
|
|
{
|
|
<div>Loading!</div>
|
|
}
|
|
</div>
|
|
|
|
@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; } = null;
|
|
private string? AvatarUrl { get; set; } = null;
|
|
private bool DelAvatar { get; set; } = false;
|
|
private IBrowserFile? BannerFile { get; set; } = null;
|
|
private string? BannerUrl { get; set; } = null;
|
|
private bool DelBanner { get; set; } = false;
|
|
private string DisplayName { get; set; } = "";
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
try
|
|
{
|
|
UserProfile = await Api.Profile.GetProfileAsync();
|
|
State = State.Loaded;
|
|
AvatarUrl = await Api.Profile.GetAvatarUrlAsync();
|
|
BannerUrl = await Api.Profile.GetBannerUrlAsync();
|
|
DisplayName = await Api.Profile.GetDisplayNameAsync();
|
|
}
|
|
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 async Task SaveChanges()
|
|
{
|
|
try
|
|
{
|
|
SaveButton.State = StateButton.StateEnum.Loading;
|
|
await Api.Profile.UpdateProfileAsync(UserProfile);
|
|
await Api.Profile.UpdateDisplayNameAsync(DisplayName);
|
|
if (DelAvatar)
|
|
await Api.Profile.DeleteAvatarAsync();
|
|
else if (AvatarFile != null)
|
|
await Api.Profile.UpdateAvatarAsync(AvatarFile);
|
|
if (DelBanner)
|
|
await Api.Profile.DeleteBannerAsync();
|
|
else if (BannerFile != null)
|
|
await Api.Profile.UpdateBannerAsync(BannerFile);
|
|
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/"));
|
|
}
|
|
|
|
private void OnBannerFileChange(InputFileChangeEventArgs e)
|
|
{
|
|
BannerFile = e.GetMultipleFiles().First(p => p.ContentType.StartsWith("image/"));
|
|
}
|
|
} |