import 'dart:async';
import 'package:complete_advanced_flutter/presentation/common/state_renderer/state_render_impl.dart';
import 'package:rxdart/rxdart.dart';
abstract class BaseViewModel extends BaseViewModelInputs
with BaseViewModelOutputs {
StreamController _inputStateStreamController =
BehaviorSubject<FlowState>();
@override
Sink get inputState => _inputStateStreamController.sink;
@override
Stream<FlowState> get outputState =>
_inputStateStreamController.stream.map((flowState) => flowState);
@override
void dispose() {
_inputStateStreamController.close();
}
// shared variables and functions that will be used through any view model.
}
abstract class BaseViewModelInputs {
void start(); // will be called while init. of view model
void dispose(); // will be called when viewmodel dies.
Sink get inputState;
}
abstract class BaseViewModelOutputs {
Stream<FlowState> get outputState;
}
import 'dart:async';
import 'package:complete_advanced_flutter/domain/model/model.dart';
import 'package:complete_advanced_flutter/presentation/base/baseviewmodel.dart';
import 'package:complete_advanced_flutter/presentation/resources/assets_manager.dart';
import 'package:complete_advanced_flutter/presentation/resources/strings_manager.dart';
import 'package:easy_localization/easy_localization.dart';
class OnBoardingViewModel extends BaseViewModel
with OnBoardingViewModelInputs, OnBoardingViewModelOutputs {
// stream controllers
final StreamController _streamController =
StreamController<SliderViewObject>();
late final List<SliderObject> _list;
int _currentIndex = 0;
// inputs
@override
void dispose() {
_streamController.close();
}
@override
void start() {
_list = _getSliderData();
// send this slider data to our view
_postDataToView();
}
@override
int goNext() {
int nextIndex = _currentIndex++; // +1
if (nextIndex >= _list.length) {
_currentIndex = 0; // infinite loop to go to first item inside the slider
}
return _currentIndex;
}
@override
int goPrevious() {
int previousIndex = _currentIndex--; // -1
if (previousIndex == -1) {
_currentIndex =
_list.length - 1; // infinite loop to go to the length of slider list
}
return _currentIndex;
}
@override
void onPageChanged(int index) {
_currentIndex = index;
_postDataToView();
}
@override
Sink get inputSliderViewObject => _streamController.sink;
// outputs
@override
Stream<SliderViewObject> get outputSliderViewObject =>
_streamController.stream.map((slideViewObject) => slideViewObject);
// private functions
List<SliderObject> _getSliderData() => [
SliderObject(
AppStrings.onBoardingTitle1.tr(),
AppStrings.onBoardingSubTitle1.tr(),
ImageAssets.onboardingLogo1),
SliderObject(
AppStrings.onBoardingTitle2.tr(),
AppStrings.onBoardingSubTitle2.tr(),
ImageAssets.onboardingLogo2),
SliderObject(
AppStrings.onBoardingTitle3.tr(),
AppStrings.onBoardingSubTitle3.tr(),
ImageAssets.onboardingLogo3),
SliderObject(
AppStrings.onBoardingTitle4.tr(),
AppStrings.onBoardingSubTitle4.tr(),
ImageAssets.onboardingLogo4)
];
_postDataToView() {
inputSliderViewObject.add(
SliderViewObject(_list[_currentIndex], _list.length, _currentIndex));
}
}
// inputs mean the orders that our view model will recieve from our view
abstract class OnBoardingViewModelInputs {
void goNext(); // when user clicks on right arrow or swipe left.
void goPrevious(); // when user clicks on left arrow or swipe right.
void onPageChanged(int index);
Sink
get inputSliderViewObject; // this is the way to add data to the stream .. stream input
}
// outputs mean data or results that will be sent from our view model to our view
abstract class OnBoardingViewModelOutputs {
Stream<SliderViewObject> get outputSliderViewObject;
}
class SliderViewObject {
SliderObject sliderObject;
int numOfSlides;
int currentIndex;
SliderViewObject(this.sliderObject, this.numOfSlides, this.currentIndex);
}