🧐Understanding your project

Feature Driven Development with Bloc

Approach

FDD is an iterative and incremental software development methodology that focuses on delivering features or functionalities in a systematic and organized manner. It divides the project into small, well-defined features, and each feature is developed independently.

Quickfire will structure your Flutter codebase around features. Each feature in your app corresponds to a set of related functionalities.

For each feature, quickfire will automatically create a corresponding Bloc (Business Logic Component). The Bloc is responsible for managing the business logic and state of that specific feature.

Modularity :

Features are modular and independent. This modular structure makes it easier to understand, maintain, and scale the codebase. Developers can work on different features without interfering with each other's code.

Readability and Maintainability :

The organization of code by features enhances code readability and maintainability. Developers can easily locate and work on specific parts of the application.

Communication between features :

Features can communicate with each other through well-defined interfaces, events, or any other suitable mechanism (In Our Case We Are Using Bloc). This ensures a clean and controlled flow of information between different parts of the app.

Understanding The Folder Architecture

lib/

  constants/
    dimensions.dart
    
  features/
  
    home/
      bloc/
        home_bloc.dart
        home_event.dart
        home_state.dart
      ui/
        home_screen.dart
      repo/
      widgets/
      
    admin/
      bloc/
        admin_bloc.dart
        admin_event.dart
        admin_state.dart
      ui/
        admin_screen.dart
      repo/
      widgets/
      
  shared/
     nav_bar.dart
     
 main.dart

Constants Folder

import 'package:flutter/widgets.dart';

final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

double getScreenWidth(BuildContext context) {
  return MediaQuery.of(context).size.width;
}

double getScreenheight(BuildContext context) {
  return MediaQuery.of(context).size.height;
}

In this file a GlobalKey is created, which has two methods getScreenWidth and getScreenheight which you can use in the entire application to get rid of

MediaQuery.of(context).size.height;

Features Folder

Inside lib/features/ a folder is created for every feature.

Each feature contains 4 subfolders.

  • bloc folder -> Contains Bloc files

  • ui folder -> Contains a stateless scaffold

  • repo folder -> You can use this folder to call your services

  • widgets folder -> Common widgets for this feature

Bloc folder

  • feature_bloc.dart

import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';

part 'home_event.dart';
part 'home_state.dart';

class HomeBloc extends Bloc<HomeEvent, HomeState> {
  HomeBloc() : super(HomeInitial()) {
    on<HomeEvent>((event, emit) {
      // TODO: implement event handler
    });
  }
}
  • feature_state.dart

part of 'home_bloc.dart';

@immutable
sealed class HomeState {}

final class HomeInitial extends HomeState {}
  • feature_event.dart

part of 'home_bloc.dart';

@immutable
sealed class HomeEvent {}

UI Folder

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('HomeScreen '),
      ),
    );
  }
}

Understanding the Onboarding Feature

There are three basic scaffolds named as intro_page1.dart intro_page2.dart intro_page3.dart

on_boarding_screen.dart controls all the three intro pages using pageview

Quickfire relies on shared_preferences to show the on_boarding_screen only one time.

Understanding Navigation Screen

Quickfire creates a nav_bar with all the UI files automatically for your app based on the features.

This NavigationScreen Widget acts as root of your UI.

Setting Up Appwrite

Create a new project on appwrite and set it up for flutter.

Inside the void main() , add your project_id and project_endpoint

 Client client = Client();
  client = Client()
      .setEndpoint("<YOUR_PROJECT_ENDPOINT>")
      .setProject("<YOUR_PROJECT_ID>");
  Account account = Account(client);

Inside lib/features/auth/service/auth_status.dart

String? get userid => _currentUser.id; // Replace this line with the bottom line

String? get userid => _currentUser.$id; // added dollar symbol before 'id'.

In the init function in lib/features/auth/service/auth_status.dart

  // Initialize the Appwrite client
  init() {
    client
        .setEndpoint('replace_with_your_endpoint')
        .setProject('replace_with_project_name')
        .setSelfSigned();
    account = Account(client);
  }

Inside android/app/src/main/AndroidManifest.xml

Replace your app name with the name of your project.

Add a $ before {applicationName} like ${applicationName} and remove the comment.

android:label="<YOUR-APP-NAME>"
android:name="{applicationName}" <-- add dollar sign before {applicationName} -->

Setting up Firebase

Create a new project on Firebase console.

Run flutterfire configure inside the project

Generate SHA Keys and add them to your firebase project settings.

Select your project.

Setting up FCM

You just need a unique channel inside AndroidManifest.xml

android:value="<channel_name>"  <-- create a uniques channel name-->

Now go inside lib/features/notification/notification_services.dart

Create a unique FCM Key from Google Cloud and add it here

'Authorization': 'key=<FIREBASE_CLOUD_MESSAGING_KEY>'

"android_channel_id": "<CHANNEL_NAME>" // replace it with your channel name

AndroidNotificationDetails(
'<channel_name>', // Change this to a unique channel ID
'Your Channel Name', // no need to change this
channelDescription: '',
importance: Importance.max,
priority: Priority.high,
);

Last updated