Added components to article
This commit is contained in:
@ -3,20 +3,79 @@ import 'package:hl_lieferservice/widget/operations/bloc/operation_event.dart';
|
||||
import 'package:hl_lieferservice/widget/operations/bloc/operation_state.dart';
|
||||
|
||||
class OperationBloc extends Bloc<OperationEvent, OperationState> {
|
||||
/// Counts how many in-flight mutations want to show the blocking overlay.
|
||||
/// Allows multiple parallel mutations without one prematurely closing the
|
||||
/// overlay before the others complete.
|
||||
int _inFlightCount = 0;
|
||||
|
||||
/// When the current overlay session began (set when [_inFlightCount]
|
||||
/// transitions 0 → 1). Used to enforce [_minimumDisplayDuration].
|
||||
DateTime? _overlayStartedAt;
|
||||
|
||||
/// Minimum time the overlay stays visible, even if the underlying request
|
||||
/// completes faster. Prevents a "did anything happen?" UX where a sub-100 ms
|
||||
/// roundtrip flashes the overlay for one frame.
|
||||
static const Duration _minimumDisplayDuration = Duration(milliseconds: 350);
|
||||
|
||||
OperationBloc() : super(OperationIdle()) {
|
||||
on<StartOperation>(_startOperation);
|
||||
on<FailOperation>(_failOperation);
|
||||
on<FinishOperation>(_finishOperation);
|
||||
}
|
||||
|
||||
Future<void> _failOperation(FailOperation event, Emitter<OperationState> emit) async {
|
||||
emit(OperationFailed(message: event.message));
|
||||
await Future.delayed(const Duration(seconds: 5));
|
||||
emit(OperationIdle());
|
||||
Future<void> _startOperation(
|
||||
StartOperation event,
|
||||
Emitter<OperationState> emit,
|
||||
) async {
|
||||
if (_inFlightCount == 0) {
|
||||
_overlayStartedAt = DateTime.now();
|
||||
}
|
||||
_inFlightCount += 1;
|
||||
emit(OperationInProgress(message: event.message));
|
||||
}
|
||||
|
||||
Future<void> _finishOperation(FinishOperation event, Emitter<OperationState> emit) async {
|
||||
emit(OperationFinished(message: event.message));
|
||||
Future<void> _finishOperation(
|
||||
FinishOperation event,
|
||||
Emitter<OperationState> emit,
|
||||
) async {
|
||||
_inFlightCount = (_inFlightCount - 1).clamp(0, 1 << 30);
|
||||
|
||||
if (event.message != null) {
|
||||
emit(OperationFinished(message: event.message));
|
||||
await Future.delayed(const Duration(seconds: 5));
|
||||
}
|
||||
|
||||
if (_inFlightCount > 0) {
|
||||
emit(OperationInProgress());
|
||||
} else {
|
||||
await _awaitMinimumOverlayDuration();
|
||||
_overlayStartedAt = null;
|
||||
emit(OperationIdle());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _failOperation(
|
||||
FailOperation event,
|
||||
Emitter<OperationState> emit,
|
||||
) async {
|
||||
_inFlightCount = (_inFlightCount - 1).clamp(0, 1 << 30);
|
||||
emit(OperationFailed(message: event.message));
|
||||
await Future.delayed(const Duration(seconds: 5));
|
||||
emit(OperationIdle());
|
||||
|
||||
if (_inFlightCount > 0) {
|
||||
emit(OperationInProgress());
|
||||
} else {
|
||||
_overlayStartedAt = null;
|
||||
emit(OperationIdle());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _awaitMinimumOverlayDuration() async {
|
||||
final startedAt = _overlayStartedAt;
|
||||
if (startedAt == null) return;
|
||||
final elapsed = DateTime.now().difference(startedAt);
|
||||
if (elapsed < _minimumDisplayDuration) {
|
||||
await Future.delayed(_minimumDisplayDuration - elapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
abstract class OperationEvent {}
|
||||
|
||||
class StartOperation extends OperationEvent {
|
||||
String? message;
|
||||
|
||||
StartOperation({this.message});
|
||||
}
|
||||
|
||||
class FailOperation extends OperationEvent {
|
||||
String message;
|
||||
|
||||
|
||||
@ -2,6 +2,12 @@ abstract class OperationState {}
|
||||
|
||||
class OperationIdle extends OperationState {}
|
||||
|
||||
class OperationInProgress extends OperationState {
|
||||
String? message;
|
||||
|
||||
OperationInProgress({this.message});
|
||||
}
|
||||
|
||||
class OperationFailed extends OperationState {
|
||||
String message;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user