diff --git a/android/app/build.gradle b/android/app/build.gradle index c7e8500..c5c2287 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -38,7 +38,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.bicolit" - minSdkVersion 23 + minSdkVersion 21 targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/android/gradle.properties b/android/gradle.properties index 8bd86f6..1b0656c 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1 +1,2 @@ org.gradle.jvmargs=-Xmx1536M +/*org.gradle.jvmargs=-Xmx1024m*/ diff --git a/assets/images/default-profile-image.png b/assets/images/default-profile-image.png new file mode 100644 index 0000000..8e970d4 Binary files /dev/null and b/assets/images/default-profile-image.png differ diff --git a/lib/screens/edit_education.dart b/lib/screens/edit_education.dart index 392697e..0121c91 100644 --- a/lib/screens/edit_education.dart +++ b/lib/screens/edit_education.dart @@ -68,7 +68,7 @@ class _EditEducationState extends State { backgroundColor: Colors.black, actions: [ FlatButton( - child: Text("Submit", style: TextStyle(color: Colors.white),), + child: Text("Save", style: TextStyle(color: Colors.white),), onPressed: next, ), // IconButton( diff --git a/lib/screens/edit_experience.dart b/lib/screens/edit_experience.dart index b2b7ca5..963b563 100644 --- a/lib/screens/edit_experience.dart +++ b/lib/screens/edit_experience.dart @@ -64,7 +64,7 @@ class _EditExperienceState extends State { backgroundColor: Colors.black, actions: [ FlatButton( - child: Text("Submit", style: TextStyle(color: Colors.white),), + child: Text("Save", style: TextStyle(color: Colors.white),), onPressed: next, ), ], diff --git a/lib/screens/news_feed.dart b/lib/screens/news_feed.dart index 466e22a..ccaf6c1 100644 --- a/lib/screens/news_feed.dart +++ b/lib/screens/news_feed.dart @@ -1,11 +1,13 @@ import 'package:flutter/material.dart'; import 'package:localstorage/localstorage.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:date_format/date_format.dart'; import 'dart:io'; import 'package:bicolit/utils/uidata.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; - import 'package:bicolit/tools/drawer.dart'; +import 'package:bicolit/tools/label_icon.dart'; class NewsFeed extends StatefulWidget { @override @@ -13,7 +15,84 @@ class NewsFeed extends StatefulWidget { } class _NewsFeedState extends State { + GlobalKey _globalKey = GlobalKey(); + final db = Firestore.instance; final storage = LocalStorage("data"); + final _formKey = GlobalKey(); + + bool _loading = true; + RefreshController _refreshController = RefreshController(); + List _users = [], _posts = []; + + List buildList() { + return List.generate(_posts.length, (i) => + Padding( + padding: const EdgeInsets.all(8.0), + child: Card( + elevation: 2.0, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + InkWell( + onTap: () {}, + child: CircleAvatar(backgroundImage: _posts[i]["user"]["profile_image"] == null + ? AssetImage(UIData.defaultProfileImage) + : NetworkImage(_posts[i]["user"]["profile_image"])), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(_posts[i]["user"]["firstname"] + " " + _posts[i]["user"]["lastname"], style: Theme.of(context).textTheme.body1.apply(fontWeightDelta: 700)), + SizedBox(height: 5.0), + Text(_posts[i]["user"]["email"]), + ], + ), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text(_posts[i]["post"]), + ), + SizedBox(height: 10.0), + _posts[i]["images"].length == 0 ? Image.network(_posts[i]["images"][0], fit: BoxFit.cover) : Container(), + _posts[i]["images"].length == 0 ? Container() : Divider(color: Colors.grey.shade300, height: 8.0), + FittedBox( + fit: BoxFit.contain, + child: ButtonBar( + alignment: MainAxisAlignment.center, + children: [ + LabelIcon( + icon: Icons.favorite, iconColor: Colors.black, onPressed: () {}, + label: (_posts[i]["likes"].length > 0 ? _posts[i]["likes"].length : "") + "Likes", + ), + LabelIcon( + icon: Icons.comment, iconColor: Colors.black, onPressed: () {}, + label: (_posts[i]["comments"].length > 0 ? _posts[i]["comments"].length : "") + "Comments", + ), + Text( + formatDate(_posts[i]["created_at"].toDate(), [yyyy, " ", M, " ", d, " at ", h, ":", nn, " ", am]), + style: TextStyle(color: Colors.grey), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } @override initState() { @@ -22,41 +101,109 @@ class _NewsFeedState extends State { } void onMount() { - print(storage.getItem("user_data")); + fetchData(); + } + + void fetchData() async { + final QuerySnapshot users_result = await db.collection("users").getDocuments(); + final QuerySnapshot newsfeed_result = await db.collection("newsfeed").getDocuments(); + final List users_docs = users_result.documents; + final List newsfeed_docs = newsfeed_result.documents; + newsfeed_docs.forEach((nfd) { + users_docs.forEach((ud) { + if (nfd.data["creator"] == ud.documentID) + { nfd.data["user"] = ud.data; } + }); + }); + setState(() { + _users = users_docs; + _posts = newsfeed_docs; + _loading = false; + }); + _refreshController.refreshCompleted(); } Future _onBack() { - return showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text("Confirm Exit", style: TextStyle(color: Colors.white),), - content: Text("Are sure you want to exit app?", style: TextStyle(color: Colors.white),), - actions: [ - FlatButton( - child: Text("No", style: TextStyle(color: Colors.white),), - onPressed: () => Navigator.pop(context, false), - ), - FlatButton( - child: Text("Yes", style: TextStyle(color: Colors.white),), - onPressed: () => exit(0), - ), - ], - ), - ); + if (_globalKey.currentState.isDrawerOpen) { + Navigator.pop(context); + } else { + return showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text("Confirm Exit", style: TextStyle(color: Colors.white),), + content: Text("Are sure you want to exit app?", style: TextStyle(color: Colors.white),), + actions: [ + FlatButton( + child: Text("No", style: TextStyle(color: Colors.white),), + onPressed: () => Navigator.pop(context, false), + ), + FlatButton( + child: Text("Yes", style: TextStyle(color: Colors.white),), + onPressed: () => exit(0), + ), + ], + ), + ); + } } + loadScreen() => Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Image.asset( + UIData.bitLogoImage, + height: 70, + width: 70, + ), + SizedBox( height: 20.0 ), + SizedBox( + child: CircularProgressIndicator( + strokeWidth: 2.0, + valueColor: AlwaysStoppedAnimation(Colors.black), + ), + height: 17.0, + width: 17.0, + ), + SizedBox( height: 20.0 ), + ] + ); + @override Widget build(BuildContext context) { return WillPopScope( onWillPop: _onBack, - child: Scaffold( - drawer: AppDrawer(current_screen: "newsFeed"), - appBar: AppBar( - title: Text("NewsFeed"), - centerTitle: true, - ), - body: Container(), - ), + child: _loading + ? Scaffold( + body: Center( + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [loadScreen()], + ), + ), + ), + ) + : Scaffold( + key: _globalKey, + drawer: AppDrawer(current_screen: "newsFeed"), + appBar: AppBar( + title: Text("News Feed"), + centerTitle: true, + ), + body: SmartRefresher( + controller: _refreshController, + enablePullDown: true, + onRefresh: fetchData, + child: CustomScrollView( + slivers: [SliverList(delegate: SliverChildListDelegate(buildList()))], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () {}, + child: Icon(Icons.edit), + backgroundColor: Colors.black, + ), + ), ); } -} +} \ No newline at end of file diff --git a/lib/screens/profile.dart b/lib/screens/profile.dart index bde054e..4ff64a1 100644 --- a/lib/screens/profile.dart +++ b/lib/screens/profile.dart @@ -6,6 +6,7 @@ import 'package:image_picker/image_picker.dart'; import 'package:uuid/uuid.dart'; import 'dart:io'; +import 'package:bicolit/utils/uidata.dart'; import 'package:bicolit/tools/common_scaffold.dart'; class Profile extends StatefulWidget { @@ -150,7 +151,9 @@ class _ProfileState extends State { onTap: getImage, child: CircleAvatar( radius: 40.0, - backgroundImage: NetworkImage("https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png"), + backgroundImage: storage.getItem("user_data")["profile_image"] == null + ? AssetImage(UIData.defaultProfileImage) + : NetworkImage(storage.getItem("user_data")["profile_image"]), child: CircularProgressIndicator( strokeWidth: 3.0, valueColor: AlwaysStoppedAnimation(Colors.black), diff --git a/lib/tools/drawer.dart b/lib/tools/drawer.dart index 845de2c..59871cd 100644 --- a/lib/tools/drawer.dart +++ b/lib/tools/drawer.dart @@ -21,9 +21,7 @@ class _AppDrawerState extends State { WidgetsBinding.instance.addPostFrameCallback((_) => onMount()); } - void onMount() { - print(storage.getItem("user_data")); - } + void onMount() {} @override Widget build(BuildContext context) { @@ -39,7 +37,9 @@ class _AppDrawerState extends State { storage.getItem("user_data")["email"], ), currentAccountPicture: CircleAvatar( - backgroundImage: NetworkImage(storage.getItem("user_data")["profile_image"] == null ? "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png" : storage.getItem("user_data")["profile_image"]), + backgroundImage: storage.getItem("user_data")["profile_image"] == null + ? AssetImage(UIData.defaultProfileImage) + : NetworkImage(storage.getItem("user_data")["profile_image"]), ), ), ListTile( @@ -51,7 +51,7 @@ class _AppDrawerState extends State { Icons.web, color: Colors.black, ), - onTap: () { if (widget.current_screen != "newsFeed") Navigator.pushNamed(context, UIData.newsFeedRoute); }, + onTap: () { widget.current_screen == "newsFeed" ? Navigator.pop(context) : Navigator.pushNamed(context, UIData.newsFeedRoute); } ), ListTile( title: Text( @@ -62,7 +62,7 @@ class _AppDrawerState extends State { Icons.person, color: Colors.black, ), - onTap: () { Navigator.pushNamed(context, UIData.profileRoute); }, + onTap: () { widget.current_screen == "profile" ? Navigator.pop(context) : Navigator.pushNamed(context, UIData.profileRoute); }, ), ListTile( title: Text( @@ -74,6 +74,7 @@ class _AppDrawerState extends State { color: Colors.black, ), onTap: () {}, + //onTap: () { widget.current_screen == "about" ? Navigator.pop(context) : Navigator.pushNamed(context, UIData.aboutRoute); }, ), Divider( color: Colors.grey.shade300, height: 8.0, ), ListTile( diff --git a/lib/tools/label_icon.dart b/lib/tools/label_icon.dart new file mode 100644 index 0000000..f85c9a9 --- /dev/null +++ b/lib/tools/label_icon.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +class LabelIcon extends StatelessWidget { + final label; + final icon; + final iconColor; + final onPressed; + + LabelIcon( + {this.label, this.icon, this.onPressed, this.iconColor = Colors.grey}); + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () => onPressed, + child: Row( + children: [ + Icon( + icon, + color: iconColor, + ), + SizedBox( + width: 5.0, + ), + Text( + label, + style: TextStyle(fontWeight: FontWeight.w700), + ) + ], + ), + ); + } +} diff --git a/lib/utils/uidata.dart b/lib/utils/uidata.dart index cf540c6..e8fefe3 100644 --- a/lib/utils/uidata.dart +++ b/lib/utils/uidata.dart @@ -28,6 +28,7 @@ class UIData { static const String imageDir = "assets/images"; static const String bitLogoImage = "$imageDir/bit-logo.png"; static const String bitLogoTransparentImage = "$imageDir/bit-logo-transparent.png"; + static const String defaultProfileImage = "$imageDir/default-profile-image.png"; //gneric static const String error = "Error"; diff --git a/pubspec.lock b/pubspec.lock index c058b35..739b1f6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -212,6 +212,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + pull_to_refresh: + dependency: "direct main" + description: + name: pull_to_refresh + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.7" quiver: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0f090fb..4d3ae3c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,6 +23,7 @@ dependencies: image_picker: 0.4.0 uuid: ^2.0.2 progress_dialog: ^1.2.0 + pull_to_refresh: ^1.5.7 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.