permissionsProcessingStream function

Stream<bool> permissionsProcessingStream(
  1. PermissionNotifier stateNotifier,
  2. List<PermissionType> permissions
)

Builds a Stream<bool> reporting whether any of permissions currently reads as PermissionUiState.requesting or PermissionUiState.openingSettings on stateNotifier — i.e. "busy" from the caller's perspective. Feed this into PermissionScreen.externalProcessingStream so the screen's busy indicator reflects the real Riverpod-driven operation state instead of only its own local tracking.

Shared by every canonical-flow caller in this package (PermissionActionNotifier and PermissionBuilder) so the bridging logic between PermissionNotifier (a ChangeNotifier) and a Stream<bool> exists in exactly one place.

Implementation

Stream<bool> permissionsProcessingStream(
  PermissionNotifier stateNotifier,
  List<PermissionType> permissions,
) {
  bool isBusy() {
    final state = stateNotifier.state;
    return permissions.any((p) {
      final uiState = state.uiStateFor(p);
      return uiState == PermissionUiState.requesting ||
          uiState == PermissionUiState.openingSettings;
    });
  }

  late final StreamController<bool> controller;
  void listener() => controller.add(isBusy());

  controller = StreamController<bool>.broadcast(
    onListen: () {
      // Seed the current value on subscribe so the screen ends up
      // with a correct initial state rather than only reacting to
      // the next change. Note: since this is a standard (non-sync)
      // broadcast controller, delivery to the listener happens on a
      // later microtask, not literally synchronously within this
      // callback — the screen's getter falls back to its own local
      // fallback state for that one microtask, which is harmless
      // here since setOpeningSettings() is what actually flips this
      // to true, and that only happens once the user taps the
      // button — well after this initial subscribe-and-seed has
      // already settled.
      controller.add(isBusy());
      stateNotifier.addListener(listener);
    },
    onCancel: () => stateNotifier.removeListener(listener),
  );

  return controller.stream;
}