Flutter के लिए Firebase के बारे में जानें

1. शुरू करने से पहले

इस कोडलैब में, आप एंड्रॉइड और आईओएस के लिए फ़्लटर मोबाइल ऐप बनाने के लिए फायरबेस की कुछ बुनियादी बातें सीखते हैं।

आवश्यक शर्तें

आप क्या सीखेंगे

  • फ़्लटर के साथ एंड्रॉइड, आईओएस, वेब और मैकओएस पर इवेंट आरएसवीपी और गेस्टबुक चैट ऐप कैसे बनाएं।
  • फ़ायरबेस प्रमाणीकरण के साथ उपयोगकर्ताओं को कैसे प्रमाणित करें और फ़ायरस्टोर के साथ डेटा सिंक करें।

एंड्रॉइड पर ऐप की होम स्क्रीन

iOS पर ऐप की होम स्क्रीन

आपको किस चीज़ की ज़रूरत पड़ेगी

निम्नलिखित में से कोई भी उपकरण:

  • एक भौतिक Android या iOS डिवाइस आपके कंप्यूटर से जुड़ा है और डेवलपर मोड पर सेट है।
  • iOS सिम्युलेटर ( Xcode टूल की आवश्यकता है)।
  • एंड्रॉइड एमुलेटर ( एंड्रॉइड स्टूडियो में सेटअप की आवश्यकता है)।

आपको निम्नलिखित की भी आवश्यकता है:

  • आपकी पसंद का ब्राउज़र, जैसे Google Chrome.
  • आपकी पसंद का एक आईडीई या टेक्स्ट एडिटर डार्ट और फ़्लटर प्लगइन्स, जैसे एंड्रॉइड स्टूडियो या विज़ुअल स्टूडियो कोड के साथ कॉन्फ़िगर किया गया है।
  • यदि आप किनारे पर रहना पसंद करते हैं तो फ़्लटर या beta का नवीनतम stable संस्करण।
  • आपके फायरबेस प्रोजेक्ट के निर्माण और प्रबंधन के लिए एक Google खाता।
  • Firebase सीएलआई ने आपके Google खाते में लॉग इन किया।

2. नमूना कोड प्राप्त करें

GitHub से अपने प्रोजेक्ट का प्रारंभिक संस्करण डाउनलोड करें:

  1. कमांड लाइन से, flutter-codelabs निर्देशिका में GitHub रिपॉजिटरी को क्लोन करें:
git clone https://github.com/flutter/codelabs.git flutter-codelabs

flutter-codelabs निर्देशिका में कोडलैब्स के संग्रह के लिए कोड होता है। इस कोडलैब का कोड flutter-codelabs/firebase-get-to-know-flutter निर्देशिका में है। निर्देशिका में स्नैपशॉट की एक श्रृंखला होती है जो दिखाती है कि प्रत्येक चरण के अंत में आपका प्रोजेक्ट कैसा दिखना चाहिए। उदाहरण के लिए, आप दूसरे चरण पर हैं.

  1. दूसरे चरण के लिए मेल खाने वाली फ़ाइलें ढूंढें:
cd flutter-codelabs/firebase-get-to-know-flutter/step_02

यदि आप आगे बढ़ना चाहते हैं या यह देखना चाहते हैं कि किसी चरण के बाद कोई चीज़ कैसी दिखनी चाहिए, तो उस चरण के नाम वाली निर्देशिका में देखें जिसमें आपकी रुचि है।

स्टार्टर ऐप आयात करें

  • अपनी पसंदीदा आईडीई में flutter-codelabs/firebase-get-to-know-flutter/step_02 निर्देशिका खोलें या आयात करें। इस निर्देशिका में कोडलैब के लिए स्टार्टर कोड शामिल है, जिसमें अभी तक काम न करने वाला फ़्लटर मीटअप ऐप शामिल है।

उन फ़ाइलों का पता लगाएँ जिन पर काम करने की आवश्यकता है

इस ऐप में कोड कई निर्देशिकाओं में फैला हुआ है। कार्यक्षमता का यह विभाजन कार्य को आसान बनाता है क्योंकि यह कोड को कार्यक्षमता के आधार पर समूहित करता है।

  • निम्नलिखित फ़ाइलों का पता लगाएँ:
    • lib/main.dart : इस फ़ाइल में मुख्य प्रविष्टि बिंदु और ऐप विजेट शामिल है।
    • lib/home_page.dart : इस फ़ाइल में होम पेज विजेट है।
    • lib/src/widgets.dart : इस फ़ाइल में ऐप की शैली को मानकीकृत करने में सहायता के लिए मुट्ठी भर विजेट शामिल हैं। वे स्टार्टर ऐप की स्क्रीन बनाते हैं।
    • lib/src/authentication.dart : इस फ़ाइल में फायरबेस ईमेल-आधारित प्रमाणीकरण के लिए लॉगिन उपयोगकर्ता अनुभव बनाने के लिए विजेट्स के एक सेट के साथ प्रमाणीकरण का आंशिक कार्यान्वयन शामिल है। ऑथ फ़्लो के लिए ये विजेट अभी तक स्टार्टर ऐप में उपयोग नहीं किए गए हैं, लेकिन आप इन्हें जल्द ही जोड़ देंगे।

आप बाकी ऐप बनाने के लिए आवश्यकतानुसार अतिरिक्त फ़ाइलें जोड़ते हैं।

lib/main.dart फ़ाइल की समीक्षा करें

यह ऐप रोबोटो को पूरे ऐप में डिफ़ॉल्ट फ़ॉन्ट बनाने के लिए google_fonts पैकेज का लाभ उठाता है। आप fonts.google.com को एक्सप्लोर कर सकते हैं और ऐप के विभिन्न हिस्सों में वहां खोजे गए फॉन्ट का उपयोग कर सकते हैं।

आप lib/src/widgets.dart फ़ाइल से Header , Paragraph और IconAndDetail के रूप में सहायक विजेट का उपयोग करते हैं। ये विजेट HomePage में वर्णित पेज लेआउट में अव्यवस्था को कम करने के लिए डुप्लिकेट कोड को खत्म करते हैं। यह एक सुसंगत रूप और अनुभव को भी सक्षम बनाता है।

यहां बताया गया है कि आपका ऐप Android, iOS, वेब और macOS पर कैसा दिखता है:

एंड्रॉइड पर ऐप की होम स्क्रीन

iOS पर ऐप की होम स्क्रीन

वेब पर ऐप की होम स्क्रीन

MacOS पर ऐप की होम स्क्रीन

3. फायरबेस प्रोजेक्ट बनाएं और कॉन्फ़िगर करें

इवेंट की जानकारी का प्रदर्शन आपके मेहमानों के लिए बहुत अच्छा है, लेकिन यह अपने आप में किसी के लिए भी बहुत उपयोगी नहीं है। आपको ऐप में कुछ गतिशील कार्यक्षमता जोड़ने की आवश्यकता है। ऐसा करने के लिए, आपको Firebase को अपने ऐप से कनेक्ट करना होगा। फायरबेस के साथ आरंभ करने के लिए, आपको एक फायरबेस प्रोजेक्ट बनाना और कॉन्फ़िगर करना होगा।

