permissionsProcessingStream function
Stream<bool>
permissionsProcessingStream(
- PermissionNotifier stateNotifier,
- 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;
}