Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce the @RxCoordinatorBloc() annotation to the rx_bloc_generator #855

Open
18 tasks
StanevPrime opened this issue Nov 5, 2024 · 2 comments
Open
18 tasks

Comments

@StanevPrime
Copy link
Member

StanevPrime commented Nov 5, 2024

As a developer I want to use @RxCoordinatorBloc() and @RxCoordinatorBroadcastState() annotations so that I have central place for all annotated states and reduce the code I need to write in the CoordinatorBloc.

ACs

  • @RxCoordinatorBloc() that generates coordinator-specific code as defined below
    • Define the new @RxCoordinatorBroadcastState() annotation in rx_bloc project
    • check if the field is annotated with @RxCoordinatorBroadcastState()
    • change the state to send data to the CoordinatorBloc
    • change the bloc to get as dependency CoordinatorBloc
    • Estimation: 3d
  • @RxCoordinatorBroadcastState() that broadcast the value of the annotated state to the coordinator bloc
    • Define the new @RxCoordinatorBloc() annotation in rx_bloc project
    • Find all annotations with @RxCoordinatorBroadcastState() within the project and get them in groups by blocName (Map <String className : List< String fieldName>>{})
    • Set up the build.yaml file to add new builder_factory
    • Add BuildController to complete the work that existing one does and adjust it to add classes for all collected in the previos point classes and statuses
    • Estimation: 7d
  • RxCoordinatorBlocProvider that enables the developer to add listeners to all annotated states
    • Estimation: 2d
  • RxBlocLoggerListener that logs the value of all annotated states for debugging purposes
    • Estimation: 2d
  • Documentation that provides information of how above classes can be utilised and why they exist.
    • Estimation: 1d

Step 1: Use the @RxCoordinatorBloc() annotation to enable coordinator-specific code generation.

The generator will scan for all @RxCoordinatorBloc() annotated blocs and will automatically generate states in the $CoordinatorBloc, such as $CoordinatorBloc.$profile.states.onProfileChanged

@RxCoordinatorBloc()
class CoordinatorBloc extends $CoordinatorBloc {}

coordinator_bloc.rxb.g.dart

abstract class _CoordinatorProfileBlocEvents {
    void setOnProfileChanged(ProfileModel model); //todo: find a better name
}

abstract class _CoordinatorProfileBlocStates {
  Stream<ProfileModel> get onProfileChanged;
}

abstract class _CoordinatorProfileBlocType extends RxBlocTypeBase {
  _CoordinatorProfileBlocEvents get events;

  _CoordinatorProfileBlocStates get states;
}

abstract class _CoordinatorProfileBloc extends RxBlocBase
    implements _CoordinatorProfileBlocEvents, _CoordinatorProfileBlocStates, _CoordinatorProfileBlocType {
  final _$setOnProfileChangedEvent = PublishSubject<ProfileModel>();
  void setOnProfileChanged(ProfileModel model) => _$setOnProfileChangedEvent.add(model);

  Stream<ProfileModel> get onProfileChanged => _$setOnProfileChangedEvent;
}

abstract class $CoordinatorBloc {
    late final _CoordinatorProfileBlocType $profile = _CoordinatorProfileBloc();
}

Step 2: Annotate the states that should be available in the coordinator bloc

abstract class ProfileBlocStates {
  @RxCoordinatorBroadcastState() // Choose better name
  Stream<ProfileModel> get onProfileChanged;
}

@RxBloc()
class ProfileBloc extends $ProfileBloc {
    ProfileBloc(CoordinatorBlocType coordinator): super(coordinator);
}

profile_bloc.rxb.g.dart

abstract class ProfileBlocType extends RxBlocTypeBase {
  ProfileBlocEvents get events;

  ProfileBlocStates get states;
}

/// $CounterBloc class - extended by the CounterBloc bloc
abstract class $ProfileBloc extends RxBlocBase
    implements ProfileBlocEvents, ProfileBlocStates, ProfileBlocType {

  $ProfileBloc(CoordinatorBlocType coordinatorBloc);

  final CoordinatorBlocType coordinatorBloc;

  late final Stream<int> _onProfileChangedState = 
 _mapToOnProfileChangedState()
    .doOnData(coordinatorBloc.$profile.events.setOnProfileChanged);

  @override
  Stream<int> get onProfileChanged => _onProfileChangedState;
  ...
}

Use cases

Use case 1: Use state listeners for debugging purposes through logs

class AppDependencies{

  late List<SingleChildWidget> providers = [
     ...
     _coordinatorBlocs,
  ];

  List<SingleChildWidget> get _coordinatorBlocs => [
        RxCoordinatorBlocProvider<CoordinatorBlocType>(
          create: (context) => CoordinatorBloc(),
          listeners: (bloc) => [
              // The states of all annotated blocs will be printed for debugging purposes.
              // Example: Coordinator: profile.onProfileChanged: {name: "Georgi Stanev"}
              if (kDebugMode) RxBlocLoggerListener(bloc), 
          ],
        ),
      ];
}

Use case 2: Use the generated states in the other blocs

@RxBloc()
class DashboardBloc extends $DashboardBloc {
    DashboardBloc(this._coordinatorBloc);

    /// The DashboardBloc can listen for the following state:  _coordinator.$profile.states.onProfileChanged
    final CoordinatorBlocType _coordinator
}
@RomanovaPrime
Copy link
Contributor

While investigating in this task I found a few points to be taken into consideration:

  • Ensure that one state will not be annotated with both @RxBlocIgnoreState() and @RxCoordinatorBroadcastState() annotations;
  • Ensure that one bloc will not be annotated with both @RxBloc() and @RxCoordinatorBloc() annotations;
  • Ensure that when we have a state, annotated with @RxCoordinatorBroadcastState(), there is at least one bloc in the project, annotated with @ RxCoordinatorBloc()
  • Think of adding abstraction for the coordinatos (as RxCoordinatorBlocBase or CoordinatorFeatureBlocType) to be able to depend on abstraction, not on implementation in classes with states, annotated with @RxCoordinatorBroadcastState()

@RomanovaPrime
Copy link
Contributor

For now, this task will be put on hold. Since its implementation might coincide with the production release of macros, we likely won’t have the opportunity to use it before reworking the entire package to incorporate macros.

@StanevPrime StanevPrime removed the status in rx_bloc Nov 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

When branches are created from issues, their pull requests are automatically linked.

2 participants