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

  1. import 'package:flutter/material.dart';
  2. import 'package:shared_preferences/shared_preferences.dart';
  3. import '/models/conversations.dart';
  4. import '/models/messages.dart';
  5. import '/utils/storage/messages.dart';
  6. String convertToAgo(String input){
  7. DateTime time = DateTime.parse(input);
  8. Duration diff = DateTime.now().difference(time);
  9. if(diff.inDays >= 1){
  10. return '${diff.inDays} day${diff.inDays == 1 ? "" : "s"} ago';
  11. }
  12. if(diff.inHours >= 1){
  13. return '${diff.inHours} hour${diff.inHours == 1 ? "" : "s"} ago';
  14. }
  15. if(diff.inMinutes >= 1){
  16. return '${diff.inMinutes} minute${diff.inMinutes == 1 ? "" : "s"} ago';
  17. }
  18. if (diff.inSeconds >= 1){
  19. return '${diff.inSeconds} second${diff.inSeconds == 1 ? "" : "s"} ago';
  20. }
  21. return 'just now';
  22. }
  23. class ConversationDetail extends StatefulWidget{
  24. final Conversation conversation;
  25. const ConversationDetail({
  26. Key? key,
  27. required this.conversation,
  28. }) : super(key: key);
  29. @override
  30. _ConversationDetailState createState() => _ConversationDetailState();
  31. }
  32. class _ConversationDetailState extends State<ConversationDetail> {
  33. List<Message> messages = [];
  34. String username = '';
  35. TextEditingController msgController = TextEditingController();
  36. @override
  37. void initState() {
  38. super.initState();
  39. fetchMessages();
  40. }
  41. Future<void> fetchMessages() async {
  42. final preferences = await SharedPreferences.getInstance();
  43. username = preferences.getString('username')!;
  44. messages = await getMessagesForThread(widget.conversation);
  45. setState(() {});
  46. }
  47. @override
  48. Widget build(BuildContext context) {
  49. return Scaffold(
  50. appBar: AppBar(
  51. elevation: 0,
  52. automaticallyImplyLeading: false,
  53. backgroundColor: Colors.white,
  54. flexibleSpace: SafeArea(
  55. child: Container(
  56. padding: const EdgeInsets.only(right: 16),
  57. child: Row(
  58. children: <Widget>[
  59. IconButton(
  60. onPressed: (){
  61. Navigator.pop(context);
  62. },
  63. icon: const Icon(Icons.arrow_back,color: Colors.black,),
  64. ),
  65. const SizedBox(width: 2,),
  66. Expanded(
  67. child: Column(
  68. crossAxisAlignment: CrossAxisAlignment.start,
  69. mainAxisAlignment: MainAxisAlignment.center,
  70. children: <Widget>[
  71. Text(
  72. widget.conversation.name,
  73. style: const TextStyle(
  74. fontSize: 16,
  75. fontWeight: FontWeight.w600),
  76. ),
  77. ],
  78. ),
  79. ),
  80. const Icon(Icons.settings,color: Colors.black54),
  81. ],
  82. ),
  83. ),
  84. ),
  85. ),
  86. body: Stack(
  87. children: <Widget>[
  88. ListView.builder(
  89. itemCount: messages.length,
  90. shrinkWrap: true,
  91. padding: const EdgeInsets.only(top: 10,bottom: 90),
  92. reverse: true,
  93. itemBuilder: (context, index) {
  94. return Container(
  95. padding: const EdgeInsets.only(left: 14,right: 14,top: 0,bottom: 0),
  96. child: Align(
  97. alignment: (
  98. messages[index].senderUsername == username ?
  99. Alignment.topRight :
  100. Alignment.topLeft
  101. ),
  102. child: Column(
  103. crossAxisAlignment: messages[index].senderUsername == username ?
  104. CrossAxisAlignment.end :
  105. CrossAxisAlignment.start,
  106. children: <Widget>[
  107. Container(
  108. decoration: BoxDecoration(
  109. borderRadius: BorderRadius.circular(20),
  110. color: (
  111. messages[index].senderUsername == username ?
  112. Colors.blue[200] :
  113. Colors.grey.shade200
  114. ),
  115. ),
  116. padding: const EdgeInsets.all(12),
  117. child: Text(messages[index].data, style: const TextStyle(fontSize: 15)),
  118. ),
  119. messages[index].senderUsername != username ?
  120. Text(messages[index].senderUsername) :
  121. const SizedBox.shrink(),
  122. Text(
  123. convertToAgo(messages[index].createdAt),
  124. textAlign: TextAlign.left,
  125. style: TextStyle(
  126. fontSize: 12,
  127. color: Colors.grey[500],
  128. ),
  129. ),
  130. ]
  131. )
  132. ),
  133. );
  134. },
  135. ),
  136. Align(
  137. alignment: Alignment.bottomLeft,
  138. child: ConstrainedBox(
  139. constraints: const BoxConstraints(
  140. maxHeight: 200.0,
  141. ),
  142. child: Container(
  143. padding: const EdgeInsets.only(left: 10,bottom: 10,top: 10),
  144. // height: 60,
  145. width: double.infinity,
  146. color: Colors.white,
  147. child: Row(
  148. children: <Widget>[
  149. GestureDetector(
  150. onTap: (){
  151. },
  152. child: Container(
  153. height: 30,
  154. width: 30,
  155. decoration: BoxDecoration(
  156. color: Colors.lightBlue,
  157. borderRadius: BorderRadius.circular(30),
  158. ),
  159. child: const Icon(Icons.add, color: Colors.white, size: 20, ),
  160. ),
  161. ),
  162. const SizedBox(width: 15,),
  163. Expanded(
  164. child: TextField(
  165. decoration: const InputDecoration(
  166. hintText: "Write message...",
  167. hintStyle: TextStyle(color: Colors.black54),
  168. border: InputBorder.none,
  169. ),
  170. maxLines: null,
  171. controller: msgController,
  172. ),
  173. ),
  174. const SizedBox(width: 15),
  175. FloatingActionButton(
  176. onPressed: () async {
  177. if (msgController.text == '') {
  178. return;
  179. }
  180. await sendMessage(widget.conversation, msgController.text);
  181. messages = await getMessagesForThread(widget.conversation);
  182. setState(() {});
  183. msgController.text = '';
  184. },
  185. child: const Icon(Icons.send,color: Colors.white,size: 18,),
  186. backgroundColor: Colors.blue,
  187. ),
  188. const SizedBox(width: 10),
  189. ],
  190. ),
  191. ),
  192. ),
  193. ),
  194. ],
  195. ),
  196. );
  197. }
  198. }