feat:theme changing done

This commit is contained in:
jahongireshonqulov
2025-11-01 15:37:05 +05:00
parent 44878e79b3
commit b734fc9ce6
9 changed files with 142 additions and 45 deletions

View File

@@ -1,6 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application <application
android:allowBackup="false"
android:fullBackupContent="false"
android:label="food_delivery_client" android:label="food_delivery_client"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">

View File

@@ -3,6 +3,8 @@ abstract class AppLocaleKeys {
static const String language = 'language'; static const String language = 'language';
static const String browseSearchHistory = 'browse-search-history'; static const String browseSearchHistory = 'browse-search-history';
static const String token = 'token'; static const String token = 'token';
static const String theme = 'theme';
static const String appName = "Felix Eats"; static const String appName = "Felix Eats";

View File

@@ -40,6 +40,8 @@ import '../../feature/auth/presentation/blocs/verify_phone_bloc/verify_phone_blo
as _i224; as _i224;
import '../../feature/common/presentation/blocs/language_bloc/language_bloc.dart' import '../../feature/common/presentation/blocs/language_bloc/language_bloc.dart'
as _i942; as _i942;
import '../../feature/common/presentation/blocs/theme_bloc/theme_bloc.dart'
as _i465;
import '../../feature/main/presentation/blocs/main_bloc/main_bloc.dart' import '../../feature/main/presentation/blocs/main_bloc/main_bloc.dart'
as _i580; as _i580;
import '../../feature/onboarding/presentation/blocs/splash_bloc/splash_bloc.dart' import '../../feature/onboarding/presentation/blocs/splash_bloc/splash_bloc.dart'
@@ -68,6 +70,9 @@ extension GetItInjectableX on _i174.GetIt {
gh.factory<_i28.SplashBloc>( gh.factory<_i28.SplashBloc>(
() => _i28.SplashBloc(gh<_i321.StorageService>()), () => _i28.SplashBloc(gh<_i321.StorageService>()),
); );
gh.factory<_i465.ThemeBloc>(
() => _i465.ThemeBloc(gh<_i321.StorageService>()),
);
gh.lazySingleton<_i361.Dio>(() => dioModule.dio(gh<_i667.DioClient>())); gh.lazySingleton<_i361.Dio>(() => dioModule.dio(gh<_i667.DioClient>()));
gh.singleton<_i354.RequestHandlerService>( gh.singleton<_i354.RequestHandlerService>(
() => _i354.RequestHandlerService(gh<_i361.Dio>()), () => _i354.RequestHandlerService(gh<_i361.Dio>()),

View File

@@ -8,6 +8,10 @@ class StorageService {
_sharedPreference = await SharedPreferences.getInstance(); _sharedPreference = await SharedPreferences.getInstance();
} }
void setBool({required String key, required bool value}) {
_sharedPreference.setBool(key, value);
}
void setString({required String key, required String value}) { void setString({required String key, required String value}) {
_sharedPreference.setString(key, value); _sharedPreference.setString(key, value);
} }
@@ -25,6 +29,10 @@ class StorageService {
String? getString({required String key}) { String? getString({required String key}) {
return _sharedPreference.getString(key); return _sharedPreference.getString(key);
} }
bool getBool({required String key}) {
return _sharedPreference.getBool(key) ?? false;
}
} }
/* /*

View File

@@ -0,0 +1,37 @@
import 'package:food_delivery_client/food_delivery_client.dart';
part 'theme_event.dart';
part 'theme_state.dart';
part 'theme_bloc.freezed.dart';
@injectable
class ThemeBloc extends Bloc<ThemeEvent, ThemeState> {
final StorageService _storageService;
ThemeBloc(this._storageService) : super(const ThemeState()) {
on<_Started>(_onStarted);
on<_Changed>(_onChanged);
}
void _onStarted(_Started event, Emitter<ThemeState> emit) {
final isDark = _storageService.getBool(key: AppLocaleKeys.theme);
if (isDark) {
emit(state.copyWith(themeMode: ThemeMode.dark));
} else {
emit(state.copyWith(themeMode: ThemeMode.light));
}
}
void _onChanged(_Changed event, Emitter<ThemeState> emit) {
if (state.themeMode == ThemeMode.light) {
_storageService.setBool(key: AppLocaleKeys.theme, value: true);
emit(state.copyWith(themeMode: ThemeMode.dark));
} else {
_storageService.setBool(key: AppLocaleKeys.theme, value: false);
emit(state.copyWith(themeMode: ThemeMode.light));
}
}
}

View File

@@ -0,0 +1,8 @@
part of 'theme_bloc.dart';
@freezed
class ThemeEvent with _$ThemeEvent {
const factory ThemeEvent.started() = _Started;
const factory ThemeEvent.changed() = _Changed;
}

View File

@@ -0,0 +1,7 @@
part of 'theme_bloc.dart';
@freezed
abstract class ThemeState with _$ThemeState {
const factory ThemeState({@Default(ThemeMode.light) ThemeMode themeMode}) =
_ThemeState;
}

View File

@@ -1,21 +1,35 @@
import '../../../../../food_delivery_client.dart'; import '../../../../../food_delivery_client.dart';
import '../../../common/presentation/blocs/theme_bloc/theme_bloc.dart';
class ProfilePage extends StatelessWidget { class ProfilePage extends StatelessWidget {
const ProfilePage({super.key}); const ProfilePage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return BlocBuilder<ThemeBloc, ThemeState>(
body: Column( builder: (context, state) {
crossAxisAlignment: CrossAxisAlignment.center, return Scaffold(
mainAxisAlignment: MainAxisAlignment.center, body: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.center,
Text("Home"), mainAxisAlignment: MainAxisAlignment.center,
GradientSwitch(value:false, onChanged: (value) { children: [
print(value); Text("Home"),
}), Row(
], mainAxisAlignment: MainAxisAlignment.spaceBetween,
), children: [
Text("Dark mode"),
GradientSwitch(
value: state.themeMode == ThemeMode.dark,
onChanged: (value) {
context.read<ThemeBloc>().add(ThemeEvent.changed());
},
),
],
).paddingSymmetric(horizontal: 20),
],
),
);
},
); );
} }
} }

View File

@@ -1,5 +1,5 @@
import 'package:food_delivery_client/feature/common/presentation/blocs/theme_bloc/theme_bloc.dart';
import 'package:toastification/toastification.dart'; import 'package:toastification/toastification.dart';
import 'food_delivery_client.dart'; import 'food_delivery_client.dart';
void main() { void main() {
@@ -13,7 +13,13 @@ void main() {
Bloc.observer = AppBlocObserver(); Bloc.observer = AppBlocObserver();
await configureDependencies(); await configureDependencies();
runApp( runApp(
BlocProvider(create: (context) => sl<LanguageBloc>(), child: MyApp()), MultiBlocProvider(
providers: [
BlocProvider(create: (context) => sl<LanguageBloc>()),
BlocProvider(create: (context) => sl<ThemeBloc>()),
],
child: MyApp(),
),
); );
}, },
(error, stack) { (error, stack) {
@@ -32,46 +38,54 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State<MyApp> { class _MyAppState extends State<MyApp> {
@override @override
void initState() { void initState() {
SystemChrome.setPreferredOrientations([ WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
DeviceOrientation.portraitUp, SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitDown, DeviceOrientation.portraitUp,
]); DeviceOrientation.portraitDown,
]);
context.read<LanguageBloc>().add(LanguageEvent.started());
context.read<ThemeBloc>().add(ThemeEvent.started());
});
super.initState(); super.initState();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<LanguageBloc, LanguageState>( return BlocBuilder<LanguageBloc, LanguageState>(
bloc: context.read<LanguageBloc>()..add(LanguageEvent.started()),
builder: (context, state) { builder: (context, state) {
return ToastificationWrapper( return BlocBuilder<ThemeBloc, ThemeState>(
child: MaterialApp.router( builder: (context, themeState) {
title: AppLocaleKeys.appName, return ToastificationWrapper(
debugShowCheckedModeBanner: false, child: MaterialApp.router(
theme: AppTheme.lightTheme, title: AppLocaleKeys.appName,
darkTheme: AppTheme.darkTheme, debugShowCheckedModeBanner: false,
themeMode: ThemeMode.light, theme: AppTheme.lightTheme,
routerConfig: sl<AppRoutes>().router, darkTheme: AppTheme.darkTheme,
locale: state.currentLocale, themeMode: themeState.themeMode,
supportedLocales: L10n.locales, routerConfig: sl<AppRoutes>().router,
localizationsDelegates: [ locale: state.currentLocale,
AppLocalizations.delegate, supportedLocales: L10n.locales,
GlobalMaterialLocalizations.delegate, localizationsDelegates: [
GlobalWidgetsLocalizations.delegate, AppLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, GlobalMaterialLocalizations.delegate,
], GlobalWidgetsLocalizations.delegate,
builder: (context, child) => GestureDetector( GlobalCupertinoLocalizations.delegate,
onTap: () { ],
FocusManager.instance.primaryFocus?.unfocus(); builder: (context, child) => GestureDetector(
}, onTap: () {
child: MediaQuery( FocusManager.instance.primaryFocus?.unfocus();
data: MediaQuery.of( },
context, child: MediaQuery(
).copyWith(textScaler: const TextScaler.linear(1)), data: MediaQuery.of(
child: child!, context,
).copyWith(textScaler: const TextScaler.linear(1)),
child: child!,
),
),
), ),
), );
), },
); );
}, },
); );