@ -0,0 +1,9 @@ | |||
package Models | |||
import "github.com/gofrs/uuid" | |||
type Friend struct { | |||
Base | |||
UserID uuid.UUID `gorm:"type:uuid;column:user_id;not null;" json:"user_id"` | |||
FriendId string `gorm:"column:friend_id;not null" json:"friend_id"` // Stored encrypted | |||
} |
@ -1,25 +1,52 @@ | |||
import 'package:flutter/material.dart'; | |||
import '/views/main/conversations_list.dart'; | |||
import '/views/main/home.dart'; | |||
import '/views/authentication/unauthenticated_landing.dart'; | |||
import '/views/authentication/login.dart'; | |||
import '/views/authentication/signup.dart'; | |||
void main() { | |||
runApp(const Home()); | |||
runApp(const MyApp()); | |||
} | |||
class Home extends StatelessWidget { | |||
const Home({Key? key}) : super(key: key); | |||
class MyApp extends StatelessWidget { | |||
const MyApp({Key? key}) : super(key: key); | |||
static const String _title = 'Envelope'; | |||
@override | |||
Widget build(BuildContext context) { | |||
return const MaterialApp( | |||
return MaterialApp( | |||
title: _title, | |||
home: Scaffold( | |||
routes: { | |||
'/home': (context) => const Home(), | |||
'/landing': (context) => const UnauthenticatedLandingWidget(), | |||
'/login': (context) => const Login(), | |||
'/signup': (context) => const Signup(), | |||
}, | |||
home: const Scaffold( | |||
backgroundColor: Colors.cyan, | |||
body: SafeArea( | |||
child: ConversationsList(), | |||
child: Home(), | |||
) | |||
) | |||
), | |||
theme: ThemeData( | |||
appBarTheme: const AppBarTheme( | |||
backgroundColor: Colors.cyan, | |||
elevation: 0, | |||
), | |||
inputDecorationTheme: const InputDecorationTheme( | |||
border: OutlineInputBorder(), | |||
focusedBorder: OutlineInputBorder(), | |||
labelStyle: TextStyle( | |||
color: Colors.white, | |||
fontSize: 30, | |||
), | |||
filled: true, | |||
fillColor: Colors.white, | |||
), | |||
), | |||
); | |||
} | |||
} |
@ -0,0 +1,9 @@ | |||
class Friend{ | |||
String id; | |||
String username; | |||
Friend({ | |||
required this.id, | |||
required this.username, | |||
}); | |||
} |
@ -0,0 +1,56 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:shared_preferences/shared_preferences.dart'; | |||
class ConversationList extends StatefulWidget { | |||
const ConversationList({Key? key}) : super(key: key); | |||
@override | |||
State<ConversationList> createState() => _ConversationListState(); | |||
} | |||
class _ConversationListState extends State<ConversationList> { | |||
final _suggestions = <String>[]; | |||
final _biggerFont = const TextStyle(fontSize: 18); | |||
Widget list() { | |||
if (_suggestions.isEmpty) { | |||
return const Center( | |||
child: Text('No Conversations'), | |||
); | |||
} | |||
return ListView.builder( | |||
itemCount: _suggestions.length, | |||
padding: const EdgeInsets.all(16.0), | |||
itemBuilder: /*1*/ (context, i) { | |||
//if (i >= _suggestions.length) { | |||
// TODO: Check for more conversations here. Remove the itemCount to use this section | |||
//_suggestions.addAll(generateWordPairs().take(10)); /*4*/ | |||
//} | |||
return Column( | |||
children: [ | |||
ListTile( | |||
title: Text( | |||
_suggestions[i], | |||
style: _biggerFont, | |||
), | |||
), | |||
const Divider(), | |||
] | |||
); | |||
}, | |||
); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
appBar: AppBar( | |||
title: const Text('Envelope'), | |||
), | |||
body: list(), | |||
); | |||
} | |||
} |
@ -1,112 +0,0 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:shared_preferences/shared_preferences.dart'; | |||
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | |||
import '/views/authentication/unauthenticated_landing.dart'; | |||
class ConversationsList extends StatefulWidget { | |||
const ConversationsList({Key? key}) : super(key: key); | |||
@override | |||
State<ConversationsList> createState() => _ConversationsListState(); | |||
} | |||
class _ConversationsListState extends State<ConversationsList> { | |||
@override | |||
void initState() { | |||
checkLogin(); | |||
super.initState(); | |||
} | |||
final _suggestions = <String>[]; | |||
final _biggerFont = const TextStyle(fontSize: 18); | |||
Future checkLogin() async { | |||
SharedPreferences preferences = await SharedPreferences.getInstance(); | |||
print(preferences.getBool('islogin')); | |||
if (preferences.getBool('islogin') != true) { | |||
setState(() { | |||
Navigator.of(context).push(MaterialPageRoute( | |||
builder: (context) => const UnauthenticatedLandingWidget(), | |||
)); | |||
}); | |||
} | |||
} | |||
Widget list() { | |||
if (_suggestions.isEmpty) { | |||
return const Center( | |||
child: Text('No Conversations'), | |||
); | |||
} | |||
return ListView.builder( | |||
itemCount: _suggestions.length, | |||
padding: const EdgeInsets.all(16.0), | |||
itemBuilder: /*1*/ (context, i) { | |||
//if (i >= _suggestions.length) { | |||
// TODO: Check for more conversations here. Remove the itemCount to use this section | |||
//_suggestions.addAll(generateWordPairs().take(10)); /*4*/ | |||
//} | |||
return Column( | |||
children: [ | |||
ListTile( | |||
title: Text( | |||
_suggestions[i], | |||
style: _biggerFont, | |||
), | |||
), | |||
const Divider(), | |||
] | |||
); | |||
}, | |||
); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return WillPopScope( | |||
onWillPop: () async => false, | |||
child: Scaffold( | |||
appBar: AppBar( | |||
title: Text('Envelope'), | |||
actions: <Widget>[ | |||
PopupMenuButton( | |||
icon: const FaIcon(FontAwesomeIcons.ellipsisVertical, color: Colors.white, size: 40), | |||
itemBuilder: (context) => [ | |||
const PopupMenuItem<int>( | |||
value: 0, | |||
child: Text("Settings"), | |||
), | |||
const PopupMenuItem<int>( | |||
value: 1, | |||
child: Text("Logout"), | |||
), | |||
], | |||
onSelected: (item) => selectedMenuItem(context, item), | |||
), | |||
], | |||
), | |||
body: list(), | |||
), | |||
); | |||
} | |||
void selectedMenuItem(BuildContext context, item) async { | |||
switch (item) { | |||
case 0: | |||
print("Settings"); | |||
break; | |||
case 1: | |||
SharedPreferences preferences = await SharedPreferences.getInstance(); | |||
preferences.setBool('islogin', false); | |||
Navigator.of(context).push(MaterialPageRoute( | |||
builder: (context) => const UnauthenticatedLandingWidget(), | |||
)); | |||
break; | |||
} | |||
} | |||
} |
@ -0,0 +1,105 @@ | |||
import 'package:flutter/material.dart'; | |||
import '/models/friends.dart'; | |||
import '/views/main/friend_list_item.dart'; | |||
class FriendList extends StatefulWidget { | |||
const FriendList({Key? key}) : super(key: key); | |||
@override | |||
State<FriendList> createState() => _FriendListState(); | |||
} | |||
class _FriendListState extends State<FriendList> { | |||
List<Friend> friends = [ | |||
Friend(id: 'abc', username: 'Test1'), | |||
Friend(id: 'abc', username: 'Test2'), | |||
Friend(id: 'abc', username: 'Test3'), | |||
Friend(id: 'abc', username: 'Test4'), | |||
Friend(id: 'abc', username: 'Test5'), | |||
]; | |||
Widget list() { | |||
if (friends.isEmpty) { | |||
return const Center( | |||
child: Text('No Friends'), | |||
); | |||
} | |||
return ListView.builder( | |||
itemCount: friends.length, | |||
shrinkWrap: true, | |||
padding: const EdgeInsets.only(top: 16), | |||
physics: const NeverScrollableScrollPhysics(), | |||
itemBuilder: (context, i) { | |||
return FriendListItem( | |||
id: friends[i].id, | |||
username: friends[i].username, | |||
); | |||
}, | |||
); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
body: SingleChildScrollView( | |||
physics: const BouncingScrollPhysics(), | |||
child: Column( | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
children: <Widget>[ | |||
SafeArea( | |||
child: Padding( | |||
padding: const EdgeInsets.only(left: 16,right: 16,top: 10), | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
children: <Widget>[ | |||
const Text("Friends",style: TextStyle(fontSize: 32,fontWeight: FontWeight.bold),), | |||
Container( | |||
padding: const EdgeInsets.only(left: 8,right: 8,top: 2,bottom: 2), | |||
height: 30, | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(30), | |||
color: Colors.pink[50], | |||
), | |||
child: Row( | |||
children: const <Widget>[ | |||
Icon(Icons.add,color: Colors.pink,size: 20,), | |||
SizedBox(width: 2,), | |||
Text("Add",style: TextStyle(fontSize: 14,fontWeight: FontWeight.bold),), | |||
], | |||
), | |||
) | |||
], | |||
), | |||
), | |||
), | |||
Padding( | |||
padding: const EdgeInsets.only(top: 16,left: 16,right: 16), | |||
child: TextField( | |||
decoration: InputDecoration( | |||
hintText: "Search...", | |||
hintStyle: TextStyle(color: Colors.grey.shade600), | |||
prefixIcon: Icon(Icons.search,color: Colors.grey.shade600, size: 20,), | |||
filled: true, | |||
fillColor: Colors.grey.shade100, | |||
contentPadding: const EdgeInsets.all(8), | |||
enabledBorder: OutlineInputBorder( | |||
borderRadius: BorderRadius.circular(20), | |||
borderSide: BorderSide( | |||
color: Colors.grey.shade100 | |||
) | |||
), | |||
), | |||
), | |||
), | |||
Padding( | |||
padding: const EdgeInsets.only(top: 16,left: 16,right: 16), | |||
child: list(), | |||
), | |||
], | |||
), | |||
), | |||
); | |||
} | |||
} |
@ -0,0 +1,56 @@ | |||
import 'package:flutter/material.dart'; | |||
class FriendListItem extends StatefulWidget{ | |||
final String id; | |||
final String username; | |||
const FriendListItem({ | |||
Key? key, | |||
required this.id, | |||
required this.username, | |||
}) : super(key: key); | |||
@override | |||
_FriendListItemState createState() => _FriendListItemState(); | |||
} | |||
class _FriendListItemState extends State<FriendListItem> { | |||
@override | |||
Widget build(BuildContext context) { | |||
return GestureDetector( | |||
onTap: (){ | |||
}, | |||
child: Container( | |||
padding: const EdgeInsets.only(left: 16,right: 16,top: 10,bottom: 10), | |||
child: Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Row( | |||
children: <Widget>[ | |||
// CircleAvatar( | |||
// backgroundImage: NetworkImage(widget.imageUrl), | |||
// maxRadius: 30, | |||
// ), | |||
//const SizedBox(width: 16), | |||
Expanded( | |||
child: Container( | |||
color: Colors.transparent, | |||
child: Column( | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
children: <Widget>[ | |||
Text(widget.username, style: const TextStyle(fontSize: 16)), | |||
const SizedBox(height: 6), | |||
//Text(widget.messageText,style: TextStyle(fontSize: 13,color: Colors.grey.shade600, fontWeight: widget.isMessageRead?FontWeight.bold:FontWeight.normal),), | |||
const Divider(), | |||
], | |||
), | |||
), | |||
), | |||
], | |||
), | |||
), | |||
], | |||
), | |||
), | |||
); | |||
} | |||
} |
@ -0,0 +1,72 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:shared_preferences/shared_preferences.dart'; | |||
import '/views/main/conversation_list.dart'; | |||
import '/views/main/friend_list.dart'; | |||
class Home extends StatefulWidget { | |||
const Home({Key? key}) : super(key: key); | |||
@override | |||
State<Home> createState() => _HomeState(); | |||
} | |||
class _HomeState extends State<Home> { | |||
@override | |||
void initState() { | |||
checkLogin(); | |||
super.initState(); | |||
} | |||
Future checkLogin() async { | |||
SharedPreferences preferences = await SharedPreferences.getInstance(); | |||
if (preferences.getBool('islogin') != true) { | |||
Navigator.pushNamedAndRemoveUntil(context, '/landing', ModalRoute.withName('/landing')); | |||
} | |||
} | |||
int _selectedIndex = 0; | |||
static const List<Widget> _widgetOptions = <Widget>[ | |||
ConversationList(), | |||
FriendList(), | |||
Text('Not Implemented'), | |||
]; | |||
void _onItemTapped(int index) { | |||
setState(() { | |||
_selectedIndex = index; | |||
}); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return WillPopScope( | |||
onWillPop: () async => false, | |||
child: Scaffold( | |||
body: _widgetOptions.elementAt(_selectedIndex), | |||
bottomNavigationBar: BottomNavigationBar( | |||
currentIndex: _selectedIndex, | |||
onTap: _onItemTapped, | |||
selectedItemColor: Colors.red, | |||
unselectedItemColor: Colors.grey.shade600, | |||
selectedLabelStyle: const TextStyle(fontWeight: FontWeight.w600), | |||
unselectedLabelStyle: const TextStyle(fontWeight: FontWeight.w600), | |||
type: BottomNavigationBarType.fixed, | |||
items: const [ | |||
BottomNavigationBarItem( | |||
icon: Icon(Icons.message), | |||
label: "Chats", | |||
), | |||
BottomNavigationBarItem( | |||
icon: Icon(Icons.group_work), | |||
label: "Friends", | |||
), | |||
BottomNavigationBarItem( | |||
icon: Icon(Icons.account_box), | |||
label: "Profile", | |||
), | |||
], | |||
), | |||
), | |||
); | |||
} | |||
} |