refactor(theme&ui): improve theme switching and navigation styling
This commit is contained in:
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:sfm_app/product/base/bloc/base_bloc.dart';
|
import 'package:sfm_app/product/base/bloc/base_bloc.dart';
|
||||||
|
import 'package:sfm_app/product/constant/enums/app_theme_enums.dart';
|
||||||
|
|
||||||
import '../bell/bell_model.dart';
|
import '../bell/bell_model.dart';
|
||||||
|
|
||||||
@@ -15,6 +16,10 @@ class MainBloc extends BlocBase {
|
|||||||
StreamSink<Locale?> get sinkLanguage => language.sink;
|
StreamSink<Locale?> get sinkLanguage => language.sink;
|
||||||
Stream<Locale?> get streamLanguage => language.stream;
|
Stream<Locale?> get streamLanguage => language.stream;
|
||||||
|
|
||||||
|
final theme = StreamController<ThemeData?>.broadcast();
|
||||||
|
StreamSink<ThemeData?> get sinkTheme => theme.sink;
|
||||||
|
Stream<ThemeData?> get streamTheme => theme.stream;
|
||||||
|
|
||||||
final themeMode = StreamController<bool>.broadcast();
|
final themeMode = StreamController<bool>.broadcast();
|
||||||
StreamSink<bool> get sinkThemeMode => themeMode.sink;
|
StreamSink<bool> get sinkThemeMode => themeMode.sink;
|
||||||
Stream<bool> get streamThemeMode => themeMode.stream;
|
Stream<bool> get streamThemeMode => themeMode.stream;
|
||||||
|
|||||||
@@ -6,15 +6,12 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:persistent_bottom_nav_bar_v2/persistent-tab-view.dart';
|
import 'package:persistent_bottom_nav_bar_v2/persistent-tab-view.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:badges/badges.dart' as badges;
|
import 'package:badges/badges.dart' as badges;
|
||||||
import 'package:sfm_app/feature/home/home_bloc.dart';
|
import '../home/home_bloc.dart';
|
||||||
import 'package:sfm_app/product/constant/app/app_constants.dart';
|
import '../../product/constant/app/app_constants.dart';
|
||||||
import 'package:sfm_app/product/constant/enums/app_route_enums.dart';
|
import '../../product/constant/enums/app_route_enums.dart';
|
||||||
import 'package:sfm_app/product/constant/enums/role_enums.dart';
|
import '../../product/permission/location_permission.dart';
|
||||||
import 'package:sfm_app/product/permission/location_permission.dart';
|
import '../../product/services/theme_services.dart';
|
||||||
import 'package:sfm_app/product/shared/shared_language_switch.dart';
|
|
||||||
import '../../product/shared/shared_light_dark_switch.dart';
|
|
||||||
import '../devices/devices_manager_bloc.dart';
|
import '../devices/devices_manager_bloc.dart';
|
||||||
import '../devices/devices_manager_screen.dart';
|
import '../devices/devices_manager_screen.dart';
|
||||||
import '../home/home_screen.dart';
|
import '../home/home_screen.dart';
|
||||||
@@ -27,13 +24,11 @@ import '../map/map_bloc.dart';
|
|||||||
import '../map/map_screen.dart';
|
import '../map/map_screen.dart';
|
||||||
import '../../product/base/bloc/base_bloc.dart';
|
import '../../product/base/bloc/base_bloc.dart';
|
||||||
import '../../product/constant/enums/app_theme_enums.dart';
|
import '../../product/constant/enums/app_theme_enums.dart';
|
||||||
import '../../product/extention/context_extention.dart';
|
|
||||||
import '../../product/services/api_services.dart';
|
import '../../product/services/api_services.dart';
|
||||||
import '../../main.dart';
|
import '../../main.dart';
|
||||||
import '../../product/constant/icon/icon_constants.dart';
|
import '../../product/constant/icon/icon_constants.dart';
|
||||||
import '../../product/constant/lang/language_constants.dart';
|
import '../../product/constant/lang/language_constants.dart';
|
||||||
import '../../product/services/language_services.dart';
|
import '../../product/services/language_services.dart';
|
||||||
import '../../product/theme/theme_notifier.dart';
|
|
||||||
import '../bell/bell_model.dart';
|
import '../bell/bell_model.dart';
|
||||||
|
|
||||||
class MainScreen extends StatefulWidget {
|
class MainScreen extends StatefulWidget {
|
||||||
@@ -69,16 +64,12 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
mainBloc.sinkIsVNIcon.add(isVN);
|
mainBloc.sinkIsVNIcon.add(isVN);
|
||||||
mainBloc.sinkThemeMode.add(isLight);
|
mainBloc.sinkThemeMode.add(isLight);
|
||||||
log("role: $role");
|
|
||||||
LocationPermissionRequest.instance.checkLocationPermission(context);
|
LocationPermissionRequest.instance.checkLocationPermission(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For test
|
|
||||||
late bool dayNightToggle2;
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
dayNightToggle2 = false;
|
|
||||||
mainBloc = BlocProvider.of(context);
|
mainBloc = BlocProvider.of(context);
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
initialCheck();
|
initialCheck();
|
||||||
@@ -178,216 +169,199 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
ThemeNotifier themeNotifier = context.watch<ThemeNotifier>();
|
return StreamBuilder<bool>(
|
||||||
return Scaffold(
|
stream: mainBloc.streamThemeMode,
|
||||||
appBar: AppBar(
|
initialData: isLight,
|
||||||
backgroundColor: Colors.transparent,
|
builder: (context, themeModeSnapshot) {
|
||||||
actions: [
|
return Scaffold(
|
||||||
// LightDarkSwitch(
|
appBar: AppBar(
|
||||||
// value: !isLight,
|
backgroundColor: Colors.transparent,
|
||||||
// onChanged: (value) {
|
actions: [
|
||||||
// themeNotifier.changeTheme();
|
// LightDarkSwitch(
|
||||||
// isLight = !isLight;
|
// value: !isLight,
|
||||||
// },
|
// onChanged: (value) {
|
||||||
// ),
|
// themeNotifier.changeTheme();
|
||||||
// SizedBox(
|
// isLight = !isLight;
|
||||||
// width: context.lowValue,
|
// },
|
||||||
// ),
|
// ),
|
||||||
// StreamBuilder<bool>(
|
// SizedBox(
|
||||||
// stream: mainBloc.streamIsVNIcon,
|
// width: context.lowValue,
|
||||||
// builder: (context, isVNSnapshot) {
|
// ),
|
||||||
// return LanguageSwitch(
|
// StreamBuilder<bool>(
|
||||||
// value: isVNSnapshot.data ?? isVN,
|
// stream: mainBloc.streamIsVNIcon,
|
||||||
// onChanged: (value) async {
|
// builder: (context, isVNSnapshot) {
|
||||||
// Locale locale = await LanguageServices().setLocale(isVN
|
// return LanguageSwitch(
|
||||||
// ? LanguageConstants.ENGLISH
|
// value: isVNSnapshot.data ?? isVN,
|
||||||
// : LanguageConstants.VIETNAM);
|
// onChanged: (value) async {
|
||||||
// MyApp.setLocale(context, locale);
|
// Locale locale = await LanguageServices().setLocale(isVN
|
||||||
// isVN = !isVN;
|
// ? LanguageConstants.ENGLISH
|
||||||
// mainBloc.sinkIsVNIcon.add(isVN);
|
// : LanguageConstants.VIETNAM);
|
||||||
// },
|
// MyApp.setLocale(context, locale);
|
||||||
// );
|
// isVN = !isVN;
|
||||||
// }),
|
// mainBloc.sinkIsVNIcon.add(isVN);
|
||||||
// SizedBox(
|
// },
|
||||||
// width: context.lowValue,
|
// );
|
||||||
// ),
|
// }),
|
||||||
StreamBuilder<bool>(
|
// SizedBox(
|
||||||
stream: mainBloc.streamThemeMode,
|
// width: context.lowValue,
|
||||||
initialData: isLight,
|
// ),
|
||||||
builder: (context, themeModeSnapshot) {
|
IconButton(
|
||||||
return IconButton(
|
onPressed: () async {
|
||||||
onPressed: () {
|
ThemeData newTheme = await ThemeServices().changeTheme(
|
||||||
themeNotifier.changeTheme();
|
isLight ? AppThemes.DARK.name : AppThemes.LIGHT.name);
|
||||||
|
MyApp.setTheme(context, newTheme);
|
||||||
isLight = !isLight;
|
isLight = !isLight;
|
||||||
mainBloc.sinkThemeMode.add(isLight);
|
mainBloc.sinkThemeMode.add(isLight);
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
themeModeSnapshot.data ?? isLight
|
themeModeSnapshot.data ?? isLight
|
||||||
? Icons.light_mode_outlined
|
? Icons.dark_mode_outlined
|
||||||
: Icons.dark_mode_outlined,
|
: Icons.light_mode_outlined,
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
StreamBuilder<bool>(
|
||||||
),
|
stream: mainBloc.streamIsVNIcon,
|
||||||
StreamBuilder<bool>(
|
initialData: isVN,
|
||||||
stream: mainBloc.streamIsVNIcon,
|
builder: (context, isVnSnapshot) {
|
||||||
initialData: isVN,
|
return IconButton(
|
||||||
builder: (context, isVnSnapshot) {
|
onPressed: () async {
|
||||||
return IconButton(
|
log("Locale: ${LanguageServices().getLocale()}");
|
||||||
onPressed: () async {
|
Locale locale = await LanguageServices().setLocale(isVN
|
||||||
log("Locale: ${LanguageServices().getLocale()}");
|
? LanguageConstants.ENGLISH
|
||||||
Locale locale = await LanguageServices().setLocale(isVN
|
: LanguageConstants.VIETNAM);
|
||||||
? LanguageConstants.ENGLISH
|
MyApp.setLocale(context, locale);
|
||||||
: LanguageConstants.VIETNAM);
|
isVN = !isVN;
|
||||||
MyApp.setLocale(context, locale);
|
mainBloc.sinkIsVNIcon.add(isVN);
|
||||||
isVN = !isVN;
|
},
|
||||||
mainBloc.sinkIsVNIcon.add(isVN);
|
icon: Image.asset(
|
||||||
|
IconConstants.instance.getIcon(
|
||||||
|
isVnSnapshot.data ?? isVN ? 'vi_icon' : 'en_icon'),
|
||||||
|
height: 24,
|
||||||
|
width: 24,
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
icon: Image.asset(
|
),
|
||||||
IconConstants.instance.getIcon(
|
StreamBuilder<Bell>(
|
||||||
isVnSnapshot.data ?? isVN ? 'vi_icon' : 'en_icon'),
|
stream: mainBloc.streamBellBloc,
|
||||||
height: 24,
|
builder: (context, bellSnapshot) {
|
||||||
width: 24,
|
return checkStatus(bellSnapshot.data?.items ?? [])
|
||||||
|
? IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
context.pushNamed(AppRoutes.BELL.name);
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.notifications,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: GestureDetector(
|
||||||
|
child: badges.Badge(
|
||||||
|
badgeStyle: const badges.BadgeStyle(
|
||||||
|
shape: badges.BadgeShape.twitter,
|
||||||
|
),
|
||||||
|
key: _badgeKey,
|
||||||
|
badgeContent: const Icon(
|
||||||
|
CupertinoIcons.circle_filled,
|
||||||
|
color: Colors.red,
|
||||||
|
size: 5,
|
||||||
|
),
|
||||||
|
badgeAnimation: const badges.BadgeAnimation.slide(
|
||||||
|
animationDuration: Duration(milliseconds: 200),
|
||||||
|
colorChangeAnimationDuration:
|
||||||
|
Duration(seconds: 1),
|
||||||
|
loopAnimation: false,
|
||||||
|
curve: Curves.decelerate,
|
||||||
|
colorChangeAnimationCurve: Curves.easeInCirc,
|
||||||
|
),
|
||||||
|
showBadge: true,
|
||||||
|
// ignorePointer: false,
|
||||||
|
child: const Icon(
|
||||||
|
Icons.notifications,
|
||||||
|
size: 30,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed(AppRoutes.BELL.name);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
PopupMenuButton(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
),
|
),
|
||||||
);
|
icon: const Icon(Icons.more_vert),
|
||||||
},
|
itemBuilder: (context) {
|
||||||
),
|
return [
|
||||||
StreamBuilder<Bell>(
|
PopupMenuItem(
|
||||||
stream: mainBloc.streamBellBloc,
|
value: ApplicationConstants.SETTINGS_PATH,
|
||||||
builder: (context, bellSnapshot) {
|
|
||||||
return checkStatus(bellSnapshot.data?.items ?? [])
|
|
||||||
? IconButton(
|
|
||||||
onPressed: () {
|
|
||||||
context.pushNamed(AppRoutes.BELL.name);
|
|
||||||
},
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.notifications,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: GestureDetector(
|
|
||||||
child: badges.Badge(
|
|
||||||
badgeStyle: const badges.BadgeStyle(
|
|
||||||
shape: badges.BadgeShape.twitter,
|
|
||||||
),
|
|
||||||
key: _badgeKey,
|
|
||||||
badgeContent: const Icon(
|
|
||||||
CupertinoIcons.circle_filled,
|
|
||||||
color: Colors.red,
|
|
||||||
size: 5,
|
|
||||||
),
|
|
||||||
badgeAnimation: const badges.BadgeAnimation.slide(
|
|
||||||
animationDuration: Duration(milliseconds: 200),
|
|
||||||
colorChangeAnimationDuration: Duration(seconds: 1),
|
|
||||||
loopAnimation: false,
|
|
||||||
curve: Curves.decelerate,
|
|
||||||
colorChangeAnimationCurve: Curves.easeInCirc,
|
|
||||||
),
|
|
||||||
showBadge: true,
|
|
||||||
// ignorePointer: false,
|
|
||||||
child: const Icon(
|
|
||||||
Icons.notifications,
|
|
||||||
size: 30,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.pushNamed(AppRoutes.BELL.name);
|
context.pushNamed(AppRoutes.SETTINGS.name);
|
||||||
},
|
},
|
||||||
);
|
child: Row(
|
||||||
},
|
children: [
|
||||||
),
|
const Icon(Icons.person),
|
||||||
PopupMenuButton(
|
const SizedBox(width: 5),
|
||||||
shape: RoundedRectangleBorder(
|
Text(appLocalization(context).profile_icon_title)
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
],
|
||||||
),
|
|
||||||
icon: const Icon(Icons.more_vert),
|
|
||||||
itemBuilder: (context) {
|
|
||||||
return [
|
|
||||||
PopupMenuItem(
|
|
||||||
value: ApplicationConstants.SETTINGS_PATH,
|
|
||||||
onTap: () {
|
|
||||||
context.pushNamed(AppRoutes.SETTINGS.name);
|
|
||||||
},
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.person),
|
|
||||||
const SizedBox(width: 5),
|
|
||||||
Text(appLocalization(context).profile_icon_title)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: ApplicationConstants.LOGOUT_PATH,
|
|
||||||
onTap: () {
|
|
||||||
Future.delayed(
|
|
||||||
const Duration(milliseconds: 200),
|
|
||||||
() async {
|
|
||||||
await apiServices.logOut(context);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.logout),
|
|
||||||
const SizedBox(width: 5),
|
|
||||||
Text(
|
|
||||||
appLocalization(context).log_out,
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
PopupMenuItem(
|
||||||
),
|
value: ApplicationConstants.LOGOUT_PATH,
|
||||||
];
|
onTap: () {
|
||||||
},
|
Future.delayed(
|
||||||
)
|
const Duration(milliseconds: 200),
|
||||||
],
|
() async {
|
||||||
),
|
await apiServices.logOut(context);
|
||||||
// bottomNavigationBar: Container(
|
},
|
||||||
// decoration:
|
);
|
||||||
// BoxDecoration(borderRadius: BorderRadius.circular(50)),
|
},
|
||||||
// padding: context.paddingLow,
|
child: Row(
|
||||||
// child: NavigationBar(
|
children: [
|
||||||
// onDestinationSelected: (index) {
|
const Icon(Icons.logout),
|
||||||
// currentPageIndex = index;
|
const SizedBox(width: 5),
|
||||||
// mainBloc.sinkCurrentPageIndex.add(currentPageIndex);
|
Text(
|
||||||
// checkSelectedIndex(currentPageIndex);
|
appLocalization(context).log_out,
|
||||||
// },
|
),
|
||||||
// selectedIndex: indexSnapshot.data ?? currentPageIndex,
|
],
|
||||||
// destinations: roleSnapshot.data == RoleEnums.USER.name
|
),
|
||||||
// ? userDestinations
|
),
|
||||||
// : modDestinations,
|
];
|
||||||
// ),
|
},
|
||||||
// ),
|
)
|
||||||
// body: IndexedStack(
|
],
|
||||||
// index: indexSnapshot.data ?? currentPageIndex,
|
),
|
||||||
// children: roleSnapshot.data == RoleEnums.USER.name
|
body: PersistentTabView(
|
||||||
// ? userBody
|
context,
|
||||||
// : modBody,
|
controller: controller,
|
||||||
// ),
|
screens: _buildScreens(),
|
||||||
body: PersistentTabView(
|
items: _navBarsItems(),
|
||||||
context,
|
confineInSafeArea: true,
|
||||||
controller: controller,
|
handleAndroidBackButtonPress: true,
|
||||||
screens: _buildScreens(),
|
resizeToAvoidBottomInset: true,
|
||||||
items: _navBarsItems(),
|
stateManagement: true,
|
||||||
confineInSafeArea: true,
|
hideNavigationBarWhenKeyboardShows: true,
|
||||||
handleAndroidBackButtonPress: true,
|
backgroundColor:
|
||||||
resizeToAvoidBottomInset: true,
|
themeModeSnapshot.data! ? Colors.white : Colors.black,
|
||||||
stateManagement: true,
|
decoration: NavBarDecoration(
|
||||||
hideNavigationBarWhenKeyboardShows: true,
|
borderRadius: BorderRadius.circular(30.0),
|
||||||
// backgroundColor: Colors.transparent,
|
colorBehindNavBar:
|
||||||
decoration: NavBarDecoration(
|
themeModeSnapshot.data! ? Colors.white : Colors.black,
|
||||||
borderRadius: BorderRadius.circular(30.0),
|
),
|
||||||
),
|
popAllScreensOnTapOfSelectedTab: true,
|
||||||
popAllScreensOnTapOfSelectedTab: true,
|
itemAnimationProperties: const ItemAnimationProperties(
|
||||||
itemAnimationProperties: const ItemAnimationProperties(
|
duration: Duration(milliseconds: 200),
|
||||||
duration: Duration(milliseconds: 200),
|
curve: Curves.bounceInOut,
|
||||||
curve: Curves.bounceInOut,
|
),
|
||||||
),
|
screenTransitionAnimation: const ScreenTransitionAnimation(
|
||||||
screenTransitionAnimation: const ScreenTransitionAnimation(
|
animateTabTransition: true,
|
||||||
animateTabTransition: true,
|
curve: Curves.linear,
|
||||||
curve: Curves.linear,
|
duration: Duration(milliseconds: 200),
|
||||||
duration: Duration(milliseconds: 200),
|
),
|
||||||
),
|
navBarStyle: NavBarStyle.style4,
|
||||||
navBarStyle: NavBarStyle.style4,
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,19 @@
|
|||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:sfm_app/product/services/theme_services.dart';
|
||||||
import 'product/services/language_services.dart';
|
import 'product/services/language_services.dart';
|
||||||
import 'feature/main/main_bloc.dart';
|
import 'feature/main/main_bloc.dart';
|
||||||
import 'product/base/bloc/base_bloc.dart';
|
import 'product/base/bloc/base_bloc.dart';
|
||||||
import 'product/constant/navigation/navigation_router.dart';
|
import 'product/constant/navigation/navigation_router.dart';
|
||||||
import 'product/theme/provider/app_provider.dart';
|
|
||||||
import 'product/theme/theme_notifier.dart';
|
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await Firebase.initializeApp();
|
await Firebase.initializeApp();
|
||||||
runApp(
|
runApp(
|
||||||
MultiProvider(
|
BlocProvider(
|
||||||
providers: [...ApplicationProvider.instance.dependItems],
|
child: const MyApp(),
|
||||||
child: BlocProvider(
|
blocBuilder: () => MainBloc(),
|
||||||
child: const MyApp(),
|
|
||||||
blocBuilder: () => MainBloc(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -32,17 +27,30 @@ class MyApp extends StatefulWidget {
|
|||||||
_MyAppState? state = context.findAncestorStateOfType<_MyAppState>();
|
_MyAppState? state = context.findAncestorStateOfType<_MyAppState>();
|
||||||
state?.setLocale(newLocale);
|
state?.setLocale(newLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setTheme(BuildContext context, ThemeData newTheme) {
|
||||||
|
_MyAppState? state = context.findAncestorStateOfType<_MyAppState>();
|
||||||
|
state?.setTheme(newTheme);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyAppState extends State<MyApp> {
|
class _MyAppState extends State<MyApp> {
|
||||||
Locale? _locale;
|
Locale? _locale;
|
||||||
|
ThemeData? _themeData;
|
||||||
late MainBloc mainBloc;
|
late MainBloc mainBloc;
|
||||||
LanguageServices languageServices = LanguageServices();
|
LanguageServices languageServices = LanguageServices();
|
||||||
|
ThemeServices themeServices = ThemeServices();
|
||||||
|
|
||||||
setLocale(Locale locale) {
|
setLocale(Locale locale) {
|
||||||
_locale = locale;
|
_locale = locale;
|
||||||
mainBloc.sinkLanguage.add(_locale);
|
mainBloc.sinkLanguage.add(_locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTheme(ThemeData theme) {
|
||||||
|
_themeData = theme;
|
||||||
|
mainBloc.sinkTheme.add(_themeData);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -52,6 +60,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
languageServices.getLocale().then((locale) => {setLocale(locale)});
|
languageServices.getLocale().then((locale) => {setLocale(locale)});
|
||||||
|
themeServices.getTheme().then((theme) => {setTheme(theme)});
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,12 +71,18 @@ class _MyAppState extends State<MyApp> {
|
|||||||
stream: mainBloc.streamLanguage,
|
stream: mainBloc.streamLanguage,
|
||||||
initialData: _locale,
|
initialData: _locale,
|
||||||
builder: (context, languageSnapshot) {
|
builder: (context, languageSnapshot) {
|
||||||
return MaterialApp.router(
|
return StreamBuilder<ThemeData?>(
|
||||||
theme: context.watch<ThemeNotifier>().currentTheme,
|
stream: mainBloc.streamTheme,
|
||||||
routerConfig: router,
|
initialData: _themeData,
|
||||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
builder: (context, themeSnapshot) {
|
||||||
supportedLocales: AppLocalizations.supportedLocales,
|
return MaterialApp.router(
|
||||||
locale: languageSnapshot.data,
|
theme: themeSnapshot.data,
|
||||||
|
routerConfig: router,
|
||||||
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
|
supportedLocales: AppLocalizations.supportedLocales,
|
||||||
|
locale: languageSnapshot.data,
|
||||||
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
33
lib/product/services/theme_services.dart
Normal file
33
lib/product/services/theme_services.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../cache/local_manager.dart';
|
||||||
|
import '../constant/enums/app_theme_enums.dart';
|
||||||
|
import '../constant/enums/local_keys_enums.dart';
|
||||||
|
import '../theme/app_theme_dark.dart';
|
||||||
|
import '../theme/app_theme_light.dart';
|
||||||
|
|
||||||
|
class ThemeServices{
|
||||||
|
|
||||||
|
ThemeData _currentTheme(String theme) {
|
||||||
|
if (theme == AppThemes.LIGHT.name) {
|
||||||
|
return AppThemeLight.instance.theme;
|
||||||
|
} else if (theme == AppThemes.DARK.name) {
|
||||||
|
return AppThemeDark.instance.theme;
|
||||||
|
} else {
|
||||||
|
return AppThemeLight.instance.theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ThemeData> getTheme() async {
|
||||||
|
await LocaleManager.prefrencesInit();
|
||||||
|
String theme = LocaleManager.instance.getStringValue(PreferencesKeys.THEME);
|
||||||
|
return _currentTheme(theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ThemeData> changeTheme(String theme) async {
|
||||||
|
await LocaleManager.prefrencesInit();
|
||||||
|
LocaleManager.instance
|
||||||
|
.setStringValue(PreferencesKeys.THEME, theme);
|
||||||
|
return _currentTheme(theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:provider/single_child_widget.dart';
|
|
||||||
|
|
||||||
import '../theme_notifier.dart';
|
|
||||||
|
|
||||||
class ApplicationProvider {
|
|
||||||
static ApplicationProvider? _instance;
|
|
||||||
static ApplicationProvider get instance {
|
|
||||||
_instance ??= ApplicationProvider._init();
|
|
||||||
return _instance!;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplicationProvider._init();
|
|
||||||
|
|
||||||
List<SingleChildWidget> singleItems = [];
|
|
||||||
List<SingleChildWidget> dependItems = [
|
|
||||||
ChangeNotifierProvider(
|
|
||||||
create: (context) => ThemeNotifier(),
|
|
||||||
),
|
|
||||||
// Provider.value(value: NavigationService.instance)
|
|
||||||
];
|
|
||||||
List<SingleChildWidget> uiChangesItems = [];
|
|
||||||
}
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'app_theme_dark.dart';
|
|
||||||
import 'app_theme_light.dart';
|
|
||||||
|
|
||||||
import '../constant/enums/app_theme_enums.dart';
|
|
||||||
|
|
||||||
class ThemeNotifier extends ChangeNotifier {
|
|
||||||
// ThemeData _currentTheme = AppThemeLight.instance.theme;
|
|
||||||
// // ThemeData get currentTheme => LocaleManager.instance.getStringValue(PreferencesKeys.THEME) ==
|
|
||||||
// // AppThemes.LIGHT.name
|
|
||||||
// // ? AppThemeLight.instance.theme
|
|
||||||
// // : AppThemeDark.instance.theme;
|
|
||||||
// ThemeData get currentTheme {
|
|
||||||
// log("ThemeKey: ${LocaleManager.instance.getStringValue(PreferencesKeys.THEME)}");
|
|
||||||
// if (LocaleManager.instance.getStringValue(PreferencesKeys.THEME) ==
|
|
||||||
// AppThemes.LIGHT.name) {
|
|
||||||
// log("light");
|
|
||||||
// } else {
|
|
||||||
// log("dark");
|
|
||||||
// }
|
|
||||||
// return LocaleManager.instance.getStringValue(PreferencesKeys.THEME) ==
|
|
||||||
// AppThemes.LIGHT.name
|
|
||||||
// ? AppThemeLight.instance.theme
|
|
||||||
// : AppThemeDark.instance.theme;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ThemeData _currentTheme = AppThemeLight.instance.theme; // Mặc định là light
|
|
||||||
|
|
||||||
// ThemeNotifier() {
|
|
||||||
// loadThemeFromPreferences();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Future<void> loadThemeFromPreferences() async {
|
|
||||||
// String themeKey =
|
|
||||||
// LocaleManager.instance.getStringValue(PreferencesKeys.THEME);
|
|
||||||
// log("ThemeNotifierKey:$themeKey ");
|
|
||||||
// if (themeKey == AppThemes.LIGHT.name) {
|
|
||||||
// _currentTheme = AppThemeLight.instance.theme;
|
|
||||||
// } else {
|
|
||||||
// _currentTheme = AppThemeDark.instance.theme;
|
|
||||||
// }
|
|
||||||
// notifyListeners(); // Thông báo cho các widget lắng nghe
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ThemeData get currentTheme => _currentTheme;
|
|
||||||
|
|
||||||
// AppThemes _currenThemeEnum = AppThemes.LIGHT;
|
|
||||||
// AppThemes get currenThemeEnum =>
|
|
||||||
// LocaleManager.instance.getStringValue(PreferencesKeys.THEME) ==
|
|
||||||
// AppThemes.LIGHT.name
|
|
||||||
// ? AppThemes.LIGHT
|
|
||||||
// : AppThemes.DARK;
|
|
||||||
// // AppThemes get currenThemeEnum => _currenThemeEnum;
|
|
||||||
|
|
||||||
// void changeValue(AppThemes theme) {
|
|
||||||
// if (theme == AppThemes.LIGHT) {
|
|
||||||
// _currentTheme = ThemeData.dark();
|
|
||||||
// } else {
|
|
||||||
// _currentTheme = ThemeData.light();
|
|
||||||
// }
|
|
||||||
// notifyListeners();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void changeTheme() {
|
|
||||||
// if (_currenThemeEnum == AppThemes.LIGHT) {
|
|
||||||
// _currentTheme = AppThemeDark.instance.theme;
|
|
||||||
// _currenThemeEnum = AppThemes.DARK;
|
|
||||||
// LocaleManager.instance
|
|
||||||
// .setString(PreferencesKeys.THEME, AppThemes.DARK.name);
|
|
||||||
// } else {
|
|
||||||
// _currentTheme = AppThemeLight.instance.theme;
|
|
||||||
// _currenThemeEnum = AppThemes.LIGHT;
|
|
||||||
// LocaleManager.instance
|
|
||||||
// .setString(PreferencesKeys.THEME, AppThemes.LIGHT.name);
|
|
||||||
// }
|
|
||||||
// notifyListeners();
|
|
||||||
// }
|
|
||||||
|
|
||||||
ThemeData _currentTheme = AppThemeLight.instance.theme;
|
|
||||||
ThemeData get currentTheme => _currentTheme;
|
|
||||||
|
|
||||||
AppThemes _currenThemeEnum = AppThemes.LIGHT;
|
|
||||||
AppThemes get currenThemeEnum => _currenThemeEnum;
|
|
||||||
|
|
||||||
Future<void> loadThemeFromPreferences() async {
|
|
||||||
// String themeKey =
|
|
||||||
// LocaleManager.instance.getStringValue(PreferencesKeys.THEME);
|
|
||||||
// if (themeKey == AppThemes.LIGHT.name) {
|
|
||||||
// _currentTheme = AppThemeLight.instance.theme;
|
|
||||||
// } else {
|
|
||||||
// _currentTheme = AppThemeDark.instance.theme;
|
|
||||||
// }
|
|
||||||
// notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeValue(AppThemes theme) {
|
|
||||||
if (theme == AppThemes.LIGHT) {
|
|
||||||
_currentTheme = AppThemeLight.instance.theme;
|
|
||||||
} else {
|
|
||||||
_currentTheme = AppThemeDark.instance.theme;
|
|
||||||
}
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeTheme() {
|
|
||||||
if (_currenThemeEnum == AppThemes.LIGHT) {
|
|
||||||
_currentTheme = AppThemeDark.instance.theme;
|
|
||||||
_currenThemeEnum = AppThemes.DARK;
|
|
||||||
} else {
|
|
||||||
_currentTheme = AppThemeLight.instance.theme;
|
|
||||||
_currenThemeEnum = AppThemes.LIGHT;
|
|
||||||
}
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user