[frontend] Overhaul compose menu, add custom dropdown component
This commit is contained in:
parent
0163721d7f
commit
55b586d0b5
8 changed files with 185 additions and 18 deletions
|
@ -8,35 +8,81 @@
|
|||
<button @onclick="CloseDialog">
|
||||
<Icon Name="Icons.X"/>
|
||||
</button>
|
||||
<select @bind="NoteDraft.Visibility">
|
||||
@foreach (var vis in Enum.GetValues<NoteVisibility>())
|
||||
{
|
||||
<option value="@vis">@vis</option>
|
||||
}
|
||||
</select>
|
||||
<button @onclick="SendNote">Send!</button>
|
||||
<Dropdown TBind="NoteVisibility" Elements="@DropDownCreate()" @bind-Value="NoteDraft.Visibility">
|
||||
</Dropdown>
|
||||
<button @onclick="SendNote" class="post-btn">Post<Icon Name="Icons.PaperPlaneRight"/></button>
|
||||
</div>
|
||||
@if (NoteDraft.Cw != null) {
|
||||
<input @bind="NoteDraft.Cw" class="input" />
|
||||
@if (NoteDraft.Cw != null)
|
||||
{
|
||||
<input @bind="NoteDraft.Cw" class="input cw-field" placeholder="Content Warning"/>
|
||||
<hr class="separator"/>
|
||||
}
|
||||
<textarea @bind="NoteDraft.Text" class="textarea" rows="5" cols="35"></textarea>
|
||||
<textarea @bind="NoteDraft.Text" class="textarea" placeholder="What's on your mind?" rows="5" cols="35"></textarea>
|
||||
<div class="footer">
|
||||
<button @onclick="ToggleCw"><Icon Name="Icons.EyeSlash"></Icon></button>
|
||||
<InputFile OnChange="Upload">Upload!</InputFile>
|
||||
<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 NoteCreateRequest NoteDraft { get; set; } = new NoteCreateRequest
|
||||
private InputFile UploadInput { get; set; }
|
||||
|
||||
private NoteCreateRequest NoteDraft { get; set; } = new NoteCreateRequest
|
||||
{
|
||||
Text = "",
|
||||
Visibility = NoteVisibility.Public, // FIXME: Default to visibilty in settings
|
||||
Cw = null
|
||||
Cw = null
|
||||
};
|
||||
|
||||
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()
|
||||
{
|
||||
await _module.InvokeVoidAsync("openDialog", Dialog);
|
||||
|
@ -53,6 +99,7 @@
|
|||
{
|
||||
NoteDraft.MediaIds = Attachments.Select(x => x.Id).ToList();
|
||||
}
|
||||
|
||||
await ApiService.Notes.CreateNote(NoteDraft);
|
||||
await CloseDialog();
|
||||
// FIXME: Implement timeline refresh and call it here.
|
||||
|
|
|
@ -2,11 +2,49 @@
|
|||
background-color: var(--background-color);
|
||||
border-radius: 1rem;
|
||||
margin: 0 auto;
|
||||
top: 10%
|
||||
top: 10%;
|
||||
padding: 1rem;
|
||||
}
|
||||
.compose::backdrop {
|
||||
background-color: black;
|
||||
opacity: 50%;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.textarea {
|
||||
display: block;
|
||||
background-color: var(--background-color);
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
.input {
|
||||
display: block;
|
||||
background-color: var(--background-color);
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.cw-field {
|
||||
margin-bottom: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
.post-btn {
|
||||
background: var(--accent-color);
|
||||
float: right;
|
||||
}
|
||||
|
||||
.footer-btn {
|
||||
width: 2.5rem;
|
||||
height: max-content;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
.separator {
|
||||
color: var(--highlight-color);
|
||||
margin-top: 0.25rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.file-input {
|
||||
display: none;
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
export function openDialog(element){
|
||||
console.log("opening JS")
|
||||
element.showModal()
|
||||
}
|
||||
export function closeDialog(element){
|
||||
console.log("closing JS")
|
||||
element.close()
|
||||
}
|
||||
|
||||
export function openUpload(element){
|
||||
element.click();
|
||||
}
|
42
Iceshrimp.Frontend/Components/Dropdown.razor
Normal file
42
Iceshrimp.Frontend/Components/Dropdown.razor
Normal file
|
@ -0,0 +1,42 @@
|
|||
@typeparam TBind
|
||||
|
||||
<div @onclick="Toggle" class="dropdown-root">
|
||||
@CurrentIcon
|
||||
</div>
|
||||
|
||||
@if (Visible)
|
||||
{
|
||||
<div class="dropdown-menu">
|
||||
@foreach (var entry in Elements)
|
||||
{
|
||||
<DropdownElement TBind="TBind" OnSelect="UpdateSelected" Icon="entry.Icon" Content="entry.Content" Selection="entry.Selection"/>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] [EditorRequired] public required IEnumerable<DropdownElement<TBind>> Elements { get; set; }
|
||||
[Parameter] [EditorRequired] public required TBind Value { get; set; }
|
||||
[Parameter] public EventCallback<TBind> ValueChanged { get; set; }
|
||||
private DropdownElement<TBind>? CurrentSelection { get; set; }
|
||||
private RenderFragment? CurrentIcon { get; set; }
|
||||
private bool Visible { get; set; } = false;
|
||||
|
||||
private void UpdateSelected(DropdownElement<TBind> element)
|
||||
{
|
||||
CurrentSelection = element;
|
||||
CurrentIcon = CurrentSelection.Icon;
|
||||
ValueChanged.InvokeAsync(element.Selection);
|
||||
Visible = false;
|
||||
}
|
||||
|
||||
private void Toggle()
|
||||
{
|
||||
Visible = !Visible;
|
||||
}
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
UpdateSelected(Elements.FirstOrDefault() ?? throw new InvalidOperationException());
|
||||
}
|
||||
|
||||
}
|
10
Iceshrimp.Frontend/Components/Dropdown.razor.css
Normal file
10
Iceshrimp.Frontend/Components/Dropdown.razor.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
.dropdown-menu {
|
||||
position: absolute;
|
||||
top: 5rem;
|
||||
background-color: var(--background-color);
|
||||
padding: 0.5rem;
|
||||
border-color: var(--highlight-color);
|
||||
border-style: solid;
|
||||
border-width: 0.1rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
5
Iceshrimp.Frontend/Components/Dropdown.razor.js
Normal file
5
Iceshrimp.Frontend/Components/Dropdown.razor.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
export class Dropdown {
|
||||
|
||||
}
|
||||
|
||||
window.Dropdown = Dropdown;
|
19
Iceshrimp.Frontend/Components/DropdownElement.razor
Normal file
19
Iceshrimp.Frontend/Components/DropdownElement.razor
Normal file
|
@ -0,0 +1,19 @@
|
|||
@typeparam TBind
|
||||
|
||||
<div @onclick="OnClick" class="dropdown-element">
|
||||
<span class="icon">@Icon</span>
|
||||
<span class="content">@Content</span>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] [EditorRequired] public required RenderFragment Icon { get; set; }
|
||||
[Parameter] [EditorRequired] public required RenderFragment Content { get; set; }
|
||||
[Parameter] [EditorRequired] public EventCallback<DropdownElement<TBind>> OnSelect { get; set; }
|
||||
[Parameter] [EditorRequired] public required TBind Selection { get; set; }
|
||||
|
||||
private async Task OnClick()
|
||||
{
|
||||
await OnSelect.InvokeAsync(this);
|
||||
}
|
||||
|
||||
}
|
4
Iceshrimp.Frontend/Components/DropdownElement.razor.css
Normal file
4
Iceshrimp.Frontend/Components/DropdownElement.razor.css
Normal file
|
@ -0,0 +1,4 @@
|
|||
.dropdown-element {
|
||||
margin: 0.25em;
|
||||
cursor: pointer;
|
||||
}
|
Loading…
Add table
Reference in a new issue