ফ্লটারের জন্য ফায়ারবেস জানুন

1. আপনি শুরু করার আগে

এই কোডল্যাবে, আপনি Android এবং iOS-এর জন্য Flutter মোবাইল অ্যাপ তৈরি করতে Firebase- এর কিছু মৌলিক বিষয় শিখবেন।

পূর্বশর্ত

এই কোডল্যাব ধরে নেয় আপনি Flutter এর সাথে পরিচিত, এবং আপনি Flutter SDK , এবং একজন সম্পাদক ইনস্টল করেছেন।

আপনি যা তৈরি করবেন

এই কোডল্যাবে আপনি Flutter ব্যবহার করে Android, iOS, Web এবং macOS-এ একটি ইভেন্ট RSVP এবং গেস্টবুক চ্যাট অ্যাপ তৈরি করবেন। আপনি ক্লাউড ফায়ারস্টোর ব্যবহার করে Firebase প্রমাণীকরণ এবং সিঙ্ক ডেটা সহ ব্যবহারকারীদের প্রমাণীকরণ করবেন।

আপনি কি প্রয়োজন হবে

আপনি নিম্নলিখিত ডিভাইসগুলির যেকোনো একটি ব্যবহার করে এই কোডল্যাবটি চালাতে পারেন:

উপরের ছাড়াও, আপনারও প্রয়োজন হবে:

  • আপনার পছন্দের একটি ব্রাউজার, যেমন Chrome।
  • আপনার পছন্দের একটি IDE বা পাঠ্য সম্পাদক, যেমন অ্যান্ড্রয়েড স্টুডিও বা ভিএস কোড ডার্ট এবং ফ্লাটার প্লাগইনগুলির সাথে কনফিগার করা৷
  • ফ্লটারের সর্বশেষ stable সংস্করণ (অথবা beta যদি আপনি প্রান্তে থাকতে উপভোগ করেন)।
  • আপনার ফায়ারবেস প্রজেক্ট তৈরি এবং পরিচালনার জন্য একটি জিমেইল অ্যাকাউন্টের মতো একটি Google অ্যাকাউন্ট।
  • firebase কমান্ড লাইন টুল , আপনার জিমেইল অ্যাকাউন্টে লগ ইন করা হয়েছে।
  • কোডল্যাবের নমুনা কোড। কোডটি কিভাবে পেতে হয় তার পরবর্তী ধাপ দেখুন।

2. নমুনা কোড পান

GitHub থেকে আমাদের প্রকল্পের প্রাথমিক সংস্করণ ডাউনলোড করে শুরু করা যাক।

কমান্ড লাইন থেকে GitHub সংগ্রহস্থল ক্লোন করুন:

git clone https://github.com/flutter/codelabs.git flutter-codelabs

বিকল্পভাবে, আপনার যদি GitHub এর cli টুল ইনস্টল করা থাকে:

gh repo clone flutter/codelabs flutter-codelabs

নমুনা কোডটি flutter-codelabs ডিরেক্টরিতে ক্লোন করা উচিত, যেখানে কোডল্যাবগুলির একটি সংগ্রহের জন্য কোড রয়েছে। এই কোডল্যাবের কোড হল flutter-codelabs/firebase-get-to-know-flutter এ।

flutter-codelabs/firebase-get-to-know-flutter এর অধীনে ডিরেক্টরি কাঠামোটি প্রতিটি নামযুক্ত ধাপের শেষে আপনার কোথায় থাকা উচিত তার স্ন্যাপশটের একটি সিরিজ। এটি ধাপ 2, তাই মিলে যাওয়া ফাইলগুলি সনাক্ত করা যতটা সহজ:

cd flutter-codelabs/firebase-get-to-know-flutter/step_02

আপনি যদি এড়িয়ে যেতে চান, বা একটি ধাপের পরে কিছু দেখতে কেমন হওয়া উচিত তা দেখতে চাইলে, আপনার আগ্রহের ধাপের নাম অনুসারে নির্দেশিকাটি দেখুন।

স্টার্টার অ্যাপ আমদানি করুন

আপনার পছন্দের IDE-এ flutter-codelabs/firebase-get-to-know-flutter/step_02 ডিরেক্টরি খুলুন বা আমদানি করুন। এই ডিরেক্টরিতে কোডল্যাবের প্রারম্ভিক কোড রয়েছে যা একটি এখনও কার্যকরী নয় ফ্লাটার মিটআপ অ্যাপ নিয়ে গঠিত।

কাজ করার জন্য ফাইলগুলি সনাক্ত করুন

এই অ্যাপের কোড একাধিক ডিরেক্টরিতে ছড়িয়ে আছে। কার্যকারিতার এই বিভাজনটি কার্যকারিতা অনুসারে কোড গ্রুপ করে কাজ করা সহজ করার জন্য ডিজাইন করা হয়েছে।

প্রকল্পে নিম্নলিখিত ফাইলগুলি সনাক্ত করুন:

  • lib/main.dart : এই ফাইলটিতে প্রধান এন্ট্রি পয়েন্ট এবং অ্যাপ্লিকেশন উইজেট রয়েছে।
  • lib/src/widgets.dart : অ্যাপ্লিকেশনটির স্টাইলিংকে মানসম্মত করতে সাহায্য করার জন্য এই ফাইলটিতে কয়েকটি উইজেট রয়েছে। এগুলি স্টার্টার অ্যাপের স্ক্রিন রচনা করতে ব্যবহৃত হয়।
  • lib/src/authentication.dart : Firebase ইমেল ভিত্তিক প্রমাণীকরণের জন্য একটি লগইন ব্যবহারকারীর অভিজ্ঞতা তৈরি করতে এই ফাইলটিতে উইজেটগুলির একটি সেট সহ FirebaseUI প্রমাণের একটি আংশিক বাস্তবায়ন রয়েছে। প্রমাণীকরণ প্রবাহের জন্য এই উইজেটগুলি এখনও স্টার্টার অ্যাপে ব্যবহার করা হয়নি, তবে আপনি শীঘ্রই সেগুলিকে সংযুক্ত করবেন৷

বাকি অ্যাপ্লিকেশন তৈরি করার জন্য আপনি অতিরিক্ত ফাইল যোগ করবেন।

lib/main.dart ফাইল পর্যালোচনা করা হচ্ছে

