Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

Blazor Custom longpress button - making sure the action only triggers once

$
0
0

We have a Blazor web UI with MudBlazor components, running on a kiosk PC with a touchscren. Problem is our users frequently place their finger on a button and just hold them there. This way the OnClick event doesn't fire, so nothing happens. Then they complain that our kiosk isn't working.

I've been developing a custom button that reacts to a "longpress" as well as a normal tap.The intended functionality is as follows:

  • if the user presses and holds the button, after 300ms the button registers it as a regular press and triggers its action.
  • the normal button press still works

How I've implemented it:on ontouchstart a 300ms timer is started (or a Task.Delay).after the timer has elapsed, or an ontouchend event is fired, the following happens:

  • timer is stopped
  • the "_actionExecuted" bool is checked. If it's false, it's immediately set to true and the action is executed. If it's already true, nothing happens, I just return.

It seems pretty straightforward, but even with the check, the action sometimes gets triggered twice.

Here's my code (abridged):

@inherits MudButton<MudButton @onmousedown="StartTimer"           @onmouseup="HandleRelease"           @ontouchstart="StartTimer"           @ontouchend="HandleRelease">    @ChildContent</MudButton>
 private async Task ExecuteAction(bool fromTimer) {     string origin = fromTimer ? "timer" : "touch end";     if (_actionExecuted)     {         Console.WriteLine($" KioskButton - {origin} - {DataTestId} - action tried to double-fire.");         return;     }// Prevent multiple calls     _actionExecuted = true;     Console.WriteLine($"a) KioskButton - {origin} - {DataTestId} - action triggered and passed check.");     if (OnAction != null)     {        Console.WriteLine($"b) KioskButton - {origin} - {DataTestId} - performing OnAction.");        await OnAction(Parameters);     } }  private void StartTimer()  {     StopTimer(); // Ensure no previous timer is running     _actionExecuted = false;     _cts = new CancellationTokenSource();     Task.Delay(HoldDuration, _cts.Token).ContinueWith(async t =>     {         if (!t.IsCanceled)         {             await ExecuteAction(true);         }     }, TaskScheduler.Default);   }  private async Task HandleRelease()  {      StopTimer(); // Stop the hold timer      await ExecuteAction(false); // Execute if not already triggered  }   private void StopTimer()   {       _cts?.Cancel();       _cts?.Dispose();       _cts = null;   }

I was under the impression this code should have prevented double-firing of the action. But it does happen, actually quite often - maybe one out of 5 clicks (although when I try to reproduce it on purpose, it stops happening). Is there a way to make absolutely sure the button never double-fires?


Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>