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