يمكنك إضافة مسار مصادقة المستخدم إلى تطبيق Flutter باستخدام FirebaseUI

1- قبل البدء

في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية إضافة Firebase Authentication إلى تطبيقك المكتوب بلغة Flutter باستخدام حزمة واجهة مستخدم FlutterFire. باستخدام هذه الحزمة، ستضيف إلى تطبيق Flutter كلّ من المصادقة باستخدام عنوان البريد الإلكتروني/كلمة المرور ومصادقة "تسجيل الدخول باستخدام حساب Google". وستتعرّف أيضًا على كيفية إعداد مشروع على Firebase واستخدام FlutterFire CLI لبدء Firebase في تطبيقك على Flutter.

المتطلبات الأساسية

يفترض هذا الدرس التطبيقي حول الترميز أنّ لديك بعض الخبرة في استخدام Flutter. إذا لم تكن كذلك، ننصحك أولاً بتعلم الأساسيات. الروابط التالية مفيدة:

من المفترض أيضًا أن تكون لديك بعض الخبرة في استخدام Firebase، ولكن لا بأس إذا لم يسبق لك إضافة Firebase إلى مشروع Flutter. إذا لم تكن معتادًا على استخدام "وحدة تحكُّم Firebase" أو إذا كنت مستخدمًا جديدًا تمامًا لمنصة Firebase، اطّلِع على الروابط التالية أولاً:

المحتوى الذي ستُنشئه

يرشدك هذا الدرس التطبيقي حول الترميز إلى كيفية إنشاء عملية المصادقة لتطبيق Flutter باستخدام Firebase للمصادقة. سيتضمّن التطبيق شاشة تسجيل الدخول وشاشة "التسجيل" وشاشة استرداد كلمة المرور وشاشة الملف الشخصي للمستخدم.

6604fc9157f2c6ae.png eab9509a41074930.png da49189a5838e0bb.png b2ccfb3632b77878.png

المعلومات التي ستطّلع عليها

يتناول هذا الدرس التطبيقي حول الترميز ما يلي:

  • إضافة Firebase إلى تطبيق Flutter
  • إعداد "وحدة تحكُّم Firebase"
  • استخدام واجهة سطر الأوامر في Firebase لإضافة Firebase إلى تطبيقك
  • استخدام FlutterFire CLI لإنشاء إعدادات Firebase في Dart
  • إضافة Firebase Authentication إلى تطبيقك المكتوب باستخدام Flutter
  • إعداد Firebase Authentication في وحدة التحكّم
  • إضافة ميزة تسجيل الدخول باستخدام عنوان البريد الإلكتروني وكلمة المرور باستخدام حزمة firebase_ui_auth
  • إضافة تسجيل المستخدمين باستخدام حزمة firebase_ui_auth
  • إضافة صفحة "هل نسيت كلمة المرور؟"
  • إضافة ميزة "تسجيل الدخول باستخدام حساب Google" من خلال firebase_ui_auth
  • جارٍ ضبط تطبيقك للعمل مع مقدّمي الخدمة الذين يستخدمون ميزة الدخول المتعدد.
  • إضافة شاشة ملف شخصي للمستخدم إلى تطبيقك باستخدام حزمة firebase_ui_auth

يركّز هذا الدرس التطبيقي حول الترميز بشكل خاص على إضافة نظام مصادقة فعّال باستخدام حزمة firebase_ui_auth. كما ستلاحظ، يمكن تنفيذ هذا التطبيق بالكامل، مع جميع الميزات المذكورة أعلاه، باستخدام 100 سطر من التعليمات البرمجية تقريبًا.

المتطلبات

  • معرفة عملية بإطار عمل Flutter وحزمة تطوير البرامج (SDK) المثبَّتة
  • محرِّر نصوص (تتوافق حِزم تطوير البرامج (IDE) من JetBrains و"استوديو Android" وVS Code مع Flutter)
  • متصفّح Google Chrome أو هدف التطوير المفضّل الآخر لديك في Flutter (ستفترض بعض أوامر الوحدة الطرفية في هذا الدليل التعليمي أنّك تشغّل تطبيقك على Chrome)

2- إنشاء مشروع على Firebase وإعداده

أول مهمة عليك إكمالها هي إنشاء مشروع Firebase في وحدة تحكّم الويب في Firebase.

إنشاء مشروع على Firebase

  1. سجِّل الدخول إلى Firebase.
  2. في وحدة تحكُّم Firebase، انقر على إضافة مشروع (أو إنشاء مشروع)، وأدخِل اسمًا لمشروع Firebase (مثل "FlutterFire-UI-Codelab").

