Flutter Chat Application with Appwrite | Splash, Intro and Login Pages
In this video, I will show you how to build a chat application using Flutter and Appwrite. Appwrite is a self-hosted backend platform that provides developers with a set of easy-to-use and integrate REST APIs to manage their core backend needs. Flutter is a cross-platform mobile development framework that allows you to build native apps for iOS, Android, and web from a single codebase.
Key Topics covered:
- Create Splash Screen
- Create Intro Screen
- Create Login Screen
- Add routing between these screens
Description:
The tutorial will walk you through the process of creating Splash, Intro and Login Screens. We shall add auto_route dependency for our navigation
Code Snippet(SplashScreen):
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text("Chat with Bisky"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
ImagePath.logo,
width: 200,
)
],
),
),
);
}
@override
void initState() {
super.initState();
Future <void>.delayed(const Duration(seconds: 3));
print("Delay is done lets go to the next page");
AutoRouter.of(context).push(const IntroPage());
}
Add the above code in _MyHomePageState class
Code Snippet (IntroPage.dart):
- create pages directory
- lib/pages
- create introduction directory inside pages
- lib/pages/introduction
import 'package:auto_route/annotations.dart';
import 'package:auto_route/auto_route.dart';
import 'package:chat_with_bisky/route/app_route/AppRouter.gr.dart';
import 'package:chat_with_bisky/values/values.dart';
import 'package:flutter/material.dart';
import 'package:introduction_screen/introduction_screen.dart';
@RoutePage()
class IntroPage extends StatefulWidget{
@override
_IntroPageState createState() {
return _IntroPageState();
}
}
class _IntroPageState extends State<IntroPage>{
@override
Widget build(BuildContext context) {
return introWidget();
}
Widget introWidget(){
return IntroductionScreen(
showSkipButton: false,
next: const Icon(Icons.arrow_forward_ios),
pages: [
PageViewModel(
title: "Chat With Loved Ones",
body: "Chat with your loved ones and share your experience",
image: _buildImage(ImagePath.intro1)
),
PageViewModel(
title: "More Secure",
body: "We are more concerned about your privacy",
image: _buildImage(ImagePath.intro2)
),
PageViewModel(
title: "Share Files",
body: "Share images, videos, location and documents with your loved ones",
image: _buildImage(ImagePath.intro3)
)
],
onDone:onDonePress,
showDoneButton: true,
done: const Text('Done', style: TextStyle(fontWeight: FontWeight.w600)),
);
}
Widget _buildImage(String imagePath){
return Image.asset(imagePath,width: 150,);
}
void onDonePress() {
AutoRouter.of(context).push(const LoginPage());
}
}
Code Snippet (Login.dart):
import 'package:auto_route/annotations.dart';
import 'package:chat_with_bisky/values/values.dart';
import 'package:flutter/material.dart';
import 'package:intl_phone_number_input/intl_phone_number_input.dart';
import 'package:introduction_screen/introduction_screen.dart';
@RoutePage()
class LoginPage extends StatefulWidget{
@override
_LoginPageState createState() {
return _LoginPageState();
}
}
class _LoginPageState extends State<LoginPage>{
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
final TextEditingController controller = TextEditingController();
String initialCountry = 'BE';
PhoneNumber number = PhoneNumber(isoCode: 'BE');
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Image.asset(ImagePath.background, height: MediaQuery.of(context).size.height,),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InternationalPhoneNumberInput(
onInputChanged: (PhoneNumber number) {
print(number.phoneNumber);
},
onInputValidated: (bool value) {
print(value);
},
selectorConfig: const SelectorConfig(
selectorType: PhoneInputSelectorType.BOTTOM_SHEET,
),
ignoreBlank: false,
autoValidateMode: AutovalidateMode.disabled,
selectorTextStyle: TextStyle(color: Colors.black),
initialValue: number,
textFieldController: controller,
formatInput: true,
keyboardType:
const TextInputType.numberWithOptions(signed: true, decimal: true),
inputBorder: const OutlineInputBorder(),
onSaved: (PhoneNumber number) {
print('On Saved: $number');
},
),
ElevatedButton(
onPressed: () {
formKey.currentState?.validate();
},
child: const Text('Verify'),
),
],)
],
),
);
}
void getPhoneNumber(String phoneNumber) async {
PhoneNumber number =
await PhoneNumber.getRegionInfoFromPhoneNumber(phoneNumber, 'US');
setState(() {
this.number = number;
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
Code Snippet (AppRouter.dart):
Add IntroPage.page and LoginPage.page routes below MyHomePage.page,initial: true)
List<AutoRoute> get routes=>[
AutoRoute(page: MyHomePage.page,initial: true),
AutoRoute(page: IntroPage.page),
AutoRoute(page: LoginPage.page),
];
Code Snippet (images.dart):
Add below images constants in images.dart in lib/values/images.dart
static const String logo = "$imageDir/logo.png";
static const String intro1 = "$imageDir/chat_with_loved_ones.jpg";
static const String intro2 = "$imageDir/security.jpg";
static const String intro3 = "$imageDir/share_photos.jpg";
Code Snippet (pubspec.yaml):
Add below assets configs
assets:
- assets/images/
- assets/svg/
Conclusion:
We managed to create SplashScreen, IntroPage and LoginPages. In the next video, we shall implement Appwrite Phone Authentication. You can customize with your own images by adding them assets folder.