replayScenarioStream function
Stream<Msg>
replayScenarioStream(
- List<
ReplayAction> actions, { - required bool loop,
- required bool keepOpen,
- required double speed,
- ReplayEventHook? eventHook,
Builds a replay message stream from a list of replay actions.
Implementation
Stream<Msg> replayScenarioStream(
List<ReplayAction> actions, {
required bool loop,
required bool keepOpen,
required double speed,
ReplayEventHook? eventHook,
}) async* {
if (actions.isEmpty) {
if (!keepOpen && !loop) yield const QuitMsg();
return;
}
Duration pendingDelay = Duration.zero;
Duration scaled(Duration input) {
final micros = (input.inMicroseconds / speed).round();
return Duration(microseconds: math.max(0, micros));
}
do {
for (final action in actions) {
if (action.type == 'sleep') {
pendingDelay += scaled(Duration(milliseconds: action.ms));
continue;
}
if (action.type == 'event') {
if (pendingDelay > Duration.zero) {
await Future<void>.delayed(pendingDelay);
pendingDelay = Duration.zero;
}
final event = action.customEvent;
if (event == null) {
continue;
}
final directive =
await eventHook?.call(event) ??
ReplayEventDirective.emit(<Msg>[ReplayEventMsg(event)]);
final hookDelay = scaled(directive.delay);
if (hookDelay > Duration.zero) {
await Future<void>.delayed(hookDelay);
}
for (final msg in directive.messages) {
yield msg;
}
if (directive.control == ReplayEventControl.quit) {
yield const QuitMsg();
return;
}
if (directive.control == ReplayEventControl.stop) {
return;
}
continue;
}
final events = action.toMessages();
for (final msg in events) {
if (pendingDelay > Duration.zero) {
await Future<void>.delayed(pendingDelay);
pendingDelay = Duration.zero;
}
yield msg;
}
}
if (pendingDelay > Duration.zero) {
await Future<void>.delayed(pendingDelay);
pendingDelay = Duration.zero;
}
} while (loop);
if (!keepOpen) {
yield const QuitMsg();
}
}