Skip to content

Commit 06c94ac

Browse files
committed
refactor(app_config): split platform-specific and shared config
- Separate platform-specific and shared configuration variables - Add platform-aware getters for OneSignal and Firebase config - Update factory constructors to use new split variables - Modify documentation to reflect changes in configuration setup
1 parent 429b433 commit 06c94ac

File tree

1 file changed

+128
-44
lines changed

1 file changed

+128
-44
lines changed

lib/app/config/app_config.dart

Lines changed: 128 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,48 @@
11
import 'package:flutter_news_app_mobile_client_full_source_code/app/config/app_environment.dart';
2+
import 'dart:io' show Platform;
23

34
/// {@template app_config}
4-
/// A centralized configuration class that provides all necessary environment-specific
5-
/// variables for the application.
5+
/// A centralized configuration class that provides all necessary
6+
/// environment-specific variables for the application.
67
///
7-
/// This class uses factory constructors (`.production()`, `.development()`, `.demo()`)
8-
/// to create an immutable configuration object based on the current build
9-
/// environment, which is determined at compile time. All required values are
10-
/// sourced from `--dart-define` variables, ensuring a clean separation of
11-
/// configuration from code and preventing accidental use of development keys
12-
/// in production builds.
8+
/// ## How It Works
9+
/// This class uses factory constructors (`.production()`, `.development()`,
10+
/// `.demo()`) to create an immutable configuration object based on the current
11+
/// build environment. All required values are sourced from `--dart-define`
12+
/// variables, ensuring a clean separation of configuration from code.
1313
///
14-
/// It includes robust validation to fail fast if required variables are missing,
15-
/// providing clear error messages to the developer.
14+
/// ## Platform-Specific Keys
15+
/// Some services, like Firebase and OneSignal, require unique keys for Android
16+
/// and iOS. This class handles that complexity internally. It reads both
17+
/// platform-specific keys (e.g., `FIREBASE_ANDROID_APP_ID` and
18+
/// `FIREBASE_IOS_APP_ID`) from the environment.
19+
///
20+
/// It then exposes simple, platform-aware getters (e.g., `firebaseAppId`).
21+
/// These getters automatically return the correct key based on the current
22+
/// operating system (`Platform.isAndroid` or `Platform.isIOS`). This means the
23+
/// rest of the application can simply use `appConfig.firebaseAppId` without
24+
/// needing to know which platform it's running on.
25+
///
26+
/// ## Validation
27+
/// The class includes a `_validateConfiguration` method that runs for
28+
/// `development` and `production` environments. It fails fast if:
29+
/// - A required key is missing.
30+
/// - A key still contains a placeholder value (e.g., 'YOUR_DEV_...').
31+
/// This prevents runtime errors and ensures a correctly configured build.
1632
/// {@endtemplate}
1733
class AppConfig {
1834
/// {@macro app_config}
1935
AppConfig({
2036
required this.environment,
2137
required this.baseUrl,
22-
required this.oneSignalAppId,
23-
required this.firebaseApiKey,
24-
required this.firebaseAppId,
38+
// Platform-specific keys
39+
required this.oneSignalAndroidAppId,
40+
required this.oneSignalIosAppId,
41+
required this.firebaseAndroidApiKey,
42+
required this.firebaseIosApiKey,
43+
required this.firebaseAndroidAppId,
44+
required this.firebaseIosAppId,
45+
// Shared keys
2546
required this.firebaseMessagingSenderId,
2647
required this.firebaseProjectId,
2748
required this.firebaseStorageBucket,
@@ -38,9 +59,20 @@ class AppConfig {
3859
final config = AppConfig(
3960
environment: AppEnvironment.production,
4061
baseUrl: const String.fromEnvironment('BASE_URL'),
41-
oneSignalAppId: const String.fromEnvironment('ONE_SIGNAL_APP_ID'),
42-
firebaseApiKey: const String.fromEnvironment('FIREBASE_API_KEY'),
43-
firebaseAppId: const String.fromEnvironment('FIREBASE_APP_ID'),
62+
// Platform-specific
63+
oneSignalAndroidAppId: const String.fromEnvironment(
64+
'ONE_SIGNAL_ANDROID_APP_ID',
65+
),
66+
oneSignalIosAppId: const String.fromEnvironment('ONE_SIGNAL_IOS_APP_ID'),
67+
firebaseAndroidApiKey: const String.fromEnvironment(
68+
'FIREBASE_ANDROID_API_KEY',
69+
),
70+
firebaseIosApiKey: const String.fromEnvironment('FIREBASE_IOS_API_KEY'),
71+
firebaseAndroidAppId: const String.fromEnvironment(
72+
'FIREBASE_ANDROID_APP_ID',
73+
),
74+
firebaseIosAppId: const String.fromEnvironment('FIREBASE_IOS_APP_ID'),
75+
// Shared
4476
firebaseMessagingSenderId: const String.fromEnvironment(
4577
'FIREBASE_MESSAGING_SENDER_ID',
4678
),
@@ -62,12 +94,17 @@ class AppConfig {
6294
factory AppConfig.demo() => AppConfig(
6395
environment: AppEnvironment.demo,
6496
baseUrl: '', // No API access needed for in-memory demo
65-
oneSignalAppId: 'YOUR_DEMO_ONESIGNAL_APP_ID', // Placeholder for demo
97+
// Placeholders for demo
98+
oneSignalAndroidAppId: 'YOUR_DEMO_ONESIGNAL_ANDROID_APP_ID',
99+
oneSignalIosAppId: 'YOUR_DEMO_ONESIGNAL_IOS_APP_ID',
100+
66101
// Dummy Firebase values for demo mode.
67102
// These are required to initialize Firebase but won't be used for
68103
// actual backend communication in demo mode.
69-
firebaseApiKey: 'demo-key',
70-
firebaseAppId: '1:000000000000:android:0000000000000000000000',
104+
firebaseAndroidApiKey: 'demo-key-android',
105+
firebaseIosApiKey: 'demo-key-ios',
106+
firebaseAndroidAppId: '1:000000000000:android:0000000000000000000000',
107+
firebaseIosAppId: '1:000000000000:ios:0000000000000000000000',
71108
firebaseMessagingSenderId: '000000000000',
72109
firebaseProjectId: 'demo-project',
73110
firebaseStorageBucket: '',
@@ -87,18 +124,32 @@ class AppConfig {
87124
'BASE_URL',
88125
defaultValue: 'http://localhost:8080',
89126
),
90-
oneSignalAppId: const String.fromEnvironment(
91-
'ONE_SIGNAL_APP_ID',
92-
defaultValue: 'YOUR_DEV_ONESIGNAL_APP_ID',
127+
// Platform-specific
128+
oneSignalAndroidAppId: const String.fromEnvironment(
129+
'ONE_SIGNAL_ANDROID_APP_ID',
130+
defaultValue: 'YOUR_DEV_ONESIGNAL_ANDROID_APP_ID',
93131
),
94-
firebaseApiKey: const String.fromEnvironment(
95-
'FIREBASE_API_KEY',
96-
defaultValue: 'YOUR_DEV_FIREBASE_API_KEY',
132+
oneSignalIosAppId: const String.fromEnvironment(
133+
'ONE_SIGNAL_IOS_APP_ID',
134+
defaultValue: 'YOUR_DEV_ONESIGNAL_IOS_APP_ID',
97135
),
98-
firebaseAppId: const String.fromEnvironment(
99-
'FIREBASE_APP_ID',
100-
defaultValue: 'YOUR_DEV_FIREBASE_APP_ID',
136+
firebaseAndroidApiKey: const String.fromEnvironment(
137+
'FIREBASE_ANDROID_API_KEY',
138+
defaultValue: 'YOUR_DEV_FIREBASE_ANDROID_API_KEY',
101139
),
140+
firebaseIosApiKey: const String.fromEnvironment(
141+
'FIREBASE_IOS_API_KEY',
142+
defaultValue: 'YOUR_DEV_FIREBASE_IOS_API_KEY',
143+
),
144+
firebaseAndroidAppId: const String.fromEnvironment(
145+
'FIREBASE_ANDROID_APP_ID',
146+
defaultValue: 'YOUR_DEV_FIREBASE_ANDROID_APP_ID',
147+
),
148+
firebaseIosAppId: const String.fromEnvironment(
149+
'FIREBASE_IOS_APP_ID',
150+
defaultValue: 'YOUR_DEV_FIREBASE_IOS_APP_ID',
151+
),
152+
// Shared
102153
firebaseMessagingSenderId: const String.fromEnvironment(
103154
'FIREBASE_MESSAGING_SENDER_ID',
104155
defaultValue: 'YOUR_DEV_FIREBASE_MESSAGING_SENDER_ID',
@@ -119,27 +170,54 @@ class AppConfig {
119170
/// The current build environment (e.g., production, development, demo).
120171
final AppEnvironment environment;
121172

122-
/// The base URL for the backend API.
123-
final String baseUrl;
124-
125-
/// The OneSignal App ID for push notifications.
126-
final String oneSignalAppId;
127-
128-
/// The API key for the Firebase project.
129-
final String firebaseApiKey;
173+
// --- Shared Configuration ---
130174

131-
/// The App ID for the Firebase app.
132-
final String firebaseAppId;
175+
/// The base URL for the backend API (shared across platforms).
176+
final String baseUrl;
133177

134-
/// The Sender ID for Firebase Cloud Messaging.
178+
/// The Sender ID for Firebase Cloud Messaging (shared across platforms).
135179
final String firebaseMessagingSenderId;
136180

137-
/// The Project ID for the Firebase project.
181+
/// The Project ID for the Firebase project (shared across platforms).
138182
final String firebaseProjectId;
139183

140-
/// The storage bucket for Firebase Storage.
184+
/// The storage bucket for Firebase Storage (shared across platforms).
141185
final String firebaseStorageBucket;
142186

187+
// --- Platform-Specific Raw Values ---
188+
189+
/// The OneSignal App ID for the Android platform.
190+
final String oneSignalAndroidAppId;
191+
192+
/// The OneSignal App ID for the iOS platform.
193+
final String oneSignalIosAppId;
194+
195+
/// The API key for the Firebase Android app.
196+
final String firebaseAndroidApiKey;
197+
198+
/// The API key for the Firebase iOS app.
199+
final String firebaseIosApiKey;
200+
201+
/// The App ID for the Firebase Android app.
202+
final String firebaseAndroidAppId;
203+
204+
/// The App ID for the Firebase iOS app.
205+
final String firebaseIosAppId;
206+
207+
// --- Platform-Aware Getters ---
208+
209+
/// Returns the correct OneSignal App ID for the current platform.
210+
String get oneSignalAppId =>
211+
Platform.isAndroid ? oneSignalAndroidAppId : oneSignalIosAppId;
212+
213+
/// Returns the correct Firebase API Key for the current platform.
214+
String get firebaseApiKey =>
215+
Platform.isAndroid ? firebaseAndroidApiKey : firebaseIosApiKey;
216+
217+
/// Returns the correct Firebase App ID for the current platform.
218+
String get firebaseAppId =>
219+
Platform.isAndroid ? firebaseAndroidAppId : firebaseIosAppId;
220+
143221
/// A private static method to validate the loaded configuration.
144222
///
145223
/// Throws a [FormatException] if any required environment variables are
@@ -161,9 +239,15 @@ class AppConfig {
161239
}
162240

163241
final placeholderKeys = [
164-
if (config.oneSignalAppId.contains('YOUR_')) 'ONE_SIGNAL_APP_ID',
165-
if (config.firebaseApiKey.contains('YOUR_')) 'FIREBASE_API_KEY',
166-
if (config.firebaseAppId.contains('YOUR_')) 'FIREBASE_APP_ID',
242+
if (config.oneSignalAndroidAppId.contains('YOUR_'))
243+
'ONE_SIGNAL_ANDROID_APP_ID',
244+
if (config.oneSignalIosAppId.contains('YOUR_')) 'ONE_SIGNAL_IOS_APP_ID',
245+
if (config.firebaseAndroidApiKey.contains('YOUR_'))
246+
'FIREBASE_ANDROID_API_KEY',
247+
if (config.firebaseIosApiKey.contains('YOUR_')) 'FIREBASE_IOS_API_KEY',
248+
if (config.firebaseAndroidAppId.contains('YOUR_'))
249+
'FIREBASE_ANDROID_APP_ID',
250+
if (config.firebaseIosAppId.contains('YOUR_')) 'FIREBASE_IOS_APP_ID',
167251
if (config.firebaseMessagingSenderId.contains('YOUR_'))
168252
'FIREBASE_MESSAGING_SENDER_ID',
169253
if (config.firebaseProjectId.contains('YOUR_')) 'FIREBASE_PROJECT_ID',

0 commit comments

Comments
 (0)