(df42a5e3d9584b48.png

  1. انقر على خيارات إنشاء المشروع. اقبل بنود Firebase إذا طُلب منك ذلك. يمكنك تخطّي عملية إعداد "إحصاءات Google" لأنّك لن تستخدم "إحصاءات Google" لهذا التطبيق.

d1fcec48bf251eaa.png

لمزيد من المعلومات عن مشاريع Firebase، يُرجى الاطّلاع على مقالة فهم مشاريع Firebase.

تفعيل تسجيل الدخول بالبريد الإلكتروني لمصادقة Firebase

يستخدم التطبيق الذي تنشئه مصادقة Firebase للسماح للمستخدمين بتسجيل الدخول إلى تطبيقك. كما يتيح للمستخدمين الجدد التسجيل من تطبيق Flutter.

يجب تفعيل مصادقة Firebase باستخدام وحدة تحكُّم Firebase، كما أنّها تحتاج إلى إعداد خاص بعد تفعيلها.

للسماح للمستخدمين بتسجيل الدخول إلى تطبيق الويب، عليك أولاً استخدام طريقة تسجيل الدخول البريد الإلكتروني/كلمة المرور. ستضيف لاحقًا طريقة تسجيل الدخول بحساب Google.

  1. في "وحدة تحكُّم Firebase"، وسِّع القائمة إنشاء في اللوحة اليمنى.
  2. انقر على المصادقة، ثم انقر على زر البدء ثم على علامة التبويب طريقة تسجيل الدخول (أو انقر هنا للانتقال مباشرةً إلى علامة التبويب طريقة تسجيل الدخول).
  3. انقر على البريد الإلكتروني/كلمة المرور في قائمة مزوّدو خدمة تسجيل الدخول، واضبط مفتاح تفعيل على الوضع "تفعيل"، ثمّ انقر على حفظ. 58e3e3e23c2f16a4.png

3- إعداد تطبيق Flutter

ستحتاج إلى تنزيل رمز إجراء التفعيل وتثبيت واجهة سطر الأوامر في Firebase قبل أن نبدأ.

الحصول على الرمز الأوّلي

استنسِخ مستودع GitHub من سطر الأوامر:

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

بدلاً من ذلك، إذا كانت أداة CLI من GitHub مثبّتة:

gh repo clone flutter/codelabs flutter-codelabs

يجب نسخ الرمز النموذجي إلى دليل flutter-codelabs على جهازك، والذي يحتوي على الرمز الخاص بمجموعة من الدروس التطبيقية حول الترميز. يمكن العثور على رمز هذا الدرس التطبيقي حول الترميز في الدليل الفرعي flutter-codelabs/firebase-auth-flutterfire-ui.

يحتوي الدليل flutter-codelabs/firebase-auth-flutterfire-ui على مشروعَين في Flutter. يُعرف أحدهما باسم complete والآخر باسم start. يحتوي دليل start على مشروع غير مكتمل، وهو المكان الذي ستقضي فيه معظم وقتك.

cd flutter-codelabs/firebase-auth-flutterfire-ui/start

إذا كنت تريد التخطّي إلى الأمام أو مشاهدة الشكل الذي من المفترض أن يبدو عليه عند اكتماله، فابحث في الدليل المسمى "complete" (مكتمل) للرجوع إليه.

إذا كنت تريد اتّباع الدرس التطبيقي حول الترميز وإضافة رمز بنفسك، عليك البدء بتطبيق Flutter في flutter-codelabs/firebase-auth-flutterfire-ui/start وإضافة رمز إلى هذا المشروع خلال الدرس التطبيقي. افتح هذا الدليل أو استورِده إلى بيئة تطوير البرامج المتكاملة المفضّلة لديك.

تثبيت Firebase CLI

يوفر واجهة سطر الأوامر في Firebase أدوات لإدارة مشاريع Firebase. يجب تثبيت واجهة برمجة التطبيقات (CLI) لاستخدام واجهة برمجة التطبيقات FlutterFire CLI التي سيتم تثبيتها بعد قليل.

تتوفّر مجموعة متنوعة من الطرق لتثبيت واجهة برمجة التطبيقات. وأبسط طريقة، إذا كنت تستخدم نظام التشغيل MacOS أو Linux، هي تشغيل هذا الأمر من الوحدة الطرفية:

curl -sL https://firebase.tools | bash

بعد تثبيت واجهة سطر الأوامر، يجب إجراء المصادقة باستخدام Firebase.

  1. سجِّل الدخول إلى Firebase باستخدام حسابك على Google من خلال تنفيذ الأمر التالي:
firebase login
  1. يربط هذا الأمر جهازك المحلي بـ Firebase ويمنحك إذن الوصول إلى مشاريعك على Firebase.
  1. تأكَّد من أنّ أداة CLI مثبَّتة بشكلٍ صحيح وأنّها يمكنها الوصول إلى حسابك من خلال إدراج مشاريعك على Firebase. نفِّذ الأمر التالي:
firebase projects:list
  1. يجب أن تكون القائمة المعروضة مماثلة لمشاريع Firebase المُدرَجة في وحدة تحكُّم Firebase. من المفترض أن يظهر لك على الأقل flutterfire-ui-codelab.

تثبيت واجهة سطر الأوامر FlutterFire

‫FlutterFire CLI هي أداة تساعد في تسهيل عملية تثبيت Firebase على جميع المنصات المتوافقة في تطبيقك على Flutter، وهي مبنية على Firebase CLI.

أولاً، عليك تثبيت سطر الأوامر:

dart pub global activate flutterfire_cli

تأكَّد من تثبيت واجهة سطر الأوامر. نفِّذ الأمر التالي وتأكَّد من أنّ واجهة سطر الأوامر تعرِض قائمة المساعدة.

flutterfire -—help

إضافة مشروع Firebase إلى تطبيق Flutter

إعداد FlutterFire

يمكنك استخدام FlutterFire لإنشاء رمز Dart المطلوب من أجل استخدام منصة Firebase في تطبيق Flutter.

flutterfire configure

عند تنفيذ هذا الأمر، سيُطلب منك اختيار مشروع Firebase الذي تريد استخدامه والأنظمة الأساسية التي تريد إعدادها.

تعرض لقطات الشاشة التالية الطلبات التي يجب الإجابة عنها.

  1. اختَر المشروع الذي تريد استخدامه. في هذه الحالة، استخدِم flutterfire-ui-codelab 1359cdeb83204baa.png
  2. اختَر الأنظمة الأساسية التي تريد استخدامها. يتضمّن هذا الدرس التطبيقي حول الترميز خطوات لضبط مصادقة Firebase لبرنامج Flutter للويب وiOS وAndroid، ولكن يمكنك إعداد مشروع Firebase لاستخدام جميع الخيارات. 301c9534f594f472.png
  3. تعرض لقطة الشاشة هذه النتيجة في نهاية العملية. إذا كنت على دراية بمنصّة Firebase، ستلاحظ أنّه لم يكن عليك إنشاء تطبيقات لمنصّة معيّنة (مثل تطبيق Android) في وحدة التحكّم، بل نفّذت أداة FlutterFire CLI ذلك نيابةً عنك. 12199a85ade30459.png

عند اكتمال ذلك، انظر إلى تطبيق Flutter في محرِّر النصوص. أنشأ FlutterFire CLI ملفًا جديدًا باسم "firebase_options.dart". يحتوي هذا الملف على فئة باسم FirebaseOptions، وهي تتضمن متغيرات ثابتة تحتفظ بإعدادات Firebase اللازمة لكل نظام أساسي. في حال اختيار جميع الأنظمة الأساسية عند تشغيل flutterfire configure، ستظهر لك قيم ثابتة باسم web وandroid وios وmacos.

firebase_options.dart

import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
   show defaultTargetPlatform, kIsWeb, TargetPlatform;

/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
///   options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
 static FirebaseOptions get currentPlatform {
   if (kIsWeb) {
     return web;
   }
   // ignore: missing_enum_constant_in_switch
   switch (defaultTargetPlatform) {
     case TargetPlatform.android:
       return android;
     case TargetPlatform.iOS:
       return ios;
     case TargetPlatform.macOS:
       return macos;
   }

   throw UnsupportedError(
     'DefaultFirebaseOptions are not supported for this platform.',
   );
 }

 static const FirebaseOptions web = FirebaseOptions(
   apiKey: 'AIzaSyCqFjCV_9CZmYeIvcK9FVy4drmKUlSaIWY',
   appId: '1:963656261848:web:7219f7fca5fc70afb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   authDomain: 'flutterfire-ui-codelab.firebaseapp.com',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
   measurementId: 'G-DGF0CP099H',
 );

 static const FirebaseOptions android = FirebaseOptions(
   apiKey: 'AIzaSyDconZaCQpkxIJ5KQBF-3tEU0rxYsLkIe8',
   appId: '1:963656261848:android:c939ccc86ab2dcdbb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
 );

 static const FirebaseOptions ios = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );

 static const FirebaseOptions macos = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );
}

