Support deletion of pics/statuses
This commit is contained in:
parent
518f181c4f
commit
295ea4834e
7 changed files with 142 additions and 13 deletions
|
@ -13,7 +13,18 @@
|
||||||
<label>Description</label>
|
<label>Description</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<nav class="right-align no-space">
|
<nav class="no-space">
|
||||||
|
@if (confirmDelete) {
|
||||||
|
<button @onclick="ConfirmDeletePic" disabled="@loading" class="red-7-bg white-fg">
|
||||||
|
<i class="fa-solid fa-exclamation-triangle"></i> <span>Are you sure?</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
<button @onclick="DeletePic" disabled="@loading" class="red-7-bg white-fg">
|
||||||
|
<i class="fa-solid fa-trash"></i> <span>Delete</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
<div class="max"></div>
|
||||||
<button class="transparent link" data-ui="#@id" disabled="@loading">Cancel</button>
|
<button class="transparent link" data-ui="#@id" disabled="@loading">Cancel</button>
|
||||||
<button @onclick="PostPic" disabled="@loading">
|
<button @onclick="PostPic" disabled="@loading">
|
||||||
@if (loading) {
|
@if (loading) {
|
||||||
|
@ -42,11 +53,38 @@
|
||||||
private bool loading = false;
|
private bool loading = false;
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string id { get; set; }
|
public string id { get; set; }
|
||||||
|
private bool confirmDelete { get; set; }
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync() {
|
protected override async Task OnInitializedAsync() {
|
||||||
Description = Pic?.Description;
|
Description = Pic?.Description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task DeletePic() {
|
||||||
|
if (!confirmDelete) confirmDelete = true;
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ConfirmDeletePic() {
|
||||||
|
if (confirmDelete) {
|
||||||
|
loading = true;
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Pic?.Id)) {
|
||||||
|
await api.DeletePic(State.SelectedAddressName, Pic.Id);
|
||||||
|
await State.RefreshPics();
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
await JS.InvokeVoidAsync("ui", "#" + id);
|
||||||
|
// clear input
|
||||||
|
Description = string.Empty;
|
||||||
|
Pic = null;
|
||||||
|
loading = false;
|
||||||
|
confirmDelete = false;
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task PostPic() {
|
public async Task PostPic() {
|
||||||
loading = true;
|
loading = true;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
|
@ -62,6 +100,7 @@
|
||||||
Description = string.Empty;
|
Description = string.Empty;
|
||||||
Pic = null;
|
Pic = null;
|
||||||
loading = false;
|
loading = false;
|
||||||
|
confirmDelete = false;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,18 @@
|
||||||
<label>Status</label>
|
<label>Status</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<nav class="right-align no-space">
|
<nav class="no-space">
|
||||||
|
@if (confirmDelete) {
|
||||||
|
<button @onclick="ConfirmDeleteStatus" disabled="@loading" class="red-7-bg white-fg">
|
||||||
|
<i class="fa-solid fa-exclamation-triangle"></i> <span>Are you sure?</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
<button @onclick="DeleteStatus" disabled="@loading" class="red-7-bg white-fg">
|
||||||
|
<i class="fa-solid fa-trash"></i> <span>Delete</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
<div class="max"></div>
|
||||||
<InputText id="status-emoji-input" class="invisible" @bind-Value="Emoji"></InputText>
|
<InputText id="status-emoji-input" class="invisible" @bind-Value="Emoji"></InputText>
|
||||||
<button class="transparent link" data-ui="#@id" disabled="@loading">Cancel</button>
|
<button class="transparent link" data-ui="#@id" disabled="@loading">Cancel</button>
|
||||||
<button @onclick="PatchStatus" disabled="@loading">
|
<button @onclick="PatchStatus" disabled="@loading">
|
||||||
|
@ -60,12 +71,40 @@
|
||||||
private bool loading = false;
|
private bool loading = false;
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string id { get; set; }
|
public string id { get; set; }
|
||||||
|
private bool confirmDelete { get; set; }
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync() {
|
protected override async Task OnInitializedAsync() {
|
||||||
Content = Status?.Content;
|
Content = Status?.Content;
|
||||||
Emoji = Status?.Emoji;
|
Emoji = Status?.Emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task DeleteStatus() {
|
||||||
|
if (!confirmDelete) confirmDelete = true;
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ConfirmDeleteStatus() {
|
||||||
|
if(confirmDelete) {
|
||||||
|
loading = true;
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Status?.Id)) {
|
||||||
|
await api.DeleteStatus(State.SelectedAddressName, Status.Id);
|
||||||
|
await State.RefreshStatuses();
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
await JS.InvokeVoidAsync("ui", "#" + id);
|
||||||
|
// clear input
|
||||||
|
Content = string.Empty;
|
||||||
|
Emoji = string.Empty;
|
||||||
|
Status = null;
|
||||||
|
loading = false;
|
||||||
|
confirmDelete = false;
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task PatchStatus() {
|
public async Task PatchStatus() {
|
||||||
loading = true;
|
loading = true;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
|
@ -82,6 +121,7 @@
|
||||||
Emoji = string.Empty;
|
Emoji = string.Empty;
|
||||||
Status = null;
|
Status = null;
|
||||||
loading = false;
|
loading = false;
|
||||||
|
confirmDelete = false;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,15 +9,15 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="min square extra">
|
<div class="min square extra">
|
||||||
<button class="transparent square extra no-margin">
|
<button class="transparent square extra no-margin">
|
||||||
<object id="status-emoji" class="large emoji @(Emoji == null ? "animated" : string.Empty)" data-emoji="@(Emoji ?? "🫥")">@(Emoji ?? "🫥")</object>
|
<object id="new-status-emoji" class="large emoji @(Emoji == null ? "animated" : string.Empty)" data-emoji="@(Emoji ?? "🫥")">@(Emoji ?? "🫥")</object>
|
||||||
<menu class="no-wrap">
|
<menu class="no-wrap">
|
||||||
<script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@@^1/index.js"></script>
|
<script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@@^1/index.js"></script>
|
||||||
<emoji-picker emoji-version="15.1"></emoji-picker>
|
<emoji-picker emoji-version="15.1"></emoji-picker>
|
||||||
<script>
|
<script>
|
||||||
document.querySelector('emoji-picker')
|
document.querySelector('emoji-picker')
|
||||||
.addEventListener('emoji-click', event => {
|
.addEventListener('emoji-click', event => {
|
||||||
document.getElementById('status-emoji').setAttribute('data-emoji', event.detail.unicode)
|
document.getElementById('new-status-emoji').setAttribute('data-emoji', event.detail.unicode)
|
||||||
const input = document.getElementById('status-emoji-input')
|
const input = document.getElementById('new-status-emoji-input')
|
||||||
input.value = event.detail.unicode
|
input.value = event.detail.unicode
|
||||||
var event = new Event('change');
|
var event = new Event('change');
|
||||||
input.dispatchEvent(event);
|
input.dispatchEvent(event);
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
<span>Post this to Mastodon</span>
|
<span>Post this to Mastodon</span>
|
||||||
</label>
|
</label>
|
||||||
}
|
}
|
||||||
<InputText id="status-emoji-input" class="invisible" @bind-Value="Emoji"></InputText>
|
<InputText id="new-status-emoji-input" class="invisible" @bind-Value="Emoji"></InputText>
|
||||||
<button class="transparent link" data-ui="#@id" disabled="@loading">Cancel</button>
|
<button class="transparent link" data-ui="#@id" disabled="@loading">Cancel</button>
|
||||||
<button @onclick="PostStatus" disabled="@loading">
|
<button @onclick="PostStatus" disabled="@loading">
|
||||||
@if (loading) {
|
@if (loading) {
|
||||||
|
|
11
Models/DeleteResponseData.cs
Normal file
11
Models/DeleteResponseData.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Neighbourhood.omg.lol.Models {
|
||||||
|
public class DeleteResponseData : IOmgLolResponseData {
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
// Account data
|
// Account data
|
||||||
public AccountResponseData? AccountInfo { get; set; }
|
public AccountResponseData? AccountInfo { get; set; }
|
||||||
public AddressResponseList? AddressList { get; set; }
|
public AddressResponseList? AddressList { get; set; }
|
||||||
|
|
||||||
public string? Name { get => AccountInfo?.Name; }
|
public string? Name { get => AccountInfo?.Name; }
|
||||||
public string? Email { get => AccountInfo?.Email; }
|
public string? Email { get => AccountInfo?.Email; }
|
||||||
public IEnumerable<string>? AddressNames { get => AddressList?.Select(a => a.Address); }
|
public IEnumerable<string>? AddressNames { get => AddressList?.Select(a => a.Address); }
|
||||||
|
@ -44,7 +44,7 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
// share intent stuff
|
// share intent stuff
|
||||||
public event EventHandler<EventArgs>? IntentReceived;
|
public event EventHandler<EventArgs>? IntentReceived;
|
||||||
private string? _shareString;
|
private string? _shareString;
|
||||||
public string? ShareString {
|
public string? ShareString {
|
||||||
get => _shareString;
|
get => _shareString;
|
||||||
set {
|
set {
|
||||||
_shareString = value;
|
_shareString = value;
|
||||||
|
@ -139,7 +139,7 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<MarkupString>?> GetEphemeralMessages(bool forceRefresh = false) {
|
public async Task<List<MarkupString>?> GetEphemeralMessages(bool forceRefresh = false) {
|
||||||
if(forceRefresh || this.EphemeralMessages == null || this.EphemeralMessages.Count == 0) {
|
if (forceRefresh || this.EphemeralMessages == null || this.EphemeralMessages.Count == 0) {
|
||||||
this.EphemeralMessages = await api.Ephemeral();
|
this.EphemeralMessages = await api.Ephemeral();
|
||||||
}
|
}
|
||||||
return this.EphemeralMessages;
|
return this.EphemeralMessages;
|
||||||
|
@ -179,7 +179,7 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Pic>?> GetPics(bool forceRefresh = false) {
|
public async Task<List<Pic>?> GetPics(bool forceRefresh = false) {
|
||||||
if(forceRefresh || this.Pics == null || this.Pics.Count == 0) {
|
if (forceRefresh || this.Pics == null || this.Pics.Count == 0) {
|
||||||
this.Pics = await api.SomePics();
|
this.Pics = await api.SomePics();
|
||||||
}
|
}
|
||||||
return this.Pics;
|
return this.Pics;
|
||||||
|
@ -193,8 +193,16 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
return CachedAddressPics;
|
return CachedAddressPics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RefreshStatuses() => await GetStatuses(forceRefresh: true);
|
public async Task RefreshStatuses() {
|
||||||
public async Task RefreshPics() => await GetPics(forceRefresh: true);
|
await GetStatuses(forceRefresh: true);
|
||||||
|
if(SelectedAddressName != null)
|
||||||
|
await GetStatuses(SelectedAddressName, forceRefresh: true);
|
||||||
|
}
|
||||||
|
public async Task RefreshPics() {
|
||||||
|
await GetPics(forceRefresh: true);
|
||||||
|
if (SelectedAddressName != null)
|
||||||
|
await GetPics(SelectedAddressName, forceRefresh: true );
|
||||||
|
}
|
||||||
public async Task RefreshNow() => await GetNowGarden(forceRefresh: true);
|
public async Task RefreshNow() => await GetNowGarden(forceRefresh: true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,31 @@ namespace Neighbourhood.omg.lol {
|
||||||
return responseData;
|
return responseData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<T?> Delete<T>(string uri, CancellationToken cancellationToken = default) where T : IOmgLolResponseData {
|
||||||
|
T? responseData = default(T);
|
||||||
|
try {
|
||||||
|
HttpResponseMessage response = await _client.DeleteAsync(uri, cancellationToken: cancellationToken);
|
||||||
|
if (response.IsSuccessStatusCode) {
|
||||||
|
string str = await response.Content.ReadAsStringAsync();
|
||||||
|
try {
|
||||||
|
OmgLolResponse<T>? responseObj = await response.Content.ReadFromJsonAsync<OmgLolResponse<T>>(_serializerOptions, cancellationToken: cancellationToken);
|
||||||
|
if (responseObj != null && responseObj.Request.Success) {
|
||||||
|
responseData = responseObj.Response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (JsonException ex) {
|
||||||
|
Debug.WriteLine(@"\tERROR {0}", ex.Message);
|
||||||
|
Debug.WriteLine(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Debug.WriteLine(@"\tERROR {0}", ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseData;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<List<Status>> StatuslogLatest() =>
|
public async Task<List<Status>> StatuslogLatest() =>
|
||||||
(await Get<StatusResponseData>("/statuslog/latest"))?.Statuses ?? new List<Status>();
|
(await Get<StatusResponseData>("/statuslog/latest"))?.Statuses ?? new List<Status>();
|
||||||
|
|
||||||
|
@ -170,10 +195,16 @@ namespace Neighbourhood.omg.lol {
|
||||||
|
|
||||||
public async Task<PutPicResponseData?> PostPicDescription(string address, string id, string description) =>
|
public async Task<PutPicResponseData?> PostPicDescription(string address, string id, string description) =>
|
||||||
(await Post<PutPicResponseData, PostPic>($"/address/{address}/pics/{id}", new PostPic { Description = description }));
|
(await Post<PutPicResponseData, PostPic>($"/address/{address}/pics/{id}", new PostPic { Description = description }));
|
||||||
|
public async Task<DeleteResponseData?> DeletePic(string address, string id) =>
|
||||||
|
(await Delete<DeleteResponseData>($"/address/{address}/pics/{id}"));
|
||||||
|
|
||||||
|
|
||||||
public async Task<PatchStatusResponseData?> PatchStatus(string address, string id, string content, string? emoji) =>
|
public async Task<PatchStatusResponseData?> PatchStatus(string address, string id, string content, string? emoji) =>
|
||||||
(await Patch<PatchStatusResponseData, PatchStatus>($"/address/{address}/statuses/", new PatchStatus { Id = id, Content = content, Emoji = emoji }));
|
(await Patch<PatchStatusResponseData, PatchStatus>($"/address/{address}/statuses/", new PatchStatus { Id = id, Content = content, Emoji = emoji }));
|
||||||
|
|
||||||
|
public async Task<DeleteResponseData?> DeleteStatus(string address, string id) =>
|
||||||
|
(await Delete<DeleteResponseData>($"/address/{address}/statuses/{id}"));
|
||||||
|
|
||||||
public async Task<List<NowData>?> NowGarden() =>
|
public async Task<List<NowData>?> NowGarden() =>
|
||||||
(await Get<NowResponseData>($"/now/garden"))?.Garden ?? new List<NowData>();
|
(await Get<NowResponseData>($"/now/garden"))?.Garden ?? new List<NowData>();
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ img {
|
||||||
text-indent: -10px;
|
text-indent: -10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status .emoji, #status-emoji {
|
.status .emoji, #status-emoji, #new-status-emoji {
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
inline-size: 3.5rem;
|
inline-size: 3.5rem;
|
||||||
block-size: 3.5rem;
|
block-size: 3.5rem;
|
||||||
|
|
Loading…
Reference in a new issue