كيفية عمل chat في firebase داخل flutter بسهوله

كيفية عمل chat في firebase داخل flutter بسهوله

كيفية عمل chat في firebase داخل flutter بسهوله

يعد الشات واحد من العناصر التي يتم البحث عنها بشده من قبل المطورين وذلك بسبب ان معظم العملاء يطلبون وجود شات في التطبيقات الخاصه بهم وفي هذا المقال سوف نشرح لكم كيف تقوم بانشاء تطبيق محادثة بسيط في فلاتر بكل سهوله عن طريق خدمة الفايربيز المجانية والتي تسمح لك بعمل سيرفر مصغر لارسال واستقبال البيانات وهذا الدرس تابع لباقي الدروس السابقه التي تساعدنا في انشاء تطبيق مشابه للانستقرام .


ستخدم لغة البرمجة Dart في تطبيقات Flutter. تشترك Dart كثيرًا مع اللغات الحالية الأخرى مثل Kotlin و Swift. يمكن أيضًا تحويل Dart إلى كود JavaScript. تحقق من البرنامج التعليمي Dart Basics إذا كنت تريد معرفة المزيد عن Dart قبل متابعة هذا البرنامج التعليمي Flutter.


Flutter هو أكثر إطار عمل متعدد المنصات تشابهًا مع React Native. كلاهما يدعم أنماط البرمجة التفاعلية والتصريحية. لا يتطلب Flutter ، بخلاف React Native ، جسر JavaScript ، مما يسرع تشغيل التطبيق والأداء العام. يتم استخدام التجميع المسبق (AOT) بواسطة Dart للقيام بذلك. يدعم Dart أيضًا تجميع Just-In-Time (JIT). يساعد تجميع JIT من Flutter سير عمل التطوير من خلال تمكين إمكانية إعادة التحميل السريع لتحديث واجهة المستخدم أثناء تطويرها.


إنشاء class model لاستقبال البيانات

في البداية نحتاج الى استخدام model لاستقبال وارسال البيانات وهنا سوف نحتاج الى id للرساله و الرساله نفسها والوقت وid للمرسل والمستقبل لكي نعرف من قام بإرسال الرساله وبناء عليها نظهر الرساله على اليمين او اليسار .


إنشاء class model لاستقبال البيانات

model.dart


class MessageModel {
  MessageModel({
    this.messageId,
    this.senderId,
    this.reciverId,
    this.message,
    this.time,});

  MessageModel.fromJson(dynamic json) {
    messageId = json['messageId'];
    senderId = json['senderId'];
    reciverId = json['reciverId'];
    message = json['message'];
    time = json['time'];
  }

  String? messageId;
  String? senderId;
  String? reciverId;
  String? message;
  String? time;

  Map<String, dynamic> toJson() {
    final map = <String, dynamic>{};
    map['messageId'] = messageId;
    map['senderId'] = senderId;
    map['reciverId'] = reciverId;
    map['message'] = message;
    map['time'] = time;
    return map;
  }
}


كيفية الحصول على الرسائل وعمل chat بشكل stream في Flutter

في هذا الجزء سوف نقوم بعمل list فارغه ونقوم بملئها بالرسائل التي نحصل عليها من الfirebase بالنسبة لعملية ارسال الرساله سوف نرسل الmodel كامل الى الفايربيز وهذا يكون عند النقر على الايقونة الخاصه بالارسال والتي سوف نشاهدها في الui وايضا لدينا methode اخرى للاستماع الى الرسائل التي تصل وكل رساله تصل يتم عرضها على الشاشه بشكل مباشر ولدينا ميثود اخرى ايضا تكون مخصصه للحصول على الرسائل وفي كل مره نقوم بحذف جميع الرسائل والاستماع اليها مره اخرى .


كيفية الحصول على الرسائل وعمل chat بشكل stream في Flutter

cubit.dart


 /// send and receive message (chatting)  ------------- start

  List<MessageModel> messages = [];

  void sendMessage(MessageModel message) async {

    // go collection users_instagram +
    await FirebaseFirestore.instance
        .collection("users_instagram")
    // sendId to user (unique every user)
        .doc(message.senderId)
    // collection chats
        .collection("chats")
    // receiveId to user (unique every user)
        .doc(message.reciverId)
    // message collection
        .collection("messages")
    // messageId .
        .doc(message.messageId)
    // set data .
        .set(message.toJson());

    await FirebaseFirestore.instance
        .collection("users_instagram")
        .doc(message.reciverId)
        .collection("chats")
        .doc(message.senderId)
        .collection("messages")
        .doc(message.messageId)
        .set(message.toJson());

    emit(SendMessageSuccessState());
  }

  void getMessages(String receiverId) {
    FirebaseFirestore.instance
        .collection("users_instagram")
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .collection("chats")
        .doc(receiverId)
        .collection("messages")
        .get()
        .then((value) {
      messages.clear();

      for (var element in value.docs) {
        MessageModel message = MessageModel.fromJson(element.data());
        messages.add(message);
      }
      emit(GetMessagesSuccessState());
    });
  }

  void listenToMessages(String receiverId) {
    FirebaseFirestore.instance
        .collection("users_instagram")
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .collection("chats")
        .doc(receiverId)
        .collection("messages")
    // sort data
        .orderBy("time")
    // get last message  || if you can get first message use (limit)
        .limitToLast(1)
    // stream snapshots
        .snapshots()
    // listen to message .
        .listen((event) {
      // messages.clear();

      print('Docs => ${event.docs.length}');

      // another method
      // MessageModel message = MessageModel.fromJson(event.docs[0].data());
      for (var element in event.docs) {
        MessageModel model = MessageModel.fromJson(element.data());
        messages.add(model);
      }

      emit(GetMessagesSuccessState());
    });
  }
