Skip to content

Instantly share code, notes, and snippets.

@knollyy
Last active June 25, 2021 16:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save knollyy/817cd6011fb01bc3fed6956792fb4e87 to your computer and use it in GitHub Desktop.
Save knollyy/817cd6011fb01bc3fed6956792fb4e87 to your computer and use it in GitHub Desktop.
Social Media App
import 'package:flutter/material.dart';
cachedNetworkImage(mediaUrl) {
return Text('cached network image');
}
import 'package:flutter/material.dart';
AppBar header(context, {bool isAppTitle=false, String strTitle, disappearedBlackButton=false}) {
return AppBar(
iconTheme: IconThemeData(
color: Colors.white,
),
automaticallyImplyLeading: disappearedBlackButton ? false : true,
title: Text(
isAppTitle ? 'BuddiesGram' : strTitle,
style: TextStyle(
color: Colors.white,
fontFamily: isAppTitle ? 'Signatra' : '',
fontSize: isAppTitle ? 45.0 : 22.0,
),
),
centerTitle: true,
backgroundColor: Theme.of(context).accentColor,
);
}
import 'dart:io';
import 'package:buddiesgram/models/user.dart';
import 'package:buddiesgram/pages/CreateAccountPage.dart';
import 'package:buddiesgram/pages/NotificationsPage.dart';
import 'package:buddiesgram/pages/ProfilePage.dart';
import 'package:buddiesgram/pages/SearchPage.dart';
import 'package:buddiesgram/pages/TimeLinePage.dart';
import 'package:buddiesgram/pages/UploadPage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
final GoogleSignIn gSignIn = GoogleSignIn();
final usersReference = Firestore.instance.collection("users");
final StorageReference storageReference = FirebaseStorage.instance.ref().child("Posts Pictures");
final postsReference = Firestore.instance.collection("posts");
final activityFeedReference = Firestore.instance.collection("feed");
final commentsReference = Firestore.instance.collection("comments");
final followersReference = Firestore.instance.collection("followers");
final followingReference = Firestore.instance.collection("following");
final timelineReference = Firestore.instance.collection("timeline");
final DateTime timestamp = DateTime.now();
User currentUser;
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>
{
bool isSignedIn = false;
PageController pageController;
int getPageIndex = 0;
FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
final _scaffoldKey = GlobalKey<ScaffoldState>();
void initState(){
super.initState();
pageController = PageController();
gSignIn.onCurrentUserChanged.listen((gSigninAccount){
controlSignIn(gSigninAccount);
}, onError: (gError){
print("Error Message: " + gError);
});
gSignIn.signInSilently(suppressErrors: false).then((gSignInAccount){
controlSignIn(gSignInAccount);
}).catchError((gError){
print("Error Message: " + gError);
});
}
controlSignIn(GoogleSignInAccount signInAccount) async
{
if(signInAccount != null)
{
await saveUserInfoToFireStore();
setState(() {
isSignedIn = true;
});
configureRealTimePushNotifications();
}
else
{
setState(() {
isSignedIn = false;
});
}
}
configureRealTimePushNotifications()
{
final GoogleSignInAccount gUser = gSignIn.currentUser;
if(Platform.isIOS)
{
getIOSPermissions();
}
_firebaseMessaging.getToken().then((token){
usersReference.document(gUser.id).updateData({"androidNotificationToken": token});
});
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> msg) async
{
final String recipientId = msg["data"]["recipient"];
final String body = msg["notification"]["body"];
if(recipientId == gUser.id)
{
SnackBar snackBar = SnackBar(
backgroundColor: Colors.grey,
content: Text(body, style: TextStyle(color: Colors.black), overflow: TextOverflow.ellipsis,),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
},
);
}
getIOSPermissions()
{
_firebaseMessaging.requestNotificationPermissions(IosNotificationSettings(alert: true, badge: true, sound: true));
_firebaseMessaging.onIosSettingsRegistered.listen((settings){
print("Settings Registered : $settings");
});
}
saveUserInfoToFireStore() async {
final GoogleSignInAccount gCurrentUser = gSignIn.currentUser;
DocumentSnapshot documentSnapshot = await usersReference.document(gCurrentUser.id).get();
if(!documentSnapshot.exists){
final username = await Navigator.push(context, MaterialPageRoute(builder: (context) => CreateAccountPage()));
usersReference.document(gCurrentUser.id).setData({
"id": gCurrentUser.id,
"profileName": gCurrentUser.displayName,
"username": username,
"url": gCurrentUser.photoUrl,
"email": gCurrentUser.email,
"bio": "",
"timestamp": timestamp,
});
await followersReference.document(gCurrentUser.id).collection("userFollowers").document(gCurrentUser.id).setData({});
documentSnapshot = await usersReference.document(gCurrentUser.id).get();
}
currentUser = User.fromDocument(documentSnapshot);
}
void dispose(){
pageController.dispose();
super.dispose();
}
loginUser(){
gSignIn.signIn();
}
logoutUser(){
gSignIn.signOut();
}
whenPageChanges(int pageIndex){
setState(() {
this.getPageIndex = pageIndex;
});
}
onTapChangePage(int pageIndex){
pageController.animateToPage(pageIndex, duration: Duration(milliseconds: 400), curve: Curves.bounceInOut,);
}
Scaffold buildHomeScreen(){
return Scaffold(
key: _scaffoldKey,
body: PageView(
children: <Widget>[
TimeLinePage(gCurrentUser: currentUser,),
SearchPage(),
UploadPage(gCurrentUser: currentUser,),
NotificationsPage(),
ProfilePage(userProfileId: currentUser?.id),
],
controller: pageController,
onPageChanged: whenPageChanges,
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: CupertinoTabBar(
currentIndex: getPageIndex,
onTap: onTapChangePage,
backgroundColor: Theme.of(context).accentColor,
activeColor: Colors.white,
inactiveColor: Colors.blueGrey,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home)),
BottomNavigationBarItem(icon: Icon(Icons.search)),
BottomNavigationBarItem(icon: Icon(Icons.photo_camera, size: 37.0,)),
BottomNavigationBarItem(icon: Icon(Icons.favorite)),
BottomNavigationBarItem(icon: Icon(Icons.person)),
],
),
);
}
Scaffold buildSignInScreen(){
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [Theme.of(context).accentColor, Theme.of(context).primaryColor],
),
),
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"BuddiesGram",
style: TextStyle(fontSize: 92.0, color: Colors.white, fontFamily: "Signatra"),
),
GestureDetector(
onTap: loginUser,
child: Container(
width: 270.0,
height: 65.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/google_signin_button.png"),
fit: BoxFit.cover,
),
),
),
),
],
),
),
);
}
@override
Widget build(BuildContext context) {
if(isSignedIn)
{
return buildHomeScreen();
}
else
{
return buildSignInScreen();
}
}
}
import 'package:buddiesgram/pages/HomePage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
void main()
{
WidgetsFlutterBinding.ensureInitialized();
Firestore.instance.settings(timestampsInSnapshotsEnabled: true);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BuddiesGram',
debugShowCheckedModeBanner: false,
theme: ThemeData
(
scaffoldBackgroundColor: Colors.black,
dialogBackgroundColor: Colors.black,
primarySwatch: Colors.grey,
cardColor: Colors.white70,
accentColor: Colors.black,
),
home: HomePage(),
);
}
}
import 'package:buddiesgram/pages/PostScreenPage.dart';
import 'package:buddiesgram/widgets/PostWidget.dart';
import 'package:flutter/material.dart';
class PostTile extends StatelessWidget
{
final Post post;
PostTile(this.post);
displayFullPost(context)
{
Navigator.push(context, MaterialPageRoute(builder: (context)=>PostScreenPage(postId: post.postId, userId: post.ownerId)));
}
@override
Widget build(BuildContext context) {
return GestureDetector
(
onTap: () => displayFullPost(context),
child: Image.network(post.url),
);
}
}
import 'dart:async';
import 'package:buddiesgram/models/user.dart';
import 'package:buddiesgram/pages/CommentsPage.dart';
import 'package:buddiesgram/pages/HomePage.dart';
import 'package:buddiesgram/pages/ProfilePage.dart';
import 'package:buddiesgram/widgets/CImageWidget.dart';
import 'package:buddiesgram/widgets/ProgressWidget.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class Post extends StatefulWidget
{
final String postId;
final String ownerId;
//final String timestamp;
final dynamic likes;
final String username;
final String description;
final String location;
final String url;
Post({
this.postId,
this.ownerId,
//this.timestamp,
this.likes,
this.username,
this.description,
this.location,
this.url,
});
factory Post.fromDocument(DocumentSnapshot documentSnapshot){
return Post(
postId: documentSnapshot['postId'],
ownerId: documentSnapshot['ownerId'],
likes: documentSnapshot['likes'],
username: documentSnapshot['username'],
description: documentSnapshot['description'],
location: documentSnapshot['location'],
url: documentSnapshot['url'],
);
}
int getTotalNumberOfLikes(likes){
if(likes == null)
{
return 0;
}
int counter = 0;
likes.values.forEach((eachValue){
if(eachValue == true)
{
counter = counter + 1;
}
});
return counter;
}
@override
_PostState createState() => _PostState(
postId: this.postId,
ownerId: this.ownerId,
//timestamp: this.timestamp,
likes: this.likes,
username: this.username,
description: this.description,
location: this.location,
url: this.url,
likeCount: getTotalNumberOfLikes(this.likes),
);
}
class _PostState extends State<Post>
{
final String postId;
final String ownerId;
//final String timestamp;
Map likes;
final String username;
final String description;
final String location;
final String url;
int likeCount;
bool isLiked;
bool showHeart = false;
final String currentOnlineUserId = currentUser?.id;
_PostState({
this.postId,
this.ownerId,
//this.timestamp,
this.likes,
this.username,
this.description,
this.location,
this.url,
this.likeCount,
});
@override
Widget build(BuildContext context)
{
isLiked = (likes[currentOnlineUserId] == true);
return Padding(
padding: EdgeInsets.only(bottom: 12.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>
[
createPostHead(),
createPostPicture(),
createPostFooter(),
],
),
);
}
createPostHead(){
return FutureBuilder(
future: usersReference.document(ownerId).get(),
builder: (context, dataSnapshot){
if(!dataSnapshot.hasData)
{
return circularProgress();
}
User user = User.fromDocument(dataSnapshot.data);
bool isPostOwner = currentOnlineUserId == ownerId;
return ListTile(
leading: CircleAvatar(backgroundImage: CachedNetworkImageProvider(user.url), backgroundColor: Colors.grey,),
title: GestureDetector(
onTap: ()=> displayUserProfile(context, userProfileId: user.id),
child: Text(
user.username,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
),
subtitle: Text(location, style: TextStyle(color: Colors.white),),
trailing: isPostOwner ? IconButton(
icon: Icon(Icons.more_vert, color: Colors.white,),
onPressed: ()=> print('deleted'),
) : Text(''),
);
},
);
}
displayUserProfile(BuildContext context, {String userProfileId})
{
Navigator.push(context, MaterialPageRoute(builder: (context) => ProfilePage(userProfileId: userProfileId,)));
}
removeLike()
{
bool isNotPostOwner = currentOnlineUserId != ownerId;
if(isNotPostOwner){
activityFeedReference.document(ownerId).collection('feedItems').document(postId).get().then((document){
if(document.exists)
{
document.reference.delete();
}
});
}
}
addLike()
{
bool isNotPostOwner = currentOnlineUserId != ownerId;
if(isNotPostOwner)
{
activityFeedReference.document(ownerId).collection('feedItems').document(postId).setData({
'type': 'like',
'username': currentUser.username,
'userId': currentUser.id,
'timestamp': DateTime.now(),
'url': url,
'postId': postId,
'userProfileImage': currentUser.url,
});
}
}
controlUserLikePost(){
bool _liked = likes[currentOnlineUserId] == true;
if(_liked)
{
postsReference.document(ownerId).collection("usersPosts").document(postId).updateData({"likes.$currentOnlineUserId": false});
removeLike();
setState(() {
likeCount = likeCount -1;
isLiked = false;
likes[currentOnlineUserId] = false;
});
}
else if(!_liked)
{
postsReference.document(ownerId).collection('usersPosts').document(postId).updateData(
{'likes.$currentOnlineUserId': true});
addLike();
setState(() {
likeCount = likeCount + 1;
isLiked = true;
likes[currentOnlineUserId] = true;
showHeart = true;
});
Timer(Duration(milliseconds: 800), (){
setState(() {
showHeart = false;
});
});
}
}
createPostPicture()
{
return GestureDetector(
onDoubleTap: ()=> controlUserLikePost,
child: Stack(
alignment: Alignment.center,
children: <Widget>
[
Image.network(url),
showHeart ? Text("") : Text(''),
],
),
);
}
createPostFooter()
{
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 40.0, left: 20.0)),
GestureDetector(
onTap: ()=> controlUserLikePost(),
child: Icon(
isLiked ? Icons.favorite : Icons.favorite_border,
size: 28.0,
color: Colors.pink,
),
),
Padding(padding: EdgeInsets.only(right: 20.0)),
GestureDetector(
onTap: ()=> displayComments(context, postId: postId, ownerId: ownerId, url: url),
child: Icon(Icons.chat_bubble_outline, size: 28.0, color: Colors.white,),
),
],
),
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 20.0),
child: Text(
'$likeCount likes',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 20.0),
child: Text('$username ', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),),
),
Expanded(
child: Text(description, style: TextStyle(color: Colors.white),),
),
],
),
],
);
}
displayComments(BuildContext context, {String postId, String ownerId, String url})
{
Navigator.push(context, MaterialPageRoute(builder: (context)
{
return CommentsPage(postId: postId, postOwnerId: ownerId, postImageUrl: url,);
}
));
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
circularProgress() {
return Container(
alignment: Alignment.center,
padding: EdgeInsets.only(top: 12.0),
child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.lightGreenAccent),),
);
}
linearProgress() {
return Container(
alignment: Alignment.center,
padding: EdgeInsets.only(top: 12.0),
child: LinearProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.lightGreenAccent),),
);
}
import 'package:buddiesgram/models/user.dart';
import 'package:buddiesgram/pages/HomePage.dart';
import 'package:buddiesgram/widgets/HeaderWidget.dart';
import 'package:buddiesgram/widgets/PostWidget.dart';
import 'package:buddiesgram/widgets/ProgressWidget.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
class TimeLinePage extends StatefulWidget
{
final User gCurrentUser;
TimeLinePage({this.gCurrentUser});
@override
_TimeLinePageState createState() => _TimeLinePageState();
}
class _TimeLinePageState extends State<TimeLinePage>
{
List<Post> postsList;
List<String> followingsList = [];
final _scaffoldKey = GlobalKey<ScaffoldState>();
retrieveTimeLine() async
{
QuerySnapshot querySnapshot = await timelineReference.document(widget.gCurrentUser.id)
.collection("timelinePosts").orderBy("timestamp", descending: true).getDocuments();
List<Post> allPosts = querySnapshot.documents.map((document) => Post.fromDocument(document)).toList();
setState(() {
this.postsList = allPosts;
});
}
retrieveFollowings() async
{
QuerySnapshot querySnapshot = await followingReference.document(currentUser.id).collection("userFollowing").getDocuments();
setState(() {
followingsList = querySnapshot.documents.map((document) => document.documentID).toList();
});
}
@override
void initState() {
// TODO: implement initState
super.initState();
retrieveTimeLine();
retrieveFollowings();
}
createUserTimeLine()
{
if(postsList == null)
{
return circularProgress();
}
else if(postsList.isEmpty)
{
return Text("test");
}
else
{
return ListView(children: postsList,);
}
}
@override
Widget build(context) {
return Scaffold(
key: _scaffoldKey,
appBar: header(context, isAppTitle: true, ),
body: RefreshIndicator(child: createUserTimeLine(), onRefresh: () => retrieveTimeLine()),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment