Skip to content

Commit 05b8720

Browse files
committed
Step 10.2 tested for web
1 parent 9014ed1 commit 05b8720

File tree

13 files changed

+286
-106
lines changed

13 files changed

+286
-106
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ Step 9: Add User Roles using Custom Claims. This requires upgrade of plan as we
8181
2. Created Navigation for each of Admin, Buyer, Seller screens
8282
3. Allowed switch from lower role Navigation to Navigation view till the given role of the user
8383

84-
Step 10: TODO: Firebase Remote Config for A/B testing
84+
Step 10: TODO: Firebase Remote Config for A/B testing. See [https://firebase.google.com/docs/remote-config]
8585

8686
1. Complete the Screen enum based Navigation framework
87-
2. Config for Navigation element change
88-
* A: Drawer for Account, Settings, Sign Out
89-
* B: Hamburger that opens BottomSheet (Context Menu in larger screen) for the same options
87+
2. Config useBottomSheetForProfileOptions for Navigation element to be one of the following
88+
* False: Drawer for Account, Settings, Sign Out
89+
* True: Hamburger that opens BottomSheet (Context Menu in larger screen) for the same options
9090
3. Config for adding Search Bar at the Top vs a Bottom Navigation button
9191

9292
Step 11: TODO: CRUD
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import 'package:get/get.dart';
2+
3+
import '../../../../models/screens.dart';
4+
5+
class MyDrawerController extends GetxController {
6+
MyDrawerController(Iterable<Screen> iter)
7+
: values = Rx<Iterable<Screen>>(iter);
8+
9+
final Rx<Iterable<Screen>> values;
10+
}

lib/app/modules/root/views/drawer.dart

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import '../../../../models/role.dart';
77
import '../../../../services/auth_service.dart';
88

99
import '../../../../models/screens.dart';
10+
import '../controllers/my_drawer_controller.dart';
1011

1112
class DrawerWidget extends StatelessWidget {
1213
const DrawerWidget({
@@ -15,20 +16,23 @@ class DrawerWidget extends StatelessWidget {
1516

1617
@override
1718
Widget build(BuildContext context) {
18-
return Drawer(
19-
//changing the shape of the drawer
20-
shape: const RoundedRectangleBorder(
21-
borderRadius: BorderRadius.only(
22-
topRight: Radius.circular(0), bottomRight: Radius.circular(20)),
23-
),
24-
width: 200,
25-
child: Column(
26-
children: drawerItems(context),
27-
),
28-
);
19+
MyDrawerController controller = Get.put(MyDrawerController([]),
20+
permanent: true); //must make true else gives error
21+
Screen.drawer().then((v) => {controller.values.value = v});
22+
return Obx(() => Drawer(
23+
//changing the shape of the drawer
24+
shape: const RoundedRectangleBorder(
25+
borderRadius: BorderRadius.only(
26+
topRight: Radius.circular(0), bottomRight: Radius.circular(20)),
27+
),
28+
width: 200,
29+
child: Column(
30+
children: drawerItems(context, controller.values),
31+
),
32+
));
2933
}
3034

31-
List<Widget> drawerItems(BuildContext context) {
35+
List<Widget> drawerItems(BuildContext context, Rx<Iterable<Screen>> values) {
3236
List<Widget> list = [
3337
Container(
3438
height: 100,
@@ -43,34 +47,38 @@ class DrawerWidget extends StatelessWidget {
4347
)
4448
];
4549

46-
for (var i = 0; i <= AuthService.to.maxRole.index; i++) {
47-
Role role = Role.values[i];
48-
list.add(ListTile(
49-
title: Text(
50-
role.name,
51-
style: const TextStyle(
52-
color: Colors.blue,
50+
if (AuthService.to.maxRole.index > 1) {
51+
for (var i = 0; i <= AuthService.to.maxRole.index; i++) {
52+
Role role = Role.values[i];
53+
list.add(ListTile(
54+
title: Text(
55+
role.name,
56+
style: const TextStyle(
57+
color: Colors.blue,
58+
),
5359
),
54-
),
60+
onTap: () {
61+
Get.rootDelegate
62+
.toNamed(Screen.HOME.route, arguments: {'role': role});
63+
//to close the drawer
64+
Navigator.of(context).pop();
65+
},
66+
));
67+
}
68+
}
69+
70+
for (Screen screen in values.value) {
71+
list.add(ListTile(
72+
title: Text(screen.label ?? ''),
5573
onTap: () {
56-
Get.rootDelegate
57-
.toNamed(Screen.HOME.route, arguments: {'role': role});
74+
Get.rootDelegate.toNamed(screen.route);
5875
//to close the drawer
76+
5977
Navigator.of(context).pop();
6078
},
6179
));
6280
}
6381

64-
Screen.drawer().forEach((Screen screen) => list.add(ListTile(
65-
title: Text(screen.label ?? ''),
66-
onTap: () {
67-
Get.rootDelegate.toNamed(screen.route);
68-
//to close the drawer
69-
70-
Navigator.of(context).pop();
71-
},
72-
)));
73-
7482
if (AuthService.to.isLoggedInValue) {
7583
list.add(ListTile(
7684
title: const Text(

lib/app/modules/root/views/root_view.dart

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,7 @@ class RootView extends GetView<RootController> {
3838
? controller.openDrawer()
3939
: {Screen.HOME.doAction()},
4040
),
41-
actions: [
42-
Container(
43-
margin: const EdgeInsets.only(right: 15),
44-
child: Screen.LOGIN.widget(current))
45-
],
41+
actions: topRightMenuButtons(current),
4642
// automaticallyImplyLeading: false, //removes drawer icon
4743
),
4844
body: GetRouterOutlet(
@@ -56,4 +52,13 @@ class RootView extends GetView<RootController> {
5652
},
5753
);
5854
}
55+
56+
//This could be used to add icon buttons in expanded web view instead of the context menu
57+
List<Widget> topRightMenuButtons(GetNavConfig current) {
58+
return [
59+
Container(
60+
margin: const EdgeInsets.only(right: 15),
61+
child: Screen.LOGIN.widget(current))
62+
]; //TODO add seach button
63+
}
5964
}

lib/app/widgets/login_widgets.dart

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:get/get.dart';
55

66
import '../../services/auth_service.dart';
77
import '../../models/screens.dart';
8+
import '../../services/remote_config.dart';
89
import 'menu_sheet_button.dart';
910

1011
class LoginWidgets {
@@ -43,23 +44,15 @@ class LoginWidgets {
4344
}
4445
}
4546

46-
// class SwitchX extends GetxController {
47-
// RxBool isLoginPage =
48-
// (Get.rootDelegate.currentConfiguration!.currentPage!.name ==
49-
// Screen.LOGIN.path)
50-
// .obs; // our observable
51-
52-
// void toggle(Screen screen) {
53-
// isLoginPage.value = screen == Screen.LOGIN;
54-
// }
55-
// }
56-
5747
class LoginBottomSheetToggle extends MenuSheetButton<Screen> {
5848
const LoginBottomSheetToggle(this.current, {super.key});
5949
final GetNavConfig current;
6050

6151
@override
62-
Iterable<Screen> get values => Screen.sheet(null);
52+
Iterable<Screen> get values {
53+
MenuItemsController<Screen> controller = Get.find();
54+
return controller.values.value;
55+
}
6356

6457
@override
6558
Icon? get icon => (AuthService.to.isLoggedInValue)
@@ -75,18 +68,19 @@ class LoginBottomSheetToggle extends MenuSheetButton<Screen> {
7568
: 'Click for Options'
7669
: 'Login';
7770

78-
// @override
79-
// void callbackFunc(act) {
80-
// SwitchX controller = Get.find();
81-
// controller.toggle(Screen.LOGIN);
82-
// }
83-
8471
@override
8572
Widget build(BuildContext context) {
86-
// SwitchX controller =
87-
// Get.put(SwitchX(), permanent: true); //must make true else gives error
73+
MenuItemsController<Screen> controller = Get.put(
74+
MenuItemsController<Screen>([]),
75+
permanent: true); //must make true else gives error
76+
Screen.sheet(null).then((val) {
77+
controller.values.value = val;
78+
});
79+
RemoteConfig.instance.then((ins) =>
80+
ins.addUseBottomSheetForProfileOptionsListener((val) async =>
81+
{controller.values.value = await Screen.sheet(null)}));
8882
return Obx(() => (AuthService.to.isLoggedInValue)
89-
? builder(context)
83+
? builder(context, vals: controller.values.value)
9084
: !(current.currentPage!.name == Screen.LOGIN.path)
9185
? IconButton(
9286
onPressed: () async {

lib/app/widgets/menu_sheet_button.dart

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import 'package:get/get.dart';
33

44
import '../../models/action_enum.dart';
55

6+
class MenuItemsController<T extends ActionEnum> extends GetxController {
7+
MenuItemsController(Iterable<T> iter) : values = Rx<Iterable<T>>(iter);
8+
9+
final Rx<Iterable<T>> values;
10+
}
11+
612
class MenuSheetButton<T extends ActionEnum> extends StatelessWidget {
713
final Iterable<T>? values_;
814
final Icon? icon;
@@ -42,7 +48,7 @@ class MenuSheetButton<T extends ActionEnum> extends StatelessWidget {
4248
);
4349
}
4450

45-
List<PopupMenuEntry<T>> getItems(BuildContext context) {
51+
List<PopupMenuEntry<T>> getItems(BuildContext context, Iterable<T> values) {
4652
return values.map<PopupMenuEntry<T>>(createPopupMenuItem).toList();
4753
}
4854

@@ -57,27 +63,29 @@ class MenuSheetButton<T extends ActionEnum> extends StatelessWidget {
5763
}
5864

5965
//This should be a modal bottom sheet if on Mobile (See https://mercyjemosop.medium.com/select-and-upload-images-to-firebase-storage-flutter-6fac855970a9)
60-
Widget builder(BuildContext context) {
66+
Widget builder(BuildContext context, {Iterable<T>? vals}) {
67+
Iterable<T> values = vals ?? values_!;
6168
return values.length == 1 ||
6269
Get.mediaQuery.orientation == Orientation.portrait
6370
// : Get.context!.isPortrait
6471
? (icon != null
6572
? IconButton(
66-
onPressed: buttonPressed,
73+
onPressed: () => buttonPressed(values),
6774
icon: icon!,
6875
tooltip: label,
6976
)
7077
: TextButton(
71-
onPressed: buttonPressed, child: Text(label ?? 'Need Label')))
78+
onPressed: () => buttonPressed(values),
79+
child: Text(label ?? 'Need Label')))
7280
: PopupMenuButton<T>(
73-
itemBuilder: getItems,
81+
itemBuilder: (context_) => getItems(context_, values),
7482
icon: icon,
7583
tooltip: label,
7684
onSelected: (T value) async =>
7785
callbackFunc(await value.doAction()));
7886
}
7987

80-
void buttonPressed() async => values.length == 1
88+
void buttonPressed(Iterable<T> values) async => values.length == 1
8189
? callbackFunc(await values.first.doAction())
8290
: Get.bottomSheet(MenuSheetButton.bottomSheet(values, callbackFunc),
8391
backgroundColor: Colors.white);

lib/constants.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const kPrimaryLightColor = Color(0xFFF1E6FF);
66

77
const double defaultPadding = 16.0;
88

9-
const useEmulator = true;
9+
const useEmulator = false;
1010

1111
const useRecaptcha = false;
1212

lib/models/role.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ enum Role {
3030
bool hasAccessOf(String role) => index >= fromString(role).index;
3131

3232
List<Screen> get tabs => permissions
33-
.where((screen) => screen.accessor == AccessedVia.navigator)
33+
.where((screen) => screen.accessor_ == AccessedVia.navigator)
3434
.toList(); //the ones in tab
3535
}

0 commit comments

Comments
 (0)