পুরো অ্যাপ জুড়ে রোবোটোকে ডিফল্ট ফন্টে পরিণত করতে এই অ্যাপটি google_fonts প্যাকেজের সুবিধা নেয়। অনুপ্রাণিত পাঠকের জন্য একটি অনুশীলন হল fonts.google.com অন্বেষণ করা এবং অ্যাপের বিভিন্ন অংশে আপনি সেখানে যে ফন্টগুলি আবিষ্কার করেন তা ব্যবহার করা৷

আপনি Header , Paragraph এবং IconAndDetail আকারে lib/src/widgets.dart থেকে হেল্পার উইজেটগুলি ব্যবহার করছেন। এই উইজেটগুলি ডুপ্লিকেট কোড বাদ দিয়ে HomePage বর্ণিত পৃষ্ঠা বিন্যাসে বিশৃঙ্খলা কমায়৷ এটি একটি সামঞ্জস্যপূর্ণ চেহারা এবং অনুভূতি সক্ষম করার অতিরিক্ত সুবিধা রয়েছে।

Android, iOS, ওয়েব এবং macOS-এ আপনার অ্যাপটি কেমন দেখায় তা এখানে:

অ্যাপের পূর্বরূপ

3. একটি ফায়ারবেস প্রকল্প তৈরি এবং সেট আপ করুন৷

ইভেন্টের তথ্য প্রদর্শন করা আপনার অতিথিদের জন্য দুর্দান্ত, কিন্তু শুধুমাত্র ইভেন্টগুলি দেখানো কারো জন্য খুব দরকারী নয়। এই অ্যাপটিতে কিছু গতিশীল কার্যকারিতা যোগ করা যাক। এর জন্য, আপনাকে আপনার অ্যাপের সাথে Firebase হুক করতে হবে। Firebase এর সাথে শুরু করার জন্য, আপনাকে একটি Firebase প্রকল্প তৈরি এবং সেট আপ করতে হবে।

একটি ফায়ারবেস প্রকল্প তৈরি করুন

  1. Firebase এ সাইন ইন করুন।
  2. Firebase কনসোলে, প্রজেক্ট যোগ করুন (বা একটি প্রকল্প তৈরি করুন ) এ ক্লিক করুন এবং আপনার Firebase প্রকল্পের নাম Firebase-Flutter-Codelab দিন

4395e4e67c08043a.png

  1. প্রকল্প তৈরির বিকল্পগুলির মাধ্যমে ক্লিক করুন। অনুরোধ করা হলে Firebase শর্তাবলী স্বীকার করুন। Google Analytics সেট আপ করা এড়িয়ে যান, কারণ আপনি এই অ্যাপের জন্য Analytics ব্যবহার করবেন না।

b7138cde5f2c7b61.png

ফায়ারবেস প্রকল্পগুলি সম্পর্কে আরও জানতে, ফায়ারবেস প্রকল্পগুলি বুঝতে দেখুন।

আপনি যে অ্যাপটি তৈরি করছেন সেটি বেশ কয়েকটি Firebase পণ্য ব্যবহার করে যা ওয়েব অ্যাপের জন্য উপলব্ধ:

  • আপনার ব্যবহারকারীদের আপনার অ্যাপে সাইন ইন করার অনুমতি দেওয়ার জন্য Firebase প্রমাণীকরণ
  • ক্লাউড ফায়ারস্টোর ক্লাউডে স্ট্রাকচার্ড ডেটা সংরক্ষণ করতে এবং ডেটা পরিবর্তন হলে তাৎক্ষণিক বিজ্ঞপ্তি পেতে।
  • আপনার ডাটাবেস সুরক্ষিত করতে ফায়ারবেস নিরাপত্তা নিয়ম

এই পণ্যগুলির মধ্যে কিছু বিশেষ কনফিগারেশন প্রয়োজন বা Firebase কনসোল ব্যবহার করে সক্ষম করা প্রয়োজন।

Firebase প্রমাণীকরণের জন্য ইমেল সাইন-ইন সক্ষম করুন

ব্যবহারকারীদের ওয়েব অ্যাপে সাইন ইন করার অনুমতি দিতে, আপনি এই কোডল্যাবের জন্য ইমেল/পাসওয়ার্ড সাইন-ইন পদ্ধতি ব্যবহার করবেন:

  1. Firebase কনসোলে, বাম প্যানেলে বিল্ড মেনুটি প্রসারিত করুন।
  2. প্রমাণীকরণ ক্লিক করুন, এবং তারপর শুরু করুন বোতামে ক্লিক করুন, তারপর সাইন-ইন পদ্ধতি ট্যাবে (বা সরাসরি সাইন-ইন পদ্ধতি ট্যাবে যেতে এখানে ক্লিক করুন )।
  3. সাইন-ইন প্রদানকারীর তালিকায় ইমেল/পাসওয়ার্ডে ক্লিক করুন, সক্রিয় স্যুইচটি অন অবস্থানে সেট করুন এবং তারপর সংরক্ষণ করুন ক্লিক করুন। 58e3e3e23c2f16a4.png

ক্লাউড ফায়ারস্টোর সক্ষম করুন

ওয়েব অ্যাপটি ক্লাউড ফায়ারস্টোর ব্যবহার করে চ্যাট মেসেজ সেভ করতে এবং নতুন চ্যাট মেসেজ পেতে।

ক্লাউড ফায়ারস্টোর সক্ষম করুন:

  1. Firebase কনসোলের বিল্ড বিভাগে, ক্লাউড ফায়ারস্টোরে ক্লিক করুন।
  2. ডাটাবেস তৈরি করুন ক্লিক করুন। 99e8429832d23fa3.png
  1. স্টার্ট ইন টেস্ট মোড বিকল্পটি নির্বাচন করুন। নিরাপত্তা নিয়ম সম্পর্কে দাবিত্যাগ পড়ুন. টেস্ট মোড নিশ্চিত করে যে আপনি বিকাশের সময় অবাধে ডাটাবেসে লিখতে পারেন। পরবর্তী ক্লিক করুন. 6be00e26c72ea032.png
  1. আপনার ডাটাবেসের জন্য অবস্থান নির্বাচন করুন (আপনি শুধু ডিফল্ট ব্যবহার করতে পারেন)। মনে রাখবেন এই অবস্থানটি পরে পরিবর্তন করা যাবে না। 278656eefcfb0216.png
  2. সক্ষম করুন ক্লিক করুন।

4. ফায়ারবেস কনফিগারেশন

