do_more/lib/src/screens/home_screen.dart

153 lines
4.8 KiB
Dart
Raw Normal View History

import 'dart:async';
import 'package:flutter/material.dart';
2019-03-21 00:06:56 -06:00
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import '../utils.dart' show showUploadStatusSnackBar;
import '../models/task_model.dart';
import '../blocs/home_bloc.dart';
2019-03-20 22:57:44 -06:00
import '../widgets/home_app_bar.dart';
import '../widgets/new_item_dialog_route.dart';
import '../widgets/task_list_tile.dart';
import '../widgets/loading_indicator.dart';
import '../widgets/populated_drawer.dart';
import '../widgets/search-box.dart';
class HomeScreen extends StatefulWidget {
createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
2019-03-21 00:06:56 -06:00
static const _searchBoxHeight = 50.0;
2019-04-05 15:03:04 -06:00
/// An instance of the bloc for this screen.
final HomeBloc bloc = HomeBloc();
/// The context of the scaffold being shown.
///
/// Needed for showing snackbars.
BuildContext _scaffoldContext;
/// A stream subscription to the snackbar status.
StreamSubscription _snackBarStatusSubscription;
@override
initState() {
super.initState();
bloc.fetchTasks();
initializeSnackBarListener();
}
Widget build(BuildContext context) {
return StreamBuilder(
stream: bloc.userStream,
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> userSnap) {
String userAvatarUrl, userDisplayName = '', userEmail = '';
if (userSnap.hasData) {
userAvatarUrl = userSnap.data.photoUrl;
userDisplayName = userSnap.data.displayName;
userEmail = userSnap.data.email;
}
return Scaffold(
drawer: PopulatedDrawer(
userAvatarUrl: userAvatarUrl,
userDisplayName: userDisplayName,
userEmail: userEmail,
selectedScreen: Screen.home,
),
floatingActionButton: FloatingActionButton(
child: Icon(FontAwesomeIcons.plus),
backgroundColor: Color(0xFF707070),
onPressed: () => Navigator.of(context).push(NewItemDialogRoute()),
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
appBar: HomeAppBar(
avatarUrl: userAvatarUrl,
subtitle: 'Hello $userDisplayName!',
),
body: Builder(
builder: (BuildContext context) {
_scaffoldContext = context;
return StreamBuilder(
stream: bloc.userTasks,
builder: (BuildContext context,
AsyncSnapshot<List<TaskModel>> snap) {
if (!snap.hasData) {
return Center(
child: LoadingIndicator(),
);
}
return Stack(
overflow: Overflow.visible,
children: <Widget>[
_buildTasksList(snap.data),
// This container is needed to make it seem like the search box is
// part of the app bar.
Container(
height: _searchBoxHeight / 2,
width: double.infinity,
color: Theme.of(context).cardColor,
),
SearchBox(
onChanged: bloc.updateSearchBoxText,
height: 50.0,
),
],
);
},
);
},
),
);
},
);
}
Widget _buildTasksList(List<TaskModel> tasks) {
return ListView(
padding: EdgeInsets.only(top: _searchBoxHeight + 15),
children: tasks
.map((task) => Container(
child: TaskListTile(
task: task,
onDone: () => bloc.markTaskAsDone(task),
onEventPressed: () {
// Include the event name in the route.
Navigator.of(context).pushNamed('event/${task.event}');
},
onEditPressed: () {
// Include the id of the task to be edited in the route.
Navigator.of(context).pushNamed('editTask/${task.id}');
},
),
padding: EdgeInsets.only(bottom: 12),
))
.toList()
..add(Container(height: 70)),
);
}
void initializeSnackBarListener() {
_snackBarStatusSubscription = bloc.snackBarStatus.listen((bool visible) {
if (visible) {
showUploadStatusSnackBar(
_scaffoldContext,
bloc.uploadStatus,
bloc.updateSnackBarStatus,
);
} else {
Scaffold.of(_scaffoldContext).hideCurrentSnackBar();
}
});
}
@override
void dispose() {
_snackBarStatusSubscription.cancel();
bloc.dispose();
super.dispose();
}
}