phase 0
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
/// Configuration class that holds application settings.
|
||||
///
|
||||
/// This class contains environment-specific configuration values
|
||||
/// such as API base URL and logging settings.
|
||||
class AppConfig {
|
||||
/// The base URL for API requests.
|
||||
final String apiBaseUrl;
|
||||
|
||||
/// Whether logging is enabled in the application.
|
||||
final bool enableLogging;
|
||||
|
||||
/// Creates an [AppConfig] instance with the provided values.
|
||||
///
|
||||
/// [apiBaseUrl] - The base URL for API requests.
|
||||
/// [enableLogging] - Whether logging should be enabled.
|
||||
const AppConfig({
|
||||
required this.apiBaseUrl,
|
||||
required this.enableLogging,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppConfig(apiBaseUrl: $apiBaseUrl, enableLogging: $enableLogging)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other is AppConfig &&
|
||||
other.apiBaseUrl == apiBaseUrl &&
|
||||
other.enableLogging == enableLogging;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => apiBaseUrl.hashCode ^ enableLogging.hashCode;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import 'app_config.dart';
|
||||
|
||||
/// Exception thrown when an invalid environment is provided to [ConfigLoader].
|
||||
class InvalidEnvironmentException implements Exception {
|
||||
/// The invalid environment that was provided.
|
||||
final String environment;
|
||||
|
||||
/// Creates an [InvalidEnvironmentException] with the provided environment.
|
||||
InvalidEnvironmentException(this.environment);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'InvalidEnvironmentException: Invalid environment "$environment". '
|
||||
'Valid environments are: dev, prod';
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads application configuration based on the specified environment.
|
||||
///
|
||||
/// This class provides a factory method to load configuration for either
|
||||
/// 'dev' or 'prod' environments. It throws [InvalidEnvironmentException]
|
||||
/// if an invalid environment is provided.
|
||||
class ConfigLoader {
|
||||
/// Private constructor to prevent instantiation.
|
||||
ConfigLoader._();
|
||||
|
||||
/// Loads configuration for the specified environment.
|
||||
///
|
||||
/// [environment] - The environment to load ('dev' or 'prod').
|
||||
///
|
||||
/// Returns an [AppConfig] instance for the specified environment.
|
||||
///
|
||||
/// Throws [InvalidEnvironmentException] if [environment] is not 'dev' or 'prod'.
|
||||
static AppConfig load(String environment) {
|
||||
switch (environment.toLowerCase()) {
|
||||
case 'dev':
|
||||
return const AppConfig(
|
||||
apiBaseUrl: 'https://api-dev.example.com',
|
||||
enableLogging: true,
|
||||
);
|
||||
case 'prod':
|
||||
return const AppConfig(
|
||||
apiBaseUrl: 'https://api.example.com',
|
||||
enableLogging: false,
|
||||
);
|
||||
default:
|
||||
throw InvalidEnvironmentException(environment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'config/config_loader.dart';
|
||||
|
||||
void main() {
|
||||
// Load configuration based on environment
|
||||
// In a real app, this would come from environment variables or build config
|
||||
const String environment = String.fromEnvironment(
|
||||
'ENV',
|
||||
defaultValue: 'dev',
|
||||
);
|
||||
|
||||
final config = ConfigLoader.load(environment);
|
||||
|
||||
if (config.enableLogging) {
|
||||
debugPrint('App initialized with config: $config');
|
||||
}
|
||||
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
/// The root widget of the application.
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Load config to display in UI
|
||||
const String environment = String.fromEnvironment(
|
||||
'ENV',
|
||||
defaultValue: 'dev',
|
||||
);
|
||||
final config = ConfigLoader.load(environment);
|
||||
|
||||
return MaterialApp(
|
||||
title: 'App Boilerplate',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('App Boilerplate'),
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.check_circle_outline,
|
||||
size: 64,
|
||||
color: Colors.green,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const Text(
|
||||
'Flutter Modular App Boilerplate',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Configuration',
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_ConfigRow(
|
||||
label: 'Environment',
|
||||
value: environment.toUpperCase(),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_ConfigRow(
|
||||
label: 'API Base URL',
|
||||
value: config.apiBaseUrl,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_ConfigRow(
|
||||
label: 'Logging',
|
||||
value: config.enableLogging ? 'Enabled' : 'Disabled',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
Text(
|
||||
'Phase 0: Project Setup Complete ✓',
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Widget to display a configuration row.
|
||||
class _ConfigRow extends StatelessWidget {
|
||||
final String label;
|
||||
final String value;
|
||||
|
||||
const _ConfigRow({
|
||||
required this.label,
|
||||
required this.value,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: Text(
|
||||
'$label:',
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user