Flutter এর সাথে Firebase ব্যবহার করার জন্য, FlutterFire লাইব্রেরিগুলিকে সঠিকভাবে ব্যবহার করার জন্য আপনাকে Flutter প্রোজেক্ট কনফিগার করার জন্য একটি প্রক্রিয়া অনুসরণ করতে হবে:

  • আপনার প্রকল্পে FlutterFire নির্ভরতা যোগ করুন
  • Firebase প্রকল্পে পছন্দসই প্ল্যাটফর্ম নিবন্ধন করুন৷
  • প্ল্যাটফর্ম-নির্দিষ্ট কনফিগারেশন ফাইলটি ডাউনলোড করুন এবং কোডে যোগ করুন।

আপনার Flutter অ্যাপের শীর্ষ-স্তরের ডিরেক্টরিতে, android , ios , macos এবং web নামে উপ-ডিরেক্টরি রয়েছে৷ এই ডিরেক্টরিগুলি যথাক্রমে iOS এবং Android এর জন্য প্ল্যাটফর্ম-নির্দিষ্ট কনফিগারেশন ফাইল ধারণ করে।

নির্ভরতা কনফিগার করুন

আপনি এই অ্যাপে যে দুটি Firebase পণ্য ব্যবহার করছেন তার জন্য আপনাকে FlutterFire লাইব্রেরি যোগ করতে হবে - Firebase Auth এবং Cloud Firestore। নির্ভরতা যোগ করতে নিম্নলিখিত তিনটি কমান্ড চালান।

$ flutter pub add firebase_core 
Resolving dependencies...
+ firebase_core 1.10.5
+ firebase_core_platform_interface 4.2.2
+ firebase_core_web 1.5.2
+ flutter_web_plugins 0.0.0 from sdk flutter
+ js 0.6.3
  test_api 0.4.3 (0.4.8 available)
Changed 5 dependencies!

Firebase_core হল সমস্ত Firebase firebase_core প্লাগইনগুলির জন্য প্রয়োজনীয় সাধারণ কোড৷

$ flutter pub add firebase_auth
Resolving dependencies...
+ firebase_auth 3.3.3
+ firebase_auth_platform_interface 6.1.8
+ firebase_auth_web 3.3.4
+ intl 0.17.0
  test_api 0.4.3 (0.4.8 available)
Changed 4 dependencies!

firebase_auth Firebase এর প্রমাণীকরণ ক্ষমতার সাথে একীকরণ সক্ষম করে।

$ flutter pub add cloud_firestore
Resolving dependencies...
+ cloud_firestore 3.1.4
+ cloud_firestore_platform_interface 5.4.9
+ cloud_firestore_web 2.6.4
  test_api 0.4.3 (0.4.8 available)
Changed 3 dependencies!

cloud_firestore ক্লাউড ফায়ারস্টোর ডেটা স্টোরেজ অ্যাক্সেস করতে সক্ষম করে।

$ flutter pub add provider
Resolving dependencies...
+ nested 1.0.0
+ provider 6.0.1
  test_api 0.4.3 (0.4.8 available)
Changed 2 dependencies!

আপনি প্রয়োজনীয় প্যাকেজ যোগ করার সময়, Firebase যথাযথভাবে ব্যবহার করার জন্য আপনাকে iOS, Android, macOS এবং ওয়েব রানার প্রকল্পগুলিও কনফিগার করতে হবে। আপনি provider প্যাকেজটিও ব্যবহার করছেন যা ডিসপ্লে লজিক থেকে ব্যবসায়িক যুক্তিকে আলাদা করতে সক্ষম করবে।

flutterfire ইনস্টল করা হচ্ছে

FlutterFire CLI অন্তর্নিহিত Firebase CLI এর উপর নির্ভর করে। আপনি যদি ইতিমধ্যে এটি না করে থাকেন, তাহলে নিশ্চিত করুন যে আপনার মেশিনে Firebase CLI ইনস্টল করা আছে।

এরপরে, নিম্নলিখিত কমান্ডটি চালিয়ে FlutterFire CLI ইনস্টল করুন:

$ dart pub global activate flutterfire_cli

একবার ইনস্টল হয়ে গেলে, flutterfire কমান্ড বিশ্বব্যাপী উপলব্ধ হবে।

আপনার অ্যাপস কনফিগার করা হচ্ছে

CLI একটি নির্দিষ্ট প্ল্যাটফর্মের জন্য সমস্ত কনফিগারেশন তৈরি করতে আপনার Firebase প্রকল্প এবং নির্বাচিত প্রকল্প অ্যাপ্লিকেশন থেকে তথ্য বের করে।

আপনার অ্যাপ্লিকেশনের রুটে, কনফিগার কমান্ডটি চালান:

$ flutterfire configure

কনফিগারেশন কমান্ড আপনাকে বেশ কয়েকটি প্রক্রিয়ার মাধ্যমে গাইড করবে:

  1. একটি Firebase প্রকল্প নির্বাচন করা (.firebaserc ফাইলের উপর ভিত্তি করে বা Firebase কনসোল থেকে)।
  2. আপনি কোন প্ল্যাটফর্মের (যেমন Android, iOS, macOS এবং ওয়েব) কনফিগারেশন চান তা প্রম্পট করুন।
  3. নির্বাচিত প্ল্যাটফর্মগুলির জন্য কোন Firebase অ্যাপ্লিকেশনগুলি কনফিগারেশন বের করতে ব্যবহার করা উচিত তা সনাক্ত করুন৷ ডিফল্টরূপে, CLI আপনার বর্তমান প্রজেক্ট কনফিগারেশনের উপর ভিত্তি করে স্বয়ংক্রিয়ভাবে Firebase অ্যাপের সাথে মিলিত হওয়ার চেষ্টা করবে।
  4. আপনার প্রকল্পে একটি firebase_options.dart ফাইল তৈরি করুন।

macOS কনফিগার করুন

macOS-এ ফ্লাটার সম্পূর্ণরূপে স্যান্ডবক্সযুক্ত অ্যাপ্লিকেশন তৈরি করে। যেহেতু এই অ্যাপ্লিকেশনটি 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>

আরো বিস্তারিত জানার জন্য এনটাইটেলমেন্ট এবং অ্যাপ স্যান্ডবক্স দেখুন।

5. ব্যবহারকারী সাইন-ইন যোগ করুন (RSVP)

এখন যেহেতু আপনি অ্যাপটিতে Firebase যোগ করেছেন, আপনি একটি RSVP বোতাম সেট আপ করতে পারেন যা Firebase প্রমাণীকরণ ব্যবহার করে লোকেদের নিবন্ধন করে। অ্যান্ড্রয়েড নেটিভ, আইওএস নেটিভ এবং ওয়েবের জন্য প্রি-বিল্ট ফায়ারবেসইউআই অথ প্যাকেজ রয়েছে, তবে ফ্লটারের জন্য আপনাকে এই ক্ষমতা তৈরি করতে হবে।

