From 0e8cabeb7f90520010d75909b1033c069708be8d Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:01:35 +0100 Subject: [PATCH 01/10] refactor: pass env to bootstrap for web splash - Pass current env to bootstrap - Web splash screen fix --- lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 646499e1..3bbebf89 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ void main() async { AppEnvironment.demo => AppConfig.demo(), }; - final appWidget = await bootstrap(appConfig); + final appWidget = await bootstrap(appConfig, currentEnvironment); // Only remove the splash screen on web after the app is ready. if (kIsWeb) { From 384508bbd3937c8f0d45d4f89ac8e28a5a262ade Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:01:41 +0100 Subject: [PATCH 02/10] feat: pass environment to app - Pass environment to App widget --- lib/bootstrap.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart index 62209b9b..422ff804 100644 --- a/lib/bootstrap.dart +++ b/lib/bootstrap.dart @@ -19,7 +19,10 @@ import 'package:ht_main/shared/localization/en_timeago_messages.dart'; import 'package:ht_shared/ht_shared.dart'; import 'package:timeago/timeago.dart' as timeago; -Future bootstrap(app_config.AppConfig appConfig) async { +Future bootstrap( + app_config.AppConfig appConfig, + app_config.AppEnvironment environment, // Added +) async { WidgetsFlutterBinding.ensureInitialized(); Bloc.observer = const AppBlocObserver(); @@ -215,5 +218,6 @@ Future bootstrap(app_config.AppConfig appConfig) async { htUserContentPreferencesRepository: userContentPreferencesRepository, htAppConfigRepository: appConfigRepository, kvStorageService: kvStorage, + environment: environment, // Pass environment to App ); } From f669839e911d75b69ecdf36ce055d321bdd248ef Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:02:00 +0100 Subject: [PATCH 03/10] feat(app): add app config and environment - Added AppConfig property - Added AppEnvironment property - Updated copyWith method --- lib/app/bloc/app_state.dart | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/app/bloc/app_state.dart b/lib/app/bloc/app_state.dart index ccfcd344..611ae44e 100644 --- a/lib/app/bloc/app_state.dart +++ b/lib/app/bloc/app_state.dart @@ -1,5 +1,8 @@ part of 'app_bloc.dart'; +import 'package:ht_main/app/config/config.dart' as local_config; +import 'package:ht_shared/ht_shared.dart' show AppConfig, UserAppSettings; // For AppConfig + /// Represents the application's authentication status. enum AppStatus { /// The application is initializing and the status is unknown. @@ -34,7 +37,8 @@ class AppState extends Equatable { this.status = AppStatus.initial, this.user, // User is now nullable and defaults to null this.locale, // Added locale - this.appConfig, // Added AppConfig + this.appConfig, + this.environment, }); /// The index of the currently selected item in the bottom navigation bar. @@ -66,7 +70,10 @@ class AppState extends Equatable { final Locale? locale; // Added locale /// The global application configuration (remote config). - final AppConfig? appConfig; // Added AppConfig + final AppConfig? appConfig; + + /// The current application environment (e.g., production, development, demo). + final local_config.AppEnvironment? environment; /// Creates a copy of the current state with updated values. AppState copyWith({ @@ -79,10 +86,12 @@ class AppState extends Equatable { User? user, UserAppSettings? settings, // Add settings to copyWith Locale? locale, // Added locale - AppConfig? appConfig, // Added AppConfig + AppConfig? appConfig, + local_config.AppEnvironment? environment, // Added AppEnvironment bool clearFontFamily = false, bool clearLocale = false, // Added to allow clearing locale bool clearAppConfig = false, // Added to allow clearing appConfig + bool clearEnvironment = false, // Added to allow clearing environment }) { return AppState( selectedBottomNavigationIndex: @@ -95,7 +104,9 @@ class AppState extends Equatable { user: user ?? this.user, settings: settings ?? this.settings, // Copy settings locale: clearLocale ? null : locale ?? this.locale, // Added locale - appConfig: clearAppConfig ? null : appConfig ?? this.appConfig, // Added + appConfig: clearAppConfig ? null : appConfig ?? this.appConfig, + environment: + clearEnvironment ? null : environment ?? this.environment, // Added ); } @@ -110,6 +121,7 @@ class AppState extends Equatable { user, settings, // Include settings in props locale, // Added locale to props - appConfig, // Added AppConfig to props + appConfig, + environment, ]; } From 4917d0932b6ad12eb59162e74fa39a97a0a0ebd4 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:02:06 +0100 Subject: [PATCH 04/10] feat(app): pass environment to AppState - Added environment variable - Passed to AppState constructor --- lib/app/bloc/app_bloc.dart | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/app/bloc/app_bloc.dart b/lib/app/bloc/app_bloc.dart index 9a260ca2..5b2a02a2 100644 --- a/lib/app/bloc/app_bloc.dart +++ b/lib/app/bloc/app_bloc.dart @@ -6,6 +6,7 @@ import 'package:flex_color_scheme/flex_color_scheme.dart'; import 'package:flutter/material.dart'; import 'package:ht_auth_repository/ht_auth_repository.dart'; import 'package:ht_data_repository/ht_data_repository.dart'; +import 'package:ht_main/app/config/config.dart' as local_config; import 'package:ht_shared/ht_shared.dart'; // Import shared models and exceptions part 'app_event.dart'; @@ -15,24 +16,23 @@ class AppBloc extends Bloc { AppBloc({ required HtAuthRepository authenticationRepository, required HtDataRepository userAppSettingsRepository, - required HtDataRepository appConfigRepository, // Added - }) : _authenticationRepository = authenticationRepository, - _userAppSettingsRepository = userAppSettingsRepository, - _appConfigRepository = appConfigRepository, // Added - // Initialize with default state, load settings after user is known - // Provide a default UserAppSettings instance - super( - // AppConfig will be null initially, fetched later - const AppState( - settings: UserAppSettings(id: 'default'), - selectedBottomNavigationIndex: 0, - appConfig: null, - ), - ) { + required HtDataRepository appConfigRepository, + required local_config.AppEnvironment environment, // Added + }) : _authenticationRepository = authenticationRepository, + _userAppSettingsRepository = userAppSettingsRepository, + _appConfigRepository = appConfigRepository, + super( + AppState( + settings: const UserAppSettings(id: 'default'), + selectedBottomNavigationIndex: 0, + appConfig: null, + environment: environment, // Pass environment to AppState + ), + ) { on(_onAppUserChanged); on(_onAppSettingsRefreshed); on(_onAppConfigFetchRequested); - on(_onAppUserAccountActionShown); // Added + on(_onAppUserAccountActionShown); on(_onLogoutRequested); on(_onThemeModeChanged); on(_onFlexSchemeChanged); From d76fea6309e52119a11a09b5cbc4e47510e826c6 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:02:12 +0100 Subject: [PATCH 05/10] feat(app): inject environment to App and AppView - Pass AppEnvironment to App - Pass AppEnvironment to AppView --- lib/app/view/app.dart | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart index 7f9ee467..7e557311 100644 --- a/lib/app/view/app.dart +++ b/lib/app/view/app.dart @@ -30,6 +30,7 @@ class App extends StatelessWidget { htUserContentPreferencesRepository, required HtDataRepository htAppConfigRepository, required HtKVStorageService kvStorageService, + required AppEnvironment environment, // Added super.key, }) : _htAuthenticationRepository = htAuthenticationRepository, _htHeadlinesRepository = htHeadlinesRepository, @@ -39,7 +40,8 @@ class App extends StatelessWidget { _htUserAppSettingsRepository = htUserAppSettingsRepository, _htUserContentPreferencesRepository = htUserContentPreferencesRepository, _htAppConfigRepository = htAppConfigRepository, - _kvStorageService = kvStorageService; + _kvStorageService = kvStorageService, + _environment = environment; // Added final HtAuthRepository _htAuthenticationRepository; final HtDataRepository _htHeadlinesRepository; @@ -51,6 +53,7 @@ class App extends StatelessWidget { _htUserContentPreferencesRepository; final HtDataRepository _htAppConfigRepository; final HtKVStorageService _kvStorageService; + final AppEnvironment _environment; // Added @override Widget build(BuildContext context) { @@ -76,8 +79,9 @@ class App extends StatelessWidget { authenticationRepository: context.read(), userAppSettingsRepository: context.read>(), - appConfigRepository: // Added - context.read>(), // Added + appConfigRepository: + context.read>(), + environment: _environment, // Pass environment ), ), BlocProvider( @@ -97,6 +101,7 @@ class App extends StatelessWidget { htUserContentPreferencesRepository: _htUserContentPreferencesRepository, htAppConfigRepository: _htAppConfigRepository, + environment: _environment, // Pass environment ), ), ); @@ -113,6 +118,7 @@ class _AppView extends StatefulWidget { required this.htUserAppSettingsRepository, required this.htUserContentPreferencesRepository, required this.htAppConfigRepository, + required this.environment, // Added }); final HtAuthRepository htAuthenticationRepository; @@ -124,6 +130,7 @@ class _AppView extends StatefulWidget { final HtDataRepository htUserContentPreferencesRepository; final HtDataRepository htAppConfigRepository; + final AppEnvironment environment; // Added @override State<_AppView> createState() => _AppViewState(); @@ -152,6 +159,7 @@ class _AppViewState extends State<_AppView> { htUserContentPreferencesRepository: widget.htUserContentPreferencesRepository, htAppConfigRepository: widget.htAppConfigRepository, + environment: widget.environment, // Pass environment ); // Removed Dynamic Link Initialization From 406e4a34eae63c693a10bef8fce327bdefa2df02 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:03:51 +0100 Subject: [PATCH 06/10] feat(auth): Display demo code in demo env - Added AppEnvironment check - Show demo code if demo env --- .../view/email_code_verification_page.dart | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/authentication/view/email_code_verification_page.dart b/lib/authentication/view/email_code_verification_page.dart index 447c5405..8d08aa40 100644 --- a/lib/authentication/view/email_code_verification_page.dart +++ b/lib/authentication/view/email_code_verification_page.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:ht_main/app/bloc/app_bloc.dart'; // Added +import 'package:ht_main/app/config/config.dart'; // Added for AppEnvironment import 'package:ht_main/authentication/bloc/authentication_bloc.dart'; import 'package:ht_main/l10n/l10n.dart'; import 'package:ht_main/shared/constants/app_spacing.dart'; @@ -72,6 +74,30 @@ class EmailCodeVerificationPage extends StatelessWidget { ), // Softer color textAlign: TextAlign.center, ), + // Display demo code if in demo environment + BlocSelector( + selector: (state) => state.environment, + builder: (context, environment) { + if (environment == AppEnvironment.demo) { + return Column( + children: [ + const SizedBox(height: AppSpacing.md), + Text( + l10n.demoVerificationCodeMessage( + '123456', + ), // Demo code + style: textTheme.bodyMedium?.copyWith( + color: colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.center, + ), + ], + ); + } + return const SizedBox.shrink(); + }, + ), const SizedBox( height: AppSpacing.xl, ), // Increased spacing From 9181c3c9cd4a69badbafeca30d747989dd12b2c9 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:08:49 +0100 Subject: [PATCH 07/10] feat(l10n): add demo verification code message --- lib/l10n/arb/app_ar.arb | 10 ++++++++++ lib/l10n/arb/app_en.arb | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/l10n/arb/app_ar.arb b/lib/l10n/arb/app_ar.arb index 38630f09..adeeb46a 100644 --- a/lib/l10n/arb/app_ar.arb +++ b/lib/l10n/arb/app_ar.arb @@ -895,5 +895,15 @@ "savedHeadlinesEmptySubheadline": "لم تقم بحفظ أي مقالات بعد. ابدأ الاستكشاف!", "@savedHeadlinesEmptySubheadline": { "description": "Subheadline for empty state on saved headlines page" + }, + "demoVerificationCodeMessage": "وضع العرض التوضيحي: استخدم الرمز {code}", + "@demoVerificationCodeMessage": { + "description": "رسالة تظهر في وضع العرض التوضيحي لتوفير رمز التحقق", + "placeholders": { + "code": { + "type": "String", + "example": "123456" + } + } } } diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 0e3bf466..eddec6d4 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -911,5 +911,15 @@ "followedCategoriesEmptySubheadline": "Start following categories to see them here.", "@followedCategoriesEmptySubheadline": { "description": "Subheadline for empty state on followed categories page" + }, + "demoVerificationCodeMessage": "Demo Mode: Use code {code}", + "@demoVerificationCodeMessage": { + "description": "Message shown in demo mode to provide the verification code", + "placeholders": { + "code": { + "type": "String", + "example": "123456" + } + } } } From d6a7ac8a2a6c65ff11726a69fde74d56bfaef1b2 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:20:41 +0100 Subject: [PATCH 08/10] feat: Add demo verification code message - Added localization keys - Added english translation - Added arabic translation --- lib/l10n/app_localizations.dart | 6 ++++++ lib/l10n/app_localizations_ar.dart | 5 +++++ lib/l10n/app_localizations_en.dart | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index cfd8253d..33ce8212 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -1381,6 +1381,12 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Start following categories to see them here.'** String get followedCategoriesEmptySubheadline; + + /// Message shown in demo mode to provide the verification code + /// + /// In en, this message translates to: + /// **'Demo Mode: Use code {code}'** + String demoVerificationCodeMessage(String code); } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_ar.dart b/lib/l10n/app_localizations_ar.dart index a5d4cd6f..77393eb0 100644 --- a/lib/l10n/app_localizations_ar.dart +++ b/lib/l10n/app_localizations_ar.dart @@ -705,4 +705,9 @@ class AppLocalizationsAr extends AppLocalizations { @override String get followedCategoriesEmptySubheadline => 'Start following categories to see them here.'; + + @override + String demoVerificationCodeMessage(String code) { + return 'وضع العرض التوضيحي: استخدم الرمز $code'; + } } diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 542d79f3..534f1a60 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -707,4 +707,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get followedCategoriesEmptySubheadline => 'Start following categories to see them here.'; + + @override + String demoVerificationCodeMessage(String code) { + return 'Demo Mode: Use code $code'; + } } From 8fd1f4314ec46be613cb9518010f85c65ef61a90 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:20:48 +0100 Subject: [PATCH 09/10] refactor: remove unused imports in app_state - Removed unused local_config import - Cleaned up app_state.dart --- lib/app/bloc/app_state.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/app/bloc/app_state.dart b/lib/app/bloc/app_state.dart index 611ae44e..a95175cb 100644 --- a/lib/app/bloc/app_state.dart +++ b/lib/app/bloc/app_state.dart @@ -1,8 +1,5 @@ part of 'app_bloc.dart'; -import 'package:ht_main/app/config/config.dart' as local_config; -import 'package:ht_shared/ht_shared.dart' show AppConfig, UserAppSettings; // For AppConfig - /// Represents the application's authentication status. enum AppStatus { /// The application is initializing and the status is unknown. From c12d944c01e03826395fe402555ab14a07f43573 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 20 Jun 2025 07:20:53 +0100 Subject: [PATCH 10/10] refactor: Remove environment from AppBloc - Removed environment param - Simplified bloc initialization --- lib/app/view/app.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart index 7e557311..6e0b5584 100644 --- a/lib/app/view/app.dart +++ b/lib/app/view/app.dart @@ -9,6 +9,7 @@ import 'package:ht_auth_repository/ht_auth_repository.dart'; // Auth Repository import 'package:ht_data_repository/ht_data_repository.dart'; // Generic Data Repository import 'package:ht_kv_storage_service/ht_kv_storage_service.dart'; // KV Storage Interface import 'package:ht_main/app/bloc/app_bloc.dart'; +import 'package:ht_main/app/config/app_environment.dart'; import 'package:ht_main/authentication/bloc/authentication_bloc.dart'; import 'package:ht_main/l10n/app_localizations.dart'; import 'package:ht_main/l10n/l10n.dart'; @@ -159,7 +160,6 @@ class _AppViewState extends State<_AppView> { htUserContentPreferencesRepository: widget.htUserContentPreferencesRepository, htAppConfigRepository: widget.htAppConfigRepository, - environment: widget.environment, // Pass environment ); // Removed Dynamic Link Initialization