Encrypted messaging app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
5.6 KiB

  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_dotenv/flutter_dotenv.dart';
  3. import 'package:http/http.dart' as http;
  4. import '/models/conversations.dart';
  5. import '/models/friends.dart';
  6. import '/models/my_profile.dart';
  7. import '/utils/storage/conversations.dart';
  8. import '/utils/storage/friends.dart';
  9. import '/utils/storage/messages.dart';
  10. import '/utils/storage/session_cookie.dart';
  11. import '/views/main/conversation/list.dart';
  12. import '/views/main/friend/list.dart';
  13. import '/views/main/profile/profile.dart';
  14. class Home extends StatefulWidget {
  15. const Home({Key? key}) : super(key: key);
  16. @override
  17. State<Home> createState() => _HomeState();
  18. }
  19. class _HomeState extends State<Home> {
  20. List<Conversation> conversations = [];
  21. List<Friend> friends = [];
  22. List<Friend> friendRequests = [];
  23. MyProfile profile = MyProfile(
  24. id: '',
  25. username: '',
  26. );
  27. bool isLoading = true;
  28. int _selectedIndex = 0;
  29. List<Widget> _widgetOptions = <Widget>[
  30. const ConversationList(conversations: [], friends: []),
  31. FriendList(friends: const [], friendRequests: const [], callback: () {}),
  32. Profile(
  33. profile: MyProfile(
  34. id: '',
  35. username: '',
  36. )
  37. ),
  38. ];
  39. @override
  40. Widget build(BuildContext context) {
  41. return WillPopScope(
  42. onWillPop: () async => false,
  43. child: isLoading ? loading() : Scaffold(
  44. body: _widgetOptions.elementAt(_selectedIndex),
  45. bottomNavigationBar: isLoading ? const SizedBox.shrink() : BottomNavigationBar(
  46. currentIndex: _selectedIndex,
  47. onTap: _onItemTapped,
  48. selectedItemColor: Theme.of(context).primaryColor,
  49. unselectedItemColor: Theme.of(context).hintColor,
  50. selectedLabelStyle: const TextStyle(fontWeight: FontWeight.w600),
  51. unselectedLabelStyle: const TextStyle(fontWeight: FontWeight.w600),
  52. type: BottomNavigationBarType.fixed,
  53. items: const [
  54. BottomNavigationBarItem(
  55. icon: Icon(Icons.message),
  56. label: 'Chats',
  57. ),
  58. BottomNavigationBarItem(
  59. icon: Icon(Icons.group_work),
  60. label: 'Friends',
  61. ),
  62. BottomNavigationBarItem(
  63. icon: Icon(Icons.account_box),
  64. label: 'Profile',
  65. ),
  66. ],
  67. ),
  68. ),
  69. );
  70. }
  71. Future<bool> checkLogin() async {
  72. bool isLoggedIn = false;
  73. try {
  74. isLoggedIn = await MyProfile.isLoggedIn();
  75. } catch (Exception) {
  76. Navigator.pushNamedAndRemoveUntil(context, '/landing', ModalRoute.withName('/landing'));
  77. return false;
  78. }
  79. if (!isLoggedIn) {
  80. await MyProfile.logout();
  81. Navigator.pushNamedAndRemoveUntil(context, '/landing', ModalRoute.withName('/landing'));
  82. return false;
  83. }
  84. int statusCode = 200;
  85. try {
  86. var resp = await http.get(
  87. Uri.parse('${dotenv.env["SERVER_URL"]}api/v1/auth/check'),
  88. headers: {
  89. 'cookie': await getSessionCookie(),
  90. }
  91. );
  92. statusCode = resp.statusCode;
  93. } catch(SocketException) {
  94. if (await MyProfile.isLoggedIn()) {
  95. return true;
  96. }
  97. }
  98. if (isLoggedIn && statusCode == 200) {
  99. return true;
  100. }
  101. MyProfile.logout();
  102. Navigator.pushNamedAndRemoveUntil(context, '/landing', ModalRoute.withName('/landing'));
  103. return false;
  104. }
  105. @override
  106. void initState() {
  107. updateData();
  108. super.initState();
  109. }
  110. Widget loading() {
  111. return Stack(
  112. children: <Widget>[
  113. const Opacity(
  114. opacity: 0.1,
  115. child: ModalBarrier(dismissible: false, color: Colors.black),
  116. ),
  117. Center(
  118. child: Column(
  119. mainAxisSize: MainAxisSize.max,
  120. mainAxisAlignment: MainAxisAlignment.center,
  121. children: const <Widget> [
  122. CircularProgressIndicator(),
  123. SizedBox(height: 25),
  124. Text('Loading...'),
  125. ],
  126. )
  127. ),
  128. ]
  129. );
  130. }
  131. void updateData() async {
  132. if (!await checkLogin()) {
  133. return;
  134. }
  135. await updateFriends();
  136. await updateConversations();
  137. await updateMessageThreads();
  138. conversations = await getConversations();
  139. friends = await getFriends(accepted: true);
  140. friendRequests = await getFriends(accepted: false);
  141. profile = await MyProfile.getProfile();
  142. setState(() {
  143. _widgetOptions = <Widget>[
  144. ConversationList(
  145. conversations: conversations,
  146. friends: friends,
  147. ),
  148. FriendList(
  149. friends: friends,
  150. friendRequests: friendRequests,
  151. callback: reinitDatabaseRecords,
  152. ),
  153. Profile(profile: profile),
  154. ];
  155. isLoading = false;
  156. });
  157. }
  158. Future<void> reinitDatabaseRecords() async {
  159. conversations = await getConversations();
  160. friends = await getFriends(accepted: true);
  161. friendRequests = await getFriends(accepted: false);
  162. profile = await MyProfile.getProfile();
  163. setState(() {
  164. _widgetOptions = <Widget>[
  165. ConversationList(
  166. conversations: conversations,
  167. friends: friends,
  168. ),
  169. FriendList(
  170. friends: friends,
  171. friendRequests: friendRequests,
  172. callback: reinitDatabaseRecords,
  173. ),
  174. Profile(profile: profile),
  175. ];
  176. isLoading = false;
  177. });
  178. }
  179. void _onItemTapped(int index) async {
  180. await reinitDatabaseRecords();
  181. setState(() {
  182. _selectedIndex = index;
  183. });
  184. }
  185. }