-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcall_answer.dart
64 lines (50 loc) · 1.77 KB
/
call_answer.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
library seaside.call_answer;
import 'dart:async';
import 'package:meta/meta.dart';
import 'component.dart';
import 'continuation.dart';
import 'has_state.dart';
import 'value_holder.dart';
/// Type of an answer handler.
typedef AnswerHandler<T> = void Function(T value);
/// A component with an answer handler.
mixin CanAnswer<T> implements Component {
/// Currently registered answer handler.
AnswerHandler<T> onAnswer;
/// Answers the provided [value].
void answer(T value) => onAnswer?.call(value);
}
/// A task defines a sequence of components being shown.
abstract class Task extends Component {
final ValueHolder<CanAnswer> _delegate = ValueHolder<CanAnswer>();
bool get isRunning => _delegate.value != null;
@override
@mustCallSuper
Iterable<HasState> get states => [_delegate];
@override
@nonVirtual
Iterable<Component> get children => isRunning ? [_delegate.value] : [];
@override
@nonVirtual
String body(Continuation continuation) => isRunning
? _delegate.value.body(continuation)
: '<script>document.location.href="${continuation.action(run)}";</script>';
/// Defines the workflow as a sequence of calls.
void run();
/// Shows the provided [component], evaluates the [onAnswer] callback with
/// the answer of the component.
void show<T>(CanAnswer<T> component, {AnswerHandler<T> onAnswer}) {
_delegate.value = component;
component.onAnswer = (value) {
_delegate.value = null;
onAnswer?.call(value);
};
}
/// Shows the provided [component] asynchronously, resolves the resulting
/// [Future] with the answer of the component.
Future<T> call<T>(CanAnswer<T> component) {
final completer = Completer<T>.sync();
show<T>(component, onAnswer: completer.complete);
return completer.future;
}
}