एक फायरबेस प्रोजेक्ट बनाएं

  1. फायरबेस में साइन इन करें।
  2. कंसोल में, प्रोजेक्ट जोड़ें या प्रोजेक्ट बनाएं पर क्लिक करें।
  3. प्रोजेक्ट नाम फ़ील्ड में, Firebase-Flutter-Codelab दर्ज करें और फिर जारी रखें पर क्लिक करें।

4395e4e67c08043a.png

  1. प्रोजेक्ट निर्माण विकल्पों पर क्लिक करें। यदि संकेत दिया जाए, तो फायरबेस शर्तों को स्वीकार करें, लेकिन Google Analytics का सेटअप छोड़ दें क्योंकि आप इस ऐप के लिए इसका उपयोग नहीं करेंगे।

b7138cde5f2c7b61.png

फायरबेस प्रोजेक्ट्स के बारे में अधिक जानने के लिए, फायरबेस प्रोजेक्ट्स को समझें देखें।

ऐप निम्नलिखित फायरबेस उत्पादों का उपयोग करता है, जो वेब ऐप्स के लिए उपलब्ध हैं:

  • प्रमाणीकरण: उपयोगकर्ताओं को आपके ऐप में साइन इन करने देता है।
  • फायरस्टोर: संरचित डेटा को क्लाउड पर सहेजता है और डेटा बदलने पर तुरंत सूचनाएं प्राप्त करता है।
  • फायरबेस सुरक्षा नियम: आपके डेटाबेस को सुरक्षित करता है।

इनमें से कुछ उत्पादों को विशेष कॉन्फ़िगरेशन की आवश्यकता है या आपको उन्हें फायरबेस कंसोल में सक्षम करने की आवश्यकता है।

ईमेल साइन-इन प्रमाणीकरण सक्षम करें

  1. फायरबेस कंसोल के प्रोजेक्ट अवलोकन फलक में, बिल्ड मेनू का विस्तार करें।
  2. प्रमाणीकरण > आरंभ करें > साइन-इन विधि > ईमेल/पासवर्ड > सक्षम करें > सहेजें पर क्लिक करें।

58e3e3e23c2f16a4.png

फायरस्टोर सक्षम करें

वेब ऐप चैट संदेशों को सहेजने और नए चैट संदेश प्राप्त करने के लिए फायरस्टोर का उपयोग करता है।

फायरस्टोर सक्षम करें:

  • बिल्ड मेनू में, फायरस्टोर डेटाबेस > डेटाबेस बनाएं पर क्लिक करें।

99e8429832d23fa3.png

  1. परीक्षण मोड में प्रारंभ का चयन करें और फिर सुरक्षा नियमों के बारे में अस्वीकरण पढ़ें। परीक्षण मोड यह सुनिश्चित करता है कि आप विकास के दौरान डेटाबेस पर स्वतंत्र रूप से लिख सकते हैं।

6be00e26c72ea032.png

  1. अगला क्लिक करें और फिर अपने डेटाबेस के लिए स्थान चुनें। आप डिफ़ॉल्ट का उपयोग कर सकते हैं. आप बाद में स्थान नहीं बदल सकते.

278656eefcfb0216.png

  1. सक्षम करें पर क्लिक करें.

4. फायरबेस कॉन्फ़िगर करें

फ़्लटर के साथ फ़ायरबेस का उपयोग करने के लिए, आपको FlutterFire लाइब्रेरीज़ का सही ढंग से उपयोग करने के लिए फ़्लटर प्रोजेक्ट को कॉन्फ़िगर करने के लिए निम्नलिखित कार्यों को पूरा करना होगा:

  1. अपने प्रोजेक्ट में FlutterFire निर्भरताएँ जोड़ें।
  2. फायरबेस प्रोजेक्ट पर वांछित प्लेटफॉर्म पंजीकृत करें।
  3. प्लेटफ़ॉर्म-विशिष्ट कॉन्फ़िगरेशन फ़ाइल डाउनलोड करें और फिर उसे कोड में जोड़ें।

आपके फ़्लटर ऐप की शीर्ष-स्तरीय निर्देशिका में, android , ios , macos और web उपनिर्देशिकाएं हैं, जो क्रमशः आईओएस और एंड्रॉइड के लिए प्लेटफ़ॉर्म-विशिष्ट कॉन्फ़िगरेशन फ़ाइलें रखती हैं।

निर्भरताएँ कॉन्फ़िगर करें

आपको इस ऐप में उपयोग किए जाने वाले दो फायरबेस उत्पादों के लिए FlutterFire लाइब्रेरीज़ जोड़ने की आवश्यकता है: प्रमाणीकरण और फायरस्टोर।

  • कमांड लाइन से, निम्नलिखित निर्भरताएँ जोड़ें:
$ flutter pub add firebase_core

firebase_core पैकेज सभी फायरबेस फ़्लटर प्लगइन्स के लिए आवश्यक सामान्य कोड है।

$ flutter pub add firebase_auth

firebase_auth पैकेज प्रमाणीकरण के साथ एकीकरण को सक्षम बनाता है।

$ flutter pub add cloud_firestore

cloud_firestore पैकेज फायरस्टोर डेटा स्टोरेज तक पहुंच सक्षम बनाता है।

$ flutter pub add provider

firebase_ui_auth पैकेज प्रमाणीकरण प्रवाह के साथ डेवलपर वेग को बढ़ाने के लिए विजेट और उपयोगिताओं का एक सेट प्रदान करता है।

$ flutter pub add firebase_ui_auth

आपने आवश्यक पैकेज जोड़े हैं, लेकिन फायरबेस का उचित उपयोग करने के लिए आपको iOS, Android, macOS और वेब रनर प्रोजेक्ट को भी कॉन्फ़िगर करना होगा। आप provider पैकेज का भी उपयोग करते हैं जो व्यावसायिक तर्क को प्रदर्शन तर्क से अलग करने में सक्षम बनाता है।

फ़्लटरफ़ायर सीएलआई स्थापित करें

फ़्लटरफ़ायर सीएलआई अंतर्निहित फायरबेस सीएलआई पर निर्भर करता है।

  1. यदि आपने पहले से ऐसा नहीं किया है, तो अपनी मशीन पर फायरबेस सीएलआई स्थापित करें।
  2. फ़्लटरफ़ायर सीएलआई स्थापित करें:
$ dart pub global activate flutterfire_cli

एक बार स्थापित होने के बाद, flutterfire कमांड विश्व स्तर पर उपलब्ध है।

अपने ऐप्स कॉन्फ़िगर करें

सीएलआई एक विशिष्ट प्लेटफ़ॉर्म के लिए सभी कॉन्फ़िगरेशन उत्पन्न करने के लिए आपके फायरबेस प्रोजेक्ट और चयनित प्रोजेक्ट ऐप्स से जानकारी निकालता है।

अपने ऐप के रूट में, configure कमांड चलाएँ:

$ flutterfire configure

