|
|
@ -1,6 +1,11 @@ |
|
|
|
import 'package:Envelope/components/custom_title_bar.dart'; |
|
|
|
import 'dart:io'; |
|
|
|
|
|
|
|
import 'package:Envelope/models/text_messages.dart'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:image_picker/image_picker.dart'; |
|
|
|
|
|
|
|
import '/components/custom_title_bar.dart'; |
|
|
|
import '/components/file_picker.dart'; |
|
|
|
import '/models/conversations.dart'; |
|
|
|
import '/models/messages.dart'; |
|
|
|
import '/models/my_profile.dart'; |
|
|
@ -30,6 +35,9 @@ class _ConversationDetailState extends State<ConversationDetail> { |
|
|
|
|
|
|
|
TextEditingController msgController = TextEditingController(); |
|
|
|
|
|
|
|
bool showFilePicker = false; |
|
|
|
List<File> selectedImages = []; |
|
|
|
|
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
return Scaffold( |
|
|
@ -61,80 +69,7 @@ class _ConversationDetailState extends State<ConversationDetail> { |
|
|
|
body: Stack( |
|
|
|
children: <Widget>[ |
|
|
|
messagesView(), |
|
|
|
Align( |
|
|
|
alignment: Alignment.bottomLeft, |
|
|
|
child: ConstrainedBox( |
|
|
|
constraints: const BoxConstraints( |
|
|
|
maxHeight: 200.0, |
|
|
|
), |
|
|
|
child: Container( |
|
|
|
padding: const EdgeInsets.only(left: 10,bottom: 10,top: 10), |
|
|
|
// height: 60, |
|
|
|
width: double.infinity, |
|
|
|
color: Theme.of(context).backgroundColor, |
|
|
|
child: Row( |
|
|
|
children: <Widget>[ |
|
|
|
GestureDetector( |
|
|
|
onTap: (){ |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
height: 30, |
|
|
|
width: 30, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Theme.of(context).primaryColor, |
|
|
|
borderRadius: BorderRadius.circular(30), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.add, |
|
|
|
color: Theme.of(context).colorScheme.onPrimary, |
|
|
|
size: 20 |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(width: 15,), |
|
|
|
Expanded( |
|
|
|
child: TextField( |
|
|
|
decoration: InputDecoration( |
|
|
|
hintText: 'Write message...', |
|
|
|
hintStyle: TextStyle( |
|
|
|
color: Theme.of(context).hintColor, |
|
|
|
), |
|
|
|
border: InputBorder.none, |
|
|
|
), |
|
|
|
maxLines: null, |
|
|
|
controller: msgController, |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(width: 15), |
|
|
|
Container( |
|
|
|
width: 45, |
|
|
|
height: 45, |
|
|
|
child: FittedBox( |
|
|
|
child: FloatingActionButton( |
|
|
|
onPressed: () async { |
|
|
|
if (msgController.text == '') { |
|
|
|
return; |
|
|
|
} |
|
|
|
await sendMessage(widget.conversation, msgController.text); |
|
|
|
messages = await getMessagesForThread(widget.conversation); |
|
|
|
setState(() {}); |
|
|
|
msgController.text = ''; |
|
|
|
}, |
|
|
|
child: Icon( |
|
|
|
Icons.send, |
|
|
|
color: Theme.of(context).colorScheme.onPrimary, |
|
|
|
size: 22 |
|
|
|
), |
|
|
|
backgroundColor: Theme.of(context).primaryColor, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(width: 10), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
newMessageContent(), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
@ -220,15 +155,7 @@ class _ConversationDetailState extends State<ConversationDetail> { |
|
|
|
), |
|
|
|
), |
|
|
|
padding: const EdgeInsets.all(12), |
|
|
|
child: Text( |
|
|
|
messages[index].data, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 15, |
|
|
|
color: messages[index].senderUsername == profile.username ? |
|
|
|
Theme.of(context).colorScheme.onPrimary : |
|
|
|
Theme.of(context).colorScheme.onTertiary, |
|
|
|
) |
|
|
|
), |
|
|
|
child: messageContent(index), |
|
|
|
), |
|
|
|
const SizedBox(height: 1.5), |
|
|
|
Row( |
|
|
@ -269,4 +196,196 @@ class _ConversationDetailState extends State<ConversationDetail> { |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
Widget messageContent(int index) { |
|
|
|
return Text( |
|
|
|
messages[index].getContent(), |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 15, |
|
|
|
color: messages[index].senderUsername == profile.username ? |
|
|
|
Theme.of(context).colorScheme.onPrimary : |
|
|
|
Theme.of(context).colorScheme.onTertiary, |
|
|
|
) |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
Widget showSelectedImages() { |
|
|
|
if (selectedImages.isEmpty) { |
|
|
|
return const SizedBox.shrink(); |
|
|
|
} |
|
|
|
|
|
|
|
return SizedBox( |
|
|
|
height: 80, |
|
|
|
width: double.infinity, |
|
|
|
child: ListView.builder( |
|
|
|
itemCount: selectedImages.length, |
|
|
|
shrinkWrap: true, |
|
|
|
scrollDirection: Axis.horizontal, |
|
|
|
padding: const EdgeInsets.all(5), |
|
|
|
itemBuilder: (context, i) { |
|
|
|
|
|
|
|
return Stack( |
|
|
|
children: [ |
|
|
|
Column( |
|
|
|
children: [ |
|
|
|
const SizedBox(height: 5), |
|
|
|
Container( |
|
|
|
alignment: Alignment.center, |
|
|
|
height: 65, |
|
|
|
width: 65, |
|
|
|
child: Image.file( |
|
|
|
selectedImages[i], |
|
|
|
fit: BoxFit.fill, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
|
|
|
|
SizedBox( |
|
|
|
height: 60, |
|
|
|
width: 70, |
|
|
|
child: Align( |
|
|
|
alignment: Alignment.topRight, |
|
|
|
child: GestureDetector( |
|
|
|
onTap: () { |
|
|
|
setState(() { |
|
|
|
selectedImages.removeAt(i); |
|
|
|
}); |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
height: 20, |
|
|
|
width: 20, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Theme.of(context).colorScheme.onPrimary, |
|
|
|
borderRadius: BorderRadius.circular(30), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.cancel, |
|
|
|
color: Theme.of(context).primaryColor, |
|
|
|
size: 20 |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
|
|
|
|
], |
|
|
|
); |
|
|
|
}, |
|
|
|
) |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
Widget newMessageContent() { |
|
|
|
return Align( |
|
|
|
alignment: Alignment.bottomLeft, |
|
|
|
child: ConstrainedBox( |
|
|
|
constraints: BoxConstraints( |
|
|
|
maxHeight: selectedImages.isEmpty ? |
|
|
|
200.0 : |
|
|
|
270.0, |
|
|
|
), |
|
|
|
child: Container( |
|
|
|
padding: const EdgeInsets.only(left: 10,bottom: 10,top: 10), |
|
|
|
width: double.infinity, |
|
|
|
color: Theme.of(context).backgroundColor, |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
|
|
|
|
showSelectedImages(), |
|
|
|
|
|
|
|
Row( |
|
|
|
children: <Widget>[ |
|
|
|
|
|
|
|
GestureDetector( |
|
|
|
onTap: (){ |
|
|
|
setState(() { |
|
|
|
showFilePicker = !showFilePicker; |
|
|
|
}); |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
height: 30, |
|
|
|
width: 30, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Theme.of(context).primaryColor, |
|
|
|
borderRadius: BorderRadius.circular(30), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.add, |
|
|
|
color: Theme.of(context).colorScheme.onPrimary, |
|
|
|
size: 20 |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
|
|
|
|
const SizedBox(width: 15,), |
|
|
|
|
|
|
|
Expanded( |
|
|
|
child: TextField( |
|
|
|
decoration: InputDecoration( |
|
|
|
hintText: 'Write message...', |
|
|
|
hintStyle: TextStyle( |
|
|
|
color: Theme.of(context).hintColor, |
|
|
|
), |
|
|
|
border: InputBorder.none, |
|
|
|
), |
|
|
|
maxLines: null, |
|
|
|
controller: msgController, |
|
|
|
), |
|
|
|
), |
|
|
|
|
|
|
|
const SizedBox(width: 15), |
|
|
|
|
|
|
|
SizedBox( |
|
|
|
width: 45, |
|
|
|
height: 45, |
|
|
|
child: FittedBox( |
|
|
|
child: FloatingActionButton( |
|
|
|
onPressed: () async { |
|
|
|
if (msgController.text == '' || selectedImages.isEmpty) { |
|
|
|
return; |
|
|
|
} |
|
|
|
await sendMessage( |
|
|
|
widget.conversation, |
|
|
|
data: msgController.text != '' ? msgController.text : null, |
|
|
|
files: selectedImages, |
|
|
|
); |
|
|
|
messages = await getMessagesForThread(widget.conversation); |
|
|
|
setState(() {}); |
|
|
|
msgController.text = ''; |
|
|
|
}, |
|
|
|
child: Icon( |
|
|
|
Icons.send, |
|
|
|
color: Theme.of(context).colorScheme.onPrimary, |
|
|
|
size: 22 |
|
|
|
), |
|
|
|
backgroundColor: Theme.of(context).primaryColor, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(width: 10), |
|
|
|
], |
|
|
|
), |
|
|
|
|
|
|
|
showFilePicker ? |
|
|
|
FilePicker( |
|
|
|
cameraHandle: () {}, |
|
|
|
galleryHandleMultiple: (List<XFile> images) async { |
|
|
|
for (var img in images) { |
|
|
|
selectedImages.add(File(img.path)); |
|
|
|
} |
|
|
|
setState(() { |
|
|
|
showFilePicker = false; |
|
|
|
}); |
|
|
|
}, |
|
|
|
fileHandle: () {}, |
|
|
|
) : |
|
|
|
const SizedBox.shrink(), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
} |