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.

211 lines
5.7 KiB

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