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 AppUser
final AppUser currentAppUser = AppUser(
id: '0',
name: 'Current AppUser',
profileImageUrl: 'assets/images/greg.jpg',
);
// AppUserS
final 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 SCREEN
List<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 SCREEN
List<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_constructors
import '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);
});
}
@override
Widget 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(),