[frontend/components] Add poll creation to compose
This commit is contained in:
parent
65bd4a3a15
commit
718a26516a
2 changed files with 164 additions and 0 deletions
|
@ -63,6 +63,9 @@
|
||||||
<div class="file-input">
|
<div class="file-input">
|
||||||
<InputFile @ref="UploadInput" OnChange="Upload">Upload!</InputFile>
|
<InputFile @ref="UploadInput" OnChange="Upload">Upload!</InputFile>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn" title="@Loc["Poll"]" @onclick="TogglePoll" aria-label="poll">
|
||||||
|
<Icon Name="Icons.MicrophoneStage" Size="1.3rem"></Icon>
|
||||||
|
</button>
|
||||||
<button class="btn" title="@Loc["Content warning"]" @onclick="ToggleCw" aria-label="content warning">
|
<button class="btn" title="@Loc["Content warning"]" @onclick="ToggleCw" aria-label="content warning">
|
||||||
<Icon Name="Icons.EyeSlash" Size="1.3rem"></Icon>
|
<Icon Name="Icons.EyeSlash" Size="1.3rem"></Icon>
|
||||||
</button>
|
</button>
|
||||||
|
@ -113,6 +116,61 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@if (NoteDraft.Poll != null)
|
||||||
|
{
|
||||||
|
<div class="poll">
|
||||||
|
<div class="choices">
|
||||||
|
@foreach (var entry in PollChoices)
|
||||||
|
{
|
||||||
|
<div class="choice">
|
||||||
|
<input class="input" placeholder="@Loc["Choice"]" @bind="@entry.Value"/>
|
||||||
|
<button class="button" title="@Loc["Delete Choice"]" @onclick="() => DeletePollChoice(entry)">
|
||||||
|
<Icon Name="Icons.Trash"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (PollChoices.Count < 10)
|
||||||
|
{
|
||||||
|
<div class="choice">
|
||||||
|
<input class="input" placeholder="@Loc["Choice"]" @bind="@PollEntry"/>
|
||||||
|
<button class="button" title="@Loc["Add Choice"]" @onclick="AddPollChoice">
|
||||||
|
<Icon Name="Icons.Plus"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<input type="checkbox" id="poll-multiple" @bind="NoteDraft.Poll.Multiple"/>
|
||||||
|
<label for="poll-multiple">@Loc["Multiple choice"]</label>
|
||||||
|
<div class="expire">
|
||||||
|
<div>
|
||||||
|
<label for="poll-expires">@Loc["End poll"]</label>
|
||||||
|
<select @bind="PollExpires" id="poll-expires">
|
||||||
|
<option value="@PollExpire.Never">@Loc["Never"]</option>
|
||||||
|
<option value="@PollExpire.ExpiresAt">@Loc["End at"]</option>
|
||||||
|
<option value="@PollExpire.ExpiresAfter">@Loc["End after"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
@switch (PollExpires)
|
||||||
|
{
|
||||||
|
case PollExpire.Never:
|
||||||
|
break;
|
||||||
|
case PollExpire.ExpiresAt:
|
||||||
|
<input type="datetime-local" class="input" @bind="PollExpireTime"/>
|
||||||
|
break;
|
||||||
|
case PollExpire.ExpiresAfter:
|
||||||
|
<input type="number" class="input" placeholder="@Loc["Duration"]" min="@(PollExpiresAft == PollExpireAfter.Minutes ? 5 : 1)" @bind="PollExpireLen"/>
|
||||||
|
<select @bind="PollExpiresAft">
|
||||||
|
<option value="@PollExpireAfter.Minutes">@Loc["Minutes"]</option>
|
||||||
|
<option value="@PollExpireAfter.Hours">@Loc["Hours"]</option>
|
||||||
|
<option value="@PollExpireAfter.Days">@Loc["Days"]</option>
|
||||||
|
</select>
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@if (Preview)
|
@if (Preview)
|
||||||
{
|
{
|
||||||
<div class="preview">
|
<div class="preview">
|
||||||
|
@ -147,6 +205,12 @@
|
||||||
private bool SendLock { get; set; } = false;
|
private bool SendLock { get; set; } = false;
|
||||||
private int UploadingFiles { get; set; }
|
private int UploadingFiles { get; set; }
|
||||||
private string? AttachedQuote { get; set; }
|
private string? AttachedQuote { get; set; }
|
||||||
|
private List<Choice> PollChoices { get; set; } = [];
|
||||||
|
private string PollEntry { get; set; } = "";
|
||||||
|
private PollExpire PollExpires { get; set; }
|
||||||
|
private DateTime PollExpireTime { get; set; }
|
||||||
|
private int PollExpireLen { get; set; }
|
||||||
|
private PollExpireAfter PollExpiresAft { get; set; }
|
||||||
|
|
||||||
private NoteCreateRequest NoteDraft { get; set; } = new()
|
private NoteCreateRequest NoteDraft { get; set; } = new()
|
||||||
{
|
{
|
||||||
|
@ -157,6 +221,25 @@
|
||||||
|
|
||||||
private Dictionary<string, string> AvailablePlaceholders { get; set; } = new() { { "default", "What's on your mind?" }, { "reply", "Reply goes here!" }, { "quote", "Quote this post!" } };
|
private Dictionary<string, string> AvailablePlaceholders { get; set; } = new() { { "default", "What's on your mind?" }, { "reply", "Reply goes here!" }, { "quote", "Quote this post!" } };
|
||||||
|
|
||||||
|
private class Choice
|
||||||
|
{
|
||||||
|
public required string Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum PollExpire
|
||||||
|
{
|
||||||
|
Never,
|
||||||
|
ExpiresAt,
|
||||||
|
ExpiresAfter
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum PollExpireAfter
|
||||||
|
{
|
||||||
|
Minutes,
|
||||||
|
Hours,
|
||||||
|
Days,
|
||||||
|
}
|
||||||
|
|
||||||
private bool SendingDisabled() =>
|
private bool SendingDisabled() =>
|
||||||
NoteLength - ((NoteDraft.Cw?.Length ?? 0) + NoteDraft.Text.Length) < 0 || UploadingFiles != 0;
|
NoteLength - ((NoteDraft.Cw?.Length ?? 0) + NoteDraft.Text.Length) < 0 || UploadingFiles != 0;
|
||||||
|
|
||||||
|
@ -317,6 +400,24 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
NoteDraft.RenoteId ??= AttachedQuote;
|
NoteDraft.RenoteId ??= AttachedQuote;
|
||||||
|
|
||||||
|
if (NoteDraft.Poll != null)
|
||||||
|
{
|
||||||
|
NoteDraft.Poll.Choices = PollChoices.Select(p => p.Value).ToList();
|
||||||
|
NoteDraft.Poll.ExpiresAt = PollExpires switch
|
||||||
|
{
|
||||||
|
PollExpire.ExpiresAt => PollExpireTime.ToUniversalTime(),
|
||||||
|
PollExpire.ExpiresAfter => PollExpiresAft switch
|
||||||
|
{
|
||||||
|
PollExpireAfter.Minutes => DateTime.UtcNow.AddMinutes(Math.Min(PollExpireLen, 5)),
|
||||||
|
PollExpireAfter.Hours => DateTime.UtcNow.AddHours(Math.Min(PollExpireLen, 1)),
|
||||||
|
PollExpireAfter.Days => DateTime.UtcNow.AddDays(Math.Min(PollExpireLen, 1)),
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
},
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ApiService.Notes.CreateNoteAsync(NoteDraft);
|
await ApiService.Notes.CreateNoteAsync(NoteDraft);
|
||||||
|
@ -340,6 +441,29 @@
|
||||||
// FIXME: Implement timeline refresh and call it here.
|
// FIXME: Implement timeline refresh and call it here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TogglePoll()
|
||||||
|
{
|
||||||
|
if (NoteDraft.Poll != null)
|
||||||
|
{
|
||||||
|
NoteDraft.Poll = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NoteDraft.Poll = new PollRequest
|
||||||
|
{
|
||||||
|
ExpiresAt = null,
|
||||||
|
Multiple = false,
|
||||||
|
Choices = []
|
||||||
|
};
|
||||||
|
PollChoices = [];
|
||||||
|
PollEntry = "";
|
||||||
|
PollExpires = PollExpire.Never;
|
||||||
|
PollExpireTime = DateTime.Now;
|
||||||
|
PollExpireLen = 7;
|
||||||
|
PollExpiresAft = PollExpireAfter.Days;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ToggleCw()
|
private void ToggleCw()
|
||||||
{
|
{
|
||||||
NoteDraft.Cw = NoteDraft.Cw == null ? "" : null;
|
NoteDraft.Cw = NoteDraft.Cw == null ? "" : null;
|
||||||
|
@ -361,6 +485,17 @@
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddPollChoice()
|
||||||
|
{
|
||||||
|
PollChoices.Add(new Choice { Value = PollEntry });
|
||||||
|
PollEntry = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeletePollChoice(Choice choice)
|
||||||
|
{
|
||||||
|
PollChoices.Remove(choice);
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
|
|
|
@ -19,6 +19,35 @@
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.poll .choice {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll .expire {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5em;
|
||||||
|
align-items: end;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
|
||||||
|
select {
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.compose .attachments {
|
.compose .attachments {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
Loading…
Add table
Reference in a new issue