يستخدِم Firebase كلمة تطبيق للإشارة إلى إصدار معيّن لنظام أساسي معيّن في مشروع Firebase. على سبيل المثال، يحتوي مشروع Firebase المُسمى FlutterFire-ui-codelab على تطبيقات متعدّدة: تطبيق لنظام التشغيل Android وتطبيق لنظام التشغيل iOS وتطبيق لنظام التشغيل MacOS وتطبيق للويب.

تستخدم الطريقة DefaultFirebaseOptions.currentPlatform التعداد TargetPlatform الذي يعرضه Flutter لرصد النظام الأساسي الذي يعمل عليه تطبيقك، ثم تعرض قيم إعداد Firebase المطلوبة لتطبيق Firebase الصحيح.

إضافة حِزم Firebase إلى تطبيق Flutter

تتمثل خطوة الإعداد النهائية في إضافة حِزم Firebase ذات الصلة إلى مشروع Flutter. من المفترض أن يتضمّن ملف firebase_options.dart أخطاء، لأنّه يعتمد على حِزم Firebase التي لم تتم إضافتها بعد. في المحطة الطرفية، تأكَّد من أنّك في جذر مشروع Flutter على flutter-codelabs/firebase-emulator-suite/start. بعد ذلك، شغِّل الأوامر الثلاثة التالية:

flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add firebase_ui_auth

هذه هي الحزم الوحيدة التي تحتاجها في هذه المرحلة.

إعداد Firebase

لاستخدام الحِزم المُضافة، تعدِّل DefaultFirebaseOptions.currentPlatform, الرمز في الدالة main في ملف main.dart.

main.dart

void main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp(
   options: DefaultFirebaseOptions.currentPlatform,
 );


 runApp(const MyApp());
}

تؤدي هذه التعليمات البرمجية أمرَين.

  1. يطلب WidgetsFlutterBinding.ensureInitialized() من Flutter عدم بدء تشغيل رمز التطبيق المصغّر إلى أن يتم تشغيل إطار عمل Flutter بالكامل. يستخدم Firebase قنوات النظام الأساسي الأصلية التي تتطلّب تشغيل الإطار العمل.
  2. Firebase.initializeApp لإعداد اتصال بين تطبيقك المكتوب بلغة Flutter ومشروعك على Firebase يتم استيراد DefaultFirebaseOptions.currentPlatform من ملف firebase_options.dart الذي تم إنشاؤه. ترصد هذه القيمة الثابتة النظام الأساسي الذي تستخدمه، وتمررها في مفاتيح Firebase المقابلة.

