import 'dart:async'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:finlytic_app/features/search/repositories/search_repository.dart'; import 'search_event.dart'; import 'search_state.dart'; export 'search_event.dart'; export 'search_state.dart'; EventTransformer debounce(Duration duration) { return (events, mapper) => events.switchMap((event) => Stream.value(event).asyncExpand(mapper)); } extension SwitchMapExtension on Stream { Stream switchMap(Stream Function(T event) mapper) { StreamController? controller; StreamSubscription? inputSub; StreamSubscription? outputSub; controller = StreamController( onListen: () { inputSub = listen((event) { outputSub?.cancel(); outputSub = mapper(event).listen( controller?.add, onError: controller?.addError, ); }, onDone: () { // Wait for last sub to finish or close }); }, onCancel: () { outputSub?.cancel(); inputSub?.cancel(); }, ); return controller.stream; } } class SearchBloc extends Bloc { final SearchRepository repository; SearchBloc({required this.repository}) : super(SearchInitial()) { on(_onSearchQueryChanged); } Future _onSearchQueryChanged(SearchQueryChanged event, Emitter emit) async { emit(SearchLoading()); try { final results = await repository.searchAssets(event.query); emit(SearchLoaded(results)); } catch (e) { emit(const SearchError("Fehler bei der Suche.")); } } }