184 lines
No EOL
6.3 KiB
Text
184 lines
No EOL
6.3 KiB
Text
@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
|
|
<dialog class="compose" @ref="Dialog">
|
|
<div class="header">
|
|
<button @onclick="CloseDialog">
|
|
<Icon Name="Icons.X"/>
|
|
</button>
|
|
<Dropdown TBind="NoteVisibility" Elements="@DropDownCreate()" @bind-Value="NoteDraft.Visibility"/>
|
|
<button @onclick="SendNote" class="post-btn">Post<Icon Name="Icons.PaperPlaneRight"/></button>
|
|
</div>
|
|
@if (ReplyOrQuote != null)
|
|
{
|
|
<div class="reply-or-quote">
|
|
<NoteComponent Note="ReplyOrQuote" AsQuote="true"/>
|
|
</div>
|
|
}
|
|
@if (NoteDraft.Cw != null)
|
|
{
|
|
<input @bind="NoteDraft.Cw" class="input cw-field" placeholder="Content Warning"/>
|
|
<hr class="separator"/>
|
|
}
|
|
<textarea @bind="NoteDraft.Text" class="textarea" placeholder="@TextPlaceholder" rows="5" cols="35"></textarea>
|
|
<div class="footer">
|
|
<button class="footer-btn" @onclick="OpenUpload">
|
|
<Icon Name="Icons.Upload" Size="1.3rem"></Icon>
|
|
</button>
|
|
<button class="footer-btn" @onclick="ToggleCw">
|
|
<Icon Name="Icons.EyeSlash" Size="1.3rem"></Icon>
|
|
</button>
|
|
<div class="file-input">
|
|
<InputFile @ref="UploadInput" OnChange="Upload">Upload!</InputFile>
|
|
</div>
|
|
</div>
|
|
</dialog>
|
|
|
|
@code {
|
|
private ElementReference Dialog { get; set; }
|
|
private IJSObjectReference? _module;
|
|
private IList<DriveFileResponse> 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<string, string> 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 => (@<Icon Name="Icons.Globe"/>),
|
|
NoteVisibility.Home => (@<Icon Name="Icons.House"/>),
|
|
NoteVisibility.Followers => (@<Icon Name="Icons.Lock"/>),
|
|
NoteVisibility.Specified => (@<Icon Name="Icons.Envelope"/>),
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
};
|
|
}
|
|
|
|
RenderFragment DropdownContent(NoteVisibility vis)
|
|
{
|
|
return vis switch
|
|
{
|
|
NoteVisibility.Public => (@<span class="dropdown-title">Public</span>),
|
|
NoteVisibility.Home => (@<span class="dropdown-title">Unlisted</span>),
|
|
NoteVisibility.Followers => (@<span class="dropdown-title">Followers</span>),
|
|
NoteVisibility.Specified => (@<span class="dropdown-title">Direct</span>),
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
};
|
|
}
|
|
|
|
private IList<DropdownElement<NoteVisibility>> DropDownCreate()
|
|
{
|
|
return Enum.GetValues<NoteVisibility>()
|
|
.Select(vis =>
|
|
new DropdownElement<NoteVisibility> { Icon = DropdownIcon(vis), Content = DropdownContent(vis), Selection = vis })
|
|
.ToList();
|
|
}
|
|
|
|
// The <InputFile> 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<DriveFileResponse>();
|
|
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<IJSObjectReference>("import",
|
|
"./Components/Compose.razor.js");
|
|
ComposeService.ComposeDialog = this;
|
|
}
|
|
}
|
|
|
|
protected override void OnInitialized()
|
|
{
|
|
TextPlaceholder = AvailablePlaceholders["default"];
|
|
}
|
|
|
|
} |