4. إضافة صفحة التفويض الأولية لواجهة مستخدم Firebase

توفّر واجهة مستخدم Firebase المخصصة للمصادقة تطبيقات مصغّرة تمثّل شاشات كاملة في تطبيقك. تتعامل هذه الشاشات مع مسارات المصادقة المختلفة في تطبيقك، مثل تسجيل الدخول والتسجيل ونسيت كلمة المرور وملف المستخدم الشخصي والمزيد. للبدء، أضِف صفحة مقصودة إلى تطبيقك تؤدي دور حارس المصادقة في التطبيق الرئيسي.

Material أو تطبيق Cupertino

تتطلّب واجهة مستخدم FlutterFire أن يكون تطبيقك مرتبطًا بتطبيق MaterialApp أو CupertinoApp. وبناءً على اختيارك، ستعكس واجهة المستخدم تلقائيًا الاختلافات بين أداتَي Material أو Cupertino. في هذا الدليل التعليمي حول الرموز البرمجية، استخدِم MaterialApp، الذي سبق أن تمت إضافته إلى التطبيق في app.dart.

app.dart

import 'package:flutter/material.dart';
import 'auth_gate.dart';

class MyApp extends StatelessWidget {
 const MyApp({super.key});
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     theme: ThemeData(
       primarySwatch: Colors.blue,
     ),
     home: const AuthGate(),
   );
 }
}

التحقّق من حالة المصادقة

قبل أن تتمكّن من عرض شاشة تسجيل الدخول، عليك تحديد ما إذا كان المستخدم قد تم مصادقة هويته حاليًا. وأكثر الطرق شيوعًا للتحقّق من ذلك هي الاستماع إلى أحداث authStateChanges في FirebaseAuth باستخدام مكوّن Firebase Auth الإضافي.

في نموذج الرمز أعلاه، ينشئ MaterialApp تطبيقًا مصغّرًا AuthGate في طريقة الإنشاء. (هذه أداة مخصّصة لا تتوفّر في واجهة مستخدم FlutterFire).

يجب تحديث التطبيق المصغّر هذا لتضمين بث authStateChanges.

تعرض واجهة برمجة التطبيقات authStateChanges Stream مع المستخدم الحالي (إذا كان مسجِّلاً الدخول) أو قيمة فارغة إذا لم يكن مسجِّلاً الدخول. للاشتراك في هذه الحالة في تطبيقنا، يمكنك استخدام عنصر StreamBuilder في Flutter ونقل البث إليه.

StreamBuilder هي أداة مصغّرة يتم إنشاؤها استنادًا إلى أحدث لقطة من البيانات من البث الذي ترسله إليها. وتتم إعادة إنشائها تلقائيًا عندما يُصدر ساحة المشاركات لقطة جديدة.

يُرجى تعديل الرمز في auth_gate.dart.

auth_gate.dart

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

import 'home.dart';

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

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [],
          );
        }

        return const HomeScreen();
      },
    );
  }
}
  • يتم حاليًا اجتياز StreamBuilder.stream FirebaseAuth.instance.authStateChanged، ساحة المشاركات المذكورة أعلاه، والتي ستعرض كائن User في Firebase إذا صادق المستخدم. (وإلا سيتم عرض null.)
  • بعد ذلك، تستخدِم التعليمة البرمجية snapshot.hasData للتحقّق مما إذا كانت القيمة من البث تتضمّن العنصر User.
  • وفي حال عدم توفّرها، سيتم عرض التطبيق المصغّر SignInScreen. فِي الْوَقْتِ الْحَالِي، لَنْ يَتِمَّ تَفْعِيلْ أَيّْ عُنْصُرْ عَلَى هَذِهِ الشَّاشَة. سيتمّ تعديل ذلك في الخطوة التالية.
  • بخلاف ذلك، يتم عرض HomeScreen، وهو الجزء الرئيسي من التطبيق الذي لا يمكن للمستخدمين الذين تم إثبات هويتهم الوصول إليه إلا.

SignInScreen هي أداة تأتي من حزمة واجهة مستخدم FlutterFire. سيكون هذا هو التركيز في الخطوة التالية من هذا الدليل التعليمي. عند تشغيل التطبيق في هذه المرحلة، من المفترض أن تظهر شاشة تسجيل دخول فارغة.

5- شاشة تسجيل الدخول

يضيف التطبيق المصغّر "SignInScreen"، المتوفّر في واجهة مستخدم FlutterFire، الوظائف التالية:

  • السماح للمستخدمين بتسجيل الدخول
  • إذا نسي المستخدمون كلمة المرور، يمكنهم النقر على "هل نسيت كلمة المرور؟" ليتم نقلهم إلى نموذج لإعادة ضبط كلمة المرور.
  • إذا لم يكن المستخدم مسجّلاً بعد، يمكنه النقر على "تسجيل"، وسيتم نقله إلى نموذج آخر يتيح له الاشتراك.

مرة أخرى، لا يتطلب هذا سوى سطرين من الرموز. استرجاع الرمز في تطبيق المصادقة المصغّر:

auth_gate.dart

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

import 'home.dart';

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

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [
              EmailAuthProvider(), // new
            ],
          );
        }

        return const HomeScreen();
      },
    );
  }
}