// send and receive message (chatting)  ------------- end


تصميم واجهة لاستقبال وارسال الرسائل في Flutter

في هذا الجزء يكون عباره عن التصميم الخاص بعرض الرسائل والاستماع اليها كما هو موضح حيث قمنا هنا بعرض الرسائل وعند النقر على ايقونة الارسال يتم ارسالها الى السيرفر .


تصميم واجهة لاستقبال وارسال الرسائل في Flutter

ui.dart


class ChattingPage extends StatefulWidget {
  const ChattingPage({Key? key,required this.user}) : super(key: key);
  final UserModel user;

  @override
  State<ChattingPage> createState() => _ChattingPageState();
}

class _ChattingPageState extends State<ChattingPage> {

  late ChatBloc cubit;
  final TextEditingController messageController = TextEditingController();

  @override
  void initState() {
    super.initState();
    cubit = BlocProvider.of<ChatBloc>(context);
    cubit.messages.clear();
    cubit.getMessages(widget.user.uId!);
    cubit.listenToMessages(widget.user.uId!);
  }

  @override
  Widget build(BuildContext context) {
    return BlocListener<ChatBloc, ChatBlocState>(
      listener: (context, state) {},
      child: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          centerTitle: false,
          backgroundColor: Colors.black,
          title: Row(
            children: [
              Stack(
                alignment: Alignment.center,
                children: [
                  CircleAvatar(
                    radius: 20,
                    child: Container(
                      decoration: const BoxDecoration(
                          shape: BoxShape.circle,
                          gradient: LinearGradient(colors: [
                            Color(0xff833ab4),
                            Color(0xfffd1d1d),
                            Color(0xfffcb045),
                          ])),
                    ),
                  ),
                  CircleAvatar(
                    backgroundImage: NetworkImage(widget.user.imageUrl!),
                    radius: 18,
                  ),
                ],
              ),
              const SizedBox(
                width: 10,
              ),
              Expanded(
                child: Text(
                  widget.user.name!,
                  // "Amir Mohammed",
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                  style: const TextStyle(
                      color: Colors.white, fontWeight: FontWeight.bold),
                ),
              ),
            ],
          ),
        ),
        body: Column(
          children: [
            buildChattingListView(),
            buildMessageTextFromFiled(),
          ],
        ),
      ),
    );
  }

  Widget buildChattingListView() {
    return Expanded(
      child: BlocBuilder<ChatBloc, ChatBlocState>(
        buildWhen: (previous, current) => current is GetMessagesSuccessState,
        builder: (context, state) {
          return ListView.builder(
            itemCount: cubit.messages.length,
            itemBuilder: (context, index) {
              MessageModel message = cubit.messages[index];

              if (message.senderId == FirebaseAuth.instance.currentUser!.uid){
                return buildSenderMessage(message.message!);
              } else {
                return buildReceiverMessage(message.message!);
              }

            },
          );
        },
      ),
    );
  }

  Widget buildSenderMessage(String message) {
    return Container(
      alignment: Alignment.centerRight,
      child: Container(
        margin: EdgeInsets.only(
          top: 10,
          bottom: 10,
          right: 15,
          left: 25,
        ),
        padding: EdgeInsets.symmetric(
          vertical: 15,
          horizontal: 10,
        ),
        // width: double.infinity,
        // alignment: Alignment.centerRight,
        decoration: BoxDecoration(
          color: Colors.blue[200],
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(15),
            topRight: Radius.circular(15),
            bottomLeft: Radius.circular(15),
          ),
        ),
        child: Text(
          message,
          style: TextStyle(
            color: Colors.black,
            fontSize: 16,
          ),
        ),
      ),
    );
  }

  Widget buildReceiverMessage(String message) {
    return Container(
      alignment: Alignment.centerLeft,
      child: Container(
        margin: EdgeInsets.only(
          top: 10,
          bottom: 10,
          right: 25,
          left: 15,
        ),
        padding: EdgeInsets.symmetric(
          vertical: 15,
          horizontal: 10,
        ),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(15),
            topRight: Radius.circular(15),
            bottomRight: Radius.circular(15),
          ),
        ),
        child: Text(
          message,
          style: TextStyle(
            color: Colors.black,
            fontSize: 16,
          ),
        ),
      ),
    );
  }

  Widget buildMessageTextFromFiled() {
    return Container(
      margin: EdgeInsets.all(15),
      padding: EdgeInsets.all(10),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(15),
      ),
      child: Row(
        children: [
          Expanded(
            child: TextFormField(
              controller: messageController,
              style: TextStyle(color: Colors.black, fontSize: 17),
              decoration: InputDecoration(
                border: InputBorder.none,
                hintText: "Write your message",
                hintStyle: TextStyle(color: Colors.black, fontSize: 17),
              ),
            ),
          ),
          IconButton(
              onPressed: () => sendMessage(),
              icon: Icon(
                Icons.send,
                color: Colors.blue[200],
                size: 22,
              ))
        ],
      ),
    );
  }

  void sendMessage() {
    String messageContent = messageController.text;
    String userId = FirebaseAuth.instance.currentUser!.uid;
    String time = DateTime.now().toString();

    MessageModel message = MessageModel(
      messageId: time + userId,
      senderId: userId,
      reciverId: widget.user.uId!,
      message: messageContent,
      time: time,
    );

    cubit.sendMessage(message);
    messageController.clear();
  }
}


مزيد من المقالات

تعليقات