ধাপ 2 এ আপনি যে প্রকল্পটি পুনরুদ্ধার করেছেন তাতে উইজেটের একটি সেট অন্তর্ভুক্ত রয়েছে যা বেশিরভাগ প্রমাণীকরণ প্রবাহের জন্য ব্যবহারকারী ইন্টারফেস প্রয়োগ করে। আপনি অ্যাপ্লিকেশনটিতে ফায়ারবেস প্রমাণীকরণকে একীভূত করতে ব্যবসায়িক যুক্তি প্রয়োগ করবেন।

প্রদানকারীর সাথে ব্যবসায়িক যুক্তি

আপনি একটি কেন্দ্রীভূত অ্যাপ্লিকেশন স্টেট অবজেক্ট ফ্লাটার উইজেটের অ্যাপ্লিকেশনের ট্রি জুড়ে উপলব্ধ করতে provider প্যাকেজটি ব্যবহার করতে যাচ্ছেন। শুরু করতে, lib/main.dart এর শীর্ষে আমদানি পরিবর্তন করুন:

lib/main.dart

import 'package:firebase_auth/firebase_auth.dart'; // new
import 'package:firebase_core/firebase_core.dart'; // new
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';           // new

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

import লাইনগুলি Firebase Core এবং Auth-এর পরিচয় দেয়, আপনি যে provider প্যাকেজটি ব্যবহার করছেন তা উইজেট ট্রির মাধ্যমে অ্যাপ্লিকেশান স্টেট অবজেক্টকে উপলব্ধ করতে এবং lib/src থেকে প্রমাণীকরণ উইজেটগুলি অন্তর্ভুক্ত করে।

এই অ্যাপ্লিকেশান স্টেট অবজেক্ট, ApplicationState , এই ধাপের জন্য দুটি প্রধান দায়িত্ব রয়েছে, কিন্তু আপনি পরবর্তী ধাপে অ্যাপ্লিকেশনটিতে আরও ক্ষমতা যুক্ত করার সাথে সাথে অতিরিক্ত দায়িত্ব লাভ করবে। প্রথম দায়িত্ব হল Firebase.initializeApp() এ কল দিয়ে Firebase লাইব্রেরি চালু করা, এবং তারপরে অনুমোদনের প্রবাহ পরিচালনা করা। lib/main.dart এর শেষে নিম্নলিখিত ক্লাস যোগ করুন:

lib/main.dart

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

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

    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loginState = ApplicationLoginState.loggedIn;
      } else {
        _loginState = ApplicationLoginState.loggedOut;
      }
      notifyListeners();
    });
  }

  ApplicationLoginState _loginState = ApplicationLoginState.loggedOut;
  ApplicationLoginState get loginState => _loginState;

  String? _email;
  String? get email => _email;

  void startLoginFlow() {
    _loginState = ApplicationLoginState.emailAddress;
    notifyListeners();
  }

  Future<void> verifyEmail(
    String email,
    void Function(FirebaseAuthException e) errorCallback,
  ) async {
    try {
      var methods =
          await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
      if (methods.contains('password')) {
        _loginState = ApplicationLoginState.password;
      } else {
        _loginState = ApplicationLoginState.register;
      }
      _email = email;
      notifyListeners();
    } on FirebaseAuthException catch (e) {
      errorCallback(e);
    }
  }

  Future<void> signInWithEmailAndPassword(
    String email,
    String password,
    void Function(FirebaseAuthException e) errorCallback,
  ) async {
    try {
      await FirebaseAuth.instance.signInWithEmailAndPassword(
        email: email,
        password: password,
      );
    } on FirebaseAuthException catch (e) {
      errorCallback(e);
    }
  }

  void cancelRegistration() {
    _loginState = ApplicationLoginState.emailAddress;
    notifyListeners();
  }

  Future<void> registerAccount(
      String email,
      String displayName,
      String password,
      void Function(FirebaseAuthException e) errorCallback) async {
    try {
      var credential = await FirebaseAuth.instance
          .createUserWithEmailAndPassword(email: email, password: password);
      await credential.user!.updateDisplayName(displayName);
    } on FirebaseAuthException catch (e) {
      errorCallback(e);
    }
  }

  void signOut() {
    FirebaseAuth.instance.signOut();
  }
}

এই ক্লাসের কয়েকটি মূল বিষয় লক্ষ্য করা উচিত। ব্যবহারকারী অননুমোদিতভাবে শুরু করে, অ্যাপটি ব্যবহারকারীর ইমেল ঠিকানা ফাইলে আছে কিনা তার উপর নির্ভর করে, অ্যাপটি ব্যবহারকারীর ইমেল ঠিকানার অনুরোধ করার জন্য একটি ফর্ম দেখায়, অ্যাপটি হয় ব্যবহারকারীর নিবন্ধনকারীকে জিজ্ঞাসা করবে, বা তাদের পাসওয়ার্ডের অনুরোধ করবে, এবং তারপরে অনুমান করে যে সবকিছু কাজ করে, ব্যবহারকারী প্রমাণিত হয়।

এটি অবশ্যই উল্লেখ্য যে এটি FirebaseUI প্রমাণীকরণ প্রবাহের সম্পূর্ণ বাস্তবায়ন নয়, কারণ এটি একটি বিদ্যমান অ্যাকাউন্টের ব্যবহারকারীর ক্ষেত্রে পরিচালনা করে না যার লগ ইন করতে সমস্যা হচ্ছে৷ এই অতিরিক্ত ক্ষমতা প্রয়োগ করা একটি অনুশীলন হিসাবে বাকি রয়েছে অনুপ্রাণিত পাঠক।

প্রমাণীকরণ প্রবাহকে একীভূত করা

এখন আপনার কাছে অ্যাপ্লিকেশন স্টেট শুরু হওয়ার সময় এসেছে অ্যাপ ইনিশিয়ালাইজেশনে অ্যাপ্লিকেশান স্টেট ওয়্যার করার এবং HomePage প্রমাণীকরণের প্রবাহ যোগ করার। provider প্যাকেজের মাধ্যমে অ্যাপ্লিকেশন অবস্থা সংহত করতে প্রধান এন্ট্রি পয়েন্ট আপডেট করুন:

lib/main.dart

void main() {
  // Modify from here
  runApp(
    ChangeNotifierProvider(
      create: (context) => ApplicationState(),
      builder: (context, _) => App(),
    ),
  );
  // to here.
}