إنّ التطبيق المصغّر SignInScreen وسيطة providers هما الرمز الوحيد المطلوب للحصول على جميع الوظائف المذكورة أعلاه. من المفترض أن تظهر الآن شاشة تسجيل الدخول التي تتضمّن حقلَي إدخال نصيَّين "البريد الإلكتروني" و"كلمة المرور"، بالإضافة إلى زر "تسجيل الدخول".

على الرغم من أنّه وظيفي، إلا أنّه يفتقر إلى التصميم. تعرِض الأداة المصغرة مَعلمات لتخصيص مظهر شاشة تسجيل الدخول. على سبيل المثال، يمكنك إضافة شعار شركتك.

تخصيص شاشة تسجيل الدخول

أداة إنشاء العناوين

باستخدام الوسيطة SignInScreen.headerBuilder، يمكنك إضافة أي تطبيقات مصغّرة تريدها فوق نموذج تسجيل الدخول. لا يتم عرض هذه الأداة إلا على شاشات ضيقة، مثل الأجهزة الجوّالة. على الشاشات العريضة، يمكنك استخدام SignInScreen.sideBuilder، والذي تتم مناقشته لاحقًا في هذا الدليل التعليمي.

عدِّل ملف auth_gate.dart باستخدام هذا الرمز:

auth_gate.dart

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

import 'home.dart';

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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('assets/flutterfire_300x.png'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

تتطلّب وسيطة headerBuilder دالة من النوع HeaderBuilder، والتي يتم تعريفها في حزمة واجهة مستخدم FlutterFire.

typedef HeaderBuilder = Widget Function(
 BuildContext context,
 BoxConstraints constraints,
 double shrinkOffset,
);

ولأنّ هذه العملية استدعاء، فهي تعرض القيم التي يمكنك استخدامها، مثل BuildContext وBoxConstraints، وتتطلّب منك عرض تطبيق مصغّر. سيتم عرض أي تطبيق مصغّر تقوم بإرجاعه في أعلى الشاشة. في هذا المثال، يضيف الرمز الجديد صورة إلى أعلى الشاشة. يُفترض أن يظهر تطبيقك الآن على النحو التالي.

73d7548d91bbd2ab.png

أداة إنشاء الترجمة

تعرض شاشة تسجيل الدخول ثلاث مَعلمات إضافية تتيح لك تخصيص الشاشة: subtitleBuilder وfooterBuilder وsideBuilder.

يختلف الإجراء subtitleBuilder قليلاً لأنّ وسيطات طلب إعادة الاتصال تتضمّن إجراءً من النوع AuthAction. AuthAction هو تعداد يمكنك استخدامه لرصد ما إذا كانت الشاشة التي ينظر إليها المستخدم هي شاشة "تسجيل الدخول" أو شاشة "التسجيل".

حدِّث الرمز في auth_gate.dart لاستخدام subtitleBuilder.

auth_gate.dart

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

import 'home.dart';

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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
              EmailAuthProvider()
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

أعِد تحميل التطبيق، ومن المفترض أن يظهر بالشكل التالي.

وسيطة footerBuilder هي نفسها وسيطة subtitleBuilder. وهو لا يعرض BoxConstraints أو shrinkOffset لأنّهما مخصّص للنصوص وليس الصور. (ويمكنك إضافة أيّ تطبيق مصغّر تريده).

يمكنك إضافة تذييل إلى شاشة تسجيل الدخول باستخدام هذا الرمز.

auth_gate.dart

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

import 'home.dart';

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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider()
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }}

أداة إنشاء المحتوى الجانبي

تقبل وسيطة SignInscreen.sidebuilder معاودة الاتصال، وهذه المرة تكون وسيطات رد الاتصال هذه هي BuildContext وdouble shrinkOffset. سيتم عرض التطبيق المصغّر الذي يعرضه sideBuilder على يسار نموذج تسجيل الدخول وعلى الشاشات العريضة فقط. يعني ذلك أنّه لن يتم عرض التطبيق المصغّر إلا على أجهزة الكمبيوتر المكتبي وتطبيقات الويب.

داخليًا، تستخدم واجهة مستخدم FlutterFire نقطة توقف لتحديد ما إذا كان يجب عرض محتوى الرأس (على الشاشات الطويلة، مثل الأجهزة الجوّالة) أو يجب عرض المحتوى الجانبي (على الشاشات العريضة أو أجهزة الكمبيوتر المكتبي أو الويب). على وجه التحديد، إذا كان عرض الشاشة أكثر من 800 بكسل، يتم عرض محتوى "أداة الإنشاء" الجانبية، ولا يتم عرض محتوى العنوان. إذا كان عرض الشاشة أقل من 800 بكسل، فإن العكس صحيح.

حدِّث الرمز في auth_gate.dart لإضافة تطبيقات sideBuilder المصغّرة.

auth_gate.dart

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

import 'home.dart';

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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }
       return const HomeScreen();
     },
   );
 }
}

من المفترض أن يظهر تطبيقك الآن على النحو التالي عند توسيع عرض النافذة (في حال استخدام Flutter Web أو MacOS).

8dc60b4e5d7dd2d0.png

إنشاء مستخدم

