I want to modify the spinner such that it only appears if the functions takes longer than a specific threshold (e.g., 0.2 secs) to execute.
While the spinner has value in showing users that something is loading and they should wait, it becomes a bit of an annoyance if it appears all the time even for fast functions.
Having the spinner flash for a split second before it disappears is not really great UX.
Ah I think I got it. Here is a decorator that can be used for client-side functions. It will work regardless of whether a server function is called or not.
Please let me know if you spot any errors.
from anvil.js import window
import anvil.server
from anvil.server import no_loading_indicator
import functools
def delayed_spinner(func, threshold=0.3):
"""
A decorator that only shows the built-in Anvil spinner if
the wrapped function takes longer than `threshold` seconds.
"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 1) Create controller for the default spinner
loading = anvil.server.loading_indicator()
# 2) Schedule .start() after `threshold` ms
timer_id = window.setTimeout(lambda: loading.start(),
int(threshold * 1000))
try:
# 3) Run the function with the automatic spinner suppressed
with no_loading_indicator:
return func(*args, **kwargs)
finally:
# 4) Cancel the pending start (if it hasn’t fired yet)
window.clearTimeout(timer_id)
# And stop it if it did fire
loading.stop()
return wrapper
I implemented this to apply for all my server calls, and the app instantly feels faster just by not displaying the spinner all the time. This should be the default behaviour of the spinner.