refactor(ui): update DetailDevice screen layout

This commit is contained in:
anhtunz
2024-12-26 11:31:21 +07:00
parent 77afc09d19
commit a69429b05f
26 changed files with 1231 additions and 671 deletions

View File

@@ -10,13 +10,6 @@ class MainBloc extends BlocBase {
StreamSink<Bell> get sinkBellBloc => bellBloc.sink;
Stream<Bell> get streamBellBloc => bellBloc.stream;
final title = StreamController<String>.broadcast();
StreamSink<String> get sinkTitle => title.sink;
Stream<String> get streamTitle => title.stream;
final role = StreamController<String>.broadcast();
StreamSink<String> get sinkRole => role.sink;
Stream<String> get streamRole => role.stream;
final language = StreamController<Locale?>.broadcast();
StreamSink<Locale?> get sinkLanguage => language.sink;
@@ -30,10 +23,6 @@ class MainBloc extends BlocBase {
StreamSink<bool> get sinkIsVNIcon => isVNIcon.sink;
Stream<bool> get streamIsVNIcon => isVNIcon.stream;
final currentPageIndex = StreamController<int>.broadcast();
StreamSink<int> get sinkCurrentPageIndex => currentPageIndex.sink;
Stream<int> get streamCurrentPageIndex => currentPageIndex.stream;
@override
void dispose() {}
}

View File

@@ -13,6 +13,8 @@ import 'package:sfm_app/product/constant/app/app_constants.dart';
import 'package:sfm_app/product/constant/enums/app_route_enums.dart';
import 'package:sfm_app/product/constant/enums/role_enums.dart';
import 'package:sfm_app/product/permission/location_permission.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_screen.dart';
import '../home/home_screen.dart';
@@ -53,8 +55,6 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
Bell bell = Bell();
void initialCheck() async {
role = await apiServices.getUserRole();
mainBloc.sinkRole.add(role);
String language = await apiServices.checkLanguage();
String theme = await apiServices.checkTheme();
if (language == LanguageConstants.VIETNAM) {
@@ -73,9 +73,12 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
LocationPermissionRequest.instance.checkLocationPermission(context);
}
// For test
late bool dayNightToggle2;
@override
void initState() {
super.initState();
dayNightToggle2 = false;
mainBloc = BlocProvider.of(context);
WidgetsBinding.instance.addObserver(this);
initialCheck();
@@ -176,303 +179,215 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
@override
Widget build(BuildContext context) {
ThemeNotifier themeNotifier = context.watch<ThemeNotifier>();
checkSelectedIndex(currentPageIndex);
List<Widget> userDestinations = [
NavigationDestination(
selectedIcon: IconConstants.instance.getMaterialIcon(Icons.home),
icon: IconConstants.instance.getMaterialIcon(Icons.home_outlined),
label: appLocalization(context).home_page_destination,
tooltip: appLocalization(context).home_page_destination,
),
NavigationDestination(
selectedIcon: IconConstants.instance.getMaterialIcon(Icons.settings),
icon: IconConstants.instance.getMaterialIcon(Icons.settings_outlined),
label: appLocalization(context).manager_page_destination,
tooltip: appLocalization(context).device_manager_page_name,
),
NavigationDestination(
selectedIcon: IconConstants.instance.getMaterialIcon(Icons.location_on),
icon:
IconConstants.instance.getMaterialIcon(Icons.location_on_outlined),
label: appLocalization(context).map_page_destination,
tooltip: appLocalization(context).map_page_destination,
),
NavigationDestination(
// selectedIcon: IconConstants.instance.getMaterialIcon(Icons.histor),
icon: IconConstants.instance.getMaterialIcon(Icons.history_rounded),
label: appLocalization(context).history_page_destination,
tooltip: appLocalization(context).history_page_destination_tooltip,
),
NavigationDestination(
selectedIcon: IconConstants.instance.getMaterialIcon(Icons.group),
icon: IconConstants.instance.getMaterialIcon(Icons.group_outlined),
label: appLocalization(context).group_page_destination,
tooltip: appLocalization(context).group_page_destination_tooltip,
),
];
List<Widget> userBody = [
BlocProvider(child: const HomeScreen(), blocBuilder: () => HomeBloc()),
BlocProvider(
child: const DevicesManagerScreen(),
blocBuilder: () => DevicesManagerBloc()),
BlocProvider(
child: const MapScreen(),
blocBuilder: () => MapBloc(),
),
BlocProvider(
child: const DeviceLogsScreen(),
blocBuilder: () => DeviceLogsBloc(),
),
BlocProvider(
child: const InterFamilyScreen(),
blocBuilder: () => InterFamilyBloc(),
),
];
List<Widget> modDestinations = [
NavigationDestination(
selectedIcon: IconConstants.instance.getMaterialIcon(Icons.home),
icon: IconConstants.instance.getMaterialIcon(Icons.home_outlined),
label: appLocalization(context).home_page_destination,
tooltip: appLocalization(context).home_page_destination,
),
NavigationDestination(
selectedIcon: IconConstants.instance.getMaterialIcon(Icons.settings),
icon: IconConstants.instance.getMaterialIcon(Icons.settings_outlined),
label: appLocalization(context).manager_page_destination,
tooltip: appLocalization(context).device_manager_page_name,
),
NavigationDestination(
selectedIcon: IconConstants.instance.getMaterialIcon(Icons.location_on),
icon:
IconConstants.instance.getMaterialIcon(Icons.location_on_outlined),
label: appLocalization(context).map_page_destination,
tooltip: appLocalization(context).map_page_destination,
),
];
List<Widget> modBody = [
BlocProvider(child: const HomeScreen(), blocBuilder: () => HomeBloc()),
BlocProvider(
child: const DevicesManagerScreen(),
blocBuilder: () => DevicesManagerBloc()),
BlocProvider(
child: const MapScreen(),
blocBuilder: () => MapBloc(),
),
];
return StreamBuilder<String>(
stream: mainBloc.streamRole,
initialData: role,
builder: (context, roleSnapshot) {
return StreamBuilder<int>(
stream: mainBloc.streamCurrentPageIndex,
initialData: currentPageIndex,
builder: (context, indexSnapshot) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
// centerTitle: true,
// title: StreamBuilder<String>(
// stream: mainBloc.streamTitle,
// initialData: titlePage,
// builder: (context, titleSnapshot) {
// return Text(
// titleSnapshot.data ?? ApplicationConstants.APP_NAME,
// );
// },
// ),
actions: [
StreamBuilder<bool>(
stream: mainBloc.streamThemeMode,
initialData: isLight,
builder: (context, themeModeSnapshot) {
return IconButton(
onPressed: () {
themeNotifier.changeTheme();
isLight = !isLight;
mainBloc.sinkThemeMode.add(isLight);
},
icon: Icon(
themeModeSnapshot.data ?? isLight
? Icons.light_mode_outlined
: Icons.dark_mode_outlined,
),
);
},
),
StreamBuilder<bool>(
stream: mainBloc.streamIsVNIcon,
initialData: isVN,
builder: (context, isVnSnapshot) {
return IconButton(
onPressed: () async {
log("Locale: ${LanguageServices().getLocale()}");
Locale locale = await LanguageServices().setLocale(
isVN
? LanguageConstants.ENGLISH
: LanguageConstants.VIETNAM);
MyApp.setLocale(context, locale);
isVN = !isVN;
mainBloc.sinkIsVNIcon.add(isVN);
},
icon: Image.asset(
IconConstants.instance.getIcon(
isVnSnapshot.data ?? isVN
? 'vi_icon'
: 'en_icon'),
height: 24,
width: 24,
),
);
},
),
StreamBuilder<Bell>(
stream: mainBloc.streamBellBloc,
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: () {
context.pushNamed(AppRoutes.BELL.name);
},
);
},
),
PopupMenuButton(
shape: RoundedRectangleBorder(
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,
),
],
),
),
];
},
)
],
),
// bottomNavigationBar: Container(
// decoration:
// BoxDecoration(borderRadius: BorderRadius.circular(50)),
// padding: context.paddingLow,
// child: NavigationBar(
// onDestinationSelected: (index) {
// currentPageIndex = index;
// mainBloc.sinkCurrentPageIndex.add(currentPageIndex);
// checkSelectedIndex(currentPageIndex);
// },
// selectedIndex: indexSnapshot.data ?? currentPageIndex,
// destinations: roleSnapshot.data == RoleEnums.USER.name
// ? userDestinations
// : modDestinations,
// ),
// ),
// body: IndexedStack(
// index: indexSnapshot.data ?? currentPageIndex,
// children: roleSnapshot.data == RoleEnums.USER.name
// ? userBody
// : modBody,
// ),
body: PersistentTabView(
context,
controller: controller,
screens: _buildScreens(),
items: _navBarsItems(),
confineInSafeArea: true,
handleAndroidBackButtonPress: true,
resizeToAvoidBottomInset: true,
stateManagement: true,
hideNavigationBarWhenKeyboardShows: true,
// backgroundColor: Colors.transparent,
decoration: NavBarDecoration(
borderRadius: BorderRadius.circular(30.0),
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
actions: [
// LightDarkSwitch(
// value: !isLight,
// onChanged: (value) {
// themeNotifier.changeTheme();
// isLight = !isLight;
// },
// ),
// SizedBox(
// width: context.lowValue,
// ),
// StreamBuilder<bool>(
// stream: mainBloc.streamIsVNIcon,
// builder: (context, isVNSnapshot) {
// return LanguageSwitch(
// value: isVNSnapshot.data ?? isVN,
// onChanged: (value) async {
// Locale locale = await LanguageServices().setLocale(isVN
// ? LanguageConstants.ENGLISH
// : LanguageConstants.VIETNAM);
// MyApp.setLocale(context, locale);
// isVN = !isVN;
// mainBloc.sinkIsVNIcon.add(isVN);
// },
// );
// }),
// SizedBox(
// width: context.lowValue,
// ),
StreamBuilder<bool>(
stream: mainBloc.streamThemeMode,
initialData: isLight,
builder: (context, themeModeSnapshot) {
return IconButton(
onPressed: () {
themeNotifier.changeTheme();
isLight = !isLight;
mainBloc.sinkThemeMode.add(isLight);
},
icon: Icon(
themeModeSnapshot.data ?? isLight
? Icons.light_mode_outlined
: Icons.dark_mode_outlined,
),
popAllScreensOnTapOfSelectedTab: true,
itemAnimationProperties: const ItemAnimationProperties(
duration: Duration(milliseconds: 200),
curve: Curves.bounceInOut,
);
},
),
StreamBuilder<bool>(
stream: mainBloc.streamIsVNIcon,
initialData: isVN,
builder: (context, isVnSnapshot) {
return IconButton(
onPressed: () async {
log("Locale: ${LanguageServices().getLocale()}");
Locale locale = await LanguageServices().setLocale(isVN
? LanguageConstants.ENGLISH
: LanguageConstants.VIETNAM);
MyApp.setLocale(context, locale);
isVN = !isVN;
mainBloc.sinkIsVNIcon.add(isVN);
},
icon: Image.asset(
IconConstants.instance.getIcon(
isVnSnapshot.data ?? isVN ? 'vi_icon' : 'en_icon'),
height: 24,
width: 24,
),
screenTransitionAnimation: const ScreenTransitionAnimation(
animateTabTransition: true,
curve: Curves.linear,
duration: Duration(milliseconds: 200),
);
},
),
StreamBuilder<Bell>(
stream: mainBloc.streamBellBloc,
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: () {
context.pushNamed(AppRoutes.BELL.name);
},
);
},
),
PopupMenuButton(
shape: RoundedRectangleBorder(
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)
],
),
),
navBarStyle: NavBarStyle.style4,
),
);
},
);
},
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,
),
],
),
),
];
},
)
],
),
// bottomNavigationBar: Container(
// decoration:
// BoxDecoration(borderRadius: BorderRadius.circular(50)),
// padding: context.paddingLow,
// child: NavigationBar(
// onDestinationSelected: (index) {
// currentPageIndex = index;
// mainBloc.sinkCurrentPageIndex.add(currentPageIndex);
// checkSelectedIndex(currentPageIndex);
// },
// selectedIndex: indexSnapshot.data ?? currentPageIndex,
// destinations: roleSnapshot.data == RoleEnums.USER.name
// ? userDestinations
// : modDestinations,
// ),
// ),
// body: IndexedStack(
// index: indexSnapshot.data ?? currentPageIndex,
// children: roleSnapshot.data == RoleEnums.USER.name
// ? userBody
// : modBody,
// ),
body: PersistentTabView(
context,
controller: controller,
screens: _buildScreens(),
items: _navBarsItems(),
confineInSafeArea: true,
handleAndroidBackButtonPress: true,
resizeToAvoidBottomInset: true,
stateManagement: true,
hideNavigationBarWhenKeyboardShows: true,
// backgroundColor: Colors.transparent,
decoration: NavBarDecoration(
borderRadius: BorderRadius.circular(30.0),
),
popAllScreensOnTapOfSelectedTab: true,
itemAnimationProperties: const ItemAnimationProperties(
duration: Duration(milliseconds: 200),
curve: Curves.bounceInOut,
),
screenTransitionAnimation: const ScreenTransitionAnimation(
animateTabTransition: true,
curve: Curves.linear,
duration: Duration(milliseconds: 200),
),
navBarStyle: NavBarStyle.style4,
),
);
}
@@ -487,23 +402,4 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
}
return !bells.any((bell) => bell.status == 0);
}
void checkSelectedIndex(int current) {
if (current == 0) {
titlePage = appLocalization(context).home_page_name;
mainBloc.sinkTitle.add(titlePage);
} else if (current == 1) {
titlePage = appLocalization(context).device_manager_page_name;
mainBloc.sinkTitle.add(titlePage);
} else if (current == 2) {
titlePage = appLocalization(context).map_page_destination;
mainBloc.sinkTitle.add(titlePage);
} else if (current == 3) {
titlePage = appLocalization(context).device_log_page_name;
mainBloc.sinkTitle.add(titlePage);
} else if (current == 4) {
titlePage = appLocalization(context).interfamily_page_name;
mainBloc.sinkTitle.add(titlePage);
}
}
}