Deleted the CurrentSelectionService and moved to route parameters
This commit is contained in:
parent
b39a490384
commit
dd13cebb80
9 changed files with 80 additions and 87 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'screens/event_screen.dart';
|
||||||
import 'screens/home_screen.dart';
|
import 'screens/home_screen.dart';
|
||||||
import 'screens/initial_loading_screen.dart';
|
import 'screens/initial_loading_screen.dart';
|
||||||
import 'screens/login_screen.dart';
|
import 'screens/login_screen.dart';
|
||||||
|
|
@ -49,6 +50,7 @@ class App extends StatelessWidget {
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return TaskScreen(
|
return TaskScreen(
|
||||||
isEdit: true,
|
isEdit: true,
|
||||||
|
taskId: routeTokens[1],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -58,6 +60,14 @@ class App extends StatelessWidget {
|
||||||
return NewImageScreen();
|
return NewImageScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} else if (routeTokens.first == 'event') {
|
||||||
|
return MaterialPageRoute(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return EventScreen(
|
||||||
|
eventName: routeTokens[1],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Default route.
|
// Default route.
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
import '../resources/firestore_provider.dart';
|
import '../resources/firestore_provider.dart';
|
||||||
import '../resources/firebase_storage_provider.dart';
|
import '../resources/firebase_storage_provider.dart';
|
||||||
import '../services/current_selection_service.dart';
|
|
||||||
|
|
||||||
/// A business logic component that manages the state for an event screen.
|
/// A business logic component that manages the state for an event screen.
|
||||||
class EventBloc {
|
class EventBloc {
|
||||||
/// An instance of the current selection service.
|
/// The name of the event being shown.
|
||||||
final CurrentSelectionService _selectionService = currentSelectionService;
|
final String eventName;
|
||||||
|
EventBloc({
|
||||||
/// The name of the event that's currently selected.
|
@required this.eventName,
|
||||||
///
|
});
|
||||||
/// Read only.
|
|
||||||
String get selectedEventName => _selectionService.event.name;
|
|
||||||
|
|
||||||
/// Fetches the tasks for the current user that a part of the currently
|
/// Fetches the tasks for the current user that a part of the currently
|
||||||
/// selected event.
|
/// selected event.
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import 'package:rxdart/rxdart.dart';
|
||||||
import '../models/task_model.dart';
|
import '../models/task_model.dart';
|
||||||
import '../resources/firestore_provider.dart';
|
import '../resources/firestore_provider.dart';
|
||||||
import '../services/auth_service.dart';
|
import '../services/auth_service.dart';
|
||||||
import '../services/current_selection_service.dart';
|
|
||||||
|
|
||||||
export '../services/auth_service.dart' show FirebaseUser;
|
export '../services/auth_service.dart' show FirebaseUser;
|
||||||
|
|
||||||
|
|
@ -19,9 +18,6 @@ class HomeBloc {
|
||||||
/// An instance of the firebase repository.
|
/// An instance of the firebase repository.
|
||||||
final FirestoreProvider _firestore = firestoreProvider;
|
final FirestoreProvider _firestore = firestoreProvider;
|
||||||
|
|
||||||
/// An instance of the current task service.
|
|
||||||
final CurrentSelectionService _selectionService = currentSelectionService;
|
|
||||||
|
|
||||||
/// A subject of list of task model.
|
/// A subject of list of task model.
|
||||||
final _tasks = BehaviorSubject<List<TaskModel>>();
|
final _tasks = BehaviorSubject<List<TaskModel>>();
|
||||||
|
|
||||||
|
|
@ -113,19 +109,6 @@ class HomeBloc {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the global selected task.
|
|
||||||
void updateSelectedTask(TaskModel task) {
|
|
||||||
_selectionService.updateSelectedTask(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updated the global selected event.
|
|
||||||
void updateSelectedEvent(TaskModel task) async {
|
|
||||||
final userModel = await _auth.getCurrentUserModel();
|
|
||||||
final event =
|
|
||||||
await _firestore.getEvent(userModel.id, eventName: task.event);
|
|
||||||
_selectionService.updateSelectedEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the serach box text.
|
/// Updates the serach box text.
|
||||||
void updateSearchBoxText(String newText) {
|
void updateSearchBoxText(String newText) {
|
||||||
_searchBoxText.add(newText);
|
_searchBoxText.add(newText);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import '../models/task_model.dart';
|
||||||
import '../models/user_model.dart';
|
import '../models/user_model.dart';
|
||||||
import '../resources/firestore_provider.dart';
|
import '../resources/firestore_provider.dart';
|
||||||
import '../services/auth_service.dart';
|
import '../services/auth_service.dart';
|
||||||
import '../services/current_selection_service.dart';
|
|
||||||
|
|
||||||
/// Business logic component that manages the state for the task screen.
|
/// Business logic component that manages the state for the task screen.
|
||||||
class TaskBloc extends Object with Validators {
|
class TaskBloc extends Object with Validators {
|
||||||
|
|
@ -17,19 +16,24 @@ class TaskBloc extends Object with Validators {
|
||||||
/// An instance of the firebase repository.
|
/// An instance of the firebase repository.
|
||||||
final FirestoreProvider _firestore = firestoreProvider;
|
final FirestoreProvider _firestore = firestoreProvider;
|
||||||
|
|
||||||
/// An instance of the current task service.
|
|
||||||
final CurrentSelectionService _selectionService = currentSelectionService;
|
|
||||||
|
|
||||||
/// A subject of user model.
|
/// A subject of user model.
|
||||||
|
///
|
||||||
|
/// Needed to access the username of the owner of the task.
|
||||||
final _user = BehaviorSubject<UserModel>();
|
final _user = BehaviorSubject<UserModel>();
|
||||||
|
|
||||||
/// A subject of task event name.
|
/// A subject of task event name.
|
||||||
|
///
|
||||||
|
/// Only needed if in edit mode. This will receive updates when the task to be
|
||||||
|
/// edited is fetched.
|
||||||
final _eventName = BehaviorSubject<String>();
|
final _eventName = BehaviorSubject<String>();
|
||||||
|
|
||||||
/// A subject of task text.
|
/// A subject of task text.
|
||||||
final _taskText = BehaviorSubject<String>();
|
final _taskText = BehaviorSubject<String>();
|
||||||
|
|
||||||
/// A subject of the text of the current global task.
|
/// A subject of the text of the current global task.
|
||||||
|
///
|
||||||
|
/// Only needed if in edit mode. This will receive updates when the task to be
|
||||||
|
/// edited is fetched.
|
||||||
final _textInitialValue = BehaviorSubject<String>();
|
final _textInitialValue = BehaviorSubject<String>();
|
||||||
|
|
||||||
/// The priority of the current task.
|
/// The priority of the current task.
|
||||||
|
|
@ -37,10 +41,10 @@ class TaskBloc extends Object with Validators {
|
||||||
|
|
||||||
/// The id of the current task.
|
/// The id of the current task.
|
||||||
///
|
///
|
||||||
/// Only to be used if editing an existing task.
|
/// Only needed if in edit mode. Not needed by the UI.
|
||||||
String taskId;
|
final String taskId;
|
||||||
|
|
||||||
//Stream getters.
|
// Stream getters.
|
||||||
/// An observable of the current user model.
|
/// An observable of the current user model.
|
||||||
Observable<UserModel> get userModelStream => _user.stream;
|
Observable<UserModel> get userModelStream => _user.stream;
|
||||||
|
|
||||||
|
|
@ -48,14 +52,20 @@ class TaskBloc extends Object with Validators {
|
||||||
Observable<String> get eventName => _eventName.stream;
|
Observable<String> get eventName => _eventName.stream;
|
||||||
|
|
||||||
/// An observable of the current task text.
|
/// An observable of the current task text.
|
||||||
|
///
|
||||||
|
/// Emits an error if the string added is empty.
|
||||||
Observable<String> get taskText =>
|
Observable<String> get taskText =>
|
||||||
_taskText.stream.transform(validateStringNotEmpty);
|
_taskText.stream.transform(validateStringNotEmpty);
|
||||||
|
|
||||||
/// An observable of the submit enabled flag.
|
/// An observable of the submit enabled flag.
|
||||||
|
///
|
||||||
|
/// Only emits true when an event is selected and the task text is not empty.
|
||||||
Observable<bool> get submitEnabled =>
|
Observable<bool> get submitEnabled =>
|
||||||
Observable.combineLatest2(eventName, taskText, (a, b) => true);
|
Observable.combineLatest2(eventName, taskText, (a, b) => true);
|
||||||
|
|
||||||
/// An observable of the text of the global selected task.
|
/// An observable of the text of the global selected task.
|
||||||
|
///
|
||||||
|
/// Only needed in edit mode.
|
||||||
Observable<String> get textInitialvalue => _textInitialValue.stream;
|
Observable<String> get textInitialvalue => _textInitialValue.stream;
|
||||||
|
|
||||||
//Sinks getters.
|
//Sinks getters.
|
||||||
|
|
@ -65,7 +75,7 @@ class TaskBloc extends Object with Validators {
|
||||||
///Changes the current task text.
|
///Changes the current task text.
|
||||||
Function(String) get changeTaskText => _taskText.sink.add;
|
Function(String) get changeTaskText => _taskText.sink.add;
|
||||||
|
|
||||||
TaskBloc() {
|
TaskBloc({this.taskId}) {
|
||||||
setCurrentUser();
|
setCurrentUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +86,6 @@ class TaskBloc extends Object with Validators {
|
||||||
|
|
||||||
//TODO: Figure out how to update the event and user properties if needed.
|
//TODO: Figure out how to update the event and user properties if needed.
|
||||||
// as in the number of pending high tasks for example.
|
// as in the number of pending high tasks for example.
|
||||||
|
|
||||||
/// Saves or updates the current task in the database.
|
/// Saves or updates the current task in the database.
|
||||||
Future<void> submit(isEdit) {
|
Future<void> submit(isEdit) {
|
||||||
if (isEdit) {
|
if (isEdit) {
|
||||||
|
|
@ -105,17 +114,11 @@ class TaskBloc extends Object with Validators {
|
||||||
|
|
||||||
/// Grabs the data from the current global task and pipes it to the local
|
/// Grabs the data from the current global task and pipes it to the local
|
||||||
/// streams.
|
/// streams.
|
||||||
void populateWithCurrentTask() {
|
void populateWithCurrentTask() async {
|
||||||
// We only want the task that was just selected and stop listening
|
final task = await _firestore.getTask(taskId);
|
||||||
// after receiving it.
|
_textInitialValue.sink.add(task.text);
|
||||||
_selectionService.task.take(1).listen(
|
changeEventName(task.event);
|
||||||
(TaskModel task) {
|
changeTaskText(task.text);
|
||||||
_textInitialValue.sink.add(task.text);
|
|
||||||
changeEventName(task.event);
|
|
||||||
changeTaskText(task.text);
|
|
||||||
taskId = task.id;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ class FirestoreProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a Stream of a single task from an id.
|
/// Returns a Stream of a single task from an id.
|
||||||
Observable<TaskModel> getTask(String id) {
|
Observable<TaskModel> getTaskObservable(String id) {
|
||||||
final mappedStream =
|
final mappedStream =
|
||||||
_firestore.collection('tasks').document(id).snapshots().map(
|
_firestore.collection('tasks').document(id).snapshots().map(
|
||||||
(DocumentSnapshot snapshot) {
|
(DocumentSnapshot snapshot) {
|
||||||
|
|
@ -143,6 +143,16 @@ class FirestoreProvider {
|
||||||
return Observable(mappedStream);
|
return Observable(mappedStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: Add tests for this method.
|
||||||
|
/// Returns a task from an id.
|
||||||
|
Future<TaskModel> getTask(String id) async {
|
||||||
|
final documentSnapshot = await _firestore.document('tasks/$id').get();
|
||||||
|
return TaskModel.fromFirestore(
|
||||||
|
documentSnapshot.data,
|
||||||
|
id: documentSnapshot.documentID,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Deletes a task from firestore.
|
/// Deletes a task from firestore.
|
||||||
Future<void> deleteTask(String id) async {
|
Future<void> deleteTask(String id) async {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,28 @@ import '../blocs/event_bloc.dart';
|
||||||
import '../widgets/custom_app_bar.dart';
|
import '../widgets/custom_app_bar.dart';
|
||||||
|
|
||||||
class EventScreen extends StatefulWidget {
|
class EventScreen extends StatefulWidget {
|
||||||
|
/// The name of the event this screenn is showing.
|
||||||
|
final String eventName;
|
||||||
|
|
||||||
|
EventScreen({
|
||||||
|
@required this.eventName,
|
||||||
|
});
|
||||||
|
|
||||||
_EventScreenState createState() => _EventScreenState();
|
_EventScreenState createState() => _EventScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _EventScreenState extends State<EventScreen> {
|
class _EventScreenState extends State<EventScreen> {
|
||||||
final EventBloc bloc = EventBloc();
|
EventBloc bloc;
|
||||||
|
|
||||||
|
initState() {
|
||||||
|
super.initState();
|
||||||
|
bloc = EventBloc(eventName: widget.eventName);
|
||||||
|
}
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: '',
|
title: widget.eventName,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,11 +93,12 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
task: task,
|
task: task,
|
||||||
onDone: () => bloc.markTaskAsDone(task),
|
onDone: () => bloc.markTaskAsDone(task),
|
||||||
onEventPressed: () {
|
onEventPressed: () {
|
||||||
bloc.updateSelectedEvent(task);
|
// Include the event name in the route.
|
||||||
|
Navigator.of(context).pushNamed('event/${task.event}');
|
||||||
},
|
},
|
||||||
onEditPressed: () {
|
onEditPressed: () {
|
||||||
bloc.updateSelectedTask(task);
|
// Include the id of the task to be edited in the route.
|
||||||
Navigator.of(context).pushNamed('editTask/');
|
Navigator.of(context).pushNamed('editTask/${task.id}');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.only(bottom: 12),
|
padding: EdgeInsets.only(bottom: 12),
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,15 @@ class TaskScreen extends StatefulWidget {
|
||||||
/// Wether the Screen is going to edit a current task or create a new one.
|
/// Wether the Screen is going to edit a current task or create a new one.
|
||||||
final bool isEdit;
|
final bool isEdit;
|
||||||
|
|
||||||
|
/// Id of the task to edit if in edit mode.
|
||||||
|
final String taskId;
|
||||||
|
|
||||||
|
/// Creates a screen capable of editing of creating a new task.
|
||||||
|
///
|
||||||
|
/// [taskId] must be provided and cannot be null if [isEdit] is set to true.
|
||||||
TaskScreen({
|
TaskScreen({
|
||||||
this.isEdit = false,
|
this.isEdit = false,
|
||||||
|
this.taskId,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -24,11 +31,14 @@ class TaskScreen extends StatefulWidget {
|
||||||
|
|
||||||
class _TaskScreenState extends State<TaskScreen> {
|
class _TaskScreenState extends State<TaskScreen> {
|
||||||
/// An instance of this screen's bloc.
|
/// An instance of this screen's bloc.
|
||||||
final TaskBloc bloc = TaskBloc();
|
TaskBloc bloc;
|
||||||
|
|
||||||
initState() {
|
initState() {
|
||||||
if (widget.isEdit) {
|
if (widget.isEdit) {
|
||||||
|
bloc = TaskBloc(taskId: widget.taskId);
|
||||||
bloc.populateWithCurrentTask();
|
bloc.populateWithCurrentTask();
|
||||||
|
} else {
|
||||||
|
bloc = TaskBloc();
|
||||||
}
|
}
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
import 'package:rxdart/rxdart.dart';
|
|
||||||
|
|
||||||
import '../models/event_model.dart';
|
|
||||||
import '../models/task_model.dart';
|
|
||||||
|
|
||||||
/// A service that keeps track of the current user selection.
|
|
||||||
///
|
|
||||||
/// When editing a task or when navigating to an event screen, the new screens
|
|
||||||
/// can grab the user selection for this service.
|
|
||||||
class CurrentSelectionService {
|
|
||||||
/// The current selected task.
|
|
||||||
final _selectedTask = BehaviorSubject<TaskModel>();
|
|
||||||
|
|
||||||
/// The current selected event.
|
|
||||||
final _selectedEvent = BehaviorSubject<EventModel>();
|
|
||||||
|
|
||||||
/// An observable of the current selected event.
|
|
||||||
Observable<TaskModel> get task => _selectedTask.stream;
|
|
||||||
|
|
||||||
/// The current selected event.
|
|
||||||
Observable<EventModel> get event => _selectedEvent.stream;
|
|
||||||
|
|
||||||
/// Updates the current selected task.
|
|
||||||
Function(TaskModel) get updateSelectedTask => _selectedTask.sink.add;
|
|
||||||
|
|
||||||
// Updates the current selected event.
|
|
||||||
Function(EventModel) get updateSelectedEvent => _selectedEvent.sink.add;
|
|
||||||
|
|
||||||
dispose() {
|
|
||||||
_selectedEvent.close();
|
|
||||||
_selectedTask.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final currentSelectionService = CurrentSelectionService();
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue