Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Add] search for users and profile abstraction #8

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions frontend/lib/screens/home/feed.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:flutter/material.dart';

class Feed extends StatefulWidget {
Feed({Key key}) : super(key: key);

@override
FeedState createState() => FeedState();
}

class FeedState extends State<Feed> {
@override
Widget build(BuildContext context) {
return Text('feed');
}
}
38 changes: 38 additions & 0 deletions frontend/lib/screens/home/search.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:twitter/screens/main/profile/list.dart';
import 'package:twitter/services/user.dart';

class Search extends StatefulWidget {
Search({Key key}) : super(key: key);

@override
_SearchState createState() => _SearchState();
}

class _SearchState extends State<Search> {
UserService _userService = UserService();
String search = '';
@override
Widget build(BuildContext context) {
return StreamProvider.value(
value: _userService.queryByName(search),
child: Column(
children: [
Padding(
padding: EdgeInsets.all(10),
child: TextField(
onChanged: (text) {
setState(() {
search = text;
});
},
decoration: InputDecoration(hintText: 'Search...'),
),
),
ListUsers()
],
),
);
}
}
37 changes: 33 additions & 4 deletions frontend/lib/screens/main/home.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:twitter/screens/home/feed.dart';
import 'package:twitter/screens/home/search.dart';
import 'package:twitter/services/auth.dart';

class Home extends StatelessWidget {
const Home({Key key}) : super(key: key);
class Home extends StatefulWidget {
Home({Key key}) : super(key: key);

@override
_HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
final AuthService _authService = AuthService();
int _currentIndex = 0;
final List<Widget> _children = [Feed(), Search()];

void onTabPressed(int index) {
setState(() {
_currentIndex = index;
});
}

@override
Widget build(BuildContext context) {
final AuthService _authService = AuthService();
return Scaffold(
appBar: AppBar(
title: Text("Home"),
Expand All @@ -26,7 +43,8 @@ class Home extends StatelessWidget {
ListTile(
title: Text('Profile'),
onTap: () {
Navigator.pushNamed(context, '/profile');
Navigator.pushNamed(context, '/profile',
arguments: FirebaseAuth.instance.currentUser.uid);
},
),
ListTile(
Expand All @@ -38,6 +56,17 @@ class Home extends StatelessWidget {
],
),
),
bottomNavigationBar: BottomNavigationBar(
onTap: onTabPressed,
currentIndex: _currentIndex,
showSelectedLabels: false,
showUnselectedLabels: false,
items: [
BottomNavigationBarItem(icon: new Icon(Icons.home), label: 'home'),
BottomNavigationBarItem(icon: new Icon(Icons.search), label: 'search')
],
),
body: _children[_currentIndex],
);
}
}
50 changes: 50 additions & 0 deletions frontend/lib/screens/main/profile/list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:twitter/models/user.dart';

class ListUsers extends StatefulWidget {
ListUsers({Key key}) : super(key: key);

@override
_ListUsersState createState() => _ListUsersState();
}

class _ListUsersState extends State<ListUsers> {
@override
Widget build(BuildContext context) {
final users = Provider.of<List<UserModel>>(context) ?? [];

return ListView.builder(
shrinkWrap: true,
itemCount: users.length,
itemBuilder: (context, index) {
final user = users[index];
return InkWell(
onTap: () =>
Navigator.pushNamed(context, '/profile', arguments: user.id),
child: Column(
children: [
Padding(
padding: EdgeInsets.all(10),
child: Row(children: [
user.profileImageUrl != ''
? CircleAvatar(
radius: 20,
backgroundImage:
NetworkImage(user.profileImageUrl),
)
: Icon(Icons.person, size: 40),
SizedBox(width: 10),
Text(user.name)
])),
const Divider(
thickness: 1,
)
],
),
);
});
}
}
24 changes: 13 additions & 11 deletions frontend/lib/screens/main/profile/profile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@ class _ProfileState extends State<Profile> {

@override
Widget build(BuildContext context) {
final String uid = ModalRoute.of(context).settings.arguments;
return MultiProvider(
providers: [
StreamProvider.value(
value: _postService
.getPostsByUser(FirebaseAuth.instance.currentUser.uid),
value: _postService.getPostsByUser(uid),
),
StreamProvider.value(
value:
_userService.getUserInfo(FirebaseAuth.instance.currentUser.uid),
value: _userService.getUserInfo(uid),
)
],
child: Scaffold(
Expand Down Expand Up @@ -56,13 +55,16 @@ class _ProfileState extends State<Profile> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Image.network(
Provider.of<UserModel>(context)
.profileImageUrl ??
'',
height: 60,
fit: BoxFit.cover,
),
Provider.of<UserModel>(context)
.profileImageUrl !=
''
? CircleAvatar(
radius: 30,
backgroundImage: NetworkImage(
Provider.of<UserModel>(context)
.profileImageUrl),
)
: Icon(Icons.person, size: 50),
FlatButton(
onPressed: () {
Navigator.pushNamed(context, '/edit');
Expand Down
31 changes: 27 additions & 4 deletions frontend/lib/services/user.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,26 @@ import 'package:twitter/services/utils.dart';
class UserService {
UtilsService _utilsService = UtilsService();

List<UserModel> _userListFromQuerySnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map((doc) {
return UserModel(
id: doc.id,
name: doc.data()['name'] ?? '',
profileImageUrl: doc.data()['profileImageUrl'] ?? '',
bannerImageUrl: doc.data()['bannerImageUrl'] ?? '',
email: doc.data()['email'] ?? '',
);
}).toList();
}

UserModel _userFromFirebaseSnapshot(DocumentSnapshot snapshot) {
return snapshot != null
? UserModel(
id: snapshot.id,
name: snapshot.data()['name'],
profileImageUrl: snapshot.data()['profileImageUrl'],
bannerImageUrl: snapshot.data()['bannerImageUrl'],
email: snapshot.data()['email'],
name: snapshot.data()['name'] ?? '',
profileImageUrl: snapshot.data()['profileImageUrl'] ?? '',
bannerImageUrl: snapshot.data()['bannerImageUrl'] ?? '',
email: snapshot.data()['email'] ?? '',
)
: null;
}
Expand All @@ -30,6 +42,17 @@ class UserService {
.map(_userFromFirebaseSnapshot);
}

Stream<List<UserModel>> queryByName(search) {
return FirebaseFirestore.instance
.collection("users")
.orderBy("name")
.startAt([search])
.endAt([search + '\uf8ff'])
.limit(10)
.snapshots()
.map(_userListFromQuerySnapshot);
}

Future<void> updateProfile(
File _bannerImage, File _profileImage, String name) async {
String bannerImageUrl = '';
Expand Down