Chat Screen
π§βπ€βπ§ Chat Screen
Lets start building the chat screen
for chat we need messages, we will create a model for messages , Create a new π file under models π folder => message.dart
import 'package:cloud_firestore/cloud_firestore.dart';class Message {final String? id, senderId, toUserId, text, imageUrl;final bool? isLiked;final bool? unread;final String? timestamp;Message({this.id,this.senderId,this.toUserId,this.text,this.imageUrl,this.isLiked,this.unread,this.timestamp,});factory Message.fromDoc(DocumentSnapshot doc) {return Message(id: doc.id,senderId: doc['senderId'],toUserId: doc['toUserId'],text: doc['text'],imageUrl: doc['imageUrl'],isLiked: doc['isLiked'],unread: doc['unread'],timestamp: doc['timestamp']);}}
We will create some dummy data to work with , update π file data.dart under data π folder , we will create some dummy users and messages
import 'package:devfest_flutter_firebase_chat/models/app_user.dart';import 'package:devfest_flutter_firebase_chat/models/message.dart';// YOU - current AppUserfinal AppUser currentAppUser = AppUser(id: '0',name: 'Current AppUser',profileImageUrl: 'assets/images/greg.jpg',);// AppUserSfinal AppUser sumith = AppUser(id: '1',name: 'Sumith',profileImageUrl: 'assets/images/user_placeholder.jpg',);final AppUser martin = AppUser(id: '2',name: 'martin',profileImageUrl: 'assets/images/user_placeholder.jpg',);final AppUser laura = AppUser(id: '3',name: 'laura',profileImageUrl: 'assets/images/user_placeholder.jpg',);final AppUser bilal = AppUser(id: '4',name: 'bilal',profileImageUrl: 'assets/images/user_placeholder.jpg',);final AppUser sam = AppUser(id: '5',name: 'Sam',profileImageUrl: 'assets/images/user_placeholder.jpg',);final AppUser sophia = AppUser(id: '6',name: 'Sophia',profileImageUrl: 'assets/images/user_placeholder.jpg',);final AppUser steven = AppUser(id: '7',name: 'Steven',profileImageUrl: 'assets/images/user_placeholder.jpg',);// EXAMPLE CHATS ON HOME SCREENList<Message> chats = [Message(senderId: 'sumith',timestamp: '5:30 PM',text: 'Hey, how\'s it going? What did you do today?',isLiked: false,unread: true,),Message(senderId: 'laura',timestamp: '4:30 PM',text: 'Hey, how\'s it going? What did you do today?',isLiked: false,unread: true,),Message(senderId: 'martin',timestamp: '3:30 PM',text: 'Hey, how\'s it going? What did you do today?',isLiked: false,unread: false,),Message(senderId: 'sophia',timestamp: '2:30 PM',text: 'Hey, how\'s it going? What did you do today?',isLiked: false,unread: true,),Message(senderId: 'bilal',timestamp: '1:30 PM',text: 'Hey, how\'s it going? What did you do today?',isLiked: false,unread: false,),Message(senderId: 'sam',timestamp: '12:30 PM',text: 'Hey, how\'s it going? What did you do today?',isLiked: false,unread: false,),Message(senderId: 'bilal',timestamp: '11:30 AM',text: 'Hey, how\'s it going? What did you do today?',isLiked: false,unread: false,),];// EXAMPLE MESSAGES IN CHAT SCREENList<Message> messages = [Message(senderId: 'martin',timestamp: '5:30 PM',text: 'Hey, how\'s it going? What did you do today?',isLiked: true,unread: true,),Message(senderId: currentAppUser.id,timestamp: '4:30 PM',text: 'Just walked my dog. She was super duper cute. The best puppy!!',isLiked: false,unread: true,),Message(senderId: 'martin',timestamp: '3:45 PM',text: 'How\'s the doggie?',isLiked: false,unread: true,),Message(senderId: 'martin',timestamp: '3:15 PM',text: 'All the food',isLiked: true,unread: true,),Message(senderId: currentAppUser.id,timestamp: '2:30 PM',text: 'Nice! What kind of food did you eat?',isLiked: false,unread: true,),Message(senderId: 'martin',timestamp: '2:00 PM',text: 'I ate so much food today.',isLiked: false,unread: true,),];
Now we start with our chat screen
Create a new π file under screens
π folder => chat_screen.dart
// ignore_for_file: prefer_const_constructorsimport 'package:devfest_flutter_firebase_chat/data/data.dart';import 'package:devfest_flutter_firebase_chat/helpers/app_constants.dart';import 'package:devfest_flutter_firebase_chat/models/message.dart';import 'package:flutter/material.dart';class ChatScreen extends StatefulWidget {const ChatScreen({Key? key}) : super(key: key);@override_ChatScreenState createState() => _ChatScreenState();}class _ChatScreenState extends State<ChatScreen> {final TextEditingController _textMessageController = TextEditingController();bool _isComposing = false;final List<Message> _messages = messages;_buildMessage(Message message, bool isMe) {final Widget msg = Padding(padding: const EdgeInsets.all(8.0),child: Container(margin: isMe? const EdgeInsets.only(top: 8.0,bottom: 8.0,left: 80.0,): const EdgeInsets.only(top: 8.0,bottom: 8.0,),padding: const EdgeInsets.symmetric(horizontal: 25.0, vertical: 15.0),width: MediaQuery.of(context).size.width * 0.75,decoration: BoxDecoration(color: isMe? AppConstants.hexToColor(AppConstants.APP_PRIMARY_TILE_COLOR): AppConstants.hexToColor(AppConstants.APP_BACKGROUND_COLOR_WHITE),borderRadius: isMe? const BorderRadius.only(topLeft: Radius.circular(15.0),topRight: Radius.circular(15.0),bottomLeft: Radius.circular(15.0),): const BorderRadius.only(topLeft: Radius.circular(15.0),topRight: Radius.circular(15.0),bottomRight: Radius.circular(15.0),),),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[Text(message.text!,style: TextStyle(color: isMe ? Colors.white60 : Colors.blueGrey,fontSize: 12.0,fontWeight: FontWeight.w600,),),SizedBox(height: 8.0),Row(mainAxisAlignment:isMe ? MainAxisAlignment.end : MainAxisAlignment.start,children: <Widget>[Text(message.timestamp!,style: TextStyle(color: isMe? AppConstants.hexToColor(AppConstants.APP_PRIMARY_COLOR_GREEN): AppConstants.hexToColor(AppConstants.APP_BACKGROUND_COLOR_GRAY),fontSize: 12.0,fontWeight: FontWeight.w800,),),],),],),),);return Row(children: <Widget>[msg],);}_buildMessageComposer() {return Container(padding: const EdgeInsets.symmetric(horizontal: 8.0),height: 70.0,color: AppConstants.hexToColor(AppConstants.APP_BACKGROUND_COLOR_WHITE),child: Row(children: <Widget>[RawMaterialButton(onPressed: () {},child: Icon(Icons.camera_alt,color: AppConstants.hexToColor(AppConstants.APP_BACKGROUND_COLOR_GRAY),size: 25.0,),shape: const CircleBorder(),elevation: 2.0,fillColor: Theme.of(context).primaryColor,padding: const EdgeInsets.all(15.0),),Expanded(child: TextField(controller: _textMessageController,textCapitalization: TextCapitalization.sentences,onChanged: (String text) {setState(() {_isComposing = text.isNotEmpty;});},decoration: InputDecoration(border: const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0),),),hintText: 'Type your message...',filled: true,hintStyle: TextStyle(color: AppConstants.hexToColor(AppConstants.APP_PRIMARY_FONT_COLOR_LIGHT)),),),),IconButton(icon: const Icon(Icons.send),iconSize: 25.0,color:AppConstants.hexToColor(AppConstants.APP_PRIMARY_COLOR_ACTION),onPressed: _isComposing? () => _handleSubmitted(_textMessageController.text): null,),],),);}void _handleSubmitted(String text) {_textMessageController.clear();setState(() {_isComposing = false;});Message message = Message(senderId: currentAppUser.id,timestamp: '6:30 PM',text: text,isLiked: true,unread: true,);setState(() {_messages.insert(0, message);});}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Chats")),body: GestureDetector(onTap: () => FocusScope.of(context).unfocus(),child: Column(children: <Widget>[Expanded(child: ListView.builder(reverse: true,padding: const EdgeInsets.only(top: 15.0),itemCount: _messages.length,itemBuilder: (BuildContext context, int index) {final Message message = _messages[index];final bool isMe = message.senderId == currentAppUser.id;return _buildMessage(message, isMe);},),),_buildMessageComposer(),],),),);}}
To test update main.dart and point home to the new chat_screen.dart
home: const ChatScreen(),