Hi, @felangel I hope u doing well.
in my project, I need to show the progress of uploading file.
I use Dio and in this library, there is a callback that returns progress of uploaded file.
this is my code can u help to fix this problem
I want to yield a state in callback function or maybe add state directly into Stream
```@override
Stream
ProfilePictureEvent event,
) async* {
if (event is UploadProfilePicture) {
final ProgressCallback progressCallback = (count, total) {
logDebug(value: 'count: $count, total: $total');
// yield loading state here
}
};
final result = await _apiService.updateProfilePicture(
event.pictureFile,
progressCallback,
);
if (result.success) {
yield UploadProfileSuccessfulState();
} else {
yield UploadProfileFailedState(error: result.parseAllErrors());
}
}
}```
thanks
Hi @payam-zahedi 馃憢
Thanks for opening an issue!
In that case I would recommend adding an event to the bloc from within the callback so that it can be processed asynchronously.
Stream<ProfilePictureState> mapEventToState(
ProfilePictureEvent event,
) async* {
if (event is UploadProfilePicture) {
final ProgressCallback progressCallback = (count, total) {
logDebug(value: 'count: $count, total: $total');
add(UploadProgressChanged(count/total));
}
};
final result = await _apiService.updateProfilePicture(
event.pictureFile,
progressCallback,
);
if (result.success) {
yield UploadProfileSuccessfulState();
} else {
yield UploadProfileFailedState(error: result.parseAllErrors());
}
}
}
@felangel thanks for your answer.
this is a good idea, but I found another way that maybe be more useful for my situation.
please check the below code and tell me your suggestion if it's possible for you.
```@override
Stream
ProfilePictureEvent event,
) async* {
if (event is UploadProfilePicture) {
StreamController
controller.add(
UploadProfileLoadingState(uploadPercentage: 0),
);
final ProgressCallback progressCallback = (count, total) {
logDebug(value: 'count: $count, total: $total');
logDebug(value: 'percent: ${(count / total * 100)}');
if( total >= -1 ){
controller.add(
UploadProfileLoadingState(uploadPercentage: (count / total * 100)),
);
}
};
_apiService.updateProfilePicture(
event.pictureFile,
progressCallback,
).then((result){
if (result.success) {
controller.add(
UploadProfileSuccessfulState(),
);
} else {
controller.add(
UploadProfileFailedState(error: result.parseAllErrors()),
);
}
}).whenComplete((){
controller.close();
});
yield* controller.stream;
}
}```
thanks
@payam-zahedi that works too but I would argue it's more complicated and involves much more code than just adding another event to the bloc. In any case, both approaches work 馃憤
thank you @felangel . I will work on it
Just an FYI: @felangel your solution processes UploadProgressChanged events only after updateProfilePicture has finished. So I ended up using @payam-zahedi solution.
@krokyze my suggestion was
if (event is UploadProfilePicture) {
add(UploadProgessChanged(uploadPercentage: 0));
final ProgressCallback progressCallback = (count, total) {
logDebug(value: 'count: $count, total: $total');
logDebug(value: 'percent: ${(count / total * 100)}');
if( total >= -1 ) {
add(UploadProgressChanged(uploadPercentage: (count / total * 100)));
}
};
_apiService.updateProfilePicture(
event.pictureFile,
progressCallback,
).then((result){
if (result.success) {
add(UploadProfileSucceeded());
} else {
add(UploadProfileFailed(error: result.parseAllErrors()));
}
});
}
}
But both solutions should work so it's up to you which you prefer 馃憤