diff --git a/lib/backend/objectbox/entities/product/product_entity.dart b/lib/backend/objectbox/entities/product/product_entity.dart new file mode 100644 index 0000000..a30c87f --- /dev/null +++ b/lib/backend/objectbox/entities/product/product_entity.dart @@ -0,0 +1,48 @@ +import 'package:barcode_scanner/backend/schema/product/product_struct.dart'; +import 'package:objectbox/objectbox.dart'; + +/// Modèle de base de données ObjectBox +@Entity() +class ProductEntity { + @Id() + int id; + + String? code; + String? name; + String? description; + String? price; + String? quantity; + + ProductEntity({ + this.id = 0, + this.code, + this.name, + this.description, + this.price, + this.quantity, + }); + + /// Convertir vers ProductStruct + ProductStruct toStruct() { + return ProductStruct( + id: id, + code: code, + name: name, + description: description, + price: price, + quantity: quantity, + ); + } + + /// Créer une instance de ProductEntity à partir de ProductStruct + static ProductEntity fromStruct(ProductStruct struct) { + return ProductEntity( + id: struct.id, + code: struct.code, + name: struct.name, + description: struct.description, + price: struct.price, + quantity: struct.quantity, + ); + } +} diff --git a/lib/backend/objectbox/objectbox-model.json b/lib/backend/objectbox/objectbox-model.json new file mode 100644 index 0000000..f7e44cf --- /dev/null +++ b/lib/backend/objectbox/objectbox-model.json @@ -0,0 +1,57 @@ +{ + "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", + "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", + "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", + "entities": [ + { + "id": "1:6757833172062715556", + "lastPropertyId": "6:7033704955625644592", + "name": "ProductEntity", + "properties": [ + { + "id": "1:1853465479129290672", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:4521897043130066476", + "name": "code", + "type": 9 + }, + { + "id": "3:2561289170534233438", + "name": "name", + "type": 9 + }, + { + "id": "4:6084891210993334692", + "name": "description", + "type": 9 + }, + { + "id": "5:883454706727408240", + "name": "price", + "type": 9 + }, + { + "id": "6:7033704955625644592", + "name": "quantity", + "type": 9 + } + ], + "relations": [] + } + ], + "lastEntityId": "1:6757833172062715556", + "lastIndexId": "0:0", + "lastRelationId": "0:0", + "lastSequenceId": "0:0", + "modelVersion": 5, + "modelVersionParserMinimum": 5, + "retiredEntityUids": [], + "retiredIndexUids": [], + "retiredPropertyUids": [], + "retiredRelationUids": [], + "version": 1 +} \ No newline at end of file diff --git a/lib/backend/objectbox/objectbox.g.dart b/lib/backend/objectbox/objectbox.g.dart new file mode 100644 index 0000000..3f382da --- /dev/null +++ b/lib/backend/objectbox/objectbox.g.dart @@ -0,0 +1,228 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// This code was generated by ObjectBox. To update it run the generator again +// with `dart run build_runner build`. +// See also https://docs.objectbox.io/getting-started#generate-objectbox-code + +// ignore_for_file: camel_case_types, depend_on_referenced_packages +// coverage:ignore-file + +import 'dart:typed_data'; + +import 'package:flat_buffers/flat_buffers.dart' as fb; +import 'package:objectbox/internal.dart' + as obx_int; // generated code can access "internal" functionality +import 'package:objectbox/objectbox.dart' as obx; +import 'package:objectbox_flutter_libs/objectbox_flutter_libs.dart'; + +import '../../backend/objectbox/entities/product/product_entity.dart'; + +export 'package:objectbox/objectbox.dart'; // so that callers only have to import this file + +final _entities = [ + obx_int.ModelEntity( + id: const obx_int.IdUid(1, 6757833172062715556), + name: 'ProductEntity', + lastPropertyId: const obx_int.IdUid(6, 7033704955625644592), + flags: 0, + properties: [ + obx_int.ModelProperty( + id: const obx_int.IdUid(1, 1853465479129290672), + name: 'id', + type: 6, + flags: 1, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(2, 4521897043130066476), + name: 'code', + type: 9, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(3, 2561289170534233438), + name: 'name', + type: 9, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(4, 6084891210993334692), + name: 'description', + type: 9, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(5, 883454706727408240), + name: 'price', + type: 9, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(6, 7033704955625644592), + name: 'quantity', + type: 9, + flags: 0, + ), + ], + relations: [], + backlinks: [], + ), +]; + +/// Shortcut for [obx.Store.new] that passes [getObjectBoxModel] and for Flutter +/// apps by default a [directory] using `defaultStoreDirectory()` from the +/// ObjectBox Flutter library. +/// +/// Note: for desktop apps it is recommended to specify a unique [directory]. +/// +/// See [obx.Store.new] for an explanation of all parameters. +/// +/// For Flutter apps, also calls `loadObjectBoxLibraryAndroidCompat()` from +/// the ObjectBox Flutter library to fix loading the native ObjectBox library +/// on Android 6 and older. +Future openStore({ + String? directory, + int? maxDBSizeInKB, + int? maxDataSizeInKB, + int? fileMode, + int? maxReaders, + bool queriesCaseSensitiveDefault = true, + String? macosApplicationGroup, +}) async { + await loadObjectBoxLibraryAndroidCompat(); + return obx.Store( + getObjectBoxModel(), + directory: directory ?? (await defaultStoreDirectory()).path, + maxDBSizeInKB: maxDBSizeInKB, + maxDataSizeInKB: maxDataSizeInKB, + fileMode: fileMode, + maxReaders: maxReaders, + queriesCaseSensitiveDefault: queriesCaseSensitiveDefault, + macosApplicationGroup: macosApplicationGroup, + ); +} + +/// Returns the ObjectBox model definition for this project for use with +/// [obx.Store.new]. +obx_int.ModelDefinition getObjectBoxModel() { + final model = obx_int.ModelInfo( + entities: _entities, + lastEntityId: const obx_int.IdUid(1, 6757833172062715556), + lastIndexId: const obx_int.IdUid(0, 0), + lastRelationId: const obx_int.IdUid(0, 0), + lastSequenceId: const obx_int.IdUid(0, 0), + retiredEntityUids: const [], + retiredIndexUids: const [], + retiredPropertyUids: const [], + retiredRelationUids: const [], + modelVersion: 5, + modelVersionParserMinimum: 5, + version: 1, + ); + + final bindings = { + ProductEntity: obx_int.EntityDefinition( + model: _entities[0], + toOneRelations: (ProductEntity object) => [], + toManyRelations: (ProductEntity object) => {}, + getId: (ProductEntity object) => object.id, + setId: (ProductEntity object, int id) { + object.id = id; + }, + objectToFB: (ProductEntity object, fb.Builder fbb) { + final codeOffset = object.code == null + ? null + : fbb.writeString(object.code!); + final nameOffset = object.name == null + ? null + : fbb.writeString(object.name!); + final descriptionOffset = object.description == null + ? null + : fbb.writeString(object.description!); + final priceOffset = object.price == null + ? null + : fbb.writeString(object.price!); + final quantityOffset = object.quantity == null + ? null + : fbb.writeString(object.quantity!); + fbb.startTable(7); + fbb.addInt64(0, object.id); + fbb.addOffset(1, codeOffset); + fbb.addOffset(2, nameOffset); + fbb.addOffset(3, descriptionOffset); + fbb.addOffset(4, priceOffset); + fbb.addOffset(5, quantityOffset); + fbb.finish(fbb.endTable()); + return object.id; + }, + objectFromFB: (obx.Store store, ByteData fbData) { + final buffer = fb.BufferContext(fbData); + final rootOffset = buffer.derefObject(0); + final idParam = const fb.Int64Reader().vTableGet( + buffer, + rootOffset, + 4, + 0, + ); + final codeParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGetNullable(buffer, rootOffset, 6); + final nameParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGetNullable(buffer, rootOffset, 8); + final descriptionParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGetNullable(buffer, rootOffset, 10); + final priceParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGetNullable(buffer, rootOffset, 12); + final quantityParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGetNullable(buffer, rootOffset, 14); + final object = ProductEntity( + id: idParam, + code: codeParam, + name: nameParam, + description: descriptionParam, + price: priceParam, + quantity: quantityParam, + ); + + return object; + }, + ), + }; + + return obx_int.ModelDefinition(model, bindings); +} + +/// [ProductEntity] entity fields to define ObjectBox queries. +class ProductEntity_ { + /// See [ProductEntity.id]. + static final id = obx.QueryIntegerProperty( + _entities[0].properties[0], + ); + + /// See [ProductEntity.code]. + static final code = obx.QueryStringProperty( + _entities[0].properties[1], + ); + + /// See [ProductEntity.name]. + static final name = obx.QueryStringProperty( + _entities[0].properties[2], + ); + + /// See [ProductEntity.description]. + static final description = obx.QueryStringProperty( + _entities[0].properties[3], + ); + + /// See [ProductEntity.price]. + static final price = obx.QueryStringProperty( + _entities[0].properties[4], + ); + + /// See [ProductEntity.quantity]. + static final quantity = obx.QueryStringProperty( + _entities[0].properties[5], + ); +} diff --git a/lib/backend/schema/product/product_struct.dart b/lib/backend/schema/product/product_struct.dart index 0bb386d..9a3e70b 100644 --- a/lib/backend/schema/product/product_struct.dart +++ b/lib/backend/schema/product/product_struct.dart @@ -6,7 +6,7 @@ part 'product_struct.g.dart'; @Freezed(toJson: true) abstract class ProductStruct with _$ProductStruct { factory ProductStruct({ - String? id, + @Default(0) int id, String? code, String? name, String? description, diff --git a/lib/backend/schema/product/product_struct.freezed.dart b/lib/backend/schema/product/product_struct.freezed.dart index a49f41e..b6efd58 100644 --- a/lib/backend/schema/product/product_struct.freezed.dart +++ b/lib/backend/schema/product/product_struct.freezed.dart @@ -16,7 +16,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$ProductStruct { - String? get id; String? get code; String? get name; String? get description; String? get price; String? get quantity; + int get id; String? get code; String? get name; String? get description; String? get price; String? get quantity; /// Create a copy of ProductStruct /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -49,7 +49,7 @@ abstract mixin class $ProductStructCopyWith<$Res> { factory $ProductStructCopyWith(ProductStruct value, $Res Function(ProductStruct) _then) = _$ProductStructCopyWithImpl; @useResult $Res call({ - String? id, String? code, String? name, String? description, String? price, String? quantity + int id, String? code, String? name, String? description, String? price, String? quantity }); @@ -66,10 +66,10 @@ class _$ProductStructCopyWithImpl<$Res> /// Create a copy of ProductStruct /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = freezed,Object? code = freezed,Object? name = freezed,Object? description = freezed,Object? price = freezed,Object? quantity = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? code = freezed,Object? name = freezed,Object? description = freezed,Object? price = freezed,Object? quantity = freezed,}) { return _then(_self.copyWith( -id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String?,code: freezed == code ? _self.code : code // ignore: cast_nullable_to_non_nullable +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as int,code: freezed == code ? _self.code : code // ignore: cast_nullable_to_non_nullable as String?,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable as String?,price: freezed == price ? _self.price : price // ignore: cast_nullable_to_non_nullable @@ -85,10 +85,10 @@ as String?, @JsonSerializable() class _ProductStruct implements ProductStruct { - _ProductStruct({this.id, this.code, this.name, this.description, this.price, this.quantity}); + _ProductStruct({this.id = 0, this.code, this.name, this.description, this.price, this.quantity}); factory _ProductStruct.fromJson(Map json) => _$ProductStructFromJson(json); -@override final String? id; +@override@JsonKey() final int id; @override final String? code; @override final String? name; @override final String? description; @@ -128,7 +128,7 @@ abstract mixin class _$ProductStructCopyWith<$Res> implements $ProductStructCopy factory _$ProductStructCopyWith(_ProductStruct value, $Res Function(_ProductStruct) _then) = __$ProductStructCopyWithImpl; @override @useResult $Res call({ - String? id, String? code, String? name, String? description, String? price, String? quantity + int id, String? code, String? name, String? description, String? price, String? quantity }); @@ -145,10 +145,10 @@ class __$ProductStructCopyWithImpl<$Res> /// Create a copy of ProductStruct /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = freezed,Object? code = freezed,Object? name = freezed,Object? description = freezed,Object? price = freezed,Object? quantity = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? code = freezed,Object? name = freezed,Object? description = freezed,Object? price = freezed,Object? quantity = freezed,}) { return _then(_ProductStruct( -id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String?,code: freezed == code ? _self.code : code // ignore: cast_nullable_to_non_nullable +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as int,code: freezed == code ? _self.code : code // ignore: cast_nullable_to_non_nullable as String?,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable as String?,price: freezed == price ? _self.price : price // ignore: cast_nullable_to_non_nullable diff --git a/lib/backend/schema/product/product_struct.g.dart b/lib/backend/schema/product/product_struct.g.dart index 8d51cef..da74061 100644 --- a/lib/backend/schema/product/product_struct.g.dart +++ b/lib/backend/schema/product/product_struct.g.dart @@ -8,7 +8,7 @@ part of 'product_struct.dart'; _ProductStruct _$ProductStructFromJson(Map json) => _ProductStruct( - id: json['id'] as String?, + id: (json['id'] as num?)?.toInt() ?? 0, code: json['code'] as String?, name: json['name'] as String?, description: json['description'] as String?, diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index d0e7f79..b773214 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,9 +7,13 @@ #include "generated_plugin_registrant.h" #include +#include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) objectbox_flutter_libs_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "ObjectboxFlutterLibsPlugin"); + objectbox_flutter_libs_plugin_register_with_registrar(objectbox_flutter_libs_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index b29e9ba..6d5d836 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST flutter_secure_storage_linux + objectbox_flutter_libs ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 34ee458..f0bb0b8 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,6 +8,7 @@ import Foundation import connectivity_plus import flutter_secure_storage_macos import mobile_scanner +import objectbox_flutter_libs import path_provider_foundation import shared_preferences_foundation @@ -15,6 +16,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) + ObjectboxFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "ObjectboxFlutterLibsPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 3bfe5d2..2ae9133 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -265,6 +265,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + flat_buffers: + dependency: transitive + description: + name: flat_buffers + sha256: "380bdcba5664a718bfd4ea20a45d39e13684f5318fcd8883066a55e21f37f4c3" + url: "https://pub.dev" + source: hosted + version: "23.5.26" flutter: dependency: "direct main" description: flutter @@ -581,6 +589,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.0" + objectbox: + dependency: "direct main" + description: + name: objectbox + sha256: "25c2e24b417d938decb5598682dc831bc6a21856eaae65affbc57cfad326808d" + url: "https://pub.dev" + source: hosted + version: "4.3.0" + objectbox_flutter_libs: + dependency: "direct main" + description: + name: objectbox_flutter_libs + sha256: "574b0233ba79a7159fca9049c67974f790a2180b6141d4951112b20bd146016a" + url: "https://pub.dev" + source: hosted + version: "4.3.0" + objectbox_generator: + dependency: "direct dev" + description: + name: objectbox_generator + sha256: "1b17e9168d03706b5bb895b5f36f4301aa7c973ac30ff761b205b1ca3e2e3865" + url: "https://pub.dev" + source: hosted + version: "4.3.0" package_config: dependency: transitive description: @@ -669,6 +701,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5" + url: "https://pub.dev" + source: hosted + version: "4.0.0" pool: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3336d4b..9795168 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,12 +50,15 @@ dependencies: flutter_secure_storage: ^9.2.4 google_fonts: ^6.2.1 shared_preferences: ^2.5.3 + objectbox: ^4.3.0 + objectbox_flutter_libs: any dev_dependencies: flutter_test: sdk: flutter go_router_builder: ^3.0.1 build_runner: ^2.4.15 + objectbox_generator: any # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is @@ -76,6 +79,14 @@ flutter_icons: remove_alpha_ios: true min_sdk_android: 21 +objectbox: + # Writes objectbox-model.json and objectbox.g.dart to lib/objectbox (and test/objectbox). + output_dir: backend/objectbox + # Or optionally specify the lib and test output folder separately. + # output_dir: + # lib: custom + # test: other + # The following section is specific to Flutter packages. flutter: # The following line ensures that the Material Icons font is diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index af1f996..de4b000 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,10 +8,13 @@ #include #include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { ConnectivityPlusWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + ObjectboxFlutterLibsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ObjectboxFlutterLibsPlugin")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index f9ef886..0d4689c 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST connectivity_plus flutter_secure_storage_windows + objectbox_flutter_libs ) list(APPEND FLUTTER_FFI_PLUGIN_LIST