कॉन्फ़िगरेशन कमांड आपको निम्नलिखित प्रक्रियाओं में मार्गदर्शन करता है:

  1. .firebaserc फ़ाइल के आधार पर या Firebase कंसोल से एक Firebase प्रोजेक्ट चुनें।
  2. कॉन्फ़िगरेशन के लिए प्लेटफ़ॉर्म निर्धारित करें, जैसे Android, iOS, macOS और वेब।
  3. उन फ़ायरबेस ऐप्स की पहचान करें जिनसे कॉन्फ़िगरेशन निकालना है। डिफ़ॉल्ट रूप से, सीएलआई आपके वर्तमान प्रोजेक्ट कॉन्फ़िगरेशन के आधार पर स्वचालित रूप से फायरबेस ऐप्स से मिलान करने का प्रयास करता है।
  4. अपने प्रोजेक्ट में एक firebase_options.dart फ़ाइल जनरेट करें।

MacOS कॉन्फ़िगर करें

MacOS पर फ़्लटर पूरी तरह से सैंडबॉक्स्ड ऐप्स बनाता है। चूंकि यह ऐप फायरबेस सर्वर के साथ संचार करने के लिए नेटवर्क के साथ एकीकृत होता है, इसलिए आपको अपने ऐप को नेटवर्क क्लाइंट विशेषाधिकारों के साथ कॉन्फ़िगर करना होगा।

मैकोज़/रनर/डीबगप्रोफ़ाइल.एंटाइटलमेंट

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
	<key>com.apple.security.cs.allow-jit</key>
	<true/>
	<key>com.apple.security.network.server</key>
	<true/>
  <!-- Add the following two lines -->
	<key>com.apple.security.network.client</key>
	<true/>
</dict>
</plist>

मैकोज़/रनर/रिलीज़.एंटाइटलमेंट

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
  <!-- Add the following two lines -->
	<key>com.apple.security.network.client</key>
	<true/>
</dict>
</plist>

अधिक जानकारी के लिए, फ़्लटर के लिए डेस्कटॉप समर्थन देखें।

5. आरएसवीपी कार्यक्षमता जोड़ें

अब जब आपने ऐप में फायरबेस जोड़ लिया है, तो आप एक आरएसवीपी बटन बना सकते हैं जो प्रमाणीकरण के साथ लोगों को पंजीकृत करता है। एंड्रॉइड नेटिव, आईओएस नेटिव और वेब के लिए, प्रीबिल्ट FirebaseUI Auth पैकेज हैं, लेकिन आपको फ़्लटर के लिए इस क्षमता का निर्माण करने की आवश्यकता है।

आपके द्वारा पहले पुनर्प्राप्त किए गए प्रोजेक्ट में विजेट्स का एक सेट शामिल था जो अधिकांश प्रमाणीकरण प्रवाह के लिए उपयोगकर्ता इंटरफ़ेस लागू करता है। आप ऐप के साथ प्रमाणीकरण को एकीकृत करने के लिए व्यावसायिक तर्क लागू करते हैं।

Provider पैकेज के साथ व्यावसायिक तर्क जोड़ें

फ़्लटर विजेट्स के ऐप ट्री में एक केंद्रीकृत ऐप स्टेट ऑब्जेक्ट उपलब्ध कराने के लिए provider पैकेज का उपयोग करें:

  1. निम्नलिखित सामग्री के साथ app_state.dart नामक एक नई फ़ाइल बनाएँ:

lib/app_state.dart

import 'package:firebase_auth/firebase_auth.dart'
    hide EmailAuthProvider, PhoneAuthProvider;
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'firebase_options.dart';

class ApplicationState extends ChangeNotifier {
  ApplicationState() {
    init();
  }

  bool _loggedIn = false;
  bool get loggedIn => _loggedIn;

  Future<void> init() async {
    await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform);

    FirebaseUIAuth.configureProviders([
      EmailAuthProvider(),
    ]);

    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loggedIn = true;
      } else {
        _loggedIn = false;
      }
      notifyListeners();
    });
  }
}

import विवरण फायरबेस कोर और ऑथ का परिचय देते हैं, provider पैकेज को खींचते हैं जो ऐप स्टेट ऑब्जेक्ट को पूरे विजेट ट्री में उपलब्ध कराता है, और firebase_ui_auth पैकेज से प्रमाणीकरण विजेट शामिल करता है।

इस ApplicationState एप्लिकेशन स्टेट ऑब्जेक्ट की इस चरण के लिए एक मुख्य जिम्मेदारी है, जो कि विजेट ट्री को सचेत करना है कि एक प्रमाणित स्थिति के लिए एक अपडेट था।

आप ऐप पर उपयोगकर्ता की लॉगिन स्थिति की स्थिति बताने के लिए केवल प्रदाता का उपयोग करते हैं। किसी उपयोगकर्ता को लॉग इन करने देने के लिए, आप firebase_ui_auth पैकेज द्वारा प्रदान किए गए UI का उपयोग करते हैं, जो आपके ऐप्स में लॉगिन स्क्रीन को त्वरित रूप से बूटस्ट्रैप करने का एक शानदार तरीका है।

प्रमाणीकरण प्रवाह को एकीकृत करें

  1. lib/main.dart फ़ाइल के शीर्ष पर आयात को संशोधित करें:

lib/main.dart

import 'package:firebase_ui_auth/firebase_ui_auth.dart'; // new
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';               // new
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';                 // new

import 'app_state.dart';                                 // new
import 'home_page.dart';
  1. ऐप स्थिति को ऐप इनिशियलाइज़ेशन से कनेक्ट करें और फिर HomePage पर प्रमाणीकरण प्रवाह जोड़ें:

lib/main.dart

void main() {
  // Modify from here...
  WidgetsFlutterBinding.ensureInitialized();

  runApp(ChangeNotifierProvider(
    create: (context) => ApplicationState(),
    builder: ((context, child) => const App()),
  ));
  // ...to here.
}

main() फ़ंक्शन में संशोधन प्रदाता पैकेज को ChangeNotifierProvider विजेट के साथ ऐप स्थिति ऑब्जेक्ट के इंस्टेंटेशन के लिए जिम्मेदार बनाता है। आप इस विशिष्ट provider वर्ग का उपयोग करते हैं क्योंकि ऐप स्टेट ऑब्जेक्ट ChangeNotifier क्लास का विस्तार करता है, जो provider पैकेज को यह बताता है कि निर्भर विजेट को कब फिर से प्रदर्शित करना है।

  1. GoRouter कॉन्फ़िगरेशन बनाकर FirebaseUI द्वारा आपके लिए प्रदान की जाने वाली विभिन्न स्क्रीन पर नेविगेशन को संभालने के लिए अपने ऐप को अपडेट करें:

lib/main.dart

// Add GoRouter configuration outside the App class
final _router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const HomePage(),
      routes: [
        GoRoute(
          path: 'sign-in',
          builder: (context, state) {
            return SignInScreen(
              actions: [
                ForgotPasswordAction(((context, email) {
                  final uri = Uri(
                    path: '/sign-in/forgot-password',
                    queryParameters: <String, String?>{
                      'email': email,
                    },
                  );
                  context.push(uri.toString());
                })),
                AuthStateChangeAction(((context, state) {
                  final user = switch (state) {
                    SignedIn state => state.user,
                    UserCreated state => state.credential.user,
                    _ => null
                  };
                  if (user == null) {
                    return;
                  }
                  if (state is UserCreated) {
                    user.updateDisplayName(user.email!.split('@')[0]);
                  }
                  if (!user.emailVerified) {
                    user.sendEmailVerification();
                    const snackBar = SnackBar(
                        content: Text(
                            'Please check your email to verify your email address'));
                    ScaffoldMessenger.of(context).showSnackBar(snackBar);
                  }
                  context.pushReplacement('/');
                })),
              ],
            );
          },
          routes: [
            GoRoute(
              path: 'forgot-password',
              builder: (context, state) {
                final arguments = state.uri.queryParameters;
                return ForgotPasswordScreen(
                  email: arguments['email'],
                  headerMaxExtent: 200,
                );
              },
            ),
          ],
        ),
        GoRoute(
          path: 'profile',
          builder: (context, state) {
            return ProfileScreen(
              providers: const [],
              actions: [
                SignedOutAction((context) {
                  context.pushReplacement('/');
                }),
              ],
            );
          },
        ),
      ],
    ),
  ],
);
// end of GoRouter configuration

