@using FParsec
@using Iceshrimp.Assets.PhosphorIcons
@using Iceshrimp.Frontend.Core.Services
@using Iceshrimp.Shared.Schemas
@using Iceshrimp.Frontend.Components.Note
@inject IJSRuntime Js
@inject ApiService ApiService
@inject ComposeService ComposeService
@code {
private ElementReference Dialog { get; set; }
private IJSObjectReference? _module;
private IList Attachments { get; set; } = [];
private InputFile UploadInput { get; set; }
private NoteBase? ReplyOrQuote { get; set; }
private string? TextPlaceholder { get; set; }
private NoteCreateRequest NoteDraft { get; set; } = new NoteCreateRequest
{
Text = "",
Visibility = NoteVisibility.Followers, // FIXME: Default to visibilty in settings
Cw = null
};
private Dictionary AvailablePlaceholders { get; set; } = new()
{
{ "default", "What's on your mind?" },
{ "reply", "Reply goes here!" },
{ "quote", "Quote this post!" }
};
RenderFragment DropdownIcon(NoteVisibility vis)
{
return vis switch
{
NoteVisibility.Public => (@),
NoteVisibility.Home => (@),
NoteVisibility.Followers => (@),
NoteVisibility.Specified => (@),
_ => throw new ArgumentOutOfRangeException()
};
}
RenderFragment DropdownContent(NoteVisibility vis)
{
return vis switch
{
NoteVisibility.Public => (@Public),
NoteVisibility.Home => (@Unlisted),
NoteVisibility.Followers => (@Followers),
NoteVisibility.Specified => (@Direct),
_ => throw new ArgumentOutOfRangeException()
};
}
private IList> DropDownCreate()
{
return Enum.GetValues()
.Select(vis =>
new DropdownElement { Icon = DropdownIcon(vis), Content = DropdownContent(vis), Selection = vis })
.ToList();
}
// The Component is hidden, and triggered by a sepperate button.
// That way we get it's functionality, without the styling limitations of the InputFile component
private async Task OpenUpload()
{
await _module.InvokeVoidAsync("openUpload", UploadInput.Element);
}
public async Task OpenDialog(NoteBase? replyTo = null, NoteBase? quote = null)
{
if (replyTo != null)
{
ResetState();
ReplyOrQuote = replyTo;
NoteDraft.ReplyId = replyTo.Id;
NoteDraft.Visibility = replyTo.Visibility;
TextPlaceholder = AvailablePlaceholders["reply"];
StateHasChanged();
}
else if (quote != null)
{
ResetState();
ReplyOrQuote = quote;
NoteDraft.RenoteId = quote.Id;
NoteDraft.Visibility = quote.Visibility;
TextPlaceholder = AvailablePlaceholders["quote"];
StateHasChanged();
}
else
{
ResetState();
StateHasChanged();
}
await _module.InvokeVoidAsync("openDialog", Dialog);
}
private void ResetState()
{
ReplyOrQuote = null;
Attachments = new List();
NoteDraft = new NoteCreateRequest { Text = "", Visibility = NoteVisibility.Followers, Cw = null };
TextPlaceholder = AvailablePlaceholders["default"];
}
private async Task CloseDialog()
{
await _module.InvokeVoidAsync("closeDialog", Dialog);
}
private async Task SendNote()
{
if (Attachments.Count > 0)
{
NoteDraft.MediaIds = Attachments.Select(x => x.Id).ToList();
}
await ApiService.Notes.CreateNote(NoteDraft);
await CloseDialog();
// FIXME: Implement timeline refresh and call it here.
}
private void ToggleCw()
{
NoteDraft.Cw = NoteDraft.Cw == null ? "" : null;
}
private async Task Upload(InputFileChangeEventArgs e)
{
Console.WriteLine(e.File.Size);
var res = await ApiService.Drive.UploadFile(e.File);
Console.WriteLine(res.Id);
Attachments.Add(res);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_module = await Js.InvokeAsync("import",
"./Components/Compose.razor.js");
ComposeService.ComposeDialog = this;
}
}
protected override void OnInitialized()
{
TextPlaceholder = AvailablePlaceholders["default"];
}
}