[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,21 +8,26 @@
|
||||||
<button @onclick="CloseDialog">
|
<button @onclick="CloseDialog">
|
||||||
<Icon Name="Icons.X"/>
|
<Icon Name="Icons.X"/>
|
||||||
</button>
|
</button>
|
||||||
<select @bind="NoteDraft.Visibility">
|
<Dropdown TBind="NoteVisibility" Elements="@DropDownCreate()" @bind-Value="NoteDraft.Visibility">
|
||||||
@foreach (var vis in Enum.GetValues<NoteVisibility>())
|
</Dropdown>
|
||||||
{
|
<button @onclick="SendNote" class="post-btn">Post<Icon Name="Icons.PaperPlaneRight"/></button>
|
||||||
<option value="@vis">@vis</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
<button @onclick="SendNote">Send!</button>
|
|
||||||
</div>
|
</div>
|
||||||
@if (NoteDraft.Cw != null) {
|
@if (NoteDraft.Cw != null)
|
||||||
<input @bind="NoteDraft.Cw" class="input" />
|
{
|
||||||
|
<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">
|
<div class="footer">
|
||||||
<button @onclick="ToggleCw"><Icon Name="Icons.EyeSlash"></Icon></button>
|
<button class="footer-btn" @onclick="OpenUpload">
|
||||||
<InputFile OnChange="Upload">Upload!</InputFile>
|
<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>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
|
@ -30,6 +35,8 @@
|
||||||
private ElementReference Dialog { get; set; }
|
private ElementReference Dialog { get; set; }
|
||||||
private IJSObjectReference? _module;
|
private IJSObjectReference? _module;
|
||||||
private IList<DriveFileResponse> Attachments { get; set; } = [];
|
private IList<DriveFileResponse> Attachments { get; set; } = [];
|
||||||
|
private InputFile UploadInput { get; set; }
|
||||||
|
|
||||||
private NoteCreateRequest NoteDraft { get; set; } = new NoteCreateRequest
|
private NoteCreateRequest NoteDraft { get; set; } = new NoteCreateRequest
|
||||||
{
|
{
|
||||||
Text = "",
|
Text = "",
|
||||||
|
@ -37,6 +44,45 @@
|
||||||
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()
|
public async Task OpenDialog()
|
||||||
{
|
{
|
||||||
await _module.InvokeVoidAsync("openDialog", Dialog);
|
await _module.InvokeVoidAsync("openDialog", Dialog);
|
||||||
|
@ -53,6 +99,7 @@
|
||||||
{
|
{
|
||||||
NoteDraft.MediaIds = Attachments.Select(x => x.Id).ToList();
|
NoteDraft.MediaIds = Attachments.Select(x => x.Id).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
await ApiService.Notes.CreateNote(NoteDraft);
|
await ApiService.Notes.CreateNote(NoteDraft);
|
||||||
await CloseDialog();
|
await CloseDialog();
|
||||||
// FIXME: Implement timeline refresh and call it here.
|
// FIXME: Implement timeline refresh and call it here.
|
||||||
|
|
|
@ -2,11 +2,49 @@
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
top: 10%
|
top: 10%;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.compose::backdrop {
|
||||||
|
background-color: black;
|
||||||
|
opacity: 50%;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
.textarea {
|
.textarea {
|
||||||
display: block;
|
display: block;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
.input {
|
.input {
|
||||||
display: block;
|
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){
|
export function openDialog(element){
|
||||||
console.log("opening JS")
|
|
||||||
element.showModal()
|
element.showModal()
|
||||||
}
|
}
|
||||||
export function closeDialog(element){
|
export function closeDialog(element){
|
||||||
console.log("closing JS")
|
|
||||||
element.close()
|
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