Skip to content

Instantly share code, notes, and snippets.

View JulianBissekkou's full-sized avatar

Julian Bissekkou JulianBissekkou

View GitHub Profile
typedef Widget EmptyBuilder();
typedef Widget Builder<T>(T state);
typedef R Mapper<R, S>(S state);
typedef void Handler<T>(T event);
abstract class ViewModelWidgetState<W extends StatefulWidget,
S extends Cloneable<S>, VM extends StateViewModel<S>> extends State<W> {
final List<StreamSubscription> _subscriptionsList =
List<StreamSubscription>();
import 'dart:async';
import 'package:meta/meta.dart';
import 'package:timecoder_common/logic/view_model/state_holder.dart';
abstract class StateViewModel<T extends Cloneable<T>> {
final List<StreamSubscription> _streamDisposeBag = List();
final StateHolder<T> _stateHolder;
import 'dart:async';
import 'package:rxdart/rxdart.dart';
import 'package:rxdart/subjects.dart';
abstract class Cloneable<T> {
T copy();
}
typedef T Reducer<T>(T state);
@immutable
class StreamWidget<T> extends StatelessWidget {
final Stream<T> stream;
final DataBuilder<T> builder;
final LoadingBuilder loadingBuilder;
final ErrorBuilder errorBuilder;
StreamWidget(
{@required this.stream,
@required this.builder,
class EmailValidator {
static bool isEmailValid(String emailInput) {
if (_containsSemicolon(emailInput)) return false;
final String _emailRegex =
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp emailRegExp = new RegExp(_emailRegex);
return emailRegExp.hasMatch(emailInput);
// using "startWith" to ensure that the combined stream emitts even though
// on of two streams did not emmited any value yet
var combinedStream = Observable.combineLatest2(
title.startWith(""),
subtitle.startWith(""),
(title, subtitle) => Pair<String, String>(title, subtitle));
new StreamBuilder<Pair<String, String>>(
stream: combinedStream,
builder: (_, snapshot) {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: StreamBuilder<String>(
stream: _viewModel.outputErrorText,
builder: (context, snapshot) {
return MyTextField(
StreamBuilder<String>(
stream: _viewModel.outputErrorText,
builder: (context, snapshot) {
return MyTextField(
controller: controller,
hintText: "Email",
errorText: snapshot.data);
}
)
class SubscriptionViewModelImpl implements SubscriptionViewModel {
var _mailTextController = StreamController<String>.broadcast();
@override
Sink get inputMailText => _mailTextController;
@override
Stream<bool> get outputIsButtonEnabled => _mailTextController.stream
.map((email) => EmailValidator.isEmailValid(email));
abstract class SubscriptionViewModel {
Sink get inputMailText;
Stream<bool> get outputIsButtonEnabled;
Stream<String> get outputErrorText;
void dispose();
}