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
6.3 KiB

  1. import 'dart:io';
  2. import 'package:Envelope/components/custom_title_bar.dart';
  3. import 'package:Envelope/components/flash_message.dart';
  4. import 'package:Envelope/database/repositories/conversations_repository.dart';
  5. import 'package:Envelope/database/repositories/friends_repository.dart';
  6. import 'package:Envelope/services/conversations_service.dart';
  7. import 'package:flutter/material.dart';
  8. import 'create_add_users.dart';
  9. import 'detail.dart';
  10. import '/database/models/friends.dart';
  11. import '/database/models/conversations.dart';
  12. import '/views/main/conversation/edit_details.dart';
  13. import '/views/main/conversation/list_item.dart';
  14. class ConversationList extends StatefulWidget {
  15. final List<Conversation> conversations;
  16. final List<Friend> friends;
  17. const ConversationList({
  18. Key? key,
  19. required this.conversations,
  20. required this.friends,
  21. }) : super(key: key);
  22. @override
  23. State<ConversationList> createState() => _ConversationListState();
  24. }
  25. class _ConversationListState extends State<ConversationList> {
  26. final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();
  27. late ScrollController _scrollController;
  28. List<Conversation> conversations = [];
  29. List<Friend> friends = [];
  30. @override
  31. Widget build(BuildContext context) {
  32. return Scaffold(
  33. appBar: const CustomTitleBar(
  34. title: Text(
  35. 'Conversations',
  36. style: TextStyle(
  37. fontSize: 32,
  38. fontWeight: FontWeight.bold
  39. )
  40. ),
  41. showBack: false,
  42. backgroundColor: Colors.transparent,
  43. ),
  44. body: Padding(
  45. padding: const EdgeInsets.only(top: 16,left: 16,right: 16, bottom: 65),
  46. child: Stack(
  47. children: <Widget>[
  48. Padding(
  49. padding: const EdgeInsets.only(top: 50),
  50. child: RefreshIndicator(
  51. key: _refreshIndicatorKey,
  52. onRefresh: _refresh,
  53. child: list(),
  54. ),
  55. ),
  56. TextField(
  57. decoration: const InputDecoration(
  58. hintText: 'Search...',
  59. prefixIcon: Icon(
  60. Icons.search,
  61. size: 20
  62. ),
  63. ),
  64. onChanged: (value) => filterSearchResults(value.toLowerCase())
  65. ),
  66. ],
  67. ),
  68. ),
  69. floatingActionButton: Padding(
  70. padding: const EdgeInsets.only(right: 10, bottom: 60),
  71. child: FloatingActionButton(
  72. onPressed: () {
  73. Navigator.of(context).push(
  74. MaterialPageRoute(builder: (context) => ConversationEditDetails(
  75. saveCallback: (String conversationName, File? file) {
  76. Navigator.of(context).push(
  77. MaterialPageRoute(builder: (context) => ConversationAddFriendsList(
  78. friends: friends,
  79. saveCallback: (List<Friend> friendsSelected) async {
  80. Conversation conversation = await ConversationsRepository.createConversation(
  81. conversationName,
  82. friendsSelected,
  83. false,
  84. );
  85. ConversationsService.uploadConversation(conversation)
  86. .catchError((dynamic) {
  87. showMessage('Failed to create conversation', context);
  88. });
  89. if (!mounted) {
  90. return;
  91. }
  92. Navigator.of(context).popUntil((route) => route.isFirst);
  93. Navigator.push(context, MaterialPageRoute(builder: (context) {
  94. return ConversationDetail(
  95. conversation: conversation,
  96. );
  97. }));
  98. },
  99. ))
  100. );
  101. },
  102. )),
  103. ).then(onGoBack);
  104. },
  105. backgroundColor: Theme.of(context).colorScheme.primary,
  106. child: Icon(
  107. Icons.add,
  108. size: 30,
  109. color: Theme.of(context).colorScheme.onPrimary,
  110. ),
  111. ),
  112. ),
  113. );
  114. }
  115. void filterSearchResults(String query) {
  116. List<Conversation> dummySearchList = [];
  117. dummySearchList.addAll(widget.conversations);
  118. if(query.isNotEmpty) {
  119. List<Conversation> dummyListData = [];
  120. for (Conversation item in dummySearchList) {
  121. if (item.name.toLowerCase().contains(query)) {
  122. dummyListData.add(item);
  123. }
  124. }
  125. setState(() {
  126. conversations.clear();
  127. conversations.addAll(dummyListData);
  128. });
  129. return;
  130. }
  131. setState(() {
  132. conversations.clear();
  133. conversations.addAll(widget.conversations);
  134. });
  135. }
  136. @override
  137. void initState() {
  138. _scrollController = ScrollController();
  139. _scrollController.addListener(_scrollListener);
  140. super.initState();
  141. conversations.addAll(widget.conversations);
  142. friends.addAll(widget.friends);
  143. setState(() {});
  144. }
  145. Widget list() {
  146. if (conversations.isEmpty) {
  147. return const Center(
  148. child: Text('No Conversations'),
  149. );
  150. }
  151. return ListView.builder(
  152. controller: _scrollController,
  153. itemCount: conversations.length,
  154. shrinkWrap: false,
  155. physics: const AlwaysScrollableScrollPhysics(),
  156. itemBuilder: (context, i) {
  157. return ConversationListItem(
  158. conversation: conversations[i],
  159. );
  160. },
  161. );
  162. }
  163. Future<void> _refresh() async {
  164. DateTime? updatedAt = await ConversationsRepository.getLatestUpdatedAt();
  165. if (updatedAt == null) {
  166. return;
  167. }
  168. ConversationsService.updateConversations(updatedAt: updatedAt);
  169. conversations = await ConversationsRepository.getConversations();
  170. setState(() {});
  171. }
  172. Future<void> _scrollListener() async {
  173. if (!(_scrollController.offset >= _scrollController.position.maxScrollExtent)) {
  174. return;
  175. }
  176. int page = 0;
  177. if (conversations.length > 19) {
  178. page = conversations.length ~/ 20;
  179. }
  180. await ConversationsService.updateConversations(page: page);
  181. onGoBack(null);
  182. }
  183. onGoBack(dynamic value) async {
  184. conversations = await ConversationsRepository.getConversations();
  185. friends = await FriendsRepository.getFriends();
  186. setState(() {});
  187. }
  188. }