في هذه المرحلة، تكون قد أنشأت كل الرموز البرمجية لهذه الشاشة. وقبل أن تتمكّن من تسجيل الدخول، عليك إنشاء مستخدِم. يمكنك إجراء ذلك من خلال شاشة "التسجيل"، أو يمكنك إنشاء مستخدم في وحدة تحكُّم Firebase.

لاستخدام وحدة التحكّم:

  1. انتقِل إلى جدول "المستخدمون" في وحدة تحكُّم Firebase.
  2. انقر هنا
  3. اختَر "flutterfire-ui-codelab" (أو مشروعًا آخر إذا استخدمت اسمًا مختلفًا). سيظهر لك الجدول التالي:

f038fd9a58ed60d9.png

  1. انقر على الزر "إضافة مستخدم".

2d78390d4c5dbbfa.png

  1. أدخِل عنوان بريد إلكتروني وكلمة مرور للمستخدم الجديد. قد يكون هذا عنوان بريد إلكتروني وكلمة مرور مزيفين، كما أدخلتُ في الصورة أدناه. سيكون ذلك مفيدًا، ولكن لن تعمل وظيفة "نسيت كلمة المرور" إذا كنت تستخدم عنوان بريد إلكتروني مزيفًا.

62ba0feb33d54add.png

  1. انقر على &quot;إضافة مستخدم&quot;.

32b236b3ef94d4c7.png

يمكنك الآن الرجوع إلى تطبيق Flutter وتسجيل دخول مستخدم من خلال صفحة تسجيل الدخول. من المفترض أن يظهر تطبيقك على النحو التالي:

dd43d260537f3b1a.png

6- شاشة الملف الشخصي

توفّر واجهة مستخدم FlutterFire أيضًا التطبيق المصغّر ProfileScreen الذي يوفّر لك وظائف كثيرة في بضعة أسطر من الرموز البرمجية.

إضافة تطبيق ProfileScreen المصغّر

انتقِل إلى ملف home.dart في محرِّر النصوص. عدِّل هذا الرمز:

home.dart

import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => const ProfileScreen(),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

الرمز الجديد الذي يجب ملاحظته هو دالة الاستدعاء التي تم تمريرها إلى IconButton.isPressed method.. عند الضغط على هذا الزر IconButton، ينشئ تطبيقك مسارًا مجهول الهوية جديدًا وينتقل إليه. سيعرض هذا المسار التطبيق المصغّر ProfileScreen الذي يتم إرجاعه من دالة الاستدعاء MaterialPageRoute.builder.

أعِد تحميل تطبيقك وانقر على الرمز في أعلى يسار الشاشة (في شريط التطبيق)، وستظهر لك صفحة على النحو التالي:

36487fc4ab4f26a7.png

هذه هي واجهة المستخدم العادية التي تقدّمها صفحة واجهة مستخدم FlutterFire. يتم ربط جميع الأزرار وحقول النصوص بخدمة Firebase Auth، وهي تعمل تلقائيًا. على سبيل المثال، يمكنك إدخال اسم في حقل نص "الاسم"، وستطلب واجهة مستخدم FlutterFire طريقة FirebaseAuth.instance.currentUser?.updateDisplayName التي ستحفظ هذا الاسم في Firebase.

تسجيل الخروج

في الوقت الحالي، لن يتغير التطبيق إذا ضغطت على زر "تسجيل الخروج". سيؤدي ذلك إلى تسجيل خروجك، ولكن لن تتم إعادة توجيهك إلى تطبيق AuthGate المصغّر. لتنفيذ ذلك، استخدِم المَعلمة ProfileScreen.actions.

أولاً، عليك تعديل الرمز في home.dart.

home.dart

import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => ProfileScreen(
                    actions: [
                      SignedOutAction((context) {
                        Navigator.of(context).pop();
                      })
                    ],
                  ),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

الآن، عند إنشاء مثيل من ProfileScreen، يمكنك أيضًا تمريره بقائمة من الإجراءات إلى وسيطة ProfileScreen.actions. تكون هذه الإجراءات من النوع FlutterFireUiAction. هناك العديد من الفئات المختلفة التي هي أنواع فرعية من FlutterFireUiAction، وهي تستخدمها بشكل عام لتطلب من تطبيقك التفاعل مع التغييرات المختلفة في حالة المصادقة. يستدعي SignedOutAction دالة ردّ اتصال تقدّمها له عندما تتغيّر حالة مصادقة Firebase إلى أنّ currentUser فارغ.

من خلال إضافة استدعاء استدعاء Navigator.of(context).pop() عند تفعيل SignedOutAction، سينتقل التطبيق إلى الصفحة السابقة. في نموذج التطبيق هذا، هناك مسار دائم واحد فقط يعرض صفحة تسجيل الدخول إذا لم يكن هناك مستخدم مسجّل الدخول، والصفحة الرئيسية إذا كان هناك مستخدم. وبما أنّ ذلك يحدث عندما يسجّل المستخدم الخروج، سيعرض التطبيق صفحة "تسجيل الدخول".

تخصيص صفحة الملف الشخصي

على غرار صفحة تسجيل الدخول، يمكن تخصيص صفحة الملف الشخصي. أولاً، لا تتيح صفحتنا الحالية الانتقال إلى الصفحة الرئيسية مرة أخرى بعد أن يصل المستخدم إلى صفحة الملف الشخصي. يمكنك حلّ هذه المشكلة من خلال إضافة AppBar لأداة Profilescreen.

home.dart

