From 9577dbd9a7e703258d916567f5ce170b848604aa Mon Sep 17 00:00:00 2001 From: rudramistry001 Date: Fri, 9 Feb 2024 16:48:55 +0530 Subject: [PATCH] upload image functionality added --- login/lib/api/apis.dart | 24 +++++- login/lib/screens/splashscreen.dart | 1 - login/lib/screens/user_chat_screen.dart | 102 ++++++++++++++++++------ login/lib/widgets/pop_menu_button.dart | 42 ++++++++++ 4 files changed, 142 insertions(+), 27 deletions(-) create mode 100644 login/lib/widgets/pop_menu_button.dart diff --git a/login/lib/api/apis.dart b/login/lib/api/apis.dart index 8000a3c..3d73e5b 100644 --- a/login/lib/api/apis.dart +++ b/login/lib/api/apis.dart @@ -123,6 +123,7 @@ class APIs { static Future sendMessage( ChatUser chatUser, String msg, + Type type, ) async { //message sending time (also used as id) final time = DateTime.now().millisecondsSinceEpoch.toString(); @@ -132,7 +133,7 @@ class APIs { toId: chatUser.Id, msg: msg, read: '', - type: Type.text, + type: type, fromId: user.uid, sent: time); @@ -158,4 +159,25 @@ class APIs { .limit(1) .snapshots(); } + + //send chat image + static Future sendChatImage(ChatUser chatUser, File file) async { + //getting image file extension + final ext = file.path.split('.').last; + + //storage file ref with path + final ref = storage.ref().child( + 'images/${getConversationID(chatUser.Id)}/${DateTime.now().millisecondsSinceEpoch}.$ext'); + + //uploading image + await ref + .putFile(file, SettableMetadata(contentType: 'image/$ext')) + .then((p0) { + print('Data Transferred: ${p0.bytesTransferred / 1000} kb'); + }); + + //updating image in firestore database + final imageUrl = await ref.getDownloadURL(); + await sendMessage(chatUser, imageUrl, Type.image); + } } diff --git a/login/lib/screens/splashscreen.dart b/login/lib/screens/splashscreen.dart index f27838f..38dd010 100644 --- a/login/lib/screens/splashscreen.dart +++ b/login/lib/screens/splashscreen.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:login/api/apis.dart'; -import 'package:login/auth/loginscreen.dart'; import 'package:login/main.dart'; import 'package:login/screens/homescreen.dart'; import 'package:login/screens/onboard_screen.dart'; diff --git a/login/lib/screens/user_chat_screen.dart b/login/lib/screens/user_chat_screen.dart index c7f843e..8f4768b 100644 --- a/login/lib/screens/user_chat_screen.dart +++ b/login/lib/screens/user_chat_screen.dart @@ -1,9 +1,12 @@ // ignore_for_file: avoid_print +import 'dart:io'; + import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:image_picker/image_picker.dart'; import 'package:login/api/apis.dart'; import 'package:login/main.dart'; import 'package:login/model/chat_user_model.dart'; @@ -20,6 +23,28 @@ class UserChatScreen extends StatefulWidget { } class _UserChatScreenState extends State { + List _newList = []; + bool _isUploading = false; + @override + void initState() { + super.initState(); + // Scroll to the bottom when the screen loads + WidgetsBinding.instance.addPostFrameCallback((_) { + _scrollToBottom(); + }); + } + + //for scrolling down to end of chat by default + final ScrollController _scrollController = ScrollController(); + // After adding a new item to the list, scroll to the bottom + _scrollToBottom() { + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 30), + curve: Curves.easeOut, + ); + } + //for storing all messages List _list = []; //for handling message text controlling @@ -96,14 +121,19 @@ class _UserChatScreenState extends State { case ConnectionState.done: final data = snapshot.data?.docs; - _list = data + _newList = data ?.map((e) => Message.fromJson(e.data())) .toList() ?? []; + var _list = _newList.reversed.toList(); + if (_list.isNotEmpty) { return ListView.builder( - itemCount: _list.length, // Use the length of the list + reverse: true, + controller: + _scrollController, // Assign the ScrollController + itemCount: _list.length, padding: EdgeInsets.only(top: mq.height * .01), physics: const BouncingScrollPhysics(), itemBuilder: (context, index) { @@ -165,35 +195,57 @@ class _UserChatScreenState extends State { ), ), IconButton( - onPressed: () {}, - icon: const Icon(Icons.image, color: Colors.blueAccent), - ), + onPressed: () async { + final ImagePicker picker = ImagePicker(); + + // Picking multiple images + final List images = + await picker.pickMultiImage(imageQuality: 70); + + // uploading & sending image one by one + for (var i in images) { + print('Image Path: ${i.path}'); + setState(() => _isUploading = true); + await APIs.sendChatImage(widget.user, File(i.path)); + setState(() => _isUploading = false); + } + }, + icon: const Icon(Icons.image, + color: Colors.blueAccent, size: 26)), + //take image from camera button IconButton( - onPressed: () {}, - icon: const Icon(Icons.camera_enhance_outlined, - color: Colors.blueAccent), - ), + onPressed: () async { + final ImagePicker picker = ImagePicker(); + + // Pick an image + final XFile? image = await picker.pickImage( + source: ImageSource.camera, imageQuality: 70); + if (image != null) { + print('Image Path: ${image.path}'); + setState(() => _isUploading = true); + + await APIs.sendChatImage( + widget.user, File(image.path)); + setState(() => _isUploading = false); + } + }, + icon: const Icon(Icons.camera_alt_rounded, + color: Colors.blueAccent, size: 26)), ], ), ), //send message button ), - MaterialButton( - onPressed: () { - if (_textController.text.isNotEmpty) { - //simply send message - APIs.sendMessage(widget.user, _textController.text); - _textController.clear(); - } - }, - minWidth: 1, - padding: EdgeInsets.only( - top: 5.sp, bottom: 5.sp, right: 5.sp, left: 5.sp), - shape: - RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), - color: Colors.blueAccent, - child: IconButton(onPressed: () {}, icon: const Icon(Icons.send)), - ), + IconButton( + onPressed: () { + if (_textController.text.isNotEmpty) { + //simply send message + APIs.sendMessage( + widget.user, _textController.text, Type.text); + _textController.clear(); + } + }, + icon: const Icon(Icons.send)), ], ), ); diff --git a/login/lib/widgets/pop_menu_button.dart b/login/lib/widgets/pop_menu_button.dart new file mode 100644 index 0000000..bea5aea --- /dev/null +++ b/login/lib/widgets/pop_menu_button.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; + +enum SampleItem { itemOne, itemTwo, itemThree } + +class CustomPopMenuButton extends StatefulWidget { + const CustomPopMenuButton({super.key}); + + @override + State createState() => _CustomPopMenuButtonState(); +} + +class _CustomPopMenuButtonState extends State { + SampleItem? selectedMenu; + @override + Widget build(BuildContext context) { + return Container( + child: PopupMenuButton( + initialValue: selectedMenu, + // Callback that sets the selected popup menu item. + onSelected: (SampleItem item) { + setState(() { + selectedMenu = item; + }); + }, + itemBuilder: (BuildContext context) => >[ + const PopupMenuItem( + value: SampleItem.itemOne, + child: Text('Item 1'), + ), + const PopupMenuItem( + value: SampleItem.itemTwo, + child: Text('Item 2'), + ), + const PopupMenuItem( + value: SampleItem.itemThree, + child: Text('Item 3'), + ), + ], + ), + ); + } +}