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.

208 lines
5.7 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 ? const SizedBox.shrink() : BottomNavigationBar(
  47. currentIndex: _selectedIndex,
  48. onTap: _onItemTapped,
  49. selectedItemColor: Theme.of(context).primaryColor,
  50. unselectedItemColor: Theme.of(context).hintColor,
  51. selectedLabelStyle: const TextStyle(fontWeight: FontWeight.w600),
  52. unselectedLabelStyle: const TextStyle(fontWeight: FontWeight.w600),
  53. type: BottomNavigationBarType.fixed,
  54. items: const [
  55. BottomNavigationBarItem(
  56. icon: Icon(Icons.message),
  57. label: 'Chats',
  58. ),
  59. BottomNavigationBarItem(
  60. icon: Icon(Icons.group_work),
  61. label: 'Friends',
  62. ),
  63. BottomNavigationBarItem(
  64. icon: Icon(Icons.account_box),
  65. label: 'Profile',
  66. ),
  67. ],
  68. ),
  69. ),
  70. );
  71. }
  72. Future<bool> checkLogin() async {
  73. bool isLoggedIn = false;
  74. try {
  75. isLoggedIn = await MyProfile.isLoggedIn();
  76. } catch (Exception) {
  77. Navigator.pushNamedAndRemoveUntil(context, '/landing', ModalRoute.withName('/landing'));
  78. return false;
  79. }
  80. if (!isLoggedIn) {
  81. await MyProfile.logout();
  82. Navigator.pushNamedAndRemoveUntil(context, '/landing', ModalRoute.withName('/landing'));
  83. return false;
  84. }
  85. int statusCode = 200;
  86. try {
  87. var resp = await http.get(
  88. await MyProfile.getServerUrl('api/v1/auth/check'),
  89. headers: {
  90. 'cookie': await getSessionCookie(),
  91. }
  92. );
  93. statusCode = resp.statusCode;
  94. } catch(SocketException) {
  95. if (await MyProfile.isLoggedIn()) {
  96. return true;
  97. }
  98. }
  99. if (isLoggedIn && statusCode == 200) {
  100. return true;
  101. }
  102. MyProfile.logout();
  103. Navigator.pushNamedAndRemoveUntil(context, '/landing', ModalRoute.withName('/landing'));
  104. return false;
  105. }
  106. @override
  107. void initState() {
  108. updateData();
  109. super.initState();
  110. }
  111. Widget loading() {
  112. return Stack(
  113. children: <Widget>[
  114. const Opacity(
  115. opacity: 0.1,
  116. child: ModalBarrier(dismissible: false, color: Colors.black),
  117. ),
  118. Center(
  119. child: Column(
  120. mainAxisSize: MainAxisSize.max,
  121. mainAxisAlignment: MainAxisAlignment.center,
  122. children: const <Widget> [
  123. CircularProgressIndicator(),
  124. SizedBox(height: 25),
  125. Text('Loading...'),
  126. ],
  127. )
  128. ),
  129. ]
  130. );
  131. }
  132. void updateData() async {
  133. if (!await checkLogin()) {
  134. return;
  135. }
  136. await updateFriends();
  137. await updateConversations();
  138. await updateMessageThreads();
  139. conversations = await getConversations();
  140. friends = await getFriends(accepted: true);
  141. friendRequests = await getFriends(accepted: false);
  142. profile = await MyProfile.getProfile();
  143. setState(() {
  144. _widgetOptions = <Widget>[
  145. ConversationList(
  146. conversations: conversations,
  147. friends: friends,
  148. ),
  149. FriendList(
  150. friends: friends,
  151. friendRequests: friendRequests,
  152. callback: reinitDatabaseRecords,
  153. ),
  154. Profile(profile: profile),
  155. ];
  156. isLoading = false;
  157. });
  158. }
  159. Future<void> reinitDatabaseRecords() async {
  160. conversations = await getConversations();
  161. friends = await getFriends(accepted: true);
  162. friendRequests = await getFriends(accepted: false);
  163. profile = await MyProfile.getProfile();
  164. setState(() {
  165. _widgetOptions = <Widget>[
  166. ConversationList(
  167. conversations: conversations,
  168. friends: friends,
  169. ),
  170. FriendList(
  171. friends: friends,
  172. friendRequests: friendRequests,
  173. callback: reinitDatabaseRecords,
  174. ),
  175. Profile(profile: profile),
  176. ];
  177. isLoading = false;
  178. });
  179. }
  180. void _onItemTapped(int index) async {
  181. await reinitDatabaseRecords();
  182. setState(() {
  183. _selectedIndex = index;
  184. });
  185. }
  186. }