42 lines
1.1 KiB
Dart
42 lines
1.1 KiB
Dart
/// Minimal async state container so screens can pattern-match over
|
|
/// loading / data / error instead of juggling three nullable fields.
|
|
sealed class AsyncValue<T> {
|
|
const AsyncValue();
|
|
|
|
const factory AsyncValue.loading() = AsyncLoading<T>;
|
|
const factory AsyncValue.data(T value) = AsyncData<T>;
|
|
const factory AsyncValue.error(String message) = AsyncError<T>;
|
|
|
|
T? get valueOrNull => this is AsyncData<T> ? (this as AsyncData<T>).value : null;
|
|
|
|
bool get isLoading => this is AsyncLoading<T>;
|
|
|
|
R map<R>({
|
|
required R Function() loading,
|
|
required R Function(T value) data,
|
|
required R Function(String message) error,
|
|
}) {
|
|
return switch (this) {
|
|
AsyncLoading<T>() => loading(),
|
|
AsyncData<T>(value: final v) => data(v),
|
|
AsyncError<T>(message: final m) => error(m),
|
|
};
|
|
}
|
|
}
|
|
|
|
final class AsyncLoading<T> extends AsyncValue<T> {
|
|
const AsyncLoading();
|
|
}
|
|
|
|
final class AsyncData<T> extends AsyncValue<T> {
|
|
const AsyncData(this.value);
|
|
|
|
final T value;
|
|
}
|
|
|
|
final class AsyncError<T> extends AsyncValue<T> {
|
|
const AsyncError(this.message);
|
|
|
|
final String message;
|
|
}
|