import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

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

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       actions: [
         IconButton(
           icon: const Icon(Icons.person),
           onPressed: () {
             Navigator.push(
               context,
               MaterialPageRoute<ProfileScreen>(
                 builder: (context) => ProfileScreen(
                   appBar: AppBar(
                     title: const Text('User Profile'),
                   ),
                   actions: [
                     SignedOutAction((context) {
                       Navigator.of(context).pop();
                     })
                   ],
                 ),
               ),
             );
           },
         )
       ],
       automaticallyImplyLeading: false,
     ),
     body: Center(
       child: Column(
         children: [
           Image.asset('dash.png'),
           Text(
             'Welcome!',
             style: Theme.of(context).textTheme.displaySmall,
           ),
           const SignOutButton(),
         ],
       ),
     ),
   );
 }
}

تقبل الوسيطة ProfileScreen.appBar عنصر AppBar من حزمة Flutter Material، لذا يمكن التعامل معه مثل أي AppBar آخر أنشأته ونقلته إلى Scaffold. في هذا المثال، تم الاحتفاظ بالوظيفة التلقائية لإضافة زر "رجوع" تلقائيًا، وأصبح للشاشة الآن عنوان.

إضافة "الأطفال" إلى شاشة "الملف الشخصي"

تحتوي أداة Profilescreen أيضًا على وسيطة اختيارية باسم "children". تقبل هذه الوسيطة قائمة بالأدوات، وسيتم وضع هذه الأدوات عموديًا داخل أداة العمود التي يتم استخدامها داخليًا لإنشاء Profilescreen. ستؤدي أداة Column المصغّرة هذه في طريقة إنشاء ProfileScreen إلى وضع الأطفال الذين تُمرّرهم فوق الزر "تسجيل الخروج".

عدِّل الرمز في home.dart لعرض شعار الشركة هنا، على غرار شاشة تسجيل الدخول.

home.dart

import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => ProfileScreen(
                    appBar: AppBar(
                      title: const Text('User Profile'),
                    ),
                    actions: [
                      SignedOutAction((context) {
                        Navigator.of(context).pop();
                      })
                    ],
                    children: [
                      const Divider(),
                      Padding(
                        padding: const EdgeInsets.all(2),
                        child: AspectRatio(
                          aspectRatio: 1,
                          child: Image.asset('flutterfire_300x.png'),
                        ),
                      ),
                    ],
                  ),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

أعِد تحميل التطبيق، وسيظهر لك ما يلي على الشاشة:

ebe5792b765dbf87.png

7- تسجيل الدخول باستخدام مصادقة Google على أنظمة أساسية متعدّدة

توفّر واجهة مستخدم FlutterFire أيضًا تطبيقات مصغّرة ووظائف لتسجيل الدخول باستخدام مقدّمي خدمات خارجيين، مثل Google وTwitter وFacebook وApple وGithub.

لدمج المصادقة مع Google، ثبِّت المكوّن الإضافي الرسمي firebase_ui_oauth_google وجميع المكوّنات التي يعتمد عليها، والتي ستتولى مسار المصادقة الأصلي. في الوحدة الطرفية، انتقِل إلى جذر مشروعك على Flutter وأدخِل الأمر التالي:

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

تفعيل مقدِّم خدمة تسجيل الدخول بحساب Google

بعد ذلك، فعِّل مقدّم خدمة Google في وحدة تحكُّم Firebase:

  1. انتقِل إلى شاشة موفِّرو خدمات تسجيل الدخول للمصادقة في وحدة التحكّم.
  2. انقر على "إضافة مقدّم خدمة جديد". 8286fb28be94bf30.png
  3. اختَر "Google". c4e28e6f4974be7f.png
  4. فعِّل مفتاح التبديل الذي يحمل اسم "تفعيل" واضغط على "حفظ". e74ff86990763826.png
  5. إذا ظهر لك مربّع حوار يتضمّن معلومات عن تنزيل ملفات الإعداد، انقر على "تم".
  6. تأكَّد من أنّه تمت إضافة مقدّم خدمة تسجيل الدخول في Google. 5329ce0543c90d95.png

إضافة زر تسجيل الدخول باستخدام حساب Google

بعد تفعيل ميزة "تسجيل الدخول بحساب Google"، أضِف إلى صفحة تسجيل الدخول التطبيق المصغّر المطلوب لعرض زر تسجيل الدخول بحساب Google بنمط معيّن. انتقِل إلى ملف auth_gate.dart وعدِّل الرمز البرمجي على النحو التالي:

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart'; // new
import 'package:flutter/material.dart';

import 'home.dart';

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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR_WEBCLIENT_ID"),  // new
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

الرمز الجديد الوحيد هنا هو إضافة GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") إلى إعدادات التطبيق المصغّر SignInScreen.

بعد إضافة هذا الرمز، أعِد تحميل تطبيقك وسيظهر لك زر تسجيل الدخول باستخدام حساب Google.

aca71a46a011bfb5.png

إعداد زر تسجيل الدخول