// Change MaterialApp to MaterialApp.router and add the routerConfig
class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Firebase Meetup',
      theme: ThemeData(
        buttonTheme: Theme.of(context).buttonTheme.copyWith(
              highlightColor: Colors.deepPurple,
            ),
        primarySwatch: Colors.deepPurple,
        textTheme: GoogleFonts.robotoTextTheme(
          Theme.of(context).textTheme,
        ),
        visualDensity: VisualDensity.adaptivePlatformDensity,
        useMaterial3: true,
      ),
      routerConfig: _router, // new
    );
  }
}

प्रमाणीकरण प्रवाह की नई स्थिति के आधार पर प्रत्येक स्क्रीन के साथ एक अलग प्रकार की क्रिया जुड़ी होती है। प्रमाणीकरण में अधिकांश स्थिति में बदलाव के बाद, आप पसंदीदा स्क्रीन पर वापस जा सकते हैं, चाहे वह होम स्क्रीन हो या कोई अलग स्क्रीन, जैसे प्रोफ़ाइल।

  1. HomePage क्लास की बिल्ड विधि में, ऐप स्थिति को AuthFunc विजेट के साथ एकीकृत करें:

lib/home_page.dart

import 'package:firebase_auth/firebase_auth.dart' // new
    hide EmailAuthProvider, PhoneAuthProvider;    // new
import 'package:flutter/material.dart';           // new
import 'package:provider/provider.dart';          // new

import 'app_state.dart';                          // new
import 'src/authentication.dart';                 // new
import 'src/widgets.dart';

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Firebase Meetup'),
      ),
      body: ListView(
        children: <Widget>[
          Image.asset('assets/codelab.png'),
          const SizedBox(height: 8),
          const IconAndDetail(Icons.calendar_today, 'October 30'),
          const IconAndDetail(Icons.location_city, 'San Francisco'),
          // Add from here
          Consumer<ApplicationState>(
            builder: (context, appState, _) => AuthFunc(
                loggedIn: appState.loggedIn,
                signOut: () {
                  FirebaseAuth.instance.signOut();
                }),
          ),
          // to here
          const Divider(
            height: 8,
            thickness: 1,
            indent: 8,
            endIndent: 8,
            color: Colors.grey,
          ),
          const Header("What we'll be doing"),
          const Paragraph(
            'Join us for a day full of Firebase Workshops and Pizza!',
          ),
        ],
      ),
    );
  }
}

आप AuthFunc विजेट को इंस्टेंटियेट करते हैं और इसे Consumer विजेट में लपेटते हैं। उपभोक्ता विजेट सामान्य तरीका है जिससे ऐप की स्थिति बदलने पर provider पैकेज का उपयोग पेड़ के हिस्से को फिर से बनाने के लिए किया जा सकता है। AuthFunc विजेट पूरक विजेट है जिसका आप परीक्षण करते हैं।

प्रमाणीकरण प्रवाह का परीक्षण करें

cdf2d25e436bd48d.png

  1. ऐप में, SignInScreen आरंभ करने के लिए आरएसवीपी बटन पर टैप करें।

2a2cd6d69d172369.png

  1. कोई ईमेल पता डालें। यदि आप पहले से पंजीकृत हैं, तो सिस्टम आपको पासवर्ड दर्ज करने के लिए संकेत देगा। अन्यथा, सिस्टम आपको पंजीकरण फॉर्म पूरा करने के लिए संकेत देगा।

e5e65065dba36b54.png

  1. त्रुटि-हैंडलिंग प्रवाह की जांच करने के लिए छह अक्षरों से कम का पासवर्ड दर्ज करें। यदि आप पंजीकृत हैं, तो आपको इसके लिए पासवर्ड दिखाई देगा।
  2. त्रुटि-हैंडलिंग प्रवाह की जांच करने के लिए गलत पासवर्ड दर्ज करें।
  3. सही पासवर्ड दर्ज करें. आप लॉग-इन अनुभव देखते हैं, जो उपयोगकर्ता को लॉग आउट करने की क्षमता प्रदान करता है।

4ed811a25b0cf816.png

6. फायरस्टोर को संदेश लिखें

यह जानना बहुत अच्छा है कि उपयोगकर्ता आ रहे हैं, लेकिन आपको मेहमानों को ऐप में कुछ और करने के लिए देना होगा। क्या होगा यदि वे अतिथि पुस्तिका में संदेश छोड़ सकें? वे साझा कर सकते हैं कि वे आने के लिए क्यों उत्साहित हैं या वे किससे मिलने की उम्मीद करते हैं।

उपयोगकर्ताओं द्वारा ऐप में लिखे गए चैट संदेशों को संग्रहीत करने के लिए, आप फायरस्टोर का उपयोग करते हैं।

डेटा मॉडल

फायरस्टोर एक NoSQL डेटाबेस है, और डेटाबेस में संग्रहीत डेटा को संग्रह, दस्तावेज़, फ़ील्ड और उपसंग्रह में विभाजित किया गया है। आप चैट के प्रत्येक संदेश को guestbook संग्रह में एक दस्तावेज़ के रूप में संग्रहीत करते हैं, जो एक शीर्ष-स्तरीय संग्रह है।

7c20dc8424bb1d84.png

फायरस्टोर में संदेश जोड़ें

इस अनुभाग में, आप उपयोगकर्ताओं के लिए डेटाबेस में संदेश लिखने की कार्यक्षमता जोड़ते हैं। सबसे पहले, आप एक फॉर्म फ़ील्ड जोड़ते हैं और बटन भेजते हैं, और फिर आप वह कोड जोड़ते हैं जो इन तत्वों को डेटाबेस से जोड़ता है।

  1. guest_book.dart नामक एक नई फ़ाइल बनाएं, संदेश फ़ील्ड और सेंड बटन के यूआई तत्वों के निर्माण के लिए एक GuestBook स्टेटफुल विजेट जोड़ें:

lib/guest_book.dart

import 'dart:async';

import 'package:flutter/material.dart';

import 'src/widgets.dart';

class GuestBook extends StatefulWidget {
  const GuestBook({required this.addMessage, super.key});

  final FutureOr<void> Function(String message) addMessage;

  @override
  State<GuestBook> createState() => _GuestBookState();
}

