spinner feedback to ui 2
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
/// Schedule heavy tab work off the first paint, yielding so nav stays responsive.
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
/// Runs [compute] after a frame, cancellable via [cancel] / generation bumps.
|
||||
class DeferredTabWork<T> {
|
||||
int _gen = 0;
|
||||
Object? _loadingKey;
|
||||
T? value;
|
||||
Object? valueKey;
|
||||
|
||||
bool readyFor(Object key) => value != null && valueKey == key;
|
||||
|
||||
bool get isLoading => _loadingKey != null;
|
||||
|
||||
void cancel() {
|
||||
_gen++;
|
||||
_loadingKey = null;
|
||||
}
|
||||
|
||||
/// Starts work for [key] unless already ready or in flight for that key.
|
||||
void ensure({
|
||||
required Object key,
|
||||
required Future<T> Function(Future<void> Function() yieldUi) compute,
|
||||
required void Function() onUpdate,
|
||||
required bool Function() mounted,
|
||||
}) {
|
||||
if (readyFor(key) || _loadingKey == key) return;
|
||||
_loadingKey = key;
|
||||
final gen = ++_gen;
|
||||
|
||||
unawaited(() async {
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
if (!mounted() || gen != _gen) return;
|
||||
|
||||
Future<void> yieldUi() async {
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
}
|
||||
|
||||
final result = await compute(yieldUi);
|
||||
if (!mounted() || gen != _gen) return;
|
||||
|
||||
value = result;
|
||||
valueKey = key;
|
||||
if (_loadingKey == key) _loadingKey = null;
|
||||
onUpdate();
|
||||
}());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user