Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: #678 - added bottom navigation bar to product page #679

Merged
merged 4 commits into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/smooth_app/lib/data_models/user_preferences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class UserPreferences extends ChangeNotifier {
static const String _TAG_INIT = 'init';
static const String _TAG_THEME_DARK = 'themeDark';
static const String _TAG_THEME_COLOR_TAG = 'themeColorTag';
static const String _TAG_BOTTOM_TAB_INDEX = 'bottomTabIndex';

static const int _BOTTOM_TAB_INDEX_DEFAULT = 1;

Future<void> init(final ProductPreferences productPreferences) async {
final bool? alreadyDone = _sharedPreferences.getBool(_TAG_INIT);
Expand Down Expand Up @@ -57,4 +60,11 @@ class UserPreferences extends ChangeNotifier {

String get themeColorTag =>
_sharedPreferences.getString(_TAG_THEME_COLOR_TAG) ?? 'COLOR_TAG_BLUE';

Future<void> setBottomTabIndex(final int index) async =>
_sharedPreferences.setInt(_TAG_BOTTOM_TAB_INDEX, index);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't read through the whole code yet, but I don't see the value in storing the index. Especially now where besides the scanner the other two pages don't provide that much value anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@M123-dev The point of storing the index is to use exactly the same navigation bar in all cases: the legacy cases (the former home page, divided in 3 tabs) and the new cases (purpose of this issue, and the product page is dealt with in this PR). And without too much complex code: just add bottomNavigationBar: SmoothBottomNavigationBar() to the Scaffold.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey this PR is pretty close to my solution for this as well, so it looks good to me.

I don't really see why we need the current index though? Is it so if a user closes the app and comes back, they land on the tab they we on when they closed the app ? In that case, it was discussed that whenever a user opens the app they should see the scan page with "Welcome to Open food facts" text on the search box.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was discussed that whenever a user opens the app they should see the scan page with "Welcome to Open food facts" text on the search box

Oh, I didn't know that.
Behind saving the current index, there was also the question (already asked): which tab should look "selected" when we're not on one tab page in particular - e.g. when we are on the product page?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in a nutshell, this is what I understand the behavior to be:

  • Navigation bar becomes sticky
  • If the user goes into a tab and clicks around (example: opens the product page from history tab), he is still in that tab, just browsing
  • Tabs are sticky, so lets say a user is on the "Product page" from the "History tab", he clicks on "Preferences tab", then clicks back on the "History tab", he will land on the "Product page" he was recently viewing, rather than on the "history page". Tapping again on the History tab will take the user to the "History page". This behavior is akin to a few other apps like Gmail/parts of GMaps etc.
  • When the user opens the app, the first tab displayed to the user is always the Scan page.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Navigation bar becomes sticky

More precisely, navigation bar was added to the product page. I'm not sure if there are other pages beyond profile, scan, history and product, but if so, the navigation bar should be added there too.

If the user goes into a tab and clicks around (example: opens the product page from history tab), he is still in that tab, just browsing

No, because you asked me to remove the tab index from the preferences and that's where I kept its value. If you go to a product page, the navigation bar will display the default tab as selected: the scan tab. Anyway I didn't get the answer to "which tab should be selected when we are on the product page", and in the meanwhile I decided to select the scan tab.

Tabs are sticky, so lets say a user is on the "Product page" from the "History tab", he clicks on "Preferences tab", then clicks back on the "History tab", he will land on the "Product page" he was recently viewing, rather than on the "history page". Tapping again on the History tab will take the user to the "History page". This behavior is akin to a few other apps like Gmail/parts of GMaps etc.

No, if you click on the history tab you always go to the history page.
This PR is only about issue #678, and does not implement the not-even-existing-yet "Make tabs stateful" issue evoked in #655.

When the user opens the app, the first tab displayed to the user is always the Scan page.

That's correct, the default tab (which is opened in main.dart) is the scan tab.

Copy link
Contributor

@jasmeet0817 jasmeet0817 Nov 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, my previous message was more around generally what the navigation behavior should be like and not about how it would be after this PR. Sorry for misunderstanding. This PR adds the feature it's meant to add, so thank you for that.

I'm not sure if there are other pages beyond profile, scan, history and product, but if so, the navigation bar should be added there too.

There's also the settings page, but that one is not that important, also doesn't feel like we should make the settings page sticky. Let's skip it for now. If we have to add the bar to it later, we can do so.

"which tab should be selected when we are on the product page"

So if the user goes to a tab (lets say history tab) and clicks around on the page and lands on some other view (lets say product page), he is considered to still be on the history tab, so the history tab should appear as selected. I was thinking this should be doable without storing the tab index in user prefs. if we instantiate with bottomNavigationBar: const SmoothBottomNavigationBar(tab=SmoothBottomNavigationTab.History) in new_product_page


int get bottomTabIndex =>
_sharedPreferences.getInt(_TAG_BOTTOM_TAB_INDEX) ??
_BOTTOM_TAB_INDEX_DEFAULT;
}
4 changes: 2 additions & 2 deletions packages/smooth_app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import 'package:smooth_app/data_models/product_preferences.dart';
import 'package:smooth_app/data_models/user_preferences.dart';
import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/database/search_history.dart';
import 'package:smooth_app/pages/home_page.dart';
import 'package:smooth_app/pages/smooth_bottom_navigation_bar.dart';
import 'package:smooth_app/themes/smooth_theme.dart';
import 'package:smooth_app/themes/theme_provider.dart';

Expand Down Expand Up @@ -171,7 +171,7 @@ class SmoothAppGetLanguage extends StatelessWidget {
DefaultAssetBundle.of(context),
languageCode,
);
return const HomePage();
return SmoothBottomNavigationBar.getCurrentPage(context);
}

Future<void> _refresh(
Expand Down
66 changes: 0 additions & 66 deletions packages/smooth_app/lib/pages/home_page.dart

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:smooth_app/pages/personalized_ranking_page.dart';
import 'package:smooth_app/pages/product/common/product_list_dialog_helper.dart';
import 'package:smooth_app/pages/product/common/product_list_item.dart';
import 'package:smooth_app/pages/product/common/product_query_page_helper.dart';
import 'package:smooth_app/pages/smooth_bottom_navigation_bar.dart';
import 'package:smooth_app/themes/smooth_theme.dart';

class ProductListPage extends StatefulWidget {
Expand Down Expand Up @@ -87,6 +88,7 @@ class _ProductListPageState extends State<ProductListPage> {
throw Exception('unknown list type ${productList.listType}');
}
return Scaffold(
bottomNavigationBar: SmoothBottomNavigationBar(),
appBar: AppBar(
backgroundColor: SmoothTheme.getColor(
colorScheme,
Expand Down
2 changes: 2 additions & 0 deletions packages/smooth_app/lib/pages/product/new_product_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:smooth_app/helpers/launch_url_helper.dart';
import 'package:smooth_app/helpers/product_cards_helper.dart';
import 'package:smooth_app/pages/product/common/product_dialog_helper.dart';
import 'package:smooth_app/pages/product/summary_card.dart';
import 'package:smooth_app/pages/smooth_bottom_navigation_bar.dart';
import 'package:smooth_app/themes/smooth_theme.dart';
import 'package:smooth_app/themes/theme_provider.dart';
import 'package:smooth_ui_library/util/ui_helpers.dart';
Expand Down Expand Up @@ -52,6 +53,7 @@ class _ProductPageState extends State<NewProductPage> {
final MaterialColor materialColor =
SmoothTheme.getMaterialColor(themeProvider);
return Scaffold(
bottomNavigationBar: SmoothBottomNavigationBar(),
backgroundColor: SmoothTheme.getColor(
colorScheme,
materialColor,
Expand Down
2 changes: 2 additions & 0 deletions packages/smooth_app/lib/pages/product/product_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import 'package:smooth_app/helpers/product_translation_helper.dart';
import 'package:smooth_app/pages/product/common/product_dialog_helper.dart';
import 'package:smooth_app/pages/product/common/product_query_page_helper.dart';
import 'package:smooth_app/pages/product/new_product_page.dart';
import 'package:smooth_app/pages/smooth_bottom_navigation_bar.dart';
import 'package:smooth_app/pages/user_preferences_page.dart';
import 'package:smooth_app/themes/constant_icons.dart';
import 'package:smooth_app/themes/smooth_theme.dart';
Expand Down Expand Up @@ -106,6 +107,7 @@ class _ProductPageState extends State<ProductPage> {
}
}
return Scaffold(
bottomNavigationBar: SmoothBottomNavigationBar(),
appBar: AppBar(
title: Text(_getProductName(appLocalizations)),
actions: <Widget>[
Expand Down
2 changes: 2 additions & 0 deletions packages/smooth_app/lib/pages/scan/continuous_scan_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:smooth_app/data_models/continuous_scan_model.dart';
import 'package:smooth_app/pages/personalized_ranking_page.dart';
import 'package:smooth_app/pages/smooth_bottom_navigation_bar.dart';
import 'package:smooth_app/widgets/smooth_product_carousel.dart';
import 'package:smooth_ui_library/smooth_ui_library.dart';
import 'package:smooth_ui_library/util/ui_helpers.dart';
Expand Down Expand Up @@ -33,6 +34,7 @@ class ContinuousScanPage extends StatelessWidget {
final double viewFinderBottomOffset = carouselHeight / 2.0;
return Scaffold(
appBar: AppBar(toolbarHeight: 0.0),
bottomNavigationBar: SmoothBottomNavigationBar(),
body: Stack(
children: <Widget>[
Container(
Expand Down
67 changes: 67 additions & 0 deletions packages/smooth_app/lib/pages/smooth_bottom_navigation_bar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smooth_app/data_models/user_preferences.dart';
import 'package:smooth_app/pages/history_page.dart';
import 'package:smooth_app/pages/scan/scan_page.dart';
import 'package:smooth_app/pages/user_preferences_page.dart';

class _Page {
const _Page({required this.name, required this.icon, required this.body});
final String name;
final IconData icon;
final Widget body;
}

class SmoothBottomNavigationBar extends StatelessWidget {
static const List<_Page> _pages = <_Page>[
_Page(
name: 'Profile', // TODO(monsieurtanuki): translate
icon: Icons.account_circle,
body: UserPreferencesPage(),
),
_Page(
name: 'Scan or Search',
icon: Icons.search,
body: ScanPage(),
),
_Page(
name: 'History',
icon: Icons.history,
body: HistoryPage(),
),
];

static Widget getCurrentPage(final BuildContext context) {
final UserPreferences userPreferences = context.watch<UserPreferences>();
return _pages[userPreferences.bottomTabIndex].body;
}

@override
Widget build(BuildContext context) {
final UserPreferences userPreferences = context.watch<UserPreferences>();
return BottomNavigationBar(
showSelectedLabels: false,
showUnselectedLabels: false,
selectedItemColor: Colors.white,
backgroundColor: Theme.of(context).appBarTheme.backgroundColor,
currentIndex: userPreferences.bottomTabIndex,
onTap: (final int index) async {
userPreferences.setBottomTabIndex(index);
await Navigator.push<Widget>(
context,
MaterialPageRoute<Widget>(
builder: (BuildContext context) => _pages[index].body,
),
);
},
items: _pages
.map(
(_Page p) => BottomNavigationBarItem(
icon: Icon(p.icon, size: 28),
label: p.name,
),
)
.toList(),
);
}
}
2 changes: 2 additions & 0 deletions packages/smooth_app/lib/pages/user_preferences_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:provider/provider.dart';
import 'package:smooth_app/data_models/product_preferences.dart';
import 'package:smooth_app/data_models/user_preferences.dart';
import 'package:smooth_app/pages/settings_page.dart';
import 'package:smooth_app/pages/smooth_bottom_navigation_bar.dart';
import 'package:smooth_app/themes/smooth_theme.dart';
import 'package:smooth_app/widgets/attribute_button.dart';

Expand Down Expand Up @@ -35,6 +36,7 @@ class UserPreferencesPage extends StatelessWidget {
final List<String> orderedImportantAttributeIds =
productPreferences.getOrderedImportantAttributeIds();
return Scaffold(
bottomNavigationBar: SmoothBottomNavigationBar(),
appBar: AppBar(
title: Text(appLocalizations.myPreferences),
actions: <Widget>[
Expand Down

This file was deleted.

Loading