Theme Mode #1

This commit is contained in:
2025-09-03 15:15:09 +05:30
parent 3e3465d5e8
commit d9f78629d2
6 changed files with 115 additions and 14 deletions

View File

@@ -2,6 +2,8 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.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:flutter_localizations/flutter_localizations.dart';
import './l10n/app_localizations.dart';
@@ -78,9 +80,37 @@ class _KMobileState extends State<KMobile> {
providers: [
BlocProvider<AuthCubit>(create: (_) => getIt<AuthCubit>()),
BlocProvider<ThemeCubit>(create: (_) => ThemeCubit()),
BlocProvider<ThemeModeCubit>(create: (_) => ThemeModeCubit()),
],
child: BlocBuilder<ThemeCubit, ThemeState>(
builder: (context, themeState) {
// 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>(
builder: (context, themeState) {
return BlocBuilder<ThemeModeCubit, ThemeModeState>(
builder: (context, modeState) {
return MaterialApp(
debugShowCheckedModeBanner: false,
locale: _locale ?? const Locale('en'),
@@ -96,14 +126,16 @@ class _KMobileState extends State<KMobile> {
],
title: 'kMobile',
theme: themeState.getThemeData(),
//darkTheme: themeState.getThemeData(),
themeMode: ThemeMode.light,
darkTheme: themeState.getThemeData(), // reuse same color in dark
themeMode: context.watch<ThemeModeCubit>().state.mode, // <<-- coming from ThemeModeCubit
onGenerateRoute: AppRoutes.generateRoute,
initialRoute: AppRoutes.splash,
home: showSplash ? const SplashScreen() : const AuthGate(),
);
},
),
);
},
),
);
}
}
@@ -336,7 +368,7 @@ class _NavigationScaffoldState extends State<NavigationScaffold> {
currentIndex: _selectedIndex,
type: BottomNavigationBarType.fixed,
backgroundColor: Theme.of(context)
.scaffoldBackgroundColor, // Light blue background
.scaffoldBackgroundColor,
selectedItemColor: Theme.of(context).primaryColor,
unselectedItemColor: Colors.black54,
onTap: (index) {

View File

@@ -8,6 +8,7 @@ import 'package:kmobile/api/services/payment_service.dart';
import 'package:kmobile/api/services/user_service.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_mode_cubit.dart';
import '../api/services/auth_service.dart';
import '../api/interceptors/auth_interceptor.dart';
import '../data/repositories/auth_repository.dart';
@@ -20,6 +21,7 @@ Future<void> setupDependencies() async {
//getIt.registerLazySingleton<ThemeController>(() => ThemeController());
//getIt.registerLazySingleton<ThemeModeController>(() => ThemeModeController());
getIt.registerSingleton<ThemeCubit>(ThemeCubit());
getIt.registerSingleton<ThemeModeCubit>(ThemeModeCubit());
// Register Dio client
getIt.registerSingleton<Dio>(_createDioClient());

View 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));
}
}

View 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];
}

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:kmobile/features/profile/preferences/theme_mode_dialog.dart';
import 'language_dialog.dart';
import 'color_theme_dialog.dart';
import '../../../l10n/app_localizations.dart';
@@ -29,7 +30,7 @@ class PreferenceScreen extends StatelessWidget {
showDialog(
context: context,
builder: (_) =>
const LanguageDialog(), // your custom language dialog
const LanguageDialog(),
);
},
),
@@ -37,12 +38,9 @@ class PreferenceScreen extends StatelessWidget {
ListTile(
leading: const Icon(Icons.brightness_6),
title: Text(AppLocalizations.of(context).themeMode),
//trailing: Switch(
// value: state.isDarkMode,
// onChanged: (val) {
// context.read<ThemeCubit>().toggleDarkMode(val);
// },
//),
onTap: () {
showThemeModeDialog(context);
},
),
//Color_Theme_Selection
ListTile(
@@ -53,7 +51,8 @@ class PreferenceScreen extends StatelessWidget {
context: context,
builder: (_) => const ColorThemeDialog(),
);
}),
}
),
],
);
},

View 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(),
),
);
},
);
}