Skip to content

Commit

Permalink
feat: 3719 - new "scan history" page among the account product lists (#…
Browse files Browse the repository at this point in the history
…4029)

Impacted files:
* `app_en.arb`: added 1 label for "scan history"
* `continuous_scan_model.dart`: added the product to "scan history"
* `product_list.dart`: added "scan history"; refactored `ProductListType`
* `product_list_page.dart`: added "scan history"
* `product_query_page_helper.dart`: added "scan history"
* `user_preferences_account.dart`: added an access to the "scan history" page
  • Loading branch information
monsieurtanuki committed May 27, 2023
1 parent 726b5d4 commit e2197d1
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class ContinuousScanModel with ChangeNotifier {
<String, ScannedProductState>{};
final List<String> _barcodes = <String>[];
final ProductList _productList = ProductList.scanSession();
final ProductList _scanHistory = ProductList.scanHistory();
final ProductList _history = ProductList.history();

String? _latestScannedBarcode;
Expand Down Expand Up @@ -250,6 +251,7 @@ class ContinuousScanModel with ChangeNotifier {
if (_latestFoundBarcode != barcode) {
_latestFoundBarcode = barcode;
await _daoProductList.push(productList, _latestFoundBarcode!);
await _daoProductList.push(_scanHistory, _latestFoundBarcode!);
await _daoProductList.push(_history, _latestFoundBarcode!);
_daoProductList.localDatabase.notifyListeners();
}
Expand Down
56 changes: 20 additions & 36 deletions packages/smooth_app/lib/data_models/product_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,41 @@ import 'package:openfoodfacts/openfoodfacts.dart';

enum ProductListType {
/// API search by [SearchTerms] keywords
HTTP_SEARCH_KEYWORDS,
HTTP_SEARCH_KEYWORDS('http/search/keywords'),

/// API search for [CategoryProductQuery] category
HTTP_SEARCH_CATEGORY,
HTTP_SEARCH_CATEGORY('http/search/category'),

/// Current scan session; can be easily cleared by the end-user
SCAN_SESSION,
SCAN_SESSION('scan_session'),

/// Whole scan history; items may be removed by the end-user
SCAN_HISTORY('scan_history'),

/// History of products seen by the end-user
HISTORY,
HISTORY('history'),

/// End-user product list
USER,
USER('user'),

/// End-user as a contributor
HTTP_USER_CONTRIBUTOR,
HTTP_USER_CONTRIBUTOR('http/user/contributor'),

/// End-user as an informer
HTTP_USER_INFORMER,
HTTP_USER_INFORMER('http/user/informer'),

/// End-user as a photographer
HTTP_USER_PHOTOGRAPHER,
HTTP_USER_PHOTOGRAPHER('http/user/photographer'),

/// End-user for products to be completed
HTTP_USER_TO_BE_COMPLETED,
HTTP_USER_TO_BE_COMPLETED('http/user/to_be_completed'),

/// For products to be completed, all of them.
HTTP_ALL_TO_BE_COMPLETED,
}
HTTP_ALL_TO_BE_COMPLETED('http/all/to_be_completed');

extension ProductListTypeExtension on ProductListType {
String get key {
switch (this) {
case ProductListType.HTTP_SEARCH_KEYWORDS:
return 'http/search/keywords';
case ProductListType.HTTP_SEARCH_CATEGORY:
return 'http/search/category';
case ProductListType.SCAN_SESSION:
return 'scan_session';
case ProductListType.HTTP_USER_CONTRIBUTOR:
return 'http/user/contributor';
case ProductListType.HTTP_USER_INFORMER:
return 'http/user/informer';
case ProductListType.HTTP_USER_PHOTOGRAPHER:
return 'http/user/photographer';
case ProductListType.HTTP_USER_TO_BE_COMPLETED:
return 'http/user/to_be_completed';
case ProductListType.HTTP_ALL_TO_BE_COMPLETED:
return 'http/all/to_be_completed';
case ProductListType.HISTORY:
return 'history';
case ProductListType.USER:
return 'user';
}
}
const ProductListType(this.key);

final String key;
}

class ProductList {
Expand Down Expand Up @@ -168,6 +148,8 @@ class ProductList {

ProductList.scanSession() : this._(listType: ProductListType.SCAN_SESSION);

ProductList.scanHistory() : this._(listType: ProductListType.SCAN_HISTORY);

ProductList.user(final String name)
: this._(
listType: ProductListType.USER,
Expand Down Expand Up @@ -245,6 +227,7 @@ class ProductList {
case ProductListType.USER:
return false;
case ProductListType.SCAN_SESSION:
case ProductListType.SCAN_HISTORY:
case ProductListType.HISTORY:
return true;
}
Expand All @@ -253,6 +236,7 @@ class ProductList {
String getParametersKey() {
switch (listType) {
case ProductListType.SCAN_SESSION:
case ProductListType.SCAN_HISTORY:
case ProductListType.HISTORY:
case ProductListType.USER:
return parameters;
Expand Down
8 changes: 6 additions & 2 deletions packages/smooth_app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -426,9 +426,13 @@
"@filter": {
"description": "A button that opens a menu where you can filter within categories. Juices => Apple juices/Orange juices"
},
"scan": "Scan",
"scan": "Scan session",
"@scan": {
"description": "Page title: List type: Scanned products"
"description": "Page title: List type: Products in the scan session"
},
"scan_history": "Scan history",
"@scan_history": {
"description": "Page title: List type: Products in the whole scan history"
},
"search": "Search",
"@search": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:provider/provider.dart';
import 'package:smooth_app/data_models/product_list.dart';
import 'package:smooth_app/data_models/user_management_provider.dart';
import 'package:smooth_app/data_models/user_preferences.dart';
import 'package:smooth_app/database/dao_product_list.dart';
import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/generic_lib/buttons/smooth_simple_button.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
Expand All @@ -15,6 +17,7 @@ import 'package:smooth_app/pages/preferences/abstract_user_preferences.dart';
import 'package:smooth_app/pages/preferences/account_deletion_webview.dart';
import 'package:smooth_app/pages/preferences/user_preferences_list_tile.dart';
import 'package:smooth_app/pages/preferences/user_preferences_page.dart';
import 'package:smooth_app/pages/product/common/product_list_page.dart';
import 'package:smooth_app/pages/product/common/product_query_page_helper.dart';
import 'package:smooth_app/pages/user_management/login_page.dart';
import 'package:smooth_app/query/paged_product_query.dart';
Expand Down Expand Up @@ -245,7 +248,7 @@ class _UserPreferencesPageState extends State<UserPreferencesSection> {
iconData: Icons.add_circle_outline,
context: context,
localDatabase: localDatabase,
type: UserSearchType.CONTRIBUTOR,
myCount: _getMyCount(UserSearchType.CONTRIBUTOR),
),
_buildProductQueryTile(
productQuery: PagedUserProductQuery(
Expand All @@ -256,7 +259,7 @@ class _UserPreferencesPageState extends State<UserPreferencesSection> {
iconData: Icons.edit,
context: context,
localDatabase: localDatabase,
type: UserSearchType.INFORMER,
myCount: _getMyCount(UserSearchType.INFORMER),
),
_buildProductQueryTile(
productQuery: PagedUserProductQuery(
Expand All @@ -267,7 +270,7 @@ class _UserPreferencesPageState extends State<UserPreferencesSection> {
iconData: Icons.add_a_photo,
context: context,
localDatabase: localDatabase,
type: UserSearchType.PHOTOGRAPHER,
myCount: _getMyCount(UserSearchType.PHOTOGRAPHER),
),
_buildProductQueryTile(
productQuery: PagedUserProductQuery(
Expand All @@ -278,7 +281,7 @@ class _UserPreferencesPageState extends State<UserPreferencesSection> {
iconData: Icons.more_horiz,
context: context,
localDatabase: localDatabase,
type: UserSearchType.TO_BE_COMPLETED,
myCount: _getMyCount(UserSearchType.TO_BE_COMPLETED),
),
_buildProductQueryTile(
productQuery: PagedToBeCompletedProductQuery(),
Expand All @@ -287,6 +290,12 @@ class _UserPreferencesPageState extends State<UserPreferencesSection> {
context: context,
localDatabase: localDatabase,
),
_buildProductLocalTile(
productList: ProductList.scanHistory(),
iconData: Icons.history,
context: context,
localDatabase: localDatabase,
),
_getListTile(
appLocalizations.view_profile,
() async => LaunchUrlHelper.launchURL(
Expand Down Expand Up @@ -390,13 +399,21 @@ class _UserPreferencesPageState extends State<UserPreferencesSection> {
}
}

Future<int?> _getMyLocalCount(
final ProductList productList,
final LocalDatabase localDatabase,
) async {
await DaoProductList(localDatabase).get(productList);
return productList.barcodes.length;
}

Widget _buildProductQueryTile({
required final PagedProductQuery productQuery,
required final String title,
required final IconData iconData,
required final BuildContext context,
required final LocalDatabase localDatabase,
final UserSearchType? type,
final Future<int?>? myCount,
}) =>
_getListTile(
title,
Expand All @@ -408,14 +425,38 @@ class _UserPreferencesPageState extends State<UserPreferencesSection> {
editableAppBarTitle: false,
),
iconData,
type: type,
myCount: myCount,
);

Widget _buildProductLocalTile({
required final ProductList productList,
required final IconData iconData,
required final BuildContext context,
required final LocalDatabase localDatabase,
}) =>
_getListTile(
ProductQueryPageHelper.getProductListLabel(productList, context),
() async {
await DaoProductList(localDatabase).get(productList);
if (!mounted) {
return;
}
await Navigator.push<void>(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) => ProductListPage(productList),
),
);
},
iconData,
myCount: _getMyLocalCount(productList, localDatabase),
);

Widget _getListTile(
final String title,
final VoidCallback onTap,
final IconData leading, {
final UserSearchType? type,
final Future<int?>? myCount,
}) =>
Card(
shape: RoundedRectangleBorder(
Expand All @@ -430,9 +471,10 @@ class _UserPreferencesPageState extends State<UserPreferencesSection> {
borderRadius: BorderRadius.circular(15),
),
leading: UserPreferencesListTile.getTintedIcon(leading, context),
trailing: (type != null)
? FutureBuilder<int?>(
future: _getMyCount(type),
trailing: myCount == null
? null
: FutureBuilder<int?>(
future: myCount,
builder:
(BuildContext context, AsyncSnapshot<int?> snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
Expand All @@ -445,8 +487,7 @@ class _UserPreferencesPageState extends State<UserPreferencesSection> {
? EMPTY_WIDGET
: Text(snapshot.data.toString());
},
)
: null,
),
),
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class _ProductListPageState extends State<ProductListPage>
final bool dismissible;
switch (productList.listType) {
case ProductListType.SCAN_SESSION:
case ProductListType.SCAN_HISTORY:
case ProductListType.HISTORY:
case ProductListType.USER:
dismissible = productList.barcodes.isNotEmpty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class ProductQueryPageHelper {
return productList.parameters;
case ProductListType.SCAN_SESSION:
return appLocalizations.scan;
case ProductListType.SCAN_HISTORY:
return appLocalizations.scan_history;
case ProductListType.HISTORY:
return appLocalizations.recently_seen_products;
}
Expand Down

0 comments on commit e2197d1

Please sign in to comment.