main ফাংশনে পরিবর্তন প্রদানকারী প্যাকেজকে ChangeNotifierProvider উইজেট ব্যবহার করে অ্যাপ্লিকেশন স্টেট অবজেক্টকে ইনস্ট্যান্ট করার জন্য দায়ী করে। আপনি এই নির্দিষ্ট প্রদানকারী শ্রেণীটি ব্যবহার করছেন কারণ অ্যাপ্লিকেশন স্টেট অবজেক্ট ChangeNotifier প্রসারিত করে এবং এটি কখন নির্ভরশীল উইজেটগুলি পুনরায় প্রদর্শন করতে হবে তা জানতে provider প্যাকেজকে সক্ষম করে৷ অবশেষে, HomePage build পদ্ধতি আপডেট করে Authentication সাথে অ্যাপ্লিকেশন অবস্থাকে একীভূত করুন:

lib/main.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'),
          // Add from here
          Consumer<ApplicationState>(
            builder: (context, appState, _) => Authentication(
              email: appState.email,
              loginState: appState.loginState,
              startLoginFlow: appState.startLoginFlow,
              verifyEmail: appState.verifyEmail,
              signInWithEmailAndPassword: appState.signInWithEmailAndPassword,
              cancelRegistration: appState.cancelRegistration,
              registerAccount: appState.registerAccount,
              signOut: appState.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!',
          ),
        ],
      ),
    );
  }
}

আপনি Authentication উইজেটটি ইনস্ট্যান্টিয়েট করুন এবং এটি একটি Consumer উইজেটে মোড়ানো। উপভোক্তা উইজেট স্বাভাবিক উপায় যে provider প্যাকেজ গাছের অংশ পুনর্নির্মাণ করতে ব্যবহার করা যেতে পারে যখন অ্যাপ্লিকেশন অবস্থা পরিবর্তন হয়। Authentication উইজেট হল প্রমাণীকরণ UI যা আপনি এখন পরীক্ষা করবেন।

প্রমাণীকরণ প্রবাহ পরীক্ষা করা হচ্ছে

cdf2d25e436bd48d.png

এখানে প্রমাণীকরণ প্রবাহের শুরু, যেখানে ব্যবহারকারী ইমেল ফর্ম শুরু করতে RSVP বোতামে ট্যাপ করতে পারেন।

2a2cd6d69d172369.png

ইমেল প্রবেশ করার পরে, সিস্টেম নিশ্চিত করে যে ব্যবহারকারী ইতিমধ্যে নিবন্ধিত কিনা, এই ক্ষেত্রে ব্যবহারকারীকে একটি পাসওয়ার্ডের জন্য অনুরোধ করা হয়, বিকল্পভাবে যদি ব্যবহারকারী নিবন্ধিত না হয়, তাহলে তারা নিবন্ধন ফর্মের মাধ্যমে যান।

e5e65065dba36b54.png

ত্রুটি পরিচালনার প্রবাহ পরীক্ষা করতে একটি সংক্ষিপ্ত পাসওয়ার্ড (ছয়টি অক্ষরের কম) প্রবেশ করার চেষ্টা করুন। ব্যবহারকারী নিবন্ধিত হলে, তারা পরিবর্তে পাসওয়ার্ড দেখতে পাবেন।

fbb3ea35fb4f67a.png

এই পৃষ্ঠায় ত্রুটি হ্যান্ডলিং পরীক্ষা করতে ভুল পাসওয়ার্ড প্রবেশ করানো নিশ্চিত করুন৷ অবশেষে, একবার ব্যবহারকারী লগ ইন করলে, আপনি লগ ইন অভিজ্ঞতা দেখতে পাবেন যা ব্যবহারকারীকে আবার লগ আউট করার ক্ষমতা প্রদান করে।

4ed811a25b0cf816.png

এবং এর সাথে, আপনি একটি প্রমাণীকরণ প্রবাহ বাস্তবায়ন করেছেন। অভিনন্দন!

6. ক্লাউড ফায়ারস্টোরে বার্তা লিখুন

ব্যবহারকারীরা আসছেন জেনে দারুণ, কিন্তু অ্যাপটিতে অতিথিদের অন্য কিছু করার সুযোগ দেওয়া যাক। যদি তারা একটি গেস্টবুকে বার্তা রেখে যেতে পারে? তারা ভাগ করে নিতে পারে কেন তারা আসতে আগ্রহী বা তারা কার সাথে দেখা করতে চায়।

ব্যবহারকারীরা অ্যাপে যে চ্যাট বার্তাগুলি লেখেন তা সংরক্ষণ করতে, আপনি Cloud Firestore ব্যবহার করবেন।

তথ্য মডেল

ক্লাউড ফায়ারস্টোর হল একটি NoSQL ডাটাবেস, এবং ডাটাবেসে সংরক্ষিত ডেটা সংগ্রহ, নথি, ক্ষেত্র এবং উপ-সংগ্রহে বিভক্ত। আপনি চ্যাটের প্রতিটি বার্তা একটি নথি হিসাবে সংরক্ষণ করবেন guestbook নামক একটি শীর্ষ-স্তরের সংগ্রহে।

7c20dc8424bb1d84.png

Firestore এ বার্তা যোগ করুন

এই বিভাগে, আপনি ডাটাবেসে নতুন বার্তা লিখতে ব্যবহারকারীদের জন্য কার্যকারিতা যোগ করবেন। প্রথমে, আপনি UI উপাদানগুলি (ফর্ম ক্ষেত্র এবং পাঠান বোতাম) যুক্ত করেন এবং তারপরে আপনি কোডটি যুক্ত করেন যা এই উপাদানগুলিকে ডাটাবেসের সাথে সংযুক্ত করে।

প্রথমে, cloud_firestore প্যাকেজ এবং dart:async async-এর জন্য আমদানি যোগ করুন।

lib/main.dart

import 'dart:async';                                    // new

import 'package:cloud_firestore/cloud_firestore.dart';  // new
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';

import 'firebase_options.dart';
import 'src/authentication.dart';
import 'src/widgets.dart';

একটি বার্তা ক্ষেত্রের UI উপাদান এবং একটি পাঠান বোতাম তৈরি করতে, lib/main.dart GuestBook নীচে একটি নতুন রাষ্ট্রীয় উইজেট গেস্টবুক যোগ করুন।

lib/main.dart

class GuestBook extends StatefulWidget {
  const GuestBook({required this.addMessage});
  final FutureOr<void> Function(String message) addMessage;

