Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
54 changes: 54 additions & 0 deletions lib/core/data/data_source/meal_data_source.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'package:collection/collection.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:logging/logging.dart';
import 'package:opennutritracker/core/data/dbo/meal_dbo.dart';

class MealDataSource {
final log = Logger('MealDataSource');
final Box<MealDBO> _mealBox;

MealDataSource(this._mealBox);

Future<void> addMeal(MealDBO mealDBO) async {
if ((await getMealByName(mealDBO.name ?? "")) == null ){
log.fine('Adding new meal item to db');
_mealBox.add(mealDBO);
}
}

Future<void> deleteMealFromId(String mealId) async {
log.fine('Deleting meal item from db');
_mealBox.values
.where((dbo) => dbo.code == mealId)
.toList()
.forEach((element) {
element.delete();
});
}

Future<MealDBO?> getMealById(String mealId) async {
return _mealBox.values.firstWhereOrNull(
(meal) => meal.code == mealId
);
}

Future<MealDBO?> getMealByName(String name) async {
return _mealBox.values.firstWhereOrNull(
(meal) => meal.name == name
);
}

Future<List<MealDBO>> getMealsByName(String name) async {
return _mealBox.values.where(
(meal) => meal.name!.contains(name)
).toList();
}


Future<MealDBO?> getMealByBarcode(String barcode) async {
return _mealBox.values.firstWhereOrNull(
(meal) => meal.barcode == barcode
);
}

}
16 changes: 13 additions & 3 deletions lib/core/data/dbo/meal_dbo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class MealDBO extends HiveObject {
@HiveField(11)
final MealNutrimentsDBO nutriments;

@HiveField(12)
final String? barcode;

MealDBO(
{required this.code,
required this.name,
Expand All @@ -49,7 +52,8 @@ class MealDBO extends HiveObject {
required this.servingQuantity,
required this.servingUnit,
required this.nutriments,
required this.source});
required this.source,
required this.barcode});

factory MealDBO.fromMealEntity(
MealEntity mealEntity) =>
Expand All @@ -68,7 +72,8 @@ class MealDBO extends HiveObject {
MealNutrimentsDBO.fromProductNutrimentsEntity(
mealEntity.nutriments),
source:
MealSourceDBO.fromMealSourceEntity(mealEntity.source));
MealSourceDBO.fromMealSourceEntity(mealEntity.source),
barcode: mealEntity.barcode);
}

