import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/core/blocs/session/session_cubit.dart'; import 'package:flux/features/notes/data/notes_repository.dart'; import 'package:flux/features/notes/models/note_model.dart'; import 'package:get_it/get_it.dart'; part 'notes_event.dart'; part 'notes_state.dart'; class NotesBloc extends Bloc { final NotesRepository _repository = GetIt.I.get(); final String _companyId = GetIt.I.get().state.company!.id!; final String _currentStaffId = GetIt.I .get() .state .currentStaffMember! .id!; NotesBloc() : super(const NotesState()) { on(_onSubscribeToNotesRequested); on(_onNoteSavedRequested); on(_onNoteDeletedRequested); // Facciamo partire l'ascolto in tempo reale al boot del BLoC add(SubscribeToNotesRequested()); } Future _onSubscribeToNotesRequested( SubscribeToNotesRequested event, Emitter emit, ) async { emit(state.copyWith(status: NotesStatus.loading)); // Usiamo l'emit.forEach sullo stream pulito del repository await emit.forEach>( _repository.notesStream( companyId: _companyId, currentStaffId: _currentStaffId, ), onData: (notesList) { return state.copyWith(status: NotesStatus.success, notes: notesList); }, onError: (error, stackTrace) { return state.copyWith( status: NotesStatus.failure, errorMessage: 'Errore nello stream realtime: $error', ); }, ); } Future _onNoteSavedRequested( NoteSavedRequested event, Emitter emit, ) async { try { await _repository.saveNote(event.note); // Non serve fare l'emit! Ci pensa lo stream a far rimbalzare i dati aggiornati } catch (e) { emit( state.copyWith(status: NotesStatus.failure, errorMessage: e.toString()), ); } } Future _onNoteDeletedRequested( NoteDeletedRequested event, Emitter emit, ) async { try { await _repository.deleteNote(event.noteId); // Anche qui, lo stream rileva la cancellazione in automatico } catch (e) { emit( state.copyWith(status: NotesStatus.failure, errorMessage: e.toString()), ); } } }