Code Monkey home page Code Monkey logo

finished-flutter-firebase-ddd-course's Introduction

FINISHED Domain-Driven Design + Firebase Flutter Course

Repository which is updated on a per-part basis is available here.

This project is provided "as is" and may not be updated in sync with the tutorial series. Principles will remain the same but the code might be a bit different.

Note: You need to provide your own Firebase configuration files in order to run this.

The whole accompanying tutorial series is available in ๐Ÿ‘‰ these articles & videos ๐Ÿ‘ˆ.

Find more tutorials on resocoder.com



Reso Coder
Be prepared for real app development

finished-flutter-firebase-ddd-course's People

Contributors

resodev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

finished-flutter-firebase-ddd-course's Issues

(flutter_bloc 8.0.1) Emitting streamed event in sign_in_form_bloc

Previously we've used these code blocks for reusing the same functionality to do Login and Registration

 Stream<SignInFormState> _performActionAuthFacadeWithEmailAndPassword(
    Future<Either<AuthFailure, Unit>> Function({
      required EmailAddress emailAddress,
      required Password password,
    })
        forwardedCall,
  ) async* {
    Either<AuthFailure, Unit>? failureOrSucces;

    final isEmailValid = state.emailAddress.isValid();
    final isPasswordValid = state.password.isValid();

    if (isEmailValid && isPasswordValid) {
      yield state.copyWith(
        isSubmitting: true,
        authFailureOrSuccessOption: none(),
      );
      failureOrSucces = await forwardedCall(
        emailAddress: state.emailAddress,
        password: state.password,
      );
    } else {
      //  failureOrSucces = none();
    }
    yield state.copyWith(
      isSubmitting: false,
      showErrorMessages: AutovalidateMode.always,
      authFailureOrSuccessOption: optionOf(failureOrSucces), //if null then none
      //if some then some (handy use of ternary)
    );
  }

and we accessed this method as like,

      registerWithEmailAndPasswordPressed: (e) async* {
        yield* _performActionAuthFacadeWithEmailAndPassword(
            _authFacade.registerWithEmailAndPassword);
      },
      signInWithEmailAndPasswordPressed: (e) async* {
        yield* _performActionAuthFacadeWithEmailAndPassword(
            _authFacade.signInWithEmailAndPassword);
      },

What should we do now??

Can we use method of Abstract class directly from it? Like here in first line we used IAuthFacade instead we might have used its implementation right?

`final IAuthFacade _authFacade;

SignInFormBloc(this._authFacade);

@OverRide
SignInFormState get initialState => SignInFormState.initial();

@OverRide
Stream mapEventToState(
SignInFormEvent event,
) async* {
yield* event.map(
emailChanged: (e) async* {
yield state.copyWith(
emailAddress: EmailAddress(e.emailStr),
authFailureOrSuccessOption: none(),
);
},
passwordChanged: (e) async* {
yield state.copyWith(
password: Password(e.passwordStr),
authFailureOrSuccessOption: none(),
);
},
registerWithEmailAndPasswordPressed: (e) async* {
yield* _performActionOnAuthFacadeWithEmailAndPassword(
_authFacade.registerWithEmailAndPassword,
);
},
signInWithEmailAndPasswordPressed: (e) async* {
yield* _performActionOnAuthFacadeWithEmailAndPassword(
_authFacade.signInWithEmailAndPassword,
);
},
signInWithGooglePressed: (e) async* {
yield state.copyWith(
isSubmitting: true,
authFailureOrSuccessOption: none(),
);
final failureOrSuccess = await _authFacade.signInWithGoogle();
yield state.copyWith(
isSubmitting: false,
authFailureOrSuccessOption: some(failureOrSuccess));
},
);
}`

Can we use method of Abstract class directly from it?

`final IAuthFacade _authFacade;

Like here we are doing?

SignInFormBloc(this._authFacade);

@OverRide
SignInFormState get initialState => SignInFormState.initial();

@OverRide
Stream mapEventToState(
SignInFormEvent event,
) async* {
yield* event.map(
emailChanged: (e) async* {
yield state.copyWith(
emailAddress: EmailAddress(e.emailStr),
authFailureOrSuccessOption: none(),
);
},
passwordChanged: (e) async* {
yield state.copyWith(
password: Password(e.passwordStr),
authFailureOrSuccessOption: none(),
);
},
registerWithEmailAndPasswordPressed: (e) async* {
yield* _performActionOnAuthFacadeWithEmailAndPassword(
_authFacade.registerWithEmailAndPassword,
);
},
signInWithEmailAndPasswordPressed: (e) async* {
yield* _performActionOnAuthFacadeWithEmailAndPassword(
_authFacade.signInWithEmailAndPassword,
);
},
signInWithGooglePressed: (e) async* {
yield state.copyWith(
isSubmitting: true,
authFailureOrSuccessOption: none(),
);
final failureOrSuccess = await _authFacade.signInWithGoogle();
yield state.copyWith(
isSubmitting: false,
authFailureOrSuccessOption: some(failureOrSuccess));
},
);
}`

Argument type dynamic can't be assigned to String

