يوجد Package تحت التطوير يسهل العمل مع Firebase ويوفر العديد من Widgets الجاهزة للإستخام، المميز هو تحتاج القليل من الاسطر للتعامل معها وتخصيصها. الآ في مرحلة Beta يدعم Authentication وبعض خصائص Firestore. سنقوم في هذا الدرس بالتعامل مع كل مايخص المستخدم من تسجيل دخول وتسجيل حساب جديد بالإضافة الى العمل على تسجيل الدخول باستخدام حساب Google او ورقم الجوال.
👩🏻💻 إضافة FlutterFire UI الى المشروع.
اولًا نحتاج الى إضافة package المسؤول عن UI وهو FlutterFire ويمكن القيام بذلك بكتابة هذا السطر في Terminal.
flutter pub add flutterfire_ui
👨🏻💼 1. تسجيل مستخدم جديد وتسجيل الدخول.
سنقوم بإضافة تسجيل مستخم جديد وايضًا صفحة تسجيل دخول. يمكن تحقيق ذلك ببساطة بكتابة Widget مرفقة مع Package تقوم بهذه المهمة.
بداية تحتاج الى اضافة Firebase Authentication الى تطبيقك.عن طريق Terminal او كتابة مباشرة في pubspec.yaml.
عن طريق Command Line
flutter pub add firebase_auth
عن طريق ملف pubspec.yaml
dependencies:
flutter:
sdk: flutter
....
....
firebase_auth: ^3.11.2
👮🏻♀️ التحقق من المصادقة.
الآن نريد ان نتحقق هل المستخدم مسجل دخول في التطبيق سابقًا؟ هل يحتاج الي تسجيل دخول ام يحتاج الى حساب جديد! سنقوم بالتحقيق باستخدام إحدي الدوال التي يقدمها Package firebase_auth. حتى يكون التطبيق أكثر وضوح سنقوم بانشاء Widget جديد بإسم AuthGate للتحقق. هذا الرسم التوضيحي يعطي فكرة بسيط عن طريقة التحقق في تطبيقنا البسيط.
import 'package:firebase_auth/firebase_auth.dart';
class AuthGate extends StatelessWidget {
const AuthGate({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
// ...
},
);
}
}
الآن سنقوم بالتحقق عن طريق هل stream يوجد في بيانات أم لا! اذا كان هناك بيانات سنقوم بتحويل المستخدم الى الشاشة الرئيسية. أما اذا كانت البيانات فارغة او بالأصح لايوجد بيانات سنقوم بتوجيه المستخدم الى الشاشة الخاصة بتسجيل الدخول او إنشاء حساب!
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
// User is not signed in
if (!snapshot.hasData) {
// ...
}
// Render your application if authenticated
return YourApplication();
},
);
🧗🏻♂️ تجهيز شاشة تسجيل الدخول.
الآن في حالة عدم وجود البيانات او المستخدم غير مصرح سنقوم بتحويله الى شاشة تسجيل الدخول وسيكون الكود بالشكل التالي.
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
// If the user is already signed-in, use it as initial data
initialData: FirebaseAuth.instance.currentUser,
builder: (context, snapshot) {
// User is not signed in
if (!snapshot.hasData) {
return SignInScreen(
providerConfigs: []
);
}
// Render your application if authenticated
return YourApplication();
},
);
عند تشغيل التطبيق الآن بالطبع سيكون شاشة فارغة لايوجد أي مكان تستطيع كتابة بيانات المستخدم فيه او بوابة أخرى لتسجيل الدخول! إذًا مالعمل؟ يوجد مايمسى بـproviderConfigs بحيث يكون هو المسؤول عن كيفية تحكمك في التطبيق. هل تريد فقط ان يقوم المستخدم بتسجيل الدخول فقط بالايميل والباسوورد؟ ام تريد ان يستخدم بوابة أخرى مثل تسجيل الدخول عن طريق قوقل؟
💌 إضافة خاصية التسجيل بإستخدام الايميل والباسوورد.
سنقوم بإضافة سطر واحد فقط وسيقوم بإضافة خاصية تسجيل الدخول بحيث يصبح شكل شاشة SignInScreen بالشكل التالي
return SignInScreen(
providerConfigs: [
EmailProviderConfiguration(),
],
);
الآن عند تشغيل التطبيق ستلاحظ ان اصبح مكان لكتابة الإيميل والباسوورد.
واو، سطر واحد قادر على اختصار الكثير من الوقت لكتابة صفحات تسجيل الدخول. الآن يستطيع مستخدمينك تسجيل الدخول والتفاعل مع تطبيقك الجميل.
☀️ اضافة Google Sign In.
هنا مثال لطريقة اضافة Google تستطيع استخدام العديد من الخدمات الأخرى كما في الصورة التالية.
الآن نحتاج اولًا الى إضافة package تسجيل الدخول عن طريق google، نفس طريقة اضافة الـpackage لك الرختيار من Terminal او من pubspec.yaml.
- من الـterminal
flutter pub add google_sign_in
- من pubspec.yaml
dependencies:
google_sign_in: ^5.4.2
الان سنقوم بتفعيل تسجيل الدخول باستخدام google من Firebase Console
من الخيار الثاني قم بإختيار ايميلك المراد الوبط معه. الآن نعود الى الكود وتقوم باضافة googlesignin الى الـproviderConfigs. وسيكون شكل الكود لدينا كالتالي.
return SignInScreen(providerConfigs: [
EmailProviderConfiguration(),
GoogleProviderConfiguration(
clientId: '...',
),
]);
عند تشغيل التطبيق ستلاحظ وجود خيار تسجيل الدخول عن طريق Google.
📱 تخصيص الواجهات.
تعلم ان لكل تطبيق طابعه الخاص وتصميمه المميز، لكن هل نستطيع التعديل على هذه الشاشة الجاهزة للتتناسب مع زي تصميم؟ يوجد العديد من خيارات التخصيص لصفحة التسجيل سنقوم باستعراض جميع خيارات التخصيص الممكنه أيضًا اضافة Widget خاصة.
تغيير ترتيب تسجيل الدخول.
اذا اردت ان يكون مثلًا تسجيل الدخول عن طريق google هو الاول بعد ذلك مربعات نص الايميل والباسوورد. تستطيع ذلك من خلال ترتيب providerConfigs
.
اضافة رأس الصفحة.
اذا اردت اضافة شعار لتطبيقك او إسم مخصص يمكنك ذلك عن طريق headerBuilder
بحيث تضع داخله نص او صورة او أي شئ يخص تطبيقك٫ سنقوم بإضافة شعار تطبيق بسيط على حسب ذوقي والله يعينك.
return SignInScreen(
headerBuilder: (context, constraints, _) {
return const Padding(
padding: EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: FlutterLogo(
size: 200,
),
),
);
},
providerConfigs: [
const GoogleProviderConfiguration(
clientId: '...',
),
const EmailProviderConfiguration(),
]);
تعديل الصفحة الجانبية (تطبيقات سطح المكتب)
بحكم حجم تطبيقات سطح المكتب من الصعب وضع رأس للصفحة.الافضل هو اضافة الشعار على جانب الصفحة، ولهذا نحتاج اضافة sideBuilder
بحيث يكون سهل وارتب للصفحة
return SignInScreen(
sideBuilder: (context, constraints) {
return const Padding(
padding: EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: FlutterLogo(
size: 200,
),
),
);
},
headerBuilder: (context, constraints, _) {
return const Padding(
padding: EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: FlutterLogo(
size: 200,
),
),
);
},
providerConfigs: [
const GoogleProviderConfiguration(
clientId: '...',
),
const EmailProviderConfiguration(),
]);
اضافة نصوص توضيحية.
سنقوم بإضافة نصوص توضيحية للمستخدم، يمكنك اضافة صور ايضا، سنقوم بتنبيه المستخدم في حال انه موجود في صفحة الدخول سنقوم له من فضلك سجل دخول للبدء اما اذا كان في صفحة تسجيل حساب جديد سنقوم بكتابة من فضلك قم برنشاء حساب جديد للبدء، ايضا في اسفل الصفحة سنقوم بإضافة شروط الإستخدام مثلا.
return SignInScreen(
subtitleBuilder: (context, action) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text(
action == AuthAction.signIn
? 'Welcome to FlutterFire UI! Please sign in to continue.'
: 'Welcome to FlutterFire UI! Please create an account to continue',
),
);
},
footerBuilder: (context, _) {
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, constraints) {
return const Padding(
padding: EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: FlutterLogo(
size: 200,
),
),
);
},
headerBuilder: (context, constraints, _) {
return const Padding(
padding: EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: FlutterLogo(
size: 200,
),
),
);
},
providerConfigs: [
const GoogleProviderConfiguration(
clientId: '...',
),
const EmailProviderConfiguration(),
]);
الغاء الانتقال.
اذا اردت الغاء انتقال المستخدم لتسجيل حساب جديد، وتريد ادزارة ذلك بنفسك لجمع معلومات اضافية يمكنك ذلك من خلال خاصية showAuthActionSwitch
وتغيير قيمتها الى false
.
return SignInScreen(
showAuthActionSwitch: false,
// ...
);
📄 صفحات اضافية.
صفحة تسجيل حساب جديد.
يتوفر في FlutterFire صفحات اضافية مثل تسجيل حساب جديد وأيضا صفحة حساب المستخدم لتعديل ايميلة او تفعيل حسابه، يمكن التعامل معها بنفس طريقة التعامل مع صفحة SiginScreen.
return RegisterScreen(
providerConfigs: [
EmailProviderConfiguration(),
GoogleProviderConfiguration(
clientId: '...',
),
],
// ...
);
نسيت كلمة المرور.
شاشة تتيح للمستخدم استعادة كلمة المرور.
return ForgotPasswordScreen(
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20).copyWith(top: 40),
child: Icon(
Icons.lock,
color: Colors.blue,
size: constraints.maxWidth / 4 * (1 - shrinkOffset),
),
);
},
);
الحساب الشخصي.
شاشة تتيع للمستخدم تعديل اسمه، او حذف الحساب الخاص به من التطبيق.
return ProfileScreen(
providerConfigs: [
EmailProviderConfiguration(),
GoogleProviderConfiguration(
clientId: '...',
),
FacebookProviderConfiguration(
clientId: '...',
),
TwitterProviderConfiguration(
clientId: '...',
),
AppleProviderConfiguration(),
],
avatarSize: 24,
);
🌍 تغيير اللغة
اذا كان تطبيقك يدعم لغة واحدة فقط، فطرية الإضافة سهلة نوعًا ما، سنقوم بانشاء كائن للكتابة على النصوص الموجودة سابقًا. كما ستلاحظ في الكود التالي قمت بتعديل أهم النصوص التي نحتاج إضافتها للصفحة الخاصة بنا.
class LabelOverrides extends DefaultLocalizations {
const LabelOverrides();
@override
String get emailInputLabel => 'اكتب البريد الإلكتروني';
@override
String get passwordInputLabel => 'اكتب كلمة المرور';
@override
String get signInButtonText => 'تسجيل الدخول';
@override
String get registerActionText => 'تسجيل';
@override
String get registerButtonText => 'تسجيل';
@override
String get signInActionText => 'تسجيل الدخول';
@override
String get forgotPasswordButtonLabel => 'إعادة تعيين كلمة المرور';
@override
String get signInWithGoogleButtonText => 'تسجيل الدخول بحساب جوجل';
@override
String get signInText => 'تسجيل الدخول';
@override
String get registerText => 'تسجيل';
@override
String get registerHintText => 'ليس لديك حساب؟';
@override
String get signInHintText => 'لديك حساب؟';
@override
String get forgotPasswordHintText => 'نسيت كلمة المرور؟';
@override
String get confirmPasswordInputLabel => 'تأكيد كلمة المرور';
@override
String get goBackButtonLabel => 'رجوع';
@override
String get resetPasswordButtonLabel => 'إعادة تعيين كلمة المرور';
@override
String get forgotPasswordViewTitle => 'إعادة تعيين كلمة المرور';
}
الآن سنقوم بتعديل MaterialApp
واضافة التعديلا التي قمنا بها ليصبح بهذا الشكل.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
// Creates an instance of FirebaseUILocalizationDelegate with overridden labels
FlutterFireUILocalizations.withDefaultOverrides(const LabelOverrides()),
// Delegates below take care of built-in flutter widgets
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
// This delegate is required to provide the labels that are not overridden by LabelOverrides
FlutterFireUILocalizations.delegate,
],
// ...
);
}
}
عند تشغيل التطبيق ستلاحظ تغير اللغة لكل النصوص التي عدلتها سابقًا.
⚠️ لا تقم بكتابة اللغة العربية أو أي لغة في التطبيق في الكود مباشرة. ابحث عن طريقة جعل التطبيق متعدد اللغات او عن Localization٫
🌈 النمط والألوان
اذا عرفت ان Flutter عبارة عن Widgets فجميع مايظهر في الشاشة قابل للتعديل والتخصيص. يمكنك تعديل جميع اشكال الأزرار ومربعات النص في تطبيقك بشكل كامل في جميع الشاشات عن طريق تعديل theme
في MaterialApp
بدون القيام بتكرار نفسك في كل صفحة.
- سنقوم أولا بتعديل الأزرار.
return MaterialApp(
...
.....
theme: ThemeData(
primarySwatch: generateMaterialColor(color: const Color(0xff6a5ae0)),
outlinedButtonTheme: OutlinedButtonThemeData(
style: ButtonStyle(
padding: MaterialStateProperty.all<EdgeInsets>(
const EdgeInsets.all(8),
),
textStyle: MaterialStateProperty.all<TextStyle>(
const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
foregroundColor:
MaterialStateProperty.all<Color>(const Color(0xffffffff)),
backgroundColor:
MaterialStateProperty.all<Color>(const Color(0xff6a5ae0)),
shape: MaterialStateProperty.all<OutlinedBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
)))),
);
- تعديل مربعات النص
يمكن تعديل مربعات النص كما فعلنا سابقًا مع Buttons وذلك بتعديل التصميم الخاص InputField
return MaterialApp(
theme: ThemeData(
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
primarySwatch: generateMaterialColor(color: const Color(0xff6a5ae0)),
);
الخاتمة 💆🏻♂️
يوجد العديد من المميزات، بالإضافة انها مازالت في نسخة Beta والتحديث عليها مستمر. يمكنك الإطلاع على Docs الخاص بها ومشاهدة المزيد من التخصيص والخيارات بالإضافة الى إمكانية اضافة Flow الخاص بك للتطبيق.
نورت دكتور جزاك الله خيراً