لا يعمل الزر بدون ضبط إضافي. وفي حال كنت تطوِّر باستخدام Flutter Web، عليك إضافة هذه الخطوة فقط. تتطلب المنصات الأخرى خطوات إضافية، وقد تمت مناقشتها قليلاً.

  1. انتقِل إلى صفحة "موفّرو المصادقة" في وحدة تحكُّم Firebase.
  2. انقر على موفر خدمات Google. 9b3a325c5eca6e49.png
  3. انقر على لوحة التوسيع "إعدادات حزمة تطوير البرامج (SDK) للويب".
  4. انسخ القيمة من "معرّف عميل الويب" 711a79f0d931c60f.png.
  5. ارجع إلى محرِّر النصوص، وعدِّل مثيل GoogleProvider في الملف auth_gate.dart من خلال تمرير هذا المعرّف إلى المَعلمة المُسمّاة clientId.
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

بعد إدخال معرِّف العميل على الويب، أعِد تحميل تطبيقك. وعند الضغط على الزر "تسجيل الدخول باستخدام حساب Google"، ستظهر نافذة جديدة (إذا كنت تستخدم الويب) ترشدك إلى خطوات تسجيل الدخول بحساب Google. في البداية، تبدو كما يلي:

14e73e3c9de704bb.png

ضبط إعدادات iOS

ولكي يعمل ذلك على نظام التشغيل iOS، هناك عملية إعداد إضافية.

  1. انتقِل إلى شاشة "إعدادات المشروع" في وحدة تحكُّم Firebase. ستتوفّر بطاقة تعرِض تطبيقاتك على Firebase والتي تبدو كما يلي: fefa674acbf213cc.png
  2. انقر على نظام التشغيل iOS. يُرجى العِلم أنّ اسم تطبيقك سيكون مختلفًا عن اسم تطبيقي. في حال استخدمت مشروع flutter-codelabs/firebase-auth-flutterfire-ui/start لمتابعة هذا الدرس التطبيقي حول الترميز، ستظهر لك عبارة "بدء" إذا كانت الإجابة "مكتمل".
  3. انقر على الزر "GoogleServices-Info.plist" لتنزيل ملف الإعدادات المطلوب. f89b3192871dfbe3.png
  4. اسحب الملف الذي تم تنزيله وأفلِته في الدليل المسمى/ios/Runner في مشروعك على Flutter.
  5. افتح Xcode من خلال تنفيذ الأمر الطرفي التالي من جذر مشروعك: open ios/Runner.xcworkspace.
  6. انقر بزر الماوس الأيمن على دليل Runner واختَر Add Files to "Runner" (إضافة ملفات إلى Runner). 858986063a4c5201.png
  7. اختَر GoogleService-Info.plist من مدير الملفات.
  8. في محرِّر النصوص (الذي لا يُعدّ Xcode)، أضِف سمات CFBundleURLTypes أدناه إلى ملف [my_project]/ios/Runner/Info.plist.
<!-- Put me in the [my_project]/ios/Runner/Info.plist file -->
<!-- Google Sign-in Section -->
<key>CFBundleURLTypes</key>
<array>
        <dict>
                <key>CFBundleTypeRole</key>
                <string>Editor</string>
                <key>CFBundleURLSchemes</key>
                <array>
                        <!-- TODO Replace this value: -->
                        <!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID -->
                        <string>com.googleusercontent.apps.861823949799-vc35cprkp249096uujjn0vvnmcvjppkn</string>
                </array>
        </dict>
</array>
<!-- End of the Google Sign-in Section -->
  1. عليك استبدال GoogleProvider.clientId الذي أضفته في إعداد الويب بمعرّف العميل المرتبط بمعرّف عميل Firebase لنظام التشغيل iOS. أولهما، يمكنك العثور على هذا المعرّف في ملف firebase_options.dart، كجزء من ثابت iOS. انسخ القيمة التي تم تمريرها إلى iOSClientId.
static const FirebaseOptions ios = FirebaseOptions(
  apiKey: 'YOUR API KEY',
  appId: 'YOUR APP ID',
  messagingSenderId: '',
  projectId: 'PROJECT_ID',
  storageBucket: 'PROJECT_ID.firebasestorage.app',
  iosClientId: 'IOS CLIENT ID', // Find your iOS client Id here.
  iosBundleId: 'com.example.BUNDLE',
);
  1. الصِق هذه القيمة في وسيطة GoogleProvider.clientId في التطبيق المصغّر AuthGate.
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart';
import 'package:flutter/material.dart';

import 'home.dart';


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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR IOS CLIENT ID"),  // replace String
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

إذا كان تطبيق Flutter قيد التشغيل على نظام التشغيل iOS، عليك إيقافه بالكامل ثم إعادة تشغيله. بخلاف ذلك، يمكنك تشغيل التطبيق في نظام التشغيل iOS.

8- تهانينا!

لقد أكملت الدرس التطبيقي حول واجهة مستخدم Firebase Auth لتطبيق Flutter. يمكنك العثور على الرمز البرمجي المكتمل لهذا الدرس التطبيقي حول الترميز في الدليل "complete" على GitHub: Flutter Codelabs

المواضيع التي تناولناها

  • إعداد تطبيق Flutter لاستخدام Firebase
  • إعداد مشروع على Firebase في وحدة تحكّم Firebase
  • واجهة سطر الأوامر في FlutterFire
  • Firebase CLI
  • استخدام مصادقة Firebase
  • استخدام واجهة مستخدم FlutterFire لمعالجة مصادقة Firebase بسهولة في تطبيق Flutter

الخطوات التالية

مزيد من المعلومات

يسرّنا أن نحتفل معك يا ريان.

2a0ad195769368b1.gif