Hi, I tried to use the failure in signup widget but it does not bring up the map. This is my code
state .authFailureOrSuccess .fold(() {}, (either) => either.fold( (failure) { FlushbarHelper .createError( //The failure does not map because dynamic can't be converted to string but it shows its of type AuthFailure message: failure.map() ); }, (_) => {}) );
Am I missing something?

Implement DDD with riverpod

Hello, @ResoDev I have been trying to implement it with riverpod instead of the bloc library.

How can I do that?

The state management is not working for me.

My state notifier code

class SignInStateNotifier extends StateNotifier<SignInFormStates> {
  SignInStateNotifier(this._authFacade) : super(SignInFormStates.initial());

  final IAuthFacade _authFacade;

  Stream<SignInFormStates> mapEventToState(SignInFormEvents events) async* {
    yield* events.map(emailChanged: (value) async* {
      yield state.copyWith(
        emailAddress: EmailAddress(value.email),
        authFailureOrSuccess: none(),
      );
    }, passwordChanged: (value) async* {
      state.copyWith(
        password: Password(value.password),
        authFailureOrSuccess: none(),
      );
    }, signInWithEmailAndPasswordPressed: (value) async* {
      Either<AuthFailure, Unit> failureOrSuccess;
      if (state.emailAddress.isValid() && state.password.isValid()) {
        yield state.copyWith(
          isSubmitting: true,
          authFailureOrSuccess: none(),
        );
        failureOrSuccess = await _authFacade.signInWithEmailAndPassword(
          emailAddress: state.emailAddress,
          password: state.password,
        );
      }
      yield state.copyWith(
        isSubmitting: false,
        showErrorMessage: true,
        authFailureOrSuccess: optionOf(failureOrSuccess),
      );
    });
  }
}

My Form Widget

Form(
              child: Column(
                children: [
                  TextFormField(
                    autovalidateMode: AutovalidateMode.onUserInteraction,
                    onChanged: (value) => state
                        .mapEventToState(SignInFormEvents.emailChanged(value)),
                    validator: (_) => state2.emailAddress.validatedObject.fold(
                            (l) => l.maybeMap(
                            orElse: () => null,
                            invalidEmail: (_) => "Invalid Email"),
                            (_) => null),
                  ),
                  FlatButton(
                      onPressed: () {
                        state.mapEventToState(SignInFormEvents
                            .signInWithEmailAndPasswordPressed());
                      },
                      child: Text("Hello World"))
                ],
              )
            );

What mistake have I made? Please give me a solution.

Thanks in advance.

[Discussion] Project structure

First of all nice approach and some heavy work you did here. Secondly, I feel like a per feature structure would be really beneficial, since you'd get everything in one place. Having to navigate between folders when working on a specific feature is pretty annoying I'd say.

TextFormField not validating correctly

The 'validated value objects' EmailAddress and Password aren't triggering the TextFormField validation on the Sign In form correctly. The value objects are always one character input behind the actual input in the TextFormField because the validator doesn't run when the widgets are rebuilt, only when the TextFormField input changes so its always using the previous bloc state.

I think you should be retrieving the current bloc state within the validator to avoid this but maybe there is a better solution?

Need to change bodyText2 to body2

Just a typo, but downloading the package yielded a number of errors.

There are references to:
style: Theme.of(context).primaryTextTheme.bodyText2

when they should be:
style: Theme.of(context).primaryTextTheme.body2

That cleaned it up. I'd put in a pull request, but I don't know how.

Error with GetIt package

reso

I get this error while running the app. The error does not occur always. Sometimes the app runs without the error.

Error with copyWith in sign_in_form_bloc.dart

The copyWith() method doesn't work inside sign_in_form_bloc.dart.
The state doesn't change when the user types the email or password inside the UI form.
The event is properly working and contains the changed value, but I can't add this value to the state.
The state remains in initial form even after the copyWith().

Annotazione 2020-04-30 112620

The mystery of Unit Testing with Firestore

Dear Resocoder,

Your tutorial is absolutely fantastic.

However, one mystery remains, and this is unit testing the NoteRepository class and the NoteWatcherBloc, and NoteActorBloc class with Firestore.

This is therefore a "feature" request.

Your tutorial is great but can get very complex for amateur programmers. So I'm trying a test-driven approach for your domain driven tutorial, in order to solve each concern separately. I'm starting therefore with the domain and infrastructure / repository layer.

Mockito doesn't seem to be able to accept constructors and hence I can't pass a Mock instance of Firebase to the repository, or the Bloc. At the moment I'm thinking of writing an additional method in the NoteRepository which I can use to parse the Firebase Mock instance, but I'm sure you will scream at me and tell me it's not good code practice :) And the problem with the Bloc still remains.

I think a separate video would be helpful that explains how to test repository and bloc classes with Firestore.

There is nobody, that is showing this, so it seems to be a complex topic that nobody can copy, as there are no examples :).

Or all use AWS Lambda with JSON and nobody uses Firebase :)

All are showing FirebaseAuth, but nobody shows how to test repository classes and blocs. I didn't figure out how to do it yet but am working on it.

UniqueId.fromFirebaseId factory should not be in the core domain layer

I think that this factory should not exist in the core domain layer since it injects the knowledge of Firebase in that layer, which should be completely agnostic to specific technologic choices.

As I already commented here, this could be avoided by using a different approach in structuring the project.
A per-feature splitting would let to insert this UniqueId.fromFirebaseId factory in the domain layer of the auth "package" so to say, imagining to have a FirebaseUniqueId object that inherits a common/core generic UniqueId one.

JsonSerializableGenerator Generated code issue

My code generation seems to be missing the .map function for the todos in the generated file

Map<String, dynamic> _$_$_NoteDtoToJson(_$_NoteDto instance) =>
    <String, dynamic>{
      'body': instance.body,
      'color': instance.color,
      //  'todos': instance.todos, <- my code generation looks like this
      'todos': instance.todos?.map((e) => e?.toJson())?.toList(),
      'serverTimeStamp':
          const ServerTimestampConverter().toJson(instance.serverTimeStamp),
    };

What part of your code controls this generation to map it like this? My code works if I manually change this.

Running the same version of json_serializable and json_annotation as you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.