class _GuestBookState extends State<GuestBook> {
  final _formKey = GlobalKey<FormState>(debugLabel: '_GuestBookState');
  final _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Form(
        key: _formKey,
        child: Row(
          children: [
            Expanded(
              child: TextFormField(
                controller: _controller,
                decoration: const InputDecoration(
                  hintText: 'Leave a message',
                ),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Enter your message to continue';
                  }
                  return null;
                },
              ),
            ),
            const SizedBox(width: 8),
            StyledButton(
              onPressed: () async {
                if (_formKey.currentState!.validate()) {
                  await widget.addMessage(_controller.text);
                  _controller.clear();
                }
              },
              child: Row(
                children: const [
                  Icon(Icons.send),
                  SizedBox(width: 4),
                  Text('SEND'),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

यहां रुचि के कुछ बिंदु हैं। सबसे पहले, आप एक फॉर्म इंस्टेंटियेट करते हैं ताकि आप सत्यापित कर सकें कि संदेश में वास्तव में सामग्री है और यदि कोई सामग्री नहीं है तो उपयोगकर्ता को एक त्रुटि संदेश दिखाएं। किसी फॉर्म को सत्यापित करने के लिए, आप GlobalKey के साथ फॉर्म के पीछे फॉर्म स्थिति तक पहुंचते हैं। कुंजियों और उनका उपयोग करने के तरीके के बारे में अधिक जानकारी के लिए, कुंजियों का उपयोग कब करें देखें।

इस बात पर भी ध्यान दें कि विजेट्स को किस तरह से रखा गया है, आपके पास एक TextFormField के साथ एक Row और एक StyledButton है, जिसमें एक Row है। यह भी ध्यान रखें TextFormField एक Expanded विजेट में लपेटा गया है, जो TextFormField पंक्ति में कोई अतिरिक्त स्थान भरने के लिए बाध्य करता है। यह बेहतर ढंग से समझने के लिए कि इसकी आवश्यकता क्यों है, बाधाओं को समझना देखें।

अब जब आपके पास एक विजेट है जो उपयोगकर्ता को अतिथि पुस्तक में जोड़ने के लिए कुछ पाठ दर्ज करने में सक्षम बनाता है, तो आपको इसे स्क्रीन पर लाने की आवश्यकता है।

  1. ListView के बच्चों के अंत में निम्नलिखित दो पंक्तियाँ जोड़ने के लिए HomePage के मुख्य भाग को संपादित करें:
const Header("What we'll be doing"),
const Paragraph(
  'Join us for a day full of Firebase Workshops and Pizza!',
),
// Add the following two lines.
const Header('Discussion'),
GuestBook(addMessage: (message) => print(message)),

हालाँकि यह विजेट प्रदर्शित करने के लिए पर्याप्त है, लेकिन यह कुछ भी उपयोगी करने के लिए पर्याप्त नहीं है। आप इस कोड को क्रियाशील बनाने के लिए शीघ्र ही अद्यतन करें।

ऐप पूर्वावलोकन

चैट एकीकरण के साथ एंड्रॉइड पर ऐप की होम स्क्रीन

चैट एकीकरण के साथ iOS पर ऐप की होम स्क्रीन

चैट एकीकरण के साथ वेब पर ऐप की होम स्क्रीन

चैट एकीकरण के साथ macOS पर ऐप की होम स्क्रीन

जब कोई उपयोगकर्ता SEND पर क्लिक करता है, तो यह निम्नलिखित कोड स्निपेट को ट्रिगर करता है। यह संदेश इनपुट फ़ील्ड की सामग्री को डेटाबेस के guestbook संग्रह में जोड़ता है। विशेष रूप से, addMessageToGuestBook विधि guestbook संग्रह में स्वचालित रूप से जेनरेट की गई आईडी के साथ संदेश सामग्री को एक नए दस्तावेज़ में जोड़ती है।

ध्यान दें कि FirebaseAuth.instance.currentUser.uid ऑटोजेनरेटेड यूनिक आईडी का एक संदर्भ है जो प्रमाणीकरण सभी लॉग-इन उपयोगकर्ताओं के लिए देता है।

  • lib/app_state.dart फ़ाइल में, addMessageToGuestBook विधि जोड़ें। आप इस क्षमता को अगले चरण में यूजर इंटरफ़ेस से जोड़ते हैं।

lib/app_state.dart

import 'package:cloud_firestore/cloud_firestore.dart'; // new
import 'package:firebase_auth/firebase_auth.dart'
    hide EmailAuthProvider, PhoneAuthProvider;
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'firebase_options.dart';

class ApplicationState extends ChangeNotifier {

  // Current content of ApplicationState elided ...

  // Add from here...
  Future<DocumentReference> addMessageToGuestBook(String message) {
    if (!_loggedIn) {
      throw Exception('Must be logged in');
    }

    return FirebaseFirestore.instance
        .collection('guestbook')
        .add(<String, dynamic>{
      'text': message,
      'timestamp': DateTime.now().millisecondsSinceEpoch,
      'name': FirebaseAuth.instance.currentUser!.displayName,
      'userId': FirebaseAuth.instance.currentUser!.uid,
    });
  }
  // ...to here.
}

यूआई और डेटाबेस कनेक्ट करें

आपके पास एक यूआई है जहां उपयोगकर्ता वह टेक्स्ट दर्ज कर सकता है जिसे वे गेस्ट बुक में जोड़ना चाहते हैं और आपके पास फायरस्टोर में प्रविष्टि जोड़ने के लिए कोड है। अब आपको बस दोनों को कनेक्ट करना है।

  • lib/home_page.dart फ़ाइल में, HomePage विजेट में निम्नलिखित परिवर्तन करें:

lib/home_page.dart

import 'package:firebase_auth/firebase_auth.dart'
    hide EmailAuthProvider, PhoneAuthProvider;
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'app_state.dart';
import 'guest_book.dart';                         // new
import 'src/authentication.dart';
import 'src/widgets.dart';

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Firebase Meetup'),
      ),
      body: ListView(
        children: <Widget>[
          Image.asset('assets/codelab.png'),
          const SizedBox(height: 8),
          const IconAndDetail(Icons.calendar_today, 'October 30'),
          const IconAndDetail(Icons.location_city, 'San Francisco'),
          Consumer<ApplicationState>(
            builder: (context, appState, _) => AuthFunc(
                loggedIn: appState.loggedIn,
                signOut: () {
                  FirebaseAuth.instance.signOut();
                }),
          ),
          const Divider(
            height: 8,
            thickness: 1,
            indent: 8,
            endIndent: 8,
            color: Colors.grey,
          ),
          const Header("What we'll be doing"),
          const Paragraph(
            'Join us for a day full of Firebase Workshops and Pizza!',
          ),
          // Modify from here...
          Consumer<ApplicationState>(
            builder: (context, appState, _) => Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                if (appState.loggedIn) ...[
                  const Header('Discussion'),
                  GuestBook(
                    addMessage: (message) =>
                        appState.addMessageToGuestBook(message),
                  ),
                ],
              ],
            ),
          ),
          // ...to here.
        ],
      ),
    );
  }
}

आपने इस चरण की शुरुआत में जोड़ी गई दो पंक्तियों को पूर्ण कार्यान्वयन के साथ बदल दिया है। आप अपने द्वारा रेंडर किए गए ट्री के भाग के लिए ऐप स्थिति उपलब्ध कराने के लिए फिर से Consumer<ApplicationState> का उपयोग करते हैं। यह आपको किसी ऐसे व्यक्ति पर प्रतिक्रिया करने देता है जो यूआई में एक संदेश दर्ज करता है और इसे डेटाबेस में प्रकाशित करता है। अगले अनुभाग में, आप परीक्षण करते हैं कि जोड़े गए संदेश डेटाबेस में प्रकाशित हैं या नहीं।

