What can't be undone asks first
Deleting a post, taking it off the persona's wall, muting or blocking an account (from a card or a profile), leaving a group, dropping a scheduled post and signing out acted at the first tap, a few pixels from their neighbours. They now ask first: new ConfirmService (Ask returns whether the reader confirmed, as PublicNoticeService does) and ConfirmHost in MainLayout, a sheet from the bottom on a phone and a dialog from md, with Cancel and the action named, in red when it deletes or cuts off. Logout is a button that asks, then goes to /logout as before. The reversible ones (unmute, unblock, removing a conversation from the list, a picture from the composer) don't ask; the inline confirms of lists, filters and the login's deletion stay. The desktop tests that delete a reply, take a post off a wall or drop a scheduled post confirm; a phone flow deletes a post after cancelling once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
931b7fcff1
commit
1c9773bab0
15 files changed
+211
-3
No files matched your search
@@ -0,0 +1,40 @@
|
||||
namespace decePubClient.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Asks before what can't be undone (deleting a post, blocking, leaving a group, signing out): Ask shows the question
|
||||
/// in ConfirmHost (MainLayout) and returns whether the reader confirmed it. One question at a time; a second one asked
|
||||
/// while the first is open answers the first no.
|
||||
/// </summary>
|
||||
public class ConfirmService
|
||||
{
|
||||
TaskCompletionSource<bool> pending;
|
||||
|
||||
public event Action Changed;
|
||||
|
||||
public bool IsAsking => pending is not null;
|
||||
public string Heading { get; private set; }
|
||||
public string Text { get; private set; }
|
||||
public string ConfirmText { get; private set; }
|
||||
/// <summary>The confirm button shows as a danger (it deletes or cuts something off).</summary>
|
||||
public bool Danger { get; private set; }
|
||||
|
||||
public async Task<bool> Ask(string heading, string text, string confirmText, bool danger, CancellationToken cancellationToken = default)
|
||||
{
|
||||
pending?.TrySetResult(false);
|
||||
var asking = new TaskCompletionSource<bool>();
|
||||
pending = asking;
|
||||
(Heading, Text, ConfirmText, Danger) = (heading, text, confirmText, danger);
|
||||
Changed?.Invoke();
|
||||
await using var cancel = cancellationToken.Register(() => asking.TrySetResult(false));
|
||||
var confirmed = await asking.Task;
|
||||
if (pending == asking)
|
||||
{
|
||||
pending = null;
|
||||
Changed?.Invoke();
|
||||
}
|
||||
return confirmed;
|
||||
}
|
||||
|
||||
public void Answer(bool confirmed) => pending?.TrySetResult(confirmed);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user