diff --git a/lib/src/blocs/new_task_bloc.dart b/lib/src/blocs/new_task_bloc.dart index f9dd71c..6a177e8 100644 --- a/lib/src/blocs/new_task_bloc.dart +++ b/lib/src/blocs/new_task_bloc.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:rxdart/rxdart.dart'; +import '../utils.dart' show Validators; import '../models/task_model.dart'; import '../models/user_model.dart'; import '../resources/authService.dart'; @@ -9,37 +10,38 @@ import '../resources/firestore_provider.dart'; // TODO: Add validation. -class NewTaskBloc { +class NewTaskBloc extends Object with Validators { final AuthService _auth = authService; final FirestoreProvider _firestore = firestoreProvider; final _user = BehaviorSubject(); final _eventName = BehaviorSubject(); + final _taskText = BehaviorSubject(); - String text = ''; TaskPriority priority = TaskPriority.high; //Stream getters. Observable get userModelStream => _user.stream; Observable get eventName => _eventName.stream; + Observable get taskText => + _taskText.stream.transform(validateStringNotEmpty); + Observable get submitEnabled => + Observable.combineLatest2(eventName, taskText, (a, b) => true); //Sinks getters. Function(String) get changeEventName => _eventName.sink.add; + Function(String) get changeTaskText => _taskText.sink.add; NewTaskBloc() { setCurrentUser(); } - void setText(String newText) { - text = newText; - } - void setPriority(TaskPriority newPriority) { priority = newPriority; } Future submit() { final newTask = TaskModel( - text: text, + text: _taskText.value, priority: priority, event: _eventName.value, ownerUsername: _user.value.username, @@ -55,6 +57,7 @@ class NewTaskBloc { } void dispose() { + _taskText.close(); _user.close(); _eventName.close(); } diff --git a/lib/src/screens/new_task_screen.dart b/lib/src/screens/new_task_screen.dart index 7e4baf6..76e87ec 100644 --- a/lib/src/screens/new_task_screen.dart +++ b/lib/src/screens/new_task_screen.dart @@ -41,7 +41,7 @@ class _NewTaskScreenState extends State { children: [ BigTextInput( height: 95, - onChanged: bloc.setText, + onChanged: bloc.changeTaskText, ), SizedBox( height: 15, @@ -54,15 +54,21 @@ class _NewTaskScreenState extends State { SizedBox( height: 20, ), - GradientTouchableContainer( - height: 40, - radius: 8, - isExpanded: true, - onTap: () => onSubmit(context, bloc), - child: Text( - 'Submit', - style: kSmallTextStyle, - ), + StreamBuilder( + stream: bloc.submitEnabled, + builder: (context, submitSnap) { + return GradientTouchableContainer( + height: 40, + radius: 8, + isExpanded: true, + enabled: submitSnap.hasData, + onTap: () => onSubmit(context), + child: Text( + 'Submit', + style: kSmallTextStyle, + ), + ); + }, ), ], ), @@ -127,7 +133,7 @@ class _NewTaskScreenState extends State { ); } - void onSubmit(BuildContext context, NewTaskBloc bloc) async { + void onSubmit(BuildContext context) async { await bloc.submit(); Navigator.of(context).pop(); } diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 60e466f..490d1c6 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import './models/task_model.dart'; @@ -37,3 +39,15 @@ Color getColorFromPriority(TaskPriority priority) { return Colors.white; } } + +class Validators { + final validateStringNotEmpty = StreamTransformer.fromHandlers( + handleData: (String string, EventSink sink) { + if (string.isEmpty) { + sink.addError('Text cannot be empty'); + } else { + sink.add(string); + } + }, + ); +}