runSpinner<T> static method

Future<T> runSpinner<T>(
  1. InlineTerminal terminal, {
  2. required String heading,
  3. required Stream<T> stream,
  4. String toMessage(
    1. T
    )?,
  5. bool isSuccess(
    1. T
    )?,
  6. String? successMessage,
  7. String? failedMessage,
  8. Duration spinnerInterval = _defaultSpinnerInterval,
  9. Duration? elapsed()?,
  10. SpinnerScheduler? scheduleTicker,
})

Runs a heading-only spinner (no scrolling output lines) while consuming stream.

The heading starts as heading and is updated with toMessage for each event. When the stream ends, the spinner is completed with success from isSuccess of the last event, or a clean end if isSuccess is omitted. A stream error or an empty stream finishes as a failure; the error is rethrown, and an empty stream throws StateError.

elapsed supplies the elapsed time shown in the heading, as for the constructor.

Implementation

static Future<T> runSpinner<T>(
  InlineTerminal terminal, {
  required String heading,
  required Stream<T> stream,
  String Function(T)? toMessage,
  bool Function(T)? isSuccess,
  String? successMessage,
  String? failedMessage,
  Duration spinnerInterval = _defaultSpinnerInterval,
  Duration? Function()? elapsed,
  SpinnerScheduler? scheduleTicker,
}) async {
  final section = ScrollingSection(
    terminal: terminal,
    rows: 1,
    heading: heading,
    successMessage: successMessage,
    failedMessage: failedMessage,
    spinnerInterval: spinnerInterval,
    elapsed: elapsed,
    scheduleTicker: scheduleTicker,
  );

  late T lastEvent;
  var receivedEvent = false;
  try {
    await for (final event in stream) {
      lastEvent = event;
      receivedEvent = true;
      final messageForEvent = toMessage;
      if (messageForEvent != null) {
        section.updateHeading(messageForEvent(event));
      }
    }
    if (!receivedEvent) {
      section.finish(success: false);
      throw StateError('Stream was empty');
    }
    section.finish(success: isSuccess?.call(lastEvent) ?? true);
    return lastEvent;
  } on Object {
    if (!section.isFinished) {
      section.finish(success: false);
    }
    rethrow;
  }
}