संदेश भेजने का परीक्षण करें

  1. यदि आवश्यक हो, तो ऐप में साइन इन करें।
  2. एक संदेश दर्ज करें, जैसे Hey there! , और फिर भेजें पर क्लिक करें।

यह क्रिया आपके फायरस्टोर डेटाबेस पर संदेश लिखती है। हालाँकि, आपको अपने वास्तविक फ़्लटर ऐप में संदेश दिखाई नहीं देता है क्योंकि आपको अभी भी डेटा की पुनर्प्राप्ति को लागू करने की आवश्यकता है, जो आप अगले चरण में करते हैं। हालाँकि, फायरबेस कंसोल के डेटाबेस डैशबोर्ड में, आप guestbook संग्रह में अपना जोड़ा गया संदेश देख सकते हैं। यदि आप अधिक संदेश भेजते हैं, तो आप अपने guestbook संग्रह में अधिक दस्तावेज़ जोड़ते हैं। उदाहरण के लिए, निम्नलिखित कोड स्निपेट देखें:

713870af0b3b63c.png

7. संदेश पढ़ें

यह बहुत अच्छा है कि मेहमान डेटाबेस में संदेश लिख सकते हैं, लेकिन वे उन्हें अभी तक ऐप में नहीं देख सकते हैं। इसे ठीक करने का समय आ गया है!

संदेशों को सिंक्रनाइज़ करें

संदेशों को प्रदर्शित करने के लिए, आपको श्रोताओं को जोड़ना होगा जो डेटा बदलने पर ट्रिगर होते हैं और फिर एक यूआई तत्व बनाते हैं जो नए संदेश दिखाता है। आप ऐप स्थिति में कोड जोड़ते हैं जो ऐप से नए जोड़े गए संदेशों को सुनता है।

  1. एक नई फ़ाइल बनाएं guest_book_message.dart , फायरस्टोर में आपके द्वारा संग्रहीत डेटा का एक संरचित दृश्य प्रदर्शित करने के लिए निम्न वर्ग जोड़ें।

lib/guest_book_message.dart

class GuestBookMessage {
  GuestBookMessage({required this.name, required this.message});

  final String name;
  final String message;
}
  1. lib/app_state.dart फ़ाइल में, निम्नलिखित आयात जोड़ें:

lib/app_state.dart

import 'dart:async';                                     // new

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart'
    hide EmailAuthProvider, PhoneAuthProvider;
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'firebase_options.dart';
import 'guest_book_message.dart';                        // new
  1. ApplicationState के अनुभाग में जहां आप राज्य और गेटर्स को परिभाषित करते हैं, निम्नलिखित पंक्तियां जोड़ें:

lib/app_state.dart

  bool _loggedIn = false;
  bool get loggedIn => _loggedIn;

  // Add from here...
  StreamSubscription<QuerySnapshot>? _guestBookSubscription;
  List<GuestBookMessage> _guestBookMessages = [];
  List<GuestBookMessage> get guestBookMessages => _guestBookMessages;
  // ...to here.
  1. ApplicationState के आरंभीकरण अनुभाग में, जब कोई उपयोगकर्ता लॉग इन करता है तो दस्तावेज़ संग्रह पर एक क्वेरी की सदस्यता लेने और लॉग आउट होने पर सदस्यता समाप्त करने के लिए निम्नलिखित पंक्तियाँ जोड़ें:

lib/app_state.dart

  Future<void> init() async {
    await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform);

    FirebaseUIAuth.configureProviders([
      EmailAuthProvider(),
    ]);
    
    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loggedIn = true;
        _guestBookSubscription = FirebaseFirestore.instance
            .collection('guestbook')
            .orderBy('timestamp', descending: true)
            .snapshots()
            .listen((snapshot) {
          _guestBookMessages = [];
          for (final document in snapshot.docs) {
            _guestBookMessages.add(
              GuestBookMessage(
                name: document.data()['name'] as String,
                message: document.data()['text'] as String,
              ),
            );
          }
          notifyListeners();
        });
      } else {
        _loggedIn = false;
        _guestBookMessages = [];
        _guestBookSubscription?.cancel();
      }
      notifyListeners();
    });
  }

यह अनुभाग महत्वपूर्ण है क्योंकि यह वह जगह है जहां आप guestbook संग्रह पर एक क्वेरी बनाते हैं, और इस संग्रह की सदस्यता लेने और सदस्यता समाप्त करने का प्रबंधन करते हैं। आप स्ट्रीम सुनते हैं, जहां आप guestbook संग्रह में संदेशों के स्थानीय कैश को फिर से बनाते हैं और इस सदस्यता का एक संदर्भ भी संग्रहीत करते हैं ताकि आप बाद में इससे सदस्यता समाप्त कर सकें। यहां बहुत कुछ चल रहा है, इसलिए एक स्पष्ट मानसिक मॉडल प्राप्त करने के लिए क्या होता है इसका निरीक्षण करने के लिए आपको डिबगर में इसका पता लगाना चाहिए। अधिक जानकारी के लिए, फायरस्टोर के साथ रीयलटाइम अपडेट प्राप्त करें देखें।

  1. lib/guest_book.dart फ़ाइल में, निम्नलिखित आयात जोड़ें:
import 'guest_book_message.dart';
  1. GuestBook विजेट में, इस बदलती स्थिति को उपयोगकर्ता इंटरफ़ेस से जोड़ने के लिए कॉन्फ़िगरेशन के हिस्से के रूप में संदेशों की एक सूची जोड़ें:

lib/guest_book.dart

class GuestBook extends StatefulWidget {
  // Modify the following line:
  const GuestBook({
    super.key, 
    required this.addMessage, 
    required this.messages,
  });

  final FutureOr<void> Function(String message) addMessage;
  final List<GuestBookMessage> messages; // new

  @override
  _GuestBookState createState() => _GuestBookState();
}
  1. _GuestBookState में, इस कॉन्फ़िगरेशन को उजागर करने के लिए build विधि को निम्नानुसार संशोधित करें:

lib/guest_book.dart

class _GuestBookState extends State<GuestBook> {
  final _formKey = GlobalKey<FormState>(debugLabel: '_GuestBookState');
  final _controller = TextEditingController();

  @override
  // Modify from here...
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // ...to here.
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Form(
            key: _formKey,
            child: Row(
              children: [
                Expanded(
                  child: TextFormField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      hintText: 'Leave a message',
                    ),
                    validator: (value) {
                      if (value == null || value.isEmpty) {
                        return 'Enter your message to continue';
                      }
                      return null;
                    },
                  ),
                ),
                const SizedBox(width: 8),
                StyledButton(
                  onPressed: () async {
                    if (_formKey.currentState!.validate()) {
                      await widget.addMessage(_controller.text);
                      _controller.clear();
                    }
                  },
                  child: Row(
                    children: const [
                      Icon(Icons.send),
                      SizedBox(width: 4),
                      Text('SEND'),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
        // Modify from here...
        const SizedBox(height: 8),
        for (var message in widget.messages)
          Paragraph('${message.name}: ${message.message}'),
        const SizedBox(height: 8),
      ],
      // ...to here.
    );
  }
}

आप build() विधि की पिछली सामग्री को Column विजेट के साथ लपेटते हैं और फिर आप संदेशों की सूची में प्रत्येक संदेश के लिए एक नया Paragraph उत्पन्न करने के लिए Column के बच्चों के पीछे एक संग्रह जोड़ते हैं।

