Skip to content

Refactor Module

Mark G edited this page Jul 2, 2021 · 2 revisions

LandingView.dart

Interface

abstract class LandingView extends View with AlertViewMixin {
  // Emits on initState()
  Stream<void> get stateDidInit;

  // Begin animation and return a stream which emits
  // when the animation completes
  Stream<void> beginAnimation();
}

Implements

class LandingViewImpl extends StatefulWidget {
  const LandingViewImpl() : super(key: LandingView.viewKey);

  @override
  LandingViewImplState createState() => LandingViewImplState();
}

class LandingViewImplState
    extends ViewState<LandingViewImpl, LandingModule>
    with SingleTickerProviderStateMixin, AlertViewMixin
    implements LandingView {
  late final AnimationController _animationController = AnimationController(
    duration: LandingView.animationDuration,
    vsync: this,
  );

  late final Animation<double> _animation = CurvedAnimation(
    parent: _animationController,
    curve: Curves.easeIn,
  );

  final _animationDidFinish = BehaviorSubject<void>();

  // Implements - Begin
  @override
  final BehaviorSubject<void> stateDidInit = BehaviorSubject<void>();

  @override
  Stream<void> beginAnimation() {
    _animationController.forward();
    return _animationDidFinish;
  }
  // Implements - End

  @override
  void initState() {
    super.initState();
    stateDidInit.add(null);

    // Listen for AnimationStatus.completed
    _animationController.addStatusListener((status) {
      if (status != AnimationStatus.completed) return;
      _animationDidFinish.add(null);
    });
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return const Content();
  }
}

LandingInteractor.dart

class LandingInteractor extends Interactor {
  final AuthRepository _authRepository = locator.get();

  Stream<bool> validateAuthentication() {
    return _authRepository
        .attemptAndFetchUser()
        .asStream()
        .map((_) => _authRepository.isAuthenticated);
  }
}

LandingPresenter.dart

class LandingPresenter extends Presenter<LandingView, LandingInteractor, LandingRouter> {
  final _retry = BehaviorSubject<Exception>();

  // When ready to subscribe
  @override
  void onReady() {
    super.onReady();

    [
      // Begin animation and validate authentication when stateDidInit
      view.stateDidInit
          .flatMap(
            (_) => <Stream<dynamic>>[
              view.beginAnimation(),
              interactor.validateAuthentication(),
            ].zip(),
          )
          .map((event) => event[1] as bool),

      // Alert error and retry validate authentication
      _retry.flatMap((value) => view.alert(value)).flatMap(
            (value) => interactor.validateAuthentication(),
          ),
    ]
        .merge()
        .handleException((exception) => _retry.add(exception))
        .listen(_navigate)
        .addTo(disposeBag);
  }

  void _navigate(bool isAuthenticated) {
    switch (isAuthenticated) {
      case true:
        router.replaceToHomeScreen(context: view.context);
        break;
      case false:
        router.replaceToLoginScreen(context: view.context);
        break;
    }
  }
}
Clone this wiki locally