How to set a minimum time threshold for showing the spinner?

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.

1 Like

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
8 Likes

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.

1 Like