Theme Mode #1
This commit is contained in:
38
lib/app.dart
38
lib/app.dart
@@ -2,6 +2,8 @@ import 'dart:io';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:kmobile/features/auth/controllers/theme_mode_cubit.dart';
|
||||||
|
import 'package:kmobile/features/auth/controllers/theme_mode_state.dart';
|
||||||
import 'package:kmobile/security/secure_storage.dart';
|
import 'package:kmobile/security/secure_storage.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import './l10n/app_localizations.dart';
|
import './l10n/app_localizations.dart';
|
||||||
@@ -78,9 +80,37 @@ class _KMobileState extends State<KMobile> {
|
|||||||
providers: [
|
providers: [
|
||||||
BlocProvider<AuthCubit>(create: (_) => getIt<AuthCubit>()),
|
BlocProvider<AuthCubit>(create: (_) => getIt<AuthCubit>()),
|
||||||
BlocProvider<ThemeCubit>(create: (_) => ThemeCubit()),
|
BlocProvider<ThemeCubit>(create: (_) => ThemeCubit()),
|
||||||
|
BlocProvider<ThemeModeCubit>(create: (_) => ThemeModeCubit()),
|
||||||
],
|
],
|
||||||
|
// child: BlocBuilder<ThemeCubit, ThemeState>(
|
||||||
|
// builder: (context, themeState) {
|
||||||
|
// return MaterialApp(
|
||||||
|
// debugShowCheckedModeBanner: false,
|
||||||
|
// locale: _locale ?? const Locale('en'),
|
||||||
|
// supportedLocales: const [
|
||||||
|
// Locale('en'),
|
||||||
|
// Locale('hi'),
|
||||||
|
// ],
|
||||||
|
// localizationsDelegates: const [
|
||||||
|
// AppLocalizations.delegate,
|
||||||
|
// GlobalMaterialLocalizations.delegate,
|
||||||
|
// GlobalWidgetsLocalizations.delegate,
|
||||||
|
// GlobalCupertinoLocalizations.delegate,
|
||||||
|
// ],
|
||||||
|
// title: 'kMobile',
|
||||||
|
// theme: themeState.getThemeData(),
|
||||||
|
// //darkTheme: themeState.getThemeData(),
|
||||||
|
// themeMode: ThemeMode.light,
|
||||||
|
// onGenerateRoute: AppRoutes.generateRoute,
|
||||||
|
// initialRoute: AppRoutes.splash,
|
||||||
|
// home: showSplash ? const SplashScreen() : const AuthGate(),
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
child: BlocBuilder<ThemeCubit, ThemeState>(
|
child: BlocBuilder<ThemeCubit, ThemeState>(
|
||||||
builder: (context, themeState) {
|
builder: (context, themeState) {
|
||||||
|
return BlocBuilder<ThemeModeCubit, ThemeModeState>(
|
||||||
|
builder: (context, modeState) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
locale: _locale ?? const Locale('en'),
|
locale: _locale ?? const Locale('en'),
|
||||||
@@ -96,13 +126,15 @@ class _KMobileState extends State<KMobile> {
|
|||||||
],
|
],
|
||||||
title: 'kMobile',
|
title: 'kMobile',
|
||||||
theme: themeState.getThemeData(),
|
theme: themeState.getThemeData(),
|
||||||
//darkTheme: themeState.getThemeData(),
|
darkTheme: themeState.getThemeData(), // reuse same color in dark
|
||||||
themeMode: ThemeMode.light,
|
themeMode: context.watch<ThemeModeCubit>().state.mode, // <<-- coming from ThemeModeCubit
|
||||||
onGenerateRoute: AppRoutes.generateRoute,
|
onGenerateRoute: AppRoutes.generateRoute,
|
||||||
initialRoute: AppRoutes.splash,
|
initialRoute: AppRoutes.splash,
|
||||||
home: showSplash ? const SplashScreen() : const AuthGate(),
|
home: showSplash ? const SplashScreen() : const AuthGate(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -336,7 +368,7 @@ class _NavigationScaffoldState extends State<NavigationScaffold> {
|
|||||||
currentIndex: _selectedIndex,
|
currentIndex: _selectedIndex,
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
backgroundColor: Theme.of(context)
|
backgroundColor: Theme.of(context)
|
||||||
.scaffoldBackgroundColor, // Light blue background
|
.scaffoldBackgroundColor,
|
||||||
selectedItemColor: Theme.of(context).primaryColor,
|
selectedItemColor: Theme.of(context).primaryColor,
|
||||||
unselectedItemColor: Colors.black54,
|
unselectedItemColor: Colors.black54,
|
||||||
onTap: (index) {
|
onTap: (index) {
|
||||||
|
@@ -8,6 +8,7 @@ import 'package:kmobile/api/services/payment_service.dart';
|
|||||||
import 'package:kmobile/api/services/user_service.dart';
|
import 'package:kmobile/api/services/user_service.dart';
|
||||||
import 'package:kmobile/data/repositories/transaction_repository.dart';
|
import 'package:kmobile/data/repositories/transaction_repository.dart';
|
||||||
import 'package:kmobile/features/auth/controllers/theme_cubit.dart';
|
import 'package:kmobile/features/auth/controllers/theme_cubit.dart';
|
||||||
|
import 'package:kmobile/features/auth/controllers/theme_mode_cubit.dart';
|
||||||
import '../api/services/auth_service.dart';
|
import '../api/services/auth_service.dart';
|
||||||
import '../api/interceptors/auth_interceptor.dart';
|
import '../api/interceptors/auth_interceptor.dart';
|
||||||
import '../data/repositories/auth_repository.dart';
|
import '../data/repositories/auth_repository.dart';
|
||||||
@@ -20,6 +21,7 @@ Future<void> setupDependencies() async {
|
|||||||
//getIt.registerLazySingleton<ThemeController>(() => ThemeController());
|
//getIt.registerLazySingleton<ThemeController>(() => ThemeController());
|
||||||
//getIt.registerLazySingleton<ThemeModeController>(() => ThemeModeController());
|
//getIt.registerLazySingleton<ThemeModeController>(() => ThemeModeController());
|
||||||
getIt.registerSingleton<ThemeCubit>(ThemeCubit());
|
getIt.registerSingleton<ThemeCubit>(ThemeCubit());
|
||||||
|
getIt.registerSingleton<ThemeModeCubit>(ThemeModeCubit());
|
||||||
|
|
||||||
// Register Dio client
|
// Register Dio client
|
||||||
getIt.registerSingleton<Dio>(_createDioClient());
|
getIt.registerSingleton<Dio>(_createDioClient());
|
||||||
|
24
lib/features/auth/controllers/theme_mode_cubit.dart
Normal file
24
lib/features/auth/controllers/theme_mode_cubit.dart
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'theme_mode_state.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class ThemeModeCubit extends Cubit<ThemeModeState> {
|
||||||
|
ThemeModeCubit() : super(const ThemeModeState(mode: ThemeMode.system)) {
|
||||||
|
loadThemeMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loadThemeMode() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
final modeIndex = prefs.getInt('theme_mode') ?? 2; // default system
|
||||||
|
final mode = ThemeMode.values[modeIndex];
|
||||||
|
emit(ThemeModeState(mode: mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> changeThemeMode(ThemeMode mode) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setInt('theme_mode', mode.index);
|
||||||
|
emit(ThemeModeState(mode: mode));
|
||||||
|
}
|
||||||
|
}
|
11
lib/features/auth/controllers/theme_mode_state.dart
Normal file
11
lib/features/auth/controllers/theme_mode_state.dart
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ThemeModeState extends Equatable {
|
||||||
|
final ThemeMode mode;
|
||||||
|
|
||||||
|
const ThemeModeState({required this.mode});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [mode];
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:kmobile/features/profile/preferences/theme_mode_dialog.dart';
|
||||||
import 'language_dialog.dart';
|
import 'language_dialog.dart';
|
||||||
import 'color_theme_dialog.dart';
|
import 'color_theme_dialog.dart';
|
||||||
import '../../../l10n/app_localizations.dart';
|
import '../../../l10n/app_localizations.dart';
|
||||||
@@ -29,7 +30,7 @@ class PreferenceScreen extends StatelessWidget {
|
|||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) =>
|
builder: (_) =>
|
||||||
const LanguageDialog(), // your custom language dialog
|
const LanguageDialog(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -37,12 +38,9 @@ class PreferenceScreen extends StatelessWidget {
|
|||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.brightness_6),
|
leading: const Icon(Icons.brightness_6),
|
||||||
title: Text(AppLocalizations.of(context).themeMode),
|
title: Text(AppLocalizations.of(context).themeMode),
|
||||||
//trailing: Switch(
|
onTap: () {
|
||||||
// value: state.isDarkMode,
|
showThemeModeDialog(context);
|
||||||
// onChanged: (val) {
|
},
|
||||||
// context.read<ThemeCubit>().toggleDarkMode(val);
|
|
||||||
// },
|
|
||||||
//),
|
|
||||||
),
|
),
|
||||||
//Color_Theme_Selection
|
//Color_Theme_Selection
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -53,7 +51,8 @@ class PreferenceScreen extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (_) => const ColorThemeDialog(),
|
builder: (_) => const ColorThemeDialog(),
|
||||||
);
|
);
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
33
lib/features/profile/preferences/theme_mode_dialog.dart
Normal file
33
lib/features/profile/preferences/theme_mode_dialog.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:kmobile/features/auth/controllers/theme_mode_cubit.dart';
|
||||||
|
|
||||||
|
Future<void> showThemeModeDialog(BuildContext context) async {
|
||||||
|
final cubit = context.read<ThemeModeCubit>();
|
||||||
|
final currentMode = context.read<ThemeModeCubit>().state.mode;
|
||||||
|
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text("Select Theme Mode"),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: ThemeMode.values.map((mode) {
|
||||||
|
return RadioListTile<ThemeMode>(
|
||||||
|
title: Text(mode.toString().split('.').last.toUpperCase()),
|
||||||
|
value: mode,
|
||||||
|
groupValue: currentMode,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
cubit.changeThemeMode(value);
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
Reference in New Issue
Block a user