Skip to content

Instantly share code, notes, and snippets.

@aliyazdi75
Created October 13, 2023 23:14
Show Gist options
  • Save aliyazdi75/5adaef404b2a7d2b6e0065a5b43d2450 to your computer and use it in GitHub Desktop.
Save aliyazdi75/5adaef404b2a7d2b6e0065a5b43d2450 to your computer and use it in GitHub Desktop.
firebase_flutter_chat

firebase_flutter_chat

Created with <3 with dartpad.dev.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
Future<void> main() async {
await Firebase.initializeApp(
options: const FirebaseOptions(
apiKey: 'AIzaSyBFQIi3pNiQNoM4y7dBKxBCp-lzeqSPfg8',
appId: '1:702148614087:web:7615cf62cdbb20e7c52be2',
messagingSenderId: '702148614087',
projectId: 'flutter-chat-aliyazdi',
authDomain: 'flutter-chat-aliyazdi.firebaseapp.com',
storageBucket: 'flutter-chat-aliyazdi.appspot.com',
),
);
// We sign the user in anonymously, meaning they get a user ID without having
// to provide credentials. While this doesn't allow us to identify the user,
// this would, for example, still allow us to associate data in the database
// with each user.
await FirebaseAuth.instance.signInAnonymously();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Chat',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final textMessageController = TextEditingController();
bool _isTextValidated = true;
void _sendMessage() {
if (textMessageController.text.isEmpty) {
setState(() {
_isTextValidated = false;
});
} else {
setState(() {
final chatMessage = ChatMessage(
time: DateTime.now().millisecondsSinceEpoch,
message: textMessageController.text,
);
FirebaseFirestore.instance.collection('chat').add(chatMessage.toJson());
});
textMessageController.clear();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('Chat Page'),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: ChatList(),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: TextField(
controller: textMessageController,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: const Icon(Icons.send),
onPressed: _sendMessage,
),
border: const OutlineInputBorder(),
labelText: 'Enter your message',
errorText:
_isTextValidated ? null : 'Message can not be empty',
),
onChanged: (value) {
setState(() {
_isTextValidated = true;
});
},
onSubmitted: (value) => _sendMessage(),
),
),
],
),
),
);
}
}
class ChatList extends StatelessWidget {
ChatList({super.key});
final chatStream = FirebaseFirestore.instance
.collection('chat')
.orderBy('time', descending: true)
.snapshots();
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: chatStream,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('$snapshot.error'));
} else if (!snapshot.hasData) {
return const Center(
child: SizedBox(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
);
}
final messages =
ChatMessage.fromQueryDocumentSnapshot(snapshot.data!.docs);
return ListView.builder(
itemCount: messages.length,
reverse: true,
padding: const EdgeInsets.symmetric(vertical: 8.0),
itemBuilder: (context, index) {
return ListTile(
leading: DefaultTextStyle.merge(
style: const TextStyle(color: Colors.indigo),
child: Text(messages[index].timestamp),
),
title: Text(messages[index].message),
);
},
);
},
);
}
}
class ChatMessage {
ChatMessage({
required this.time,
required this.message,
});
final int time;
final String message;
String get timestamp =>
'${DateTime.fromMillisecondsSinceEpoch(time).hour}:${DateTime.fromMillisecondsSinceEpoch(time).minute}';
factory ChatMessage.fromJson(Map<String, dynamic> json) {
return ChatMessage(
time: json['time'],
message: json['message'],
);
}
static List<ChatMessage> fromQueryDocumentSnapshot(
List<QueryDocumentSnapshot> docs) {
return docs
.map<ChatMessage>(
(json) => ChatMessage.fromJson(json.data() as Map<String, dynamic>),
)
.toList();
}
Map<String, dynamic> toJson() {
return {
'time': time,
'message': message,
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment