2019-03-20 22:57:44 -06:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
2019-03-09 20:34:09 -06:00
|
|
|
import 'package:flutter/material.dart';
|
2019-03-21 00:06:56 -06:00
|
|
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
2019-03-09 20:34:09 -06:00
|
|
|
|
2019-03-11 23:55:02 -06:00
|
|
|
import '../models/task_model.dart';
|
2019-03-13 21:51:42 -06:00
|
|
|
import '../blocs/home_bloc.dart';
|
2019-03-20 22:57:44 -06:00
|
|
|
import '../widgets/home_app_bar.dart';
|
2019-03-11 23:38:00 -06:00
|
|
|
import '../widgets/task_list_tile.dart';
|
2019-03-12 21:23:35 -06:00
|
|
|
import '../widgets/loading_indicator.dart';
|
2019-03-21 00:06:56 -06:00
|
|
|
import '../widgets/gradient_touchable_container.dart';
|
2019-03-09 21:47:04 -06:00
|
|
|
|
2019-03-13 21:51:42 -06:00
|
|
|
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-03-13 21:51:42 -06:00
|
|
|
final HomeBloc bloc = HomeBloc();
|
2019-03-20 22:57:44 -06:00
|
|
|
String avatarUrl;
|
|
|
|
|
String userDisplayName;
|
2019-03-13 21:51:42 -06:00
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
initState() {
|
|
|
|
|
super.initState();
|
|
|
|
|
bloc.fetchTasks();
|
2019-03-20 22:57:44 -06:00
|
|
|
setUserAttributes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> setUserAttributes() async {
|
|
|
|
|
final url = await bloc.getUserAvatarUrl();
|
|
|
|
|
final name = await bloc.getUserDisplayName();
|
|
|
|
|
setState(() {
|
|
|
|
|
avatarUrl = url;
|
|
|
|
|
userDisplayName = name;
|
|
|
|
|
});
|
2019-03-13 21:51:42 -06:00
|
|
|
}
|
2019-03-09 21:47:04 -06:00
|
|
|
|
2019-03-09 20:34:09 -06:00
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
return Scaffold(
|
2019-03-28 00:47:05 -06:00
|
|
|
floatingActionButton: FloatingActionButton(
|
|
|
|
|
child: Icon(FontAwesomeIcons.plus),
|
|
|
|
|
backgroundColor: Color(0xFF707070),
|
|
|
|
|
onPressed: () {},
|
|
|
|
|
),
|
|
|
|
|
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
2019-03-20 22:57:44 -06:00
|
|
|
appBar: HomeAppBar(
|
|
|
|
|
avatarUrl: avatarUrl,
|
|
|
|
|
subtitle: 'Hello $userDisplayName!',
|
2019-03-09 20:34:09 -06:00
|
|
|
),
|
2019-03-20 19:02:22 -06:00
|
|
|
body: StreamBuilder(
|
|
|
|
|
stream: bloc.userTasks,
|
|
|
|
|
builder: (BuildContext context, AsyncSnapshot<List<TaskModel>> snap) {
|
|
|
|
|
if (!snap.hasData) {
|
|
|
|
|
return Center(
|
|
|
|
|
child: LoadingIndicator(),
|
2019-03-12 21:23:35 -06:00
|
|
|
);
|
2019-03-20 19:02:22 -06:00
|
|
|
}
|
2019-03-21 00:06:56 -06:00
|
|
|
return Stack(
|
|
|
|
|
overflow: Overflow.visible,
|
|
|
|
|
children: <Widget>[
|
2019-03-27 15:52:16 -06:00
|
|
|
buildTasksList(snap.data),
|
2019-03-21 00:32:00 -06:00
|
|
|
// This container is needed to make it seem like the search box is
|
|
|
|
|
// part of the app bar.
|
2019-03-21 00:06:56 -06:00
|
|
|
Container(
|
|
|
|
|
height: _searchBoxHeight / 2,
|
|
|
|
|
width: double.infinity,
|
|
|
|
|
color: Theme.of(context).cardColor,
|
|
|
|
|
),
|
|
|
|
|
buildSearchBox(),
|
|
|
|
|
],
|
2019-03-20 19:02:22 -06:00
|
|
|
);
|
|
|
|
|
},
|
2019-03-12 21:23:35 -06:00
|
|
|
),
|
2019-03-09 20:34:09 -06:00
|
|
|
);
|
|
|
|
|
}
|
2019-03-13 21:51:42 -06:00
|
|
|
|
2019-03-27 15:52:16 -06:00
|
|
|
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),
|
|
|
|
|
),
|
|
|
|
|
padding: EdgeInsets.only(bottom: 12),
|
|
|
|
|
))
|
2019-03-28 00:47:05 -06:00
|
|
|
.toList()
|
|
|
|
|
..add(Container(height: 70)),
|
2019-03-27 15:52:16 -06:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-21 00:06:56 -06:00
|
|
|
Widget buildSearchBox() {
|
|
|
|
|
return Row(
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
Spacer(flex: 1),
|
|
|
|
|
Expanded(
|
|
|
|
|
flex: 8,
|
|
|
|
|
child: GradientTouchableContainer(
|
|
|
|
|
radius: _searchBoxHeight / 2,
|
|
|
|
|
height: _searchBoxHeight,
|
|
|
|
|
shadow: BoxShadow(
|
|
|
|
|
color: Color(0x20FFFFFF),
|
|
|
|
|
offset: Offset(0, 3),
|
|
|
|
|
blurRadius: 6,
|
|
|
|
|
spreadRadius: 1,
|
|
|
|
|
),
|
|
|
|
|
child: Row(
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
SizedBox(
|
|
|
|
|
width: 10,
|
|
|
|
|
),
|
|
|
|
|
Icon(
|
|
|
|
|
FontAwesomeIcons.sistrix,
|
|
|
|
|
color: Colors.white,
|
|
|
|
|
),
|
|
|
|
|
SizedBox(
|
|
|
|
|
width: 8,
|
|
|
|
|
),
|
|
|
|
|
Expanded(
|
|
|
|
|
child: TextField(
|
|
|
|
|
decoration: InputDecoration(
|
|
|
|
|
border: InputBorder.none,
|
|
|
|
|
hintText: 'Search...',
|
|
|
|
|
hintStyle: TextStyle(
|
|
|
|
|
fontSize: 16,
|
|
|
|
|
color: Colors.white,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
cursorColor: Colors.white,
|
|
|
|
|
scrollPadding: EdgeInsets.zero,
|
|
|
|
|
style: TextStyle(
|
|
|
|
|
fontSize: 16,
|
|
|
|
|
color: Colors.white,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
Spacer(flex: 1),
|
|
|
|
|
],
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-13 21:51:42 -06:00
|
|
|
@override
|
|
|
|
|
void dispose() {
|
|
|
|
|
bloc.dispose();
|
|
|
|
|
super.dispose();
|
|
|
|
|
}
|
2019-03-09 20:34:09 -06:00
|
|
|
}
|