@HiveType(typeId: 14)
Expand All @@ -80,7 +85,9 @@ enum MealSourceDBO {
@HiveField(2)
off,
@HiveField(3)
fdc;
fdc,
@HiveField(4)
imported;

factory MealSourceDBO.fromMealSourceEntity(MealSourceEntity entity) {
MealSourceDBO mealSourceDBO;
Expand All @@ -91,6 +98,9 @@ enum MealSourceDBO {
case MealSourceEntity.custom:
mealSourceDBO = MealSourceDBO.custom;
break;
case MealSourceEntity.imported:
mealSourceDBO = MealSourceDBO.imported;
break;
case MealSourceEntity.off:
mealSourceDBO = MealSourceDBO.off;
break;
Expand Down
12 changes: 10 additions & 2 deletions lib/core/data/dbo/meal_dbo.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions lib/core/data/repository/meal_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:opennutritracker/core/data/data_source/meal_data_source.dart';
import 'package:opennutritracker/core/data/dbo/meal_dbo.dart';
import 'package:opennutritracker/features/add_meal/domain/entity/meal_entity.dart';

class MealRepository {
final MealDataSource _mealDataSource;

MealRepository(this._mealDataSource);

Future<void> addMeal(MealEntity mealEntity) async {
final mealDBO = MealDBO.fromMealEntity(mealEntity);

await _mealDataSource.addMeal(mealDBO);
}

Future<void> deleteMeal(MealEntity mealEntity) async {
if (mealEntity.code != null) {
await _mealDataSource.deleteMealFromId(mealEntity.code ?? "");
}
}

// Future<MealEntity?> updateMeal(String mealId, Map<String, dynamic> fields) async {
// var result = await _mealDataSource.updateMeal(mealId, fields);
// return result == null ? null : MealEntity.fromMealDBO(result);
// }

Future<MealEntity?> getMealById(String mealId) async {
final result = await _mealDataSource.getMealById(mealId);
return result == null ? null : MealEntity.fromMealDBO(result);
}
}
4 changes: 4 additions & 0 deletions lib/core/utils/hive_db_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ class HiveDBProvider extends ChangeNotifier {
static const userActivityBoxName = 'UserActivityBox';
static const userBoxName = 'UserBox';
static const trackedDayBoxName = 'TrackedDayBox';
static const importedMealsBoxName = 'importedMealsBox';

late Box<ConfigDBO> configBox;
late Box<IntakeDBO> intakeBox;
late Box<UserActivityDBO> userActivityBox;
late Box<UserDBO> userBox;
late Box<TrackedDayDBO> trackedDayBox;
late Box<MealDBO> importedMealsBox;

Future<void> initHiveDB(Uint8List encryptionKey) async {
final encryptionCypher = HiveAesCipher(encryptionKey);
Expand Down Expand Up @@ -58,6 +60,8 @@ class HiveDBProvider extends ChangeNotifier {
await Hive.openBox(userBoxName, encryptionCipher: encryptionCypher);
trackedDayBox = await Hive.openBox(trackedDayBoxName,
encryptionCipher: encryptionCypher);
importedMealsBox = await Hive.openBox(importedMealsBoxName,
encryptionCipher: encryptionCypher);
}

static generateNewHiveEncryptionKey() => Hive.generateSecureKey();
Expand Down
10 changes: 9 additions & 1 deletion lib/core/utils/locator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import 'package:opennutritracker/core/data/data_source/physical_activity_data_so
import 'package:opennutritracker/core/data/data_source/tracked_day_data_source.dart';
import 'package:opennutritracker/core/data/data_source/user_activity_data_source.dart';
import 'package:opennutritracker/core/data/data_source/user_data_source.dart';
import 'package:opennutritracker/core/data/data_source/meal_data_source.dart';
import 'package:opennutritracker/core/data/repository/config_repository.dart';
import 'package:opennutritracker/core/data/repository/intake_repository.dart';
import 'package:opennutritracker/core/data/repository/meal_repository.dart';
import 'package:opennutritracker/core/data/repository/physical_activity_repository.dart';
import 'package:opennutritracker/core/data/repository/tracked_day_repository.dart';
import 'package:opennutritracker/core/data/repository/user_activity_repository.dart';
Expand Down Expand Up @@ -36,6 +38,7 @@ import 'package:opennutritracker/features/add_activity/presentation/bloc/recent_
import 'package:opennutritracker/features/add_meal/data/data_sources/fdc_data_source.dart';
import 'package:opennutritracker/features/add_meal/data/data_sources/off_data_source.dart';
import 'package:opennutritracker/features/add_meal/data/data_sources/sp_fdc_data_source.dart';
import 'package:opennutritracker/features/add_meal/data/data_sources/local_data_source.dart';
import 'package:opennutritracker/features/add_meal/data/repository/products_repository.dart';
import 'package:opennutritracker/features/add_meal/domain/usecase/search_products_usecase.dart';
import 'package:opennutritracker/features/add_meal/presentation/bloc/food_bloc.dart';
Expand Down Expand Up @@ -137,13 +140,15 @@ Future<void> initLocator() async {
locator.registerLazySingleton<IntakeRepository>(
() => IntakeRepository(locator()));
locator.registerLazySingleton<ProductsRepository>(
() => ProductsRepository(locator(), locator(), locator()));
() => ProductsRepository(locator(), locator(), locator(), locator()));
locator.registerLazySingleton<UserActivityRepository>(
() => UserActivityRepository(locator()));
locator.registerLazySingleton<PhysicalActivityRepository>(
() => PhysicalActivityRepository(locator()));
locator.registerLazySingleton<TrackedDayRepository>(
() => TrackedDayRepository(locator()));
locator.registerLazySingleton<MealRepository>(
() => MealRepository(locator()));

// DataSources
locator
Expand All @@ -156,9 +161,12 @@ Future<void> initLocator() async {
() => UserActivityDataSource(hiveDBProvider.userActivityBox));
locator.registerLazySingleton<PhysicalActivityDataSource>(
() => PhysicalActivityDataSource());
locator.registerLazySingleton<MealDataSource>(
() => MealDataSource(hiveDBProvider.importedMealsBox));
locator.registerLazySingleton<OFFDataSource>(() => OFFDataSource());
locator.registerLazySingleton<FDCDataSource>(() => FDCDataSource());
locator.registerLazySingleton<SpFdcDataSource>(() => SpFdcDataSource());
locator.registerLazySingleton<LocalDataSource>(() => LocalDataSource());
locator.registerLazySingleton(
() => TrackedDayDataSource(hiveDBProvider.trackedDayBox));

Expand Down
24 changes: 24 additions & 0 deletions lib/features/add_meal/data/data_sources/local_data_source.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:logging/logging.dart';
import 'package:opennutritracker/core/data/data_source/meal_data_source.dart';
import 'package:opennutritracker/features/add_meal/domain/entity/meal_entity.dart';
import 'package:opennutritracker/core/utils/locator.dart';
import 'package:opennutritracker/features/scanner/data/product_not_found_exception.dart';

class LocalDataSource {
final log = Logger('LocalDataSource');
final mealSrc = locator<MealDataSource>();

Future<List<MealEntity>> fetchSearchWordResults(String searchString) async {
return (await mealSrc.getMealsByName(searchString)).map((meal) => MealEntity.fromMealDBO(meal)).toList();
}

Future<MealEntity> fetchBarcodeResults(String barcode) async {
log.fine('Fetching Local result for $barcode');
final product = await mealSrc.getMealByBarcode(barcode);
if (product == null) {
log.warning("Local product not found");
return Future.error(ProductNotFoundException);
}
return MealEntity.fromMealDBO(product);
}
}
16 changes: 15 additions & 1 deletion lib/features/add_meal/data/repository/products_repository.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import 'package:opennutritracker/features/add_meal/data/data_sources/fdc_data_source.dart';
import 'package:opennutritracker/features/add_meal/data/data_sources/off_data_source.dart';
import 'package:opennutritracker/features/add_meal/data/data_sources/sp_fdc_data_source.dart';
import 'package:opennutritracker/features/add_meal/data/data_sources/local_data_source.dart';
import 'package:opennutritracker/features/add_meal/domain/entity/meal_entity.dart';

class ProductsRepository {
final OFFDataSource _offDataSource;
final FDCDataSource _fdcDataSource;
final SpFdcDataSource _spBackendDataSource;
final LocalDataSource _localDataSource;

ProductsRepository(
this._offDataSource, this._fdcDataSource, this._spBackendDataSource);
this._offDataSource, this._fdcDataSource, this._spBackendDataSource,
this._localDataSource);

Future<List<MealEntity>> getOFFProductsByString(String searchString) async {
final offWordResponse =
Expand Down Expand Up @@ -41,9 +44,20 @@ class ProductsRepository {
return products;
}

Future<List<MealEntity>> getLocalMealsByString(String searchString) async {
return await _localDataSource.fetchSearchWordResults(searchString);
}

Future<MealEntity> getOFFProductByBarcode(String barcode) async {
final productResponse = await _offDataSource.fetchBarcodeResults(barcode);

return MealEntity.fromOFFProduct(productResponse.product);
}

Future<MealEntity> getImportProductByBarcode(String barcode) async {
final productResponse = await _localDataSource.fetchBarcodeResults(barcode);

return productResponse;
}

}
15 changes: 12 additions & 3 deletions lib/features/add_meal/domain/entity/meal_entity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class MealEntity extends Equatable {
final double? servingQuantity;
final String? servingUnit;

final String? barcode;

final MealSourceEntity source;

final MealNutrimentsEntity nutriments;
Expand All @@ -42,7 +44,8 @@ class MealEntity extends Equatable {
required this.servingQuantity,
required this.servingUnit,
required this.nutriments,
required this.source});
required this.source,
this.barcode});

factory MealEntity.empty() => MealEntity(
code: IdGenerator.getUniqueID(),
Expand All @@ -53,7 +56,8 @@ class MealEntity extends Equatable {
servingQuantity: null,
servingUnit: 'g',
nutriments: MealNutrimentsEntity.empty(),
source: MealSourceEntity.custom);
source: MealSourceEntity.custom,
barcode: null);

factory MealEntity.fromMealDBO(MealDBO mealDBO) => MealEntity(
code: mealDBO.code,
Expand All @@ -68,7 +72,8 @@ class MealEntity extends Equatable {
servingUnit: mealDBO.servingUnit,
nutriments:
MealNutrimentsEntity.fromMealNutrimentsDBO(mealDBO.nutriments),
source: MealSourceEntity.fromMealSourceDBO(mealDBO.source));
source: MealSourceEntity.fromMealSourceDBO(mealDBO.source),
barcode: mealDBO.barcode);

factory MealEntity.fromOFFProduct(OFFProductDTO offProduct) {
return MealEntity(
Expand Down Expand Up @@ -164,6 +169,7 @@ enum MealSourceEntity {
unknown,
custom,
off,
imported,
fdc;

factory MealSourceEntity.fromMealSourceDBO(MealSourceDBO mealSourceDBO) {
Expand All @@ -175,6 +181,9 @@ enum MealSourceEntity {
case MealSourceDBO.custom:
mealSourceEntity = MealSourceEntity.custom;
break;
case MealSourceDBO.imported:
mealSourceEntity = MealSourceEntity.imported;
break;
case MealSourceDBO.off:
mealSourceEntity = MealSourceEntity.off;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,11 @@ class SearchProductsUseCase {
await _productsRepository.getSupabaseFDCFoodsByString(searchString);
return foods;
}

Future<List<MealEntity>> searchLocalProductsByString(
String searchString) async {
final products =
await _productsRepository.getLocalMealsByString(searchString);
return products;
}
}
Loading