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.

212 lines
5.8 KiB

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