  @override
  _GuestBookState 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 ব্যবহার করুন। কীগুলি সম্পর্কে আরও তথ্যের জন্য এবং কীভাবে সেগুলি ব্যবহার করতে হয়, অনুগ্রহ করে ফ্লটার উইজেটস 101 পর্ব "কীগুলি কখন ব্যবহার করবেন" দেখুন৷

এছাড়াও নোট করুন যেভাবে উইজেটগুলি সাজানো হয়েছে, আপনার কাছে একটি Row রয়েছে, একটি TextFormField এবং একটি StyledButton , যেটিতে নিজেই একটি Row রয়েছে। এছাড়াও মনে রাখবেন TextFormField একটি Expanded উইজেটে মোড়ানো, এটি TextFormField কে সারিতে অতিরিক্ত স্থান নিতে বাধ্য করে। কেন এটি প্রয়োজন তা আরও ভালভাবে বুঝতে, অনুগ্রহ করে বোঝার সীমাবদ্ধতাগুলি পড়ুন।

এখন আপনার কাছে একটি উইজেট রয়েছে যা ব্যবহারকারীকে অতিথি বইতে যোগ করার জন্য কিছু পাঠ্য প্রবেশ করতে সক্ষম করে, আপনাকে এটি স্ক্রিনে পেতে হবে। এটি করার জন্য, 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)),

যদিও এটি উইজেট প্রদর্শনের জন্য যথেষ্ট, এটি দরকারী কিছু করার জন্য যথেষ্ট নয়। আপনি খুব শীঘ্রই এই কোড আপডেট করবেন এটি কার্যকরী করতে।

অ্যাপের পূর্বরূপ

একজন ব্যবহারকারী পাঠান বোতামে ক্লিক করলে নিচের কোড স্নিপেটটি ট্রিগার করবে। এটি ডাটাবেসের guestbook সংগ্রহে বার্তা ইনপুট ক্ষেত্রের বিষয়বস্তু যোগ করে। বিশেষত, addMessageToGuestBook পদ্ধতি guestbook সংগ্রহে একটি নতুন নথিতে (স্বয়ংক্রিয়ভাবে তৈরি আইডি সহ) বার্তা সামগ্রী যোগ করে।

মনে রাখবেন FirebaseAuth.instance.currentUser.uid হল স্বয়ংক্রিয়ভাবে তৈরি হওয়া অনন্য আইডির একটি রেফারেন্স যা Firebase প্রমাণীকরণ সমস্ত লগ-ইন ব্যবহারকারীদের জন্য দেয়।

lib/main.dart ফাইলে আরেকটি পরিবর্তন করুন। addMessageToGuestBook পদ্ধতি যোগ করুন। আপনি পরবর্তী ধাপে ইউজার ইন্টারফেস এবং এই ক্ষমতা একসাথে সংযুক্ত করবেন।

lib/main.dart

class ApplicationState extends ChangeNotifier {

  // Current content of ApplicationState elided ...

  // Add from here
  Future<DocumentReference> addMessageToGuestBook(String message) {
    if (_loginState != ApplicationLoginState.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
}

ডাটাবেসের মধ্যে UI এর ওয়্যারিং

আপনার কাছে একটি UI আছে যেখানে ব্যবহারকারী অতিথি বইতে যোগ করতে চান এমন পাঠ্য লিখতে পারেন এবং ক্লাউড ফায়ারস্টোরে এন্ট্রি যোগ করার জন্য আপনার কাছে কোড রয়েছে। এখন আপনাকে যা করতে হবে তা হল দুটিকে একসাথে সংযুক্ত করা। lib/main.dart HomePage হোমপেজ উইজেটে নিম্নলিখিত পরিবর্তন করুন।

lib/main.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, _) => Authentication(
              email: appState.email,
              loginState: appState.loginState,
              startLoginFlow: appState.startLoginFlow,
              verifyEmail: appState.verifyEmail,
              signInWithEmailAndPassword: appState.signInWithEmailAndPassword,
              cancelRegistration: appState.cancelRegistration,
              registerAccount: appState.registerAccount,
              signOut: appState.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.loginState == ApplicationLoginState.loggedIn) ...[
                  const Header('Discussion'),
                  GuestBook(
                    addMessage: (message) =>
                        appState.addMessageToGuestBook(message),
                  ),
                ],
              ],
            ),
          ),
          // To here.
        ],
      ),
    );
  }
}

এই ধাপের শুরুতে আপনি যে দুটি লাইন যোগ করেছেন তা সম্পূর্ণ বাস্তবায়নের সাথে প্রতিস্থাপন করেছেন। আপনি যে গাছটি রেন্ডার করছেন তার অংশে অ্যাপ্লিকেশন অবস্থা উপলব্ধ করতে আপনি আবার Consumer<ApplicationState> ব্যবহার করছেন। এটি আপনাকে UI-তে একটি বার্তা প্রবেশকারী কেউ প্রতিক্রিয়া জানাতে এবং এটি ডাটাবেসে প্রকাশ করতে সক্ষম করে। পরবর্তী বিভাগে আপনি পরীক্ষা করবেন যে যোগ করা বার্তাগুলি ডাটাবেসে প্রকাশিত হয়েছে কিনা।

বার্তা পাঠানোর পরীক্ষা করুন

  1. আপনি অ্যাপে সাইন ইন করেছেন তা নিশ্চিত করুন।
  2. একটি বার্তা লিখুন যেমন "আরে আছে!", এবং তারপরে পাঠান ক্লিক করুন।

এই ক্রিয়াটি আপনার ক্লাউড ফায়ারস্টোর ডাটাবেসে বার্তাটি লেখে। যাইহোক, আপনি এখনও আপনার প্রকৃত ফ্লাটার অ্যাপে বার্তাটি দেখতে পাবেন না কারণ আপনাকে এখনও ডেটা পুনরুদ্ধার বাস্তবায়ন করতে হবে। আপনি পরবর্তী ধাপে এটি করবেন।

কিন্তু আপনি Firebase কনসোলে নতুন যোগ করা বার্তাটি দেখতে পারেন।

Firebase কনসোলে, ডেটাবেস ড্যাশবোর্ডে , আপনার নতুন যোগ করা বার্তা সহ guestbook সংগ্রহ দেখতে হবে। আপনি যদি বার্তা পাঠাতে থাকেন, আপনার গেস্টবুক সংগ্রহে অনেক নথি থাকবে, যেমন:

ফায়ারবেস কনসোল

713870af0b3b63c.png

7. বার্তা পড়ুন

