A design pattern type question. I'm working with the TextToSpeech package for Flutter.
The user presses play (UI) this passes play event to Bloc, the bloc creates a TTSPlayer object and passes it a list of strings (TTSScript). The TTS reads aloud each string in the list by iterating through.
The PROBLEM: I want the bloc to dispatch an event every time the TTSPlayer moves to the next string in the list, so that i can display the current string on screen.
BUT: How do I pass a 'currentTextUpdatedEvent' from the TTSPlayer to the bloc, which I can then pass back to the UI.
I TRIED: I was hoping I could do something like:
BlocProvider.of<TTSPlayerBloc>(context).add(updateCurrentTtsString(currentTtsString));
from inside the TTSPlayer class... but of course, this class is not a widget it has no context. Should I use a callback? What would work here...? Should I move the TTSPlayer out of the bloc and into the screen instead?
Stream<TTSPlayerState> mapEventToState(TTSPlayerEvent event) async* {
TTSPlayer lessonPlayer = new TTSPlayer();
if (event is TTSPlayerScreenLoadedEvent) {
//get the script
TTSScript myScript = await scriptRepository.fetchScript(event.script);
// play it
lessonPlayer.play(myLessonScript);
//// How can the lessonplayer inform this Stream every time it's current string has changed?
yield TTSPlayingState();
}
/// something like this??? But how to send this event from TTSPlayer class...
if (event is updateCurrentTtsString){
yield NewStringState(newstring)
}
UPDATE So, i added a callback inside the TTSPlayer. So the bloc now looks like this:
Stream<TTSPlayerState> mapEventToState(TTSPlayerEvent event) async* {
TTSPlayer lessonPlayer = new TTSPlayer();
///
final newStringCallback = () {
this.add(updateCurrentTtsString(lessonPlayer.currentTtsString));
};
///
if (event is TTSPlayerScreenLoadedEvent) {
//get the script
TTSScript myScript = await scriptRepository.fetchScript(event.script);
// play it
lessonPlayer.play(myLessonScript, newStringCallback););
yield TTSPlayingState();
}
if (event is updateCurrentTtsString) {
print('New String');
yield TTSPlayingState(event.currentString);
}
The updateCurrentStringEvent does fire every time IF if remove the yield statement... the moment I include the yield statement, it stops the TTSPlayer from continuing. I don't get why the player would stop, but it does.