  1. नए messages पैरामीटर के साथ GuestBook सही ढंग से बनाने के लिए HomePage के मुख्य भाग को अपडेट करें:

lib/home_page.dart

Consumer<ApplicationState>(
  builder: (context, appState, _) => Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      if (appState.loggedIn) ...[
        const Header('Discussion'),
        GuestBook(
          addMessage: (message) =>
              appState.addMessageToGuestBook(message),
          messages: appState.guestBookMessages, // new
        ),
      ],
    ],
  ),
),

संदेश सिंक्रनाइज़ेशन का परीक्षण करें

फायरस्टोर स्वचालित रूप से और तुरंत डेटाबेस में सब्सक्राइब किए गए ग्राहकों के साथ डेटा को सिंक्रनाइज़ करता है।

परीक्षण संदेश तुल्यकालन:

  1. ऐप में, वे संदेश ढूंढें जो आपने पहले डेटाबेस में बनाए थे।
  2. नए संदेश लिखें. वे तुरंत प्रकट हो जाते हैं.
  3. अपने कार्यक्षेत्र को एकाधिक विंडो या टैब में खोलें। संदेश वास्तविक समय में विंडो और टैब पर सिंक होते हैं।
  4. वैकल्पिक: फायरबेस कंसोल के डेटाबेस मेनू में, मैन्युअल रूप से हटाएं, संशोधित करें या नए संदेश जोड़ें। सभी परिवर्तन यूआई में दिखाई देते हैं।

बधाई हो! आप अपने ऐप में फायरस्टोर दस्तावेज़ पढ़ते हैं!

ऐप पूर्वावलोकन

चैट एकीकरण के साथ एंड्रॉइड पर ऐप की होम स्क्रीन

चैट एकीकरण के साथ iOS पर ऐप की होम स्क्रीन

चैट एकीकरण के साथ वेब पर ऐप की होम स्क्रीन

चैट एकीकरण के साथ macOS पर ऐप की होम स्क्रीन

8. बुनियादी सुरक्षा नियम स्थापित करें

आपने प्रारंभ में परीक्षण मोड का उपयोग करने के लिए फायरस्टोर को सेट किया है, जिसका अर्थ है कि आपका डेटाबेस पढ़ने और लिखने के लिए खुला है। हालाँकि, आपको परीक्षण मोड का उपयोग केवल विकास के प्रारंभिक चरणों के दौरान ही करना चाहिए। सर्वोत्तम अभ्यास के रूप में, आपको अपना ऐप विकसित करते समय अपने डेटाबेस के लिए सुरक्षा नियम स्थापित करने चाहिए। सुरक्षा आपके ऐप की संरचना और व्यवहार का अभिन्न अंग है।

फायरबेस सुरक्षा नियम आपको अपने डेटाबेस में दस्तावेज़ों और संग्रहों तक पहुंच को नियंत्रित करने देते हैं। लचीला नियम सिंटैक्स आपको ऐसे नियम बनाने की सुविधा देता है जो संपूर्ण डेटाबेस में सभी लेखन से लेकर किसी विशिष्ट दस्तावेज़ पर संचालन तक किसी भी चीज़ से मेल खाते हैं।

बुनियादी सुरक्षा नियम स्थापित करें:

  1. फायरबेस कंसोल के डेवलप मेनू में, डेटाबेस > नियम पर क्लिक करें। आपको निम्नलिखित डिफ़ॉल्ट सुरक्षा नियम और नियमों के सार्वजनिक होने के बारे में एक चेतावनी देखनी चाहिए:

7767a2d2e64e7275.png

  1. उन संग्रहों की पहचान करें जिनमें ऐप डेटा लिखता है:

match /databases/{database}/documents में, उस संग्रह की पहचान करें जिसे आप सुरक्षित करना चाहते हैं:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
     // You'll add rules here in the next step.
  }
}

क्योंकि आपने प्रत्येक गेस्टबुक दस्तावेज़ में प्रमाणीकरण यूआईडी को एक फ़ील्ड के रूप में उपयोग किया है, आप प्रमाणीकरण यूआईडी प्राप्त कर सकते हैं और सत्यापित कर सकते हैं कि दस्तावेज़ में लिखने का प्रयास करने वाले किसी भी व्यक्ति के पास मिलान प्रमाणीकरण यूआईडी है।

  1. अपने नियम सेट में पढ़ने और लिखने के नियम जोड़ें:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
      allow read: if request.auth.uid != null;
      allow write:
        if request.auth.uid == request.resource.data.userId;
    }
  }
}

अब, केवल साइन-इन किए हुए उपयोगकर्ता ही अतिथि पुस्तिका में संदेश पढ़ सकते हैं, लेकिन केवल संदेश का लेखक ही संदेश को संपादित कर सकता है।

  1. यह सुनिश्चित करने के लिए डेटा सत्यापन जोड़ें कि सभी अपेक्षित फ़ील्ड दस्तावेज़ में मौजूद हैं:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
      allow read: if request.auth.uid != null;
      allow write:
      if request.auth.uid == request.resource.data.userId
          && "name" in request.resource.data
          && "text" in request.resource.data
          && "timestamp" in request.resource.data;
    }
  }
}

9. बोनस चरण: आपने जो सीखा है उसका अभ्यास करें

किसी सहभागी की आरएसवीपी स्थिति रिकॉर्ड करें

अभी, आपका ऐप लोगों को केवल तभी चैट करने की अनुमति देता है जब वे ईवेंट में रुचि रखते हों। इसके अलावा, आपको यह जानने का एकमात्र तरीका है कि कोई आ रहा है या नहीं, जब वे चैट में ऐसा कहते हैं।

इस चरण में, आप संगठित हो जाते हैं और लोगों को बताते हैं कि कितने लोग आ रहे हैं। आप ऐप स्थिति में कुछ क्षमताएं जोड़ते हैं। पहली बात यह है कि लॉग-इन किए गए उपयोगकर्ता के लिए यह नामांकित करने की क्षमता है कि वे भाग ले रहे हैं या नहीं। दूसरा यह काउंटर है कि कितने लोग शामिल हो रहे हैं।

  1. lib/app_state.dart फ़ाइल में, ApplicationState के एक्सेसर्स सेक्शन में निम्नलिखित पंक्तियाँ जोड़ें ताकि UI कोड इस स्थिति के साथ इंटरैक्ट कर सके:

lib/app_state.dart

int _attendees = 0;
int get attendees => _attendees;

Attending _attending = Attending.unknown;
StreamSubscription<DocumentSnapshot>? _attendingSubscription;
Attending get attending => _attending;
set attending(Attending attending) {
  final userDoc = FirebaseFirestore.instance
      .collection('attendees')
      .doc(FirebaseAuth.instance.currentUser!.uid);
  if (attending == Attending.yes) {
    userDoc.set(<String, dynamic>{'attending': true});
  } else {
    userDoc.set(<String, dynamic>{'attending': false});
  }
}
  1. ApplicationState की init() विधि को निम्नानुसार अपडेट करें:

