1. शुरू करने से पहले
इस कोडलैब में, Android और iOS के लिए Flutter मोबाइल ऐप्लिकेशन बनाने के लिए, Firebase की कुछ बुनियादी बातें बताई गई हैं.
ज़रूरी शर्तें
- Flutter के बारे में जानकारी
- Flutter SDK
- अपनी पसंद का टेक्स्ट एडिटर
आपको क्या सीखने को मिलेगा
- Flutter की मदद से, Android, iOS, वेब, और macOS पर इवेंट में शामिल होने के लिए न्योते का जवाब देने और मेहमानों की चैट बुक करने वाला ऐप्लिकेशन बनाने का तरीका.
- Firebase Authentication की मदद से उपयोगकर्ताओं की पुष्टि कैसे करें और Firestore के साथ डेटा सिंक कैसे करें.
आपको इनकी ज़रूरत होगी
इनमें से कोई भी डिवाइस:
- आपके कंप्यूटर से कनेक्ट किया गया कोई Android या iOS डिवाइस, जिस पर डेवलपर मोड चालू हो.
- iOS सिम्युलेटर (इसके लिए, Xcode टूल की ज़रूरत होती है).
- Android एम्युलेटर (इसे Android Studio में सेट अप करना ज़रूरी है).
आपको इनकी भी ज़रूरत होगी:
- अपनी पसंद का कोई ब्राउज़र, जैसे कि Google Chrome.
- आपकी पसंद का कोई आईडीई या टेक्स्ट एडिटर, जिसमें Dart और Flutter प्लगिन कॉन्फ़िगर किए गए हों. जैसे, Android Studio या Visual Studio Code.
- Flutter का नया
stable
वर्शन याbeta
वर्शन. - Firebase प्रोजेक्ट बनाने और उसे मैनेज करने के लिए, Google खाता.
Firebase
CLI आपके Google खाते में लॉग इन हो.
2. सैंपल कोड पाना
GitHub से अपने प्रोजेक्ट का शुरुआती वर्शन डाउनलोड करें:
- कमांड लाइन से,
flutter-codelabs
डायरेक्ट्री में GitHub रिपॉज़िटरी का क्लोन बनाएं:
git clone https://github.com/flutter/codelabs.git flutter-codelabs
flutter-codelabs
डायरेक्ट्री में, कोडलैब के कलेक्शन का कोड होता है. इस कोडलैब का कोड, flutter-codelabs/firebase-get-to-know-flutter
डायरेक्ट्री में है. इस डायरेक्ट्री में स्नैपशॉट की एक सीरीज़ होती है. इससे पता चलता है कि हर चरण के आखिर में आपका प्रोजेक्ट कैसा दिखना चाहिए. उदाहरण के लिए, आप दूसरे चरण पर हैं.
- दूसरे चरण के लिए मिलती-जुलती फ़ाइलें ढूंढें:
cd flutter-codelabs/firebase-get-to-know-flutter/step_02
अगर आपको आगे बढ़ना है या यह देखना है कि किसी चरण के बाद कोई चीज़ कैसी दिखनी चाहिए, तो उस चरण के नाम वाली डायरेक्ट्री में देखें जिसमें आपकी दिलचस्पी है.
स्टार्टर ऐप्लिकेशन इंपोर्ट करना
- अपनी पसंद के IDE में
flutter-codelabs/firebase-get-to-know-flutter/step_02
डायरेक्ट्री खोलें या इंपोर्ट करें. इस डायरेक्ट्री में कोडलैब के लिए स्टार्टर कोड है. इसमें फ़िलहाल काम न करने वाला Flutter मीटअप ऐप्लिकेशन शामिल है.
उन फ़ाइलों को ढूंढें जिन पर काम करना है
इस ऐप्लिकेशन का कोड, कई डायरेक्ट्री में फैला हुआ है. फ़ंक्शन को इस तरह से बांटने से काम आसान हो जाता है, क्योंकि इससे कोड को फ़ंक्शन के हिसाब से ग्रुप किया जाता है.
- इन फ़ाइलों का पता लगाएं:
lib/main.dart
: इस फ़ाइल में मुख्य एंट्री पॉइंट और ऐप्लिकेशन विजेट शामिल होता है.lib/home_page.dart
: इस फ़ाइल में होम पेज का विजेट होता है.lib/src/widgets.dart
: इस फ़ाइल में कुछ विजेट शामिल हैं. इनकी मदद से, ऐप्लिकेशन की स्टाइल को स्टैंडर्ड बनाया जा सकता है. ये विजेट, स्टार्टर ऐप्लिकेशन की स्क्रीन बनाते हैं.lib/src/authentication.dart
: इस फ़ाइल में, Authentication को आंशिक तौर पर लागू किया गया है. इसमें विजेट का एक सेट भी शामिल है. इसकी मदद से, Firebase में ईमेल के ज़रिए पुष्टि करने की सुविधा के लिए, लॉगिन करने वाले उपयोगकर्ता का अनुभव बेहतर बनाया जा सकता है. फ़िलहाल, पुष्टि करने के फ़्लो के लिए इन विजेट का इस्तेमाल स्टार्टर ऐप्लिकेशन में नहीं किया गया है. हालांकि, इन्हें जल्द ही जोड़ा जाएगा.
ऐप्लिकेशन के बाकी हिस्से को बनाने के लिए, ज़रूरत के मुताबिक अन्य फ़ाइलें जोड़ी जाती हैं.
lib/main.dart
फ़ाइल की समीक्षा करें
यह ऐप्लिकेशन, google_fonts
पैकेज का इस्तेमाल करता है, ताकि पूरे ऐप्लिकेशन में Roboto को डिफ़ॉल्ट फ़ॉन्ट के तौर पर इस्तेमाल किया जा सके. fonts.google.com पर जाकर, अलग-अलग फ़ॉन्ट देखे जा सकते हैं. साथ ही, ऐप्लिकेशन के अलग-अलग हिस्सों में इन फ़ॉन्ट का इस्तेमाल किया जा सकता है.
आपने lib/src/widgets.dart
फ़ाइल से हेल्पर विजेट का इस्तेमाल किया हो. ये विजेट Header
, Paragraph
, और IconAndDetail
के तौर पर उपलब्ध होते हैं. इन विजेट की मदद से, डुप्लीकेट कोड को हटाया जा सकता है. इससे HomePage
में बताए गए पेज लेआउट में मौजूद गड़बड़ी को कम किया जा सकता है. इससे, एक जैसा लुक और फ़ील भी मिलता है.
Android, iOS, वेब, और macOS पर आपका ऐप्लिकेशन ऐसा दिखता है:
3. Firebase प्रोजेक्ट बनाना और उसे सेट अप करना
मेहमानों के लिए इवेंट की जानकारी दिखाना बहुत अच्छा है, लेकिन यह जानकारी अपने-आप में किसी के लिए भी बहुत काम की नहीं होती. आपको ऐप्लिकेशन में कुछ डाइनैमिक फ़ंक्शन जोड़ने होंगे. इसके लिए, आपको Firebase को अपने ऐप्लिकेशन से कनेक्ट करना होगा. Firebase का इस्तेमाल शुरू करने के लिए, आपको एक Firebase प्रोजेक्ट बनाना और उसे सेट अप करना होगा.
Firebase प्रोजेक्ट बनाना
- अपने Google खाते का इस्तेमाल करके, Firebase कंसोल में साइन इन करें.
- नया प्रोजेक्ट बनाने के लिए, बटन पर क्लिक करें. इसके बाद, प्रोजेक्ट का नाम डालें. उदाहरण के लिए,
Firebase-Flutter-Codelab
.
- जारी रखें पर क्लिक करें.
- अगर आपसे कहा जाए, तो Firebase की शर्तें पढ़ें और स्वीकार करें. इसके बाद, जारी रखें पर क्लिक करें.
- (ज़रूरी नहीं) Firebase कंसोल में एआई की मदद पाने की सुविधा चालू करें. इसे "Firebase में Gemini" कहा जाता है.
- इस कोडलैब के लिए, आपको Google Analytics की ज़रूरत नहीं है. इसलिए, Google Analytics के विकल्प को टॉगल करके बंद करें.
- प्रोजेक्ट बनाएं पर क्लिक करें. इसके बाद, प्रोजेक्ट के प्रोविज़न होने का इंतज़ार करें. इसके बाद, जारी रखें पर क्लिक करें.
Firebase प्रोजेक्ट के बारे में ज़्यादा जानने के लिए, Firebase प्रोजेक्ट के बारे में जानकारी लेख पढ़ें.
Firebase प्रॉडक्ट सेट अप करना
ऐप्लिकेशन, Firebase के इन प्रॉडक्ट का इस्तेमाल करता है. ये वेब ऐप्लिकेशन के लिए उपलब्ध हैं:
- पुष्टि करना: इससे उपयोगकर्ताओं को आपके ऐप्लिकेशन में साइन इन करने की सुविधा मिलती है.
- Firestore: यह क्लाउड पर स्ट्रक्चर्ड डेटा सेव करता है. साथ ही, डेटा में बदलाव होने पर तुरंत सूचनाएं भेजता है.
- Firebase के सुरक्षा नियम: ये आपके डेटाबेस को सुरक्षित रखते हैं.
इनमें से कुछ प्रॉडक्ट के लिए, खास कॉन्फ़िगरेशन की ज़रूरत होती है. इसके अलावा, आपको इन्हें Firebase कंसोल में चालू करना होगा.
ईमेल पते से साइन इन करने की पुष्टि करने की सुविधा चालू करना
- Firebase कंसोल के प्रोजेक्ट की खास जानकारी वाले पैनल में, बनाएं मेन्यू को बड़ा करें.
- पुष्टि करें > शुरू करें > साइन-इन करने का तरीका > ईमेल/पासवर्ड > चालू करें > सेव करें पर क्लिक करें.
Firestore सेट अप करना
यह वेब ऐप्लिकेशन, चैट मैसेज सेव करने और नए चैट मैसेज पाने के लिए Firestore का इस्तेमाल करता है.
अपने Firebase प्रोजेक्ट में Firestore को सेट अप करने का तरीका यहां बताया गया है:
- Firebase कंसोल के बाईं ओर मौजूद पैनल में, बनाएं को बड़ा करें. इसके बाद, Firestore डेटाबेस को चुनें.
- डेटाबेस बनाएं पर क्लिक करें.
- डेटाबेस आईडी को
(default)
पर सेट रहने दें. - अपने डेटाबेस के लिए कोई जगह चुनें. इसके बाद, आगे बढ़ें पर क्लिक करें.
किसी असली ऐप्लिकेशन के लिए, आपको ऐसी जगह चुननी चाहिए जो आपके उपयोगकर्ताओं के आस-पास हो. - टेस्ट मोड में शुरू करें पर क्लिक करें. सुरक्षा नियमों के बारे में डिसक्लेमर पढ़ें.
इस कोडलैब में बाद में, अपने डेटा को सुरक्षित करने के लिए सुरक्षा नियम जोड़े जाएंगे. अपने डेटाबेस के लिए सुरक्षा के नियम जोड़े बिना, सार्वजनिक तौर पर किसी ऐप्लिकेशन को डिस्ट्रिब्यूट या उपलब्ध न करें. - बनाएं पर क्लिक करें.
4. Firebase को कॉन्फ़िगर करना
Flutter के साथ Firebase का इस्तेमाल करने के लिए, आपको ये टास्क पूरे करने होंगे. इससे FlutterFire
लाइब्रेरी का सही तरीके से इस्तेमाल करने के लिए, Flutter प्रोजेक्ट को कॉन्फ़िगर किया जा सकेगा:
- अपने प्रोजेक्ट में
FlutterFire
डिपेंडेंसी जोड़ें. - Firebase प्रोजेक्ट पर, अपने हिसाब से प्लैटफ़ॉर्म रजिस्टर करें.
- प्लेटफ़ॉर्म के हिसाब से कॉन्फ़िगरेशन फ़ाइल डाउनलोड करें. इसके बाद, उसे कोड में जोड़ें.
आपके Flutter ऐप्लिकेशन की टॉप-लेवल डायरेक्ट्री में android
, ios
, macos
, और web
सबडायरेक्ट्री होती हैं. इनमें iOS और Android के लिए, प्लैटफ़ॉर्म के हिसाब से कॉन्फ़िगरेशन फ़ाइलें होती हैं.
डिपेंडेंसी कॉन्फ़िगर करना
आपको इस ऐप्लिकेशन में इस्तेमाल किए जाने वाले Firebase के दो प्रॉडक्ट के लिए, FlutterFire
लाइब्रेरी जोड़नी होंगी: Authentication और Firestore.
- कमांड लाइन से, ये डिपेंडेंसी जोड़ें:
$ flutter pub add firebase_core
firebase_core
package, सभी Firebase Flutter प्लगिन के लिए ज़रूरी कॉमन कोड है.
$ flutter pub add firebase_auth
firebase_auth
पैकेज की मदद से, पुष्टि करने की सुविधा को इंटिग्रेट किया जा सकता है.
$ flutter pub add cloud_firestore
cloud_firestore
पैकेज की मदद से, Firestore के डेटा स्टोरेज को ऐक्सेस किया जा सकता है.
$ flutter pub add provider
firebase_ui_auth
पैकेज, विजेट और यूटिलिटी का एक सेट उपलब्ध कराता है. इससे डेवलपर को पुष्टि करने के फ़्लो को तेज़ी से पूरा करने में मदद मिलती है.
$ flutter pub add firebase_ui_auth
आपने ज़रूरी पैकेज जोड़ लिए हैं. हालांकि, Firebase का सही तरीके से इस्तेमाल करने के लिए, आपको iOS, Android, macOS, और वेब रनर प्रोजेक्ट को भी कॉन्फ़िगर करना होगा. provider
पैकेज का इस्तेमाल किया जाता है. इससे, कारोबार के लॉजिक को डिसप्ले लॉजिक से अलग किया जा सकता है.
FlutterFire सीएलआई इंस्टॉल करना
FlutterFire CLI, Firebase CLI पर निर्भर करता है.
- अगर आपने अब तक ऐसा नहीं किया है, तो अपने कंप्यूटर पर Firebase CLI इंस्टॉल करें.
- FlutterFire CLI इंस्टॉल करें:
$ dart pub global activate flutterfire_cli
इंस्टॉल हो जाने के बाद, flutterfire
कमांड दुनिया भर में उपलब्ध होती है.
अपने ऐप्लिकेशन कॉन्फ़िगर करना
सीएलआई, आपके Firebase प्रोजेक्ट और चुने गए प्रोजेक्ट ऐप्लिकेशन से जानकारी निकालता है. इससे किसी प्लैटफ़ॉर्म के लिए पूरा कॉन्फ़िगरेशन जनरेट किया जा सकता है.
अपने ऐप्लिकेशन के रूट में, configure
कमांड चलाएं:
$ flutterfire configure
कॉन्फ़िगरेशन कमांड की मदद से, ये काम किए जा सकते हैं:
.firebaserc
फ़ाइल के आधार पर या Firebase कंसोल से कोई Firebase प्रोजेक्ट चुनें.- कॉन्फ़िगरेशन के लिए प्लैटफ़ॉर्म तय करें. जैसे, Android, iOS, macOS, और वेब.
- उन Firebase ऐप्लिकेशन की पहचान करें जिनसे कॉन्फ़िगरेशन निकालना है. डिफ़ॉल्ट रूप से, सीएलआई आपके मौजूदा प्रोजेक्ट कॉन्फ़िगरेशन के आधार पर, Firebase ऐप्लिकेशन को अपने-आप मैच करने की कोशिश करता है.
- अपने प्रोजेक्ट में
firebase_options.dart
फ़ाइल जनरेट करें.
macOS को कॉन्फ़िगर करना
macOS पर Flutter, पूरी तरह से सैंडबॉक्स किए गए ऐप्लिकेशन बनाता है. यह ऐप्लिकेशन, Firebase सर्वर से कम्यूनिकेट करने के लिए नेटवर्क के साथ इंटिग्रेट होता है. इसलिए, आपको अपने ऐप्लिकेशन को नेटवर्क क्लाइंट के तौर पर कॉन्फ़िगर करना होगा.
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/Runner/Release.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/>
<!-- Add the following two lines -->
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>
ज़्यादा जानकारी के लिए, डेस्कटॉप पर Flutter का इस्तेमाल करना लेख पढ़ें.
5. जवाब देने की सुविधा जोड़ना
ऐप्लिकेशन में Firebase जोड़ने के बाद, RSVP बटन बनाया जा सकता है. इससे उन लोगों को रजिस्टर किया जा सकेगा जिन्होंने Authentication का इस्तेमाल किया है. Android नेटिव, iOS नेटिव, और वेब के लिए, पहले से बने हुए FirebaseUI Auth
पैकेज उपलब्ध हैं. हालांकि, आपको Flutter के लिए यह सुविधा बनानी होगी.
आपने जिस प्रोजेक्ट को पहले वापस पाया था उसमें विजेट का एक सेट शामिल था. यह सेट, पुष्टि करने के ज़्यादातर फ़्लो के लिए उपयोगकर्ता इंटरफ़ेस लागू करता है. ऐप्लिकेशन के साथ पुष्टि करने की सुविधा को इंटिग्रेट करने के लिए, कारोबार के लॉजिक को लागू करें.
Provider
पैकेज की मदद से, कारोबार से जुड़ी लॉजिक लेयर जोड़ना
provider
पैकेज का इस्तेमाल करके, ऐप्लिकेशन के पूरे फ़्लटर विजेट ट्री में ऐप्लिकेशन स्टेट ऑब्जेक्ट उपलब्ध कराएं:
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
स्टेटमेंट, Firebase Core और Auth को पेश करते हैं. साथ ही, provider
पैकेज को पुल करते हैं, जो पूरे विजेट ट्री में ऐप्लिकेशन स्टेट ऑब्जेक्ट उपलब्ध कराता है. इसके अलावा, इसमें firebase_ui_auth
पैकेज से पुष्टि करने वाले विजेट शामिल होते हैं.
इस चरण के लिए, ApplicationState
ऐप्लिकेशन स्टेट ऑब्जेक्ट की एक मुख्य ज़िम्मेदारी होती है. यह विजेट ट्री को सूचना देता है कि पुष्टि की गई स्थिति में कोई अपडेट हुआ है.
ऐप्लिकेशन को यह बताने के लिए कि उपयोगकर्ता ने लॉग इन किया है या नहीं, सिर्फ़ एक प्रोवाइडर का इस्तेमाल किया जाता है. किसी उपयोगकर्ता को लॉग इन करने की अनुमति देने के लिए, firebase_ui_auth
पैकेज से मिले यूज़र इंटरफ़ेस (यूआई) का इस्तेमाल किया जाता है. यह आपके ऐप्लिकेशन में लॉग इन स्क्रीन को तुरंत बूटस्ट्रैप करने का एक बेहतरीन तरीका है.
पुष्टि करने की प्रोसेस को इंटिग्रेट करना
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';
- ऐप्लिकेशन की स्थिति को ऐप्लिकेशन के शुरू होने से कनेक्ट करें. इसके बाद,
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
पैकेज को यह पता चलता है कि डिपेंडेंट विजेट को कब फिर से दिखाया जाए.
- अपने ऐप्लिकेशन को अपडेट करें, ताकि FirebaseUI की ओर से उपलब्ध कराई गई अलग-अलग स्क्रीन पर नेविगेट किया जा सके. इसके लिए,
GoRouter
कॉन्फ़िगरेशन बनाएं:
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
);
}
}
पुष्टि करने के फ़्लो की नई स्थिति के आधार पर, हर स्क्रीन से अलग-अलग तरह के ऐक्शन जुड़े होते हैं. पुष्टि करने की प्रोसेस में ज़्यादातर बदलावों के बाद, आपको अपनी पसंद की स्क्रीन पर वापस भेज दिया जाता है. यह होम स्क्रीन या प्रोफ़ाइल जैसी कोई दूसरी स्क्रीन हो सकती है.
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
विजेट, ऐसे पूरक विजेट होते हैं जिनकी जांच की जाती है.
पुष्टि करने की प्रोसेस की जांच करना
- ऐप्लिकेशन में,
SignInScreen
शुरू करने के लिए, जवाब दें बटन पर टैप करें.
- कोई ईमेल पता डालें. अगर आपने पहले से रजिस्टर किया हुआ है, तो सिस्टम आपको पासवर्ड डालने के लिए कहेगा. अगर आपने रजिस्ट्रेशन नहीं किया है, तो सिस्टम आपको रजिस्ट्रेशन फ़ॉर्म भरने के लिए कहेगा.
- गड़बड़ी ठीक करने के तरीके की जांच करने के लिए, छह से कम वर्णों वाला पासवर्ड डालें. अगर आपने रजिस्टर किया है, तो आपको इसके बजाय पासवर्ड दिखेगा.
- गड़बड़ी ठीक करने के फ़्लो की जांच करने के लिए, गलत पासवर्ड डालें.
- सही पासवर्ड डालें. आपको लॉग इन करने का विकल्प दिखता है. इससे उपयोगकर्ता को लॉग आउट करने का विकल्प मिलता है.
6. Firestore में मैसेज लिखना
यह जानकर अच्छा लगा कि उपयोगकर्ता आ रहे हैं, लेकिन आपको मेहमानों को ऐप्लिकेशन में कुछ और करने के लिए देना होगा. अगर वे गेस्टबुक में मैसेज छोड़ सकें, तो क्या होगा? वे बता सकते हैं कि वे इस इवेंट में आने के लिए क्यों उत्साहित हैं या वे किससे मिलना चाहते हैं.
ऐप्लिकेशन में उपयोगकर्ताओं के लिखे गए चैट मैसेज सेव करने के लिए, Firestore का इस्तेमाल किया जाता है.
डेटा मॉडल
Firestore एक NoSQL डेटाबेस है. इसमें सेव किए गए डेटा को कलेक्शन, दस्तावेज़, फ़ील्ड, और सब-कलेक्शन में बांटा जाता है. चैट के हर मैसेज को guestbook
कलेक्शन में एक दस्तावेज़ के तौर पर सेव किया जाता है. यह टॉप-लेवल का कलेक्शन होता है.
Firestore में मैसेज जोड़ना
इस सेक्शन में, उपयोगकर्ताओं को डेटाबेस में मैसेज लिखने की सुविधा जोड़ी जाती है. सबसे पहले, फ़ॉर्म फ़ील्ड और 'भेजें' बटन जोड़ा जाता है. इसके बाद, वह कोड जोड़ा जाता है जो इन एलिमेंट को डेटाबेस से कनेक्ट करता है.
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
की मदद से फ़ॉर्म के पीछे मौजूद फ़ॉर्म की स्थिति को ऐक्सेस करें. कुंजियों और उनके इस्तेमाल के तरीके के बारे में ज़्यादा जानने के लिए, कुंजियों का इस्तेमाल कब करें लेख पढ़ें.
यह भी ध्यान दें कि विजेट किस तरह से लेआउट किए गए हैं. आपके पास Row
है, जिसमें TextFormField
और StyledButton
है. इसमें Row
शामिल है. यह भी ध्यान दें कि TextFormField
को Expanded
विजेट में रैप किया गया है. इससे TextFormField
को लाइन में मौजूद अतिरिक्त जगह को भरने के लिए मजबूर किया जाता है. यह जानकारी क्यों ज़रूरी है, इस बारे में ज़्यादा जानने के लिए पाबंदियों के बारे में जानकारी लेख पढ़ें.
अब आपके पास एक ऐसा विजेट है जिसकी मदद से उपयोगकर्ता, मेहमानों की सूची में जोड़ने के लिए कुछ टेक्स्ट डाल सकता है. अब आपको इसे स्क्रीन पर दिखाना होगा.
HomePage
के मुख्य हिस्से में बदलाव करके,ListView
के बच्चों के आखिर में ये दो लाइनें जोड़ें:
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)),
विजेट दिखाने के लिए यह काफ़ी है, लेकिन इससे कोई काम का फ़ंक्शन नहीं किया जा सकता. इस कोड को जल्द ही अपडेट करें, ताकि यह काम कर सके.
ऐप्लिकेशन की झलक
जब कोई उपयोगकर्ता भेजें पर क्लिक करता है, तो यह कोड स्निपेट ट्रिगर होता है. यह मैसेज इनपुट फ़ील्ड के कॉन्टेंट को डेटाबेस के guestbook
कलेक्शन में जोड़ता है. खास तौर पर, addMessageToGuestBook
तरीके से मैसेज के कॉन्टेंट को एक नए दस्तावेज़ में जोड़ा जाता है. इस दस्तावेज़ का आईडी, guestbook
कलेक्शन में अपने-आप जनरेट होता है.
ध्यान दें कि FirebaseAuth.instance.currentUser.uid
, अपने-आप जनरेट होने वाले उस यूनीक आईडी का रेफ़रंस है जो Authentication, लॉग-इन किए हुए सभी उपयोगकर्ताओं के लिए देता है.
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.
}
कनेक्ट यूज़र इंटरफ़ेस (यूआई) और डेटाबेस
आपके पास एक यूज़र इंटरफ़ेस (यूआई) है, जहां उपयोगकर्ता गेस्ट बुक में जोड़ने के लिए टेक्स्ट डाल सकता है. साथ ही, आपके पास Firestore में एंट्री जोड़ने का कोड है. अब आपको सिर्फ़ इन दोनों को कनेक्ट करना है.
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>
का इस्तेमाल करें जिसे आपको रेंडर करना है. इसकी मदद से, यूज़र इंटरफ़ेस (यूआई) में मैसेज डालने वाले किसी व्यक्ति को जवाब दिया जा सकता है. साथ ही, उस मैसेज को डेटाबेस में पब्लिश किया जा सकता है. अगले सेक्शन में, यह टेस्ट किया जाता है कि जोड़े गए मैसेज डेटाबेस में पब्लिश हुए हैं या नहीं.
मैसेज भेजने की सुविधा की जांच करना
- अगर ज़रूरी हो, तो ऐप्लिकेशन में साइन इन करें.
- कोई मैसेज डालें, जैसे कि
Hey there!
. इसके बाद, भेजें पर क्लिक करें.
इस कार्रवाई से, मैसेज को आपके Firestore डेटाबेस में लिखा जाता है. हालांकि, आपको अपने Flutter ऐप्लिकेशन में यह मैसेज नहीं दिखेगा. ऐसा इसलिए, क्योंकि आपको अब भी डेटा को वापस पाने की सुविधा लागू करनी होगी. यह काम अगले चरण में किया जाता है. हालांकि, Firebase कंसोल के डेटाबेस डैशबोर्ड में, जोड़े गए मैसेज को guestbook
कलेक्शन में देखा जा सकता है. ज़्यादा मैसेज भेजने पर, आपके guestbook
कलेक्शन में ज़्यादा दस्तावेज़ जुड़ जाते हैं. उदाहरण के लिए, यहां दिया गया कोड स्निपेट देखें:
7. मैसेज पढ़ना
यह बहुत अच्छा है कि मेहमान डेटाबेस में मैसेज लिख सकते हैं. हालाँकि, वे उन्हें अभी ऐप्लिकेशन में नहीं देख सकते. अब इसे ठीक करने का समय आ गया है!
मैसेज सिंक करना
मैसेज दिखाने के लिए, आपको ऐसे लिसनर जोड़ने होंगे जो डेटा में बदलाव होने पर ट्रिगर हों. इसके बाद, एक ऐसा यूज़र इंटरफ़ेस (यूआई) एलिमेंट बनाना होगा जो नए मैसेज दिखाए. ऐप्लिकेशन की स्थिति में ऐसा कोड जोड़ा जाता है जो ऐप्लिकेशन से जोड़े गए नए मैसेज को सुनता है.
- एक नई फ़ाइल
guest_book_message.dart
बनाएं. इसके बाद, Firestore में सेव किए गए डेटा का स्ट्रक्चर्ड व्यू दिखाने के लिए, इसमें यह क्लास जोड़ें.
lib/guest_book_message.dart
class GuestBookMessage {
GuestBookMessage({required this.name, required this.message});
final String name;
final String message;
}
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
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.
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
कलेक्शन में मौजूद मैसेज की लोकल कैश मेमोरी को फिर से बनाया जाता है. साथ ही, इस सदस्यता का रेफ़रंस भी सेव किया जाता है, ताकि बाद में इससे सदस्यता छोड़ी जा सके. यहां बहुत कुछ हो रहा है. इसलिए, आपको इसे डीबगर में एक्सप्लोर करना चाहिए, ताकि यह पता चल सके कि साफ़ तौर पर समझने के लिए क्या होता है. ज़्यादा जानकारी के लिए, Firestore की मदद से रीयलटाइम अपडेट पाना लेख पढ़ें.
lib/guest_book.dart
फ़ाइल में, यह इंपोर्ट जोड़ें:
import 'guest_book_message.dart';
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();
}
- इस कॉन्फ़िगरेशन को दिखाने के लिए,
_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
विजेट में रैप किया जाता है. इसके बाद, Column
के बच्चों के आखिर में collection for जोड़ा जाता है, ताकि मैसेज की सूची में मौजूद हर मैसेज के लिए एक नया Paragraph
जनरेट किया जा सके.
HomePage
के मुख्य हिस्से को अपडेट करें, ताकि नएmessages
पैरामीटर के साथGuestBook
को सही तरीके से बनाया जा सके:
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
),
],
],
),
),
मैसेज सिंक करने की सुविधा की जांच करना
Firestore, डेटाबेस के लिए सदस्यता लेने वाले क्लाइंट के साथ डेटा को अपने-आप और तुरंत सिंक करता है.
मैसेज सिंक करने की सुविधा की जांच करना:
- ऐप्लिकेशन में, उन मैसेज को ढूंढें जिन्हें आपने डेटाबेस में पहले बनाया था.
- नए मैसेज लिखो. ये तुरंत दिखते हैं.
- अपने फ़ाइल फ़ोल्डर को एक से ज़्यादा विंडो या टैब में खोलें. मैसेज, विंडो और टैब में रीयल टाइम में सिंक होते हैं.
- वैकल्पिक: Firebase कंसोल के डेटाबेस मेन्यू में जाकर, मैन्युअल तरीके से नए मैसेज जोड़ें, मौजूदा मैसेज में बदलाव करें या उन्हें मिटाएं. सभी बदलाव यूज़र इंटरफ़ेस (यूआई) में दिखते हैं.
बधाई हो! आपने अपने ऐप्लिकेशन में Firestore के दस्तावेज़ पढ़े!
ऐप्लिकेशन की झलक
8. सुरक्षा से जुड़े बुनियादी नियम सेट अप करना
आपने शुरुआत में, टेस्ट मोड का इस्तेमाल करने के लिए Firestore सेट अप किया था. इसका मतलब है कि आपका डेटाबेस, पढ़ने और लिखने के लिए खुला है. हालांकि, आपको डेवलपमेंट के शुरुआती चरणों में ही टेस्ट मोड का इस्तेमाल करना चाहिए. सबसे सही तरीका यह है कि ऐप्लिकेशन डेवलप करते समय, अपने डेटाबेस के लिए सुरक्षा से जुड़े नियम सेट अप करें. सुरक्षा, आपके ऐप्लिकेशन के स्ट्रक्चर और व्यवहार का अहम हिस्सा है.
Firebase के सुरक्षा नियमों की मदद से, अपने डेटाबेस में मौजूद दस्तावेज़ों और कलेक्शन का ऐक्सेस कंट्रोल किया जा सकता है. नियमों के सिंटैक्स का इस्तेमाल करके, ऐसे नियम बनाए जा सकते हैं जो सभी राइट ऑपरेशन, पूरे डेटाबेस, और किसी खास दस्तावेज़ पर किए जाने वाले ऑपरेशन से मेल खाते हों.
सुरक्षा से जुड़े बुनियादी नियम सेट अप करें:
- Firebase कंसोल के Develop मेन्यू में, Database > Rules पर क्लिक करें. आपको सुरक्षा के ये डिफ़ॉल्ट नियम और नियमों के सार्वजनिक होने के बारे में चेतावनी दिखेगी:
- उन कलेक्शन की पहचान करें जिनमें ऐप्लिकेशन डेटा लिखता है:
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.
}
}
आपने हर guestbook दस्तावेज़ में, पुष्टि करने वाले यूआईडी को फ़ील्ड के तौर पर इस्तेमाल किया है. इसलिए, आपको पुष्टि करने वाला यूआईडी मिल सकता है. साथ ही, यह पुष्टि की जा सकती है कि दस्तावेज़ में लिखने की कोशिश करने वाले किसी भी व्यक्ति के पास, पुष्टि करने वाला यूआईडी मौजूद है.
- अपने नियमों के सेट में, पढ़ने और लिखने के नियम जोड़ें:
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;
}
}
}
अब, मेहमानों की किताब में सिर्फ़ वे लोग मैसेज पढ़ सकते हैं जिन्होंने साइन इन किया है. हालांकि, किसी मैसेज में सिर्फ़ उसका लेखक बदलाव कर सकता है.
- डेटा की पुष्टि करने की सुविधा जोड़ें, ताकि यह पक्का किया जा सके कि दस्तावेज़ में सभी ज़रूरी फ़ील्ड मौजूद हैं:
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. बोनस चरण: आपने जो सीखा है उसकी प्रैक्टिस करें
मीटिंग में शामिल होने वाले व्यक्ति के जवाब का स्टेटस रिकॉर्ड करना
फ़िलहाल, आपका ऐप्लिकेशन लोगों को सिर्फ़ तब चैट करने की अनुमति देता है, जब उनकी इवेंट में दिलचस्पी हो. इसके अलावा, आपको सिर्फ़ तब पता चलेगा कि कोई व्यक्ति आ रहा है, जब वह चैट में इसकी जानकारी देगा.
इस चरण में, आपको व्यवस्थित तरीके से काम करना होता है. साथ ही, लोगों को यह बताना होता है कि कितने लोग आ रहे हैं. ऐप्लिकेशन की स्थिति में कुछ सुविधाएं जोड़ी जाती हैं. पहला विकल्प यह है कि लॉग इन किया हुआ उपयोगकर्ता, यह तय कर सकता है कि वह इवेंट में शामिल हो रहा है या नहीं. दूसरा काउंटर, इवेंट में शामिल होने वाले लोगों की संख्या दिखाता है.
lib/app_state.dart
फ़ाइल में,ApplicationState
के ऐक्सेस करने वाले सेक्शन में ये लाइनें जोड़ें, ताकि यूज़र इंटरफ़ेस (यूआई) कोड इस स्थिति के साथ इंटरैक्ट कर सके:
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});
}
}
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();
});
}
यह कोड, हमेशा सदस्यता लेने वाली क्वेरी जोड़ता है, ताकि शामिल होने वाले लोगों की संख्या का पता लगाया जा सके. साथ ही, यह एक दूसरी क्वेरी जोड़ता है, जो सिर्फ़ तब सक्रिय होती है, जब कोई उपयोगकर्ता लॉग इन होता है. इससे यह पता चलता है कि उपयोगकर्ता शामिल हो रहा है या नहीं.
lib/app_state.dart
फ़ाइल में सबसे ऊपर, यहां दिया गया एन्यूमरेशन जोड़ें.
lib/app_state.dart
enum Attending { yes, no, unknown }
- नई फ़ाइल
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'),
),
],
),
);
}
}
}
यह अनिश्चित स्थिति में शुरू होता है. इसमें न तो हां चुना जाता है और न ही नहीं. जब उपयोगकर्ता यह चुन लेता है कि वह इवेंट में शामिल हो रहा है या नहीं, तो आपको उस विकल्प को हाइलाइट करना होगा. इसके लिए, भरे हुए बटन का इस्तेमाल करें. साथ ही, दूसरे विकल्प को फ़्लैट रेंडरिंग के साथ दिखाना होगा.
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
कलेक्शन में आइटम जोड़ने की अनुमति देने के लिए, नियमों को अपडेट करना होगा.
attendees
कलेक्शन में, दस्तावेज़ के नाम के तौर पर इस्तेमाल किया गया पुष्टि करने वाला यूआईडी पाएं. साथ ही, पुष्टि करें कि सबमिट करने वाले काuid
, उस दस्तावेज़ के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;
}
}
}
इससे सभी लोग, शामिल होने वाले लोगों की सूची को पढ़ सकते हैं, क्योंकि इसमें कोई निजी डेटा नहीं होता. हालांकि, इसे सिर्फ़ क्रिएटर अपडेट कर सकता है.
- डेटा की पुष्टि करने की सुविधा जोड़ें, ताकि यह पक्का किया जा सके कि दस्तावेज़ में सभी ज़रूरी फ़ील्ड मौजूद हैं:
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;
}
}
}
- ज़रूरी नहीं: ऐप्लिकेशन में, बटन पर क्लिक करके Firebase कंसोल में Firestore डैशबोर्ड में नतीजे देखें.
ऐप्लिकेशन की झलक
10. बधाई हो!
आपने Firebase का इस्तेमाल करके, एक इंटरैक्टिव और रीयल-टाइम वेब ऐप्लिकेशन बनाया है!