এটা চমৎকার যে অতিথিরা ডাটাবেসে বার্তা লিখতে পারে, কিন্তু তারা এখনও অ্যাপে সেগুলি দেখতে পায় না। এর ঠিক করা যাক!

বার্তা সিঙ্ক্রোনাইজ করুন

বার্তাগুলি প্রদর্শন করতে, আপনাকে এমন শ্রোতাদের যোগ করতে হবে যা ডেটা পরিবর্তনের সময় ট্রিগার করে এবং তারপরে নতুন বার্তাগুলি দেখায় এমন একটি UI উপাদান তৈরি করতে হবে। আপনি অ্যাপ্লিকেশন রাজ্যে কোড যোগ করবেন যা অ্যাপ থেকে নতুন যোগ করা বার্তাগুলির জন্য শোনে।

GuestBook উইজেটের ঠিক উপরে নিম্নলিখিত মান শ্রেণী। এই ক্লাসটি ক্লাউড ফায়ারস্টোরে আপনি যে ডেটা সংরক্ষণ করছেন তার একটি কাঠামোগত দৃশ্য প্রকাশ করে৷

lib/main.dart

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

ApplicationState এর বিভাগে যেখানে আপনি স্টেট এবং গেটার্স সংজ্ঞায়িত করেন, নিম্নলিখিত নতুন লাইন যোগ করুন:

lib/main.dart

  ApplicationLoginState _loginState = ApplicationLoginState.loggedOut;
  ApplicationLoginState get loginState => _loginState;

  String? _email;
  String? get email => _email;

  // Add from here
  StreamSubscription<QuerySnapshot>? _guestBookSubscription;
  List<GuestBookMessage> _guestBookMessages = [];
  List<GuestBookMessage> get guestBookMessages => _guestBookMessages;
  // to here.

এবং পরিশেষে, ApplicationState এর প্রারম্ভিক বিভাগে, ব্যবহারকারী লগ ইন করার সময় নথি সংগ্রহের জন্য একটি প্রশ্নে সাবস্ক্রাইব করতে নিম্নলিখিত যোগ করুন এবং লগ আউট করার সময় সদস্যতা ত্যাগ করুন।

lib/main.dart

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

    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loginState = ApplicationLoginState.loggedIn;
        // Add from here
        _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();
        });
        // to here.
      } else {
        _loginState = ApplicationLoginState.loggedOut;
        // Add from here
        _guestBookMessages = [];
        _guestBookSubscription?.cancel();
        // to here.
      }
      notifyListeners();
    });
  }

এই বিভাগটি গুরুত্বপূর্ণ, কারণ এখানে আপনি guestbook সংগ্রহের উপর একটি প্রশ্ন তৈরি করেন এবং এই সংগ্রহে সদস্যতা এবং সদস্যতা ত্যাগ করেন। আপনি স্ট্রীমটি শোনেন, যেখানে আপনি guestbook সংগ্রহে বার্তাগুলির একটি স্থানীয় ক্যাশে পুনর্গঠন করেন এবং এই সদস্যতার একটি রেফারেন্সও সংরক্ষণ করেন যাতে আপনি পরে এটি থেকে সদস্যতা ত্যাগ করতে পারেন। এখানে অনেক কিছু চলছে, এবং একটি পরিষ্কার মানসিক মডেল পেতে হলে কী হয় তা পরিদর্শন করার জন্য ডিবাগারে কিছু সময় ব্যয় করা মূল্যবান।

আরও তথ্যের জন্য, ক্লাউড ফায়ারস্টোর ডকুমেন্টেশন দেখুন।

GuestBook উইজেটে আপনাকে এই পরিবর্তনশীল অবস্থাটিকে ইউজার ইন্টারফেসের সাথে সংযুক্ত করতে হবে। আপনি উইজেটটির কনফিগারেশনের অংশ হিসাবে বার্তাগুলির একটি তালিকা যোগ করে পরিবর্তন করুন।

lib/main.dart

class GuestBook extends StatefulWidget {
  // Modify the following line
  const GuestBook({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/main.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.
    );
  }
}

আপনি একটি Column উইজেট দিয়ে বিল্ড পদ্ধতির পূর্ববর্তী বিষয়বস্তু মোড়ানো, এবং তারপর Column বাচ্চাদের লেজে আপনি বার্তার তালিকায় প্রতিটি বার্তার জন্য একটি নতুন Paragraph তৈরি করার জন্য একটি সংগ্রহ যোগ করুন।

অবশেষে, নতুন messages প্যারামিটারের সাথে সঠিকভাবে GuestBook তৈরি করতে আপনাকে এখন HomePage বডি আপডেট করতে হবে।

lib/main.dart

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

সিঙ্ক্রোনাইজিং বার্তা পরীক্ষা করুন

ক্লাউড ফায়ারস্টোর ডাটাবেসে সাবস্ক্রাইব করা ক্লায়েন্টদের সাথে স্বয়ংক্রিয়ভাবে এবং তাত্ক্ষণিকভাবে ডেটা সিঙ্ক্রোনাইজ করে।

  1. ডাটাবেসে আগে তৈরি করা মেসেজগুলো অ্যাপে দেখাতে হবে। নতুন বার্তা লিখতে নির্দ্বিধায়; তারা অবিলম্বে প্রদর্শিত উচিত.
  2. আপনি একাধিক উইন্ডো বা ট্যাবে আপনার ওয়ার্কস্পেস খোলে, ট্যাব জুড়ে রিয়েল টাইমে বার্তাগুলি সিঙ্ক হবে৷
  3. (ঐচ্ছিক) আপনি Firebase কনসোলের ডাটাবেস বিভাগে সরাসরি ম্যানুয়ালি মুছে ফেলা, পরিবর্তন বা নতুন বার্তা যোগ করার চেষ্টা করতে পারেন; যেকোন পরিবর্তন UI এ উপস্থিত হওয়া উচিত।

অভিনন্দন! আপনি আপনার অ্যাপে ক্লাউড ফায়ারস্টোর ডকুমেন্ট পড়ছেন!

অ্যাপ পি পর্যালোচনা

8. মৌলিক নিরাপত্তা নিয়ম সেট আপ করুন

আপনি প্রাথমিকভাবে পরীক্ষা মোড ব্যবহার করার জন্য ক্লাউড ফায়ারস্টোর সেট আপ করেছেন, যার অর্থ হল আপনার ডাটাবেস পড়া এবং লেখার জন্য উন্মুক্ত। যাইহোক, আপনি শুধুমাত্র বিকাশের খুব প্রাথমিক পর্যায়ে পরীক্ষা মোড ব্যবহার করা উচিত. একটি সর্বোত্তম অনুশীলন হিসাবে, আপনি আপনার অ্যাপটি বিকাশ করার সাথে সাথে আপনার ডেটাবেসের জন্য সুরক্ষা নিয়ম সেট আপ করা উচিত। নিরাপত্তা আপনার অ্যাপের গঠন এবং আচরণের অবিচ্ছেদ্য হওয়া উচিত।