lib/app_state.dart

  Future<void> init() async {
    await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform);

    FirebaseUIAuth.configureProviders([
      EmailAuthProvider(),
    ]);

    // Add from here...
    FirebaseFirestore.instance
        .collection('attendees')
        .where('attending', isEqualTo: true)
        .snapshots()
        .listen((snapshot) {
      _attendees = snapshot.docs.length;
      notifyListeners();
    });
    // ...to here.

    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loggedIn = true;
        _emailVerified = user.emailVerified;
        _guestBookSubscription = FirebaseFirestore.instance
            .collection('guestbook')
            .orderBy('timestamp', descending: true)
            .snapshots()
            .listen((snapshot) {
          _guestBookMessages = [];
          for (final document in snapshot.docs) {
            _guestBookMessages.add(
              GuestBookMessage(
                name: document.data()['name'] as String,
                message: document.data()['text'] as String,
              ),
            );
          }
          notifyListeners();
        });
        // Add from here...
        _attendingSubscription = FirebaseFirestore.instance
            .collection('attendees')
            .doc(user.uid)
            .snapshots()
            .listen((snapshot) {
          if (snapshot.data() != null) {
            if (snapshot.data()!['attending'] as bool) {
              _attending = Attending.yes;
            } else {
              _attending = Attending.no;
            }
          } else {
            _attending = Attending.unknown;
          }
          notifyListeners();
        });
        // ...to here.
      } else {
        _loggedIn = false;
        _emailVerified = false;
        _guestBookMessages = [];
        _guestBookSubscription?.cancel();
        _attendingSubscription?.cancel(); // new
      }
      notifyListeners();
    });
  }

यह कोड उपस्थित लोगों की संख्या निर्धारित करने के लिए एक हमेशा सदस्यता वाली क्वेरी जोड़ता है और एक दूसरी क्वेरी जो केवल तब सक्रिय होती है जब उपयोगकर्ता लॉग इन होता है यह निर्धारित करने के लिए कि उपयोगकर्ता भाग ले रहा है या नहीं।

  1. lib/app_state.dart फ़ाइल के शीर्ष पर निम्नलिखित गणना जोड़ें।

lib/app_state.dart

enum Attending { yes, no, unknown }
  1. एक नई फ़ाइल yes_no_selection.dart बनाएं, एक नया विजेट परिभाषित करें जो रेडियो बटन की तरह काम करता है:

lib/yes_no_selection.dart

import 'package:flutter/material.dart';

import 'app_state.dart';
import 'src/widgets.dart';

class YesNoSelection extends StatelessWidget {
  const YesNoSelection(
      {super.key, required this.state, required this.onSelection});
  final Attending state;
  final void Function(Attending selection) onSelection;

  @override
  Widget build(BuildContext context) {
    switch (state) {
      case Attending.yes:
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              FilledButton(
                onPressed: () => onSelection(Attending.yes),
                child: const Text('YES'),
              ),
              const SizedBox(width: 8),
              TextButton(
                onPressed: () => onSelection(Attending.no),
                child: const Text('NO'),
              ),
            ],
          ),
        );
      case Attending.no:
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              TextButton(
                onPressed: () => onSelection(Attending.yes),
                child: const Text('YES'),
              ),
              const SizedBox(width: 8),
              FilledButton(
                onPressed: () => onSelection(Attending.no),
                child: const Text('NO'),
              ),
            ],
          ),
        );
      default:
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              StyledButton(
                onPressed: () => onSelection(Attending.yes),
                child: const Text('YES'),
              ),
              const SizedBox(width: 8),
              StyledButton(
                onPressed: () => onSelection(Attending.no),
                child: const Text('NO'),
              ),
            ],
          ),
        );
    }
  }
}

यह एक अनिश्चित स्थिति में प्रारंभ होता है जिसमें न तो हां चुना जाता है और न ही कोई चुना जाता है। एक बार जब उपयोगकर्ता यह चुन लेता है कि वे भाग ले रहे हैं या नहीं, तो आप उस विकल्प को एक भरे हुए बटन के साथ हाइलाइट करके दिखाते हैं और दूसरा विकल्प एक फ्लैट रेंडरिंग के साथ पीछे हट जाता है।

  1. YesNoSelection का लाभ उठाने के लिए HomePage की build() विधि को अपडेट करें, लॉग-इन किए गए उपयोगकर्ता को यह नामांकित करने में सक्षम करें कि वे भाग ले रहे हैं या नहीं, और ईवेंट के लिए उपस्थित लोगों की संख्या प्रदर्शित करें:

lib/home_page.dart

Consumer<ApplicationState>(
  builder: (context, appState, _) => Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      // Add from here...
      switch (appState.attendees) {
        1 => const Paragraph('1 person going'),
        >= 2 => Paragraph('${appState.attendees} people going'),
        _ => const Paragraph('No one going'),
      },
      // ...to here.
      if (appState.loggedIn) ...[
        // Add from here...
        YesNoSelection(
          state: appState.attending,
          onSelection: (attending) => appState.attending = attending,
        ),
        // ...to here.
        const Header('Discussion'),
        GuestBook(
          addMessage: (message) =>
              appState.addMessageToGuestBook(message),
          messages: appState.guestBookMessages,
        ),
      ],
    ],
  ),
),

नियम जोड़ें

आपने पहले से ही कुछ नियम सेट कर लिए हैं, इसलिए बटनों के साथ आपके द्वारा जोड़ा गया डेटा अस्वीकार कर दिया जाएगा। आपको attendees संग्रह में वृद्धि की अनुमति देने के लिए नियमों को अद्यतन करने की आवश्यकता है।

  1. attendees संग्रह में, प्रमाणीकरण यूआईडी लें जिसे आपने दस्तावेज़ नाम के रूप में उपयोग किया है और सत्यापित करें कि जमाकर्ता का uid वही दस्तावेज़ है जो वे लिख रहे हैं:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ... //
    match /attendees/{userId} {
      allow read: if true;
      allow write: if request.auth.uid == userId;
    }
  }
}

इससे हर कोई उपस्थित लोगों की सूची पढ़ सकता है क्योंकि वहां कोई निजी डेटा नहीं है, लेकिन केवल निर्माता ही इसे अपडेट कर सकता है।

  1. यह सुनिश्चित करने के लिए डेटा सत्यापन जोड़ें कि सभी अपेक्षित फ़ील्ड दस्तावेज़ में मौजूद हैं:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ... //
    match /attendees/{userId} {
      allow read: if true;
      allow write: if request.auth.uid == userId
          && "attending" in request.resource.data;

    }
  }
}
  1. वैकल्पिक: ऐप में, फायरबेस कंसोल में फायरस्टोर डैशबोर्ड में परिणाम देखने के लिए बटन पर क्लिक करें।

ऐप पूर्वावलोकन

एंड्रॉइड पर ऐप की होम स्क्रीन

iOS पर ऐप की होम स्क्रीन

वेब पर ऐप की होम स्क्रीन

MacOS पर ऐप की होम स्क्रीन

10. बधाई हो!

आपने एक इंटरैक्टिव, रीयल-टाइम वेब ऐप बनाने के लिए फायरबेस का उपयोग किया!

और अधिक जानें