I've encountered a problem with the bootstrap progress-bar in a mobile browser while developing a Blazor project. The issue arises when I use two buttons to control the progress bar - one to start it and the other to stop it. The animations are managed using the transition property. Strangely, everything works fine on my desktop and laptop, but fails on mobile browsers (although it works when emulated through developer tools).
The problem begins after pressing the Stop button for the first time on mobile browsers. When I try to restart the progress bar by pressing Start again, it doesn't reset properly and instead starts increasing slowly despite having 'transition: none' set. Subsequent presses on the stop and start buttons further break the functionality. A screen recording showcasing this bug on mobile is available on swisstransfer file share service: .
You can find the code below and test the site on Azure.
Any help would be greatly appreciated.
@page "/"
@* The progress bar ===================================================================*@
<div style="padding-bottom: 5px;">
<div class="progress" style="height: 10px;">
<div class="progress-bar" style="width: @_progressPercent%; background-color: @_progressColor; transition: @_transition"></div>
</div>
</div>
<button disabled="@_startButtonIsDisabled" @onclick="StartProgressBar">Start</button>
<button disabled="@_stopButtonIsDisabled" @onclick="StopProgressBar">Stop</button>
@code {
private Timer? _timer;
private int _counter;
private string _progressColor="grey";
private string _transition="none";
private int _progressPercent=100;
private double _t1 = 4;
private double _t2 = 8;
private double _tend = 16;
private DateTime _timerStartTime;
private bool _startButtonIsDisabled = false;
private bool _stopButtonIsDisabled = true;
private void TimerCallback(object? o)
{
_counter++;
switch (_counter)
{
case 0:
_progressPercent = (int)(100 * ( 1 - _t1 / _tend));
_transition = $"width {_t1}s linear";
InvokeAsync(StateHasChanged); // Update the UI
break;
case 1:
_progressPercent = (int)(100 * ( 1 - _t2 / _tend));
_progressColor = "orange";
_transition = $"width {_t2-_t1}s linear";
InvokeAsync(StateHasChanged); // Update the UI
_timer.Change(1000*(int)(_t2-_t1), Timeout.Infinite); // Set timer to _t2-_t1 seconds for the next event
break;
case 2:
_progressPercent = 0;
_progressColor = "red";
_transition = $"width {_tend-_t2}s linear";
InvokeAsync(StateHasChanged); // Update the UI
_timer.Change(1000*(int)(_tend-_t2), Timeout.Infinite); // Set timer to _tend-_t2 seconds for the next event
break;
case 3:
InvokeAsync(StateHasChanged); // Update the UI
_timer.Dispose(); // Stop the timer
break;
}
}
void StartProgressBar()
{
_startButtonIsDisabled = true;
_stopButtonIsDisabled = false;
_timerStartTime = DateTime.Now;
// reset the progress bar ==================
_counter = -1;
ResetProgressBar();
InvokeAsync(StateHasChanged);
_timer = new Timer(TimerCallback, null, 0, (int)_t1 * 1000);
}
void ResetProgressBar()
{
_progressPercent = 100;
_progressColor = "green";
_transition = "none";
}
void StopProgressBar()
{
_startButtonIsDisabled = false;
_stopButtonIsDisabled = true;
_timer.Dispose(); // Stop the timer
var ts = DateTime.Now - _timerStartTime;
_progressPercent = (int)(100 * ( 1 - ts.TotalMilliseconds / (_tend*1_000)));
_transition = "none";
}
}