92 lines
2.2 KiB
Dart
92 lines
2.2 KiB
Dart
/// Coordinates Scheduler Read Controller state for the FocusFlow Flutter UI.
|
|
library;
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:scheduler_core/scheduler_core.dart';
|
|
|
|
typedef ApplicationReader<T> = Future<ApplicationResult<T>> Function();
|
|
typedef EmptyPredicate<T> = bool Function(T value);
|
|
|
|
abstract class UiReadController<T> extends ChangeNotifier {
|
|
SchedulerReadState<T> get state;
|
|
|
|
Future<void> load();
|
|
|
|
Future<void> retry();
|
|
}
|
|
|
|
sealed class SchedulerReadState<T> {
|
|
const SchedulerReadState();
|
|
}
|
|
|
|
class SchedulerReadLoading<T> extends SchedulerReadState<T> {
|
|
const SchedulerReadLoading();
|
|
}
|
|
|
|
class SchedulerReadData<T> extends SchedulerReadState<T> {
|
|
const SchedulerReadData(this.value);
|
|
|
|
final T value;
|
|
}
|
|
|
|
class SchedulerReadEmpty<T> extends SchedulerReadState<T> {
|
|
const SchedulerReadEmpty(this.value);
|
|
|
|
final T value;
|
|
}
|
|
|
|
class SchedulerReadFailure<T> extends SchedulerReadState<T> {
|
|
const SchedulerReadFailure({this.failure, this.error});
|
|
|
|
final ApplicationFailure? failure;
|
|
final Object? error;
|
|
|
|
String get codeLabel {
|
|
final typed = failure;
|
|
if (typed != null) {
|
|
return typed.detailCode ?? typed.code.name;
|
|
}
|
|
return 'unexpected';
|
|
}
|
|
}
|
|
|
|
class ApplicationReadController<T> extends UiReadController<T> {
|
|
ApplicationReadController({required this.read, required this.isEmpty});
|
|
|
|
final ApplicationReader<T> read;
|
|
final EmptyPredicate<T> isEmpty;
|
|
|
|
SchedulerReadState<T> _state = SchedulerReadLoading<T>();
|
|
|
|
@override
|
|
SchedulerReadState<T> get state => _state;
|
|
|
|
@override
|
|
Future<void> load() async {
|
|
_setState(SchedulerReadLoading<T>());
|
|
try {
|
|
final result = await read();
|
|
final failure = result.failure;
|
|
if (failure != null) {
|
|
_setState(SchedulerReadFailure<T>(failure: failure));
|
|
return;
|
|
}
|
|
final value = result.requireValue;
|
|
_setState(
|
|
isEmpty(value)
|
|
? SchedulerReadEmpty<T>(value)
|
|
: SchedulerReadData<T>(value),
|
|
);
|
|
} on Object catch (error) {
|
|
_setState(SchedulerReadFailure<T>(error: error));
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> retry() => load();
|
|
|
|
void _setState(SchedulerReadState<T> next) {
|
|
_state = next;
|
|
notifyListeners();
|
|
}
|
|
}
|