নিরাপত্তা বিধি আপনাকে আপনার ডাটাবেসের নথি এবং সংগ্রহগুলিতে অ্যাক্সেস নিয়ন্ত্রণ করতে দেয়। নমনীয় নিয়ম সিনট্যাক্স আপনাকে এমন নিয়ম তৈরি করতে দেয় যা সমস্ত লেখা থেকে শুরু করে সম্পূর্ণ ডাটাবেস থেকে একটি নির্দিষ্ট নথিতে ক্রিয়াকলাপের সাথে মেলে।

আপনি Firebase কনসোলে ক্লাউড ফায়ারস্টোরের জন্য নিরাপত্তা নিয়ম লিখতে পারেন:

  1. Firebase কনসোলের বিকাশ বিভাগে, Database এ ক্লিক করুন এবং তারপরে নিয়ম ট্যাবটি নির্বাচন করুন (বা সরাসরি নিয়ম ট্যাবে যেতে এখানে ক্লিক করুন )।
  2. আপনি নিম্নলিখিত ডিফল্ট নিরাপত্তা নিয়মগুলি দেখতে পাবেন, পাশাপাশি নিয়মগুলি সর্বজনীন হওয়ার বিষয়ে একটি সতর্কতা সহ।

7767a2d2e64e7275.png

সংগ্রহ চিহ্নিত করুন

প্রথমে, অ্যাপটি যে সংগ্রহগুলিতে ডেটা লেখে তা চিহ্নিত করুন।

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.
  }
}

নিরাপত্তা নিয়ম যোগ করুন

যেহেতু আপনি প্রতিটি গেস্টবুক নথিতে একটি ক্ষেত্র হিসাবে প্রমাণীকরণ UID ব্যবহার করেছেন, আপনি প্রমাণীকরণ UID পেতে পারেন এবং যাচাই করতে পারেন যে যে কেউ নথিতে লেখার চেষ্টা করছেন তার একটি মিলিত প্রমাণীকরণ UID আছে।

নীচে দেখানো হিসাবে আপনার নিয়ম সেটে পড়ার এবং লেখার নিয়মগুলি যুক্ত করুন:

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/main.dart এ, এই অবস্থার সাথে ইন্টারঅ্যাক্ট করতে UI কোড সক্ষম করতে অ্যাক্সেসর বিভাগে নিম্নলিখিত যোগ করুন:

lib/main.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/main.dart

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

    // 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();
    });
  }

উপরোক্ত একটি সর্বদা সাবস্ক্রাইব করা ক্যোয়ারী যোগ করে অংশগ্রহণকারীদের সংখ্যা খুঁজে বের করার জন্য, এবং একটি দ্বিতীয় ক্যোয়ারী যেটি শুধুমাত্র সক্রিয় থাকে যখন একজন ব্যবহারকারী লগইন করে থাকে কিনা তা খুঁজে বের করতে। এর পরে, GuestBookMessage ঘোষণার পরে নিম্নলিখিত গণনা যোগ করুন:

lib/main.dart

enum Attending { yes, no, unknown }

আপনি এখন একটি নতুন উইজেট সংজ্ঞায়িত করতে যাচ্ছেন যা পুরানো রেডিও বোতামের মতো কাজ করে। এটি একটি অনির্দিষ্ট অবস্থায় শুরু হয়, হ্যাঁ বা না কোনটিই নির্বাচিত নয়, কিন্তু একবার ব্যবহারকারী নির্বাচন করেন যে তারা উপস্থিত হচ্ছেন কি না, তারপরে আপনি সেই বিকল্পটি একটি ভরা বোতাম দিয়ে হাইলাইট করা এবং অন্য বিকল্পটি একটি ফ্ল্যাট রেন্ডারিং সহ পিছিয়ে দেখাবেন৷

lib/main.dart

class YesNoSelection extends StatelessWidget {
  const YesNoSelection({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: [
              ElevatedButton(
                style: ElevatedButton.styleFrom(elevation: 0),
                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),
              ElevatedButton(
                style: ElevatedButton.styleFrom(elevation: 0),
                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'),
              ),
            ],
          ),
        );
    }
  }
}

এরপরে, আপনাকে HomePage এর সুবিধা নিতে YesNoSelection বিল্ড পদ্ধতি আপডেট করতে হবে, যাতে লগ ইন করা ব্যবহারকারীরা অংশগ্রহণ করে থাকলে মনোনীত করতে সক্ষম করে। আপনি এই ইভেন্টে অংশগ্রহণকারীদের সংখ্যাও প্রদর্শন করবেন।

lib/main.dart

Consumer<ApplicationState>(
  builder: (context, appState, _) => Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      // Add from here
      if (appState.attendees >= 2)
        Paragraph('${appState.attendees} people going')
      else if (appState.attendees == 1)
        const Paragraph('1 person going')
      else
        const Paragraph('No one going'),
      // To here.
      if (appState.loginState == ApplicationLoginState.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 তারা যে নথিটি লিখছে তার মতোই। আপনি প্রত্যেককে অংশগ্রহণকারীদের তালিকা পড়ার অনুমতি দেবেন (যেহেতু সেখানে কোনও ব্যক্তিগত ডেটা নেই), তবে শুধুমাত্র নির্মাতা এটি আপডেট করতে সক্ষম হবেন।

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 কনসোলে আপনার ক্লাউড ফায়ারস্টোর ড্যাশবোর্ডে যান।

অ্যাপের পূর্বরূপ

10. অভিনন্দন!

আপনি একটি ইন্টারেক্টিভ, রিয়েল-টাইম ওয়েব অ্যাপ্লিকেশন তৈরি করতে Firebase ব্যবহার করেছেন!

আমরা কভার করেছি কি

  • ফায়ারবেস প্রমাণীকরণ
  • ক্লাউড ফায়ারস্টোর
  • ফায়ারবেস নিরাপত্তা নিয়ম

পরবর্তী পদক্ষেপ

আরও জানুন

কেমন যাচ্ছে?

আমরা আপনার প্রতিক্রিয়া চাই! এখানে একটি (খুব) সংক্ষিপ্ত ফর্ম পূরণ করুন .