Skip to content

Commit

Permalink
chore: added flavor config to the application
Browse files Browse the repository at this point in the history
  • Loading branch information
IamMuuo committed Jan 7, 2025
1 parent af25ae0 commit 990814f
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 19 deletions.
8 changes: 4 additions & 4 deletions lib/app.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:academia/configs/configs.dart';
import 'package:academia/database/database.dart';
import 'package:academia/features/features.dart';
import 'package:academia/utils/router/router.dart';
Expand All @@ -8,16 +9,15 @@ import 'package:get_it/get_it.dart';
import 'package:google_fonts/google_fonts.dart';

class Academia extends StatelessWidget {
final String flavor;
const Academia({
super.key,
required this.flavor,
});

@override
Widget build(BuildContext context) {
final GetIt getIt = GetIt.instance;
// Inject the application database
GetIt.instance.registerSingletonIfAbsent<AppDatabase>(
getIt.registerSingletonIfAbsent<AppDatabase>(
() => AppDatabase(),
instanceName: "cacheDB",
);
Expand All @@ -29,7 +29,7 @@ class Academia extends StatelessWidget {
],
child: DynamicColorBuilder(
builder: (lightscheme, darkscheme) => MaterialApp.router(
title: flavor,
title: getIt<FlavorConfig>().appName,
routerConfig: AcademiaRouter.router,
theme: ThemeData(
colorScheme: lightscheme,
Expand Down
73 changes: 73 additions & 0 deletions lib/configs/configs.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/// Enum to define available app flavors
///
/// This is used to differentiate between different versions of the app,
/// such as development, staging, and production environments.
enum Flavor { dev, staging, production }

/// Class to manage flavor configurations
///
/// This class provides a structure for managing different app flavors,
/// allowing you to specify flavor-specific properties like the app name
/// and API base URL. It includes helpers to determine the current flavor.
class FlavorConfig {
/// The current app flavor
///
/// Defines whether the app is running in development, staging, or production.
final Flavor flavor;

/// The name of the application
///
/// This can be used for display purposes to indicate the current flavor of the app.
final String appName;

/// The base URL for API calls
///
/// This allows you to configure different backend environments for each flavor.
final String apiBaseUrl;

/// The human-readable name of the current flavor
///
/// This is derived from the `Flavor` enum and is primarily used for logging or debugging.
final String flavorName;

/// Constructor
///
/// Creates an instance of `FlavorConfig` with the specified properties.
///
/// * [flavor] - The app flavor (e.g., `Flavor.dev` for development).
/// * [appName] - The name of the app for the specified flavor.
/// * [apiBaseUrl] - The API base URL for the specified flavor.
FlavorConfig({
required this.flavor,
required this.appName,
required this.apiBaseUrl,
}) : flavorName = flavor.name;

/// Checks if the current flavor is development
///
/// Returns `true` if the app is running in the development environment.
bool get isDevelopment => flavor == Flavor.dev;

/// Checks if the current flavor is staging
///
/// Returns `true` if the app is running in the staging environment.
bool get isStaging => flavor == Flavor.staging;

/// Checks if the current flavor is production
///
/// Returns `true` if the app is running in the production environment.
bool get isProduction => flavor == Flavor.production;
}

/// Example of how to use this class with `get_it` for dependency injection:
///
/// ```dart
/// final getIt = GetIt.instance;
/// getIt.registerSingleton<FlavorConfig>(
/// FlavorConfig(
/// flavor: Flavor.dev,
/// appName: "My App Dev",
/// apiBaseUrl: "https://api.dev.myapp.com",
/// ),
/// );
/// ```
4 changes: 2 additions & 2 deletions lib/features/auth/repository/user_remote_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class UserRemoteRepository with DioErrorHandler {
) async {
try {
final response = await _client.dio.post(
"/auth/authenticate",
"/verisafe/v2/auth/authenticate",
data: credentials.toJson(),
);

Expand All @@ -36,7 +36,7 @@ final class UserRemoteRepository with DioErrorHandler {
/// went wrong
Future<Either<String, UserProfileData>> fetchUserProfile() async {
try {
final response = await _client.dio.get("/users/profile");
final response = await _client.dio.get("/verisafe/v2/users/profile");
if (response.statusCode == 200) {
return right(UserProfileData.fromJson(response.data));
}
Expand Down
11 changes: 10 additions & 1 deletion lib/main_development.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import 'package:academia/app.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:academia/configs/configs.dart';

// Development's entry point
void main() {
runApp(const Academia(flavor: "development"));
GetIt.instance.registerSingleton<FlavorConfig>(
FlavorConfig(
flavor: Flavor.dev,
appName: "Academia - Dev",
apiBaseUrl: "http://127.0.0.1:8000",
),
);
runApp(const Academia());
}
12 changes: 11 additions & 1 deletion lib/main_production.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import 'package:academia/app.dart';
import 'package:academia/configs/configs.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';

// Production's entry point
void main() {
runApp(const Academia(flavor: "production"));
GetIt.instance.registerSingleton<FlavorConfig>(
FlavorConfig(
flavor: Flavor.dev,
appName: "Academia",
apiBaseUrl: "http://127.0.0.1:8000",
),
);

runApp(const Academia());
}
12 changes: 11 additions & 1 deletion lib/main_staging.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import 'package:academia/app.dart';
import 'package:academia/configs/configs.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';

// Staging's entry point
void main(List<String> args) {
runApp(const Academia(flavor: "staging"));
GetIt.instance.registerSingleton<FlavorConfig>(
FlavorConfig(
flavor: Flavor.dev,
appName: "Academia - Staging",
apiBaseUrl: "http://127.0.0.1:8000",
),
);

runApp(const Academia());
}
28 changes: 18 additions & 10 deletions lib/utils/network/dio_client.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import 'package:academia/configs/configs.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:get_it/get_it.dart';
import './auth_interceptor.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';

class DioClient {
static const String _baseUrl = "http://192.168.43.218:8000/v2";
// static const String _baseUrl = "http://127.0.0.1:8000/v2";
/// The DioClient
///
/// Will be used to send requests to the server
late Dio dio;

/// Ensure that before instanciating a DioClient that
/// you must have injected the flavor
DioClient() {
final GetIt getIt = GetIt.instance;

dio = Dio(
BaseOptions(
baseUrl: getIt<FlavorConfig>().apiBaseUrl,
preserveHeaderCase: true,
receiveDataWhenStatusError: true,
),
);

dio.interceptors.add(
PrettyDioLogger(
error: true,
Expand All @@ -25,14 +41,6 @@ class DioClient {
_addAuthInterceptor();
}

final Dio dio = Dio(
BaseOptions(
baseUrl: _baseUrl,
preserveHeaderCase: true,
receiveDataWhenStatusError: true,
),
);

void _addAuthInterceptor() {
dio.interceptors.add(
AuthInterceptor(
Expand Down

0 comments on commit 990814f

Please sign in to comment.