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

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

इस कोडलैब में, आप Android और iOS के लिए Flutter मोबाइल ऐप बनाने के लिए Firebase की कुछ मूल बातें सीखते हैं।

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

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

  • फ़्लटर के साथ Android, iOS, वेब और macOS पर इवेंट RSVP और गेस्टबुक चैट ऐप कैसे बनाएं।
  • फायरबेस ऑथेंटिकेशन के साथ यूजर्स को कैसे ऑथेंटिकेट करें और फायरस्टोर के साथ डेटा सिंक करें।

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

आईओएस पर ऐप की होम स्क्रीन

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

निम्न में से कोई भी डिवाइस:

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

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

  • आपकी पसंद का ब्राउज़र, जैसे Google Chrome।
  • Android Studio या Visual Studio Code जैसे डार्ट और फ़्लटर प्लगइन्स के साथ कॉन्फ़िगर किया गया आपकी पसंद का एक IDE या टेक्स्ट एडिटर।
  • यदि आप किनारे पर रहना पसंद करते हैं तो स्पंदन या 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 को एक्सप्लोर कर सकते हैं और ऐप के विभिन्न हिस्सों में आपके द्वारा खोजे गए फोंट का उपयोग कर सकते हैं।

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

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

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

आईओएस पर ऐप की होम स्क्रीन

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

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

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

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

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

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

4395e4e67c08043a.png

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

b7138cde5f2c7b61.png

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

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

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

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

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

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

58e3e3e23c2f16a4.png

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

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

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

  • बिल्ड मेन्यू में, Cloud Firestore > डेटाबेस बनाएं पर क्लिक करें.

99e8429832d23fa3.png

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

6be00e26c72ea032.png

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

278656eefcfb0216.png

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

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

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

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

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

निर्भरताओं को कॉन्फ़िगर करें

आपको इस ऐप में उपयोग किए जाने वाले दो फायरबेस उत्पादों के लिए 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 पैकेज का भी उपयोग करते हैं जो व्यापार तर्क को प्रदर्शन तर्क से अलग करने में सक्षम बनाता है।

FlutterFire सीएलआई स्थापित करें

FlutterFire CLI अंतर्निहित Firebase CLI पर निर्भर करता है।

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

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

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

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

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

$ flutterfire configure

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

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

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

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

macos/Runner/DebugProfile.entitlements

<?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>

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/>
  <!-- Add the following two lines -->
	<key>com.apple.security.network.client</key>
	<true/>
</dict>
</plist>

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

5. RSVP कार्यक्षमता जोड़ें

अब जब आपने ऐप में Firebase जोड़ लिया है, तो आप एक RSVP बटन बना सकते हैं जो लोगों को प्रमाणीकरण के साथ पंजीकृत करता है। एंड्रॉइड नेटिव, आईओएस नेटिव और वेब के लिए, पहले से निर्मित 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.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 आरंभ करने के लिए RSVP बटन पर टैप करें।

2a2cd6d69d172369.png

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

e5e65065dba36b54.png

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

4ed811a25b0cf816.png

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

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

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

डेटा मॉडल

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

7c20dc8424bb1d84.png

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

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

  1. guest_book.dart नामक एक नई फ़ाइल बनाएँ, संदेश फ़ील्ड के UI तत्वों और भेजें बटन के निर्माण के लिए 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 और StyledButton के साथ एक Row है, जिसमें एक 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)),

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

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

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

चैट एकीकरण के साथ 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> का उपयोग करके ऐप स्टेट को ट्री के उस हिस्से के लिए उपलब्ध करा सकते हैं जिसे आप रेंडर करते हैं। यह आपको किसी ऐसे व्यक्ति पर प्रतिक्रिया करने देता है जो UI में संदेश दर्ज करता है और इसे डेटाबेस में प्रकाशित करता है। अगले खंड में, आप परीक्षण करते हैं कि जोड़े गए संदेश डेटाबेस में प्रकाशित हैं या नहीं।

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

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

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

713870af0b3b63c.png

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

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

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

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

  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. वैकल्पिक: फायरबेस कंसोल के डेटाबेस मेनू में, मैन्युअल रूप से हटाएं, संशोधित करें या नए संदेश जोड़ें। सभी परिवर्तन UI में दिखाई देते हैं।

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

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

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

चैट एकीकरण के साथ 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. बोनस चरण: आपने जो सीखा है उसका अभ्यास करें

सहभागी की RSVP स्थिति रिकॉर्ड करें

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

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

  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) {
        _loginState = ApplicationLoginState.loggedIn;
        _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 {
        _loginState = ApplicationLoginState.loggedOut;
        _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. वैकल्पिक: ऐप में, Firebase कंसोल में Firestore डैशबोर्ड में परिणाम देखने के लिए बटन क्लिक करें।

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

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

आईओएस पर ऐप की होम स्क्रीन

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

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

10. बधाई हो!

आपने इंटरैक्टिव, रीयल-टाइम वेब ऐप्लिकेशन बनाने के लिए Firebase का इस्तेमाल किया!

और अधिक जानें